let searchParams: URLSearchParams | null = null; export function isDebugMode() { if (searchParams == null) { searchParams = new URLSearchParams(location.search); } return searchParams.has("debug"); } export function isStandaloneSaveMode() { if (searchParams == null) { searchParams = new URLSearchParams(location.search); } return searchParams.has("standalone"); } export function url(url: string) { const parsedUrl = new URL(url, location.href); const ticketCode = getTicketCode(); if (isDebugMode()) { parsedUrl.searchParams.append("debug", "1"); } if (ticketCode) { parsedUrl.searchParams.append("token", ticketCode); } return parsedUrl.href; } export function moveTo(distUrl: string) { location.href = url(distUrl); } export function getGameURL() { if (searchParams == null) { searchParams = new URLSearchParams(location.search); } return searchParams.get("url"); } export function getContentCode() { if (searchParams == null) { searchParams = new URLSearchParams(location.search); } return searchParams.get("code") ?? undefined; } export function getContentVersion() { if (searchParams == null) { searchParams = new URLSearchParams(location.search); } return searchParams.get("version") ?? undefined; } export function qsThrowIfNotExists(parent: Element | Document, selector: string) { const result = parent.querySelector(selector); if (result == null) { if (parent === document) { throw new Error(`documnetに${selector}が見つかりません。`); } else { const parentElement = parent as Element; throw new Error(`${parentElement.tagName}(${parentElement.id})に${selector}が見つかりません。`); } } return result; } export function getTicketCode() { /* if (searchParams == null) { searchParams = new URLSearchParams(location.search); } return searchParams.get("token"); */ return "-"; } export function getFlagsDataStorageKey(project: string) { return `project${project}-flags`; } export function convertDataToSingleLine(data: string) { return data.replace(/\r\n|\r|\n/g, " "); } type AlertType = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark"; export function insertAlert(targetElement: HTMLElement, message: string, alertType?: AlertType): void { const alertDiv = document.createElement("div"); alertDiv.className = `alert alert-${alertType ?? "warning"} alert-dismissible fade show`; alertDiv.setAttribute("role", "alert"); const textNode = document.createTextNode(` ${message}`); alertDiv.appendChild(textNode); const closeButton = document.createElement("button"); closeButton.type = "button"; closeButton.className = "btn-close"; closeButton.setAttribute("data-bs-dismiss", "alert"); closeButton.setAttribute("aria-label", "Close"); alertDiv.appendChild(closeButton); targetElement.insertBefore(alertDiv, targetElement.firstChild); } export function translateErrorMessage(message: string): string { const translations = [ { pattern: /Invalid flag number: (\d*), (.*)/, translation: "不正なフラグ番号です: $1, vars: $2", }, { pattern: /SetFlagOnOver: vars is null: (.*)/, translation: "Set Flag On Overイベント: 変数がnullです $1", }, { pattern: /Invalid angle: (.*)/, translation: "無効なキャラクター移動の入力: $1", }, { pattern: /invalid clear action/, translation: "無効なClear Actionが発生しました", }, { pattern: /ClearAction: doorObject is empty/, translation: "Clear Action: doorObjectが空です", }, { pattern: /Invalid action of (\d*)/, translation: "無効な $1 のアクションが発生しました", }, { pattern: /Invalid object number (\d+)/, translation: "無効なオブジェクト番号 $1 が指定されました", }, { pattern: /Invalid door object\(unattached entity\) (\d+)/, translation: "無効なドアオブジェクト(アタッチされていないエンティティ) が番号 $1 のオブジェクトで指定されました", }, ]; for (const { pattern, translation } of translations) { if (pattern.test(message)) { return message.replace(pattern, translation); } } return message; // パターンに一致しない場合は、オリジナルのメッセージを返す } export function isIOSorMacintoshTouchDevice() { const ua = navigator.userAgent; return ua.match(/[ \(]iP/) != null || (ua.match(/macintosh/i) != null && "ontouchend" in document); }