haori 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +2 -1
- package/README.md +2 -1
- package/dist/haori.cjs.js +6 -6
- package/dist/haori.cjs.js.map +1 -1
- package/dist/haori.es.js +279 -252
- package/dist/haori.es.js.map +1 -1
- package/dist/haori.iife.js +5 -5
- package/dist/haori.iife.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/package.json +1 -1
- package/dist/src/core.d.ts +6 -0
- package/dist/src/core.d.ts.map +1 -1
- package/dist/src/core.js +34 -13
- package/dist/src/core.js.map +1 -1
- package/dist/src/fragment.d.ts +4 -0
- package/dist/src/fragment.d.ts.map +1 -1
- package/dist/src/fragment.js +20 -1
- package/dist/src/fragment.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/tests/core.test.js +84 -1
- package/dist/tests/core.test.js.map +1 -1
- package/dist/tests/data-fetch-tbody-dom.test.js +9 -26
- package/dist/tests/data-fetch-tbody-dom.test.js.map +1 -1
- package/dist/tests/fetch-and-procedure-scenarios.test.js +19 -11
- package/dist/tests/fetch-and-procedure-scenarios.test.js.map +1 -1
- package/dist/tests/fragment.test.js +8 -0
- package/dist/tests/fragment.test.js.map +1 -1
- package/package.json +1 -1
package/dist/haori.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"haori.cjs.js","sources":["../src/dev.ts","../src/env.ts","../src/log.ts","../src/queue.ts","../src/haori.ts","../src/form.ts","../src/expression.ts","../src/fragment.ts","../src/event.ts","../src/procedure.ts","../src/url.ts","../src/import.ts","../src/core.ts","../src/event_dispatcher.ts","../src/intersect.ts","../src/observer.ts","../src/index.ts"],"sourcesContent":["/**\n * @fileoverview Haori開発モード管理機能\n *\n * 開発モードの有効/無効を管理し、デバッグ機能の制御を行います。\n * プロダクション環境では開発向け機能を無効化することで、\n * パフォーマンスとセキュリティを向上させます。\n */\n\n/**\n * 開発モード管理クラスです。\n */\nexport default class Dev {\n /** 開発モードフラグ */\n private static devMode = false;\n\n /**\n * 開発モードの状態を取得します。\n *\n * @returns 開発モードならtrue、そうでなければfalse\n */\n static isEnabled(): boolean {\n return Dev.devMode;\n }\n\n /**\n * 開発モードを有効化します。\n */\n static enable(): void {\n Dev.devMode = true;\n }\n\n /**\n * 開発モードを無効化します。\n */\n static disable(): void {\n Dev.devMode = false;\n }\n\n /**\n * 開発モードを切り替えます。\n *\n * @param enabled trueで有効化、falseで無効化\n */\n static set(enabled: boolean): void {\n Dev.devMode = enabled;\n }\n}\n","/**\n * @fileoverview Haori環境検出機能\n *\n * 実行環境を管理します。\n */\n\nimport Dev from './dev';\n\n/**\n * Haori.js の実行モードを表します。\n */\nexport type HaoriRuntime = 'embedded' | 'demo';\n\nconst DEFAULT_RUNTIME: HaoriRuntime = 'embedded';\n\n/**\n * 指定文字列が有効な実行モードかどうかを判定します。\n *\n * @param runtime 判定対象の文字列。\n * @return 有効な実行モードなら true。\n */\nfunction isHaoriRuntime(runtime: string): runtime is HaoriRuntime {\n return runtime === 'embedded' || runtime === 'demo';\n}\n\n/**\n * data-runtime 属性値を実行モードへ正規化します。\n *\n * @param runtime 属性から取得した値。\n * @return 有効な実行モード。属性が未設定なら null、無効値なら embedded。\n */\nfunction resolveRuntimeAttribute(runtime: string | null): HaoriRuntime | null {\n if (runtime === null) {\n return null;\n }\n\n return isHaoriRuntime(runtime) ? runtime : DEFAULT_RUNTIME;\n}\n\n/**\n * 実行環境を管理するクラスです。\n */\nexport default class Env {\n private static _prefix: string = 'data-';\n private static _runtime: HaoriRuntime = DEFAULT_RUNTIME;\n\n /**\n * 実行モードを取得します。\n *\n * @returns 実行モード。\n */\n public static get runtime(): HaoriRuntime {\n return Env._runtime;\n }\n\n /**\n * 実行モードを設定します。\n *\n * @param runtime 設定する実行モード。\n * @return 戻り値はありません。\n */\n public static setRuntime(runtime: string): void {\n Env._runtime = isHaoriRuntime(runtime) ? runtime : DEFAULT_RUNTIME;\n }\n\n /**\n * 実行環境からプレフィックスと開発モードかどうかを自動検出します。\n * scriptタグにdata-prefixがある場合は、その値+\"-\"をプレフィックスとして使用します。\n * scriptタグにdata-dev属性がある場合、\n * もしくはローカルホスト系ドメインであれば開発モードを有効化します。\n */\n static detect(): void {\n try {\n const currentScript =\n document.currentScript ||\n document.querySelector('script[src*=\"haori\"]');\n if (currentScript instanceof HTMLScriptElement) {\n const prefix = currentScript.getAttribute('data-prefix') || Env._prefix;\n Env._prefix = prefix.endsWith('-') ? prefix : prefix + '-';\n\n const runtime = resolveRuntimeAttribute(\n currentScript.getAttribute('data-runtime'),\n );\n if (runtime !== null) {\n Env._runtime = runtime;\n }\n }\n if (\n currentScript instanceof HTMLScriptElement &&\n currentScript.hasAttribute(`${Env._prefix}dev`)\n ) {\n Dev.set(true);\n return;\n }\n\n // ローカルホスト系ドメインの場合\n const host = window.location.hostname;\n if (\n host === 'localhost' ||\n host.endsWith('.localhost') ||\n host === '127.0.0.1' ||\n host === '::1' ||\n host.endsWith('.local')\n ) {\n Dev.set(true);\n return;\n }\n\n // それ以外は開発モードを無効化\n Dev.set(false);\n } catch {\n // SSRや非ブラウザ環境では無視\n }\n }\n\n /**\n * プレフィックスを取得します。\n *\n * @returns プレフィックス\n */\n public static get prefix(): string {\n return Env._prefix;\n }\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', Env.detect);\n} else {\n Env.detect();\n}\n","/**\n * @fileoverview Haori共通ログ機能\n *\n * 開発モード時のみログ出力を行います。\n */\n\nimport Dev from './dev';\n\n/**\n * ログ出力を管理するクラス\n */\nexport default class Log {\n /**\n * 開発モードでのみコンソールに情報を出力します。\n *\n * @param message 出力するメッセージ\n * @param args 追加の引数\n */\n static info(message: string, ...args: unknown[]): void {\n if (Dev.isEnabled() && console.log) {\n console.log(message, ...args);\n }\n }\n\n /**\n * 開発モードでのみコンソールに警告を出力します。\n *\n * @param message 出力するメッセージ\n * @param args 追加の引数\n */\n static warn(message: string, ...args: unknown[]): void {\n if (Dev.isEnabled() && console.warn) {\n console.warn(message, ...args);\n }\n }\n\n /**\n * モードに関係なくコンソールにエラーを出力します。\n *\n * @param message 出力するメッセージ\n * @param args 追加の引数\n */\n static error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","/**\n * @fileoverview 汎用非同期キュー機能\n *\n * 任意の処理を非同期でキューイングし、requestAnimationFrameを使用して順次実行します。\n * 各処理はPromiseを返し、完了時の処理を記述できます。\n * DOM操作などの非同期処理に適しています。\n */\n\nimport Log from './log';\n\n/**\n * キューアイテムの基本構造。\n */\ninterface QueueItem {\n /** 実行する処理 */\n task: () => unknown | Promise<unknown>;\n\n /** 作成時刻 */\n timestamp: number;\n\n /** 完了Promise */\n promise: Promise<unknown>;\n\n /** Promise解決用の関数 */\n resolve: (value: unknown | PromiseLike<unknown>) => void;\n\n /** Promise拒否用の関数 */\n reject: (reason?: unknown) => void;\n}\n\n/**\n * 非同期キュークラス。\n * キュー内の処理を管理し、順次実行します。\n */\nclass AsyncQueue {\n private readonly MAX_BUDGET = 8; // 1フレームあたりの最大処理時間(ms)\n\n /** キュー内の処理 */\n private readonly queue: QueueItem[] = [];\n\n /** 処理中フラグ */\n private processing = false;\n\n /**\n * 処理をキューに追加します\n *\n * @param task 実行する処理\n * @param prepend trueの場合はキューの先頭に追加、falseの場合は末尾に追加\n * @returns 処理完了Promise\n */\n public enqueue(\n task: () => unknown,\n prepend: boolean = false,\n ): Promise<unknown> {\n let resolve: (value: unknown | PromiseLike<unknown>) => void;\n let reject: (reason?: unknown) => void;\n const promise = new Promise<unknown>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem = {\n task,\n timestamp: performance.now(),\n promise,\n resolve: resolve!,\n reject: reject!,\n };\n if (prepend) {\n this.queue.unshift(item);\n } else {\n this.queue.push(item);\n }\n this.scheduleProcessing();\n return promise;\n }\n\n /**\n * キューを処理します。\n *\n * @returns 処理完了Promise\n */\n private async processQueue(): Promise<void> {\n if (this.processing || this.queue.length === 0) {\n return;\n }\n this.processing = true;\n try {\n const start = performance.now();\n while (this.queue.length > 0) {\n const item = this.queue.shift();\n if (!item) {\n return;\n }\n try {\n const result = await item.task();\n item.resolve(result);\n } catch (error) {\n item.reject(error);\n Log.error('[Haori]', `Task ${item.timestamp} failed:`, error);\n }\n if (performance.now() - start > this.MAX_BUDGET) {\n // 1フレームの処理時間を超えたら一旦終了\n break;\n }\n }\n } catch (error) {\n Log.error('[Haori]', 'Error processing queue:', error);\n } finally {\n this.processing = false;\n if (this.queue.length > 0) {\n this.scheduleProcessing();\n }\n }\n }\n\n /**\n * 処理をスケジュールします。\n */\n private scheduleProcessing(): void {\n if (this.processing) {\n return;\n }\n if (typeof requestAnimationFrame !== 'undefined') {\n requestAnimationFrame(() => {\n this.processQueue();\n });\n } else {\n setTimeout(() => {\n this.processQueue();\n }, 16); // 60fps\n }\n }\n\n /**\n * キューが空になるまで待機します。\n *\n * @returns キューが空になったら解決されるPromise\n */\n public async wait(): Promise<void> {\n if (this.queue.length === 0 && !this.processing) {\n return;\n }\n const promises = this.queue.map(item => item.promise);\n if (promises.length > 0) {\n await Promise.allSettled(promises);\n }\n }\n}\n\n/**\n * 非同期キューのデフォルトインスタンス。\n * このインスタンスを使用して、アプリケーション全体でタスクをキューイングできます。\n */\nexport default class Queue {\n /** 非同期キューインスタンス */\n private static readonly ASYNC_QUEUE = new AsyncQueue();\n\n /**\n * タスクをキューに追加します。\n *\n * @param task 実行する処理\n * @param prepend trueの場合はキューの先頭に追加、falseの場合は末尾に追加\n * @returns 処理完了Promise\n */\n public static enqueue(\n task: () => unknown,\n prepend: boolean = false,\n ): Promise<unknown> {\n return this.ASYNC_QUEUE.enqueue(task, prepend);\n }\n\n /**\n * 全てのキュー処理が完了するまで待機します。\n */\n public static wait(): Promise<void> {\n return this.ASYNC_QUEUE.wait();\n }\n}\n","import Log from './log';\nimport Env from './env';\nimport Queue from './queue';\n\n/**\n * Haoriクラスは、アプリケーション全体で使用されるユーティリティメソッドを提供します。\n * 挙動を変更する場合は必要に応じてオーバライドしてください。\n */\nexport default class Haori {\n /**\n * 実行モードを取得します。\n *\n * @return 実行モード。\n */\n public static get runtime(): 'embedded' | 'demo' {\n return Env.runtime;\n }\n\n /**\n * 実行モードを設定します。\n *\n * @param runtime 設定する実行モード。\n * @return 戻り値はありません。\n */\n public static setRuntime(runtime: string): void {\n Env.setRuntime(runtime);\n }\n\n /**\n * 通知ダイアログを表示します。\n *\n * @param message 表示メッセージ\n * @returns 通知が閉じられると解決されるPromise\n */\n public static dialog(message: string): Promise<void> {\n return Queue.enqueue(() => {\n window.alert(message);\n }, true) as Promise<void>;\n }\n\n /**\n * 通知トーストを表示します。\n *\n * @param message 表示メッセージ\n * @param level メッセージのレベル(省略時は 'info')\n * @return 通知が表示されると解決されるPromise\n */\n public static async toast(\n message: string,\n level: 'info' | 'warning' | 'error' | 'success' = 'info',\n ): Promise<void> {\n const toast = document.createElement('div');\n toast.className = `haori-toast haori-toast-${level}`;\n toast.textContent = message;\n toast.setAttribute('popover', 'manual');\n toast.setAttribute('role', 'status');\n toast.setAttribute('aria-live', level === 'error' ? 'assertive' : 'polite');\n document.body.appendChild(toast);\n toast.showPopover();\n setTimeout(() => {\n try {\n toast.hidePopover();\n } finally {\n toast.remove();\n }\n }, 3000);\n }\n\n /**\n * 確認ダイアログを表示します。\n *\n * @param message 確認メッセージ\n * @returns ユーザーがOKをクリックした場合はtrue、キャンセルした場合はfalseが解決されるPromise\n */\n public static confirm(message: string): Promise<boolean> {\n return Queue.enqueue(() => {\n return window.confirm(message);\n }, true) as Promise<boolean>;\n }\n\n /**\n * ダイアログを開きます。\n *\n * @param element 開くダイアログのHTML要素\n */\n public static openDialog(element: HTMLElement): Promise<void> {\n return Queue.enqueue(() => {\n if (element instanceof HTMLDialogElement) {\n element.showModal();\n } else {\n Log.error('[Haori]', 'Element is not a dialog: ', element);\n }\n }, true) as Promise<void>;\n }\n\n /**\n * ダイアログを閉じます。\n *\n * @param element 閉じるダイアログのHTML要素\n */\n public static closeDialog(element: HTMLElement): Promise<void> {\n return Queue.enqueue(() => {\n if (element instanceof HTMLDialogElement) {\n element.close();\n } else {\n Log.error('[Haori]', 'Element is not a dialog: ', element);\n }\n }, true) as Promise<void>;\n }\n\n /**\n * エラーメッセージを追加します。\n *\n * @param target メッセージを表示する要素\n * @param message エラーメッセージ\n */\n public static addErrorMessage(\n target: HTMLElement | HTMLFormElement,\n message: string,\n ): Promise<void> {\n return Haori.addMessage(target, message, 'error');\n }\n\n /**\n * メッセージをレベル付きで追加します。\n *\n * @param target メッセージを表示する要素\n * @param message メッセージ\n * @param level メッセージのレベル(省略可能)\n */\n public static addMessage(\n target: HTMLElement | HTMLFormElement,\n message: string,\n level?: 'info' | 'warning' | 'error' | 'success',\n ): Promise<void> {\n return Queue.enqueue(() => {\n // 仕様: 入力要素の場合は親要素に、フォーム要素の場合はフォーム自身に data-message を付与する。\n const recipient =\n target instanceof HTMLFormElement\n ? target\n : (target.parentElement ?? target);\n recipient.setAttribute('data-message', message);\n if (level !== undefined) {\n recipient.setAttribute('data-message-level', level);\n } else {\n recipient.removeAttribute('data-message-level');\n }\n }, true) as Promise<void>;\n }\n\n /**\n * 対象のエレメントおよびその子要素のメッセージをクリアします。\n *\n * @param parent メッセージをクリアする親要素\n */\n public static clearMessages(parent: HTMLElement): Promise<void> {\n return Queue.enqueue(() => {\n parent.removeAttribute('data-message');\n parent.removeAttribute('data-message-level');\n parent.querySelectorAll('[data-message]').forEach(element => {\n element.removeAttribute('data-message');\n element.removeAttribute('data-message-level');\n });\n }, true) as Promise<void>;\n }\n}\n","/**\n * @fileoverview フォーム双方向バインディング\n *\n * フォームと入力要素の双方向バインディングを実現します。\n */\n\nimport Core from './core';\nimport Env from './env';\nimport {ElementFragment} from './fragment';\nimport Haori from './haori';\nimport Log from './log';\nimport Queue from './queue';\n\ntype FormHaoriApi = Pick<typeof Haori, 'addErrorMessage' | 'clearMessages'>;\n\nconst FORM_HAORI_METHOD_NAMES = ['addErrorMessage', 'clearMessages'] as const;\n\n/**\n * Form から利用する Haori API を解決します。\n * window.Haori が差し替えられている場合はそちらを優先します。\n *\n * @returns Form が使用する Haori API。\n */\nfunction resolveFormHaoriApi(): FormHaoriApi {\n const scope = globalThis as typeof globalThis & {\n window?: Window & {Haori?: unknown};\n };\n const candidate = scope.window?.Haori;\n const hasRequiredMethods = FORM_HAORI_METHOD_NAMES.every(\n methodName =>\n typeof (candidate as Record<string, unknown> | undefined)?.[\n methodName\n ] === 'function',\n );\n return hasRequiredMethods ? (candidate as FormHaoriApi) : Haori;\n}\n\n/**\n * Formクラスは、フォームの双方向バインディングを提供します。\n * 入力要素の値をフォームにバインドし、フォームのバインド値を入力要素に反映します。\n */\nexport default class Form {\n /**\n * フォーム内にある入力エレメントの値をオブジェクトとして取得します。\n * data-form-object属性があると、そのエレメント内の値はオブジェクトとして処理されます。\n * 入力エレメントにdata-form-list属性があると、そのエレメントの値はリストとして処理されます。\n * 入力エレメント以外にdata-form-list属性があると、そのエレメントの値はオブジェクトのリストとして処理されます。\n *\n * @param form フォームのElementFragment\n */\n public static getValues(form: ElementFragment): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n return Form.getPartValues(form, values);\n }\n\n /**\n * フォーム内の各入力エレメントから値を取得し、オブジェクトとして返します。\n * 入力エレメントのname属性、data-form-object属性、data-form-list属性に基づいて値を整理します。\n *\n * @param fragment 対象のElementFragment\n * @param values オブジェクトに追加する値のオブジェクト\n * @returns values と同じオブジェクト\n */\n private static getPartValues(\n fragment: ElementFragment,\n values: Record<string, unknown>,\n ): Record<string, unknown> {\n const name = fragment.getAttribute('name');\n const objectName = fragment.getAttribute(`${Env.prefix}form-object`);\n const listName = fragment.getAttribute(`${Env.prefix}form-list`);\n if (name) {\n if (listName) {\n if (Array.isArray(values[String(name)])) {\n (values[String(name)] as unknown[]).push(fragment.getValue());\n } else {\n values[String(name)] = [fragment.getValue()];\n }\n } else {\n values[String(name)] = fragment.getValue();\n }\n if (objectName) {\n Log.warn(\n 'Haori',\n `Element cannot have both ${Env.prefix}form-object` +\n ' and name attributes.',\n );\n }\n for (const child of fragment.getChildElementFragments()) {\n Form.getPartValues(child, values);\n }\n } else if (objectName) {\n const childValues: Record<string, unknown> = {};\n for (const child of fragment.getChildElementFragments()) {\n Form.getPartValues(child, childValues);\n }\n if (Object.keys(childValues).length > 0) {\n values[String(objectName)] = childValues;\n }\n if (listName) {\n Log.warn(\n 'Haori',\n `Element cannot have both ${Env.prefix}form-list` +\n ` and ${Env.prefix}form-object attributes.`,\n );\n }\n } else if (listName) {\n const childList: Record<string, unknown>[] = [];\n for (const child of fragment.getChildElementFragments()) {\n const childValues: Record<string, unknown> = {};\n Form.getPartValues(child, childValues);\n if (Object.keys(childValues).length > 0) {\n childList.push(childValues);\n }\n }\n if (childList.length > 0) {\n values[String(listName)] = childList;\n }\n } else {\n for (const child of fragment.getChildElementFragments()) {\n Form.getPartValues(child, values);\n }\n }\n return values;\n }\n\n /**\n * フォーム内にある入力エレメントに値を設定します。\n * フォームのdata-bind属性に値が反映されます。\n *\n * @param form フォームのElementFragment\n * @param values フォームに設定する値のオブジェクト\n * @param force data-form-detach属性があるエレメントにも値を反映するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n public static setValues(\n form: ElementFragment,\n values: Record<string, unknown>,\n force: boolean = false,\n ): Promise<void> {\n return Form.setPartValues(form, values, null, force, true);\n }\n\n /**\n * フォーム内にある入力エレメントに値をイベントなしで設定します。\n * フォーム bindingData からの内部同期に利用します。\n *\n * @param form フォームのElementFragment\n * @param values フォームに設定する値のオブジェクト\n * @param force data-form-detach属性があるエレメントにも値を反映するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n public static syncValues(\n form: ElementFragment,\n values: Record<string, unknown>,\n force: boolean = false,\n ): Promise<void> {\n return Form.setPartValues(form, values, null, force, false);\n }\n\n /**\n * 単一フラグメントへ値を設定します。\n *\n * @param fragment 対象フラグメント\n * @param value 設定する値\n * @param emitEvents input/change イベントを発火するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n private static applyFragmentValue(\n fragment: ElementFragment,\n value: string | number | boolean | null,\n emitEvents: boolean,\n ): Promise<void> {\n return emitEvents\n ? fragment.setValue(value)\n : fragment.syncBindingValue(value);\n }\n\n /**\n * フラグメント内にある各入力エレメントに値を設定します。\n *\n * @param fragment 対象フラグメント\n * @param values フラグメントに設定する値のオブジェクト\n * @param index 配列の場合のインデックス\n * @param force data-form-detach属性があるエレメントにも値を反映するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n private static setPartValues(\n fragment: ElementFragment,\n values: Record<string, unknown>,\n index: number | null = null,\n force: boolean = false,\n emitEvents: boolean = true,\n ): Promise<void> {\n const promises: Promise<void>[] = [];\n const name = fragment.getAttribute('name');\n const objectName = fragment.getAttribute(`${Env.prefix}form-object`);\n const listName = fragment.getAttribute(`${Env.prefix}form-list`);\n const detach = fragment.getAttribute(`${Env.prefix}form-detach`);\n if (name) {\n if (!detach || force) {\n const value = values[String(name)];\n if (listName && Array.isArray(value) && index !== null) {\n promises.push(\n Form.applyFragmentValue(fragment, value[index] ?? null, emitEvents),\n );\n } else if (typeof value === 'undefined') {\n // 未指定のキーは既存の入力値を維持する。\n } else if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value === null\n ) {\n promises.push(Form.applyFragmentValue(fragment, value, emitEvents));\n } else {\n promises.push(\n Form.applyFragmentValue(fragment, String(value), emitEvents),\n );\n }\n }\n } else if (objectName) {\n const childValues = values[String(objectName)];\n if (childValues && typeof childValues === 'object') {\n for (const child of fragment.getChildElementFragments()) {\n promises.push(\n Form.setPartValues(\n child,\n childValues as Record<string, unknown>,\n null,\n force,\n emitEvents,\n ),\n );\n }\n }\n } else if (listName) {\n const childList = values[String(listName)];\n if (Array.isArray(childList)) {\n const children = fragment.getChildElementFragments();\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (childList.length > i) {\n promises.push(\n Form.setPartValues(\n child,\n childList[i] as Record<string, unknown>,\n i,\n force,\n emitEvents,\n ),\n );\n } else {\n promises.push(Form.setPartValues(child, {}, i, force, emitEvents));\n }\n }\n }\n } else {\n for (const child of fragment.getChildElementFragments()) {\n promises.push(\n Form.setPartValues(child, values, null, force, emitEvents),\n );\n }\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 対象フラグメントとその子孫要素の値を初期化します。\n * 値の初期化とメッセージのクリアを行います。\n *\n * @param fragment 対象フラグメント\n * @returns すべての初期化処理が完了するPromise\n */\n public static async reset(fragment: ElementFragment): Promise<void> {\n // 値をクリア\n Form.clearValues(fragment);\n\n // メッセージをクリアし、data-eachの複製を削除\n await Promise.all([\n Form.clearMessages(fragment),\n Form.clearEachClones(fragment),\n ]);\n\n // フォーム要素をリセット\n await Queue.enqueue(() => {\n const element = fragment.getTarget();\n if (element instanceof HTMLFormElement) {\n element.reset();\n } else {\n const parent = element.parentElement;\n if (parent) {\n const next = element.nextElementSibling;\n const form = document.createElement('form');\n form.appendChild(element);\n form.reset();\n parent.insertBefore(element, next);\n }\n }\n });\n\n // 再評価\n await Core.evaluateAll(fragment);\n }\n\n /**\n * data-each によって生成された複製(テンプレート以外)を削除します。\n * 既存のテンプレートは保持し、その後の再評価で必要に応じて再生成されます。\n * 対象エレメント自体がdata-eachを持つ場合はその子の複製を削除しますが、\n * 対象エレメント自体は削除しません。\n */\n private static clearEachClones(fragment: ElementFragment): Promise<void> {\n const tasks: Promise<void>[] = [];\n\n const removeClones = (f: ElementFragment) => {\n if (f.hasAttribute(`${Env.prefix}each`)) {\n for (const child of f.getChildElementFragments()) {\n const isBefore = child.hasAttribute(`${Env.prefix}each-before`);\n const isAfter = child.hasAttribute(`${Env.prefix}each-after`);\n if (!isBefore && !isAfter) {\n tasks.push(child.remove());\n }\n }\n }\n };\n\n const processChildren = (f: ElementFragment) => {\n removeClones(f);\n for (const child of f.getChildElementFragments()) {\n processChildren(child);\n }\n };\n\n // 対象フラグメント自体のクローンを削除し、子エレメント以下を再帰処理\n removeClones(fragment);\n for (const child of fragment.getChildElementFragments()) {\n processChildren(child);\n }\n\n return Promise.all(tasks).then(() => undefined);\n }\n\n /**\n * 再帰的に値を初期化します。\n *\n * @param fragment 対象フラグメント\n */\n private static clearValues(fragment: ElementFragment): void {\n fragment.clearValue();\n for (const child of fragment.getChildElementFragments()) {\n Form.clearValues(child);\n }\n }\n\n /**\n * フラグメントとその子要素のメッセージをクリアします。\n *\n * @param fragment 対象フラグメント\n * @returns Promise(メッセージのクリアが完了したら解決される)\n */\n public static clearMessages(fragment: ElementFragment): Promise<void> {\n return resolveFormHaoriApi().clearMessages(\n fragment.getTarget(),\n ) as Promise<void>;\n }\n\n /**\n * キーに一致するフラグメントにエラーメッセージを追加します。\n * キーに一致するフラグメントが見つからない場合は、指定されたフラグメントにメッセージを追加します。\n *\n * @param fragment 対象フラグメント\n * @param key キー(ドット区切りの文字列)\n * @param message 追加するエラーメッセージ\n * @return Promise(メッセージの追加が完了したら解決される)\n */\n public static addErrorMessage(\n fragment: ElementFragment,\n key: string,\n message: string,\n ): Promise<void> {\n return Form.addMessage(fragment, key, message, 'error');\n }\n\n /**\n * キーに一致するフラグメントにレベル付きメッセージを追加します。\n * キーに一致するフラグメントが見つからない場合は、指定されたフラグメントにメッセージを追加します。\n *\n * @param fragment 対象フラグメント\n * @param key キー(ドット区切りの文字列)\n * @param message 追加するメッセージ\n * @param level メッセージのレベル(省略可能)\n * @return Promise(メッセージの追加が完了したら解決される)\n */\n public static addMessage(\n fragment: ElementFragment,\n key: string,\n message: string,\n level?: 'info' | 'warning' | 'error' | 'success',\n ): Promise<void> {\n const promises: Promise<void>[] = [];\n const activeHaori = resolveFormHaoriApi();\n const addMsgFn = (\n activeHaori as {addMessage?: typeof Haori.addMessage}\n ).addMessage;\n const doAdd = (target: HTMLElement): Promise<void> =>\n typeof addMsgFn === 'function'\n ? (addMsgFn.call(activeHaori, target, message, level) as Promise<void>)\n : (activeHaori.addErrorMessage(target, message) as Promise<void>);\n\n const targetFragments = Form.findFragmentsByKey(fragment, key);\n targetFragments.forEach(targetFragment => {\n promises.push(doAdd(targetFragment.getTarget() as HTMLElement));\n });\n if (targetFragments.length === 0) {\n promises.push(doAdd(fragment.getTarget() as HTMLElement));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 指定されたキーに一致するフラグメントを検索します。\n *\n * @param fragment 対象フラグメント\n * @param key キー(ドット区切りの文字列)\n * @returns 一致するフラグメントの配列\n */\n public static findFragmentsByKey(\n fragment: ElementFragment,\n key: string,\n ): ElementFragment[] {\n return Form.findFragmentByKeyParts(fragment, key.split('.'));\n }\n\n /**\n * 指定されたキーに一致するフラグメントを検索します。\n * data-form-list属性で指定された場合はdata-row属性を持つ子要素の位置と添字が一致するものを対象とします。\n *\n * @param fragment 対象フラグメント\n * @param parts キーのパーツ\n * @returns 一致するフラグメントの配列\n */\n private static findFragmentByKeyParts(\n fragment: ElementFragment,\n parts: string[],\n ): ElementFragment[] {\n const results: ElementFragment[] = [];\n const key = parts[0];\n if (parts.length == 1) {\n const name = fragment.getAttribute('name');\n if (name === key) {\n results.push(fragment);\n }\n }\n if (fragment.hasAttribute(`${Env.prefix}form-object`)) {\n if (parts.length > 1) {\n const objectName = fragment.getAttribute(`${Env.prefix}form-object`);\n if (objectName === key) {\n fragment.getChildElementFragments().forEach(child => {\n results.push(...Form.findFragmentByKeyParts(child, parts.slice(1)));\n });\n }\n }\n } else if (fragment.hasAttribute(`${Env.prefix}form-list`)) {\n if (parts.length > 1) {\n const listName = fragment.getAttribute(`${Env.prefix}form-list`);\n const firstPoint = key.lastIndexOf('[');\n const lastPoint = key.lastIndexOf(']');\n if (firstPoint !== -1 && lastPoint !== -1 && firstPoint < lastPoint) {\n const rawKey = key.substring(0, firstPoint);\n if (listName === rawKey) {\n const indexString = key.substring(firstPoint + 1, lastPoint);\n const index = Number(indexString);\n if (isNaN(index)) {\n Log.error('Haori', `Invalid index: ${key}`);\n } else {\n const rows = fragment\n .getChildElementFragments()\n .filter(child => child.hasAttribute(`${Env.prefix}row`));\n if (index < rows.length) {\n results.push(\n ...Form.findFragmentByKeyParts(rows[index], parts.slice(1)),\n );\n }\n }\n }\n }\n }\n } else {\n fragment.getChildElementFragments().forEach(child => {\n results.push(...Form.findFragmentByKeyParts(child, parts));\n });\n }\n return results;\n }\n\n /**\n * 対象のフラグメントがフォームフラグメントであればそれを返し、\n * そうでなければ先祖要素をたどってフォームフラグメントを探します。\n *\n * @param fragment\n */\n public static getFormFragment(\n fragment: ElementFragment,\n ): ElementFragment | null {\n const element = fragment.getTarget();\n if (element instanceof HTMLFormElement) {\n return fragment;\n }\n const parent = fragment.getParent();\n if (parent) {\n return this.getFormFragment(parent);\n }\n return null;\n }\n}\n","/**\n * @fileoverview 式評価エンジン\n *\n * 式評価システムです。\n * XSS攻撃やコードインジェクションを防ぐためのセキュリティ機能と、\n * パフォーマンス向上のためのキャッシュ機能を提供します。\n */\n\nimport Log from './log';\n\ntype ExpressionTokenType = 'identifier' | 'number' | 'string' | 'operator';\n\ninterface ExpressionToken {\n type: ExpressionTokenType;\n value: string;\n position: number;\n}\n\ntype GroupContext = 'paren' | 'array' | 'member' | 'object';\n\nexport default class Expression {\n /** Haoriで禁止すべき識別子一覧(eval と arguments は strict モードで無効化) */\n private static readonly FORBIDDEN_NAMES = [\n // グローバルオブジェクト\n 'window',\n 'self',\n 'globalThis',\n 'frames',\n 'parent',\n 'top',\n // 危険な関数/オブジェクト\n 'Function',\n 'setTimeout',\n 'setInterval',\n 'requestAnimationFrame',\n 'alert',\n 'confirm',\n 'prompt',\n 'fetch',\n 'XMLHttpRequest',\n 'Reflect',\n // 脱出経路・プロトタイプ\n 'constructor',\n '__proto__',\n 'prototype',\n 'Object',\n // その他\n 'document',\n 'location',\n 'navigator',\n 'localStorage',\n 'sessionStorage',\n 'IndexedDB',\n 'history',\n ];\n\n /** strict モードで禁止される識別子 */\n private static readonly STRICT_FORBIDDEN_NAMES = ['eval', 'arguments'];\n\n /** 明示バインド時のみ利用を許可する衝突名 */\n private static readonly REBINDABLE_FORBIDDEN_NAMES = new Set(['location']);\n\n /** バインド識別子としては拒否する名前 */\n private static readonly FORBIDDEN_BINDING_NAMES = new Set([\n ...Expression.FORBIDDEN_NAMES.filter(\n name => !Expression.REBINDABLE_FORBIDDEN_NAMES.has(name),\n ),\n 'constructor',\n '__proto__',\n 'prototype',\n ...Expression.STRICT_FORBIDDEN_NAMES,\n ]);\n\n /**\n * 明示バインド内に持ち込まれてはならない危険値を返します。\n *\n * @returns 危険値の配列\n */\n private static getForbiddenBindingValues(): unknown[] {\n const scope = globalThis as typeof globalThis & {\n window?: Window;\n document?: Document;\n navigator?: Navigator;\n history?: History;\n localStorage?: Storage;\n sessionStorage?: Storage;\n fetch?: typeof fetch;\n };\n const candidates: unknown[] = [\n scope,\n scope.window,\n scope.document,\n scope.navigator,\n scope.history,\n scope.localStorage,\n scope.sessionStorage,\n scope.fetch,\n scope.Function,\n scope.setTimeout,\n scope.setInterval,\n scope.requestAnimationFrame,\n scope.alert,\n scope.confirm,\n scope.prompt,\n ];\n if (scope.window?.location) {\n candidates.push(scope.window.location);\n }\n return candidates.filter(value => value !== undefined && value !== null);\n }\n\n /** プロパティアクセスで拒否する名前 */\n private static readonly FORBIDDEN_PROPERTY_NAMES = new Set([\n 'constructor',\n '__proto__',\n 'prototype',\n ]);\n\n /** object literal のプロパティ定義で前置修飾子として扱う識別子 */\n private static readonly OBJECT_PROPERTY_MODIFIERS = new Set([\n 'get',\n 'set',\n 'async',\n ]);\n\n /** 式構文として許可しない予約語 */\n private static readonly DISALLOWED_KEYWORDS = new Set([\n 'await',\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'export',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'import',\n 'in',\n 'instanceof',\n 'let',\n 'new',\n 'return',\n 'switch',\n 'this',\n 'throw',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n ]);\n\n /** 式 → 評価関数のグローバルキャッシュ */\n private static readonly EXPRESSION_CACHE = new Map<\n string,\n (...args: unknown[]) => unknown\n >();\n\n /**\n * 現在のバインド識別子に含まれない禁止グローバルを遮断するコードを生成します。\n *\n * @param bindKeys 現在の式で利用するバインド識別子一覧\n * @returns 評価前に挿入する初期化コード\n */\n private static buildAssignments(bindKeys: string[]): string {\n const bindKeySet = new Set(bindKeys);\n return this.FORBIDDEN_NAMES.filter(name => !bindKeySet.has(name))\n .map(name => `const ${name} = undefined`)\n .join(';\\n');\n }\n\n /**\n * 式を評価します。\n *\n * @param expression 評価する式文字列\n * @param bindedValue バインドされた値のオブジェクト\n */\n public static evaluate(\n expression: string,\n bindedValues: Record<string, unknown> = {},\n ): unknown {\n if (expression.trim() === '') {\n Log.warn('[Haori]', expression, 'Expression is empty');\n return null;\n }\n if (this.containsDangerousPatterns(expression)) {\n Log.warn('[Haori]', expression, 'Expression contains dangerous patterns');\n return null;\n }\n if (this.containsForbiddenKeys(bindedValues)) {\n Log.warn('[Haori]', bindedValues, 'Binded values contain forbidden keys');\n return null;\n }\n if (this.containsForbiddenBindingValues(bindedValues)) {\n Log.warn(\n '[Haori]',\n bindedValues,\n 'Binded values contain forbidden values',\n );\n return null;\n }\n\n const bindKeys = Object.keys(bindedValues)\n .filter(key => !this.FORBIDDEN_BINDING_NAMES.has(key))\n .sort();\n const cacheKey = `${expression}:${bindKeys.join(',')}`;\n\n let evaluator = this.EXPRESSION_CACHE.get(cacheKey);\n if (!evaluator) {\n const assignments = this.buildAssignments(bindKeys);\n const body = assignments\n ? '\"use strict\";\\n' + `${assignments};\\nreturn (${expression});`\n : '\"use strict\";\\n' + `return (${expression});`;\n try {\n evaluator = new Function(...bindKeys, body) as (\n ...args: unknown[]\n ) => unknown;\n this.EXPRESSION_CACHE.set(cacheKey, evaluator);\n } catch (error) {\n Log.error(\n '[Haori]',\n 'Failed to compile expression:',\n expression,\n error,\n );\n return null;\n }\n }\n try {\n const argValues: unknown[] = [];\n const wrappedValues = this.wrapBoundValues(bindedValues);\n bindKeys.forEach((key: string) => {\n argValues.push(wrappedValues[key]);\n });\n return this.withBlockedPropertyAccess(() => evaluator(...argValues));\n } catch (error) {\n Log.error('[Haori]', 'Expression evaluation error:', expression, error);\n if (error instanceof ReferenceError) {\n // ReferenceError(未定義変数)はundefinedを返す\n return undefined;\n }\n return null;\n }\n }\n\n /**\n * 式にevalや危険な構文が含まれているかチェックします。\n *\n * @param expression チェック対象の式文字列\n * @return 危険なパターンが含まれている場合はtrue\n */\n protected static containsDangerousPatterns(expression: string): boolean {\n if (!this.hasAllowedSyntax(expression)) {\n return true;\n }\n const dangerousPatterns = [\n /\\beval\\s*\\(/, // eval(...)\n /\\barguments\\s*\\[/, // arguments[...]\n /\\barguments\\s*\\./, // arguments.xxx\n ];\n return dangerousPatterns.some(pattern => pattern.test(expression));\n }\n\n /**\n * 許可する式構文かどうかを検証します。\n *\n * @param expression 検証対象の式\n * @returns 許可する構文であればtrue\n */\n private static hasAllowedSyntax(expression: string): boolean {\n const tokens = this.tokenizeExpression(expression);\n if (tokens === null || tokens.length === 0) {\n return false;\n }\n\n const groups: GroupContext[] = [];\n let previous: ExpressionToken | null = null;\n\n for (let index = 0; index < tokens.length; index++) {\n const token = tokens[index];\n const next = tokens[index + 1] || null;\n\n const activeGroup = groups[groups.length - 1] || null;\n const beforePrevious = tokens[index - 2] || null;\n const thirdPrevious = tokens[index - 3] || null;\n\n if (\n this.startsObjectKey(\n activeGroup,\n previous,\n beforePrevious,\n thirdPrevious,\n )\n ) {\n if (token.value === '[') {\n return false;\n }\n if (\n token.type === 'identifier' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(token.value)\n ) {\n return false;\n }\n if (\n token.type === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(\n this.decodeStringLiteral(token.value),\n )\n ) {\n return false;\n }\n }\n\n if (token.type === 'identifier') {\n if (this.DISALLOWED_KEYWORDS.has(token.value)) {\n return false;\n }\n if (this.STRICT_FORBIDDEN_NAMES.includes(token.value)) {\n return false;\n }\n if (\n (previous?.value === '.' || previous?.value === '?.') &&\n this.FORBIDDEN_PROPERTY_NAMES.has(token.value)\n ) {\n return false;\n }\n }\n\n if (activeGroup === 'member' && token.value !== ']') {\n if (\n token.type === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(\n this.decodeStringLiteral(token.value),\n )\n ) {\n return false;\n }\n }\n\n if (token.value === '.' && next?.type !== 'identifier') {\n return false;\n }\n\n if (\n token.value === '?.' &&\n next?.type !== 'identifier' &&\n next?.value !== '[' &&\n next?.value !== '('\n ) {\n return false;\n }\n\n switch (token.value) {\n case '(':\n groups.push('paren');\n break;\n case ')': {\n const group = groups.pop();\n if (group !== 'paren') {\n return false;\n }\n break;\n }\n case '[': {\n const group: GroupContext = this.startsMemberAccess(previous)\n ? 'member'\n : 'array';\n groups.push(group);\n break;\n }\n case '{':\n groups.push('object');\n break;\n case ']': {\n const group = groups.pop();\n if (group === undefined) {\n return false;\n }\n break;\n }\n case '}': {\n const group = groups.pop();\n if (group !== 'object') {\n return false;\n }\n break;\n }\n }\n\n previous = token;\n }\n\n return groups.length === 0;\n }\n\n /**\n * 式をトークン列に分解します。\n *\n * @param expression 評価前に検証する式\n * @returns 分解結果。未対応構文を含む場合はnull\n */\n private static tokenizeExpression(\n expression: string,\n ): ExpressionToken[] | null {\n const tokens: ExpressionToken[] = [];\n const operators = [\n '===',\n '!==',\n '...',\n '?.',\n '&&',\n '||',\n '>=',\n '<=',\n '==',\n '!=',\n '=>',\n ];\n const singleCharacters = new Set([\n '(',\n ')',\n '{',\n '}',\n '[',\n ']',\n '.',\n ',',\n '?',\n ':',\n '+',\n '-',\n '*',\n '/',\n '%',\n '!',\n '>',\n '<',\n ]);\n let index = 0;\n\n while (index < expression.length) {\n const current = expression[index];\n\n if (/\\s/.test(current)) {\n index += 1;\n continue;\n }\n\n if (\n current === '/' &&\n (expression[index + 1] === '/' || expression[index + 1] === '*')\n ) {\n return null;\n }\n\n if (current === '\"' || current === '\\'') {\n const stringToken = this.readStringToken(expression, index);\n if (stringToken === null) {\n return null;\n }\n tokens.push(stringToken.token);\n index = stringToken.nextIndex;\n continue;\n }\n\n const operator = operators.find(item =>\n expression.startsWith(item, index),\n );\n if (operator) {\n tokens.push({type: 'operator', value: operator, position: index});\n index += operator.length;\n continue;\n }\n\n if (/[0-9]/.test(current)) {\n const numberToken = this.readNumberToken(expression, index);\n tokens.push(numberToken.token);\n index = numberToken.nextIndex;\n continue;\n }\n\n if (/[A-Za-z_$]/.test(current)) {\n const identifierToken = this.readIdentifierToken(expression, index);\n tokens.push(identifierToken.token);\n index = identifierToken.nextIndex;\n continue;\n }\n\n if (singleCharacters.has(current)) {\n tokens.push({type: 'operator', value: current, position: index});\n index += 1;\n continue;\n }\n\n return null;\n }\n\n return tokens;\n }\n\n /**\n * 文字列リテラルを読み取ります。\n *\n * @param expression 式全体\n * @param start 開始位置\n * @returns トークンと次の位置\n */\n private static readStringToken(\n expression: string,\n start: number,\n ): {token: ExpressionToken; nextIndex: number} | null {\n const quote = expression[start];\n let index = start + 1;\n\n while (index < expression.length) {\n const current = expression[index];\n if (current === '\\\\') {\n index += 2;\n continue;\n }\n if (current === quote) {\n return {\n token: {\n type: 'string',\n value: expression.slice(start, index + 1),\n position: start,\n },\n nextIndex: index + 1,\n };\n }\n index += 1;\n }\n\n return null;\n }\n\n /**\n * 数値リテラルを読み取ります。\n *\n * @param expression 式全体\n * @param start 開始位置\n * @returns トークンと次の位置\n */\n private static readNumberToken(\n expression: string,\n start: number,\n ): {token: ExpressionToken; nextIndex: number} {\n let index = start;\n while (index < expression.length && /[0-9_]/.test(expression[index])) {\n index += 1;\n }\n if (expression[index] === '.') {\n index += 1;\n while (index < expression.length && /[0-9_]/.test(expression[index])) {\n index += 1;\n }\n }\n return {\n token: {\n type: 'number',\n value: expression.slice(start, index),\n position: start,\n },\n nextIndex: index,\n };\n }\n\n /**\n * 識別子を読み取ります。\n *\n * @param expression 式全体\n * @param start 開始位置\n * @returns トークンと次の位置\n */\n private static readIdentifierToken(\n expression: string,\n start: number,\n ): {token: ExpressionToken; nextIndex: number} {\n let index = start;\n while (\n index < expression.length &&\n /[A-Za-z0-9_$]/.test(expression[index])\n ) {\n index += 1;\n }\n return {\n token: {\n type: 'identifier',\n value: expression.slice(start, index),\n position: start,\n },\n nextIndex: index,\n };\n }\n\n /**\n * 角括弧がメンバーアクセスかどうかを判定します。\n *\n * @param previous 直前のトークン\n * @returns メンバーアクセスであればtrue\n */\n private static startsMemberAccess(previous: ExpressionToken | null): boolean {\n if (previous === null) {\n return false;\n }\n if (previous.type === 'identifier' || previous.type === 'number') {\n return true;\n }\n return (\n previous.value === ')' ||\n previous.value === ']' ||\n previous.value === '?.'\n );\n }\n\n /**\n * object literal 内で次のトークンがキー位置かどうかを判定します。\n *\n * @param activeGroup 現在のグループ種別\n * @param previous 直前のトークン\n * @returns object literal のキー位置であれば true\n */\n private static startsObjectKey(\n activeGroup: GroupContext | null,\n previous: ExpressionToken | null,\n beforePrevious: ExpressionToken | null,\n thirdPrevious: ExpressionToken | null,\n ): boolean {\n if (activeGroup !== 'object') {\n return false;\n }\n if (previous?.value === '{' || previous?.value === ',') {\n return true;\n }\n\n if (\n previous?.type === 'identifier' &&\n this.OBJECT_PROPERTY_MODIFIERS.has(previous.value) &&\n (beforePrevious?.value === '{' || beforePrevious?.value === ',')\n ) {\n return true;\n }\n\n if (previous?.value !== '*') {\n return false;\n }\n\n if (beforePrevious?.value === '{' || beforePrevious?.value === ',') {\n return true;\n }\n\n return (\n beforePrevious?.type === 'identifier' &&\n beforePrevious.value === 'async' &&\n (thirdPrevious?.value === '{' || thirdPrevious?.value === ',')\n );\n }\n\n /**\n * 文字列リテラルをプレーン文字列へ変換します。\n *\n * @param literal 文字列リテラル\n * @returns デコード後の文字列\n */\n private static decodeStringLiteral(literal: string): string {\n return literal\n .slice(1, -1)\n .replace(/\\\\u\\{([0-9a-fA-F]+)\\}/g, (_, code: string) =>\n String.fromCodePoint(parseInt(code, 16)),\n )\n .replace(/\\\\u([0-9a-fA-F]{4})/g, (_, code: string) =>\n String.fromCharCode(parseInt(code, 16)),\n )\n .replace(/\\\\x([0-9a-fA-F]{2})/g, (_, code: string) =>\n String.fromCharCode(parseInt(code, 16)),\n )\n .replace(/\\\\([\"'\\\\bfnrtv0])/g, (_, escaped: string) => {\n switch (escaped) {\n case 'b':\n return '\\b';\n case 'f':\n return '\\f';\n case 'n':\n return '\\n';\n case 'r':\n return '\\r';\n case 't':\n return '\\t';\n case 'v':\n return '\\v';\n case '0':\n return '\\0';\n default:\n return escaped;\n }\n });\n }\n\n /**\n * バインド値を安全なProxyでラップします。\n *\n * @param bindedValues バインド値\n * @returns ラップ済みのバインド値\n */\n private static wrapBoundValues(\n bindedValues: Record<string, unknown>,\n ): Record<string, unknown> {\n const cache = new WeakMap<object, unknown>();\n const wrappedValues: Record<string, unknown> = {};\n\n Object.entries(bindedValues).forEach(([key, value]) => {\n wrappedValues[key] = this.wrapBoundValue(value, cache);\n });\n\n return wrappedValues;\n }\n\n /**\n * 危険なプロパティアクセスを防ぐために値を再帰的にラップします。\n *\n * @param value ラップ対象の値\n * @param cache 既存Proxyのキャッシュ\n * @returns ラップ済みの値\n */\n private static wrapBoundValue(\n value: unknown,\n cache: WeakMap<object, unknown>,\n ): unknown {\n if (!this.shouldWrapValue(value)) {\n return value;\n }\n\n const target = value as object;\n const cachedValue = cache.get(target);\n if (cachedValue !== undefined) {\n return cachedValue;\n }\n\n const proxy = new Proxy(target, {\n get: (currentTarget, property, receiver) => {\n if (\n typeof property === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(property)\n ) {\n return undefined;\n }\n const result = Reflect.get(currentTarget, property, receiver);\n if (typeof property === 'symbol') {\n return result;\n }\n return this.wrapBoundValue(\n result,\n cache,\n );\n },\n has: (currentTarget, property) => {\n if (\n typeof property === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(property)\n ) {\n return false;\n }\n return Reflect.has(currentTarget, property);\n },\n getOwnPropertyDescriptor: (currentTarget, property) => {\n if (\n typeof property === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(property)\n ) {\n return undefined;\n }\n return Reflect.getOwnPropertyDescriptor(currentTarget, property);\n },\n apply: (currentTarget, thisArg, argArray) => {\n const result = Reflect.apply(\n currentTarget as (...args: unknown[]) => unknown,\n thisArg,\n argArray,\n );\n if (this.isIteratorLike(result)) {\n return result;\n }\n return this.wrapBoundValue(result, cache);\n },\n construct: (currentTarget, argArray, newTarget) => {\n return this.wrapBoundValue(\n Reflect.construct(\n currentTarget as new (...args: unknown[]) => object,\n argArray,\n newTarget,\n ),\n cache,\n ) as object;\n },\n });\n\n cache.set(target, proxy);\n return proxy;\n }\n\n /**\n * Proxy ラップ対象の値かどうかを判定します。\n *\n * @param value 判定対象\n * @returns ラップ対象であればtrue\n */\n private static shouldWrapValue(value: unknown): value is object {\n if (typeof value === 'function') {\n return true;\n }\n if (value === null || typeof value !== 'object') {\n return false;\n }\n if (Array.isArray(value)) {\n return true;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n }\n\n /**\n * 評価中のみ prototype 系プロパティへの生アクセスを抑止します。\n *\n * @param callback 実行する処理\n * @returns 処理結果\n */\n private static withBlockedPropertyAccess<T>(callback: () => T): T {\n const blockedDescriptors = [\n {target: Object.prototype, property: 'constructor'},\n {target: Function.prototype, property: 'constructor'},\n {target: Object.prototype, property: '__proto__'},\n ] as const;\n const originals = blockedDescriptors\n .map(item => ({\n ...item,\n descriptor: Object.getOwnPropertyDescriptor(item.target, item.property),\n }))\n .filter(item => item.descriptor?.configurable === true);\n\n originals.forEach(({target, property}) => {\n Object.defineProperty(target, property, {\n configurable: true,\n enumerable: false,\n get: () => undefined,\n set: () => undefined,\n });\n });\n\n try {\n return callback();\n } finally {\n originals.forEach(({target, property, descriptor}) => {\n if (descriptor !== undefined) {\n Object.defineProperty(target, property, descriptor);\n }\n });\n }\n }\n\n /**\n * イテレータ互換オブジェクトかどうかを判定します。\n *\n * @param value 判定対象\n * @returns イテレータ互換であればtrue\n */\n private static isIteratorLike(value: unknown): boolean {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n return typeof (value as Iterator<unknown>).next === 'function';\n }\n\n /**\n * トップレベルのバインド識別子に拒否対象名が含まれていないかを判定します。\n * ネストしたオブジェクトのプロパティ名は識別子として評価されないため、ここでは拒否しません。\n *\n * @param obj チェック対象のオブジェクト\n * @return 禁止識別子が含まれていればtrue\n */\n protected static containsForbiddenKeys(obj: unknown): boolean {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n\n for (const key of Object.keys(obj as object)) {\n if (this.FORBIDDEN_BINDING_NAMES.has(key)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * バインド値に危険なホストオブジェクトやグローバル関数が含まれていないかを再帰的に判定します。\n *\n * @param obj チェック対象の値\n * @param seen 循環参照検出用の訪問済み集合\n * @return 危険値が含まれていればtrue\n */\n protected static containsForbiddenBindingValues(\n obj: unknown,\n seen: WeakSet<object> = new WeakSet<object>(),\n ): boolean {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n\n if (seen.has(obj as object)) {\n return false;\n }\n seen.add(obj as object);\n\n if (this.getForbiddenBindingValues().some(value => value === obj)) {\n return true;\n }\n\n for (const value of Object.values(obj as Record<string, unknown>)) {\n if (typeof value === 'function') {\n if (\n this.getForbiddenBindingValues().some(\n forbidden => forbidden === value,\n )\n ) {\n return true;\n }\n continue;\n }\n if (this.containsForbiddenBindingValues(value, seen)) {\n return true;\n }\n }\n\n return false;\n }\n}\n","/**\n * @fileoverview 仮想DOM実装\n *\n * メモリ上にノードツリーを保持し、DOMへの反映を非同期で行います。\n * DOMからの読み込みは行わず、オブザーバーとchangeイベントで更新されます。\n */\nimport Queue from './queue';\nimport Log from './log';\nimport Expression from './expression';\nimport Env from './env';\n\n/**\n * 仮想DOMのフラグメントの抽象クラス。\n */\nexport default abstract class Fragment {\n /** フラグメントの対象ノードに対するキャッシュ */\n protected static readonly FRAGMENT_CACHE = new WeakMap<Node, Fragment>();\n\n /**\n * フラグメントを取得もしくは作成します。\n *\n * @param node 対象ノード\n * @returns フラグメント\n */\n public static get(node: HTMLElement): ElementFragment;\n public static get(node: Text): TextFragment;\n public static get(node: Comment): CommentFragment;\n public static get(node: Node | null): Fragment | null;\n public static get(node: Node | null): Fragment | null {\n if (node == null) {\n return null;\n }\n if (Fragment.FRAGMENT_CACHE.has(node)) {\n return Fragment.FRAGMENT_CACHE.get(node)!;\n }\n let fragment;\n switch (node.nodeType) {\n case Node.ELEMENT_NODE:\n fragment = new ElementFragment(node as HTMLElement);\n break;\n case Node.TEXT_NODE:\n fragment = new TextFragment(node as Text);\n break;\n case Node.COMMENT_NODE:\n fragment = new CommentFragment(node as Comment);\n break;\n default:\n Log.warn('[Haori]', 'Unsupported node type:', node.nodeType);\n return null;\n }\n return fragment;\n }\n\n /** 親フラグメント */\n protected parent: ElementFragment | null = null;\n\n /** 対象ノード */\n protected readonly target: Node;\n\n /** フラグメントがDOMにマウントされているかどうか */\n protected mounted = false;\n\n /** ノード更新スキップフラグ(オブザーバーによる無限ループ対応) */\n protected skipMutationNodes = false;\n\n /**\n * フラグメントのコンストラクタ。\n *\n * @param target 対象ノード\n */\n protected constructor(target: Node) {\n this.target = target;\n Fragment.FRAGMENT_CACHE.set(target, this);\n }\n\n /**\n * skipMutationNodesフラグの値を取得します。\n *\n * @returns skipMutationNodesの値\n */\n public isSkipMutationNodes(): boolean {\n return this.skipMutationNodes;\n }\n\n /**\n * フラグメントをDOMから除去します。\n *\n * @return 除去のPromise\n */\n public unmount(): Promise<void> {\n if (!this.mounted || this.skipMutationNodes) {\n return Promise.resolve();\n }\n if (this.parent) {\n const parent = this.parent;\n const prevSkip = parent.skipMutationNodes;\n return Queue.enqueue(() => {\n parent.skipMutationNodes = true;\n if (this.target.parentNode === parent.getTarget()) {\n parent.getTarget().removeChild(this.target);\n }\n this.mounted = false;\n }).finally(() => {\n parent.skipMutationNodes = prevSkip;\n }) as Promise<void>;\n } else {\n // 親フラグメント情報が無くても、DOM 上に親ノードが存在する場合は安全に除去する。\n const host = this.target.parentNode as (HTMLElement | null);\n if (host) {\n return Queue.enqueue(() => {\n if (this.target.parentNode === host) {\n host.removeChild(this.target);\n }\n this.mounted = false;\n }) as Promise<void>;\n }\n this.mounted = false;\n }\n return Promise.resolve();\n }\n\n /**\n * フラグメントをDOMに追加します。\n *\n * @return 追加のPromise\n */\n public mount(): Promise<void> {\n if (this.mounted || this.skipMutationNodes) {\n return Promise.resolve();\n }\n if (this.parent) {\n const parent = this.parent;\n const prevSkip = parent.skipMutationNodes;\n return Queue.enqueue(() => {\n parent.skipMutationNodes = true;\n if (this.target.parentNode !== parent.getTarget()) {\n // 既に同じ親なら何もしない\n parent.getTarget().appendChild(this.target);\n }\n this.mounted = true;\n }).finally(() => {\n parent.skipMutationNodes = prevSkip;\n }) as Promise<void>;\n }\n return Promise.resolve();\n }\n\n /**\n * フラグメントのマウント状態を取得します。\n *\n * @returns マウント状態\n */\n public isMounted(): boolean {\n return this.mounted;\n }\n\n /**\n * フラグメントのマウント状態を設定します。\n *\n * @param mounted マウント状態\n */\n public setMounted(mounted: boolean): void {\n this.mounted = mounted;\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public abstract clone(): Fragment;\n\n /**\n * フラグメントとノードを削除します。\n *\n * @param unmount DOMからの除去を行うかどうか(内部の子呼び出しの場合のみfalseとする)\n * @return 除去のPromise\n */\n public remove(unmount = true): Promise<void> {\n if (this.parent) {\n this.parent.removeChild(this);\n }\n Fragment.FRAGMENT_CACHE.delete(this.target);\n if (unmount) {\n return this.unmount();\n }\n return Promise.resolve();\n }\n\n /**\n * 対象ノードを取得します。\n *\n * @returns 対象ノード\n */\n public getTarget(): Node {\n return this.target;\n }\n\n /**\n * 親フラグメントを取得します。\n *\n * @returns 親フラグメント\n */\n public getParent(): ElementFragment | null {\n return this.parent;\n }\n\n /**\n * 親フラグメントを設定します。\n *\n * @param parent 親フラグメント\n */\n public setParent(parent: ElementFragment | null): void {\n this.parent = parent;\n }\n}\n\n/**\n * エレメントフラグメント。\n * DOM要素を表現し、子ノードを持つことができます。\n */\nexport class ElementFragment extends Fragment {\n /** inputイベントを発生させるタイプ */\n private readonly INPUT_EVENT_TYPES = [\n 'text',\n 'password',\n 'email',\n 'url',\n 'tel',\n 'search',\n 'number',\n 'range',\n 'color',\n 'date',\n 'datetime-local',\n 'month',\n 'time',\n 'week',\n ];\n\n /** 子フラグメントのリスト */\n private readonly children: Fragment[] = [];\n\n /** 属性名に対する属性情報のマップ */\n private readonly attributeMap = new Map<string, AttributeContents>();\n\n /** バインドデータ */\n private bindingData: Record<string, unknown> | null = null;\n\n /** バインドデータのキャッシュ */\n private bindingDataCache: Record<string, unknown> | null = null;\n\n /** 表示状態 */\n private visible = true;\n\n /** 元の display 値 */\n private display: string | null = null;\n\n /** each用のテンプレート */\n private template: ElementFragment | null = null;\n\n /** each比較用のキー */\n private listKey: string | null = null;\n\n /** valueプロパティの値 */\n private value: string | number | boolean | null = null;\n\n /** 属性更新スキップフラグ(オブザーバーによる無限ループ対応) */\n private skipMutationAttributes = false;\n\n /** 値変更スキップフラグ(更新イベントによる無限ループ対応) */\n private skipChangeValue = false;\n\n /**\n * エレメントフラグメントのコンストラクタ。\n * アトリビュートや子フラグメントの作成も行います。\n *\n * @param target 対象エレメント\n */\n public constructor(target: HTMLElement) {\n super(target);\n this.syncValue();\n target.getAttributeNames().forEach(name => {\n const value = target.getAttribute(name);\n if (value !== null && !this.attributeMap.has(name)) {\n const contents = new AttributeContents(name, value);\n this.attributeMap.set(name, contents);\n }\n });\n target.childNodes.forEach(node => {\n const childFragment = Fragment.get(node);\n childFragment!.setParent(this);\n this.children.push(childFragment!);\n });\n }\n\n /**\n * 子フラグメントのリストを取得します。\n *\n * @returns 子フラグメントのリスト\n */\n public getChildren(): Fragment[] {\n return this.children;\n }\n\n /**\n * 子エレメントフラグメントのリストを取得します。\n *\n * @returns 子エレメントフラグメントのリスト\n */\n public getChildElementFragments(): ElementFragment[] {\n return this.children.filter(\n child => child instanceof ElementFragment,\n ) as ElementFragment[];\n }\n\n /**\n * 子フラグメントをリストに追加します。\n * DOMの追加は行いません。\n *\n * @param child 追加する子フラグメント\n */\n public pushChild(child: Fragment) {\n this.children.push(child);\n child.setParent(this);\n }\n\n /**\n * 子フラグメントをリストから削除します。\n * DOMからの削除は行いません。\n *\n * @param child 削除する子フラグメント\n */\n public removeChild(child: Fragment): void {\n const index = this.children.indexOf(child);\n if (index < 0) {\n Log.warn('[Haori]', 'Child fragment not found.', child);\n return;\n }\n this.children.splice(index, 1);\n child.setParent(null);\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public clone(): ElementFragment {\n const clone = new ElementFragment(\n this.target.cloneNode(false) as HTMLElement,\n );\n // DOM 属性は評価後の値になっているため、\n // クローンでは attributeMap をコピーしてテンプレート式を保持します。\n this.attributeMap.forEach((contents, name) => {\n clone.attributeMap.set(name, contents);\n });\n this.children.forEach(child => {\n const childClone = child.clone();\n clone.getTarget().appendChild(childClone.getTarget());\n clone.pushChild(childClone);\n });\n clone.mounted = false;\n clone.bindingData = this.bindingData;\n clone.clearBindingDataCache();\n clone.visible = this.visible;\n clone.display = this.display;\n clone.template = this.template;\n return clone;\n }\n\n /**\n * フラグメントとノードを削除します。\n *\n * @param unmount DOMからの除去を行うかどうか(内部の子呼び出しの場合のみfalseとする)\n * @return 除去のPromise\n */\n public remove(unmount = true): Promise<void> {\n const promises: Promise<void>[] = [];\n this.children.forEach(child => {\n promises.push(child.remove(false));\n });\n this.children.length = 0;\n this.attributeMap.clear();\n this.bindingData = null;\n this.bindingDataCache = null;\n if (this.template) {\n promises.push(this.template.remove(false));\n this.template = null;\n }\n promises.push(super.remove(unmount));\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * フラグメントの対象エレメントを取得します。\n *\n * @returns フラグメントの対象エレメント\n */\n public getTarget(): HTMLElement {\n return this.target as HTMLElement;\n }\n\n /**\n * 継承を考慮したバインドデータを取得します。\n *\n * @returns バインドデータのオブジェクト\n */\n public getBindingData(): Record<string, unknown> {\n if (this.bindingDataCache) {\n return this.bindingDataCache;\n }\n this.bindingDataCache = {};\n if (this.parent) {\n Object.assign(this.bindingDataCache, this.parent.getBindingData());\n }\n if (this.bindingData) {\n Object.assign(this.bindingDataCache, this.bindingData);\n }\n return this.bindingDataCache;\n }\n\n /**\n * 生のバインドデータを取得します。\n *\n * @returns 生のバインドデータ\n */\n public getRawBindingData(): Record<string, unknown> | null {\n return this.bindingData;\n }\n\n /**\n * バインドデータを設定します。\n *\n * @param data バインドデータ\n */\n public setBindingData(data: Record<string, unknown>): void {\n this.bindingData = data;\n this.clearBindingDataCache();\n }\n\n /**\n * 親フラグメントを設定します。バインドデータキャッシュをクリアします。\n *\n * @param parent 親フラグメント\n */\n public override setParent(parent: ElementFragment | null): void {\n if (this.parent === parent) {\n return;\n }\n this.parent = parent;\n this.clearBindingDataCache();\n }\n\n /**\n * バインドデータのキャッシュをクリアします。\n */\n public clearBindingDataCache(): void {\n this.bindingDataCache = null;\n this.children.forEach(child => {\n if (child instanceof ElementFragment) {\n child.clearBindingDataCache();\n }\n });\n }\n\n /**\n * フラグメントのテンプレートを取得します。\n *\n * @returns テンプレート\n */\n public getTemplate(): ElementFragment | null {\n return this.template;\n }\n\n /**\n * フラグメントのテンプレートを設定します。\n *\n * @param template フラグメントのテンプレート\n */\n public setTemplate(template: ElementFragment | null): void {\n this.template = template;\n }\n\n /**\n * 比較用リストキーを設定します。\n *\n * @param key 比較用リストキー\n */\n public setListKey(key: string): void {\n this.listKey = key;\n }\n\n /**\n * 比較用リストキーを取得します。\n *\n * @returns 比較用リストキー\n */\n public getListKey(): string | null {\n return this.listKey;\n }\n\n /**\n * 入力エレメントに値を設定します。\n * チェックボックとラジオボタンの場合は値に一致するかどうかでチェック状態を変更します。\n *\n * @param value 値\n * @returns エレメントの更新のPromise\n */\n public setValue(value: string | number | boolean | null): Promise<void> {\n return this.applyValue(value, true);\n }\n\n /**\n * 入力エレメントに値をイベントなしで設定します。\n * フォームの bindingData 反映時に内部同期として利用します。\n *\n * @param value 値\n * @returns エレメントの更新のPromise\n */\n public syncBindingValue(\n value: string | number | boolean | null,\n ): Promise<void> {\n return this.applyValue(value, false);\n }\n\n /**\n * 入力エレメントに値を設定します。\n * 必要に応じて入力系イベントも発火します。\n *\n * @param value 値\n * @param dispatchEvents input/change イベントを発火するかどうか\n * @returns エレメントの更新のPromise\n */\n private applyValue(\n value: string | number | boolean | null,\n dispatchEvents: boolean,\n ): Promise<void> {\n if (this.skipChangeValue) {\n return Promise.resolve();\n }\n if (this.value === value) {\n return Promise.resolve();\n }\n const element = this.getTarget();\n if (\n element instanceof HTMLInputElement &&\n (element.type === 'checkbox' || element.type === 'radio')\n ) {\n const result = this.getAttribute('value');\n const isBooleanCheckbox =\n element.type === 'checkbox' && result === 'true';\n let newChecked: boolean;\n if (isBooleanCheckbox) {\n newChecked = value === true || value === 'true';\n } else if (result === 'false') {\n newChecked = value === false;\n } else {\n newChecked = result === String(value);\n }\n this.value = isBooleanCheckbox\n ? newChecked\n : newChecked\n ? value\n : null;\n if (element.checked === newChecked) {\n return Promise.resolve();\n }\n this.skipChangeValue = true;\n return Queue.enqueue(() => {\n element.checked = newChecked;\n if (dispatchEvents) {\n element.dispatchEvent(new Event('change', {bubbles: true}));\n }\n }).finally(() => {\n this.skipChangeValue = false;\n }) as Promise<void>;\n } else if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n this.value = value;\n this.skipChangeValue = true;\n return Queue.enqueue(() => {\n element.value = value === null ? '' : String(value);\n if (dispatchEvents) {\n if (\n (element instanceof HTMLInputElement &&\n this.INPUT_EVENT_TYPES.includes(element.type)) ||\n element instanceof HTMLTextAreaElement\n ) {\n element.dispatchEvent(new Event('input', {bubbles: true}));\n }\n element.dispatchEvent(new Event('change', {bubbles: true}));\n }\n }).finally(() => {\n this.skipChangeValue = false;\n }) as Promise<void>;\n } else {\n Log.warn(\n '[Haori]',\n 'setValue is not supported for this element type.',\n element,\n );\n return Promise.resolve();\n }\n }\n\n /**\n * 入力エレメントの値を取得します。\n * DOM要素の現在の値と同期します。\n *\n * @returns 入力エレメントの値\n */\n public getValue(): string | number | boolean | null {\n return this.value;\n }\n\n /**\n * 内部の値をクリアします。エレメントのvalue値は変化しません。\n */\n public clearValue() {\n this.value = null;\n }\n\n /**\n * 内部の値をDOMの値と同期します。\n * changeイベント時など、DOM値が変更された後に呼び出されます。\n */\n public syncValue() {\n const element = this.getTarget();\n if (element instanceof HTMLInputElement) {\n if (element.type === 'checkbox' || element.type === 'radio') {\n const isBooleanCheckbox =\n element.type === 'checkbox' && element.value === 'true';\n if (element.checked) {\n const value = element.value;\n if (isBooleanCheckbox) {\n this.value = true;\n } else if (value === 'false') {\n this.value = false;\n } else {\n this.value = value;\n }\n } else {\n // チェックボックスがOFFの場合\n const value = element.value;\n if (isBooleanCheckbox) {\n this.value = false;\n } else if (value === 'false') {\n this.value = true;\n } else {\n this.value = null;\n }\n }\n } else {\n this.value = element.value;\n }\n } else if (element instanceof HTMLTextAreaElement) {\n this.value = element.value;\n } else if (element instanceof HTMLSelectElement) {\n this.value = element.value;\n }\n }\n\n /**\n * 属性の値を評価して設定します。\n * 評価値がfalseの場合は属性を削除します。\n * 矯正評価属性の場合は元の値を設定します。\n *\n * @param name 属性名\n * @param value 属性値\n * @returns 属性の更新のPromise\n */\n public setAttribute(name: string, value: string | null): Promise<void> {\n return this.setAttributeInternal(name, name, value, true);\n }\n\n /**\n * data-attr-* の生値を保持しつつ、別名の属性へ評価結果を反映します。\n *\n * @param rawName 生の属性名\n * @param targetName 反映先の属性名\n * @param value 生の属性値\n * @returns 属性更新の Promise\n */\n public setAliasedAttribute(\n rawName: string,\n targetName: string,\n value: string | null,\n ): Promise<void> {\n return this.setAttributeInternal(rawName, targetName, value, false);\n }\n\n /**\n * data-attr-* の生属性と反映先属性を同時に削除します。\n *\n * @param rawName 生の属性名\n * @param targetName 反映先の属性名\n * @returns 属性削除の Promise\n */\n public removeAliasedAttribute(\n rawName: string,\n targetName: string,\n ): Promise<void> {\n if (this.skipMutationAttributes) {\n return Promise.resolve();\n }\n this.attributeMap.delete(rawName);\n this.skipMutationAttributes = true;\n const element = this.getTarget();\n return Queue.enqueue(() => {\n element.removeAttribute(rawName);\n if (targetName !== rawName) {\n element.removeAttribute(targetName);\n }\n }).finally(() => {\n this.skipMutationAttributes = false;\n }) as Promise<void>;\n }\n\n /**\n * 生の属性値を保持しつつ、必要に応じて別名属性へ評価結果を反映します。\n *\n * @param rawName 生の属性名\n * @param targetName 反映先の属性名\n * @param value 生の属性値\n * @param syncValueProperty value 属性更新時に DOM property も同期するかどうか\n * @returns 属性更新の Promise\n */\n private setAttributeInternal(\n rawName: string,\n targetName: string,\n value: string | null,\n syncValueProperty: boolean,\n ): Promise<void> {\n if (this.skipMutationAttributes) {\n return Promise.resolve();\n }\n if (value === null) {\n if (rawName === targetName) {\n return this.removeAttribute(rawName);\n }\n return this.removeAliasedAttribute(rawName, targetName);\n }\n const contents = new AttributeContents(rawName, value);\n this.attributeMap.set(rawName, contents);\n this.skipMutationAttributes = true;\n const element = this.getTarget();\n const result = contents.isForceEvaluation()\n ? value\n : this.getAttribute(rawName);\n return Queue.enqueue(() => {\n if (element.getAttribute(rawName) !== value) {\n element.setAttribute(rawName, value);\n }\n if (result === null || result === false) {\n element.removeAttribute(targetName);\n } else {\n const string = String(result);\n if (element.getAttribute(targetName) !== string) {\n element.setAttribute(targetName, string);\n }\n // element.setAttribute('value', ...) は defaultValue のみ更新するため、\n // setValue と同じ対象には element.value も反映して DOM と内部状態を揃える。\n if (\n syncValueProperty &&\n contents.isEvaluate &&\n targetName === 'value' &&\n ((element instanceof HTMLInputElement &&\n this.INPUT_EVENT_TYPES.includes(element.type)) ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement)\n ) {\n this.value = string;\n if (element.value !== string) {\n element.value = string;\n }\n }\n }\n }).finally(() => {\n this.skipMutationAttributes = false;\n }) as Promise<void>;\n }\n\n /**\n * 属性の値を削除します。\n *\n * @param name 属性名\n * @returns 属性の削除のPromise\n */\n public removeAttribute(name: string): Promise<void> {\n if (this.skipMutationAttributes) {\n return Promise.resolve();\n }\n this.attributeMap.delete(name);\n this.skipMutationAttributes = true;\n const element = this.getTarget();\n return Queue.enqueue(() => {\n element.removeAttribute(name);\n }).finally(() => {\n this.skipMutationAttributes = false;\n }) as Promise<void>;\n }\n\n /**\n * 属性の評価された値を取得します。\n * 複数の評価値がある場合は結合して返します。\n *\n * @param name 属性名\n * @returns 評価された値\n */\n public getAttribute(name: string): string | false | unknown | null {\n const contents = this.attributeMap.get(name);\n if (contents === undefined) {\n return null;\n }\n const results = contents.evaluate(this.getBindingData());\n if (results.length === 1) {\n return results[0];\n }\n return TextContents.joinEvaluateResults(results);\n }\n\n /**\n * 属性の生の値を取得します。\n *\n * @param name 属性名\n * @returns 生の属性値\n */\n public getRawAttribute(name: string): string | null {\n const contents = this.attributeMap.get(name);\n if (contents === undefined) {\n return null;\n }\n return contents.getValue();\n }\n\n /**\n * 属性名のリストを取得します。\n *\n * @return 属性名のリスト\n */\n public getAttributeNames(): string[] {\n return Array.from(this.attributeMap.keys());\n }\n\n /**\n * 属性の有無を確認します。\n *\n * @param name 属性名\n * @returns 属性の有無\n */\n public hasAttribute(name: string): boolean {\n return this.attributeMap.has(name);\n }\n\n /**\n * DOM上の順序から、参照フラグメントに対応する children 配列の挿入位置を推定します。\n *\n * @param referenceChild 参照フラグメント\n * @param insertAfter 参照位置の後ろに挿入するかどうか\n * @returns 挿入位置。解決できない場合はnull\n */\n private resolveInsertionPointFromDom(\n referenceChild: Fragment,\n insertAfter: boolean,\n ): {index: number; referenceNode: Node | null} | null {\n const referenceNode = referenceChild.getTarget();\n if (referenceNode.parentNode !== this.target) {\n return null;\n }\n\n const insertionReferenceNode = insertAfter\n ? referenceNode.nextSibling\n : referenceNode;\n\n let nextTrackedNode = insertAfter\n ? referenceNode.nextSibling\n : referenceNode;\n while (nextTrackedNode !== null) {\n const childFragment = Fragment.get(nextTrackedNode);\n if (childFragment !== null) {\n const childIndex = this.children.indexOf(childFragment);\n if (childIndex !== -1) {\n return {index: childIndex, referenceNode: insertionReferenceNode};\n }\n }\n nextTrackedNode = nextTrackedNode.nextSibling;\n }\n\n return {index: this.children.length, referenceNode: insertionReferenceNode};\n }\n\n /**\n * 子ノードを参照ノードの前に挿入します。\n * 参照ノードがnullの場合、親の最後に追加されます。\n *\n * @param newChild 新しい子ノード\n * @param referenceChild 参照ノード\n * @return 挿入のPromise\n */\n public insertBefore(\n newChild: Fragment,\n referenceChild: Fragment | null,\n referenceNodeOverride?: Node | null,\n ): Promise<void> {\n if (this.skipMutationNodes) {\n return Promise.resolve();\n }\n\n // 循環参照チェック\n if (newChild === this) {\n Log.error('[Haori]', 'Cannot insert element as child of itself');\n return Promise.reject(new Error('Self-insertion not allowed'));\n }\n\n // 祖先チェック\n const ancestors = new Set<Fragment>();\n let ancestor = this.parent;\n while (ancestor) {\n ancestors.add(ancestor);\n ancestor = ancestor.getParent();\n }\n if (ancestors.has(newChild)) {\n Log.error('[Haori]', 'Cannot create circular reference');\n return Promise.reject(new Error('Circular reference detected'));\n }\n\n // 同じ親内での移動かどうかを確認\n const isSameParent = newChild.getParent() === this;\n let newChildIndex = -1;\n let referenceIndex = -1;\n\n if (isSameParent) {\n newChildIndex = this.children.indexOf(newChild);\n if (referenceChild !== null) {\n referenceIndex = this.children.indexOf(referenceChild);\n }\n }\n\n const newChildParent = newChild.getParent();\n if (newChildParent !== null) {\n // 既存の親から削除\n newChildParent.removeChild(newChild);\n }\n\n let referenceNode: Node | null =\n referenceNodeOverride === undefined\n ? referenceChild?.getTarget() || null\n : referenceNodeOverride;\n\n if (referenceChild === null) {\n this.children.push(newChild);\n } else {\n let index: number;\n if (isSameParent) {\n // 同じ親内での移動の場合、削除後のインデックスを調整\n if (newChildIndex !== -1 && newChildIndex < referenceIndex) {\n // 削除する要素が参照要素より前にあった場合、インデックスは1つ減る\n index = referenceIndex - 1;\n } else {\n index = referenceIndex;\n }\n } else {\n index = this.children.indexOf(referenceChild);\n }\n\n if (index === -1) {\n const insertionPoint = this.resolveInsertionPointFromDom(\n referenceChild,\n false,\n );\n if (insertionPoint === null) {\n Log.warn(\n '[Haori]',\n 'Reference child not found in children.',\n referenceChild,\n );\n this.children.push(newChild);\n } else {\n this.children.splice(insertionPoint.index, 0, newChild);\n referenceNode = insertionPoint.referenceNode;\n }\n } else {\n this.children.splice(index, 0, newChild);\n }\n }\n\n newChild.setParent(this);\n newChild.setMounted(this.mounted);\n\n const prevSkip = this.skipMutationNodes;\n this.skipMutationNodes = true;\n return Queue.enqueue(() => {\n this.target.insertBefore(newChild.getTarget(), referenceNode);\n }).finally(() => {\n this.skipMutationNodes = prevSkip;\n }) as Promise<void>;\n }\n\n /**\n * 指定した参照ノードの後に子ノードを挿入します。\n *\n * @param newChild 子ノード\n * @param referenceChild 参照ノード\n * @returns 挿入のPromise\n */\n public insertAfter(\n newChild: Fragment,\n referenceChild: Fragment | null,\n ): Promise<void> {\n if (referenceChild == null) {\n return this.insertBefore(newChild, null);\n }\n const index = this.children.indexOf(referenceChild);\n if (index === -1) {\n const insertionPoint = this.resolveInsertionPointFromDom(\n referenceChild,\n true,\n );\n if (insertionPoint === null) {\n Log.warn(\n '[Haori]',\n 'Reference child not found in children.',\n referenceChild,\n );\n return this.insertBefore(newChild, null);\n }\n return this.insertBefore(\n newChild,\n this.children[insertionPoint.index] || null,\n insertionPoint.referenceNode,\n );\n }\n return this.insertBefore(newChild, this.children[index + 1] || null);\n }\n\n /**\n * 前のエレメントフラグメントを取得します。\n * 存在しない場合はnullを返します。\n *\n * @return 前のエレメントフラグメントまたはnull\n */\n public getPrevious(): ElementFragment | null {\n const parent = this.getParent();\n if (parent === null) {\n return null;\n }\n const siblings = parent.getChildElementFragments();\n const index = siblings.indexOf(this);\n if (index <= 0) {\n return null;\n }\n return siblings[index - 1];\n }\n\n /**\n * 次のエレメントフラグメントを取得します。\n * 存在しない場合はnullを返します。\n *\n * @return 次のエレメントフラグメントまたはnull\n */\n public getNext(): ElementFragment | null {\n const parent = this.getParent();\n if (parent === null) {\n return null;\n }\n const siblings = parent.getChildElementFragments();\n const index = siblings.indexOf(this);\n if (index < 0 || index + 1 >= siblings.length) {\n return null;\n }\n return siblings[index + 1];\n }\n\n /**\n * 表示状態を返します。\n *\n * @returns 表示状態\n */\n public isVisible(): boolean {\n return this.visible;\n }\n\n /**\n * エレメントを非表示にします。\n *\n * @returns エレメントの非表示のPromise\n */\n public hide(): Promise<void> {\n this.visible = false;\n this.display = this.getTarget().style.display;\n this.getTarget().style.display = 'none';\n this.getTarget().setAttribute(`${Env.prefix}if-false`, '');\n return Promise.resolve();\n }\n\n /**\n * エレメントを表示します。\n *\n * @return エレメントの表示のPromise\n */\n public show(): Promise<void> {\n this.getTarget().style.display = this.display ?? '';\n this.getTarget().removeAttribute(`${Env.prefix}if-false`);\n this.visible = true;\n return Promise.resolve();\n }\n\n /**\n * 指定した属性名を持つ最も近い親要素を返します。\n * 見つからない場合はnullを返します。\n *\n * @param name 属性名\n * @returns 最も近い親要素またはnull\n */\n public closestByAttribute(name: string): ElementFragment | null {\n if (this.hasAttribute(name)) {\n return this;\n }\n const parent = this.getParent();\n if (parent === null) {\n return null;\n }\n return parent.closestByAttribute(name);\n }\n}\n\n/**\n * テキストフラグメント。\n * テキストノードを表現します。\n */\nexport class TextFragment extends Fragment {\n /** 未評価のテキスト文字列 */\n private text: string;\n\n /** コンテンツ */\n private contents: TextContents;\n\n /** 更新スキップフラグ(オブザーバーによる無限ループ対応) */\n private skipMutation = false;\n\n /**\n * テキストフラグメントのコンストラクタ。\n * 対象テキストノードの内容を初期化します。\n *\n * @param target 対象テキストノード\n */\n public constructor(target: Text) {\n super(target);\n this.text = target.textContent || '';\n this.contents = new TextContents(this.text);\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public clone(): TextFragment {\n const clone = new TextFragment(this.target.cloneNode(true) as Text);\n clone.mounted = false;\n clone.text = this.text;\n clone.contents = this.contents;\n return clone;\n }\n\n /**\n * フラグメントの対象ノードを取得します。\n *\n * @returns フラグメントの対象ノード\n */\n public getTarget(): Text {\n return this.target as Text;\n }\n\n /**\n * コンテンツを更新します。\n *\n * @param text テキスト\n * @returns 更新のPromise\n */\n public setContent(text: string): Promise<void> {\n if (this.skipMutation || this.text === text) {\n return Promise.resolve();\n }\n this.text = text;\n this.contents = new TextContents(text);\n return this.evaluate();\n }\n\n /**\n * フラグメントを評価します。\n *\n * @returns 評価結果のPromise\n */\n public evaluate(): Promise<void> {\n if (this.contents.isRawEvaluate && this.parent === null) {\n return Promise.reject(\n new Error('Parent fragment is required for raw evaluation'),\n );\n }\n return Queue.enqueue(() => {\n this.skipMutation = true;\n if (this.contents.isRawEvaluate) {\n this.parent!.getTarget().innerHTML = this.contents.evaluate(\n this.parent!.getBindingData(),\n )[0] as string;\n } else if (this.contents.isEvaluate) {\n this.target.textContent = TextContents.joinEvaluateResults(\n this.contents.evaluate(this.parent!.getBindingData()),\n );\n } else {\n this.target.textContent = this.text;\n }\n }).finally(() => {\n this.skipMutation = false;\n }) as Promise<void>;\n }\n}\n\n/**\n * コメントフラグメント。\n * コメントノードを表現します。\n */\nexport class CommentFragment extends Fragment {\n /** コメント文字列 */\n private text: string;\n\n /** 更新スキップフラグ(オブザーバーによる無限ループ対応) */\n private skipMutation = false;\n\n /**\n * コメントフラグメントのコンストラクタ。\n * 対象コメントノードの内容を初期化します。\n *\n * @param target 対象コメントノード\n */\n public constructor(target: Comment) {\n super(target);\n this.text = target.textContent || '';\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public clone(): Fragment {\n const clone = new CommentFragment(this.target.cloneNode(true) as Comment);\n clone.mounted = false;\n clone.text = this.text;\n return clone;\n }\n\n /**\n * フラグメントの対象ノードを取得します。\n *\n * @returns フラグメントの対象ノード\n */\n public getTarget(): Comment {\n return this.target as Comment;\n }\n\n /**\n * コンテンツを更新します。\n *\n * @param text テキスト\n * @return 更新のPromise\n */\n public setContent(text: string): Promise<void> {\n if (this.skipMutation || this.text === text) {\n return Promise.resolve();\n }\n this.text = text;\n return Queue.enqueue(() => {\n this.skipMutation = true;\n this.target.textContent = this.text;\n }).finally(() => {\n this.skipMutation = false;\n }) as Promise<void>;\n }\n}\n\n/**\n * 値の種別。\n */\nenum ExpressionType {\n /** テキスト */\n TEXT,\n\n /** 評価式 */\n EXPRESSION,\n\n /** 生の評価式 */\n RAW_EXPRESSION,\n}\n\n/**\n * コンテンツのインターフェース。\n */\ninterface Content {\n /** コンテンツの内容 */\n text: string;\n\n /** 値の種別 */\n type: ExpressionType;\n}\n\n/**\n * テキストコンテンツを管理するクラスです。\n * 一度生成されると内部は変更しません。\n */\nclass TextContents {\n /** プレースホルダ検出用の正規表現 */\n protected static readonly PLACEHOLDER_REGEX =\n /\\{\\{\\{([\\s\\S]+?)\\}\\}\\}|\\{\\{([\\s\\S]+?)\\}\\}/g;\n\n /**\n * 評価結果を結合して文字列にします。\n *\n * @param contents 評価結果の配列\n * @returns 結合された文字列\n */\n public static joinEvaluateResults(contents: unknown[] | null): string {\n if (contents === null || contents.length === 0) {\n return '';\n }\n return contents\n .map(c => {\n if (c === null || c === undefined || c === false || Number.isNaN(c)) {\n return '';\n } else if (typeof c !== 'string') {\n return String(c);\n } else {\n return c;\n }\n })\n .join('');\n }\n\n /** コンテンツのリスト */\n protected readonly contents: Content[] = [];\n\n /** 評価式が含まれるかどうか */\n public readonly isEvaluate: boolean = false;\n\n /** 生の評価式が含まれるかどうか */\n public readonly isRawEvaluate: boolean = false;\n\n /** 評価前の値 */\n private readonly value: string;\n\n /**\n * コンストラクタ。\n *\n * @param text テキスト\n */\n constructor(text: string) {\n this.value = text;\n\n const matches = [...text.matchAll(TextContents.PLACEHOLDER_REGEX)];\n let lastIndex = 0;\n\n let hasEvaluate = false;\n let hasRawEvaluate = false;\n for (const match of matches) {\n // プレースホルダ前の通常テキスト\n if (match.index > lastIndex) {\n this.contents.push({\n text: text.slice(lastIndex, match.index),\n type: ExpressionType.TEXT,\n });\n }\n // プレースホルダ本体\n const content = {\n text: match[1] ?? match[2],\n type: match[1]\n ? ExpressionType.RAW_EXPRESSION\n : ExpressionType.EXPRESSION,\n };\n hasEvaluate = true;\n hasRawEvaluate =\n hasRawEvaluate || content.type === ExpressionType.RAW_EXPRESSION;\n this.contents.push(content);\n lastIndex = match.index! + match[0].length;\n }\n // 最後のプレースホルダ以降の通常テキスト\n if (lastIndex < text.length) {\n this.contents.push({\n text: text.slice(lastIndex),\n type: ExpressionType.TEXT,\n });\n }\n this.isEvaluate = hasEvaluate;\n this.isRawEvaluate = hasRawEvaluate;\n this.checkRawExpressions();\n }\n\n /**\n * 評価前の値を取得します。\n *\n * @returns 評価前の値\n */\n public getValue(): string {\n return this.value;\n }\n\n /**\n * RAW_EXPRESSION のチェックを行います。\n */\n protected checkRawExpressions(): void {\n for (let i = 0; i < this.contents.length; i++) {\n const content = this.contents[i];\n if (\n content.type === ExpressionType.RAW_EXPRESSION &&\n this.contents.length > 1\n ) {\n Log.error(\n '[Haori]',\n 'Raw expressions are not allowed in multi-content expressions.',\n );\n this.contents[i].type = ExpressionType.EXPRESSION;\n }\n }\n }\n\n /**\n * 式評価を行い、結果を返します。\n *\n * @param bindingValues バインディングされた値のオブジェクト\n * @returns 評価結果のリスト\n */\n public evaluate(bindingValues: Record<string, unknown>): unknown[] {\n if (!this.isEvaluate && !this.isRawEvaluate) {\n return this.contents.map(c => c.text);\n }\n const results: unknown[] = [];\n this.contents.forEach(c => {\n try {\n if (\n c.type === ExpressionType.EXPRESSION ||\n c.type === ExpressionType.RAW_EXPRESSION\n ) {\n const result = Expression.evaluate(c.text, bindingValues);\n results.push(result);\n } else {\n results.push(c.text);\n }\n } catch (error) {\n Log.error(\n '[Haori]',\n `Error evaluating text expression: ${c.text}`,\n error,\n );\n results.push('');\n }\n });\n return results;\n }\n}\n\n/**\n * 属性のコンテンツを管理するクラスです。\n * 一度生成されると内部は変更しません。\n */\nclass AttributeContents extends TextContents {\n /** 強制評価する属性名 */\n private static readonly FORCE_EVALUATION_ATTRIBUTES = [\n 'data-if',\n 'hor-if',\n 'data-each',\n 'hor-each',\n ];\n\n /** 強制評価フラグ(プレースホルダでなくても評価する) */\n private readonly forceEvaluation: boolean;\n\n /**\n * コンストラクタ。\n *\n * @param name 属性名\n * @param text 属性値\n */\n constructor(name: string, value: string) {\n super(value);\n this.forceEvaluation =\n AttributeContents.FORCE_EVALUATION_ATTRIBUTES.includes(name);\n }\n\n /**\n * 強制評価フラグを取得します。\n *\n * @returns 強制評価フラグ\n */\n public isForceEvaluation(): boolean {\n return this.forceEvaluation;\n }\n\n /**\n * 式評価を行い、結果を返します。\n *\n * @param bindingValues バインディングされた値のオブジェクト\n * @returns 評価結果のリスト\n */\n public evaluate(bindingValues: Record<string, unknown>): unknown[] {\n if (!this.isEvaluate && !this.forceEvaluation) {\n return this.contents.map(c => c.text);\n }\n const results: unknown[] = [];\n this.contents.forEach(c => {\n try {\n if (\n (this.forceEvaluation && c.type === ExpressionType.TEXT) ||\n c.type === ExpressionType.EXPRESSION ||\n c.type === ExpressionType.RAW_EXPRESSION\n ) {\n const result = Expression.evaluate(c.text, bindingValues);\n results.push(result);\n } else {\n results.push(c.text);\n }\n } catch (error) {\n Log.error(\n '[Haori]',\n `Error evaluating attribute expression: ${c.text}`,\n error,\n );\n results.push('');\n }\n });\n if (this.forceEvaluation && results.length > 1) {\n Log.error(\n '[Haori]',\n 'each or if expressions must have a single content.',\n results,\n );\n return [results[0]];\n }\n return results;\n }\n}\n","/**\n * @fileoverview Haoriイベント発火ユーティリティ\n *\n * Haoriライブラリが発火するカスタムイベントの統一的な発火機能を提供します。\n */\n\nimport type {HaoriRuntime} from './env';\n\n/**\n * Haoriイベントを発火するユーティリティクラス\n */\nexport interface FetchStartMetadata {\n /** 実行モード。 */\n runtime?: HaoriRuntime;\n /** 属性で指定された元の HTTP メソッド。 */\n requestedMethod?: string;\n /** 実際の通信に使う HTTP メソッド。 */\n effectiveMethod?: string;\n /** 通信方式。 */\n transportMode?: string;\n /** クエリ化後の検索文字列。 */\n queryString?: string;\n}\n\nexport default class HaoriEvent {\n /**\n * カスタムイベントを発火します。\n *\n * @param target イベントを発火する対象要素\n * @param eventName イベント名(haori:プレフィックスは自動追加)\n * @param detail イベントの詳細データ\n * @param options イベントオプション\n */\n public static dispatch(\n target: EventTarget,\n eventName: string,\n detail?: unknown,\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n },\n ): boolean {\n const event = new CustomEvent(`haori:${eventName}`, {\n bubbles: options?.bubbles ?? true,\n cancelable: options?.cancelable ?? false,\n composed: options?.composed ?? true,\n detail,\n });\n\n return target.dispatchEvent(event);\n }\n\n /**\n * readyイベントを発火します。\n *\n * @param version ライブラリバージョン\n */\n public static ready(version?: string): void {\n HaoriEvent.dispatch(document, 'ready', {version});\n }\n\n /**\n * renderイベントを発火します。\n *\n * @param target 評価対象要素\n */\n public static render(target: HTMLElement): void {\n HaoriEvent.dispatch(target, 'render', {target});\n }\n\n /**\n * importstartイベントを発火します。\n *\n * @param target data-import要素\n * @param url インポート対象URL\n */\n public static importStart(target: HTMLElement, url: string): void {\n HaoriEvent.dispatch(target, 'importstart', {\n url,\n startedAt: performance.now(),\n });\n }\n\n /**\n * importendイベントを発火します。\n *\n * @param target data-import要素\n * @param url インポート対象URL\n * @param bytes 取得バイト数\n * @param startedAt 開始時刻\n */\n public static importEnd(\n target: HTMLElement,\n url: string,\n bytes: number,\n startedAt: number,\n ): void {\n HaoriEvent.dispatch(target, 'importend', {\n url,\n bytes,\n durationMs: performance.now() - startedAt,\n });\n }\n\n /**\n * importerrorイベントを発火します。\n *\n * @param target data-import要素\n * @param url インポート対象URL\n * @param error エラー内容\n */\n public static importError(\n target: HTMLElement,\n url: string,\n error: unknown,\n ): void {\n HaoriEvent.dispatch(target, 'importerror', {url, error});\n }\n\n /**\n * bindchangeイベントを発火します。\n *\n * @param target バインド対象要素\n * @param previous 変更前のデータ\n * @param next 変更後のデータ\n * @param reason 変更理由\n */\n public static bindChange(\n target: HTMLElement,\n previous: Record<string, unknown> | null,\n next: Record<string, unknown>,\n reason: 'form' | 'fetch' | 'manual' | 'import' | 'other' = 'other',\n ): void {\n const changedKeys: string[] = [];\n\n // 変更されたキーを検出\n const prevKeys = new Set(Object.keys(previous || {}));\n const nextKeys = new Set(Object.keys(next));\n const allKeys = new Set([...prevKeys, ...nextKeys]);\n\n for (const key of allKeys) {\n const prevValue = previous?.[key];\n const nextValue = next[key];\n if (prevValue !== nextValue) {\n changedKeys.push(key);\n }\n }\n\n HaoriEvent.dispatch(target, 'bindchange', {\n previous: previous || {},\n next,\n changedKeys,\n reason,\n });\n }\n\n /**\n * eachupdateイベントを発火します。\n *\n * @param target data-each要素\n * @param added 追加された行のキー\n * @param removed 削除された行のキー\n * @param order 現在の順序\n */\n public static eachUpdate(\n target: HTMLElement,\n added: string[],\n removed: string[],\n order: string[],\n ): void {\n HaoriEvent.dispatch(target, 'eachupdate', {\n added,\n removed,\n order,\n total: order.length,\n });\n }\n\n /**\n * rowaddイベントを発火します。\n *\n * @param target 行要素\n * @param key 行キー\n * @param index インデックス\n * @param item 行データ\n */\n public static rowAdd(\n target: HTMLElement,\n key: string,\n index: number,\n item: unknown,\n ): void {\n HaoriEvent.dispatch(target, 'rowadd', {key, index, item});\n }\n\n /**\n * rowremoveイベントを発火します。\n *\n * @param target 行要素\n * @param key 行キー\n * @param index インデックス\n */\n public static rowRemove(\n target: HTMLElement,\n key: string,\n index: number,\n ): void {\n HaoriEvent.dispatch(target, 'rowremove', {key, index});\n }\n\n /**\n * rowmoveイベントを発火します。\n *\n * @param target 行要素\n * @param key 行キー\n * @param from 移動前インデックス\n * @param to 移動後インデックス\n */\n public static rowMove(\n target: HTMLElement,\n key: string,\n from: number,\n to: number,\n ): void {\n HaoriEvent.dispatch(target, 'rowmove', {key, from, to});\n }\n\n /**\n * showイベントを発火します。\n *\n * @param target data-if要素\n */\n public static show(target: HTMLElement): void {\n HaoriEvent.dispatch(target, 'show', {visible: true});\n }\n\n /**\n * hideイベントを発火します。\n *\n * @param target data-if要素\n */\n public static hide(target: HTMLElement): void {\n HaoriEvent.dispatch(target, 'hide', {visible: false});\n }\n\n /**\n * fetchstartイベントを発火します。\n *\n * @param target 起点要素\n * @param url フェッチURL\n * @param options フェッチオプション\n * @param payload 送信データ\n * @param metadata runtime とメソッド変換情報。\n * @return 戻り値はありません。\n */\n public static fetchStart(\n target: HTMLElement,\n url: string,\n options?: RequestInit,\n payload?: Record<string, unknown>,\n metadata?: FetchStartMetadata,\n ): void {\n HaoriEvent.dispatch(target, 'fetchstart', {\n url,\n options: options || {},\n payload,\n startedAt: performance.now(),\n ...metadata,\n });\n }\n\n /**\n * fetchendイベントを発火します。\n *\n * @param target 起点要素\n * @param url フェッチURL\n * @param status HTTPステータス\n * @param startedAt 開始時刻\n */\n public static fetchEnd(\n target: HTMLElement,\n url: string,\n status: number,\n startedAt: number,\n ): void {\n HaoriEvent.dispatch(target, 'fetchend', {\n url,\n status,\n durationMs: performance.now() - startedAt,\n });\n }\n\n /**\n * fetcherrorイベントを発火します。\n *\n * @param target 起点要素\n * @param url フェッチURL\n * @param error エラー内容\n * @param status HTTPステータス(存在する場合)\n * @param startedAt 開始時刻(存在する場合)\n */\n public static fetchError(\n target: HTMLElement,\n url: string,\n error: unknown,\n status?: number,\n startedAt?: number,\n ): void {\n HaoriEvent.dispatch(target, 'fetcherror', {\n url,\n status,\n error,\n durationMs: startedAt ? performance.now() - startedAt : undefined,\n });\n }\n}\n","/**\n * @fileoverview 手続き的処理管理機能\n *\n * イベントに基づく手続き的な処理を提供します。\n */\n\nimport Core from './core';\nimport Env from './env';\nimport Expression from './expression';\nimport Form from './form';\nimport Fragment, {ElementFragment} from './fragment';\nimport Haori from './haori';\nimport Log from './log';\nimport HaoriEvent from './event';\n\ntype ProcedureHaoriApi = Pick<\n typeof Haori,\n | 'addErrorMessage'\n | 'closeDialog'\n | 'confirm'\n | 'dialog'\n | 'openDialog'\n | 'toast'\n>;\n\nconst PROCEDURE_HAORI_METHOD_NAMES = [\n 'addErrorMessage',\n 'closeDialog',\n 'confirm',\n 'dialog',\n 'openDialog',\n 'toast',\n] as const;\n\nconst PROCEDURE_HISTORY_STATE_KEY = '__haoriHistoryState__';\n\n/**\n * Procedure から利用する Haori API を解決します。\n * window.Haori が差し替えられている場合はそちらを優先します。\n *\n * @returns Procedure が使用する Haori API。\n */\nfunction resolveProcedureHaoriApi(): ProcedureHaoriApi {\n const scope = globalThis as typeof globalThis & {\n window?: Window & {Haori?: unknown};\n };\n const candidate = scope.window?.Haori;\n const hasRequiredMethods = PROCEDURE_HAORI_METHOD_NAMES.every(\n methodName =>\n typeof (candidate as Record<string, unknown> | undefined)?.[\n methodName\n ] === 'function',\n );\n return hasRequiredMethods ? (candidate as ProcedureHaoriApi) : Haori;\n}\n\nconst QUERY_TRANSPORT_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);\n\n/**\n * URL クエリ化の対象メソッドかどうかを判定します。\n *\n * @param method 判定対象の HTTP メソッド。\n * @return クエリ送信対象なら true。\n */\nfunction isQueryTransportMethod(method: string): boolean {\n return QUERY_TRANSPORT_METHODS.has(method.toUpperCase());\n}\n\n/**\n * 送信データを URLSearchParams に追加します。\n *\n * @param params 追加先の URLSearchParams。\n * @param payload 追加対象の送信データ。\n * @return 戻り値はありません。\n */\nfunction appendPayloadToSearchParams(\n params: URLSearchParams,\n payload: Record<string, unknown>,\n): void {\n for (const [key, value] of Object.entries(payload)) {\n if (value === undefined) {\n continue;\n }\n if (value === null) {\n params.append(key, '');\n } else if (Array.isArray(value)) {\n value.forEach(item => {\n params.append(key, String(item));\n });\n } else if (typeof value === 'object' || typeof value === 'function') {\n params.append(key, JSON.stringify(value));\n } else {\n params.append(key, String(value));\n }\n }\n}\n\n/**\n * 送信データをクエリ文字列へ付加した URL を返します。\n *\n * @param fetchUrl 元のフェッチ URL。\n * @param payload 追加対象の送信データ。\n * @return クエリ文字列を付加した URL。\n */\nfunction appendPayloadToUrl(\n fetchUrl: string,\n payload: Record<string, unknown>,\n): string {\n const url = new URL(fetchUrl, window.location.href);\n const params = new URLSearchParams(url.search);\n appendPayloadToSearchParams(params, payload);\n url.search = params.toString();\n return url.toString();\n}\n\n/**\n * フェッチ前実行スクリプト戻り値型。\n */\nexport interface BeforeCallbackResult {\n /** 処理を停止する場合は true */\n stop?: boolean;\n\n /** 上書きするフェッチURL */\n fetchUrl?: string | null;\n\n /** 上書きするフェッチオプション */\n fetchOptions?: RequestInit | null;\n}\n\n/**\n * フェッチ後実行スクリプト戻り値型。\n */\nexport interface AfterCallbackResult {\n /** 処理を停止する場合は true */\n stop?: boolean;\n\n /** レスポンスとして使用するデータ */\n response?: Response;\n}\n\n/**\n * Procedureクラスのオプションインターフェース。\n */\nexport interface ProcedureOptions {\n /** 処理対象のフラグメント */\n targetFragment?: ElementFragment;\n\n /** バリデーションを行うかどうか */\n valid?: boolean;\n\n /** 確認メッセージ */\n confirmMessage?: string | null;\n\n /** 送信もしくは受信データ */\n data?: Record<string, unknown> | null;\n\n /** フェッチ前実行スクリプト */\n beforeCallback?: (\n fetchUrl: string | null,\n fetchOptions: RequestInit | null,\n ) => BeforeCallbackResult | boolean | void;\n\n /** 対象フォームフラグメント */\n formFragment?: ElementFragment | null;\n\n /** フェッチURL */\n fetchUrl?: string | null;\n\n /** フェッチオプション */\n fetchOptions?: RequestInit | null;\n\n /** バインド対象フラグメント */\n bindFragments?: ElementFragment[] | null;\n\n /** レスポンスデータから抽出するパラメータ名のリスト */\n bindParams?: string[] | null;\n\n /** レスポンスデータのうち既存配列へ追記するパラメータ名のリスト */\n bindAppendParams?: string[] | null;\n\n /** レスポンスデータをバインドする際のキー名 */\n bindArg?: string | null;\n\n /** フェッチ後実行スクリプト */\n afterCallback?: (\n response: Response | Record<string, unknown>,\n ) => AfterCallbackResult | boolean | void;\n\n /** 値を変更するフラグメント */\n adjustFragments?: ElementFragment[] | null;\n\n /** 変更する値の増減値 */\n adjustValue?: number | null;\n\n /** 行追加の有無 */\n rowAdd?: boolean | null;\n\n /** 行削除の有無 */\n rowRemove?: boolean | null;\n\n /** 前の行へ移動するかどうか */\n rowMovePrev?: boolean | null;\n\n /** 次の行へ移動するかどうか */\n rowMoveNext?: boolean | null;\n\n /** リセットするフラグメント */\n resetFragments?: ElementFragment[] | null;\n\n /** 再フェッチするフラグメント */\n refetchFragments?: ElementFragment[] | null;\n\n /** クリックするフラグメント */\n clickFragments?: ElementFragment[] | null;\n\n /** ダイアログを開くフラグメント */\n openFragments?: ElementFragment[] | null;\n\n /** ダイアログを閉じるフラグメント */\n closeFragments?: ElementFragment[] | null;\n\n /** コピー先フラグメント */\n copyFragments?: ElementFragment[] | null;\n\n /** コピー対象パラメータ名のリスト */\n copyParams?: string[] | null;\n\n /** ダイアログメッセージ */\n dialogMessage?: string | null;\n\n /** トーストメッセージ */\n toastMessage?: string | null;\n\n /** トーストレベル */\n toastLevel?: 'info' | 'warning' | 'error' | 'success' | null;\n\n /** history.pushState で追加する URL */\n historyUrl?: string | null;\n\n /** history.pushState の URL に追記するクエリパラメータ */\n historyData?: Record<string, unknown> | null;\n\n /** history.pushState の URL に追記するフォームフラグメント */\n historyFormFragment?: ElementFragment | null;\n\n /** リダイレクトURL */\n redirectUrl?: string | null;\n\n /** エラー時に最初のエラー要素へスクロールするかどうか */\n scrollOnError?: boolean | null;\n\n /** 成功時にスクロールする要素のCSSセレクター */\n scrollTarget?: string | null;\n}\n\n/**\n * 手続き的処理管理クラスです。\n */\nexport default class Procedure {\n /** data 属性内のテンプレート式検出用正規表現 */\n private static readonly DATA_PLACEHOLDER_REGEX =\n /\\{\\{\\{([\\s\\S]+?)\\}\\}\\}|\\{\\{([\\s\\S]+?)\\}\\}/g;\n\n /** 属性全体が単一テンプレート式かを判定する正規表現 */\n private static readonly SINGLE_PLACEHOLDER_REGEX =\n /^(\\{\\{\\{[\\s\\S]+?\\}\\}\\}|\\{\\{[\\s\\S]+?\\}\\})$/;\n\n /**\n * イベント属性名を正しく生成します。\n * 例: (\"click\", \"fetch\") => \"data-click-fetch\"\n * (null, \"fetch\") => \"data-fetch\"\n * (\"change\", \"bind-arg\") => \"data-change-bind-arg\"\n * 非イベント変種が \"data-fetch-xxx\" として存在するものについては、event が null の場合にそちらを返します。\n */\n private static attrName(\n event: string | null,\n key: string,\n hasFetchFallback: boolean = false,\n ): string {\n if (event) {\n return `${Env.prefix}${event}-${key}`;\n }\n return hasFetchFallback\n ? `${Env.prefix}fetch-${key}`\n : `${Env.prefix}${key}`;\n }\n\n /**\n * data 属性のテンプレート式評価結果を URLSearchParams 向けに組み立てます。\n *\n * @param rawAttribute 生の属性値\n * @param bindingValues バインディング値\n * @returns パラメータ形式として扱える文字列\n */\n private static resolveDataParamString(\n rawAttribute: string,\n bindingValues: Record<string, unknown>,\n ): string {\n return rawAttribute.replace(\n Procedure.DATA_PLACEHOLDER_REGEX,\n (\n _matched: string,\n rawExpression: string | undefined,\n expression: string | undefined,\n ): string => {\n const result = Expression.evaluate(\n rawExpression ?? expression ?? '',\n bindingValues,\n );\n if (result === null || result === undefined || Number.isNaN(result)) {\n return '';\n }\n if (typeof result === 'object') {\n return encodeURIComponent(JSON.stringify(result));\n }\n return encodeURIComponent(String(result));\n },\n );\n }\n\n /**\n * JSON 文字列中のテンプレート式かどうかを判定します。\n *\n * @param source 生の属性値\n * @param offset プレースホルダ開始位置\n * @returns JSON 文字列中なら true\n */\n private static isJsonStringContext(source: string, offset: number): boolean {\n let inString = false;\n let escaped = false;\n for (let index = 0; index < offset; index += 1) {\n const char = source[index];\n if (escaped) {\n escaped = false;\n continue;\n }\n if (char === '\\\\') {\n escaped = true;\n continue;\n }\n if (char === '\"') {\n inString = !inString;\n }\n }\n return inString;\n }\n\n /**\n * JSON 値コンテキスト向けにテンプレート式の評価結果を直列化します。\n *\n * @param result テンプレート式の評価結果\n * @returns JSON 値として埋め込める文字列\n */\n private static stringifyJsonTemplateValue(result: unknown): string {\n if (result === undefined || Number.isNaN(result)) {\n return 'null';\n }\n try {\n const serialized = JSON.stringify(result);\n return serialized ?? JSON.stringify(String(result));\n } catch {\n return JSON.stringify(String(result));\n }\n }\n\n /**\n * JSON 文字列コンテキスト向けにテンプレート式の評価結果を直列化します。\n *\n * @param result テンプレート式の評価結果\n * @returns JSON 文字列へ安全に埋め込める文字列\n */\n private static stringifyJsonTemplateStringContent(result: unknown): string {\n if (result === null || result === undefined || Number.isNaN(result)) {\n return '';\n }\n const value =\n typeof result === 'object'\n ? Procedure.stringifyJsonTemplateValue(result)\n : String(result);\n return JSON.stringify(value).slice(1, -1);\n }\n\n /**\n * JSON 形式 data 属性内のテンプレート式を安全に解決します。\n *\n * @param rawAttribute 生の属性値\n * @param bindingValues バインディング値\n * @returns JSON として解釈可能な文字列\n */\n private static resolveDataJsonString(\n rawAttribute: string,\n bindingValues: Record<string, unknown>,\n ): string {\n return rawAttribute.replace(\n Procedure.DATA_PLACEHOLDER_REGEX,\n (\n _matched: string,\n rawExpression: string | undefined,\n expression: string | undefined,\n offset: number,\n ): string => {\n const result = Expression.evaluate(\n rawExpression ?? expression ?? '',\n bindingValues,\n );\n return Procedure.isJsonStringContext(rawAttribute, offset)\n ? Procedure.stringifyJsonTemplateStringContent(result)\n : Procedure.stringifyJsonTemplateValue(result);\n },\n );\n }\n\n /**\n * data 属性を評価済みの値として取得します。\n *\n * @param fragment フラグメント\n * @param attrName 属性名\n * @returns 送信データ\n */\n private static resolveDataAttribute(\n fragment: ElementFragment,\n attrName: string,\n ): Record<string, unknown> | null {\n const rawAttribute = fragment.getRawAttribute(attrName);\n const dataAttribute = fragment.getAttribute(attrName);\n if (\n dataAttribute &&\n typeof dataAttribute === 'object' &&\n !Array.isArray(dataAttribute)\n ) {\n return dataAttribute as Record<string, unknown>;\n }\n if (typeof dataAttribute !== 'string' || rawAttribute === null) {\n return null;\n }\n const trimmed = rawAttribute.trim();\n if (Procedure.SINGLE_PLACEHOLDER_REGEX.test(trimmed)) {\n return Core.parseDataBind(dataAttribute);\n }\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n return Core.parseDataBind(\n Procedure.resolveDataJsonString(\n rawAttribute,\n fragment.getBindingData(),\n ),\n );\n }\n return Core.parseDataBind(\n Procedure.resolveDataParamString(rawAttribute, fragment.getBindingData()),\n );\n }\n\n /**\n * オプションをフラグメントの属性から構築します。\n *\n * @param fragment フラグメント\n * @param event イベント名\n * @return 構築されたオプション\n */\n private static buildOptions(\n fragment: ElementFragment,\n event: string | null,\n ): ProcedureOptions {\n const options: ProcedureOptions = {\n targetFragment: fragment,\n };\n if (event) {\n // validate(spec: data-???-validate)\n if (fragment.hasAttribute(Procedure.attrName(event, 'validate'))) {\n options.valid = true;\n }\n // confirm\n if (fragment.hasAttribute(Procedure.attrName(event, 'confirm'))) {\n options.confirmMessage = (fragment.getAttribute(\n Procedure.attrName(event, 'confirm'),\n ) as string).replace(/\\\\n/g, '\\n');\n }\n // data(イベント)\n if (fragment.hasAttribute(Procedure.attrName(event, 'data'))) {\n options.data = Procedure.resolveDataAttribute(\n fragment,\n Procedure.attrName(event, 'data'),\n );\n }\n // form(イベント)\n if (fragment.hasAttribute(Procedure.attrName(event, 'form'))) {\n const formSelector = fragment.getRawAttribute(\n Procedure.attrName(event, 'form'),\n ) as string | null;\n if (formSelector) {\n const formElement = document.body.querySelector(formSelector);\n if (formElement !== null) {\n options.formFragment = Form.getFormFragment(\n Fragment.get(formElement) as ElementFragment,\n );\n } else {\n Log.error(\n 'Haori',\n `Form element not found: ${formSelector}` +\n ` (${Procedure.attrName(event, 'form')})`,\n );\n }\n } else {\n // 属性はあるが値が省略された場合は自要素もしくは先祖の form を対象\n options.formFragment = Form.getFormFragment(fragment);\n }\n } else if (event === 'change') {\n // changeイベントの場合、data-change-form属性がなくても自動的にフォームを検索\n options.formFragment = Form.getFormFragment(fragment);\n }\n if (fragment.hasAttribute(`${Env.prefix}${event}-before-run`)) {\n const body = fragment.getRawAttribute(\n `${Env.prefix}${event}-before-run`,\n ) as string;\n try {\n options.beforeCallback = new Function(\n 'fetchUrl',\n 'fetchOptions',\n `\n\"use strict\";\n${body}\n`,\n ) as (\n fetchUrl: string | null,\n fetchOptions: RequestInit | null,\n ) => BeforeCallbackResult | boolean | void;\n } catch (e) {\n Log.error('Haori', `Invalid before script: ${e}`);\n }\n }\n }\n // fetch URL(イベントあり/なし)\n const fetchAttrName = Procedure.attrName(event, 'fetch');\n const hasFetchAttr = fragment.hasAttribute(fetchAttrName);\n if (hasFetchAttr) {\n options.fetchUrl = fragment.getAttribute(fetchAttrName) as string;\n }\n const fetchOptions: RequestInit = {};\n // fetch-method(イベントあり/なし)\n // event: data-{event}-fetch-method, non-event: data-fetch-method\n if (event) {\n const fetchMethodAttrEvent = Procedure.attrName(event, 'fetch-method');\n if (fragment.hasAttribute(fetchMethodAttrEvent)) {\n fetchOptions.method = fragment.getAttribute(\n fetchMethodAttrEvent,\n ) as string;\n }\n } else {\n const fetchMethodAttrNonEvent = Procedure.attrName(null, 'method', true);\n if (fragment.hasAttribute(fetchMethodAttrNonEvent)) {\n fetchOptions.method = fragment.getAttribute(\n fetchMethodAttrNonEvent,\n ) as string;\n }\n }\n // fetch-headers(イベントあり/なし)\n // event: data-{event}-fetch-headers, non-event: data-fetch-headers\n if (event) {\n const fetchHeadersAttrEvent = Procedure.attrName(event, 'fetch-headers');\n if (fragment.hasAttribute(fetchHeadersAttrEvent)) {\n const headersString = fragment.getRawAttribute(\n fetchHeadersAttrEvent,\n ) as string;\n try {\n fetchOptions.headers = Core.parseDataBind(headersString) as Record<\n string,\n string\n >;\n } catch (e) {\n Log.error('Haori', `Invalid fetch headers: ${e}`);\n }\n }\n } else {\n const fetchHeadersAttrNonEvent = Procedure.attrName(\n null,\n 'headers',\n true,\n );\n if (fragment.hasAttribute(fetchHeadersAttrNonEvent)) {\n const headersString = fragment.getRawAttribute(\n fetchHeadersAttrNonEvent,\n ) as string;\n try {\n fetchOptions.headers = Core.parseDataBind(headersString) as Record<\n string,\n string\n >;\n } catch (e) {\n Log.error('Haori', `Invalid fetch headers: ${e}`);\n }\n }\n }\n // fetch-content-type(イベントあり/なし)\n // event: data-{event}-fetch-content-type\n // non-event: data-fetch-content-type\n if (event) {\n const fetchCTAttrEvent = Procedure.attrName(\n event,\n 'fetch-content-type',\n );\n if (fragment.hasAttribute(fetchCTAttrEvent)) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': fragment.getAttribute(fetchCTAttrEvent) as string,\n };\n } else if (\n fetchOptions.method &&\n fetchOptions.method !== 'GET' &&\n fetchOptions.method !== 'HEAD' &&\n fetchOptions.method !== 'OPTIONS'\n ) {\n // only set default Content-Type when one is not already provided\n let hasContentType = false;\n if (fetchOptions.headers && typeof fetchOptions.headers === 'object') {\n const headersObj = fetchOptions.headers as Record<string, unknown>;\n hasContentType = 'Content-Type' in headersObj;\n }\n if (!hasContentType) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/json',\n };\n }\n } else if (\n fetchOptions.method &&\n (fetchOptions.method === 'GET' ||\n fetchOptions.method === 'HEAD' ||\n fetchOptions.method === 'OPTIONS')\n ) {\n // 仕様: GET/HEAD/OPTIONS 既定は application/x-www-form-urlencoded\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n }\n } else {\n const fetchCTAttrNonEvent = Procedure.attrName(\n null,\n 'content-type',\n true,\n );\n if (fragment.hasAttribute(fetchCTAttrNonEvent)) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': fragment.getAttribute(fetchCTAttrNonEvent) as string,\n };\n } else if (\n fetchOptions.method &&\n fetchOptions.method !== 'GET' &&\n fetchOptions.method !== 'HEAD' &&\n fetchOptions.method !== 'OPTIONS'\n ) {\n // only set default Content-Type when one is not already provided\n let hasContentType = false;\n if (fetchOptions.headers && typeof fetchOptions.headers === 'object') {\n const headersObj = fetchOptions.headers as Record<string, unknown>;\n hasContentType = 'Content-Type' in headersObj;\n }\n if (!hasContentType) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/json',\n };\n }\n } else if (\n fetchOptions.method &&\n (fetchOptions.method === 'GET' ||\n fetchOptions.method === 'HEAD' ||\n fetchOptions.method === 'OPTIONS')\n ) {\n // 仕様: GET/HEAD/OPTIONS 既定は application/x-www-form-urlencoded\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n }\n }\n if (Object.keys(fetchOptions).length > 0) {\n options.fetchOptions = fetchOptions;\n }\n // bind(イベントあり/なし: 非イベントは data-fetch-bind)\n const bindAttr = event\n ? Procedure.attrName(event, 'bind')\n : Procedure.attrName(null, 'bind', true);\n if (fragment.hasAttribute(bindAttr)) {\n const bindSelector = fragment.getRawAttribute(bindAttr) as string | null;\n if (bindSelector) {\n const bindElements = document.body.querySelectorAll(bindSelector);\n if (bindElements.length > 0) {\n options.bindFragments = [];\n bindElements.forEach(element => {\n const fragment = Fragment.get(element);\n if (fragment) {\n options.bindFragments!.push(fragment as ElementFragment);\n }\n });\n } else {\n Log.error(\n 'Haori',\n `Bind element not found: ${bindSelector} (${bindAttr})`,\n );\n }\n }\n }\n const bindArgAttrEvent = Procedure.attrName(event, 'bind-arg');\n const bindArgAttrNonEventLegacy = Procedure.attrName(\n null,\n 'arg',\n true,\n ); // data-fetch-arg\n const bindArgAttrNonEventNew = Procedure.attrName(\n null,\n 'bind-arg',\n true,\n ); // data-fetch-bind-arg (less common)\n if (event) {\n if (fragment.hasAttribute(bindArgAttrEvent)) {\n options.bindArg = fragment.getRawAttribute(bindArgAttrEvent) as\n | string\n | null;\n }\n } else {\n // Prefer legacy `data-fetch-arg` for non-event usage.\n // Fallback to `data-fetch-bind-arg` if legacy is not present.\n if (fragment.hasAttribute(bindArgAttrNonEventLegacy)) {\n options.bindArg = fragment.getRawAttribute(\n bindArgAttrNonEventLegacy,\n ) as string | null;\n } else if (fragment.hasAttribute(bindArgAttrNonEventNew)) {\n options.bindArg = fragment.getRawAttribute(bindArgAttrNonEventNew) as\n | string\n | null;\n }\n }\n const bindParamsAttr = event\n ? Procedure.attrName(event, 'bind-params')\n : Procedure.attrName(null, 'bind-params', true);\n if (fragment.hasAttribute(bindParamsAttr)) {\n const paramsString = fragment.getRawAttribute(bindParamsAttr) as string;\n options.bindParams = paramsString.split('&').map(p => p.trim());\n }\n const bindAppendAttr = event\n ? Procedure.attrName(event, 'bind-append')\n : Procedure.attrName(null, 'bind-append', true);\n if (fragment.hasAttribute(bindAppendAttr)) {\n const paramsString = fragment.getRawAttribute(bindAppendAttr) as string;\n options.bindAppendParams = paramsString\n .split('&')\n .map(p => p.trim())\n .filter(Boolean);\n }\n const copyParamsAttr = event\n ? Procedure.attrName(event, 'copy-params')\n : null;\n if (copyParamsAttr && fragment.hasAttribute(copyParamsAttr)) {\n const paramsString = fragment.getRawAttribute(\n copyParamsAttr,\n ) as string;\n options.copyParams = paramsString\n .split('&')\n .map(param => param.trim())\n .filter(Boolean);\n }\n if (event) {\n if (fragment.hasAttribute(Procedure.attrName(event, 'adjust'))) {\n const adjustSelector = fragment.getRawAttribute(\n Procedure.attrName(event, 'adjust'),\n ) as string | null;\n if (adjustSelector) {\n const adjustElements = document.body.querySelectorAll(adjustSelector);\n if (adjustElements.length > 0) {\n options.adjustFragments = [];\n adjustElements.forEach(element => {\n const fragment = Fragment.get(element);\n if (fragment) {\n options.adjustFragments!.push(fragment as ElementFragment);\n }\n });\n } else {\n Log.error(\n 'Haori',\n `Adjust element not found: ${adjustSelector}` +\n ` (${Procedure.attrName(event, 'adjust')})`,\n );\n }\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'adjust-value'))) {\n const valueString = fragment.getRawAttribute(\n Procedure.attrName(event, 'adjust-value'),\n ) as string;\n const value = Number(valueString);\n if (!isNaN(value)) {\n options.adjustValue = value;\n }\n }\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-add'))) {\n options.rowAdd = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-remove'))) {\n options.rowRemove = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-prev'))) {\n options.rowMovePrev = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-next'))) {\n options.rowMoveNext = true;\n }\n if (fragment.hasAttribute(`${Env.prefix}${event}-after-run`)) {\n const body = fragment.getRawAttribute(\n `${Env.prefix}${event}-after-run`,\n ) as string;\n try {\n options.afterCallback = new Function(\n 'response',\n `\n\"use strict\";\n${body}\n`,\n ) as (\n response: Response | Record<string, unknown>,\n ) => AfterCallbackResult | boolean | void;\n } catch (e) {\n Log.error('Haori', `Invalid after script: ${e}`);\n }\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'dialog'))) {\n options.dialogMessage = (fragment.getAttribute(\n Procedure.attrName(event, 'dialog'),\n ) as string).replace(/\\\\n/g, '\\n');\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'toast'))) {\n options.toastMessage = fragment.getAttribute(\n Procedure.attrName(event, 'toast'),\n ) as string;\n const rawLevel = fragment.getRawAttribute(\n Procedure.attrName(event, 'toast-level'),\n );\n const validLevels = ['info', 'warning', 'error', 'success'] as const;\n type ToastLevel = (typeof validLevels)[number];\n const isValidLevel = validLevels.includes(rawLevel as ToastLevel);\n options.toastLevel = isValidLevel ? (rawLevel as ToastLevel) : null;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'redirect'))) {\n options.redirectUrl = fragment.getAttribute(\n Procedure.attrName(event, 'redirect'),\n ) as string;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'scroll-error'))) {\n options.scrollOnError = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'scroll'))) {\n options.scrollTarget = fragment.getAttribute(\n Procedure.attrName(event, 'scroll'),\n ) as string;\n }\n // history(data-{event}-history / history-data / history-form)\n if (fragment.hasAttribute(Procedure.attrName(event, 'history'))) {\n options.historyUrl = fragment.getAttribute(\n Procedure.attrName(event, 'history'),\n ) as string | null;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'history-data'))) {\n options.historyData = Procedure.resolveDataAttribute(\n fragment,\n Procedure.attrName(event, 'history-data'),\n );\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'history-form'))) {\n const historyFormSelector = fragment.getRawAttribute(\n Procedure.attrName(event, 'history-form'),\n ) as string | null;\n if (historyFormSelector) {\n const historyFormElement =\n document.body.querySelector(historyFormSelector);\n if (historyFormElement !== null) {\n options.historyFormFragment = Form.getFormFragment(\n Fragment.get(historyFormElement) as ElementFragment,\n );\n } else {\n Log.error(\n 'Haori',\n `Form element not found: ${historyFormSelector}` +\n ` (${Procedure.attrName(event, 'history-form')})`,\n );\n }\n } else {\n options.historyFormFragment = Form.getFormFragment(fragment);\n }\n }\n\n // reset/refetch/click/open/close(イベント、CSSセレクタ)\n const selectorAttrs = [\n 'reset',\n 'refetch',\n 'click',\n 'copy',\n 'open',\n 'close',\n ] as const;\n selectorAttrs.forEach(attrKey => {\n const attrName = Procedure.attrName(event, attrKey);\n if (!fragment.hasAttribute(attrName)) {\n return;\n }\n const selector = fragment.getRawAttribute(attrName) as string | null;\n const list: ElementFragment[] = [];\n if (selector) {\n const elements = document.body.querySelectorAll(selector);\n elements.forEach(el => {\n const frag = Fragment.get(el);\n if (frag) {\n list.push(frag as ElementFragment);\n }\n });\n if (list.length === 0) {\n Log.error('Haori', `Element not found: ${selector} (${attrName})`);\n }\n } else {\n // 値が省略されている場合は自要素を対象\n list.push(fragment);\n }\n if (list.length > 0) {\n switch (attrKey) {\n case 'reset':\n options.resetFragments = list;\n break;\n case 'refetch':\n options.refetchFragments = list;\n break;\n case 'click':\n options.clickFragments = list;\n break;\n case 'copy':\n options.copyFragments = list;\n break;\n case 'open':\n options.openFragments = list;\n break;\n case 'close':\n options.closeFragments = list;\n break;\n }\n }\n });\n }\n\n // 非イベントの data / form(data-fetch-data / data-fetch-form)も取り込む\n if (!event) {\n if (fragment.hasAttribute(Procedure.attrName(null, 'data', true))) {\n options.data = Procedure.resolveDataAttribute(\n fragment,\n Procedure.attrName(null, 'data', true),\n );\n }\n if (fragment.hasAttribute(Procedure.attrName(null, 'form', true))) {\n const formSelector = fragment.getRawAttribute(\n Procedure.attrName(null, 'form', true),\n ) as string | null;\n if (formSelector) {\n const formElement = document.body.querySelector(formSelector);\n if (formElement !== null) {\n options.formFragment = Form.getFormFragment(\n Fragment.get(formElement) as ElementFragment,\n );\n } else {\n Log.error(\n 'Haori',\n `Form element not found: ${formSelector} (` +\n `${Procedure.attrName(null, 'fetch-form', true)})`,\n );\n }\n } else {\n // 属性はあるが値が省略された場合は自要素もしくは先祖の form を対象\n options.formFragment = Form.getFormFragment(fragment);\n }\n }\n }\n\n // fetch が指定されているのにバインド先が無い場合、デフォルトで自要素にバインド\n if (\n hasFetchAttr &&\n (!options.bindFragments || options.bindFragments.length === 0)\n ) {\n options.bindFragments = [fragment];\n }\n return options;\n }\n\n /**\n * ElementFragment の構造的タイプガード。\n *\n * @param value チェックする値\n * @returns ElementFragment である場合は true、それ以外は false\n */\n private static isElementFragment(value: unknown): value is ElementFragment {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.getTarget === 'function' &&\n typeof obj.getChildElementFragments === 'function'\n );\n }\n\n /** オプション */\n private readonly options: ProcedureOptions;\n\n /**\n * オプションを指定してProcedureクラスのインスタンスを生成します。\n *\n * @param options オプション\n */\n constructor(options: ProcedureOptions);\n\n /**\n * フラグメントの属性からオプションを生成してProcedureクラスのインスタンスを生成します。\n *\n * @param fragment フラグメント\n * @param event イベント名\n */\n constructor(fragment: ElementFragment, event: string | null);\n\n /**\n * コンストラクタ。\n *\n * @param arg1 オプションもしくはフラグメント\n * @param arg2 イベント名\n */\n constructor(\n arg1: ProcedureOptions | ElementFragment,\n arg2: string | null = null,\n ) {\n if (Procedure.isElementFragment(arg1)) {\n this.options = Procedure.buildOptions(arg1, arg2);\n } else {\n this.options = arg1;\n }\n }\n\n /**\n * 一連の処理を実行します。オプションが空の場合は即座にresolveされます。\n *\n * @returns 実行結果のPromise\n */\n run(): Promise<void> {\n return this.runWithResult().then(() => undefined);\n }\n\n /**\n * 一連の処理を実行し、成功したかどうかを返します。\n *\n * @returns 成功した場合は true、途中停止や失敗時は false\n */\n runWithResult(): Promise<boolean> {\n return this.execute();\n }\n\n /**\n * 一連の処理を実行します。成功結果を内部で扱うための実体です。\n *\n * @returns 実行成功時は true、停止や失敗時は false\n */\n private async execute(): Promise<boolean> {\n if (Object.keys(this.options).length === 0) {\n return false;\n }\n if (\n this.options.formFragment &&\n this.validate(this.options.formFragment) === false\n ) {\n return false;\n }\n const confirmed = await this.confirm();\n if (!confirmed) {\n return false;\n }\n let fetchUrl = this.options.fetchUrl;\n let fetchOptions = this.options.fetchOptions;\n if (this.options.beforeCallback) {\n const result = this.options.beforeCallback(\n fetchUrl || null,\n fetchOptions || null,\n );\n if (result !== undefined && result !== null) {\n if (result === false || (typeof result === 'object' && result.stop)) {\n return false;\n }\n if (typeof result === 'object') {\n fetchUrl = ('fetchUrl' in result ? result.fetchUrl : fetchUrl) as\n | string\n | null;\n fetchOptions = (\n 'fetchOptions' in result ? result.fetchOptions : fetchOptions\n ) as RequestInit | null;\n }\n }\n }\n\n // フォーム値と data を統合してペイロードを作成\n const payload: Record<string, unknown> = {};\n if (this.options.formFragment) {\n const formValues = Form.getValues(this.options.formFragment);\n Object.assign(payload, formValues);\n }\n if (this.options.data && typeof this.options.data === 'object') {\n Object.assign(payload, this.options.data);\n }\n\n const hasPayload = Object.keys(payload).length > 0;\n if (fetchUrl) {\n const finalOptions: RequestInit = {...(fetchOptions || {})};\n const headers = new Headers(\n (finalOptions.headers as HeadersInit | undefined) || undefined,\n );\n const requestedMethod = (finalOptions.method || 'GET').toUpperCase();\n const isDemoQueryNormalization =\n Env.runtime === 'demo' && !isQueryTransportMethod(requestedMethod);\n const method = isDemoQueryNormalization ? 'GET' : requestedMethod;\n\n finalOptions.method = method;\n\n if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS') {\n if (hasPayload) {\n fetchUrl = appendPayloadToUrl(fetchUrl!, payload);\n }\n } else if (hasPayload) {\n const contentType = headers.get('Content-Type') || '';\n if (/multipart\\/form-data/i.test(contentType)) {\n headers.delete('Content-Type');\n const formData = new FormData();\n for (const [k, v] of Object.entries(payload)) {\n if (v === undefined || v === null) {\n formData.append(k, '');\n } else if (v instanceof Blob) {\n formData.append(k, v);\n } else if (Array.isArray(v)) {\n v.forEach(item => formData.append(k, String(item)));\n } else if (typeof v === 'object') {\n formData.append(k, JSON.stringify(v));\n } else {\n formData.append(k, String(v));\n }\n }\n finalOptions.body = formData;\n } else if (/application\\/x-www-form-urlencoded/i.test(contentType)) {\n const params = new URLSearchParams();\n for (const [k, v] of Object.entries(payload)) {\n if (v === undefined) {\n continue;\n }\n if (v === null) {\n params.append(k, '');\n } else if (Array.isArray(v)) {\n v.forEach(item => params.append(k, String(item)));\n } else if (typeof v === 'object') {\n params.append(k, JSON.stringify(v));\n } else {\n params.append(k, String(v));\n }\n }\n finalOptions.body = params;\n } else {\n headers.set('Content-Type', 'application/json');\n finalOptions.body = JSON.stringify(payload);\n }\n }\n\n finalOptions.headers = headers;\n let queryString: string | undefined;\n\n if (isDemoQueryNormalization) {\n queryString = fetchUrl\n ? new URL(fetchUrl, window.location.href).search || undefined\n : undefined;\n headers.delete('Content-Type');\n Log.info('Haori demo fetch normalization', {\n runtime: Env.runtime,\n requestedMethod,\n effectiveMethod: method,\n transportMode: 'query-get',\n url: fetchUrl,\n payload: hasPayload ? payload : undefined,\n queryString,\n });\n }\n\n // fetchstartイベントを発火\n if (this.options.targetFragment && fetchUrl) {\n const startedAt = performance.now();\n const fetchStartMetadata = {\n runtime: Env.runtime,\n requestedMethod,\n effectiveMethod: method,\n transportMode: isDemoQueryNormalization ? 'query-get' : 'http',\n ...(isDemoQueryNormalization ? {queryString} : {}),\n };\n\n HaoriEvent.fetchStart(\n this.options.targetFragment.getTarget(),\n fetchUrl,\n finalOptions,\n hasPayload ? payload : undefined,\n fetchStartMetadata,\n );\n\n return fetch(fetchUrl, finalOptions)\n .then(response => {\n return this.handleFetchResult(\n response,\n fetchUrl || undefined,\n startedAt,\n );\n })\n .catch(error => {\n if (fetchUrl) {\n HaoriEvent.fetchError(\n this.options.targetFragment!.getTarget(),\n fetchUrl,\n error,\n );\n }\n throw error;\n });\n }\n return fetch(fetchUrl, finalOptions).then(response => {\n return this.handleFetchResult(response, fetchUrl || undefined);\n });\n }\n\n // fetchUrlが無い場合(changeイベント等)、bindFragmentsが無ければformFragmentにバインド\n if (\n (!this.options.bindFragments ||\n this.options.bindFragments.length === 0) &&\n this.options.formFragment &&\n hasPayload\n ) {\n // 双方向バインディング: フォーム値を自動的にバインディングデータに反映\n const formFragment = this.options.formFragment;\n const formElement = formFragment.getTarget();\n\n formElement.setAttribute(\n `${Env.prefix}bind`,\n JSON.stringify(payload),\n );\n\n const bindingData = formFragment.getBindingData();\n Object.assign(bindingData, payload);\n await Core.setBindingData(formElement, bindingData);\n }\n\n const merged = hasPayload ? payload : {};\n const response = new Response(JSON.stringify(merged), {\n headers: {'Content-Type': 'application/json'},\n });\n return this.handleFetchResult(response);\n }\n\n /**\n * フェッチ後の処理を実行します。\n */\n private async handleFetchResult(\n response: Response,\n url?: string,\n startedAt?: number,\n ): Promise<boolean> {\n const activeHaori = resolveProcedureHaoriApi();\n // エラー応答時は以後の処理を停止し、メッセージを伝播\n if (!response.ok) {\n if (this.options.targetFragment && url) {\n HaoriEvent.fetchError(\n this.options.targetFragment.getTarget(),\n url,\n new Error(`${response.status} ${response.statusText}`),\n response.status,\n startedAt,\n );\n }\n await this.handleFetchError(response);\n return false;\n }\n\n // fetchendイベントを発火\n if (this.options.targetFragment && url && startedAt) {\n HaoriEvent.fetchEnd(\n this.options.targetFragment.getTarget(),\n url,\n response.status,\n startedAt,\n );\n }\n\n if (this.options.afterCallback) {\n const result = this.options.afterCallback(response);\n if (result !== undefined && result !== null) {\n if (result === false || (typeof result === 'object' && result.stop)) {\n return false;\n }\n if (typeof result === 'object' && 'response' in result) {\n response = (\n 'response' in result ? result.response : response\n ) as Response;\n }\n }\n }\n const promises: Promise<unknown>[] = [];\n promises.push(this.bindResult(response));\n promises.push(this.adjust());\n promises.push(this.addRow());\n promises.push(this.removeRow());\n promises.push(this.movePrevRow());\n promises.push(this.moveNextRow());\n await Promise.all(promises);\n\n if (this.options.resetFragments && this.options.resetFragments.length > 0) {\n await Promise.all(\n this.options.resetFragments.map(fragment => Form.reset(fragment)),\n );\n }\n\n await this.copy();\n\n const deferredPromises: Promise<unknown>[] = [];\n if (\n this.options.refetchFragments &&\n this.options.refetchFragments.length > 0\n ) {\n this.options.refetchFragments.forEach(fragment => {\n deferredPromises.push(new Procedure(fragment, null).run());\n });\n }\n if (this.options.clickFragments && this.options.clickFragments.length > 0) {\n this.options.clickFragments.forEach(fragment => {\n const target = fragment.getTarget();\n if (typeof target.click === 'function') {\n target.click();\n } else {\n target.dispatchEvent(\n new MouseEvent('click', {bubbles: true, cancelable: true}),\n );\n }\n });\n }\n if (this.options.openFragments && this.options.openFragments.length > 0) {\n this.options.openFragments.forEach(fragment => {\n const target = fragment.getTarget();\n if (target instanceof HTMLElement) {\n deferredPromises.push(activeHaori.openDialog(target));\n } else {\n Log.error('Haori', 'Element is not an HTML element: ', target);\n }\n });\n }\n if (this.options.closeFragments && this.options.closeFragments.length > 0) {\n this.options.closeFragments.forEach(fragment => {\n const target = fragment.getTarget();\n if (target instanceof HTMLElement) {\n deferredPromises.push(activeHaori.closeDialog(target));\n } else {\n Log.error('Haori', 'Element is not an HTML element: ', target);\n }\n });\n }\n // 仕様順序: 先に各種操作(bind/adjust/row/reset/refetch/click/open/close)を完了\n await Promise.all(deferredPromises);\n // その後にダイアログ/トーストを表示\n if (this.options.dialogMessage) {\n await activeHaori.dialog(this.options.dialogMessage);\n }\n if (this.options.toastMessage) {\n await activeHaori.toast(\n this.options.toastMessage,\n this.options.toastLevel ?? 'info',\n );\n }\n this.pushHistory();\n if (this.options.scrollTarget) {\n const el = document.querySelector<HTMLElement>(this.options.scrollTarget);\n el?.scrollIntoView({behavior: 'smooth', block: 'nearest'});\n }\n if (this.options.redirectUrl) {\n window.location.href = this.options.redirectUrl;\n }\n return true;\n }\n\n /**\n * history.pushState を実行します。\n *\n * `historyUrl` / `historyData` / `historyFormFragment` の内容を基に URL を組み立て、\n * `history.pushState()` を呼び出します。いずれも未指定の場合は何もしません。\n * 不正 URL・オリジン違反・例外は `Log.error` でログ出力してスキップし、後続処理は継続します。\n */\n private pushHistory(): void {\n const hasHistoryUrl =\n this.options.historyUrl !== undefined && this.options.historyUrl !== null;\n const hasHistoryData =\n this.options.historyData !== undefined &&\n this.options.historyData !== null;\n const hasHistoryForm =\n this.options.historyFormFragment !== undefined &&\n this.options.historyFormFragment !== null;\n\n if (!hasHistoryUrl && !hasHistoryData && !hasHistoryForm) {\n return;\n }\n\n try {\n const baseUrlString = hasHistoryUrl\n ? (this.options.historyUrl as string)\n : window.location.pathname;\n const url = new URL(baseUrlString, window.location.href);\n\n if (url.origin !== window.location.origin) {\n const errorMessage =\n 'history.pushState: cross-origin URL is not allowed: ' +\n url.toString();\n Log.error(\n 'Haori',\n errorMessage,\n );\n return;\n }\n\n const appendParams = (values: Record<string, unknown>): void => {\n for (const [k, v] of Object.entries(values)) {\n if (v === undefined || v === null) {\n continue;\n }\n if (Array.isArray(v)) {\n v.forEach(item => url.searchParams.append(k, String(item)));\n } else if (typeof v === 'object') {\n url.searchParams.set(k, JSON.stringify(v));\n } else {\n url.searchParams.set(k, String(v));\n }\n }\n };\n\n if (hasHistoryData) {\n appendParams(this.options.historyData as Record<string, unknown>);\n }\n if (hasHistoryForm) {\n appendParams(\n Form.getValues(\n this.options.historyFormFragment as ElementFragment,\n ),\n );\n }\n\n history.pushState(\n {[PROCEDURE_HISTORY_STATE_KEY]: true},\n '',\n url.toString(),\n );\n } catch (e) {\n Log.error('Haori', `history.pushState failed: ${e}`);\n }\n }\n\n /**\n * フェッチエラー応答のメッセージを適切な要素へ伝播します。\n */\n private async handleFetchError(response: Response): Promise<boolean> {\n // ベースとなるフォーム/フラグメントを決定\n let baseFragment: ElementFragment | null = null;\n if (this.options.formFragment) {\n baseFragment = this.options.formFragment;\n } else if (this.options.targetFragment) {\n baseFragment =\n Form.getFormFragment(this.options.targetFragment) ||\n this.options.targetFragment;\n }\n\n const addGeneralMessage = async (message: string) => {\n const targetEl = baseFragment ? baseFragment.getTarget() : document.body;\n await resolveProcedureHaoriApi().addErrorMessage(targetEl, message);\n };\n\n const scrollToFirstError = () => {\n if (!this.options.scrollOnError) {\n return;\n }\n const root = baseFragment ? baseFragment.getTarget() : document.body;\n // addErrorMessage はフォーム以外の target に対して parentElement へエラーを付与するため、\n // root 自身・parentElement・root 配下の順で探索する\n const errorTarget =\n root.getAttribute('data-message-level') === 'error'\n ? root\n : root.parentElement?.getAttribute('data-message-level') === 'error'\n ? root.parentElement\n : root.querySelector<HTMLElement>('[data-message-level=\"error\"]');\n errorTarget?.scrollIntoView({behavior: 'smooth', block: 'nearest'});\n };\n\n // コンテンツタイプに応じて解析\n const contentType = response.headers.get('Content-Type') || '';\n if (contentType.includes('application/json')) {\n try {\n const data = await response.json();\n // 代表的な形式に対応\n const entries: Array<{key?: string; message: string}> = [];\n if (data && typeof data === 'object') {\n if (typeof data.message === 'string') {\n entries.push({message: data.message});\n }\n if (Array.isArray(data.messages)) {\n for (const m of data.messages) {\n if (typeof m === 'string') {\n entries.push({message: m});\n }\n }\n }\n if (data.errors && typeof data.errors === 'object') {\n for (const [k, v] of Object.entries(data.errors)) {\n if (Array.isArray(v)) {\n entries.push({key: k, message: v.join('\\n')});\n } else if (typeof v === 'string') {\n entries.push({key: k, message: v});\n } else if (v != null) {\n entries.push({key: k, message: String(v)});\n }\n }\n }\n // キー: 値(文字列/配列)形式にフォールバック\n if (entries.length === 0) {\n for (const [k, v] of Object.entries(data)) {\n if (k === 'message' || k === 'messages' || k === 'errors') {\n continue;\n }\n if (Array.isArray(v)) {\n entries.push({key: k, message: v.join('\\n')});\n } else if (typeof v === 'string') {\n entries.push({key: k, message: v});\n }\n }\n }\n }\n if (entries.length === 0) {\n // 汎用メッセージ\n await addGeneralMessage(`${response.status} ${response.statusText}`);\n scrollToFirstError();\n return false;\n }\n // メッセージを反映\n for (const e of entries) {\n if (e.key && baseFragment) {\n await Form.addErrorMessage(baseFragment, e.key, e.message);\n } else {\n await addGeneralMessage(e.message);\n }\n }\n scrollToFirstError();\n return false;\n } catch {\n // JSON 解析失敗時はテキストにフォールバック\n }\n }\n // テキストとして処理\n try {\n const text = await response.text();\n if (text && text.trim().length > 0) {\n await addGeneralMessage(text.trim());\n } else {\n await addGeneralMessage(`${response.status} ${response.statusText}`);\n }\n } catch {\n await addGeneralMessage(`${response.status} ${response.statusText}`);\n }\n scrollToFirstError();\n return false;\n }\n\n /**\n * 対象のフラグメント以下の入力要素に対してバリデーションを実行します。\n * バリデーションエラーがある場合は、最初のエラー要素にフォーカスを移動します。\n *\n * @param fragment 対象のフラグメント\n * @returns バリデーション結果(true: 成功, false: 失敗)\n */\n validate(fragment: ElementFragment): boolean {\n if (this.options.valid !== true) {\n return true;\n }\n const firstInvalid = this.findFirstInvalid(fragment);\n if (firstInvalid === null) {\n return true;\n }\n // 検出フェーズ(findFirstInvalid)は checkValidity で副作用なく走査済み。\n // reportValidity と focus は確定した 1 要素にだけ呼び出す。\n (\n firstInvalid as\n | HTMLInputElement\n | HTMLSelectElement\n | HTMLTextAreaElement\n ).reportValidity();\n firstInvalid.focus();\n if (this.options.scrollOnError) {\n firstInvalid.scrollIntoView({behavior: 'smooth', block: 'nearest'});\n }\n return false;\n }\n\n /**\n * 対象フラグメント以下で DOM 順の最上部にある invalid 要素を返します。\n * 副作用のない checkValidity のみを使用し、検出のみを行います。\n *\n * @param fragment 対象のフラグメント\n * @returns 最初の invalid 要素、なければ null\n */\n private findFirstInvalid(fragment: ElementFragment): HTMLElement | null {\n // 子要素を逆順に処理することで、DOM 順の先頭要素が最後に found を上書きし、\n // 最終的に最上部の invalid 要素が返る\n let found: HTMLElement | null = null;\n for (const child of fragment.getChildElementFragments().reverse()) {\n const result = this.findFirstInvalid(child);\n if (result !== null) {\n found = result;\n }\n }\n // 自身は子より DOM 上位にあるため、invalid なら子の結果を上書きする\n if (!this.checkOne(fragment)) {\n return fragment.getTarget();\n }\n return found;\n }\n\n /**\n * 対象のフラグメントに対して、副作用なく有効性を検査します。\n * reportValidity は使わず checkValidity のみ呼び出します。\n *\n * @param fragment 対象のフラグメント\n * @returns 有効なら true、無効なら false\n */\n private checkOne(fragment: ElementFragment): boolean {\n const target = fragment.getTarget();\n if (\n target instanceof HTMLInputElement ||\n target instanceof HTMLSelectElement ||\n target instanceof HTMLTextAreaElement\n ) {\n return target.checkValidity();\n }\n return true;\n }\n\n /**\n * 確認メッセージを表示し、ユーザーの確認を求めます。\n * メッセージが設定されていない場合は、即座に成功とみなします。\n *\n * @returns ユーザーの確認結果を含むPromise(true: 確認, false: キャンセル)\n */\n private confirm(): Promise<boolean> {\n const message = this.options.confirmMessage;\n if (message === null || message === undefined) {\n return Promise.resolve(true);\n }\n return resolveProcedureHaoriApi().confirm(message);\n }\n\n /**\n * 結果データを対象のフラグメントにバインドします。\n *\n * @param response フェッチのレスポンスオブジェクト\n */\n private bindResult(response: Response): Promise<void> {\n if (\n !this.options.bindFragments ||\n this.options.bindFragments.length === 0\n ) {\n return Promise.resolve();\n }\n const promise = response.headers\n .get('Content-Type')\n ?.includes('application/json')\n ? response.json()\n : response.text();\n return promise.then(data => {\n if (this.options.bindParams) {\n const newData = {} as Record<string, unknown>;\n this.options.bindParams.forEach(param => {\n if (data && typeof data === 'object' && param in data) {\n newData[param] = data[param];\n }\n });\n data = newData;\n }\n const promises: Promise<unknown>[] = [];\n if (this.options.bindArg) {\n this.options.bindFragments!.forEach(fragment => {\n const bindingData = fragment.getBindingData();\n const bindArg = this.options.bindArg as string;\n if (\n data &&\n typeof data === 'object' &&\n !Array.isArray(data)\n ) {\n const currentValue = bindingData[bindArg];\n const currentObject =\n currentValue &&\n typeof currentValue === 'object' &&\n !Array.isArray(currentValue)\n ? (currentValue as Record<string, unknown>)\n : {};\n bindingData[bindArg] = this.mergeAppendBindingData(\n fragment,\n data as Record<string, unknown>,\n currentObject,\n );\n } else {\n bindingData[bindArg] = data;\n }\n promises.push(Core.setBindingData(fragment.getTarget(), bindingData));\n });\n } else if (typeof data === 'string') {\n Log.error('Haori', 'string data cannot be bound without a bindArg.');\n return Promise.reject(\n new Error('string data cannot be bound without a bindArg.'),\n );\n } else {\n this.options.bindFragments!.forEach(fragment => {\n const resolvedData = this.mergeAppendBindingData(\n fragment,\n data as Record<string, unknown>,\n );\n promises.push(\n Core.setBindingData(\n fragment.getTarget(),\n resolvedData,\n ),\n );\n });\n }\n return Promise.all(promises).then(() => undefined);\n });\n }\n\n /**\n * bind-append 指定があるキーについて、既存配列と結合したデータを返します。\n */\n private mergeAppendBindingData(\n fragment: ElementFragment,\n data: Record<string, unknown>,\n currentData: Record<string, unknown> = fragment.getBindingData(),\n ): Record<string, unknown> {\n if (\n !this.options.bindAppendParams ||\n this.options.bindAppendParams.length === 0\n ) {\n return data;\n }\n\n const merged = {...data};\n const current = currentData;\n for (const key of this.options.bindAppendParams) {\n const incoming = merged[key];\n const existing = current[key];\n if (Array.isArray(existing) && Array.isArray(incoming)) {\n merged[key] = existing.concat(incoming);\n }\n }\n return merged;\n }\n\n /**\n * 指定されたフラグメントへバインディングデータをコピーします。\n */\n private copy(): Promise<void> {\n if (\n !this.options.copyFragments ||\n this.options.copyFragments.length === 0\n ) {\n return Promise.resolve();\n }\n\n const sourceData = this.resolveCopySourceData();\n const copyData = this.pickCopyData(sourceData);\n const promises = this.options.copyFragments.map(fragment => {\n const bindingData = {\n ...fragment.getBindingData(),\n ...copyData,\n };\n return Core.setBindingData(fragment.getTarget(), bindingData);\n });\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * copy のコピー元データを取得します。\n */\n private resolveCopySourceData(): Record<string, unknown> {\n if (this.options.formFragment) {\n return Form.getValues(this.options.formFragment);\n }\n if (this.options.targetFragment) {\n return {...this.options.targetFragment.getBindingData()};\n }\n return {};\n }\n\n /**\n * copy-params が指定されている場合は対象キーだけ抽出します。\n */\n private pickCopyData(\n sourceData: Record<string, unknown>,\n ): Record<string, unknown> {\n if (!this.options.copyParams || this.options.copyParams.length === 0) {\n return sourceData;\n }\n\n const filtered: Record<string, unknown> = {};\n this.options.copyParams.forEach(param => {\n if (param in sourceData) {\n filtered[param] = sourceData[param];\n }\n });\n return filtered;\n }\n\n /**\n * 値の増減を行います。\n */\n private adjust(): Promise<void> {\n if (\n !this.options.adjustFragments ||\n this.options.adjustFragments.length === 0\n ) {\n return Promise.resolve();\n }\n const adjustValue = this.options.adjustValue ?? 0;\n const promises: Promise<void>[] = [];\n for (const fragment of this.options.adjustFragments) {\n let valueString = fragment.getValue();\n if (\n valueString === null ||\n valueString === undefined ||\n valueString === ''\n ) {\n valueString = '0';\n }\n let value = Number(valueString);\n if (isNaN(value)) {\n value = 0;\n }\n value += adjustValue;\n promises.push(fragment.setValue(String(value)));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 行フラグメントを取得します。\n *\n * @returns 行フラグメントまたはnull\n */\n private getRowFragment(): ElementFragment | null {\n if (!this.options.targetFragment) {\n Log.error('Haori', 'Target fragment is not specified for row operation.');\n return null;\n }\n const rowFragment = this.options.targetFragment.closestByAttribute(\n `${Env.prefix}row`,\n );\n if (!rowFragment) {\n Log.error('Haori', 'Row fragment not found.');\n return null;\n }\n return rowFragment;\n }\n\n /**\n * 行を追加します。\n *\n * @returns 処理結果のPromise\n */\n private addRow(): Promise<void> {\n if (this.options.rowAdd !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n const promises: Promise<void>[] = [];\n const newFragment = rowFragment.clone();\n promises.push(\n rowFragment.getParent()!.insertAfter(newFragment, rowFragment),\n );\n promises.push(Core.evaluateAll(newFragment));\n // 追加された行のフォーム要素をリセット\n promises.push(Form.reset(newFragment as ElementFragment));\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 行を削除します。\n *\n * @returns 処理結果のPromise\n */\n private removeRow(): Promise<void> {\n if (this.options.rowRemove !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n // 1行だった場合は削除しない\n const parent = rowFragment.getParent();\n if (parent) {\n const siblings = parent.getChildElementFragments().filter(child => {\n // data-each-before と data-each-after を除外\n return (\n !child.hasAttribute(`${Env.prefix}each-before`) &&\n !child.hasAttribute(`${Env.prefix}each-after`)\n );\n });\n if (siblings.length <= 1) {\n return Promise.resolve();\n }\n }\n return rowFragment.remove();\n }\n\n /**\n * 前の行へ移動します。\n *\n * @returns 処理結果のPromise\n */\n private movePrevRow(): Promise<void> {\n if (this.options.rowMovePrev !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n const prevFragment = rowFragment.getPrevious();\n if (!prevFragment) {\n return Promise.resolve();\n }\n const parent = rowFragment.getParent();\n if (!parent) {\n return Promise.resolve();\n }\n return parent.insertBefore(rowFragment, prevFragment);\n }\n\n /**\n * 次の行へ移動します。\n *\n * @returns 処理結果のPromise\n */\n private moveNextRow(): Promise<void> {\n if (this.options.rowMoveNext !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n const nextFragment = rowFragment.getNext();\n if (!nextFragment) {\n return Promise.resolve();\n }\n const parent = rowFragment.getParent();\n if (!parent) {\n return Promise.resolve();\n }\n return parent.insertAfter(rowFragment, nextFragment);\n }\n}\n","/**\n * @fileoverview URLパラメータ取得クラス\n *\n * URLのクエリパラメータを取得します。\n */\n\nexport default class Url {\n /**\n * URLのクエリパラメータを取得します。\n *\n * @returns URLのクエリパラメータのキーと値のマップ\n */\n public static readParams(): Record<string, string> {\n const params: Record<string, string> = {};\n const queryString = window.location.search;\n const urlParams = new URLSearchParams(queryString);\n urlParams.forEach((value, key) => {\n params[key] = value;\n });\n return params;\n }\n}\n","/**\n * @fileoverview HTMLインポート機能\n *\n * 指定URLの HTML を取得し、body タグの中身のみを取り出します。\n * 仕様: data-import — 指定したURLの body タグの中身を対象エレメントの innerHTML に設定する。\n */\nimport Log from './log';\n\n/**\n * インポート機能を提供するクラスです。\n */\nexport class Import {\n /**\n * 指定URLから HTML を取得し、body 内の HTML 文字列を返します。\n *\n * 振る舞い:\n * - HTTP ステータスが成功以外の場合は例外を投げます。\n * - HTML のパースに失敗した場合はログを出力し、テキスト全体を返します(フォールバック)。\n * - body タグが存在しない場合もテキスト全体を返します(フォールバック)。\n *\n * @param url 取得先の URL\n * @param init fetch のオプション(任意)\n * @returns body 内の HTML 文字列\n */\n public static async load(url: string, init?: RequestInit): Promise<string> {\n let response: Response;\n try {\n response = await fetch(url, init);\n } catch (e) {\n Log.error('[Haori]', 'Failed to fetch import source:', url, e);\n throw new Error(`Failed to fetch: ${url}`);\n }\n\n if (!response.ok) {\n // ネットワーク/HTTP エラーは上位で扱いやすいように例外化\n const status = `${response.status} ${response.statusText}`;\n Log.error('[Haori]', 'Import HTTP error:', url, status);\n throw new Error(`Failed to load ${url}: ${status}`);\n }\n\n let text: string;\n try {\n text = await response.text();\n } catch (e) {\n Log.error('[Haori]', 'Failed to read response text:', url, e);\n throw new Error(`Failed to read response from: ${url}`);\n }\n\n // HTML としてパースし、body 内のみを返す\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(text, 'text/html');\n if (doc && doc.body) {\n return doc.body.innerHTML;\n }\n Log.warn('[Haori]', 'No body found in imported document:', url);\n return text;\n } catch (e) {\n // パース失敗時はフォールバックとしてテキスト全体を返す\n Log.error('[Haori]', 'Failed to parse imported HTML:', url, e);\n return text;\n }\n }\n}\n","/**\n * @fileoverview Core機能\n *\n * Fragmentの管理、属性変化の監視、条件分岐・繰り返し処理など、\n * アプリケーションの中心的な機能を提供します。\n */\nimport Env from './env';\nimport Form from './form';\nimport Fragment, {ElementFragment, TextFragment} from './fragment';\nimport Log from './log';\nimport Procedure from './procedure';\nimport Url from './url';\nimport {Import} from './import';\nimport Queue from './queue';\nimport HaoriEvent from './event';\n\n/**\n * アプリケーションの中心的な制御を行うクラスです。\n * Fragment の初期化、属性変化の処理、条件分岐・繰り返し処理を管理します。\n */\nexport default class Core {\n /** 属性エイリアスのサフィックス */\n private static readonly ATTRIBUTE_ALIAS_SUFFIX = 'attr-';\n\n /** 優先処理する属性のサフィックス(処理順序で定義) */\n private static readonly PRIORITY_ATTRIBUTE_SUFFIXES = ['bind', 'if', 'each'];\n\n /** 遅延処理する属性のサフィックス */\n private static readonly DEFERRED_ATTRIBUTE_SUFFIXES = ['fetch', 'url-param'];\n\n /** evaluateAll で再評価対象から除外する特殊属性のサフィックス */\n private static readonly EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES = [\n 'bind',\n 'if',\n 'each',\n 'fetch',\n 'import',\n 'url-param',\n ];\n\n /** 属性内プレースホルダ検出用の正規表現 */\n private static readonly ATTRIBUTE_PLACEHOLDER_REGEX =\n /\\{\\{\\{[\\s\\S]+?\\}\\}\\}|\\{\\{[\\s\\S]+?\\}\\}/;\n\n /**\n * 遅延属性かどうか(完全名で判定)を判定します。\n *\n * @param name 属性名\n * @returns 遅延属性かどうか\n */\n private static isDeferredAttributeName(name: string): boolean {\n return Core.DEFERRED_ATTRIBUTE_SUFFIXES.some(\n suffix => name === `${Env.prefix}${suffix}`,\n );\n }\n\n /**\n * evaluateAll で再評価対象から除外する特殊属性かどうかを判定します。\n *\n * @param name 属性名\n * @returns 除外対象かどうか\n */\n private static isEvaluateAllExcludedAttributeName(name: string): boolean {\n return Core.EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES.some(\n suffix => name === `${Env.prefix}${suffix}`,\n );\n }\n\n /**\n * evaluateAll で通常属性を再評価すべきかを判定します。\n *\n * @param name 属性名\n * @param value 属性の生値\n * @returns 再評価する場合は true\n */\n private static shouldReevaluateAttribute(\n name: string,\n value: string | null,\n ): boolean {\n return (\n value !== null &&\n !Core.isEvaluateAllExcludedAttributeName(name) &&\n Core.ATTRIBUTE_PLACEHOLDER_REGEX.test(value)\n );\n }\n\n /**\n * data-attr-* 形式の属性名から実際に更新する属性名を取得します。\n *\n * @param name 属性名\n * @returns 実際の属性名。data-attr-* でない場合は null\n */\n private static getAliasedAttributeName(name: string): string | null {\n const aliasPrefix = `${Env.prefix}${Core.ATTRIBUTE_ALIAS_SUFFIX}`;\n if (!name.startsWith(aliasPrefix) || name.length <= aliasPrefix.length) {\n return null;\n }\n return name.slice(aliasPrefix.length);\n }\n\n /**\n * 実属性の変更が data-attr-* の内部反映かどうかを判定します。\n *\n * @param element 対象要素\n * @param name 変更された属性名\n * @returns data-attr-* の内部反映なら true\n */\n public static isAliasedAttributeReflection(\n element: HTMLElement,\n name: string,\n ): boolean {\n const fragment = Fragment.get(element);\n if (!(fragment instanceof ElementFragment)) {\n return false;\n }\n return fragment.hasAttribute(\n `${Env.prefix}${Core.ATTRIBUTE_ALIAS_SUFFIX}${name}`,\n );\n }\n\n /**\n * プレースホルダを含む通常属性を再評価します。\n * 内部状態の更新は同期的に行い、DOM 反映は fragment 側の非同期更新に委ねます。\n *\n * @param fragment 対象フラグメント\n * @returns 再評価完了の Promise\n */\n private static reevaluateInterpolatedAttributes(\n fragment: ElementFragment,\n ): Promise<void> {\n let chain = Promise.resolve();\n for (const name of fragment.getAttributeNames()) {\n const rawValue = fragment.getRawAttribute(name);\n if (!Core.shouldReevaluateAttribute(name, rawValue)) {\n continue;\n }\n chain = chain.then(() =>\n Core.setAttribute(fragment.getTarget(), name, rawValue),\n );\n }\n return chain.then(() => undefined);\n }\n\n /**\n * 指定された要素と、その子要素をスキャンし、Fragmentを生成します。\n *\n * @param element スキャン対象の要素\n * @returns Promise (スキャンが完了したときに解決される)\n */\n public static scan(element: HTMLElement): Promise<void> {\n const fragment = Fragment.get(element);\n if (!fragment) {\n return Promise.resolve();\n }\n // DOMに組み込まれている場合はmountedをtrueにする\n if (element.parentNode) {\n const parentFragment = Fragment.get(element.parentNode as HTMLElement);\n if (parentFragment?.isMounted()) {\n fragment.setMounted(true);\n } else if (document.body.contains(element)) {\n // document.bodyに含まれている場合はマウント済みとする\n fragment.setMounted(true);\n } else {\n fragment.setMounted(false);\n }\n }\n let attributeChain = Promise.resolve();\n const processedAttributes = new Set<string>();\n for (const suffix of Core.PRIORITY_ATTRIBUTE_SUFFIXES) {\n // 優先属性の処理\n const name = Env.prefix + suffix;\n if (fragment.hasAttribute(name)) {\n attributeChain = attributeChain.then(() =>\n Core.setAttribute(\n fragment.getTarget(),\n name,\n fragment.getRawAttribute(name),\n ),\n );\n processedAttributes.add(name);\n }\n }\n for (const name of fragment.getAttributeNames()) {\n if (processedAttributes.has(name) || Core.isDeferredAttributeName(name)) {\n // すでに処理済みもしくは遅延処理の属性はスキップ\n continue;\n }\n const value = fragment.getRawAttribute(name);\n if (value !== null) {\n attributeChain = attributeChain.then(() =>\n Core.setAttribute(fragment.getTarget(), name, value),\n );\n }\n }\n for (const suffix of Core.DEFERRED_ATTRIBUTE_SUFFIXES) {\n // 遅延属性の処理\n const name = Env.prefix + suffix;\n if (fragment.hasAttribute(name)) {\n attributeChain = attributeChain.then(() =>\n Core.setAttribute(\n fragment.getTarget(),\n name,\n fragment.getRawAttribute(name),\n ),\n );\n processedAttributes.add(name);\n }\n }\n return attributeChain\n .then(() => {\n const childPromises: Promise<void>[] = [];\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n childPromises.push(Core.scan(child.getTarget()));\n } else if (child instanceof TextFragment) {\n childPromises.push(Core.evaluateText(child));\n }\n });\n return Promise.all(childPromises).then(() => undefined);\n })\n .then(() => undefined);\n }\n\n /**\n * エレメントに属性を設定します。\n * 属性固有の処理も行います。\n *\n * @param element エレメント\n * @param name 属性名\n * @param value 属性値\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static setAttribute(\n element: HTMLElement,\n name: string,\n value: string | null,\n ): Promise<void> {\n const fragment = Fragment.get(element);\n const aliasedAttributeName = Core.getAliasedAttributeName(name);\n if (aliasedAttributeName !== null) {\n if (value === null) {\n return fragment.removeAliasedAttribute(name, aliasedAttributeName);\n }\n return fragment.setAliasedAttribute(name, aliasedAttributeName, value);\n }\n const promises: Promise<void>[] = [];\n switch (name) {\n case `${Env.prefix}bind`: {\n if (value === null) {\n fragment.clearBindingDataCache();\n fragment.setBindingData({});\n } else {\n fragment.setBindingData(Core.parseDataBind(value));\n }\n break;\n }\n case `${Env.prefix}if`:\n promises.push(Core.evaluateIf(fragment));\n break;\n case `${Env.prefix}each`:\n promises.push(Core.evaluateEach(fragment));\n break;\n case `${Env.prefix}fetch`:\n promises.push(\n new Procedure(fragment, null).run().then(() => undefined),\n );\n break;\n case `${Env.prefix}import`: {\n if (typeof value === 'string') {\n const target = fragment.getTarget();\n const startedAt = performance.now();\n HaoriEvent.importStart(target, value);\n\n promises.push(\n Import.load(value)\n .then(html => {\n const bytes = new TextEncoder().encode(html).length;\n // DOM 更新はキュー内で実行し、オブザーバーに差分を拾わせる\n return Queue.enqueue(() => {\n target.innerHTML = html;\n }).then(() => {\n HaoriEvent.importEnd(target, value, bytes, startedAt);\n });\n })\n .catch(error => {\n HaoriEvent.importError(target, value, error);\n Log.error('[Haori]', 'Failed to import HTML:', value, error);\n }) as unknown as Promise<void>,\n );\n }\n break;\n }\n case `${Env.prefix}url-param`: {\n const arg = fragment.getAttribute(`${Env.prefix}url-arg`);\n const params = Url.readParams();\n if (arg === null) {\n promises.push(Core.setBindingData(element, params));\n } else {\n const data = fragment.getRawBindingData() || {};\n data[String(arg)] = params;\n promises.push(Core.setBindingData(element, data));\n }\n break;\n }\n }\n if (value === null) {\n promises.push(fragment.removeAttribute(name));\n } else {\n promises.push(fragment.setAttribute(name, value));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * エレメントに属性を設定し、評価を行います。\n *\n * @param element エレメント\n * @param name 属性名\n * @param value 属性値\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static setBindingData(\n element: HTMLElement,\n data: Record<string, unknown>,\n ): Promise<void> {\n const fragment = Fragment.get(element) as ElementFragment;\n const previous = fragment.getRawBindingData();\n fragment.setBindingData(data);\n let chain = fragment.setAttribute(\n `${Env.prefix}bind`,\n JSON.stringify(data),\n );\n if (element.tagName === 'FORM') {\n const arg = fragment.getAttribute(`${Env.prefix}form-arg`);\n const formValues =\n arg &&\n data[String(arg)] &&\n typeof data[String(arg)] === 'object' &&\n !Array.isArray(data[String(arg)])\n ? (data[String(arg)] as Record<string, unknown>)\n : arg\n ? {}\n : data;\n chain = chain.then(() => Form.syncValues(fragment, formValues));\n }\n chain = chain.then(() => Core.evaluateAll(fragment));\n\n // bindchangeイベントを発火\n HaoriEvent.bindChange(element, previous, data, 'manual');\n\n return chain.then(() => undefined);\n }\n\n /**\n * data-bind 属性の値をパースします。\n *\n * @param data data-bind 属性の値\n * @returns パースされたデータオブジェクト\n */\n public static parseDataBind(data: string): Record<string, unknown> {\n if (data.startsWith('{') || data.startsWith('[')) {\n // JSONとしてパース\n try {\n return JSON.parse(data);\n } catch (e) {\n Log.error('[Haori]', 'Invalid JSON in data-bind:', e);\n return {};\n }\n } else {\n // URLSearchParamsでパース\n const params = new URLSearchParams(data);\n const result: Record<string, unknown> = {};\n for (const [key, value] of params.entries()) {\n if (result[key] !== undefined) {\n // すでに値がある場合は配列化\n if (Array.isArray(result[key])) {\n (result[key] as string[]).push(value);\n } else {\n result[key] = [result[key], value];\n }\n } else {\n result[key] = value;\n }\n }\n return result;\n }\n }\n\n /**\n * ノードを親要素に追加し評価を行います。\n *\n * @param parentElement 親エレメント\n * @param node 追加するノード\n */\n public static addNode(parentElement: HTMLElement, node: Node) {\n const parent = Fragment.get(parentElement);\n // skipMutationNodesが設定されている場合は処理をスキップ\n if (parent.isSkipMutationNodes()) {\n return;\n }\n const next = Fragment.get(node.nextSibling);\n const fragment = Fragment.get(node);\n if (fragment) {\n parent.insertBefore(fragment, next);\n if (fragment instanceof ElementFragment) {\n // 新規追加ノードは属性評価(bind/if/each/import など含む)のフルスキャンを行う。\n // これにより、取り込まれた断片内の data-import の入れ子や data-bind も正しく処理される。\n Core.scan(fragment.getTarget());\n } else if (fragment instanceof TextFragment) {\n Core.evaluateText(fragment);\n }\n }\n }\n\n /**\n * ノードを親要素から削除します。\n *\n * @param node 削除するノード\n */\n public static removeNode(node: Node) {\n const fragment = Fragment.get(node);\n if (fragment) {\n const parent = fragment.getParent();\n // skipMutationNodesが設定されている場合は処理をスキップ\n if (parent && parent.isSkipMutationNodes()) {\n return;\n }\n fragment.remove();\n }\n }\n\n /**\n * ノードのテキストを変更します。\n *\n * @param node 変更するノード\n * @param text 新しいテキスト\n */\n public static changeText(node: Text | Comment, text: string) {\n const fragment = Fragment.get(node);\n if (fragment) {\n fragment.setContent(text);\n }\n }\n\n /**\n * エレメントの値を変更します。\n * フォームの双方向バインディングを考慮し、フォームのバインドデータも更新します。\n *\n * @param element 変更するエレメント\n * @param value 新しい値\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static changeValue(\n element: HTMLElement,\n value: string,\n ): Promise<void> {\n const fragment = Fragment.get(element);\n if (fragment.getValue() === value) {\n return Promise.resolve();\n }\n const promises: Promise<void>[] = [];\n promises.push(fragment.setValue(value));\n const formFragment = Core.getFormFragment(fragment);\n if (formFragment) {\n const values = Form.getValues(formFragment);\n const arg = formFragment.getAttribute(`${Env.prefix}form-arg`);\n let bindingData;\n if (arg) {\n bindingData = formFragment.getRawBindingData();\n if (!bindingData) {\n bindingData = {};\n }\n bindingData[String(arg)] = values;\n } else {\n bindingData = values;\n }\n promises.push(Core.setBindingData(formFragment.getTarget(), bindingData));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * フォームフラグメントを取得します。\n *\n * @param fragment フラグメント\n * @returns フォームフラグメントまたはnull\n */\n private static getFormFragment(\n fragment: ElementFragment,\n ): ElementFragment | null {\n if (fragment.getTarget() instanceof HTMLFormElement) {\n return fragment;\n }\n const parent = fragment.getParent();\n if (parent) {\n return Core.getFormFragment(parent);\n }\n return null;\n }\n\n /**\n * フラグメントとその子要素を評価します。\n *\n * @param fragment 対象フラグメント\n * @return Promise (DOM操作が完了したときに解決される)\n */\n public static evaluateAll(fragment: ElementFragment): Promise<void> {\n const promises: Promise<void>[] = [];\n promises.push(Core.reevaluateInterpolatedAttributes(fragment));\n if (fragment.hasAttribute(`${Env.prefix}if`)) {\n promises.push(Core.evaluateIf(fragment));\n }\n if (fragment.hasAttribute(`${Env.prefix}each`)) {\n return Promise.all(promises)\n .then(() => Core.evaluateEach(fragment))\n .then(() => {\n const childPromises: Promise<void>[] = [];\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n childPromises.push(Core.evaluateAll(child));\n } else if (child instanceof TextFragment) {\n childPromises.push(Core.evaluateText(child));\n }\n });\n return Promise.all(childPromises).then(() => undefined);\n });\n }\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n promises.push(Core.evaluateAll(child));\n } else if (child instanceof TextFragment) {\n promises.push(Core.evaluateText(child));\n }\n });\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * テキストフラグメントを評価します。\n *\n * @param fragment 対象フラグメント\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static evaluateText(fragment: TextFragment): Promise<void> {\n return fragment.evaluate();\n }\n\n /**\n * if要素を評価します。\n * 値がfalse、null、undefined、NaNの場合は非表示にし、それ以外の場合は表示します。\n *\n * @param fragment 対象フラグメント\n * @return Promise (DOM操作が完了したときに解決される)\n */\n public static evaluateIf(fragment: ElementFragment): Promise<void> {\n const promises: Promise<void>[] = [];\n const condition = fragment.getAttribute(`${Env.prefix}if`);\n if (\n condition === false ||\n condition === undefined ||\n condition === null ||\n Number.isNaN(condition)\n ) {\n if (fragment.isVisible()) {\n promises.push(\n fragment.hide().then(() => {\n HaoriEvent.hide(fragment.getTarget());\n }),\n );\n }\n } else {\n if (!fragment.isVisible()) {\n promises.push(\n fragment.show().then(() => {\n HaoriEvent.show(fragment.getTarget());\n }),\n );\n promises.push(Core.evaluateAll(fragment));\n }\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * each要素を評価します。\n * 非表示または未マウントの場合は処理をスキップします。\n *\n * @param fragment 対象フラグメント\n */\n public static evaluateEach(fragment: ElementFragment): Promise<void> {\n if (!fragment.isVisible() || !fragment.isMounted()) {\n return Promise.resolve();\n }\n let template = fragment.getTemplate();\n if (template === null) {\n // テンプレートの作成\n let found = false;\n fragment.getChildren().forEach(child => {\n if (found) {\n return;\n }\n if (child instanceof ElementFragment) {\n if (\n child.hasAttribute(`${Env.prefix}each-before`) ||\n child.hasAttribute(`${Env.prefix}each-after`)\n ) {\n return;\n }\n // 最初のElementFragmentをテンプレートとして採用\n template = child.clone();\n fragment.setTemplate(template);\n found = true;\n // 元のchildはchildrenから除外\n fragment.removeChild(child);\n // DOMからも必ず除去\n const templateTarget = child.getTarget();\n if (templateTarget.parentNode) {\n templateTarget.parentNode.removeChild(templateTarget);\n }\n child.setMounted(false);\n }\n // TextNodeやCommentNodeはテンプレートにならないので無視\n });\n const data = fragment.getAttribute(`${Env.prefix}each`);\n if (!Array.isArray(data)) {\n Log.error('[Haori]', 'Invalid each attribute:', data);\n return Promise.reject(new Error('Invalid each attribute.'));\n }\n // テンプレートのunmount完了後にupdateDiffを実行\n return this.updateDiff(fragment, data);\n }\n const data = fragment.getAttribute(`${Env.prefix}each`);\n if (!Array.isArray(data)) {\n Log.error('[Haori]', 'Invalid each attribute:', data);\n return Promise.reject(new Error('Invalid each attribute.'));\n }\n return this.updateDiff(fragment, data);\n }\n\n /**\n * 差分を更新します。\n *\n * @param parent 親フラグメント\n * @param newList 新しいリスト\n */\n private static updateDiff(\n parent: ElementFragment,\n newList: (Record<string, unknown> | string | number)[],\n ): Promise<void> {\n const template = parent.getTemplate();\n if (template === null) {\n Log.error('[Haori]', 'Template is not set for each element.');\n return Promise.resolve();\n }\n let indexKey = parent.getAttribute(`${Env.prefix}each-index`);\n if (indexKey) {\n indexKey = String(indexKey);\n }\n const keyArg = parent.getAttribute(`${Env.prefix}each-key`);\n const itemArg = parent.getAttribute(`${Env.prefix}each-arg`);\n const keyDataMap: Map<\n string,\n {item: (typeof newList)[0]; itemIndex: number}\n > = new Map();\n const newKeys: string[] = [];\n newList.forEach((item, itemIndex) => {\n const listKey = Core.createListKey(\n item,\n keyArg ? String(keyArg) : null,\n itemIndex,\n );\n newKeys.push(listKey);\n keyDataMap.set(listKey, {item, itemIndex});\n });\n const removalPromises: Promise<void>[] = [];\n let childElements = parent\n .getChildren()\n .filter(child => child instanceof ElementFragment)\n .filter(\n child =>\n !child.hasAttribute(`${Env.prefix}each-before`) &&\n !child.hasAttribute(`${Env.prefix}each-after`),\n );\n childElements = childElements.filter(child => {\n const index = newKeys.indexOf(String(child.getListKey()));\n if (index === -1) {\n removalPromises.push(child.remove());\n return false;\n }\n return true;\n });\n const srcKeys = childElements.map(child => child.getListKey());\n const baseInsertIndex = parent\n .getChildren()\n .filter(child => child instanceof ElementFragment)\n .filter(child => child.hasAttribute(`${Env.prefix}each-before`)).length;\n let chain = Promise.resolve();\n newKeys.forEach((newKey, loopIndex) => {\n const srcIndex = srcKeys.indexOf(newKey);\n const {item, itemIndex} = keyDataMap.get(newKey)!;\n let child: ElementFragment;\n if (srcIndex !== -1) {\n // 既存の要素を再利用\n child = childElements[srcIndex];\n // 既存要素にも必ずバインドデータを再セットし、キャッシュもクリア\n chain = chain.then(() =>\n Core.updateRowFragment(\n child,\n item,\n indexKey as string | null,\n itemIndex,\n itemArg ? String(itemArg) : null,\n newKey,\n ).then(() => Core.evaluateAll(child)),\n );\n } else {\n // 新しい要素を追加\n child = template.clone();\n const currentInsertIndex = baseInsertIndex + loopIndex;\n chain = chain.then(() =>\n Core.updateRowFragment(\n child,\n item,\n indexKey as string | null,\n itemIndex,\n itemArg ? String(itemArg) : null,\n newKey,\n ).then(() =>\n parent\n .insertBefore(\n child,\n parent.getChildren()[currentInsertIndex] || null,\n )\n .then(() => Core.evaluateAll(child)),\n )\n );\n }\n });\n return Promise.all(removalPromises)\n .then(() => chain)\n .then(() => {\n // eachupdateイベントを発火\n const validNewKeys = newKeys.filter(\n (key): key is string => key !== null,\n );\n const validSrcKeys = srcKeys.filter(\n (key): key is string => key !== null,\n );\n const addedKeys = validNewKeys.filter(\n key => !validSrcKeys.includes(key),\n );\n const removedKeys = validSrcKeys.filter(\n key => !validNewKeys.includes(key),\n );\n HaoriEvent.eachUpdate(\n parent.getTarget(),\n addedKeys,\n removedKeys,\n validNewKeys,\n );\n return undefined;\n });\n }\n\n /**\n * リスト比較用のキーを生成します。\n *\n * @param item 対象オブジェクト\n * @param keyArg リストキーに使用するプロパティ名\n * @param index 配列のインデックス\n * @returns リストキー\n */\n private static createListKey(\n item: Record<string, unknown> | string | number,\n keyArg: string | null,\n index: number,\n ): string {\n let listKey: string;\n if (typeof item === 'object' && item !== null) {\n if (keyArg) {\n const key = item[keyArg as string];\n if (key === null || key === undefined) {\n listKey = `__index_${index}`;\n } else if (typeof key == 'object') {\n listKey = JSON.stringify(key);\n } else {\n listKey = String(key);\n }\n } else {\n // data-each-key がない場合はインデックスをキーとして使用\n listKey = `__index_${index}`;\n }\n } else {\n listKey = String(item);\n }\n return listKey;\n }\n\n /**\n * 行フラグメントにデータを設定します。\n *\n * @param rowFragment 行フラグメント\n * @param data 行データ\n * @param indexKey インデックスキー\n * @param index インデックス番号\n * @param arg バインドデータパラメータ名\n * @param listKey リストキー\n * @returns 行メタデータの更新完了 Promise\n */\n private static updateRowFragment(\n rowFragment: ElementFragment,\n data: Record<string, unknown> | string | number,\n indexKey: string | null,\n index: number,\n arg: string | null,\n listKey: string,\n ): Promise<void> {\n let bindingData = data;\n if (typeof data === 'object' && data !== null) {\n bindingData = {...data};\n if (indexKey) {\n bindingData[indexKey] = index;\n }\n if (arg) {\n bindingData = {\n [arg]: bindingData,\n };\n }\n } else {\n if (arg) {\n bindingData = {\n [arg]: data,\n };\n if (indexKey) {\n bindingData[indexKey] = index;\n }\n } else {\n Log.error(\n '[Haori]',\n `Primitive value requires '${Env.prefix}each-arg' attribute: ${data}`,\n );\n return Promise.resolve();\n }\n }\n rowFragment.setListKey(listKey);\n rowFragment.setBindingData(bindingData as Record<string, unknown>);\n return rowFragment.setAttribute(`${Env.prefix}row`, listKey);\n }\n}\n","/**\n * @fileoverview イベント振り分け機能\n *\n * クリック/変更/ロード/ポップステートイベントを検出し Procedure に委譲します。\n */\n\nimport Fragment, {ElementFragment} from './fragment';\nimport Procedure from './procedure';\nimport Log from './log';\n\n/**\n * イベントの振り分けを行うクラスです。\n */\nexport default class EventDispatcher {\n /** Haori が history.state に埋め込む状態キー */\n private static readonly HISTORY_STATE_KEY = '__haoriHistoryState__';\n\n /** ルート要素 */\n private readonly root: Document | HTMLElement;\n\n /** クリックデリゲータ */\n private readonly onClick = (event: Event) => this.delegate(event, 'click');\n\n /** 変更デリゲータ */\n private readonly onChange = (event: Event) => this.delegate(event, 'change');\n\n /** ロードデリゲータ(キャプチャで拾う) */\n private readonly onLoadCapture = (event: Event) =>\n this.delegate(event, 'load');\n\n /** ページ全体のロード完了時の処理 */\n private readonly onWindowLoad = () => {\n // ページロード時にも load を1回ディスパッチ\n const html = document.documentElement;\n const fragment = Fragment.get(html);\n if (fragment) {\n void new Procedure(fragment, 'load').run();\n }\n };\n\n /**\n * popstate デリゲータ(Haori が管理する履歴に戻った場合だけページをリロード)。\n *\n * @param event popstate イベント\n */\n private readonly onPopstate = (event: PopStateEvent) => {\n const state = event.state as Record<string, unknown> | null;\n if (!state || state[EventDispatcher.HISTORY_STATE_KEY] !== true) {\n return;\n }\n location.reload();\n };\n\n /**\n * コンストラクタ。\n *\n * @param root 監視対象のルート要素(デフォルトは document )\n */\n constructor(root: Document | HTMLElement = document) {\n this.root = root;\n }\n\n /**\n * イベントリスナーの登録を開始します。\n * クリック、変更、ロード、popstate イベントを監視し、対応するProcedureを実行します。\n */\n start(): void {\n this.root.addEventListener('click', this.onClick);\n this.root.addEventListener('change', this.onChange);\n // load は非バブルなのでキャプチャで拾う\n this.root.addEventListener('load', this.onLoadCapture, true);\n // ページ全体のロード\n window.addEventListener('load', this.onWindowLoad, {once: true});\n // ブラウザの戻る・進む操作\n window.addEventListener('popstate', this.onPopstate);\n }\n\n /**\n * イベントリスナーの登録を停止します。\n */\n stop(): void {\n this.root.removeEventListener('click', this.onClick);\n this.root.removeEventListener('change', this.onChange);\n this.root.removeEventListener('load', this.onLoadCapture, true);\n window.removeEventListener('load', this.onWindowLoad);\n window.removeEventListener('popstate', this.onPopstate);\n }\n\n /**\n * イベントを処理し、対応するProcedureを実行します。\n *\n * @param event 発生したイベント\n * @param type イベントタイプ('click', 'change', 'load'など)\n */\n private delegate(event: Event, type: string) {\n const element = this.getElementFromTarget(event.target);\n if (!element) {\n return;\n }\n const fragment = Fragment.get(element);\n if (!fragment) {\n return;\n }\n\n // changeイベントの場合、DOM値と同期\n if (type === 'change' && fragment instanceof ElementFragment) {\n fragment.syncValue();\n }\n\n new Procedure(fragment, type).run().catch(error => {\n Log.error('[Haori]', 'Procedure execution error:', error);\n });\n }\n\n /**\n * イベントのターゲットから HTMLElement を取得します。\n *\n * @param target イベントのターゲット\n * @returns HTMLElement または null\n */\n private getElementFromTarget(target: EventTarget | null): HTMLElement | null {\n if (!target) {\n return null;\n }\n if (target instanceof HTMLElement) {\n return target;\n }\n if (target instanceof Node) {\n return target.parentElement;\n }\n return null;\n }\n}\n","/**\n * @fileoverview IntersectionObserver based trigger dispatcher.\n */\n\nimport Env from './env';\nimport Fragment, {ElementFragment} from './fragment';\nimport Log from './log';\nimport Procedure from './procedure';\n\ninterface IntersectRegistration {\n fragment: ElementFragment;\n observer: IntersectionObserver;\n once: boolean;\n running: boolean;\n}\n\n/**\n * `data-intersect-*` 属性を監視し、交差時に Procedure を実行します。\n */\nexport default class IntersectObserver {\n private static readonly CONFIG_KEYS = new Set([\n 'root',\n 'root-margin',\n 'threshold',\n 'disabled',\n 'once',\n ]);\n\n private static readonly registrations = new Map<\n HTMLElement,\n IntersectRegistration\n >();\n\n public static syncTree(root: Node): void {\n if (!(root instanceof Element || root instanceof DocumentFragment)) {\n return;\n }\n if (root instanceof HTMLElement) {\n IntersectObserver.syncElement(root);\n }\n root.querySelectorAll<HTMLElement>('*').forEach(element => {\n IntersectObserver.syncElement(element);\n });\n }\n\n public static syncElement(element: HTMLElement): void {\n const registration = IntersectObserver.registrations.get(element);\n const fragment = Fragment.get(element);\n if (!fragment || !IntersectObserver.shouldObserve(fragment)) {\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n return;\n }\n\n if (typeof IntersectionObserver === 'undefined') {\n return;\n }\n\n const nextRoot = IntersectObserver.resolveRoot(fragment);\n const nextRootMargin = IntersectObserver.resolveRootMargin(fragment);\n const nextThreshold = IntersectObserver.resolveThreshold(fragment);\n const nextOnce = fragment.hasAttribute(`${Env.prefix}intersect-once`);\n\n if (\n registration &&\n registration.observer.root === nextRoot &&\n registration.observer.rootMargin === nextRootMargin &&\n IntersectObserver.sameThreshold(\n registration.observer.thresholds,\n nextThreshold,\n ) &&\n registration.once === nextOnce\n ) {\n registration.fragment = fragment;\n return;\n }\n\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n\n const observer = new IntersectionObserver(\n entries => {\n const current = IntersectObserver.registrations.get(element);\n if (!current) {\n return;\n }\n entries.forEach(entry => {\n if (!entry.isIntersecting || current.running) {\n return;\n }\n if (IntersectObserver.isDisabled(current.fragment)) {\n return;\n }\n current.running = true;\n void new Procedure(current.fragment, 'intersect')\n .runWithResult()\n .then(success => {\n if (success && current.once) {\n current.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n })\n .catch(error => {\n Log.error(\n '[Haori]',\n 'Intersect procedure execution error:',\n error,\n );\n })\n .finally(() => {\n const latest = IntersectObserver.registrations.get(element);\n if (latest) {\n latest.running = false;\n }\n });\n });\n },\n {\n root: nextRoot,\n rootMargin: nextRootMargin,\n threshold: nextThreshold,\n },\n );\n\n observer.observe(element);\n IntersectObserver.registrations.set(element, {\n fragment,\n observer,\n once: nextOnce,\n running: false,\n });\n }\n\n public static cleanupTree(root: Node): void {\n if (root instanceof HTMLElement) {\n const registration = IntersectObserver.registrations.get(root);\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(root);\n }\n }\n if (!(root instanceof Element || root instanceof DocumentFragment)) {\n return;\n }\n root.querySelectorAll<HTMLElement>('*').forEach(element => {\n const registration = IntersectObserver.registrations.get(element);\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n });\n }\n\n public static disconnectAll(): void {\n IntersectObserver.registrations.forEach(registration => {\n registration.observer.disconnect();\n });\n IntersectObserver.registrations.clear();\n }\n\n private static shouldObserve(fragment: ElementFragment): boolean {\n return fragment.getAttributeNames().some(name => {\n if (!name.startsWith(`${Env.prefix}intersect-`)) {\n return false;\n }\n const key = name.slice(`${Env.prefix}intersect-`.length);\n return !IntersectObserver.CONFIG_KEYS.has(key);\n });\n }\n\n private static resolveRoot(fragment: ElementFragment): HTMLElement | null {\n const attrName = `${Env.prefix}intersect-root`;\n if (!fragment.hasAttribute(attrName)) {\n return null;\n }\n const selector = fragment.getAttribute(attrName);\n if (typeof selector !== 'string' || selector.trim() === '') {\n return null;\n }\n const root = document.querySelector(selector);\n if (root instanceof HTMLElement) {\n return root;\n }\n Log.error('[Haori]', `Intersect root element not found: ${selector}`);\n return null;\n }\n\n private static resolveRootMargin(fragment: ElementFragment): string {\n const attrName = `${Env.prefix}intersect-root-margin`;\n const value = fragment.getAttribute(attrName);\n if (value === null || value === false || value === '') {\n return '0px';\n }\n return String(value);\n }\n\n private static resolveThreshold(fragment: ElementFragment): number {\n const attrName = `${Env.prefix}intersect-threshold`;\n const value = fragment.getAttribute(attrName);\n const threshold =\n typeof value === 'number' ? value : Number.parseFloat(String(value ?? 0));\n if (Number.isNaN(threshold)) {\n return 0;\n }\n return Math.min(1, Math.max(0, threshold));\n }\n\n private static isDisabled(fragment: ElementFragment): boolean {\n const attrName = `${Env.prefix}intersect-disabled`;\n const value = fragment.getAttribute(attrName);\n if (value === null || value === false) {\n return false;\n }\n if (typeof value === 'boolean') {\n return value;\n }\n const stringValue = String(value).trim().toLowerCase();\n return stringValue !== '' && stringValue !== 'false' && stringValue !== '0';\n }\n\n private static sameThreshold(\n thresholds: readonly number[],\n threshold: number,\n ): boolean {\n return thresholds.length === 1 && thresholds[0] === threshold;\n }\n}\n","/**\n * @fileoverview 監視機能\n *\n * Observerクラスは、DOMの変更を監視し、バインディングの更新を行います。\n * MutationObserverを使用して、属性の変更、ノードの追加・削除、テキストノードの変更を監視します。\n */\nimport Core from './core';\nimport EventDispatcher from './event_dispatcher';\nimport IntersectObserver from './intersect';\nimport Log from './log';\n\n/**\n * 監視対象の要素を管理するためのクラスです。\n */\nexport class Observer {\n private static _initialized = false;\n /**\n * 初期化メソッド。\n * ドキュメントのheadとbodyを監視対象として設定します。\n */\n public static async init() {\n if (Observer._initialized) {\n return;\n }\n Observer._initialized = true;\n const results = await Promise.allSettled([\n Core.scan(document.head),\n Core.scan(document.body),\n ]);\n const [headResult, bodyResult] = results;\n if (headResult.status !== 'fulfilled') {\n Log.error('[Haori]', 'Failed to build head fragment:', headResult.reason);\n }\n if (bodyResult.status !== 'fulfilled') {\n Log.error('[Haori]', 'Failed to build body fragment:', bodyResult.reason);\n }\n Observer.observe(document.head);\n Observer.observe(document.body);\n new EventDispatcher().start();\n IntersectObserver.syncTree(document.body);\n }\n\n /**\n * 指定された要素を監視します。\n *\n * @param root 監視対象の要素\n */\n public static observe(root: HTMLElement | Document) {\n const observer = new MutationObserver(async mutations => {\n for (const mutation of mutations) {\n try {\n switch (mutation.type) {\n case 'attributes': {\n // 属性の変更\n Log.info(\n '[Haori]',\n 'Attribute changed:',\n mutation.target,\n mutation.attributeName,\n );\n const element = mutation.target as HTMLElement;\n if (\n mutation.attributeName &&\n Core.isAliasedAttributeReflection(\n element,\n mutation.attributeName,\n )\n ) {\n break;\n }\n Core.setAttribute(\n element,\n mutation.attributeName!,\n element.getAttribute(mutation.attributeName!),\n );\n IntersectObserver.syncElement(element);\n break;\n }\n case 'childList': {\n // ノードの追加・削除\n Log.info(\n '[Haori]',\n 'Child list changed:',\n Array.from(mutation.removedNodes).map(node => node.nodeName),\n Array.from(mutation.addedNodes).map(node => node.nodeName),\n );\n Array.from(mutation.removedNodes).forEach(node => {\n IntersectObserver.cleanupTree(node);\n Core.removeNode(node);\n });\n Array.from(mutation.addedNodes).forEach(node => {\n if (!(node.parentElement instanceof HTMLElement)) {\n return;\n }\n Core.addNode(node.parentElement, node);\n IntersectObserver.syncTree(node);\n });\n break;\n }\n case 'characterData': {\n // テキストノードの変更\n Log.info(\n '[Haori]',\n 'Character data changed:',\n mutation.target,\n mutation.target.textContent,\n );\n if (\n mutation.target instanceof Text ||\n mutation.target instanceof Comment\n ) {\n Core.changeText(mutation.target, mutation.target.textContent!);\n } else {\n Log.warn(\n '[Haori]',\n 'Unsupported character data type:',\n mutation.target,\n );\n }\n break;\n }\n default:\n Log.warn('[Haori]', 'Unknown mutation type:', mutation.type);\n continue;\n }\n } catch (error) {\n Log.error('[Haori]', 'Error processing mutation:', error);\n }\n }\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n Log.info('[Haori]', 'Observer initialized for', root);\n }\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', Observer.init);\n} else {\n Observer.init();\n}\n","/**\n * @fileoverview Haori-js メインエントリーポイント\n *\n * Haori-jsライブラリのすべての機能を提供するメインファイルです。\n */\n\nimport Core from './core';\nimport Env from './env';\nimport Fragment from './fragment';\nimport Form from './form';\nimport Haori from './haori';\nimport Log from './log';\nimport Queue from './queue';\n// ブラウザ運用時の監視・自動起動(本番動作)は observer モジュールが担います\nimport './observer';\n\n// メインクラスとユーティリティをエクスポート\nexport {Core, Env, Fragment, Form, Haori, Log, Queue};\nexport type {HaoriRuntime} from './env';\n\n// デフォルトエクスポート(Haoriをメインとして提供)\nexport default Haori;\n\n// バージョン情報\nexport const version = '0.4.6';\n"],"names":["_Dev","enabled","Dev","DEFAULT_RUNTIME","isHaoriRuntime","runtime","resolveRuntimeAttribute","_Env","currentScript","prefix","host","Env","Log","message","args","AsyncQueue","task","prepend","resolve","reject","promise","res","rej","item","start","result","error","promises","_Queue","Queue","Haori","level","toast","element","target","recipient","parent","FORM_HAORI_METHOD_NAMES","resolveFormHaoriApi","candidate","methodName","Form","form","values","fragment","name","objectName","listName","child","childValues","childList","force","value","emitEvents","index","detach","children","i","next","Core","tasks","removeClones","f","isBefore","isAfter","processChildren","key","activeHaori","addMsgFn","doAdd","targetFragments","targetFragment","parts","results","firstPoint","lastPoint","rawKey","indexString","rows","_Expression","scope","candidates","bindKeys","bindKeySet","expression","bindedValues","cacheKey","evaluator","assignments","body","argValues","wrappedValues","pattern","tokens","groups","previous","token","activeGroup","beforePrevious","thirdPrevious","group","operators","singleCharacters","current","stringToken","operator","numberToken","identifierToken","quote","literal","_","code","escaped","cache","cachedValue","proxy","currentTarget","property","receiver","thisArg","argArray","newTarget","prototype","callback","originals","descriptor","obj","seen","forbidden","Expression","_Fragment","node","ElementFragment","TextFragment","CommentFragment","prevSkip","mounted","unmount","Fragment","contents","AttributeContents","childFragment","clone","childClone","data","template","dispatchEvents","isBooleanCheckbox","newChecked","rawName","targetName","syncValueProperty","string","TextContents","referenceChild","insertAfter","referenceNode","insertionReferenceNode","nextTrackedNode","childIndex","newChild","referenceNodeOverride","ancestors","ancestor","isSameParent","newChildIndex","referenceIndex","newChildParent","insertionPoint","siblings","text","_TextContents","matches","lastIndex","hasEvaluate","hasRawEvaluate","match","content","c","bindingValues","_AttributeContents","HaoriEvent","eventName","detail","options","event","version","url","bytes","startedAt","reason","changedKeys","prevKeys","nextKeys","allKeys","prevValue","nextValue","added","removed","order","from","to","payload","metadata","status","PROCEDURE_HAORI_METHOD_NAMES","PROCEDURE_HISTORY_STATE_KEY","resolveProcedureHaoriApi","QUERY_TRANSPORT_METHODS","isQueryTransportMethod","method","appendPayloadToSearchParams","params","appendPayloadToUrl","fetchUrl","_Procedure","hasFetchFallback","rawAttribute","_matched","rawExpression","source","offset","inString","char","attrName","dataAttribute","trimmed","formSelector","formElement","e","fetchAttrName","hasFetchAttr","fetchOptions","fetchMethodAttrEvent","fetchMethodAttrNonEvent","fetchHeadersAttrEvent","headersString","fetchHeadersAttrNonEvent","fetchCTAttrEvent","hasContentType","fetchCTAttrNonEvent","bindAttr","bindSelector","bindElements","bindArgAttrEvent","bindArgAttrNonEventLegacy","bindArgAttrNonEventNew","bindParamsAttr","paramsString","p","bindAppendAttr","copyParamsAttr","param","adjustSelector","adjustElements","valueString","rawLevel","isValidLevel","historyFormSelector","historyFormElement","attrKey","selector","list","el","frag","arg1","arg2","formValues","hasPayload","finalOptions","headers","requestedMethod","isDemoQueryNormalization","contentType","formData","k","v","queryString","fetchStartMetadata","response","formFragment","bindingData","merged","deferredPromises","hasHistoryUrl","hasHistoryData","hasHistoryForm","baseUrlString","errorMessage","appendParams","baseFragment","addGeneralMessage","targetEl","scrollToFirstError","root","entries","m","firstInvalid","found","newData","bindArg","currentValue","currentObject","resolvedData","currentData","incoming","existing","sourceData","copyData","filtered","adjustValue","rowFragment","newFragment","prevFragment","nextFragment","Procedure","Url","Import","init","doc","_Core","suffix","aliasPrefix","chain","rawValue","attributeChain","processedAttributes","childPromises","aliasedAttributeName","html","arg","parentElement","condition","templateTarget","newList","indexKey","keyArg","itemArg","keyDataMap","newKeys","itemIndex","listKey","removalPromises","childElements","srcKeys","baseInsertIndex","newKey","loopIndex","srcIndex","currentInsertIndex","validNewKeys","validSrcKeys","addedKeys","removedKeys","_EventDispatcher","state","type","EventDispatcher","_IntersectObserver","registration","nextRoot","nextRootMargin","nextThreshold","nextOnce","observer","entry","success","latest","threshold","stringValue","thresholds","IntersectObserver","_Observer","headResult","bodyResult","mutations","mutation","Observer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"haori.cjs.js","sources":["../src/dev.ts","../src/env.ts","../src/log.ts","../src/queue.ts","../src/haori.ts","../src/form.ts","../src/expression.ts","../src/fragment.ts","../src/event.ts","../src/procedure.ts","../src/url.ts","../src/import.ts","../src/core.ts","../src/event_dispatcher.ts","../src/intersect.ts","../src/observer.ts","../src/index.ts"],"sourcesContent":["/**\n * @fileoverview Haori開発モード管理機能\n *\n * 開発モードの有効/無効を管理し、デバッグ機能の制御を行います。\n * プロダクション環境では開発向け機能を無効化することで、\n * パフォーマンスとセキュリティを向上させます。\n */\n\n/**\n * 開発モード管理クラスです。\n */\nexport default class Dev {\n /** 開発モードフラグ */\n private static devMode = false;\n\n /**\n * 開発モードの状態を取得します。\n *\n * @returns 開発モードならtrue、そうでなければfalse\n */\n static isEnabled(): boolean {\n return Dev.devMode;\n }\n\n /**\n * 開発モードを有効化します。\n */\n static enable(): void {\n Dev.devMode = true;\n }\n\n /**\n * 開発モードを無効化します。\n */\n static disable(): void {\n Dev.devMode = false;\n }\n\n /**\n * 開発モードを切り替えます。\n *\n * @param enabled trueで有効化、falseで無効化\n */\n static set(enabled: boolean): void {\n Dev.devMode = enabled;\n }\n}\n","/**\n * @fileoverview Haori環境検出機能\n *\n * 実行環境を管理します。\n */\n\nimport Dev from './dev';\n\n/**\n * Haori.js の実行モードを表します。\n */\nexport type HaoriRuntime = 'embedded' | 'demo';\n\nconst DEFAULT_RUNTIME: HaoriRuntime = 'embedded';\n\n/**\n * 指定文字列が有効な実行モードかどうかを判定します。\n *\n * @param runtime 判定対象の文字列。\n * @return 有効な実行モードなら true。\n */\nfunction isHaoriRuntime(runtime: string): runtime is HaoriRuntime {\n return runtime === 'embedded' || runtime === 'demo';\n}\n\n/**\n * data-runtime 属性値を実行モードへ正規化します。\n *\n * @param runtime 属性から取得した値。\n * @return 有効な実行モード。属性が未設定なら null、無効値なら embedded。\n */\nfunction resolveRuntimeAttribute(runtime: string | null): HaoriRuntime | null {\n if (runtime === null) {\n return null;\n }\n\n return isHaoriRuntime(runtime) ? runtime : DEFAULT_RUNTIME;\n}\n\n/**\n * 実行環境を管理するクラスです。\n */\nexport default class Env {\n private static _prefix: string = 'data-';\n private static _runtime: HaoriRuntime = DEFAULT_RUNTIME;\n\n /**\n * 実行モードを取得します。\n *\n * @returns 実行モード。\n */\n public static get runtime(): HaoriRuntime {\n return Env._runtime;\n }\n\n /**\n * 実行モードを設定します。\n *\n * @param runtime 設定する実行モード。\n * @return 戻り値はありません。\n */\n public static setRuntime(runtime: string): void {\n Env._runtime = isHaoriRuntime(runtime) ? runtime : DEFAULT_RUNTIME;\n }\n\n /**\n * 実行環境からプレフィックスと開発モードかどうかを自動検出します。\n * scriptタグにdata-prefixがある場合は、その値+\"-\"をプレフィックスとして使用します。\n * scriptタグにdata-dev属性がある場合、\n * もしくはローカルホスト系ドメインであれば開発モードを有効化します。\n */\n static detect(): void {\n try {\n const currentScript =\n document.currentScript ||\n document.querySelector('script[src*=\"haori\"]');\n if (currentScript instanceof HTMLScriptElement) {\n const prefix = currentScript.getAttribute('data-prefix') || Env._prefix;\n Env._prefix = prefix.endsWith('-') ? prefix : prefix + '-';\n\n const runtime = resolveRuntimeAttribute(\n currentScript.getAttribute('data-runtime'),\n );\n if (runtime !== null) {\n Env._runtime = runtime;\n }\n }\n if (\n currentScript instanceof HTMLScriptElement &&\n currentScript.hasAttribute(`${Env._prefix}dev`)\n ) {\n Dev.set(true);\n return;\n }\n\n // ローカルホスト系ドメインの場合\n const host = window.location.hostname;\n if (\n host === 'localhost' ||\n host.endsWith('.localhost') ||\n host === '127.0.0.1' ||\n host === '::1' ||\n host.endsWith('.local')\n ) {\n Dev.set(true);\n return;\n }\n\n // それ以外は開発モードを無効化\n Dev.set(false);\n } catch {\n // SSRや非ブラウザ環境では無視\n }\n }\n\n /**\n * プレフィックスを取得します。\n *\n * @returns プレフィックス\n */\n public static get prefix(): string {\n return Env._prefix;\n }\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', Env.detect);\n} else {\n Env.detect();\n}\n","/**\n * @fileoverview Haori共通ログ機能\n *\n * 開発モード時のみログ出力を行います。\n */\n\nimport Dev from './dev';\n\n/**\n * ログ出力を管理するクラス\n */\nexport default class Log {\n /**\n * 開発モードでのみコンソールに情報を出力します。\n *\n * @param message 出力するメッセージ\n * @param args 追加の引数\n */\n static info(message: string, ...args: unknown[]): void {\n if (Dev.isEnabled() && console.log) {\n console.log(message, ...args);\n }\n }\n\n /**\n * 開発モードでのみコンソールに警告を出力します。\n *\n * @param message 出力するメッセージ\n * @param args 追加の引数\n */\n static warn(message: string, ...args: unknown[]): void {\n if (Dev.isEnabled() && console.warn) {\n console.warn(message, ...args);\n }\n }\n\n /**\n * モードに関係なくコンソールにエラーを出力します。\n *\n * @param message 出力するメッセージ\n * @param args 追加の引数\n */\n static error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","/**\n * @fileoverview 汎用非同期キュー機能\n *\n * 任意の処理を非同期でキューイングし、requestAnimationFrameを使用して順次実行します。\n * 各処理はPromiseを返し、完了時の処理を記述できます。\n * DOM操作などの非同期処理に適しています。\n */\n\nimport Log from './log';\n\n/**\n * キューアイテムの基本構造。\n */\ninterface QueueItem {\n /** 実行する処理 */\n task: () => unknown | Promise<unknown>;\n\n /** 作成時刻 */\n timestamp: number;\n\n /** 完了Promise */\n promise: Promise<unknown>;\n\n /** Promise解決用の関数 */\n resolve: (value: unknown | PromiseLike<unknown>) => void;\n\n /** Promise拒否用の関数 */\n reject: (reason?: unknown) => void;\n}\n\n/**\n * 非同期キュークラス。\n * キュー内の処理を管理し、順次実行します。\n */\nclass AsyncQueue {\n private readonly MAX_BUDGET = 8; // 1フレームあたりの最大処理時間(ms)\n\n /** キュー内の処理 */\n private readonly queue: QueueItem[] = [];\n\n /** 処理中フラグ */\n private processing = false;\n\n /**\n * 処理をキューに追加します\n *\n * @param task 実行する処理\n * @param prepend trueの場合はキューの先頭に追加、falseの場合は末尾に追加\n * @returns 処理完了Promise\n */\n public enqueue(\n task: () => unknown,\n prepend: boolean = false,\n ): Promise<unknown> {\n let resolve: (value: unknown | PromiseLike<unknown>) => void;\n let reject: (reason?: unknown) => void;\n const promise = new Promise<unknown>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem = {\n task,\n timestamp: performance.now(),\n promise,\n resolve: resolve!,\n reject: reject!,\n };\n if (prepend) {\n this.queue.unshift(item);\n } else {\n this.queue.push(item);\n }\n this.scheduleProcessing();\n return promise;\n }\n\n /**\n * キューを処理します。\n *\n * @returns 処理完了Promise\n */\n private async processQueue(): Promise<void> {\n if (this.processing || this.queue.length === 0) {\n return;\n }\n this.processing = true;\n try {\n const start = performance.now();\n while (this.queue.length > 0) {\n const item = this.queue.shift();\n if (!item) {\n return;\n }\n try {\n const result = await item.task();\n item.resolve(result);\n } catch (error) {\n item.reject(error);\n Log.error('[Haori]', `Task ${item.timestamp} failed:`, error);\n }\n if (performance.now() - start > this.MAX_BUDGET) {\n // 1フレームの処理時間を超えたら一旦終了\n break;\n }\n }\n } catch (error) {\n Log.error('[Haori]', 'Error processing queue:', error);\n } finally {\n this.processing = false;\n if (this.queue.length > 0) {\n this.scheduleProcessing();\n }\n }\n }\n\n /**\n * 処理をスケジュールします。\n */\n private scheduleProcessing(): void {\n if (this.processing) {\n return;\n }\n if (typeof requestAnimationFrame !== 'undefined') {\n requestAnimationFrame(() => {\n this.processQueue();\n });\n } else {\n setTimeout(() => {\n this.processQueue();\n }, 16); // 60fps\n }\n }\n\n /**\n * キューが空になるまで待機します。\n *\n * @returns キューが空になったら解決されるPromise\n */\n public async wait(): Promise<void> {\n if (this.queue.length === 0 && !this.processing) {\n return;\n }\n const promises = this.queue.map(item => item.promise);\n if (promises.length > 0) {\n await Promise.allSettled(promises);\n }\n }\n}\n\n/**\n * 非同期キューのデフォルトインスタンス。\n * このインスタンスを使用して、アプリケーション全体でタスクをキューイングできます。\n */\nexport default class Queue {\n /** 非同期キューインスタンス */\n private static readonly ASYNC_QUEUE = new AsyncQueue();\n\n /**\n * タスクをキューに追加します。\n *\n * @param task 実行する処理\n * @param prepend trueの場合はキューの先頭に追加、falseの場合は末尾に追加\n * @returns 処理完了Promise\n */\n public static enqueue(\n task: () => unknown,\n prepend: boolean = false,\n ): Promise<unknown> {\n return this.ASYNC_QUEUE.enqueue(task, prepend);\n }\n\n /**\n * 全てのキュー処理が完了するまで待機します。\n */\n public static wait(): Promise<void> {\n return this.ASYNC_QUEUE.wait();\n }\n}\n","import Log from './log';\nimport Env from './env';\nimport Queue from './queue';\n\n/**\n * Haoriクラスは、アプリケーション全体で使用されるユーティリティメソッドを提供します。\n * 挙動を変更する場合は必要に応じてオーバライドしてください。\n */\nexport default class Haori {\n /**\n * 実行モードを取得します。\n *\n * @return 実行モード。\n */\n public static get runtime(): 'embedded' | 'demo' {\n return Env.runtime;\n }\n\n /**\n * 実行モードを設定します。\n *\n * @param runtime 設定する実行モード。\n * @return 戻り値はありません。\n */\n public static setRuntime(runtime: string): void {\n Env.setRuntime(runtime);\n }\n\n /**\n * 通知ダイアログを表示します。\n *\n * @param message 表示メッセージ\n * @returns 通知が閉じられると解決されるPromise\n */\n public static dialog(message: string): Promise<void> {\n return Queue.enqueue(() => {\n window.alert(message);\n }, true) as Promise<void>;\n }\n\n /**\n * 通知トーストを表示します。\n *\n * @param message 表示メッセージ\n * @param level メッセージのレベル(省略時は 'info')\n * @return 通知が表示されると解決されるPromise\n */\n public static async toast(\n message: string,\n level: 'info' | 'warning' | 'error' | 'success' = 'info',\n ): Promise<void> {\n const toast = document.createElement('div');\n toast.className = `haori-toast haori-toast-${level}`;\n toast.textContent = message;\n toast.setAttribute('popover', 'manual');\n toast.setAttribute('role', 'status');\n toast.setAttribute('aria-live', level === 'error' ? 'assertive' : 'polite');\n document.body.appendChild(toast);\n toast.showPopover();\n setTimeout(() => {\n try {\n toast.hidePopover();\n } finally {\n toast.remove();\n }\n }, 3000);\n }\n\n /**\n * 確認ダイアログを表示します。\n *\n * @param message 確認メッセージ\n * @returns ユーザーがOKをクリックした場合はtrue、キャンセルした場合はfalseが解決されるPromise\n */\n public static confirm(message: string): Promise<boolean> {\n return Queue.enqueue(() => {\n return window.confirm(message);\n }, true) as Promise<boolean>;\n }\n\n /**\n * ダイアログを開きます。\n *\n * @param element 開くダイアログのHTML要素\n */\n public static openDialog(element: HTMLElement): Promise<void> {\n return Queue.enqueue(() => {\n if (element instanceof HTMLDialogElement) {\n element.showModal();\n } else {\n Log.error('[Haori]', 'Element is not a dialog: ', element);\n }\n }, true) as Promise<void>;\n }\n\n /**\n * ダイアログを閉じます。\n *\n * @param element 閉じるダイアログのHTML要素\n */\n public static closeDialog(element: HTMLElement): Promise<void> {\n return Queue.enqueue(() => {\n if (element instanceof HTMLDialogElement) {\n element.close();\n } else {\n Log.error('[Haori]', 'Element is not a dialog: ', element);\n }\n }, true) as Promise<void>;\n }\n\n /**\n * エラーメッセージを追加します。\n *\n * @param target メッセージを表示する要素\n * @param message エラーメッセージ\n */\n public static addErrorMessage(\n target: HTMLElement | HTMLFormElement,\n message: string,\n ): Promise<void> {\n return Haori.addMessage(target, message, 'error');\n }\n\n /**\n * メッセージをレベル付きで追加します。\n *\n * @param target メッセージを表示する要素\n * @param message メッセージ\n * @param level メッセージのレベル(省略可能)\n */\n public static addMessage(\n target: HTMLElement | HTMLFormElement,\n message: string,\n level?: 'info' | 'warning' | 'error' | 'success',\n ): Promise<void> {\n return Queue.enqueue(() => {\n // 仕様: 入力要素の場合は親要素に、フォーム要素の場合はフォーム自身に data-message を付与する。\n const recipient =\n target instanceof HTMLFormElement\n ? target\n : (target.parentElement ?? target);\n recipient.setAttribute('data-message', message);\n if (level !== undefined) {\n recipient.setAttribute('data-message-level', level);\n } else {\n recipient.removeAttribute('data-message-level');\n }\n }, true) as Promise<void>;\n }\n\n /**\n * 対象のエレメントおよびその子要素のメッセージをクリアします。\n *\n * @param parent メッセージをクリアする親要素\n */\n public static clearMessages(parent: HTMLElement): Promise<void> {\n return Queue.enqueue(() => {\n parent.removeAttribute('data-message');\n parent.removeAttribute('data-message-level');\n parent.querySelectorAll('[data-message]').forEach(element => {\n element.removeAttribute('data-message');\n element.removeAttribute('data-message-level');\n });\n }, true) as Promise<void>;\n }\n}\n","/**\n * @fileoverview フォーム双方向バインディング\n *\n * フォームと入力要素の双方向バインディングを実現します。\n */\n\nimport Core from './core';\nimport Env from './env';\nimport {ElementFragment} from './fragment';\nimport Haori from './haori';\nimport Log from './log';\nimport Queue from './queue';\n\ntype FormHaoriApi = Pick<typeof Haori, 'addErrorMessage' | 'clearMessages'>;\n\nconst FORM_HAORI_METHOD_NAMES = ['addErrorMessage', 'clearMessages'] as const;\n\n/**\n * Form から利用する Haori API を解決します。\n * window.Haori が差し替えられている場合はそちらを優先します。\n *\n * @returns Form が使用する Haori API。\n */\nfunction resolveFormHaoriApi(): FormHaoriApi {\n const scope = globalThis as typeof globalThis & {\n window?: Window & {Haori?: unknown};\n };\n const candidate = scope.window?.Haori;\n const hasRequiredMethods = FORM_HAORI_METHOD_NAMES.every(\n methodName =>\n typeof (candidate as Record<string, unknown> | undefined)?.[\n methodName\n ] === 'function',\n );\n return hasRequiredMethods ? (candidate as FormHaoriApi) : Haori;\n}\n\n/**\n * Formクラスは、フォームの双方向バインディングを提供します。\n * 入力要素の値をフォームにバインドし、フォームのバインド値を入力要素に反映します。\n */\nexport default class Form {\n /**\n * フォーム内にある入力エレメントの値をオブジェクトとして取得します。\n * data-form-object属性があると、そのエレメント内の値はオブジェクトとして処理されます。\n * 入力エレメントにdata-form-list属性があると、そのエレメントの値はリストとして処理されます。\n * 入力エレメント以外にdata-form-list属性があると、そのエレメントの値はオブジェクトのリストとして処理されます。\n *\n * @param form フォームのElementFragment\n */\n public static getValues(form: ElementFragment): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n return Form.getPartValues(form, values);\n }\n\n /**\n * フォーム内の各入力エレメントから値を取得し、オブジェクトとして返します。\n * 入力エレメントのname属性、data-form-object属性、data-form-list属性に基づいて値を整理します。\n *\n * @param fragment 対象のElementFragment\n * @param values オブジェクトに追加する値のオブジェクト\n * @returns values と同じオブジェクト\n */\n private static getPartValues(\n fragment: ElementFragment,\n values: Record<string, unknown>,\n ): Record<string, unknown> {\n const name = fragment.getAttribute('name');\n const objectName = fragment.getAttribute(`${Env.prefix}form-object`);\n const listName = fragment.getAttribute(`${Env.prefix}form-list`);\n if (name) {\n if (listName) {\n if (Array.isArray(values[String(name)])) {\n (values[String(name)] as unknown[]).push(fragment.getValue());\n } else {\n values[String(name)] = [fragment.getValue()];\n }\n } else {\n values[String(name)] = fragment.getValue();\n }\n if (objectName) {\n Log.warn(\n 'Haori',\n `Element cannot have both ${Env.prefix}form-object` +\n ' and name attributes.',\n );\n }\n for (const child of fragment.getChildElementFragments()) {\n Form.getPartValues(child, values);\n }\n } else if (objectName) {\n const childValues: Record<string, unknown> = {};\n for (const child of fragment.getChildElementFragments()) {\n Form.getPartValues(child, childValues);\n }\n if (Object.keys(childValues).length > 0) {\n values[String(objectName)] = childValues;\n }\n if (listName) {\n Log.warn(\n 'Haori',\n `Element cannot have both ${Env.prefix}form-list` +\n ` and ${Env.prefix}form-object attributes.`,\n );\n }\n } else if (listName) {\n const childList: Record<string, unknown>[] = [];\n for (const child of fragment.getChildElementFragments()) {\n const childValues: Record<string, unknown> = {};\n Form.getPartValues(child, childValues);\n if (Object.keys(childValues).length > 0) {\n childList.push(childValues);\n }\n }\n if (childList.length > 0) {\n values[String(listName)] = childList;\n }\n } else {\n for (const child of fragment.getChildElementFragments()) {\n Form.getPartValues(child, values);\n }\n }\n return values;\n }\n\n /**\n * フォーム内にある入力エレメントに値を設定します。\n * フォームのdata-bind属性に値が反映されます。\n *\n * @param form フォームのElementFragment\n * @param values フォームに設定する値のオブジェクト\n * @param force data-form-detach属性があるエレメントにも値を反映するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n public static setValues(\n form: ElementFragment,\n values: Record<string, unknown>,\n force: boolean = false,\n ): Promise<void> {\n return Form.setPartValues(form, values, null, force, true);\n }\n\n /**\n * フォーム内にある入力エレメントに値をイベントなしで設定します。\n * フォーム bindingData からの内部同期に利用します。\n *\n * @param form フォームのElementFragment\n * @param values フォームに設定する値のオブジェクト\n * @param force data-form-detach属性があるエレメントにも値を反映するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n public static syncValues(\n form: ElementFragment,\n values: Record<string, unknown>,\n force: boolean = false,\n ): Promise<void> {\n return Form.setPartValues(form, values, null, force, false);\n }\n\n /**\n * 単一フラグメントへ値を設定します。\n *\n * @param fragment 対象フラグメント\n * @param value 設定する値\n * @param emitEvents input/change イベントを発火するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n private static applyFragmentValue(\n fragment: ElementFragment,\n value: string | number | boolean | null,\n emitEvents: boolean,\n ): Promise<void> {\n return emitEvents\n ? fragment.setValue(value)\n : fragment.syncBindingValue(value);\n }\n\n /**\n * フラグメント内にある各入力エレメントに値を設定します。\n *\n * @param fragment 対象フラグメント\n * @param values フラグメントに設定する値のオブジェクト\n * @param index 配列の場合のインデックス\n * @param force data-form-detach属性があるエレメントにも値を反映するかどうか\n * @returns Promise(DOMの更新が完了したら解決される)\n */\n private static setPartValues(\n fragment: ElementFragment,\n values: Record<string, unknown>,\n index: number | null = null,\n force: boolean = false,\n emitEvents: boolean = true,\n ): Promise<void> {\n const promises: Promise<void>[] = [];\n const name = fragment.getAttribute('name');\n const objectName = fragment.getAttribute(`${Env.prefix}form-object`);\n const listName = fragment.getAttribute(`${Env.prefix}form-list`);\n const detach = fragment.getAttribute(`${Env.prefix}form-detach`);\n if (name) {\n if (!detach || force) {\n const value = values[String(name)];\n if (listName && Array.isArray(value) && index !== null) {\n promises.push(\n Form.applyFragmentValue(fragment, value[index] ?? null, emitEvents),\n );\n } else if (typeof value === 'undefined') {\n // 未指定のキーは既存の入力値を維持する。\n } else if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value === null\n ) {\n promises.push(Form.applyFragmentValue(fragment, value, emitEvents));\n } else {\n promises.push(\n Form.applyFragmentValue(fragment, String(value), emitEvents),\n );\n }\n }\n } else if (objectName) {\n const childValues = values[String(objectName)];\n if (childValues && typeof childValues === 'object') {\n for (const child of fragment.getChildElementFragments()) {\n promises.push(\n Form.setPartValues(\n child,\n childValues as Record<string, unknown>,\n null,\n force,\n emitEvents,\n ),\n );\n }\n }\n } else if (listName) {\n const childList = values[String(listName)];\n if (Array.isArray(childList)) {\n const children = fragment.getChildElementFragments();\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (childList.length > i) {\n promises.push(\n Form.setPartValues(\n child,\n childList[i] as Record<string, unknown>,\n i,\n force,\n emitEvents,\n ),\n );\n } else {\n promises.push(Form.setPartValues(child, {}, i, force, emitEvents));\n }\n }\n }\n } else {\n for (const child of fragment.getChildElementFragments()) {\n promises.push(\n Form.setPartValues(child, values, null, force, emitEvents),\n );\n }\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 対象フラグメントとその子孫要素の値を初期化します。\n * 値の初期化とメッセージのクリアを行います。\n *\n * @param fragment 対象フラグメント\n * @returns すべての初期化処理が完了するPromise\n */\n public static async reset(fragment: ElementFragment): Promise<void> {\n // 値をクリア\n Form.clearValues(fragment);\n\n // メッセージをクリアし、data-eachの複製を削除\n await Promise.all([\n Form.clearMessages(fragment),\n Form.clearEachClones(fragment),\n ]);\n\n // フォーム要素をリセット\n await Queue.enqueue(() => {\n const element = fragment.getTarget();\n if (element instanceof HTMLFormElement) {\n element.reset();\n } else {\n const parent = element.parentElement;\n if (parent) {\n const next = element.nextElementSibling;\n const form = document.createElement('form');\n form.appendChild(element);\n form.reset();\n parent.insertBefore(element, next);\n }\n }\n });\n\n // 再評価\n await Core.evaluateAll(fragment);\n }\n\n /**\n * data-each によって生成された複製(テンプレート以外)を削除します。\n * 既存のテンプレートは保持し、その後の再評価で必要に応じて再生成されます。\n * 対象エレメント自体がdata-eachを持つ場合はその子の複製を削除しますが、\n * 対象エレメント自体は削除しません。\n */\n private static clearEachClones(fragment: ElementFragment): Promise<void> {\n const tasks: Promise<void>[] = [];\n\n const removeClones = (f: ElementFragment) => {\n if (f.hasAttribute(`${Env.prefix}each`)) {\n for (const child of f.getChildElementFragments()) {\n const isBefore = child.hasAttribute(`${Env.prefix}each-before`);\n const isAfter = child.hasAttribute(`${Env.prefix}each-after`);\n if (!isBefore && !isAfter) {\n tasks.push(child.remove());\n }\n }\n }\n };\n\n const processChildren = (f: ElementFragment) => {\n removeClones(f);\n for (const child of f.getChildElementFragments()) {\n processChildren(child);\n }\n };\n\n // 対象フラグメント自体のクローンを削除し、子エレメント以下を再帰処理\n removeClones(fragment);\n for (const child of fragment.getChildElementFragments()) {\n processChildren(child);\n }\n\n return Promise.all(tasks).then(() => undefined);\n }\n\n /**\n * 再帰的に値を初期化します。\n *\n * @param fragment 対象フラグメント\n */\n private static clearValues(fragment: ElementFragment): void {\n fragment.clearValue();\n for (const child of fragment.getChildElementFragments()) {\n Form.clearValues(child);\n }\n }\n\n /**\n * フラグメントとその子要素のメッセージをクリアします。\n *\n * @param fragment 対象フラグメント\n * @returns Promise(メッセージのクリアが完了したら解決される)\n */\n public static clearMessages(fragment: ElementFragment): Promise<void> {\n return resolveFormHaoriApi().clearMessages(\n fragment.getTarget(),\n ) as Promise<void>;\n }\n\n /**\n * キーに一致するフラグメントにエラーメッセージを追加します。\n * キーに一致するフラグメントが見つからない場合は、指定されたフラグメントにメッセージを追加します。\n *\n * @param fragment 対象フラグメント\n * @param key キー(ドット区切りの文字列)\n * @param message 追加するエラーメッセージ\n * @return Promise(メッセージの追加が完了したら解決される)\n */\n public static addErrorMessage(\n fragment: ElementFragment,\n key: string,\n message: string,\n ): Promise<void> {\n return Form.addMessage(fragment, key, message, 'error');\n }\n\n /**\n * キーに一致するフラグメントにレベル付きメッセージを追加します。\n * キーに一致するフラグメントが見つからない場合は、指定されたフラグメントにメッセージを追加します。\n *\n * @param fragment 対象フラグメント\n * @param key キー(ドット区切りの文字列)\n * @param message 追加するメッセージ\n * @param level メッセージのレベル(省略可能)\n * @return Promise(メッセージの追加が完了したら解決される)\n */\n public static addMessage(\n fragment: ElementFragment,\n key: string,\n message: string,\n level?: 'info' | 'warning' | 'error' | 'success',\n ): Promise<void> {\n const promises: Promise<void>[] = [];\n const activeHaori = resolveFormHaoriApi();\n const addMsgFn = (\n activeHaori as {addMessage?: typeof Haori.addMessage}\n ).addMessage;\n const doAdd = (target: HTMLElement): Promise<void> =>\n typeof addMsgFn === 'function'\n ? (addMsgFn.call(activeHaori, target, message, level) as Promise<void>)\n : (activeHaori.addErrorMessage(target, message) as Promise<void>);\n\n const targetFragments = Form.findFragmentsByKey(fragment, key);\n targetFragments.forEach(targetFragment => {\n promises.push(doAdd(targetFragment.getTarget() as HTMLElement));\n });\n if (targetFragments.length === 0) {\n promises.push(doAdd(fragment.getTarget() as HTMLElement));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 指定されたキーに一致するフラグメントを検索します。\n *\n * @param fragment 対象フラグメント\n * @param key キー(ドット区切りの文字列)\n * @returns 一致するフラグメントの配列\n */\n public static findFragmentsByKey(\n fragment: ElementFragment,\n key: string,\n ): ElementFragment[] {\n return Form.findFragmentByKeyParts(fragment, key.split('.'));\n }\n\n /**\n * 指定されたキーに一致するフラグメントを検索します。\n * data-form-list属性で指定された場合はdata-row属性を持つ子要素の位置と添字が一致するものを対象とします。\n *\n * @param fragment 対象フラグメント\n * @param parts キーのパーツ\n * @returns 一致するフラグメントの配列\n */\n private static findFragmentByKeyParts(\n fragment: ElementFragment,\n parts: string[],\n ): ElementFragment[] {\n const results: ElementFragment[] = [];\n const key = parts[0];\n if (parts.length == 1) {\n const name = fragment.getAttribute('name');\n if (name === key) {\n results.push(fragment);\n }\n }\n if (fragment.hasAttribute(`${Env.prefix}form-object`)) {\n if (parts.length > 1) {\n const objectName = fragment.getAttribute(`${Env.prefix}form-object`);\n if (objectName === key) {\n fragment.getChildElementFragments().forEach(child => {\n results.push(...Form.findFragmentByKeyParts(child, parts.slice(1)));\n });\n }\n }\n } else if (fragment.hasAttribute(`${Env.prefix}form-list`)) {\n if (parts.length > 1) {\n const listName = fragment.getAttribute(`${Env.prefix}form-list`);\n const firstPoint = key.lastIndexOf('[');\n const lastPoint = key.lastIndexOf(']');\n if (firstPoint !== -1 && lastPoint !== -1 && firstPoint < lastPoint) {\n const rawKey = key.substring(0, firstPoint);\n if (listName === rawKey) {\n const indexString = key.substring(firstPoint + 1, lastPoint);\n const index = Number(indexString);\n if (isNaN(index)) {\n Log.error('Haori', `Invalid index: ${key}`);\n } else {\n const rows = fragment\n .getChildElementFragments()\n .filter(child => child.hasAttribute(`${Env.prefix}row`));\n if (index < rows.length) {\n results.push(\n ...Form.findFragmentByKeyParts(rows[index], parts.slice(1)),\n );\n }\n }\n }\n }\n }\n } else {\n fragment.getChildElementFragments().forEach(child => {\n results.push(...Form.findFragmentByKeyParts(child, parts));\n });\n }\n return results;\n }\n\n /**\n * 対象のフラグメントがフォームフラグメントであればそれを返し、\n * そうでなければ先祖要素をたどってフォームフラグメントを探します。\n *\n * @param fragment\n */\n public static getFormFragment(\n fragment: ElementFragment,\n ): ElementFragment | null {\n const element = fragment.getTarget();\n if (element instanceof HTMLFormElement) {\n return fragment;\n }\n const parent = fragment.getParent();\n if (parent) {\n return this.getFormFragment(parent);\n }\n return null;\n }\n}\n","/**\n * @fileoverview 式評価エンジン\n *\n * 式評価システムです。\n * XSS攻撃やコードインジェクションを防ぐためのセキュリティ機能と、\n * パフォーマンス向上のためのキャッシュ機能を提供します。\n */\n\nimport Log from './log';\n\ntype ExpressionTokenType = 'identifier' | 'number' | 'string' | 'operator';\n\ninterface ExpressionToken {\n type: ExpressionTokenType;\n value: string;\n position: number;\n}\n\ntype GroupContext = 'paren' | 'array' | 'member' | 'object';\n\nexport default class Expression {\n /** Haoriで禁止すべき識別子一覧(eval と arguments は strict モードで無効化) */\n private static readonly FORBIDDEN_NAMES = [\n // グローバルオブジェクト\n 'window',\n 'self',\n 'globalThis',\n 'frames',\n 'parent',\n 'top',\n // 危険な関数/オブジェクト\n 'Function',\n 'setTimeout',\n 'setInterval',\n 'requestAnimationFrame',\n 'alert',\n 'confirm',\n 'prompt',\n 'fetch',\n 'XMLHttpRequest',\n 'Reflect',\n // 脱出経路・プロトタイプ\n 'constructor',\n '__proto__',\n 'prototype',\n 'Object',\n // その他\n 'document',\n 'location',\n 'navigator',\n 'localStorage',\n 'sessionStorage',\n 'IndexedDB',\n 'history',\n ];\n\n /** strict モードで禁止される識別子 */\n private static readonly STRICT_FORBIDDEN_NAMES = ['eval', 'arguments'];\n\n /** 明示バインド時のみ利用を許可する衝突名 */\n private static readonly REBINDABLE_FORBIDDEN_NAMES = new Set(['location']);\n\n /** バインド識別子としては拒否する名前 */\n private static readonly FORBIDDEN_BINDING_NAMES = new Set([\n ...Expression.FORBIDDEN_NAMES.filter(\n name => !Expression.REBINDABLE_FORBIDDEN_NAMES.has(name),\n ),\n 'constructor',\n '__proto__',\n 'prototype',\n ...Expression.STRICT_FORBIDDEN_NAMES,\n ]);\n\n /**\n * 明示バインド内に持ち込まれてはならない危険値を返します。\n *\n * @returns 危険値の配列\n */\n private static getForbiddenBindingValues(): unknown[] {\n const scope = globalThis as typeof globalThis & {\n window?: Window;\n document?: Document;\n navigator?: Navigator;\n history?: History;\n localStorage?: Storage;\n sessionStorage?: Storage;\n fetch?: typeof fetch;\n };\n const candidates: unknown[] = [\n scope,\n scope.window,\n scope.document,\n scope.navigator,\n scope.history,\n scope.localStorage,\n scope.sessionStorage,\n scope.fetch,\n scope.Function,\n scope.setTimeout,\n scope.setInterval,\n scope.requestAnimationFrame,\n scope.alert,\n scope.confirm,\n scope.prompt,\n ];\n if (scope.window?.location) {\n candidates.push(scope.window.location);\n }\n return candidates.filter(value => value !== undefined && value !== null);\n }\n\n /** プロパティアクセスで拒否する名前 */\n private static readonly FORBIDDEN_PROPERTY_NAMES = new Set([\n 'constructor',\n '__proto__',\n 'prototype',\n ]);\n\n /** object literal のプロパティ定義で前置修飾子として扱う識別子 */\n private static readonly OBJECT_PROPERTY_MODIFIERS = new Set([\n 'get',\n 'set',\n 'async',\n ]);\n\n /** 式構文として許可しない予約語 */\n private static readonly DISALLOWED_KEYWORDS = new Set([\n 'await',\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'export',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'import',\n 'in',\n 'instanceof',\n 'let',\n 'new',\n 'return',\n 'switch',\n 'this',\n 'throw',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n ]);\n\n /** 式 → 評価関数のグローバルキャッシュ */\n private static readonly EXPRESSION_CACHE = new Map<\n string,\n (...args: unknown[]) => unknown\n >();\n\n /**\n * 現在のバインド識別子に含まれない禁止グローバルを遮断するコードを生成します。\n *\n * @param bindKeys 現在の式で利用するバインド識別子一覧\n * @returns 評価前に挿入する初期化コード\n */\n private static buildAssignments(bindKeys: string[]): string {\n const bindKeySet = new Set(bindKeys);\n return this.FORBIDDEN_NAMES.filter(name => !bindKeySet.has(name))\n .map(name => `const ${name} = undefined`)\n .join(';\\n');\n }\n\n /**\n * 式を評価します。\n *\n * @param expression 評価する式文字列\n * @param bindedValue バインドされた値のオブジェクト\n */\n public static evaluate(\n expression: string,\n bindedValues: Record<string, unknown> = {},\n ): unknown {\n if (expression.trim() === '') {\n Log.warn('[Haori]', expression, 'Expression is empty');\n return null;\n }\n if (this.containsDangerousPatterns(expression)) {\n Log.warn('[Haori]', expression, 'Expression contains dangerous patterns');\n return null;\n }\n if (this.containsForbiddenKeys(bindedValues)) {\n Log.warn('[Haori]', bindedValues, 'Binded values contain forbidden keys');\n return null;\n }\n if (this.containsForbiddenBindingValues(bindedValues)) {\n Log.warn(\n '[Haori]',\n bindedValues,\n 'Binded values contain forbidden values',\n );\n return null;\n }\n\n const bindKeys = Object.keys(bindedValues)\n .filter(key => !this.FORBIDDEN_BINDING_NAMES.has(key))\n .sort();\n const cacheKey = `${expression}:${bindKeys.join(',')}`;\n\n let evaluator = this.EXPRESSION_CACHE.get(cacheKey);\n if (!evaluator) {\n const assignments = this.buildAssignments(bindKeys);\n const body = assignments\n ? '\"use strict\";\\n' + `${assignments};\\nreturn (${expression});`\n : '\"use strict\";\\n' + `return (${expression});`;\n try {\n evaluator = new Function(...bindKeys, body) as (\n ...args: unknown[]\n ) => unknown;\n this.EXPRESSION_CACHE.set(cacheKey, evaluator);\n } catch (error) {\n Log.error(\n '[Haori]',\n 'Failed to compile expression:',\n expression,\n error,\n );\n return null;\n }\n }\n try {\n const argValues: unknown[] = [];\n const wrappedValues = this.wrapBoundValues(bindedValues);\n bindKeys.forEach((key: string) => {\n argValues.push(wrappedValues[key]);\n });\n return this.withBlockedPropertyAccess(() => evaluator(...argValues));\n } catch (error) {\n Log.error('[Haori]', 'Expression evaluation error:', expression, error);\n if (error instanceof ReferenceError) {\n // ReferenceError(未定義変数)はundefinedを返す\n return undefined;\n }\n return null;\n }\n }\n\n /**\n * 式にevalや危険な構文が含まれているかチェックします。\n *\n * @param expression チェック対象の式文字列\n * @return 危険なパターンが含まれている場合はtrue\n */\n protected static containsDangerousPatterns(expression: string): boolean {\n if (!this.hasAllowedSyntax(expression)) {\n return true;\n }\n const dangerousPatterns = [\n /\\beval\\s*\\(/, // eval(...)\n /\\barguments\\s*\\[/, // arguments[...]\n /\\barguments\\s*\\./, // arguments.xxx\n ];\n return dangerousPatterns.some(pattern => pattern.test(expression));\n }\n\n /**\n * 許可する式構文かどうかを検証します。\n *\n * @param expression 検証対象の式\n * @returns 許可する構文であればtrue\n */\n private static hasAllowedSyntax(expression: string): boolean {\n const tokens = this.tokenizeExpression(expression);\n if (tokens === null || tokens.length === 0) {\n return false;\n }\n\n const groups: GroupContext[] = [];\n let previous: ExpressionToken | null = null;\n\n for (let index = 0; index < tokens.length; index++) {\n const token = tokens[index];\n const next = tokens[index + 1] || null;\n\n const activeGroup = groups[groups.length - 1] || null;\n const beforePrevious = tokens[index - 2] || null;\n const thirdPrevious = tokens[index - 3] || null;\n\n if (\n this.startsObjectKey(\n activeGroup,\n previous,\n beforePrevious,\n thirdPrevious,\n )\n ) {\n if (token.value === '[') {\n return false;\n }\n if (\n token.type === 'identifier' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(token.value)\n ) {\n return false;\n }\n if (\n token.type === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(\n this.decodeStringLiteral(token.value),\n )\n ) {\n return false;\n }\n }\n\n if (token.type === 'identifier') {\n if (this.DISALLOWED_KEYWORDS.has(token.value)) {\n return false;\n }\n if (this.STRICT_FORBIDDEN_NAMES.includes(token.value)) {\n return false;\n }\n if (\n (previous?.value === '.' || previous?.value === '?.') &&\n this.FORBIDDEN_PROPERTY_NAMES.has(token.value)\n ) {\n return false;\n }\n }\n\n if (activeGroup === 'member' && token.value !== ']') {\n if (\n token.type === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(\n this.decodeStringLiteral(token.value),\n )\n ) {\n return false;\n }\n }\n\n if (token.value === '.' && next?.type !== 'identifier') {\n return false;\n }\n\n if (\n token.value === '?.' &&\n next?.type !== 'identifier' &&\n next?.value !== '[' &&\n next?.value !== '('\n ) {\n return false;\n }\n\n switch (token.value) {\n case '(':\n groups.push('paren');\n break;\n case ')': {\n const group = groups.pop();\n if (group !== 'paren') {\n return false;\n }\n break;\n }\n case '[': {\n const group: GroupContext = this.startsMemberAccess(previous)\n ? 'member'\n : 'array';\n groups.push(group);\n break;\n }\n case '{':\n groups.push('object');\n break;\n case ']': {\n const group = groups.pop();\n if (group === undefined) {\n return false;\n }\n break;\n }\n case '}': {\n const group = groups.pop();\n if (group !== 'object') {\n return false;\n }\n break;\n }\n }\n\n previous = token;\n }\n\n return groups.length === 0;\n }\n\n /**\n * 式をトークン列に分解します。\n *\n * @param expression 評価前に検証する式\n * @returns 分解結果。未対応構文を含む場合はnull\n */\n private static tokenizeExpression(\n expression: string,\n ): ExpressionToken[] | null {\n const tokens: ExpressionToken[] = [];\n const operators = [\n '===',\n '!==',\n '...',\n '?.',\n '&&',\n '||',\n '>=',\n '<=',\n '==',\n '!=',\n '=>',\n ];\n const singleCharacters = new Set([\n '(',\n ')',\n '{',\n '}',\n '[',\n ']',\n '.',\n ',',\n '?',\n ':',\n '+',\n '-',\n '*',\n '/',\n '%',\n '!',\n '>',\n '<',\n ]);\n let index = 0;\n\n while (index < expression.length) {\n const current = expression[index];\n\n if (/\\s/.test(current)) {\n index += 1;\n continue;\n }\n\n if (\n current === '/' &&\n (expression[index + 1] === '/' || expression[index + 1] === '*')\n ) {\n return null;\n }\n\n if (current === '\"' || current === '\\'') {\n const stringToken = this.readStringToken(expression, index);\n if (stringToken === null) {\n return null;\n }\n tokens.push(stringToken.token);\n index = stringToken.nextIndex;\n continue;\n }\n\n const operator = operators.find(item =>\n expression.startsWith(item, index),\n );\n if (operator) {\n tokens.push({type: 'operator', value: operator, position: index});\n index += operator.length;\n continue;\n }\n\n if (/[0-9]/.test(current)) {\n const numberToken = this.readNumberToken(expression, index);\n tokens.push(numberToken.token);\n index = numberToken.nextIndex;\n continue;\n }\n\n if (/[A-Za-z_$]/.test(current)) {\n const identifierToken = this.readIdentifierToken(expression, index);\n tokens.push(identifierToken.token);\n index = identifierToken.nextIndex;\n continue;\n }\n\n if (singleCharacters.has(current)) {\n tokens.push({type: 'operator', value: current, position: index});\n index += 1;\n continue;\n }\n\n return null;\n }\n\n return tokens;\n }\n\n /**\n * 文字列リテラルを読み取ります。\n *\n * @param expression 式全体\n * @param start 開始位置\n * @returns トークンと次の位置\n */\n private static readStringToken(\n expression: string,\n start: number,\n ): {token: ExpressionToken; nextIndex: number} | null {\n const quote = expression[start];\n let index = start + 1;\n\n while (index < expression.length) {\n const current = expression[index];\n if (current === '\\\\') {\n index += 2;\n continue;\n }\n if (current === quote) {\n return {\n token: {\n type: 'string',\n value: expression.slice(start, index + 1),\n position: start,\n },\n nextIndex: index + 1,\n };\n }\n index += 1;\n }\n\n return null;\n }\n\n /**\n * 数値リテラルを読み取ります。\n *\n * @param expression 式全体\n * @param start 開始位置\n * @returns トークンと次の位置\n */\n private static readNumberToken(\n expression: string,\n start: number,\n ): {token: ExpressionToken; nextIndex: number} {\n let index = start;\n while (index < expression.length && /[0-9_]/.test(expression[index])) {\n index += 1;\n }\n if (expression[index] === '.') {\n index += 1;\n while (index < expression.length && /[0-9_]/.test(expression[index])) {\n index += 1;\n }\n }\n return {\n token: {\n type: 'number',\n value: expression.slice(start, index),\n position: start,\n },\n nextIndex: index,\n };\n }\n\n /**\n * 識別子を読み取ります。\n *\n * @param expression 式全体\n * @param start 開始位置\n * @returns トークンと次の位置\n */\n private static readIdentifierToken(\n expression: string,\n start: number,\n ): {token: ExpressionToken; nextIndex: number} {\n let index = start;\n while (\n index < expression.length &&\n /[A-Za-z0-9_$]/.test(expression[index])\n ) {\n index += 1;\n }\n return {\n token: {\n type: 'identifier',\n value: expression.slice(start, index),\n position: start,\n },\n nextIndex: index,\n };\n }\n\n /**\n * 角括弧がメンバーアクセスかどうかを判定します。\n *\n * @param previous 直前のトークン\n * @returns メンバーアクセスであればtrue\n */\n private static startsMemberAccess(previous: ExpressionToken | null): boolean {\n if (previous === null) {\n return false;\n }\n if (previous.type === 'identifier' || previous.type === 'number') {\n return true;\n }\n return (\n previous.value === ')' ||\n previous.value === ']' ||\n previous.value === '?.'\n );\n }\n\n /**\n * object literal 内で次のトークンがキー位置かどうかを判定します。\n *\n * @param activeGroup 現在のグループ種別\n * @param previous 直前のトークン\n * @returns object literal のキー位置であれば true\n */\n private static startsObjectKey(\n activeGroup: GroupContext | null,\n previous: ExpressionToken | null,\n beforePrevious: ExpressionToken | null,\n thirdPrevious: ExpressionToken | null,\n ): boolean {\n if (activeGroup !== 'object') {\n return false;\n }\n if (previous?.value === '{' || previous?.value === ',') {\n return true;\n }\n\n if (\n previous?.type === 'identifier' &&\n this.OBJECT_PROPERTY_MODIFIERS.has(previous.value) &&\n (beforePrevious?.value === '{' || beforePrevious?.value === ',')\n ) {\n return true;\n }\n\n if (previous?.value !== '*') {\n return false;\n }\n\n if (beforePrevious?.value === '{' || beforePrevious?.value === ',') {\n return true;\n }\n\n return (\n beforePrevious?.type === 'identifier' &&\n beforePrevious.value === 'async' &&\n (thirdPrevious?.value === '{' || thirdPrevious?.value === ',')\n );\n }\n\n /**\n * 文字列リテラルをプレーン文字列へ変換します。\n *\n * @param literal 文字列リテラル\n * @returns デコード後の文字列\n */\n private static decodeStringLiteral(literal: string): string {\n return literal\n .slice(1, -1)\n .replace(/\\\\u\\{([0-9a-fA-F]+)\\}/g, (_, code: string) =>\n String.fromCodePoint(parseInt(code, 16)),\n )\n .replace(/\\\\u([0-9a-fA-F]{4})/g, (_, code: string) =>\n String.fromCharCode(parseInt(code, 16)),\n )\n .replace(/\\\\x([0-9a-fA-F]{2})/g, (_, code: string) =>\n String.fromCharCode(parseInt(code, 16)),\n )\n .replace(/\\\\([\"'\\\\bfnrtv0])/g, (_, escaped: string) => {\n switch (escaped) {\n case 'b':\n return '\\b';\n case 'f':\n return '\\f';\n case 'n':\n return '\\n';\n case 'r':\n return '\\r';\n case 't':\n return '\\t';\n case 'v':\n return '\\v';\n case '0':\n return '\\0';\n default:\n return escaped;\n }\n });\n }\n\n /**\n * バインド値を安全なProxyでラップします。\n *\n * @param bindedValues バインド値\n * @returns ラップ済みのバインド値\n */\n private static wrapBoundValues(\n bindedValues: Record<string, unknown>,\n ): Record<string, unknown> {\n const cache = new WeakMap<object, unknown>();\n const wrappedValues: Record<string, unknown> = {};\n\n Object.entries(bindedValues).forEach(([key, value]) => {\n wrappedValues[key] = this.wrapBoundValue(value, cache);\n });\n\n return wrappedValues;\n }\n\n /**\n * 危険なプロパティアクセスを防ぐために値を再帰的にラップします。\n *\n * @param value ラップ対象の値\n * @param cache 既存Proxyのキャッシュ\n * @returns ラップ済みの値\n */\n private static wrapBoundValue(\n value: unknown,\n cache: WeakMap<object, unknown>,\n ): unknown {\n if (!this.shouldWrapValue(value)) {\n return value;\n }\n\n const target = value as object;\n const cachedValue = cache.get(target);\n if (cachedValue !== undefined) {\n return cachedValue;\n }\n\n const proxy = new Proxy(target, {\n get: (currentTarget, property, receiver) => {\n if (\n typeof property === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(property)\n ) {\n return undefined;\n }\n const result = Reflect.get(currentTarget, property, receiver);\n if (typeof property === 'symbol') {\n return result;\n }\n return this.wrapBoundValue(\n result,\n cache,\n );\n },\n has: (currentTarget, property) => {\n if (\n typeof property === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(property)\n ) {\n return false;\n }\n return Reflect.has(currentTarget, property);\n },\n getOwnPropertyDescriptor: (currentTarget, property) => {\n if (\n typeof property === 'string' &&\n this.FORBIDDEN_PROPERTY_NAMES.has(property)\n ) {\n return undefined;\n }\n return Reflect.getOwnPropertyDescriptor(currentTarget, property);\n },\n apply: (currentTarget, thisArg, argArray) => {\n const result = Reflect.apply(\n currentTarget as (...args: unknown[]) => unknown,\n thisArg,\n argArray,\n );\n if (this.isIteratorLike(result)) {\n return result;\n }\n return this.wrapBoundValue(result, cache);\n },\n construct: (currentTarget, argArray, newTarget) => {\n return this.wrapBoundValue(\n Reflect.construct(\n currentTarget as new (...args: unknown[]) => object,\n argArray,\n newTarget,\n ),\n cache,\n ) as object;\n },\n });\n\n cache.set(target, proxy);\n return proxy;\n }\n\n /**\n * Proxy ラップ対象の値かどうかを判定します。\n *\n * @param value 判定対象\n * @returns ラップ対象であればtrue\n */\n private static shouldWrapValue(value: unknown): value is object {\n if (typeof value === 'function') {\n return true;\n }\n if (value === null || typeof value !== 'object') {\n return false;\n }\n if (Array.isArray(value)) {\n return true;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n }\n\n /**\n * 評価中のみ prototype 系プロパティへの生アクセスを抑止します。\n *\n * @param callback 実行する処理\n * @returns 処理結果\n */\n private static withBlockedPropertyAccess<T>(callback: () => T): T {\n const blockedDescriptors = [\n {target: Object.prototype, property: 'constructor'},\n {target: Function.prototype, property: 'constructor'},\n {target: Object.prototype, property: '__proto__'},\n ] as const;\n const originals = blockedDescriptors\n .map(item => ({\n ...item,\n descriptor: Object.getOwnPropertyDescriptor(item.target, item.property),\n }))\n .filter(item => item.descriptor?.configurable === true);\n\n originals.forEach(({target, property}) => {\n Object.defineProperty(target, property, {\n configurable: true,\n enumerable: false,\n get: () => undefined,\n set: () => undefined,\n });\n });\n\n try {\n return callback();\n } finally {\n originals.forEach(({target, property, descriptor}) => {\n if (descriptor !== undefined) {\n Object.defineProperty(target, property, descriptor);\n }\n });\n }\n }\n\n /**\n * イテレータ互換オブジェクトかどうかを判定します。\n *\n * @param value 判定対象\n * @returns イテレータ互換であればtrue\n */\n private static isIteratorLike(value: unknown): boolean {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n return typeof (value as Iterator<unknown>).next === 'function';\n }\n\n /**\n * トップレベルのバインド識別子に拒否対象名が含まれていないかを判定します。\n * ネストしたオブジェクトのプロパティ名は識別子として評価されないため、ここでは拒否しません。\n *\n * @param obj チェック対象のオブジェクト\n * @return 禁止識別子が含まれていればtrue\n */\n protected static containsForbiddenKeys(obj: unknown): boolean {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n\n for (const key of Object.keys(obj as object)) {\n if (this.FORBIDDEN_BINDING_NAMES.has(key)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * バインド値に危険なホストオブジェクトやグローバル関数が含まれていないかを再帰的に判定します。\n *\n * @param obj チェック対象の値\n * @param seen 循環参照検出用の訪問済み集合\n * @return 危険値が含まれていればtrue\n */\n protected static containsForbiddenBindingValues(\n obj: unknown,\n seen: WeakSet<object> = new WeakSet<object>(),\n ): boolean {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n\n if (seen.has(obj as object)) {\n return false;\n }\n seen.add(obj as object);\n\n if (this.getForbiddenBindingValues().some(value => value === obj)) {\n return true;\n }\n\n for (const value of Object.values(obj as Record<string, unknown>)) {\n if (typeof value === 'function') {\n if (\n this.getForbiddenBindingValues().some(\n forbidden => forbidden === value,\n )\n ) {\n return true;\n }\n continue;\n }\n if (this.containsForbiddenBindingValues(value, seen)) {\n return true;\n }\n }\n\n return false;\n }\n}\n","/**\n * @fileoverview 仮想DOM実装\n *\n * メモリ上にノードツリーを保持し、DOMへの反映を非同期で行います。\n * DOMからの読み込みは行わず、オブザーバーとchangeイベントで更新されます。\n */\nimport Queue from './queue';\nimport Log from './log';\nimport Expression from './expression';\nimport Env from './env';\n\n/**\n * 仮想DOMのフラグメントの抽象クラス。\n */\nexport default abstract class Fragment {\n /** フラグメントの対象ノードに対するキャッシュ */\n protected static readonly FRAGMENT_CACHE = new WeakMap<Node, Fragment>();\n\n /**\n * フラグメントを取得もしくは作成します。\n *\n * @param node 対象ノード\n * @returns フラグメント\n */\n public static get(node: HTMLElement): ElementFragment;\n public static get(node: Text): TextFragment;\n public static get(node: Comment): CommentFragment;\n public static get(node: Node | null): Fragment | null;\n public static get(node: Node | null): Fragment | null {\n if (node == null) {\n return null;\n }\n if (Fragment.FRAGMENT_CACHE.has(node)) {\n return Fragment.FRAGMENT_CACHE.get(node)!;\n }\n let fragment;\n switch (node.nodeType) {\n case Node.ELEMENT_NODE:\n fragment = new ElementFragment(node as HTMLElement);\n break;\n case Node.TEXT_NODE:\n fragment = new TextFragment(node as Text);\n break;\n case Node.COMMENT_NODE:\n fragment = new CommentFragment(node as Comment);\n break;\n default:\n Log.warn('[Haori]', 'Unsupported node type:', node.nodeType);\n return null;\n }\n return fragment;\n }\n\n /** 親フラグメント */\n protected parent: ElementFragment | null = null;\n\n /** 対象ノード */\n protected readonly target: Node;\n\n /** フラグメントがDOMにマウントされているかどうか */\n protected mounted = false;\n\n /** ノード更新スキップフラグ(オブザーバーによる無限ループ対応) */\n protected skipMutationNodes = false;\n\n /**\n * フラグメントのコンストラクタ。\n *\n * @param target 対象ノード\n */\n protected constructor(target: Node) {\n this.target = target;\n Fragment.FRAGMENT_CACHE.set(target, this);\n }\n\n /**\n * skipMutationNodesフラグの値を取得します。\n *\n * @returns skipMutationNodesの値\n */\n public isSkipMutationNodes(): boolean {\n return this.skipMutationNodes;\n }\n\n /**\n * フラグメントをDOMから除去します。\n *\n * @return 除去のPromise\n */\n public unmount(): Promise<void> {\n if (!this.mounted || this.skipMutationNodes) {\n return Promise.resolve();\n }\n if (this.parent) {\n const parent = this.parent;\n const prevSkip = parent.skipMutationNodes;\n return Queue.enqueue(() => {\n parent.skipMutationNodes = true;\n if (this.target.parentNode === parent.getTarget()) {\n parent.getTarget().removeChild(this.target);\n }\n this.mounted = false;\n }).finally(() => {\n parent.skipMutationNodes = prevSkip;\n }) as Promise<void>;\n } else {\n // 親フラグメント情報が無くても、DOM 上に親ノードが存在する場合は安全に除去する。\n const host = this.target.parentNode as (HTMLElement | null);\n if (host) {\n return Queue.enqueue(() => {\n if (this.target.parentNode === host) {\n host.removeChild(this.target);\n }\n this.mounted = false;\n }) as Promise<void>;\n }\n this.mounted = false;\n }\n return Promise.resolve();\n }\n\n /**\n * フラグメントをDOMに追加します。\n *\n * @return 追加のPromise\n */\n public mount(): Promise<void> {\n if (this.mounted || this.skipMutationNodes) {\n return Promise.resolve();\n }\n if (this.parent) {\n const parent = this.parent;\n const prevSkip = parent.skipMutationNodes;\n return Queue.enqueue(() => {\n parent.skipMutationNodes = true;\n if (this.target.parentNode !== parent.getTarget()) {\n // 既に同じ親なら何もしない\n parent.getTarget().appendChild(this.target);\n }\n this.mounted = true;\n }).finally(() => {\n parent.skipMutationNodes = prevSkip;\n }) as Promise<void>;\n }\n return Promise.resolve();\n }\n\n /**\n * フラグメントのマウント状態を取得します。\n *\n * @returns マウント状態\n */\n public isMounted(): boolean {\n return this.mounted;\n }\n\n /**\n * フラグメントのマウント状態を設定します。\n *\n * @param mounted マウント状態\n */\n public setMounted(mounted: boolean): void {\n this.mounted = mounted;\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public abstract clone(): Fragment;\n\n /**\n * フラグメントとノードを削除します。\n *\n * @param unmount DOMからの除去を行うかどうか(内部の子呼び出しの場合のみfalseとする)\n * @return 除去のPromise\n */\n public remove(unmount = true): Promise<void> {\n if (this.parent) {\n this.parent.removeChild(this);\n }\n Fragment.FRAGMENT_CACHE.delete(this.target);\n if (unmount) {\n return this.unmount();\n }\n return Promise.resolve();\n }\n\n /**\n * 対象ノードを取得します。\n *\n * @returns 対象ノード\n */\n public getTarget(): Node {\n return this.target;\n }\n\n /**\n * 親フラグメントを取得します。\n *\n * @returns 親フラグメント\n */\n public getParent(): ElementFragment | null {\n return this.parent;\n }\n\n /**\n * 親フラグメントを設定します。\n *\n * @param parent 親フラグメント\n */\n public setParent(parent: ElementFragment | null): void {\n this.parent = parent;\n }\n}\n\n/**\n * エレメントフラグメント。\n * DOM要素を表現し、子ノードを持つことができます。\n */\nexport class ElementFragment extends Fragment {\n /** inputイベントを発生させるタイプ */\n private readonly INPUT_EVENT_TYPES = [\n 'text',\n 'password',\n 'email',\n 'url',\n 'tel',\n 'search',\n 'number',\n 'range',\n 'color',\n 'date',\n 'datetime-local',\n 'month',\n 'time',\n 'week',\n ];\n\n /** 子フラグメントのリスト */\n private readonly children: Fragment[] = [];\n\n /** 属性名に対する属性情報のマップ */\n private readonly attributeMap = new Map<string, AttributeContents>();\n\n /** バインドデータ */\n private bindingData: Record<string, unknown> | null = null;\n\n /** バインドデータのキャッシュ */\n private bindingDataCache: Record<string, unknown> | null = null;\n\n /** 表示状態 */\n private visible = true;\n\n /** 元の display 値 */\n private display: string | null = null;\n\n /** each用のテンプレート */\n private template: ElementFragment | null = null;\n\n /** each比較用のキー */\n private listKey: string | null = null;\n\n /** valueプロパティの値 */\n private value: string | number | boolean | null = null;\n\n /** 属性更新スキップフラグ(オブザーバーによる無限ループ対応) */\n private skipMutationAttributes = false;\n\n /** 値変更スキップフラグ(更新イベントによる無限ループ対応) */\n private skipChangeValue = false;\n\n /**\n * エレメントフラグメントのコンストラクタ。\n * アトリビュートや子フラグメントの作成も行います。\n *\n * @param target 対象エレメント\n */\n public constructor(target: HTMLElement) {\n super(target);\n this.syncValue();\n target.getAttributeNames().forEach(name => {\n const value = target.getAttribute(name);\n if (value !== null && !this.attributeMap.has(name)) {\n const contents = new AttributeContents(name, value);\n this.attributeMap.set(name, contents);\n }\n });\n target.childNodes.forEach(node => {\n const childFragment = Fragment.get(node);\n childFragment!.setParent(this);\n this.children.push(childFragment!);\n });\n }\n\n /**\n * 子フラグメントのリストを取得します。\n *\n * @returns 子フラグメントのリスト\n */\n public getChildren(): Fragment[] {\n return this.children;\n }\n\n /**\n * 子エレメントフラグメントのリストを取得します。\n *\n * @returns 子エレメントフラグメントのリスト\n */\n public getChildElementFragments(): ElementFragment[] {\n return this.children.filter(\n child => child instanceof ElementFragment,\n ) as ElementFragment[];\n }\n\n /**\n * 子フラグメントをリストに追加します。\n * DOMの追加は行いません。\n *\n * @param child 追加する子フラグメント\n */\n public pushChild(child: Fragment) {\n this.children.push(child);\n child.setParent(this);\n }\n\n /**\n * 子フラグメントをリストから削除します。\n * DOMからの削除は行いません。\n *\n * @param child 削除する子フラグメント\n */\n public removeChild(child: Fragment): void {\n const index = this.children.indexOf(child);\n if (index < 0) {\n Log.warn('[Haori]', 'Child fragment not found.', child);\n return;\n }\n this.children.splice(index, 1);\n child.setParent(null);\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public clone(): ElementFragment {\n const clone = new ElementFragment(\n this.target.cloneNode(false) as HTMLElement,\n );\n // DOM 属性は評価後の値になっているため、\n // クローンでは attributeMap をコピーしてテンプレート式を保持します。\n this.attributeMap.forEach((contents, name) => {\n clone.attributeMap.set(name, contents);\n });\n this.children.forEach(child => {\n const childClone = child.clone();\n clone.getTarget().appendChild(childClone.getTarget());\n clone.pushChild(childClone);\n });\n clone.mounted = false;\n clone.bindingData = this.bindingData;\n clone.clearBindingDataCache();\n clone.visible = true;\n clone.display = this.display;\n clone.template = this.template;\n clone.normalizeClonedVisibilityState();\n return clone;\n }\n\n /**\n * clone 時に runtime の hidden 状態だけを落とします。\n */\n private normalizeClonedVisibilityState(): void {\n if (\n this.visible === false ||\n this.getTarget().style.display === 'none' ||\n this.getTarget().hasAttribute(`${Env.prefix}if-false`)\n ) {\n this.visible = true;\n this.display = '';\n this.getTarget().style.display = '';\n this.getTarget().removeAttribute(`${Env.prefix}if-false`);\n }\n this.children.forEach(child => {\n if (child instanceof ElementFragment) {\n child.normalizeClonedVisibilityState();\n }\n });\n }\n\n /**\n * フラグメントとノードを削除します。\n *\n * @param unmount DOMからの除去を行うかどうか(内部の子呼び出しの場合のみfalseとする)\n * @return 除去のPromise\n */\n public remove(unmount = true): Promise<void> {\n const promises: Promise<void>[] = [];\n this.children.forEach(child => {\n promises.push(child.remove(false));\n });\n this.children.length = 0;\n this.attributeMap.clear();\n this.bindingData = null;\n this.bindingDataCache = null;\n if (this.template) {\n promises.push(this.template.remove(false));\n this.template = null;\n }\n promises.push(super.remove(unmount));\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * フラグメントの対象エレメントを取得します。\n *\n * @returns フラグメントの対象エレメント\n */\n public getTarget(): HTMLElement {\n return this.target as HTMLElement;\n }\n\n /**\n * 継承を考慮したバインドデータを取得します。\n *\n * @returns バインドデータのオブジェクト\n */\n public getBindingData(): Record<string, unknown> {\n if (this.bindingDataCache) {\n return this.bindingDataCache;\n }\n this.bindingDataCache = {};\n if (this.parent) {\n Object.assign(this.bindingDataCache, this.parent.getBindingData());\n }\n if (this.bindingData) {\n Object.assign(this.bindingDataCache, this.bindingData);\n }\n return this.bindingDataCache;\n }\n\n /**\n * 生のバインドデータを取得します。\n *\n * @returns 生のバインドデータ\n */\n public getRawBindingData(): Record<string, unknown> | null {\n return this.bindingData;\n }\n\n /**\n * バインドデータを設定します。\n *\n * @param data バインドデータ\n */\n public setBindingData(data: Record<string, unknown>): void {\n this.bindingData = data;\n this.clearBindingDataCache();\n }\n\n /**\n * 親フラグメントを設定します。バインドデータキャッシュをクリアします。\n *\n * @param parent 親フラグメント\n */\n public override setParent(parent: ElementFragment | null): void {\n if (this.parent === parent) {\n return;\n }\n this.parent = parent;\n this.clearBindingDataCache();\n }\n\n /**\n * バインドデータのキャッシュをクリアします。\n */\n public clearBindingDataCache(): void {\n this.bindingDataCache = null;\n this.children.forEach(child => {\n if (child instanceof ElementFragment) {\n child.clearBindingDataCache();\n }\n });\n }\n\n /**\n * フラグメントのテンプレートを取得します。\n *\n * @returns テンプレート\n */\n public getTemplate(): ElementFragment | null {\n return this.template;\n }\n\n /**\n * フラグメントのテンプレートを設定します。\n *\n * @param template フラグメントのテンプレート\n */\n public setTemplate(template: ElementFragment | null): void {\n this.template = template;\n }\n\n /**\n * 比較用リストキーを設定します。\n *\n * @param key 比較用リストキー\n */\n public setListKey(key: string): void {\n this.listKey = key;\n }\n\n /**\n * 比較用リストキーを取得します。\n *\n * @returns 比較用リストキー\n */\n public getListKey(): string | null {\n return this.listKey;\n }\n\n /**\n * 入力エレメントに値を設定します。\n * チェックボックとラジオボタンの場合は値に一致するかどうかでチェック状態を変更します。\n *\n * @param value 値\n * @returns エレメントの更新のPromise\n */\n public setValue(value: string | number | boolean | null): Promise<void> {\n return this.applyValue(value, true);\n }\n\n /**\n * 入力エレメントに値をイベントなしで設定します。\n * フォームの bindingData 反映時に内部同期として利用します。\n *\n * @param value 値\n * @returns エレメントの更新のPromise\n */\n public syncBindingValue(\n value: string | number | boolean | null,\n ): Promise<void> {\n return this.applyValue(value, false);\n }\n\n /**\n * 入力エレメントに値を設定します。\n * 必要に応じて入力系イベントも発火します。\n *\n * @param value 値\n * @param dispatchEvents input/change イベントを発火するかどうか\n * @returns エレメントの更新のPromise\n */\n private applyValue(\n value: string | number | boolean | null,\n dispatchEvents: boolean,\n ): Promise<void> {\n if (this.skipChangeValue) {\n return Promise.resolve();\n }\n if (this.value === value) {\n return Promise.resolve();\n }\n const element = this.getTarget();\n if (\n element instanceof HTMLInputElement &&\n (element.type === 'checkbox' || element.type === 'radio')\n ) {\n const result = this.getAttribute('value');\n const isBooleanCheckbox =\n element.type === 'checkbox' && result === 'true';\n let newChecked: boolean;\n if (isBooleanCheckbox) {\n newChecked = value === true || value === 'true';\n } else if (result === 'false') {\n newChecked = value === false;\n } else {\n newChecked = result === String(value);\n }\n this.value = isBooleanCheckbox\n ? newChecked\n : newChecked\n ? value\n : null;\n if (element.checked === newChecked) {\n return Promise.resolve();\n }\n this.skipChangeValue = true;\n return Queue.enqueue(() => {\n element.checked = newChecked;\n if (dispatchEvents) {\n element.dispatchEvent(new Event('change', {bubbles: true}));\n }\n }).finally(() => {\n this.skipChangeValue = false;\n }) as Promise<void>;\n } else if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n this.value = value;\n this.skipChangeValue = true;\n return Queue.enqueue(() => {\n element.value = value === null ? '' : String(value);\n if (dispatchEvents) {\n if (\n (element instanceof HTMLInputElement &&\n this.INPUT_EVENT_TYPES.includes(element.type)) ||\n element instanceof HTMLTextAreaElement\n ) {\n element.dispatchEvent(new Event('input', {bubbles: true}));\n }\n element.dispatchEvent(new Event('change', {bubbles: true}));\n }\n }).finally(() => {\n this.skipChangeValue = false;\n }) as Promise<void>;\n } else {\n Log.warn(\n '[Haori]',\n 'setValue is not supported for this element type.',\n element,\n );\n return Promise.resolve();\n }\n }\n\n /**\n * 入力エレメントの値を取得します。\n * DOM要素の現在の値と同期します。\n *\n * @returns 入力エレメントの値\n */\n public getValue(): string | number | boolean | null {\n return this.value;\n }\n\n /**\n * 内部の値をクリアします。エレメントのvalue値は変化しません。\n */\n public clearValue() {\n this.value = null;\n }\n\n /**\n * 内部の値をDOMの値と同期します。\n * changeイベント時など、DOM値が変更された後に呼び出されます。\n */\n public syncValue() {\n const element = this.getTarget();\n if (element instanceof HTMLInputElement) {\n if (element.type === 'checkbox' || element.type === 'radio') {\n const isBooleanCheckbox =\n element.type === 'checkbox' && element.value === 'true';\n if (element.checked) {\n const value = element.value;\n if (isBooleanCheckbox) {\n this.value = true;\n } else if (value === 'false') {\n this.value = false;\n } else {\n this.value = value;\n }\n } else {\n // チェックボックスがOFFの場合\n const value = element.value;\n if (isBooleanCheckbox) {\n this.value = false;\n } else if (value === 'false') {\n this.value = true;\n } else {\n this.value = null;\n }\n }\n } else {\n this.value = element.value;\n }\n } else if (element instanceof HTMLTextAreaElement) {\n this.value = element.value;\n } else if (element instanceof HTMLSelectElement) {\n this.value = element.value;\n }\n }\n\n /**\n * 属性の値を評価して設定します。\n * 評価値がfalseの場合は属性を削除します。\n * 矯正評価属性の場合は元の値を設定します。\n *\n * @param name 属性名\n * @param value 属性値\n * @returns 属性の更新のPromise\n */\n public setAttribute(name: string, value: string | null): Promise<void> {\n return this.setAttributeInternal(name, name, value, true);\n }\n\n /**\n * data-attr-* の生値を保持しつつ、別名の属性へ評価結果を反映します。\n *\n * @param rawName 生の属性名\n * @param targetName 反映先の属性名\n * @param value 生の属性値\n * @returns 属性更新の Promise\n */\n public setAliasedAttribute(\n rawName: string,\n targetName: string,\n value: string | null,\n ): Promise<void> {\n return this.setAttributeInternal(rawName, targetName, value, false);\n }\n\n /**\n * data-attr-* の生属性と反映先属性を同時に削除します。\n *\n * @param rawName 生の属性名\n * @param targetName 反映先の属性名\n * @returns 属性削除の Promise\n */\n public removeAliasedAttribute(\n rawName: string,\n targetName: string,\n ): Promise<void> {\n if (this.skipMutationAttributes) {\n return Promise.resolve();\n }\n this.attributeMap.delete(rawName);\n this.skipMutationAttributes = true;\n const element = this.getTarget();\n return Queue.enqueue(() => {\n element.removeAttribute(rawName);\n if (targetName !== rawName) {\n element.removeAttribute(targetName);\n }\n }).finally(() => {\n this.skipMutationAttributes = false;\n }) as Promise<void>;\n }\n\n /**\n * 生の属性値を保持しつつ、必要に応じて別名属性へ評価結果を反映します。\n *\n * @param rawName 生の属性名\n * @param targetName 反映先の属性名\n * @param value 生の属性値\n * @param syncValueProperty value 属性更新時に DOM property も同期するかどうか\n * @returns 属性更新の Promise\n */\n private setAttributeInternal(\n rawName: string,\n targetName: string,\n value: string | null,\n syncValueProperty: boolean,\n ): Promise<void> {\n if (this.skipMutationAttributes) {\n return Promise.resolve();\n }\n if (value === null) {\n if (rawName === targetName) {\n return this.removeAttribute(rawName);\n }\n return this.removeAliasedAttribute(rawName, targetName);\n }\n const contents = new AttributeContents(rawName, value);\n this.attributeMap.set(rawName, contents);\n this.skipMutationAttributes = true;\n const element = this.getTarget();\n const result = contents.isForceEvaluation()\n ? value\n : this.getAttribute(rawName);\n return Queue.enqueue(() => {\n if (element.getAttribute(rawName) !== value) {\n element.setAttribute(rawName, value);\n }\n if (result === null || result === false) {\n element.removeAttribute(targetName);\n } else {\n const string = String(result);\n if (element.getAttribute(targetName) !== string) {\n element.setAttribute(targetName, string);\n }\n // element.setAttribute('value', ...) は defaultValue のみ更新するため、\n // setValue と同じ対象には element.value も反映して DOM と内部状態を揃える。\n if (\n syncValueProperty &&\n contents.isEvaluate &&\n targetName === 'value' &&\n ((element instanceof HTMLInputElement &&\n this.INPUT_EVENT_TYPES.includes(element.type)) ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement)\n ) {\n this.value = string;\n if (element.value !== string) {\n element.value = string;\n }\n }\n }\n }).finally(() => {\n this.skipMutationAttributes = false;\n }) as Promise<void>;\n }\n\n /**\n * 属性の値を削除します。\n *\n * @param name 属性名\n * @returns 属性の削除のPromise\n */\n public removeAttribute(name: string): Promise<void> {\n if (this.skipMutationAttributes) {\n return Promise.resolve();\n }\n this.attributeMap.delete(name);\n this.skipMutationAttributes = true;\n const element = this.getTarget();\n return Queue.enqueue(() => {\n element.removeAttribute(name);\n }).finally(() => {\n this.skipMutationAttributes = false;\n }) as Promise<void>;\n }\n\n /**\n * 属性の評価された値を取得します。\n * 複数の評価値がある場合は結合して返します。\n *\n * @param name 属性名\n * @returns 評価された値\n */\n public getAttribute(name: string): string | false | unknown | null {\n const contents = this.attributeMap.get(name);\n if (contents === undefined) {\n return null;\n }\n const results = contents.evaluate(this.getBindingData());\n if (results.length === 1) {\n return results[0];\n }\n return TextContents.joinEvaluateResults(results);\n }\n\n /**\n * 属性の生の値を取得します。\n *\n * @param name 属性名\n * @returns 生の属性値\n */\n public getRawAttribute(name: string): string | null {\n const contents = this.attributeMap.get(name);\n if (contents === undefined) {\n return null;\n }\n return contents.getValue();\n }\n\n /**\n * 属性名のリストを取得します。\n *\n * @return 属性名のリスト\n */\n public getAttributeNames(): string[] {\n return Array.from(this.attributeMap.keys());\n }\n\n /**\n * 属性の有無を確認します。\n *\n * @param name 属性名\n * @returns 属性の有無\n */\n public hasAttribute(name: string): boolean {\n return this.attributeMap.has(name);\n }\n\n /**\n * DOM上の順序から、参照フラグメントに対応する children 配列の挿入位置を推定します。\n *\n * @param referenceChild 参照フラグメント\n * @param insertAfter 参照位置の後ろに挿入するかどうか\n * @returns 挿入位置。解決できない場合はnull\n */\n private resolveInsertionPointFromDom(\n referenceChild: Fragment,\n insertAfter: boolean,\n ): {index: number; referenceNode: Node | null} | null {\n const referenceNode = referenceChild.getTarget();\n if (referenceNode.parentNode !== this.target) {\n return null;\n }\n\n const insertionReferenceNode = insertAfter\n ? referenceNode.nextSibling\n : referenceNode;\n\n let nextTrackedNode = insertAfter\n ? referenceNode.nextSibling\n : referenceNode;\n while (nextTrackedNode !== null) {\n const childFragment = Fragment.get(nextTrackedNode);\n if (childFragment !== null) {\n const childIndex = this.children.indexOf(childFragment);\n if (childIndex !== -1) {\n return {index: childIndex, referenceNode: insertionReferenceNode};\n }\n }\n nextTrackedNode = nextTrackedNode.nextSibling;\n }\n\n return {index: this.children.length, referenceNode: insertionReferenceNode};\n }\n\n /**\n * 子ノードを参照ノードの前に挿入します。\n * 参照ノードがnullの場合、親の最後に追加されます。\n *\n * @param newChild 新しい子ノード\n * @param referenceChild 参照ノード\n * @return 挿入のPromise\n */\n public insertBefore(\n newChild: Fragment,\n referenceChild: Fragment | null,\n referenceNodeOverride?: Node | null,\n ): Promise<void> {\n if (this.skipMutationNodes) {\n return Promise.resolve();\n }\n\n // 循環参照チェック\n if (newChild === this) {\n Log.error('[Haori]', 'Cannot insert element as child of itself');\n return Promise.reject(new Error('Self-insertion not allowed'));\n }\n\n // 祖先チェック\n const ancestors = new Set<Fragment>();\n let ancestor = this.parent;\n while (ancestor) {\n ancestors.add(ancestor);\n ancestor = ancestor.getParent();\n }\n if (ancestors.has(newChild)) {\n Log.error('[Haori]', 'Cannot create circular reference');\n return Promise.reject(new Error('Circular reference detected'));\n }\n\n // 同じ親内での移動かどうかを確認\n const isSameParent = newChild.getParent() === this;\n let newChildIndex = -1;\n let referenceIndex = -1;\n\n if (isSameParent) {\n newChildIndex = this.children.indexOf(newChild);\n if (referenceChild !== null) {\n referenceIndex = this.children.indexOf(referenceChild);\n }\n }\n\n const newChildParent = newChild.getParent();\n if (newChildParent !== null) {\n // 既存の親から削除\n newChildParent.removeChild(newChild);\n }\n\n let referenceNode: Node | null =\n referenceNodeOverride === undefined\n ? referenceChild?.getTarget() || null\n : referenceNodeOverride;\n\n if (referenceChild === null) {\n this.children.push(newChild);\n } else {\n let index: number;\n if (isSameParent) {\n // 同じ親内での移動の場合、削除後のインデックスを調整\n if (newChildIndex !== -1 && newChildIndex < referenceIndex) {\n // 削除する要素が参照要素より前にあった場合、インデックスは1つ減る\n index = referenceIndex - 1;\n } else {\n index = referenceIndex;\n }\n } else {\n index = this.children.indexOf(referenceChild);\n }\n\n if (index === -1) {\n const insertionPoint = this.resolveInsertionPointFromDom(\n referenceChild,\n false,\n );\n if (insertionPoint === null) {\n Log.warn(\n '[Haori]',\n 'Reference child not found in children.',\n referenceChild,\n );\n this.children.push(newChild);\n } else {\n this.children.splice(insertionPoint.index, 0, newChild);\n referenceNode = insertionPoint.referenceNode;\n }\n } else {\n this.children.splice(index, 0, newChild);\n }\n }\n\n newChild.setParent(this);\n newChild.setMounted(this.mounted);\n\n const prevSkip = this.skipMutationNodes;\n this.skipMutationNodes = true;\n return Queue.enqueue(() => {\n this.target.insertBefore(newChild.getTarget(), referenceNode);\n }).finally(() => {\n this.skipMutationNodes = prevSkip;\n }) as Promise<void>;\n }\n\n /**\n * 指定した参照ノードの後に子ノードを挿入します。\n *\n * @param newChild 子ノード\n * @param referenceChild 参照ノード\n * @returns 挿入のPromise\n */\n public insertAfter(\n newChild: Fragment,\n referenceChild: Fragment | null,\n ): Promise<void> {\n if (referenceChild == null) {\n return this.insertBefore(newChild, null);\n }\n const index = this.children.indexOf(referenceChild);\n if (index === -1) {\n const insertionPoint = this.resolveInsertionPointFromDom(\n referenceChild,\n true,\n );\n if (insertionPoint === null) {\n Log.warn(\n '[Haori]',\n 'Reference child not found in children.',\n referenceChild,\n );\n return this.insertBefore(newChild, null);\n }\n return this.insertBefore(\n newChild,\n this.children[insertionPoint.index] || null,\n insertionPoint.referenceNode,\n );\n }\n return this.insertBefore(newChild, this.children[index + 1] || null);\n }\n\n /**\n * 前のエレメントフラグメントを取得します。\n * 存在しない場合はnullを返します。\n *\n * @return 前のエレメントフラグメントまたはnull\n */\n public getPrevious(): ElementFragment | null {\n const parent = this.getParent();\n if (parent === null) {\n return null;\n }\n const siblings = parent.getChildElementFragments();\n const index = siblings.indexOf(this);\n if (index <= 0) {\n return null;\n }\n return siblings[index - 1];\n }\n\n /**\n * 次のエレメントフラグメントを取得します。\n * 存在しない場合はnullを返します。\n *\n * @return 次のエレメントフラグメントまたはnull\n */\n public getNext(): ElementFragment | null {\n const parent = this.getParent();\n if (parent === null) {\n return null;\n }\n const siblings = parent.getChildElementFragments();\n const index = siblings.indexOf(this);\n if (index < 0 || index + 1 >= siblings.length) {\n return null;\n }\n return siblings[index + 1];\n }\n\n /**\n * 表示状態を返します。\n *\n * @returns 表示状態\n */\n public isVisible(): boolean {\n return this.visible;\n }\n\n /**\n * エレメントを非表示にします。\n *\n * @returns エレメントの非表示のPromise\n */\n public hide(): Promise<void> {\n this.visible = false;\n this.display = this.getTarget().style.display;\n this.getTarget().style.display = 'none';\n this.getTarget().setAttribute(`${Env.prefix}if-false`, '');\n return Promise.resolve();\n }\n\n /**\n * エレメントを表示します。\n *\n * @return エレメントの表示のPromise\n */\n public show(): Promise<void> {\n this.getTarget().style.display = this.display ?? '';\n this.getTarget().removeAttribute(`${Env.prefix}if-false`);\n this.visible = true;\n return Promise.resolve();\n }\n\n /**\n * 指定した属性名を持つ最も近い親要素を返します。\n * 見つからない場合はnullを返します。\n *\n * @param name 属性名\n * @returns 最も近い親要素またはnull\n */\n public closestByAttribute(name: string): ElementFragment | null {\n if (this.hasAttribute(name)) {\n return this;\n }\n const parent = this.getParent();\n if (parent === null) {\n return null;\n }\n return parent.closestByAttribute(name);\n }\n}\n\n/**\n * テキストフラグメント。\n * テキストノードを表現します。\n */\nexport class TextFragment extends Fragment {\n /** 未評価のテキスト文字列 */\n private text: string;\n\n /** コンテンツ */\n private contents: TextContents;\n\n /** 更新スキップフラグ(オブザーバーによる無限ループ対応) */\n private skipMutation = false;\n\n /**\n * テキストフラグメントのコンストラクタ。\n * 対象テキストノードの内容を初期化します。\n *\n * @param target 対象テキストノード\n */\n public constructor(target: Text) {\n super(target);\n this.text = target.textContent || '';\n this.contents = new TextContents(this.text);\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public clone(): TextFragment {\n const clone = new TextFragment(this.target.cloneNode(true) as Text);\n clone.mounted = false;\n clone.text = this.text;\n clone.contents = this.contents;\n return clone;\n }\n\n /**\n * フラグメントの対象ノードを取得します。\n *\n * @returns フラグメントの対象ノード\n */\n public getTarget(): Text {\n return this.target as Text;\n }\n\n /**\n * コンテンツを更新します。\n *\n * @param text テキスト\n * @returns 更新のPromise\n */\n public setContent(text: string): Promise<void> {\n if (this.skipMutation || this.text === text) {\n return Promise.resolve();\n }\n this.text = text;\n this.contents = new TextContents(text);\n return this.evaluate();\n }\n\n /**\n * フラグメントを評価します。\n *\n * @returns 評価結果のPromise\n */\n public evaluate(): Promise<void> {\n if (this.contents.isRawEvaluate && this.parent === null) {\n return Promise.reject(\n new Error('Parent fragment is required for raw evaluation'),\n );\n }\n return Queue.enqueue(() => {\n this.skipMutation = true;\n if (this.contents.isRawEvaluate) {\n this.parent!.getTarget().innerHTML = this.contents.evaluate(\n this.parent!.getBindingData(),\n )[0] as string;\n } else if (this.contents.isEvaluate) {\n this.target.textContent = TextContents.joinEvaluateResults(\n this.contents.evaluate(this.parent!.getBindingData()),\n );\n } else {\n this.target.textContent = this.text;\n }\n }).finally(() => {\n this.skipMutation = false;\n }) as Promise<void>;\n }\n}\n\n/**\n * コメントフラグメント。\n * コメントノードを表現します。\n */\nexport class CommentFragment extends Fragment {\n /** コメント文字列 */\n private text: string;\n\n /** 更新スキップフラグ(オブザーバーによる無限ループ対応) */\n private skipMutation = false;\n\n /**\n * コメントフラグメントのコンストラクタ。\n * 対象コメントノードの内容を初期化します。\n *\n * @param target 対象コメントノード\n */\n public constructor(target: Comment) {\n super(target);\n this.text = target.textContent || '';\n }\n\n /**\n * フラグメントをクローンします。\n *\n * @returns クローンされたフラグメント\n */\n public clone(): Fragment {\n const clone = new CommentFragment(this.target.cloneNode(true) as Comment);\n clone.mounted = false;\n clone.text = this.text;\n return clone;\n }\n\n /**\n * フラグメントの対象ノードを取得します。\n *\n * @returns フラグメントの対象ノード\n */\n public getTarget(): Comment {\n return this.target as Comment;\n }\n\n /**\n * コンテンツを更新します。\n *\n * @param text テキスト\n * @return 更新のPromise\n */\n public setContent(text: string): Promise<void> {\n if (this.skipMutation || this.text === text) {\n return Promise.resolve();\n }\n this.text = text;\n return Queue.enqueue(() => {\n this.skipMutation = true;\n this.target.textContent = this.text;\n }).finally(() => {\n this.skipMutation = false;\n }) as Promise<void>;\n }\n}\n\n/**\n * 値の種別。\n */\nenum ExpressionType {\n /** テキスト */\n TEXT,\n\n /** 評価式 */\n EXPRESSION,\n\n /** 生の評価式 */\n RAW_EXPRESSION,\n}\n\n/**\n * コンテンツのインターフェース。\n */\ninterface Content {\n /** コンテンツの内容 */\n text: string;\n\n /** 値の種別 */\n type: ExpressionType;\n}\n\n/**\n * テキストコンテンツを管理するクラスです。\n * 一度生成されると内部は変更しません。\n */\nclass TextContents {\n /** プレースホルダ検出用の正規表現 */\n protected static readonly PLACEHOLDER_REGEX =\n /\\{\\{\\{([\\s\\S]+?)\\}\\}\\}|\\{\\{([\\s\\S]+?)\\}\\}/g;\n\n /**\n * 評価結果を結合して文字列にします。\n *\n * @param contents 評価結果の配列\n * @returns 結合された文字列\n */\n public static joinEvaluateResults(contents: unknown[] | null): string {\n if (contents === null || contents.length === 0) {\n return '';\n }\n return contents\n .map(c => {\n if (c === null || c === undefined || c === false || Number.isNaN(c)) {\n return '';\n } else if (typeof c !== 'string') {\n return String(c);\n } else {\n return c;\n }\n })\n .join('');\n }\n\n /** コンテンツのリスト */\n protected readonly contents: Content[] = [];\n\n /** 評価式が含まれるかどうか */\n public readonly isEvaluate: boolean = false;\n\n /** 生の評価式が含まれるかどうか */\n public readonly isRawEvaluate: boolean = false;\n\n /** 評価前の値 */\n private readonly value: string;\n\n /**\n * コンストラクタ。\n *\n * @param text テキスト\n */\n constructor(text: string) {\n this.value = text;\n\n const matches = [...text.matchAll(TextContents.PLACEHOLDER_REGEX)];\n let lastIndex = 0;\n\n let hasEvaluate = false;\n let hasRawEvaluate = false;\n for (const match of matches) {\n // プレースホルダ前の通常テキスト\n if (match.index > lastIndex) {\n this.contents.push({\n text: text.slice(lastIndex, match.index),\n type: ExpressionType.TEXT,\n });\n }\n // プレースホルダ本体\n const content = {\n text: match[1] ?? match[2],\n type: match[1]\n ? ExpressionType.RAW_EXPRESSION\n : ExpressionType.EXPRESSION,\n };\n hasEvaluate = true;\n hasRawEvaluate =\n hasRawEvaluate || content.type === ExpressionType.RAW_EXPRESSION;\n this.contents.push(content);\n lastIndex = match.index! + match[0].length;\n }\n // 最後のプレースホルダ以降の通常テキスト\n if (lastIndex < text.length) {\n this.contents.push({\n text: text.slice(lastIndex),\n type: ExpressionType.TEXT,\n });\n }\n this.isEvaluate = hasEvaluate;\n this.isRawEvaluate = hasRawEvaluate;\n this.checkRawExpressions();\n }\n\n /**\n * 評価前の値を取得します。\n *\n * @returns 評価前の値\n */\n public getValue(): string {\n return this.value;\n }\n\n /**\n * RAW_EXPRESSION のチェックを行います。\n */\n protected checkRawExpressions(): void {\n for (let i = 0; i < this.contents.length; i++) {\n const content = this.contents[i];\n if (\n content.type === ExpressionType.RAW_EXPRESSION &&\n this.contents.length > 1\n ) {\n Log.error(\n '[Haori]',\n 'Raw expressions are not allowed in multi-content expressions.',\n );\n this.contents[i].type = ExpressionType.EXPRESSION;\n }\n }\n }\n\n /**\n * 式評価を行い、結果を返します。\n *\n * @param bindingValues バインディングされた値のオブジェクト\n * @returns 評価結果のリスト\n */\n public evaluate(bindingValues: Record<string, unknown>): unknown[] {\n if (!this.isEvaluate && !this.isRawEvaluate) {\n return this.contents.map(c => c.text);\n }\n const results: unknown[] = [];\n this.contents.forEach(c => {\n try {\n if (\n c.type === ExpressionType.EXPRESSION ||\n c.type === ExpressionType.RAW_EXPRESSION\n ) {\n const result = Expression.evaluate(c.text, bindingValues);\n results.push(result);\n } else {\n results.push(c.text);\n }\n } catch (error) {\n Log.error(\n '[Haori]',\n `Error evaluating text expression: ${c.text}`,\n error,\n );\n results.push('');\n }\n });\n return results;\n }\n}\n\n/**\n * 属性のコンテンツを管理するクラスです。\n * 一度生成されると内部は変更しません。\n */\nclass AttributeContents extends TextContents {\n /** 強制評価する属性名 */\n private static readonly FORCE_EVALUATION_ATTRIBUTES = [\n 'data-if',\n 'hor-if',\n 'data-each',\n 'hor-each',\n ];\n\n /** 強制評価フラグ(プレースホルダでなくても評価する) */\n private readonly forceEvaluation: boolean;\n\n /**\n * コンストラクタ。\n *\n * @param name 属性名\n * @param text 属性値\n */\n constructor(name: string, value: string) {\n super(value);\n this.forceEvaluation =\n AttributeContents.FORCE_EVALUATION_ATTRIBUTES.includes(name);\n }\n\n /**\n * 強制評価フラグを取得します。\n *\n * @returns 強制評価フラグ\n */\n public isForceEvaluation(): boolean {\n return this.forceEvaluation;\n }\n\n /**\n * 式評価を行い、結果を返します。\n *\n * @param bindingValues バインディングされた値のオブジェクト\n * @returns 評価結果のリスト\n */\n public evaluate(bindingValues: Record<string, unknown>): unknown[] {\n if (!this.isEvaluate && !this.forceEvaluation) {\n return this.contents.map(c => c.text);\n }\n const results: unknown[] = [];\n this.contents.forEach(c => {\n try {\n if (\n (this.forceEvaluation && c.type === ExpressionType.TEXT) ||\n c.type === ExpressionType.EXPRESSION ||\n c.type === ExpressionType.RAW_EXPRESSION\n ) {\n const result = Expression.evaluate(c.text, bindingValues);\n results.push(result);\n } else {\n results.push(c.text);\n }\n } catch (error) {\n Log.error(\n '[Haori]',\n `Error evaluating attribute expression: ${c.text}`,\n error,\n );\n results.push('');\n }\n });\n if (this.forceEvaluation && results.length > 1) {\n Log.error(\n '[Haori]',\n 'each or if expressions must have a single content.',\n results,\n );\n return [results[0]];\n }\n return results;\n }\n}\n","/**\n * @fileoverview Haoriイベント発火ユーティリティ\n *\n * Haoriライブラリが発火するカスタムイベントの統一的な発火機能を提供します。\n */\n\nimport type {HaoriRuntime} from './env';\n\n/**\n * Haoriイベントを発火するユーティリティクラス\n */\nexport interface FetchStartMetadata {\n /** 実行モード。 */\n runtime?: HaoriRuntime;\n /** 属性で指定された元の HTTP メソッド。 */\n requestedMethod?: string;\n /** 実際の通信に使う HTTP メソッド。 */\n effectiveMethod?: string;\n /** 通信方式。 */\n transportMode?: string;\n /** クエリ化後の検索文字列。 */\n queryString?: string;\n}\n\nexport default class HaoriEvent {\n /**\n * カスタムイベントを発火します。\n *\n * @param target イベントを発火する対象要素\n * @param eventName イベント名(haori:プレフィックスは自動追加)\n * @param detail イベントの詳細データ\n * @param options イベントオプション\n */\n public static dispatch(\n target: EventTarget,\n eventName: string,\n detail?: unknown,\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n },\n ): boolean {\n const event = new CustomEvent(`haori:${eventName}`, {\n bubbles: options?.bubbles ?? true,\n cancelable: options?.cancelable ?? false,\n composed: options?.composed ?? true,\n detail,\n });\n\n return target.dispatchEvent(event);\n }\n\n /**\n * readyイベントを発火します。\n *\n * @param version ライブラリバージョン\n */\n public static ready(version?: string): void {\n HaoriEvent.dispatch(document, 'ready', {version});\n }\n\n /**\n * renderイベントを発火します。\n *\n * @param target 評価対象要素\n */\n public static render(target: HTMLElement): void {\n HaoriEvent.dispatch(target, 'render', {target});\n }\n\n /**\n * importstartイベントを発火します。\n *\n * @param target data-import要素\n * @param url インポート対象URL\n */\n public static importStart(target: HTMLElement, url: string): void {\n HaoriEvent.dispatch(target, 'importstart', {\n url,\n startedAt: performance.now(),\n });\n }\n\n /**\n * importendイベントを発火します。\n *\n * @param target data-import要素\n * @param url インポート対象URL\n * @param bytes 取得バイト数\n * @param startedAt 開始時刻\n */\n public static importEnd(\n target: HTMLElement,\n url: string,\n bytes: number,\n startedAt: number,\n ): void {\n HaoriEvent.dispatch(target, 'importend', {\n url,\n bytes,\n durationMs: performance.now() - startedAt,\n });\n }\n\n /**\n * importerrorイベントを発火します。\n *\n * @param target data-import要素\n * @param url インポート対象URL\n * @param error エラー内容\n */\n public static importError(\n target: HTMLElement,\n url: string,\n error: unknown,\n ): void {\n HaoriEvent.dispatch(target, 'importerror', {url, error});\n }\n\n /**\n * bindchangeイベントを発火します。\n *\n * @param target バインド対象要素\n * @param previous 変更前のデータ\n * @param next 変更後のデータ\n * @param reason 変更理由\n */\n public static bindChange(\n target: HTMLElement,\n previous: Record<string, unknown> | null,\n next: Record<string, unknown>,\n reason: 'form' | 'fetch' | 'manual' | 'import' | 'other' = 'other',\n ): void {\n const changedKeys: string[] = [];\n\n // 変更されたキーを検出\n const prevKeys = new Set(Object.keys(previous || {}));\n const nextKeys = new Set(Object.keys(next));\n const allKeys = new Set([...prevKeys, ...nextKeys]);\n\n for (const key of allKeys) {\n const prevValue = previous?.[key];\n const nextValue = next[key];\n if (prevValue !== nextValue) {\n changedKeys.push(key);\n }\n }\n\n HaoriEvent.dispatch(target, 'bindchange', {\n previous: previous || {},\n next,\n changedKeys,\n reason,\n });\n }\n\n /**\n * eachupdateイベントを発火します。\n *\n * @param target data-each要素\n * @param added 追加された行のキー\n * @param removed 削除された行のキー\n * @param order 現在の順序\n */\n public static eachUpdate(\n target: HTMLElement,\n added: string[],\n removed: string[],\n order: string[],\n ): void {\n HaoriEvent.dispatch(target, 'eachupdate', {\n added,\n removed,\n order,\n total: order.length,\n });\n }\n\n /**\n * rowaddイベントを発火します。\n *\n * @param target 行要素\n * @param key 行キー\n * @param index インデックス\n * @param item 行データ\n */\n public static rowAdd(\n target: HTMLElement,\n key: string,\n index: number,\n item: unknown,\n ): void {\n HaoriEvent.dispatch(target, 'rowadd', {key, index, item});\n }\n\n /**\n * rowremoveイベントを発火します。\n *\n * @param target 行要素\n * @param key 行キー\n * @param index インデックス\n */\n public static rowRemove(\n target: HTMLElement,\n key: string,\n index: number,\n ): void {\n HaoriEvent.dispatch(target, 'rowremove', {key, index});\n }\n\n /**\n * rowmoveイベントを発火します。\n *\n * @param target 行要素\n * @param key 行キー\n * @param from 移動前インデックス\n * @param to 移動後インデックス\n */\n public static rowMove(\n target: HTMLElement,\n key: string,\n from: number,\n to: number,\n ): void {\n HaoriEvent.dispatch(target, 'rowmove', {key, from, to});\n }\n\n /**\n * showイベントを発火します。\n *\n * @param target data-if要素\n */\n public static show(target: HTMLElement): void {\n HaoriEvent.dispatch(target, 'show', {visible: true});\n }\n\n /**\n * hideイベントを発火します。\n *\n * @param target data-if要素\n */\n public static hide(target: HTMLElement): void {\n HaoriEvent.dispatch(target, 'hide', {visible: false});\n }\n\n /**\n * fetchstartイベントを発火します。\n *\n * @param target 起点要素\n * @param url フェッチURL\n * @param options フェッチオプション\n * @param payload 送信データ\n * @param metadata runtime とメソッド変換情報。\n * @return 戻り値はありません。\n */\n public static fetchStart(\n target: HTMLElement,\n url: string,\n options?: RequestInit,\n payload?: Record<string, unknown>,\n metadata?: FetchStartMetadata,\n ): void {\n HaoriEvent.dispatch(target, 'fetchstart', {\n url,\n options: options || {},\n payload,\n startedAt: performance.now(),\n ...metadata,\n });\n }\n\n /**\n * fetchendイベントを発火します。\n *\n * @param target 起点要素\n * @param url フェッチURL\n * @param status HTTPステータス\n * @param startedAt 開始時刻\n */\n public static fetchEnd(\n target: HTMLElement,\n url: string,\n status: number,\n startedAt: number,\n ): void {\n HaoriEvent.dispatch(target, 'fetchend', {\n url,\n status,\n durationMs: performance.now() - startedAt,\n });\n }\n\n /**\n * fetcherrorイベントを発火します。\n *\n * @param target 起点要素\n * @param url フェッチURL\n * @param error エラー内容\n * @param status HTTPステータス(存在する場合)\n * @param startedAt 開始時刻(存在する場合)\n */\n public static fetchError(\n target: HTMLElement,\n url: string,\n error: unknown,\n status?: number,\n startedAt?: number,\n ): void {\n HaoriEvent.dispatch(target, 'fetcherror', {\n url,\n status,\n error,\n durationMs: startedAt ? performance.now() - startedAt : undefined,\n });\n }\n}\n","/**\n * @fileoverview 手続き的処理管理機能\n *\n * イベントに基づく手続き的な処理を提供します。\n */\n\nimport Core from './core';\nimport Env from './env';\nimport Expression from './expression';\nimport Form from './form';\nimport Fragment, {ElementFragment} from './fragment';\nimport Haori from './haori';\nimport Log from './log';\nimport HaoriEvent from './event';\n\ntype ProcedureHaoriApi = Pick<\n typeof Haori,\n | 'addErrorMessage'\n | 'closeDialog'\n | 'confirm'\n | 'dialog'\n | 'openDialog'\n | 'toast'\n>;\n\nconst PROCEDURE_HAORI_METHOD_NAMES = [\n 'addErrorMessage',\n 'closeDialog',\n 'confirm',\n 'dialog',\n 'openDialog',\n 'toast',\n] as const;\n\nconst PROCEDURE_HISTORY_STATE_KEY = '__haoriHistoryState__';\n\n/**\n * Procedure から利用する Haori API を解決します。\n * window.Haori が差し替えられている場合はそちらを優先します。\n *\n * @returns Procedure が使用する Haori API。\n */\nfunction resolveProcedureHaoriApi(): ProcedureHaoriApi {\n const scope = globalThis as typeof globalThis & {\n window?: Window & {Haori?: unknown};\n };\n const candidate = scope.window?.Haori;\n const hasRequiredMethods = PROCEDURE_HAORI_METHOD_NAMES.every(\n methodName =>\n typeof (candidate as Record<string, unknown> | undefined)?.[\n methodName\n ] === 'function',\n );\n return hasRequiredMethods ? (candidate as ProcedureHaoriApi) : Haori;\n}\n\nconst QUERY_TRANSPORT_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);\n\n/**\n * URL クエリ化の対象メソッドかどうかを判定します。\n *\n * @param method 判定対象の HTTP メソッド。\n * @return クエリ送信対象なら true。\n */\nfunction isQueryTransportMethod(method: string): boolean {\n return QUERY_TRANSPORT_METHODS.has(method.toUpperCase());\n}\n\n/**\n * 送信データを URLSearchParams に追加します。\n *\n * @param params 追加先の URLSearchParams。\n * @param payload 追加対象の送信データ。\n * @return 戻り値はありません。\n */\nfunction appendPayloadToSearchParams(\n params: URLSearchParams,\n payload: Record<string, unknown>,\n): void {\n for (const [key, value] of Object.entries(payload)) {\n if (value === undefined) {\n continue;\n }\n if (value === null) {\n params.append(key, '');\n } else if (Array.isArray(value)) {\n value.forEach(item => {\n params.append(key, String(item));\n });\n } else if (typeof value === 'object' || typeof value === 'function') {\n params.append(key, JSON.stringify(value));\n } else {\n params.append(key, String(value));\n }\n }\n}\n\n/**\n * 送信データをクエリ文字列へ付加した URL を返します。\n *\n * @param fetchUrl 元のフェッチ URL。\n * @param payload 追加対象の送信データ。\n * @return クエリ文字列を付加した URL。\n */\nfunction appendPayloadToUrl(\n fetchUrl: string,\n payload: Record<string, unknown>,\n): string {\n const url = new URL(fetchUrl, window.location.href);\n const params = new URLSearchParams(url.search);\n appendPayloadToSearchParams(params, payload);\n url.search = params.toString();\n return url.toString();\n}\n\n/**\n * フェッチ前実行スクリプト戻り値型。\n */\nexport interface BeforeCallbackResult {\n /** 処理を停止する場合は true */\n stop?: boolean;\n\n /** 上書きするフェッチURL */\n fetchUrl?: string | null;\n\n /** 上書きするフェッチオプション */\n fetchOptions?: RequestInit | null;\n}\n\n/**\n * フェッチ後実行スクリプト戻り値型。\n */\nexport interface AfterCallbackResult {\n /** 処理を停止する場合は true */\n stop?: boolean;\n\n /** レスポンスとして使用するデータ */\n response?: Response;\n}\n\n/**\n * Procedureクラスのオプションインターフェース。\n */\nexport interface ProcedureOptions {\n /** 処理対象のフラグメント */\n targetFragment?: ElementFragment;\n\n /** バリデーションを行うかどうか */\n valid?: boolean;\n\n /** 確認メッセージ */\n confirmMessage?: string | null;\n\n /** 送信もしくは受信データ */\n data?: Record<string, unknown> | null;\n\n /** フェッチ前実行スクリプト */\n beforeCallback?: (\n fetchUrl: string | null,\n fetchOptions: RequestInit | null,\n ) => BeforeCallbackResult | boolean | void;\n\n /** 対象フォームフラグメント */\n formFragment?: ElementFragment | null;\n\n /** フェッチURL */\n fetchUrl?: string | null;\n\n /** フェッチオプション */\n fetchOptions?: RequestInit | null;\n\n /** バインド対象フラグメント */\n bindFragments?: ElementFragment[] | null;\n\n /** レスポンスデータから抽出するパラメータ名のリスト */\n bindParams?: string[] | null;\n\n /** レスポンスデータのうち既存配列へ追記するパラメータ名のリスト */\n bindAppendParams?: string[] | null;\n\n /** レスポンスデータをバインドする際のキー名 */\n bindArg?: string | null;\n\n /** フェッチ後実行スクリプト */\n afterCallback?: (\n response: Response | Record<string, unknown>,\n ) => AfterCallbackResult | boolean | void;\n\n /** 値を変更するフラグメント */\n adjustFragments?: ElementFragment[] | null;\n\n /** 変更する値の増減値 */\n adjustValue?: number | null;\n\n /** 行追加の有無 */\n rowAdd?: boolean | null;\n\n /** 行削除の有無 */\n rowRemove?: boolean | null;\n\n /** 前の行へ移動するかどうか */\n rowMovePrev?: boolean | null;\n\n /** 次の行へ移動するかどうか */\n rowMoveNext?: boolean | null;\n\n /** リセットするフラグメント */\n resetFragments?: ElementFragment[] | null;\n\n /** 再フェッチするフラグメント */\n refetchFragments?: ElementFragment[] | null;\n\n /** クリックするフラグメント */\n clickFragments?: ElementFragment[] | null;\n\n /** ダイアログを開くフラグメント */\n openFragments?: ElementFragment[] | null;\n\n /** ダイアログを閉じるフラグメント */\n closeFragments?: ElementFragment[] | null;\n\n /** コピー先フラグメント */\n copyFragments?: ElementFragment[] | null;\n\n /** コピー対象パラメータ名のリスト */\n copyParams?: string[] | null;\n\n /** ダイアログメッセージ */\n dialogMessage?: string | null;\n\n /** トーストメッセージ */\n toastMessage?: string | null;\n\n /** トーストレベル */\n toastLevel?: 'info' | 'warning' | 'error' | 'success' | null;\n\n /** history.pushState で追加する URL */\n historyUrl?: string | null;\n\n /** history.pushState の URL に追記するクエリパラメータ */\n historyData?: Record<string, unknown> | null;\n\n /** history.pushState の URL に追記するフォームフラグメント */\n historyFormFragment?: ElementFragment | null;\n\n /** リダイレクトURL */\n redirectUrl?: string | null;\n\n /** エラー時に最初のエラー要素へスクロールするかどうか */\n scrollOnError?: boolean | null;\n\n /** 成功時にスクロールする要素のCSSセレクター */\n scrollTarget?: string | null;\n}\n\n/**\n * 手続き的処理管理クラスです。\n */\nexport default class Procedure {\n /** data 属性内のテンプレート式検出用正規表現 */\n private static readonly DATA_PLACEHOLDER_REGEX =\n /\\{\\{\\{([\\s\\S]+?)\\}\\}\\}|\\{\\{([\\s\\S]+?)\\}\\}/g;\n\n /** 属性全体が単一テンプレート式かを判定する正規表現 */\n private static readonly SINGLE_PLACEHOLDER_REGEX =\n /^(\\{\\{\\{[\\s\\S]+?\\}\\}\\}|\\{\\{[\\s\\S]+?\\}\\})$/;\n\n /**\n * イベント属性名を正しく生成します。\n * 例: (\"click\", \"fetch\") => \"data-click-fetch\"\n * (null, \"fetch\") => \"data-fetch\"\n * (\"change\", \"bind-arg\") => \"data-change-bind-arg\"\n * 非イベント変種が \"data-fetch-xxx\" として存在するものについては、event が null の場合にそちらを返します。\n */\n private static attrName(\n event: string | null,\n key: string,\n hasFetchFallback: boolean = false,\n ): string {\n if (event) {\n return `${Env.prefix}${event}-${key}`;\n }\n return hasFetchFallback\n ? `${Env.prefix}fetch-${key}`\n : `${Env.prefix}${key}`;\n }\n\n /**\n * data 属性のテンプレート式評価結果を URLSearchParams 向けに組み立てます。\n *\n * @param rawAttribute 生の属性値\n * @param bindingValues バインディング値\n * @returns パラメータ形式として扱える文字列\n */\n private static resolveDataParamString(\n rawAttribute: string,\n bindingValues: Record<string, unknown>,\n ): string {\n return rawAttribute.replace(\n Procedure.DATA_PLACEHOLDER_REGEX,\n (\n _matched: string,\n rawExpression: string | undefined,\n expression: string | undefined,\n ): string => {\n const result = Expression.evaluate(\n rawExpression ?? expression ?? '',\n bindingValues,\n );\n if (result === null || result === undefined || Number.isNaN(result)) {\n return '';\n }\n if (typeof result === 'object') {\n return encodeURIComponent(JSON.stringify(result));\n }\n return encodeURIComponent(String(result));\n },\n );\n }\n\n /**\n * JSON 文字列中のテンプレート式かどうかを判定します。\n *\n * @param source 生の属性値\n * @param offset プレースホルダ開始位置\n * @returns JSON 文字列中なら true\n */\n private static isJsonStringContext(source: string, offset: number): boolean {\n let inString = false;\n let escaped = false;\n for (let index = 0; index < offset; index += 1) {\n const char = source[index];\n if (escaped) {\n escaped = false;\n continue;\n }\n if (char === '\\\\') {\n escaped = true;\n continue;\n }\n if (char === '\"') {\n inString = !inString;\n }\n }\n return inString;\n }\n\n /**\n * JSON 値コンテキスト向けにテンプレート式の評価結果を直列化します。\n *\n * @param result テンプレート式の評価結果\n * @returns JSON 値として埋め込める文字列\n */\n private static stringifyJsonTemplateValue(result: unknown): string {\n if (result === undefined || Number.isNaN(result)) {\n return 'null';\n }\n try {\n const serialized = JSON.stringify(result);\n return serialized ?? JSON.stringify(String(result));\n } catch {\n return JSON.stringify(String(result));\n }\n }\n\n /**\n * JSON 文字列コンテキスト向けにテンプレート式の評価結果を直列化します。\n *\n * @param result テンプレート式の評価結果\n * @returns JSON 文字列へ安全に埋め込める文字列\n */\n private static stringifyJsonTemplateStringContent(result: unknown): string {\n if (result === null || result === undefined || Number.isNaN(result)) {\n return '';\n }\n const value =\n typeof result === 'object'\n ? Procedure.stringifyJsonTemplateValue(result)\n : String(result);\n return JSON.stringify(value).slice(1, -1);\n }\n\n /**\n * JSON 形式 data 属性内のテンプレート式を安全に解決します。\n *\n * @param rawAttribute 生の属性値\n * @param bindingValues バインディング値\n * @returns JSON として解釈可能な文字列\n */\n private static resolveDataJsonString(\n rawAttribute: string,\n bindingValues: Record<string, unknown>,\n ): string {\n return rawAttribute.replace(\n Procedure.DATA_PLACEHOLDER_REGEX,\n (\n _matched: string,\n rawExpression: string | undefined,\n expression: string | undefined,\n offset: number,\n ): string => {\n const result = Expression.evaluate(\n rawExpression ?? expression ?? '',\n bindingValues,\n );\n return Procedure.isJsonStringContext(rawAttribute, offset)\n ? Procedure.stringifyJsonTemplateStringContent(result)\n : Procedure.stringifyJsonTemplateValue(result);\n },\n );\n }\n\n /**\n * data 属性を評価済みの値として取得します。\n *\n * @param fragment フラグメント\n * @param attrName 属性名\n * @returns 送信データ\n */\n private static resolveDataAttribute(\n fragment: ElementFragment,\n attrName: string,\n ): Record<string, unknown> | null {\n const rawAttribute = fragment.getRawAttribute(attrName);\n const dataAttribute = fragment.getAttribute(attrName);\n if (\n dataAttribute &&\n typeof dataAttribute === 'object' &&\n !Array.isArray(dataAttribute)\n ) {\n return dataAttribute as Record<string, unknown>;\n }\n if (typeof dataAttribute !== 'string' || rawAttribute === null) {\n return null;\n }\n const trimmed = rawAttribute.trim();\n if (Procedure.SINGLE_PLACEHOLDER_REGEX.test(trimmed)) {\n return Core.parseDataBind(dataAttribute);\n }\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n return Core.parseDataBind(\n Procedure.resolveDataJsonString(\n rawAttribute,\n fragment.getBindingData(),\n ),\n );\n }\n return Core.parseDataBind(\n Procedure.resolveDataParamString(rawAttribute, fragment.getBindingData()),\n );\n }\n\n /**\n * オプションをフラグメントの属性から構築します。\n *\n * @param fragment フラグメント\n * @param event イベント名\n * @return 構築されたオプション\n */\n private static buildOptions(\n fragment: ElementFragment,\n event: string | null,\n ): ProcedureOptions {\n const options: ProcedureOptions = {\n targetFragment: fragment,\n };\n if (event) {\n // validate(spec: data-???-validate)\n if (fragment.hasAttribute(Procedure.attrName(event, 'validate'))) {\n options.valid = true;\n }\n // confirm\n if (fragment.hasAttribute(Procedure.attrName(event, 'confirm'))) {\n options.confirmMessage = (fragment.getAttribute(\n Procedure.attrName(event, 'confirm'),\n ) as string).replace(/\\\\n/g, '\\n');\n }\n // data(イベント)\n if (fragment.hasAttribute(Procedure.attrName(event, 'data'))) {\n options.data = Procedure.resolveDataAttribute(\n fragment,\n Procedure.attrName(event, 'data'),\n );\n }\n // form(イベント)\n if (fragment.hasAttribute(Procedure.attrName(event, 'form'))) {\n const formSelector = fragment.getRawAttribute(\n Procedure.attrName(event, 'form'),\n ) as string | null;\n if (formSelector) {\n const formElement = document.body.querySelector(formSelector);\n if (formElement !== null) {\n options.formFragment = Form.getFormFragment(\n Fragment.get(formElement) as ElementFragment,\n );\n } else {\n Log.error(\n 'Haori',\n `Form element not found: ${formSelector}` +\n ` (${Procedure.attrName(event, 'form')})`,\n );\n }\n } else {\n // 属性はあるが値が省略された場合は自要素もしくは先祖の form を対象\n options.formFragment = Form.getFormFragment(fragment);\n }\n } else if (event === 'change') {\n // changeイベントの場合、data-change-form属性がなくても自動的にフォームを検索\n options.formFragment = Form.getFormFragment(fragment);\n }\n if (fragment.hasAttribute(`${Env.prefix}${event}-before-run`)) {\n const body = fragment.getRawAttribute(\n `${Env.prefix}${event}-before-run`,\n ) as string;\n try {\n options.beforeCallback = new Function(\n 'fetchUrl',\n 'fetchOptions',\n `\n\"use strict\";\n${body}\n`,\n ) as (\n fetchUrl: string | null,\n fetchOptions: RequestInit | null,\n ) => BeforeCallbackResult | boolean | void;\n } catch (e) {\n Log.error('Haori', `Invalid before script: ${e}`);\n }\n }\n }\n // fetch URL(イベントあり/なし)\n const fetchAttrName = Procedure.attrName(event, 'fetch');\n const hasFetchAttr = fragment.hasAttribute(fetchAttrName);\n if (hasFetchAttr) {\n options.fetchUrl = fragment.getAttribute(fetchAttrName) as string;\n }\n const fetchOptions: RequestInit = {};\n // fetch-method(イベントあり/なし)\n // event: data-{event}-fetch-method, non-event: data-fetch-method\n if (event) {\n const fetchMethodAttrEvent = Procedure.attrName(event, 'fetch-method');\n if (fragment.hasAttribute(fetchMethodAttrEvent)) {\n fetchOptions.method = fragment.getAttribute(\n fetchMethodAttrEvent,\n ) as string;\n }\n } else {\n const fetchMethodAttrNonEvent = Procedure.attrName(null, 'method', true);\n if (fragment.hasAttribute(fetchMethodAttrNonEvent)) {\n fetchOptions.method = fragment.getAttribute(\n fetchMethodAttrNonEvent,\n ) as string;\n }\n }\n // fetch-headers(イベントあり/なし)\n // event: data-{event}-fetch-headers, non-event: data-fetch-headers\n if (event) {\n const fetchHeadersAttrEvent = Procedure.attrName(event, 'fetch-headers');\n if (fragment.hasAttribute(fetchHeadersAttrEvent)) {\n const headersString = fragment.getRawAttribute(\n fetchHeadersAttrEvent,\n ) as string;\n try {\n fetchOptions.headers = Core.parseDataBind(headersString) as Record<\n string,\n string\n >;\n } catch (e) {\n Log.error('Haori', `Invalid fetch headers: ${e}`);\n }\n }\n } else {\n const fetchHeadersAttrNonEvent = Procedure.attrName(\n null,\n 'headers',\n true,\n );\n if (fragment.hasAttribute(fetchHeadersAttrNonEvent)) {\n const headersString = fragment.getRawAttribute(\n fetchHeadersAttrNonEvent,\n ) as string;\n try {\n fetchOptions.headers = Core.parseDataBind(headersString) as Record<\n string,\n string\n >;\n } catch (e) {\n Log.error('Haori', `Invalid fetch headers: ${e}`);\n }\n }\n }\n // fetch-content-type(イベントあり/なし)\n // event: data-{event}-fetch-content-type\n // non-event: data-fetch-content-type\n if (event) {\n const fetchCTAttrEvent = Procedure.attrName(\n event,\n 'fetch-content-type',\n );\n if (fragment.hasAttribute(fetchCTAttrEvent)) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': fragment.getAttribute(fetchCTAttrEvent) as string,\n };\n } else if (\n fetchOptions.method &&\n fetchOptions.method !== 'GET' &&\n fetchOptions.method !== 'HEAD' &&\n fetchOptions.method !== 'OPTIONS'\n ) {\n // only set default Content-Type when one is not already provided\n let hasContentType = false;\n if (fetchOptions.headers && typeof fetchOptions.headers === 'object') {\n const headersObj = fetchOptions.headers as Record<string, unknown>;\n hasContentType = 'Content-Type' in headersObj;\n }\n if (!hasContentType) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/json',\n };\n }\n } else if (\n fetchOptions.method &&\n (fetchOptions.method === 'GET' ||\n fetchOptions.method === 'HEAD' ||\n fetchOptions.method === 'OPTIONS')\n ) {\n // 仕様: GET/HEAD/OPTIONS 既定は application/x-www-form-urlencoded\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n }\n } else {\n const fetchCTAttrNonEvent = Procedure.attrName(\n null,\n 'content-type',\n true,\n );\n if (fragment.hasAttribute(fetchCTAttrNonEvent)) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': fragment.getAttribute(fetchCTAttrNonEvent) as string,\n };\n } else if (\n fetchOptions.method &&\n fetchOptions.method !== 'GET' &&\n fetchOptions.method !== 'HEAD' &&\n fetchOptions.method !== 'OPTIONS'\n ) {\n // only set default Content-Type when one is not already provided\n let hasContentType = false;\n if (fetchOptions.headers && typeof fetchOptions.headers === 'object') {\n const headersObj = fetchOptions.headers as Record<string, unknown>;\n hasContentType = 'Content-Type' in headersObj;\n }\n if (!hasContentType) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/json',\n };\n }\n } else if (\n fetchOptions.method &&\n (fetchOptions.method === 'GET' ||\n fetchOptions.method === 'HEAD' ||\n fetchOptions.method === 'OPTIONS')\n ) {\n // 仕様: GET/HEAD/OPTIONS 既定は application/x-www-form-urlencoded\n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n }\n }\n if (Object.keys(fetchOptions).length > 0) {\n options.fetchOptions = fetchOptions;\n }\n // bind(イベントあり/なし: 非イベントは data-fetch-bind)\n const bindAttr = event\n ? Procedure.attrName(event, 'bind')\n : Procedure.attrName(null, 'bind', true);\n if (fragment.hasAttribute(bindAttr)) {\n const bindSelector = fragment.getRawAttribute(bindAttr) as string | null;\n if (bindSelector) {\n const bindElements = document.body.querySelectorAll(bindSelector);\n if (bindElements.length > 0) {\n options.bindFragments = [];\n bindElements.forEach(element => {\n const fragment = Fragment.get(element);\n if (fragment) {\n options.bindFragments!.push(fragment as ElementFragment);\n }\n });\n } else {\n Log.error(\n 'Haori',\n `Bind element not found: ${bindSelector} (${bindAttr})`,\n );\n }\n }\n }\n const bindArgAttrEvent = Procedure.attrName(event, 'bind-arg');\n const bindArgAttrNonEventLegacy = Procedure.attrName(\n null,\n 'arg',\n true,\n ); // data-fetch-arg\n const bindArgAttrNonEventNew = Procedure.attrName(\n null,\n 'bind-arg',\n true,\n ); // data-fetch-bind-arg (less common)\n if (event) {\n if (fragment.hasAttribute(bindArgAttrEvent)) {\n options.bindArg = fragment.getRawAttribute(bindArgAttrEvent) as\n | string\n | null;\n }\n } else {\n // Prefer legacy `data-fetch-arg` for non-event usage.\n // Fallback to `data-fetch-bind-arg` if legacy is not present.\n if (fragment.hasAttribute(bindArgAttrNonEventLegacy)) {\n options.bindArg = fragment.getRawAttribute(\n bindArgAttrNonEventLegacy,\n ) as string | null;\n } else if (fragment.hasAttribute(bindArgAttrNonEventNew)) {\n options.bindArg = fragment.getRawAttribute(bindArgAttrNonEventNew) as\n | string\n | null;\n }\n }\n const bindParamsAttr = event\n ? Procedure.attrName(event, 'bind-params')\n : Procedure.attrName(null, 'bind-params', true);\n if (fragment.hasAttribute(bindParamsAttr)) {\n const paramsString = fragment.getRawAttribute(bindParamsAttr) as string;\n options.bindParams = paramsString.split('&').map(p => p.trim());\n }\n const bindAppendAttr = event\n ? Procedure.attrName(event, 'bind-append')\n : Procedure.attrName(null, 'bind-append', true);\n if (fragment.hasAttribute(bindAppendAttr)) {\n const paramsString = fragment.getRawAttribute(bindAppendAttr) as string;\n options.bindAppendParams = paramsString\n .split('&')\n .map(p => p.trim())\n .filter(Boolean);\n }\n const copyParamsAttr = event\n ? Procedure.attrName(event, 'copy-params')\n : null;\n if (copyParamsAttr && fragment.hasAttribute(copyParamsAttr)) {\n const paramsString = fragment.getRawAttribute(\n copyParamsAttr,\n ) as string;\n options.copyParams = paramsString\n .split('&')\n .map(param => param.trim())\n .filter(Boolean);\n }\n if (event) {\n if (fragment.hasAttribute(Procedure.attrName(event, 'adjust'))) {\n const adjustSelector = fragment.getRawAttribute(\n Procedure.attrName(event, 'adjust'),\n ) as string | null;\n if (adjustSelector) {\n const adjustElements = document.body.querySelectorAll(adjustSelector);\n if (adjustElements.length > 0) {\n options.adjustFragments = [];\n adjustElements.forEach(element => {\n const fragment = Fragment.get(element);\n if (fragment) {\n options.adjustFragments!.push(fragment as ElementFragment);\n }\n });\n } else {\n Log.error(\n 'Haori',\n `Adjust element not found: ${adjustSelector}` +\n ` (${Procedure.attrName(event, 'adjust')})`,\n );\n }\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'adjust-value'))) {\n const valueString = fragment.getRawAttribute(\n Procedure.attrName(event, 'adjust-value'),\n ) as string;\n const value = Number(valueString);\n if (!isNaN(value)) {\n options.adjustValue = value;\n }\n }\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-add'))) {\n options.rowAdd = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-remove'))) {\n options.rowRemove = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-prev'))) {\n options.rowMovePrev = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'row-next'))) {\n options.rowMoveNext = true;\n }\n if (fragment.hasAttribute(`${Env.prefix}${event}-after-run`)) {\n const body = fragment.getRawAttribute(\n `${Env.prefix}${event}-after-run`,\n ) as string;\n try {\n options.afterCallback = new Function(\n 'response',\n `\n\"use strict\";\n${body}\n`,\n ) as (\n response: Response | Record<string, unknown>,\n ) => AfterCallbackResult | boolean | void;\n } catch (e) {\n Log.error('Haori', `Invalid after script: ${e}`);\n }\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'dialog'))) {\n options.dialogMessage = (fragment.getAttribute(\n Procedure.attrName(event, 'dialog'),\n ) as string).replace(/\\\\n/g, '\\n');\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'toast'))) {\n options.toastMessage = fragment.getAttribute(\n Procedure.attrName(event, 'toast'),\n ) as string;\n const rawLevel = fragment.getRawAttribute(\n Procedure.attrName(event, 'toast-level'),\n );\n const validLevels = ['info', 'warning', 'error', 'success'] as const;\n type ToastLevel = (typeof validLevels)[number];\n const isValidLevel = validLevels.includes(rawLevel as ToastLevel);\n options.toastLevel = isValidLevel ? (rawLevel as ToastLevel) : null;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'redirect'))) {\n options.redirectUrl = fragment.getAttribute(\n Procedure.attrName(event, 'redirect'),\n ) as string;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'scroll-error'))) {\n options.scrollOnError = true;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'scroll'))) {\n options.scrollTarget = fragment.getAttribute(\n Procedure.attrName(event, 'scroll'),\n ) as string;\n }\n // history(data-{event}-history / history-data / history-form)\n if (fragment.hasAttribute(Procedure.attrName(event, 'history'))) {\n options.historyUrl = fragment.getAttribute(\n Procedure.attrName(event, 'history'),\n ) as string | null;\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'history-data'))) {\n options.historyData = Procedure.resolveDataAttribute(\n fragment,\n Procedure.attrName(event, 'history-data'),\n );\n }\n if (fragment.hasAttribute(Procedure.attrName(event, 'history-form'))) {\n const historyFormSelector = fragment.getRawAttribute(\n Procedure.attrName(event, 'history-form'),\n ) as string | null;\n if (historyFormSelector) {\n const historyFormElement =\n document.body.querySelector(historyFormSelector);\n if (historyFormElement !== null) {\n options.historyFormFragment = Form.getFormFragment(\n Fragment.get(historyFormElement) as ElementFragment,\n );\n } else {\n Log.error(\n 'Haori',\n `Form element not found: ${historyFormSelector}` +\n ` (${Procedure.attrName(event, 'history-form')})`,\n );\n }\n } else {\n options.historyFormFragment = Form.getFormFragment(fragment);\n }\n }\n\n // reset/refetch/click/open/close(イベント、CSSセレクタ)\n const selectorAttrs = [\n 'reset',\n 'refetch',\n 'click',\n 'copy',\n 'open',\n 'close',\n ] as const;\n selectorAttrs.forEach(attrKey => {\n const attrName = Procedure.attrName(event, attrKey);\n if (!fragment.hasAttribute(attrName)) {\n return;\n }\n const selector = fragment.getRawAttribute(attrName) as string | null;\n const list: ElementFragment[] = [];\n if (selector) {\n const elements = document.body.querySelectorAll(selector);\n elements.forEach(el => {\n const frag = Fragment.get(el);\n if (frag) {\n list.push(frag as ElementFragment);\n }\n });\n if (list.length === 0) {\n Log.error('Haori', `Element not found: ${selector} (${attrName})`);\n }\n } else {\n // 値が省略されている場合は自要素を対象\n list.push(fragment);\n }\n if (list.length > 0) {\n switch (attrKey) {\n case 'reset':\n options.resetFragments = list;\n break;\n case 'refetch':\n options.refetchFragments = list;\n break;\n case 'click':\n options.clickFragments = list;\n break;\n case 'copy':\n options.copyFragments = list;\n break;\n case 'open':\n options.openFragments = list;\n break;\n case 'close':\n options.closeFragments = list;\n break;\n }\n }\n });\n }\n\n // 非イベントの data / form(data-fetch-data / data-fetch-form)も取り込む\n if (!event) {\n if (fragment.hasAttribute(Procedure.attrName(null, 'data', true))) {\n options.data = Procedure.resolveDataAttribute(\n fragment,\n Procedure.attrName(null, 'data', true),\n );\n }\n if (fragment.hasAttribute(Procedure.attrName(null, 'form', true))) {\n const formSelector = fragment.getRawAttribute(\n Procedure.attrName(null, 'form', true),\n ) as string | null;\n if (formSelector) {\n const formElement = document.body.querySelector(formSelector);\n if (formElement !== null) {\n options.formFragment = Form.getFormFragment(\n Fragment.get(formElement) as ElementFragment,\n );\n } else {\n Log.error(\n 'Haori',\n `Form element not found: ${formSelector} (` +\n `${Procedure.attrName(null, 'fetch-form', true)})`,\n );\n }\n } else {\n // 属性はあるが値が省略された場合は自要素もしくは先祖の form を対象\n options.formFragment = Form.getFormFragment(fragment);\n }\n }\n }\n\n // fetch が指定されているのにバインド先が無い場合、デフォルトで自要素にバインド\n if (\n hasFetchAttr &&\n (!options.bindFragments || options.bindFragments.length === 0)\n ) {\n options.bindFragments = [fragment];\n }\n return options;\n }\n\n /**\n * ElementFragment の構造的タイプガード。\n *\n * @param value チェックする値\n * @returns ElementFragment である場合は true、それ以外は false\n */\n private static isElementFragment(value: unknown): value is ElementFragment {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.getTarget === 'function' &&\n typeof obj.getChildElementFragments === 'function'\n );\n }\n\n /** オプション */\n private readonly options: ProcedureOptions;\n\n /**\n * オプションを指定してProcedureクラスのインスタンスを生成します。\n *\n * @param options オプション\n */\n constructor(options: ProcedureOptions);\n\n /**\n * フラグメントの属性からオプションを生成してProcedureクラスのインスタンスを生成します。\n *\n * @param fragment フラグメント\n * @param event イベント名\n */\n constructor(fragment: ElementFragment, event: string | null);\n\n /**\n * コンストラクタ。\n *\n * @param arg1 オプションもしくはフラグメント\n * @param arg2 イベント名\n */\n constructor(\n arg1: ProcedureOptions | ElementFragment,\n arg2: string | null = null,\n ) {\n if (Procedure.isElementFragment(arg1)) {\n this.options = Procedure.buildOptions(arg1, arg2);\n } else {\n this.options = arg1;\n }\n }\n\n /**\n * 一連の処理を実行します。オプションが空の場合は即座にresolveされます。\n *\n * @returns 実行結果のPromise\n */\n run(): Promise<void> {\n return this.runWithResult().then(() => undefined);\n }\n\n /**\n * 一連の処理を実行し、成功したかどうかを返します。\n *\n * @returns 成功した場合は true、途中停止や失敗時は false\n */\n runWithResult(): Promise<boolean> {\n return this.execute();\n }\n\n /**\n * 一連の処理を実行します。成功結果を内部で扱うための実体です。\n *\n * @returns 実行成功時は true、停止や失敗時は false\n */\n private async execute(): Promise<boolean> {\n if (Object.keys(this.options).length === 0) {\n return false;\n }\n if (\n this.options.formFragment &&\n this.validate(this.options.formFragment) === false\n ) {\n return false;\n }\n const confirmed = await this.confirm();\n if (!confirmed) {\n return false;\n }\n let fetchUrl = this.options.fetchUrl;\n let fetchOptions = this.options.fetchOptions;\n if (this.options.beforeCallback) {\n const result = this.options.beforeCallback(\n fetchUrl || null,\n fetchOptions || null,\n );\n if (result !== undefined && result !== null) {\n if (result === false || (typeof result === 'object' && result.stop)) {\n return false;\n }\n if (typeof result === 'object') {\n fetchUrl = ('fetchUrl' in result ? result.fetchUrl : fetchUrl) as\n | string\n | null;\n fetchOptions = (\n 'fetchOptions' in result ? result.fetchOptions : fetchOptions\n ) as RequestInit | null;\n }\n }\n }\n\n // フォーム値と data を統合してペイロードを作成\n const payload: Record<string, unknown> = {};\n if (this.options.formFragment) {\n const formValues = Form.getValues(this.options.formFragment);\n Object.assign(payload, formValues);\n }\n if (this.options.data && typeof this.options.data === 'object') {\n Object.assign(payload, this.options.data);\n }\n\n const hasPayload = Object.keys(payload).length > 0;\n if (fetchUrl) {\n const finalOptions: RequestInit = {...(fetchOptions || {})};\n const headers = new Headers(\n (finalOptions.headers as HeadersInit | undefined) || undefined,\n );\n const requestedMethod = (finalOptions.method || 'GET').toUpperCase();\n const isDemoQueryNormalization =\n Env.runtime === 'demo' && !isQueryTransportMethod(requestedMethod);\n const method = isDemoQueryNormalization ? 'GET' : requestedMethod;\n\n finalOptions.method = method;\n\n if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS') {\n if (hasPayload) {\n fetchUrl = appendPayloadToUrl(fetchUrl!, payload);\n }\n } else if (hasPayload) {\n const contentType = headers.get('Content-Type') || '';\n if (/multipart\\/form-data/i.test(contentType)) {\n headers.delete('Content-Type');\n const formData = new FormData();\n for (const [k, v] of Object.entries(payload)) {\n if (v === undefined || v === null) {\n formData.append(k, '');\n } else if (v instanceof Blob) {\n formData.append(k, v);\n } else if (Array.isArray(v)) {\n v.forEach(item => formData.append(k, String(item)));\n } else if (typeof v === 'object') {\n formData.append(k, JSON.stringify(v));\n } else {\n formData.append(k, String(v));\n }\n }\n finalOptions.body = formData;\n } else if (/application\\/x-www-form-urlencoded/i.test(contentType)) {\n const params = new URLSearchParams();\n for (const [k, v] of Object.entries(payload)) {\n if (v === undefined) {\n continue;\n }\n if (v === null) {\n params.append(k, '');\n } else if (Array.isArray(v)) {\n v.forEach(item => params.append(k, String(item)));\n } else if (typeof v === 'object') {\n params.append(k, JSON.stringify(v));\n } else {\n params.append(k, String(v));\n }\n }\n finalOptions.body = params;\n } else {\n headers.set('Content-Type', 'application/json');\n finalOptions.body = JSON.stringify(payload);\n }\n }\n\n finalOptions.headers = headers;\n let queryString: string | undefined;\n\n if (isDemoQueryNormalization) {\n queryString = fetchUrl\n ? new URL(fetchUrl, window.location.href).search || undefined\n : undefined;\n headers.delete('Content-Type');\n Log.info('Haori demo fetch normalization', {\n runtime: Env.runtime,\n requestedMethod,\n effectiveMethod: method,\n transportMode: 'query-get',\n url: fetchUrl,\n payload: hasPayload ? payload : undefined,\n queryString,\n });\n }\n\n // fetchstartイベントを発火\n if (this.options.targetFragment && fetchUrl) {\n const startedAt = performance.now();\n const fetchStartMetadata = {\n runtime: Env.runtime,\n requestedMethod,\n effectiveMethod: method,\n transportMode: isDemoQueryNormalization ? 'query-get' : 'http',\n ...(isDemoQueryNormalization ? {queryString} : {}),\n };\n\n HaoriEvent.fetchStart(\n this.options.targetFragment.getTarget(),\n fetchUrl,\n finalOptions,\n hasPayload ? payload : undefined,\n fetchStartMetadata,\n );\n\n return fetch(fetchUrl, finalOptions)\n .then(response => {\n return this.handleFetchResult(\n response,\n fetchUrl || undefined,\n startedAt,\n );\n })\n .catch(error => {\n if (fetchUrl) {\n HaoriEvent.fetchError(\n this.options.targetFragment!.getTarget(),\n fetchUrl,\n error,\n );\n }\n throw error;\n });\n }\n return fetch(fetchUrl, finalOptions).then(response => {\n return this.handleFetchResult(response, fetchUrl || undefined);\n });\n }\n\n // fetchUrlが無い場合(changeイベント等)、bindFragmentsが無ければformFragmentにバインド\n if (\n (!this.options.bindFragments ||\n this.options.bindFragments.length === 0) &&\n this.options.formFragment &&\n hasPayload\n ) {\n // 双方向バインディング: フォーム値を自動的にバインディングデータに反映\n const formFragment = this.options.formFragment;\n const formElement = formFragment.getTarget();\n\n formElement.setAttribute(\n `${Env.prefix}bind`,\n JSON.stringify(payload),\n );\n\n const bindingData = formFragment.getBindingData();\n Object.assign(bindingData, payload);\n await Core.setBindingData(formElement, bindingData);\n }\n\n const merged = hasPayload ? payload : {};\n const response = new Response(JSON.stringify(merged), {\n headers: {'Content-Type': 'application/json'},\n });\n return this.handleFetchResult(response);\n }\n\n /**\n * フェッチ後の処理を実行します。\n */\n private async handleFetchResult(\n response: Response,\n url?: string,\n startedAt?: number,\n ): Promise<boolean> {\n const activeHaori = resolveProcedureHaoriApi();\n // エラー応答時は以後の処理を停止し、メッセージを伝播\n if (!response.ok) {\n if (this.options.targetFragment && url) {\n HaoriEvent.fetchError(\n this.options.targetFragment.getTarget(),\n url,\n new Error(`${response.status} ${response.statusText}`),\n response.status,\n startedAt,\n );\n }\n await this.handleFetchError(response);\n return false;\n }\n\n // fetchendイベントを発火\n if (this.options.targetFragment && url && startedAt) {\n HaoriEvent.fetchEnd(\n this.options.targetFragment.getTarget(),\n url,\n response.status,\n startedAt,\n );\n }\n\n if (this.options.afterCallback) {\n const result = this.options.afterCallback(response);\n if (result !== undefined && result !== null) {\n if (result === false || (typeof result === 'object' && result.stop)) {\n return false;\n }\n if (typeof result === 'object' && 'response' in result) {\n response = (\n 'response' in result ? result.response : response\n ) as Response;\n }\n }\n }\n const promises: Promise<unknown>[] = [];\n promises.push(this.bindResult(response));\n promises.push(this.adjust());\n promises.push(this.addRow());\n promises.push(this.removeRow());\n promises.push(this.movePrevRow());\n promises.push(this.moveNextRow());\n await Promise.all(promises);\n\n if (this.options.resetFragments && this.options.resetFragments.length > 0) {\n await Promise.all(\n this.options.resetFragments.map(fragment => Form.reset(fragment)),\n );\n }\n\n await this.copy();\n\n const deferredPromises: Promise<unknown>[] = [];\n if (\n this.options.refetchFragments &&\n this.options.refetchFragments.length > 0\n ) {\n this.options.refetchFragments.forEach(fragment => {\n deferredPromises.push(new Procedure(fragment, null).run());\n });\n }\n if (this.options.clickFragments && this.options.clickFragments.length > 0) {\n this.options.clickFragments.forEach(fragment => {\n const target = fragment.getTarget();\n if (typeof target.click === 'function') {\n target.click();\n } else {\n target.dispatchEvent(\n new MouseEvent('click', {bubbles: true, cancelable: true}),\n );\n }\n });\n }\n if (this.options.openFragments && this.options.openFragments.length > 0) {\n this.options.openFragments.forEach(fragment => {\n const target = fragment.getTarget();\n if (target instanceof HTMLElement) {\n deferredPromises.push(activeHaori.openDialog(target));\n } else {\n Log.error('Haori', 'Element is not an HTML element: ', target);\n }\n });\n }\n if (this.options.closeFragments && this.options.closeFragments.length > 0) {\n this.options.closeFragments.forEach(fragment => {\n const target = fragment.getTarget();\n if (target instanceof HTMLElement) {\n deferredPromises.push(activeHaori.closeDialog(target));\n } else {\n Log.error('Haori', 'Element is not an HTML element: ', target);\n }\n });\n }\n // 仕様順序: 先に各種操作(bind/adjust/row/reset/refetch/click/open/close)を完了\n await Promise.all(deferredPromises);\n // その後にダイアログ/トーストを表示\n if (this.options.dialogMessage) {\n await activeHaori.dialog(this.options.dialogMessage);\n }\n if (this.options.toastMessage) {\n await activeHaori.toast(\n this.options.toastMessage,\n this.options.toastLevel ?? 'info',\n );\n }\n this.pushHistory();\n if (this.options.scrollTarget) {\n const el = document.querySelector<HTMLElement>(this.options.scrollTarget);\n el?.scrollIntoView({behavior: 'smooth', block: 'nearest'});\n }\n if (this.options.redirectUrl) {\n window.location.href = this.options.redirectUrl;\n }\n return true;\n }\n\n /**\n * history.pushState を実行します。\n *\n * `historyUrl` / `historyData` / `historyFormFragment` の内容を基に URL を組み立て、\n * `history.pushState()` を呼び出します。いずれも未指定の場合は何もしません。\n * 不正 URL・オリジン違反・例外は `Log.error` でログ出力してスキップし、後続処理は継続します。\n */\n private pushHistory(): void {\n const hasHistoryUrl =\n this.options.historyUrl !== undefined && this.options.historyUrl !== null;\n const hasHistoryData =\n this.options.historyData !== undefined &&\n this.options.historyData !== null;\n const hasHistoryForm =\n this.options.historyFormFragment !== undefined &&\n this.options.historyFormFragment !== null;\n\n if (!hasHistoryUrl && !hasHistoryData && !hasHistoryForm) {\n return;\n }\n\n try {\n const baseUrlString = hasHistoryUrl\n ? (this.options.historyUrl as string)\n : window.location.pathname;\n const url = new URL(baseUrlString, window.location.href);\n\n if (url.origin !== window.location.origin) {\n const errorMessage =\n 'history.pushState: cross-origin URL is not allowed: ' +\n url.toString();\n Log.error(\n 'Haori',\n errorMessage,\n );\n return;\n }\n\n const appendParams = (values: Record<string, unknown>): void => {\n for (const [k, v] of Object.entries(values)) {\n if (v === undefined || v === null) {\n continue;\n }\n if (Array.isArray(v)) {\n v.forEach(item => url.searchParams.append(k, String(item)));\n } else if (typeof v === 'object') {\n url.searchParams.set(k, JSON.stringify(v));\n } else {\n url.searchParams.set(k, String(v));\n }\n }\n };\n\n if (hasHistoryData) {\n appendParams(this.options.historyData as Record<string, unknown>);\n }\n if (hasHistoryForm) {\n appendParams(\n Form.getValues(\n this.options.historyFormFragment as ElementFragment,\n ),\n );\n }\n\n history.pushState(\n {[PROCEDURE_HISTORY_STATE_KEY]: true},\n '',\n url.toString(),\n );\n } catch (e) {\n Log.error('Haori', `history.pushState failed: ${e}`);\n }\n }\n\n /**\n * フェッチエラー応答のメッセージを適切な要素へ伝播します。\n */\n private async handleFetchError(response: Response): Promise<boolean> {\n // ベースとなるフォーム/フラグメントを決定\n let baseFragment: ElementFragment | null = null;\n if (this.options.formFragment) {\n baseFragment = this.options.formFragment;\n } else if (this.options.targetFragment) {\n baseFragment =\n Form.getFormFragment(this.options.targetFragment) ||\n this.options.targetFragment;\n }\n\n const addGeneralMessage = async (message: string) => {\n const targetEl = baseFragment ? baseFragment.getTarget() : document.body;\n await resolveProcedureHaoriApi().addErrorMessage(targetEl, message);\n };\n\n const scrollToFirstError = () => {\n if (!this.options.scrollOnError) {\n return;\n }\n const root = baseFragment ? baseFragment.getTarget() : document.body;\n // addErrorMessage はフォーム以外の target に対して parentElement へエラーを付与するため、\n // root 自身・parentElement・root 配下の順で探索する\n const errorTarget =\n root.getAttribute('data-message-level') === 'error'\n ? root\n : root.parentElement?.getAttribute('data-message-level') === 'error'\n ? root.parentElement\n : root.querySelector<HTMLElement>('[data-message-level=\"error\"]');\n errorTarget?.scrollIntoView({behavior: 'smooth', block: 'nearest'});\n };\n\n // コンテンツタイプに応じて解析\n const contentType = response.headers.get('Content-Type') || '';\n if (contentType.includes('application/json')) {\n try {\n const data = await response.json();\n // 代表的な形式に対応\n const entries: Array<{key?: string; message: string}> = [];\n if (data && typeof data === 'object') {\n if (typeof data.message === 'string') {\n entries.push({message: data.message});\n }\n if (Array.isArray(data.messages)) {\n for (const m of data.messages) {\n if (typeof m === 'string') {\n entries.push({message: m});\n }\n }\n }\n if (data.errors && typeof data.errors === 'object') {\n for (const [k, v] of Object.entries(data.errors)) {\n if (Array.isArray(v)) {\n entries.push({key: k, message: v.join('\\n')});\n } else if (typeof v === 'string') {\n entries.push({key: k, message: v});\n } else if (v != null) {\n entries.push({key: k, message: String(v)});\n }\n }\n }\n // キー: 値(文字列/配列)形式にフォールバック\n if (entries.length === 0) {\n for (const [k, v] of Object.entries(data)) {\n if (k === 'message' || k === 'messages' || k === 'errors') {\n continue;\n }\n if (Array.isArray(v)) {\n entries.push({key: k, message: v.join('\\n')});\n } else if (typeof v === 'string') {\n entries.push({key: k, message: v});\n }\n }\n }\n }\n if (entries.length === 0) {\n // 汎用メッセージ\n await addGeneralMessage(`${response.status} ${response.statusText}`);\n scrollToFirstError();\n return false;\n }\n // メッセージを反映\n for (const e of entries) {\n if (e.key && baseFragment) {\n await Form.addErrorMessage(baseFragment, e.key, e.message);\n } else {\n await addGeneralMessage(e.message);\n }\n }\n scrollToFirstError();\n return false;\n } catch {\n // JSON 解析失敗時はテキストにフォールバック\n }\n }\n // テキストとして処理\n try {\n const text = await response.text();\n if (text && text.trim().length > 0) {\n await addGeneralMessage(text.trim());\n } else {\n await addGeneralMessage(`${response.status} ${response.statusText}`);\n }\n } catch {\n await addGeneralMessage(`${response.status} ${response.statusText}`);\n }\n scrollToFirstError();\n return false;\n }\n\n /**\n * 対象のフラグメント以下の入力要素に対してバリデーションを実行します。\n * バリデーションエラーがある場合は、最初のエラー要素にフォーカスを移動します。\n *\n * @param fragment 対象のフラグメント\n * @returns バリデーション結果(true: 成功, false: 失敗)\n */\n validate(fragment: ElementFragment): boolean {\n if (this.options.valid !== true) {\n return true;\n }\n const firstInvalid = this.findFirstInvalid(fragment);\n if (firstInvalid === null) {\n return true;\n }\n // 検出フェーズ(findFirstInvalid)は checkValidity で副作用なく走査済み。\n // reportValidity と focus は確定した 1 要素にだけ呼び出す。\n (\n firstInvalid as\n | HTMLInputElement\n | HTMLSelectElement\n | HTMLTextAreaElement\n ).reportValidity();\n firstInvalid.focus();\n if (this.options.scrollOnError) {\n firstInvalid.scrollIntoView({behavior: 'smooth', block: 'nearest'});\n }\n return false;\n }\n\n /**\n * 対象フラグメント以下で DOM 順の最上部にある invalid 要素を返します。\n * 副作用のない checkValidity のみを使用し、検出のみを行います。\n *\n * @param fragment 対象のフラグメント\n * @returns 最初の invalid 要素、なければ null\n */\n private findFirstInvalid(fragment: ElementFragment): HTMLElement | null {\n // 子要素を逆順に処理することで、DOM 順の先頭要素が最後に found を上書きし、\n // 最終的に最上部の invalid 要素が返る\n let found: HTMLElement | null = null;\n for (const child of fragment.getChildElementFragments().reverse()) {\n const result = this.findFirstInvalid(child);\n if (result !== null) {\n found = result;\n }\n }\n // 自身は子より DOM 上位にあるため、invalid なら子の結果を上書きする\n if (!this.checkOne(fragment)) {\n return fragment.getTarget();\n }\n return found;\n }\n\n /**\n * 対象のフラグメントに対して、副作用なく有効性を検査します。\n * reportValidity は使わず checkValidity のみ呼び出します。\n *\n * @param fragment 対象のフラグメント\n * @returns 有効なら true、無効なら false\n */\n private checkOne(fragment: ElementFragment): boolean {\n const target = fragment.getTarget();\n if (\n target instanceof HTMLInputElement ||\n target instanceof HTMLSelectElement ||\n target instanceof HTMLTextAreaElement\n ) {\n return target.checkValidity();\n }\n return true;\n }\n\n /**\n * 確認メッセージを表示し、ユーザーの確認を求めます。\n * メッセージが設定されていない場合は、即座に成功とみなします。\n *\n * @returns ユーザーの確認結果を含むPromise(true: 確認, false: キャンセル)\n */\n private confirm(): Promise<boolean> {\n const message = this.options.confirmMessage;\n if (message === null || message === undefined) {\n return Promise.resolve(true);\n }\n return resolveProcedureHaoriApi().confirm(message);\n }\n\n /**\n * 結果データを対象のフラグメントにバインドします。\n *\n * @param response フェッチのレスポンスオブジェクト\n */\n private bindResult(response: Response): Promise<void> {\n if (\n !this.options.bindFragments ||\n this.options.bindFragments.length === 0\n ) {\n return Promise.resolve();\n }\n const promise = response.headers\n .get('Content-Type')\n ?.includes('application/json')\n ? response.json()\n : response.text();\n return promise.then(data => {\n if (this.options.bindParams) {\n const newData = {} as Record<string, unknown>;\n this.options.bindParams.forEach(param => {\n if (data && typeof data === 'object' && param in data) {\n newData[param] = data[param];\n }\n });\n data = newData;\n }\n const promises: Promise<unknown>[] = [];\n if (this.options.bindArg) {\n this.options.bindFragments!.forEach(fragment => {\n const bindingData = fragment.getBindingData();\n const bindArg = this.options.bindArg as string;\n if (\n data &&\n typeof data === 'object' &&\n !Array.isArray(data)\n ) {\n const currentValue = bindingData[bindArg];\n const currentObject =\n currentValue &&\n typeof currentValue === 'object' &&\n !Array.isArray(currentValue)\n ? (currentValue as Record<string, unknown>)\n : {};\n bindingData[bindArg] = this.mergeAppendBindingData(\n fragment,\n data as Record<string, unknown>,\n currentObject,\n );\n } else {\n bindingData[bindArg] = data;\n }\n promises.push(Core.setBindingData(fragment.getTarget(), bindingData));\n });\n } else if (typeof data === 'string') {\n Log.error('Haori', 'string data cannot be bound without a bindArg.');\n return Promise.reject(\n new Error('string data cannot be bound without a bindArg.'),\n );\n } else {\n this.options.bindFragments!.forEach(fragment => {\n const resolvedData = this.mergeAppendBindingData(\n fragment,\n data as Record<string, unknown>,\n );\n promises.push(\n Core.setBindingData(\n fragment.getTarget(),\n resolvedData,\n ),\n );\n });\n }\n return Promise.all(promises).then(() => undefined);\n });\n }\n\n /**\n * bind-append 指定があるキーについて、既存配列と結合したデータを返します。\n */\n private mergeAppendBindingData(\n fragment: ElementFragment,\n data: Record<string, unknown>,\n currentData: Record<string, unknown> = fragment.getBindingData(),\n ): Record<string, unknown> {\n if (\n !this.options.bindAppendParams ||\n this.options.bindAppendParams.length === 0\n ) {\n return data;\n }\n\n const merged = {...data};\n const current = currentData;\n for (const key of this.options.bindAppendParams) {\n const incoming = merged[key];\n const existing = current[key];\n if (Array.isArray(existing) && Array.isArray(incoming)) {\n merged[key] = existing.concat(incoming);\n }\n }\n return merged;\n }\n\n /**\n * 指定されたフラグメントへバインディングデータをコピーします。\n */\n private copy(): Promise<void> {\n if (\n !this.options.copyFragments ||\n this.options.copyFragments.length === 0\n ) {\n return Promise.resolve();\n }\n\n const sourceData = this.resolveCopySourceData();\n const copyData = this.pickCopyData(sourceData);\n const promises = this.options.copyFragments.map(fragment => {\n const bindingData = {\n ...fragment.getBindingData(),\n ...copyData,\n };\n return Core.setBindingData(fragment.getTarget(), bindingData);\n });\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * copy のコピー元データを取得します。\n */\n private resolveCopySourceData(): Record<string, unknown> {\n if (this.options.formFragment) {\n return Form.getValues(this.options.formFragment);\n }\n if (this.options.targetFragment) {\n return {...this.options.targetFragment.getBindingData()};\n }\n return {};\n }\n\n /**\n * copy-params が指定されている場合は対象キーだけ抽出します。\n */\n private pickCopyData(\n sourceData: Record<string, unknown>,\n ): Record<string, unknown> {\n if (!this.options.copyParams || this.options.copyParams.length === 0) {\n return sourceData;\n }\n\n const filtered: Record<string, unknown> = {};\n this.options.copyParams.forEach(param => {\n if (param in sourceData) {\n filtered[param] = sourceData[param];\n }\n });\n return filtered;\n }\n\n /**\n * 値の増減を行います。\n */\n private adjust(): Promise<void> {\n if (\n !this.options.adjustFragments ||\n this.options.adjustFragments.length === 0\n ) {\n return Promise.resolve();\n }\n const adjustValue = this.options.adjustValue ?? 0;\n const promises: Promise<void>[] = [];\n for (const fragment of this.options.adjustFragments) {\n let valueString = fragment.getValue();\n if (\n valueString === null ||\n valueString === undefined ||\n valueString === ''\n ) {\n valueString = '0';\n }\n let value = Number(valueString);\n if (isNaN(value)) {\n value = 0;\n }\n value += adjustValue;\n promises.push(fragment.setValue(String(value)));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 行フラグメントを取得します。\n *\n * @returns 行フラグメントまたはnull\n */\n private getRowFragment(): ElementFragment | null {\n if (!this.options.targetFragment) {\n Log.error('Haori', 'Target fragment is not specified for row operation.');\n return null;\n }\n const rowFragment = this.options.targetFragment.closestByAttribute(\n `${Env.prefix}row`,\n );\n if (!rowFragment) {\n Log.error('Haori', 'Row fragment not found.');\n return null;\n }\n return rowFragment;\n }\n\n /**\n * 行を追加します。\n *\n * @returns 処理結果のPromise\n */\n private addRow(): Promise<void> {\n if (this.options.rowAdd !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n const promises: Promise<void>[] = [];\n const newFragment = rowFragment.clone();\n promises.push(\n rowFragment.getParent()!.insertAfter(newFragment, rowFragment),\n );\n promises.push(Core.evaluateAll(newFragment));\n // 追加された行のフォーム要素をリセット\n promises.push(Form.reset(newFragment as ElementFragment));\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * 行を削除します。\n *\n * @returns 処理結果のPromise\n */\n private removeRow(): Promise<void> {\n if (this.options.rowRemove !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n // 1行だった場合は削除しない\n const parent = rowFragment.getParent();\n if (parent) {\n const siblings = parent.getChildElementFragments().filter(child => {\n // data-each-before と data-each-after を除外\n return (\n !child.hasAttribute(`${Env.prefix}each-before`) &&\n !child.hasAttribute(`${Env.prefix}each-after`)\n );\n });\n if (siblings.length <= 1) {\n return Promise.resolve();\n }\n }\n return rowFragment.remove();\n }\n\n /**\n * 前の行へ移動します。\n *\n * @returns 処理結果のPromise\n */\n private movePrevRow(): Promise<void> {\n if (this.options.rowMovePrev !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n const prevFragment = rowFragment.getPrevious();\n if (!prevFragment) {\n return Promise.resolve();\n }\n const parent = rowFragment.getParent();\n if (!parent) {\n return Promise.resolve();\n }\n return parent.insertBefore(rowFragment, prevFragment);\n }\n\n /**\n * 次の行へ移動します。\n *\n * @returns 処理結果のPromise\n */\n private moveNextRow(): Promise<void> {\n if (this.options.rowMoveNext !== true) {\n return Promise.resolve();\n }\n const rowFragment = this.getRowFragment();\n if (!rowFragment) {\n return Promise.reject(new Error('Row fragment not found.'));\n }\n const nextFragment = rowFragment.getNext();\n if (!nextFragment) {\n return Promise.resolve();\n }\n const parent = rowFragment.getParent();\n if (!parent) {\n return Promise.resolve();\n }\n return parent.insertAfter(rowFragment, nextFragment);\n }\n}\n","/**\n * @fileoverview URLパラメータ取得クラス\n *\n * URLのクエリパラメータを取得します。\n */\n\nexport default class Url {\n /**\n * URLのクエリパラメータを取得します。\n *\n * @returns URLのクエリパラメータのキーと値のマップ\n */\n public static readParams(): Record<string, string> {\n const params: Record<string, string> = {};\n const queryString = window.location.search;\n const urlParams = new URLSearchParams(queryString);\n urlParams.forEach((value, key) => {\n params[key] = value;\n });\n return params;\n }\n}\n","/**\n * @fileoverview HTMLインポート機能\n *\n * 指定URLの HTML を取得し、body タグの中身のみを取り出します。\n * 仕様: data-import — 指定したURLの body タグの中身を対象エレメントの innerHTML に設定する。\n */\nimport Log from './log';\n\n/**\n * インポート機能を提供するクラスです。\n */\nexport class Import {\n /**\n * 指定URLから HTML を取得し、body 内の HTML 文字列を返します。\n *\n * 振る舞い:\n * - HTTP ステータスが成功以外の場合は例外を投げます。\n * - HTML のパースに失敗した場合はログを出力し、テキスト全体を返します(フォールバック)。\n * - body タグが存在しない場合もテキスト全体を返します(フォールバック)。\n *\n * @param url 取得先の URL\n * @param init fetch のオプション(任意)\n * @returns body 内の HTML 文字列\n */\n public static async load(url: string, init?: RequestInit): Promise<string> {\n let response: Response;\n try {\n response = await fetch(url, init);\n } catch (e) {\n Log.error('[Haori]', 'Failed to fetch import source:', url, e);\n throw new Error(`Failed to fetch: ${url}`);\n }\n\n if (!response.ok) {\n // ネットワーク/HTTP エラーは上位で扱いやすいように例外化\n const status = `${response.status} ${response.statusText}`;\n Log.error('[Haori]', 'Import HTTP error:', url, status);\n throw new Error(`Failed to load ${url}: ${status}`);\n }\n\n let text: string;\n try {\n text = await response.text();\n } catch (e) {\n Log.error('[Haori]', 'Failed to read response text:', url, e);\n throw new Error(`Failed to read response from: ${url}`);\n }\n\n // HTML としてパースし、body 内のみを返す\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(text, 'text/html');\n if (doc && doc.body) {\n return doc.body.innerHTML;\n }\n Log.warn('[Haori]', 'No body found in imported document:', url);\n return text;\n } catch (e) {\n // パース失敗時はフォールバックとしてテキスト全体を返す\n Log.error('[Haori]', 'Failed to parse imported HTML:', url, e);\n return text;\n }\n }\n}\n","/**\n * @fileoverview Core機能\n *\n * Fragmentの管理、属性変化の監視、条件分岐・繰り返し処理など、\n * アプリケーションの中心的な機能を提供します。\n */\nimport Env from './env';\nimport Form from './form';\nimport Fragment, {ElementFragment, TextFragment} from './fragment';\nimport Log from './log';\nimport Procedure from './procedure';\nimport Url from './url';\nimport {Import} from './import';\nimport Queue from './queue';\nimport HaoriEvent from './event';\n\n/**\n * アプリケーションの中心的な制御を行うクラスです。\n * Fragment の初期化、属性変化の処理、条件分岐・繰り返し処理を管理します。\n */\nexport default class Core {\n /** 属性エイリアスのサフィックス */\n private static readonly ATTRIBUTE_ALIAS_SUFFIX = 'attr-';\n\n /** 優先処理する属性のサフィックス(処理順序で定義) */\n private static readonly PRIORITY_ATTRIBUTE_SUFFIXES = ['bind', 'if', 'each'];\n\n /** 遅延処理する属性のサフィックス */\n private static readonly DEFERRED_ATTRIBUTE_SUFFIXES = ['fetch', 'url-param'];\n\n /** evaluateAll で再評価対象から除外する特殊属性のサフィックス */\n private static readonly EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES = [\n 'bind',\n 'if',\n 'each',\n 'fetch',\n 'import',\n 'url-param',\n ];\n\n /** 属性内プレースホルダ検出用の正規表現 */\n private static readonly ATTRIBUTE_PLACEHOLDER_REGEX =\n /\\{\\{\\{[\\s\\S]+?\\}\\}\\}|\\{\\{[\\s\\S]+?\\}\\}/;\n\n /**\n * 遅延属性かどうか(完全名で判定)を判定します。\n *\n * @param name 属性名\n * @returns 遅延属性かどうか\n */\n private static isDeferredAttributeName(name: string): boolean {\n return Core.DEFERRED_ATTRIBUTE_SUFFIXES.some(\n suffix => name === `${Env.prefix}${suffix}`,\n );\n }\n\n /**\n * evaluateAll で再評価対象から除外する特殊属性かどうかを判定します。\n *\n * @param name 属性名\n * @returns 除外対象かどうか\n */\n private static isEvaluateAllExcludedAttributeName(name: string): boolean {\n return Core.EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES.some(\n suffix => name === `${Env.prefix}${suffix}`,\n );\n }\n\n /**\n * evaluateAll で通常属性を再評価すべきかを判定します。\n *\n * @param name 属性名\n * @param value 属性の生値\n * @returns 再評価する場合は true\n */\n private static shouldReevaluateAttribute(\n name: string,\n value: string | null,\n ): boolean {\n return (\n value !== null &&\n !Core.isEvaluateAllExcludedAttributeName(name) &&\n Core.ATTRIBUTE_PLACEHOLDER_REGEX.test(value)\n );\n }\n\n /**\n * data-attr-* 形式の属性名から実際に更新する属性名を取得します。\n *\n * @param name 属性名\n * @returns 実際の属性名。data-attr-* でない場合は null\n */\n private static getAliasedAttributeName(name: string): string | null {\n const aliasPrefix = `${Env.prefix}${Core.ATTRIBUTE_ALIAS_SUFFIX}`;\n if (!name.startsWith(aliasPrefix) || name.length <= aliasPrefix.length) {\n return null;\n }\n return name.slice(aliasPrefix.length);\n }\n\n /**\n * 実属性の変更が data-attr-* の内部反映かどうかを判定します。\n *\n * @param element 対象要素\n * @param name 変更された属性名\n * @returns data-attr-* の内部反映なら true\n */\n public static isAliasedAttributeReflection(\n element: HTMLElement,\n name: string,\n ): boolean {\n const fragment = Fragment.get(element);\n if (!(fragment instanceof ElementFragment)) {\n return false;\n }\n return fragment.hasAttribute(\n `${Env.prefix}${Core.ATTRIBUTE_ALIAS_SUFFIX}${name}`,\n );\n }\n\n /**\n * プレースホルダを含む通常属性を再評価します。\n * 内部状態の更新は同期的に行い、DOM 反映は fragment 側の非同期更新に委ねます。\n *\n * @param fragment 対象フラグメント\n * @returns 再評価完了の Promise\n */\n private static reevaluateInterpolatedAttributes(\n fragment: ElementFragment,\n ): Promise<void> {\n let chain = Promise.resolve();\n for (const name of fragment.getAttributeNames()) {\n const rawValue = fragment.getRawAttribute(name);\n if (!Core.shouldReevaluateAttribute(name, rawValue)) {\n continue;\n }\n chain = chain.then(() =>\n Core.setAttribute(fragment.getTarget(), name, rawValue),\n );\n }\n return chain.then(() => undefined);\n }\n\n /**\n * 指定された要素と、その子要素をスキャンし、Fragmentを生成します。\n *\n * @param element スキャン対象の要素\n * @returns Promise (スキャンが完了したときに解決される)\n */\n public static scan(element: HTMLElement): Promise<void> {\n const fragment = Fragment.get(element);\n if (!fragment) {\n return Promise.resolve();\n }\n // DOMに組み込まれている場合はmountedをtrueにする\n if (element.parentNode) {\n const parentFragment = Fragment.get(element.parentNode as HTMLElement);\n if (parentFragment?.isMounted()) {\n fragment.setMounted(true);\n } else if (document.body.contains(element)) {\n // document.bodyに含まれている場合はマウント済みとする\n fragment.setMounted(true);\n } else {\n fragment.setMounted(false);\n }\n }\n let attributeChain = Promise.resolve();\n const processedAttributes = new Set<string>();\n for (const suffix of Core.PRIORITY_ATTRIBUTE_SUFFIXES) {\n // 優先属性の処理\n const name = Env.prefix + suffix;\n if (fragment.hasAttribute(name)) {\n attributeChain = attributeChain.then(() =>\n Core.setAttribute(\n fragment.getTarget(),\n name,\n fragment.getRawAttribute(name),\n ),\n );\n processedAttributes.add(name);\n }\n }\n for (const name of fragment.getAttributeNames()) {\n if (processedAttributes.has(name) || Core.isDeferredAttributeName(name)) {\n // すでに処理済みもしくは遅延処理の属性はスキップ\n continue;\n }\n const value = fragment.getRawAttribute(name);\n if (value !== null) {\n attributeChain = attributeChain.then(() =>\n Core.setAttribute(fragment.getTarget(), name, value),\n );\n }\n }\n for (const suffix of Core.DEFERRED_ATTRIBUTE_SUFFIXES) {\n // 遅延属性の処理\n const name = Env.prefix + suffix;\n if (fragment.hasAttribute(name)) {\n attributeChain = attributeChain.then(() =>\n Core.setAttribute(\n fragment.getTarget(),\n name,\n fragment.getRawAttribute(name),\n ),\n );\n processedAttributes.add(name);\n }\n }\n return attributeChain\n .then(() => {\n const childPromises: Promise<void>[] = [];\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n childPromises.push(Core.scan(child.getTarget()));\n } else if (child instanceof TextFragment) {\n childPromises.push(Core.evaluateText(child));\n }\n });\n return Promise.all(childPromises).then(() => undefined);\n })\n .then(() => undefined);\n }\n\n /**\n * エレメントに属性を設定します。\n * 属性固有の処理も行います。\n *\n * @param element エレメント\n * @param name 属性名\n * @param value 属性値\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static setAttribute(\n element: HTMLElement,\n name: string,\n value: string | null,\n ): Promise<void> {\n const fragment = Fragment.get(element);\n const aliasedAttributeName = Core.getAliasedAttributeName(name);\n if (aliasedAttributeName !== null) {\n if (value === null) {\n return fragment.removeAliasedAttribute(name, aliasedAttributeName);\n }\n return fragment.setAliasedAttribute(name, aliasedAttributeName, value);\n }\n const promises: Promise<void>[] = [];\n switch (name) {\n case `${Env.prefix}bind`: {\n if (value === null) {\n fragment.clearBindingDataCache();\n fragment.setBindingData({});\n } else {\n fragment.setBindingData(Core.parseDataBind(value));\n }\n break;\n }\n case `${Env.prefix}if`:\n promises.push(Core.evaluateIf(fragment));\n break;\n case `${Env.prefix}each`:\n promises.push(Core.evaluateEach(fragment));\n break;\n case `${Env.prefix}fetch`:\n promises.push(\n new Procedure(fragment, null).run().then(() => undefined),\n );\n break;\n case `${Env.prefix}import`: {\n if (typeof value === 'string') {\n const target = fragment.getTarget();\n const startedAt = performance.now();\n target.setAttribute(`${Env.prefix}importing`, '');\n HaoriEvent.importStart(target, value);\n\n promises.push(\n Import.load(value)\n .then(html => {\n const bytes = new TextEncoder().encode(html).length;\n // DOM 更新はキュー内で実行し、オブザーバーに差分を拾わせる\n return Queue.enqueue(() => {\n target.innerHTML = html;\n }).then(() => {\n target.removeAttribute(`${Env.prefix}importing`);\n HaoriEvent.importEnd(target, value, bytes, startedAt);\n });\n })\n .catch(error => {\n target.removeAttribute(`${Env.prefix}importing`);\n HaoriEvent.importError(target, value, error);\n Log.error('[Haori]', 'Failed to import HTML:', value, error);\n }) as unknown as Promise<void>,\n );\n }\n break;\n }\n case `${Env.prefix}url-param`: {\n const arg = fragment.getAttribute(`${Env.prefix}url-arg`);\n const params = Url.readParams();\n if (arg === null) {\n promises.push(Core.setBindingData(element, params));\n } else {\n const data = fragment.getRawBindingData() || {};\n data[String(arg)] = params;\n promises.push(Core.setBindingData(element, data));\n }\n break;\n }\n }\n if (value === null) {\n promises.push(fragment.removeAttribute(name));\n } else {\n promises.push(fragment.setAttribute(name, value));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * エレメントに属性を設定し、評価を行います。\n *\n * @param element エレメント\n * @param name 属性名\n * @param value 属性値\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static setBindingData(\n element: HTMLElement,\n data: Record<string, unknown>,\n ): Promise<void> {\n const fragment = Fragment.get(element) as ElementFragment;\n const previous = fragment.getRawBindingData();\n fragment.setBindingData(data);\n let chain = fragment.setAttribute(\n `${Env.prefix}bind`,\n JSON.stringify(data),\n );\n if (element.tagName === 'FORM') {\n const arg = fragment.getAttribute(`${Env.prefix}form-arg`);\n const formValues =\n arg &&\n data[String(arg)] &&\n typeof data[String(arg)] === 'object' &&\n !Array.isArray(data[String(arg)])\n ? (data[String(arg)] as Record<string, unknown>)\n : arg\n ? {}\n : data;\n chain = chain.then(() => Form.syncValues(fragment, formValues));\n }\n chain = chain.then(() => Core.evaluateAll(fragment));\n\n // bindchangeイベントを発火\n HaoriEvent.bindChange(element, previous, data, 'manual');\n\n return chain.then(() => undefined);\n }\n\n /**\n * data-bind 属性の値をパースします。\n *\n * @param data data-bind 属性の値\n * @returns パースされたデータオブジェクト\n */\n public static parseDataBind(data: string): Record<string, unknown> {\n if (data.startsWith('{') || data.startsWith('[')) {\n // JSONとしてパース\n try {\n return JSON.parse(data);\n } catch (e) {\n Log.error('[Haori]', 'Invalid JSON in data-bind:', e);\n return {};\n }\n } else {\n // URLSearchParamsでパース\n const params = new URLSearchParams(data);\n const result: Record<string, unknown> = {};\n for (const [key, value] of params.entries()) {\n if (result[key] !== undefined) {\n // すでに値がある場合は配列化\n if (Array.isArray(result[key])) {\n (result[key] as string[]).push(value);\n } else {\n result[key] = [result[key], value];\n }\n } else {\n result[key] = value;\n }\n }\n return result;\n }\n }\n\n /**\n * ノードを親要素に追加し評価を行います。\n *\n * @param parentElement 親エレメント\n * @param node 追加するノード\n */\n public static addNode(parentElement: HTMLElement, node: Node) {\n const parent = Fragment.get(parentElement);\n // skipMutationNodesが設定されている場合は処理をスキップ\n if (parent.isSkipMutationNodes()) {\n return;\n }\n const next = Fragment.get(node.nextSibling);\n const fragment = Fragment.get(node);\n if (fragment) {\n parent.insertBefore(fragment, next);\n if (fragment instanceof ElementFragment) {\n // 新規追加ノードは属性評価(bind/if/each/import など含む)のフルスキャンを行う。\n // これにより、取り込まれた断片内の data-import の入れ子や data-bind も正しく処理される。\n Core.scan(fragment.getTarget());\n } else if (fragment instanceof TextFragment) {\n Core.evaluateText(fragment);\n }\n }\n }\n\n /**\n * ノードを親要素から削除します。\n *\n * @param node 削除するノード\n */\n public static removeNode(node: Node) {\n const fragment = Fragment.get(node);\n if (fragment) {\n const parent = fragment.getParent();\n // skipMutationNodesが設定されている場合は処理をスキップ\n if (parent && parent.isSkipMutationNodes()) {\n return;\n }\n fragment.remove();\n }\n }\n\n /**\n * ノードのテキストを変更します。\n *\n * @param node 変更するノード\n * @param text 新しいテキスト\n */\n public static changeText(node: Text | Comment, text: string) {\n const fragment = Fragment.get(node);\n if (fragment) {\n fragment.setContent(text);\n }\n }\n\n /**\n * エレメントの値を変更します。\n * フォームの双方向バインディングを考慮し、フォームのバインドデータも更新します。\n *\n * @param element 変更するエレメント\n * @param value 新しい値\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static changeValue(\n element: HTMLElement,\n value: string,\n ): Promise<void> {\n const fragment = Fragment.get(element);\n if (fragment.getValue() === value) {\n return Promise.resolve();\n }\n const promises: Promise<void>[] = [];\n promises.push(fragment.setValue(value));\n const formFragment = Core.getFormFragment(fragment);\n if (formFragment) {\n const values = Form.getValues(formFragment);\n const arg = formFragment.getAttribute(`${Env.prefix}form-arg`);\n let bindingData;\n if (arg) {\n bindingData = formFragment.getRawBindingData();\n if (!bindingData) {\n bindingData = {};\n }\n bindingData[String(arg)] = values;\n } else {\n bindingData = values;\n }\n promises.push(Core.setBindingData(formFragment.getTarget(), bindingData));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * フォームフラグメントを取得します。\n *\n * @param fragment フラグメント\n * @returns フォームフラグメントまたはnull\n */\n private static getFormFragment(\n fragment: ElementFragment,\n ): ElementFragment | null {\n if (fragment.getTarget() instanceof HTMLFormElement) {\n return fragment;\n }\n const parent = fragment.getParent();\n if (parent) {\n return Core.getFormFragment(parent);\n }\n return null;\n }\n\n /**\n * フラグメントとその子要素を評価します。\n *\n * @param fragment 対象フラグメント\n * @return Promise (DOM操作が完了したときに解決される)\n */\n public static evaluateAll(fragment: ElementFragment): Promise<void> {\n const promises: Promise<void>[] = [];\n promises.push(Core.reevaluateInterpolatedAttributes(fragment));\n if (fragment.hasAttribute(`${Env.prefix}if`)) {\n promises.push(Core.evaluateIf(fragment));\n }\n if (fragment.hasAttribute(`${Env.prefix}each`)) {\n return Promise.all(promises)\n .then(() => Core.evaluateEach(fragment))\n .then(() => {\n const childPromises: Promise<void>[] = [];\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n childPromises.push(Core.evaluateAll(child));\n } else if (child instanceof TextFragment) {\n childPromises.push(Core.evaluateText(child));\n }\n });\n return Promise.all(childPromises).then(() => undefined);\n });\n }\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n promises.push(Core.evaluateAll(child));\n } else if (child instanceof TextFragment) {\n promises.push(Core.evaluateText(child));\n }\n });\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * テキストフラグメントを評価します。\n *\n * @param fragment 対象フラグメント\n * @returns Promise (DOM操作が完了したときに解決される)\n */\n public static evaluateText(fragment: TextFragment): Promise<void> {\n return fragment.evaluate();\n }\n\n /**\n * if要素を評価します。\n * 値がfalse、null、undefined、NaNの場合は非表示にし、それ以外の場合は表示します。\n *\n * @param fragment 対象フラグメント\n * @return Promise (DOM操作が完了したときに解決される)\n */\n public static evaluateIf(fragment: ElementFragment): Promise<void> {\n const promises: Promise<void>[] = [];\n const condition = fragment.getAttribute(`${Env.prefix}if`);\n if (\n condition === false ||\n condition === undefined ||\n condition === null ||\n Number.isNaN(condition)\n ) {\n promises.push(\n fragment.hide().then(() => {\n HaoriEvent.hide(fragment.getTarget());\n }),\n );\n } else {\n const childPromises: Promise<void>[] = [];\n fragment.getChildren().forEach(child => {\n if (child instanceof ElementFragment) {\n childPromises.push(Core.evaluateAll(child));\n } else if (child instanceof TextFragment) {\n childPromises.push(Core.evaluateText(child));\n }\n });\n promises.push(\n fragment.show().then(() => {\n HaoriEvent.show(fragment.getTarget());\n }),\n );\n promises.push(Promise.all(childPromises).then(() => undefined));\n }\n return Promise.all(promises).then(() => undefined);\n }\n\n /**\n * each要素を評価します。\n * 非表示または未マウントの場合は処理をスキップします。\n *\n * @param fragment 対象フラグメント\n */\n public static evaluateEach(fragment: ElementFragment): Promise<void> {\n if (!fragment.isVisible() || !fragment.isMounted()) {\n return Promise.resolve();\n }\n let template = fragment.getTemplate();\n if (template === null) {\n // テンプレートの作成\n let found = false;\n fragment.getChildren().forEach(child => {\n if (found) {\n return;\n }\n if (child instanceof ElementFragment) {\n if (\n child.hasAttribute(`${Env.prefix}each-before`) ||\n child.hasAttribute(`${Env.prefix}each-after`)\n ) {\n return;\n }\n // 最初のElementFragmentをテンプレートとして採用\n template = child.clone();\n fragment.setTemplate(template);\n found = true;\n // 元のchildはchildrenから除外\n fragment.removeChild(child);\n // DOMからも必ず除去\n const templateTarget = child.getTarget();\n if (templateTarget.parentNode) {\n templateTarget.parentNode.removeChild(templateTarget);\n }\n child.setMounted(false);\n }\n // TextNodeやCommentNodeはテンプレートにならないので無視\n });\n const data = fragment.getAttribute(`${Env.prefix}each`);\n if (!Array.isArray(data)) {\n Log.error('[Haori]', 'Invalid each attribute:', data);\n return Promise.reject(new Error('Invalid each attribute.'));\n }\n // テンプレートのunmount完了後にupdateDiffを実行\n return this.updateDiff(fragment, data);\n }\n const data = fragment.getAttribute(`${Env.prefix}each`);\n if (!Array.isArray(data)) {\n Log.error('[Haori]', 'Invalid each attribute:', data);\n return Promise.reject(new Error('Invalid each attribute.'));\n }\n return this.updateDiff(fragment, data);\n }\n\n /**\n * 差分を更新します。\n *\n * @param parent 親フラグメント\n * @param newList 新しいリスト\n */\n private static updateDiff(\n parent: ElementFragment,\n newList: (Record<string, unknown> | string | number)[],\n ): Promise<void> {\n const template = parent.getTemplate();\n if (template === null) {\n Log.error('[Haori]', 'Template is not set for each element.');\n return Promise.resolve();\n }\n let indexKey = parent.getAttribute(`${Env.prefix}each-index`);\n if (indexKey) {\n indexKey = String(indexKey);\n }\n const keyArg = parent.getAttribute(`${Env.prefix}each-key`);\n const itemArg = parent.getAttribute(`${Env.prefix}each-arg`);\n const keyDataMap: Map<\n string,\n {item: (typeof newList)[0]; itemIndex: number}\n > = new Map();\n const newKeys: string[] = [];\n newList.forEach((item, itemIndex) => {\n const listKey = Core.createListKey(\n item,\n keyArg ? String(keyArg) : null,\n itemIndex,\n );\n newKeys.push(listKey);\n keyDataMap.set(listKey, {item, itemIndex});\n });\n const removalPromises: Promise<void>[] = [];\n let childElements = parent\n .getChildren()\n .filter(child => child instanceof ElementFragment)\n .filter(\n child =>\n !child.hasAttribute(`${Env.prefix}each-before`) &&\n !child.hasAttribute(`${Env.prefix}each-after`),\n );\n childElements = childElements.filter(child => {\n const index = newKeys.indexOf(String(child.getListKey()));\n if (index === -1) {\n removalPromises.push(child.remove());\n return false;\n }\n return true;\n });\n const srcKeys = childElements.map(child => child.getListKey());\n const baseInsertIndex = parent\n .getChildren()\n .filter(child => child instanceof ElementFragment)\n .filter(child => child.hasAttribute(`${Env.prefix}each-before`)).length;\n let chain = Promise.resolve();\n newKeys.forEach((newKey, loopIndex) => {\n const srcIndex = srcKeys.indexOf(newKey);\n const {item, itemIndex} = keyDataMap.get(newKey)!;\n let child: ElementFragment;\n if (srcIndex !== -1) {\n // 既存の要素を再利用\n child = childElements[srcIndex];\n // 既存要素にも必ずバインドデータを再セットし、キャッシュもクリア\n chain = chain.then(() =>\n Core.updateRowFragment(\n child,\n item,\n indexKey as string | null,\n itemIndex,\n itemArg ? String(itemArg) : null,\n newKey,\n )\n .then(() => Core.evaluateAll(child))\n .then(() => Core.scheduleEvaluateAll(child))\n );\n } else {\n // 新しい要素を追加\n child = template.clone();\n const currentInsertIndex = baseInsertIndex + loopIndex;\n chain = chain.then(() =>\n Core.updateRowFragment(\n child,\n item,\n indexKey as string | null,\n itemIndex,\n itemArg ? String(itemArg) : null,\n newKey,\n ).then(() =>\n parent\n .insertBefore(\n child,\n parent.getChildren()[currentInsertIndex] || null,\n )\n .then(() => Core.evaluateAll(child))\n .then(() => Core.scheduleEvaluateAll(child)),\n )\n );\n }\n });\n return Promise.all(removalPromises)\n .then(() => chain)\n .then(() => {\n // eachupdateイベントを発火\n const validNewKeys = newKeys.filter(\n (key): key is string => key !== null,\n );\n const validSrcKeys = srcKeys.filter(\n (key): key is string => key !== null,\n );\n const addedKeys = validNewKeys.filter(\n key => !validSrcKeys.includes(key),\n );\n const removedKeys = validSrcKeys.filter(\n key => !validNewKeys.includes(key),\n );\n HaoriEvent.eachUpdate(\n parent.getTarget(),\n addedKeys,\n removedKeys,\n validNewKeys,\n );\n return undefined;\n });\n }\n\n /**\n * リスト比較用のキーを生成します。\n *\n * @param item 対象オブジェクト\n * @param keyArg リストキーに使用するプロパティ名\n * @param index 配列のインデックス\n * @returns リストキー\n */\n private static createListKey(\n item: Record<string, unknown> | string | number,\n keyArg: string | null,\n index: number,\n ): string {\n let listKey: string;\n if (typeof item === 'object' && item !== null) {\n if (keyArg) {\n const key = item[keyArg as string];\n if (key === null || key === undefined) {\n listKey = `__index_${index}`;\n } else if (typeof key == 'object') {\n listKey = JSON.stringify(key);\n } else {\n listKey = String(key);\n }\n } else {\n // data-each-key がない場合はインデックスをキーとして使用\n listKey = `__index_${index}`;\n }\n } else {\n listKey = String(item);\n }\n return listKey;\n }\n\n /**\n * 行フラグメントにデータを設定します。\n *\n * @param rowFragment 行フラグメント\n * @param data 行データ\n * @param indexKey インデックスキー\n * @param index インデックス番号\n * @param arg バインドデータパラメータ名\n * @param listKey リストキー\n * @returns 行メタデータの更新完了 Promise\n */\n private static updateRowFragment(\n rowFragment: ElementFragment,\n data: Record<string, unknown> | string | number,\n indexKey: string | null,\n index: number,\n arg: string | null,\n listKey: string,\n ): Promise<void> {\n let bindingData = data;\n if (typeof data === 'object' && data !== null) {\n bindingData = {...data};\n if (indexKey) {\n bindingData[indexKey] = index;\n }\n if (arg) {\n bindingData = {\n [arg]: bindingData,\n };\n }\n } else {\n if (arg) {\n bindingData = {\n [arg]: data,\n };\n if (indexKey) {\n bindingData[indexKey] = index;\n }\n } else {\n Log.error(\n '[Haori]',\n `Primitive value requires '${Env.prefix}each-arg' attribute: ${data}`,\n );\n return Promise.resolve();\n }\n }\n rowFragment.setListKey(listKey);\n rowFragment.setBindingData(bindingData as Record<string, unknown>);\n return rowFragment.setAttribute(`${Env.prefix}row`, listKey);\n }\n\n /**\n * フラグメントの再評価を次のイベントループで実行します。\n *\n * @param fragment 再評価対象のフラグメント\n */\n private static scheduleEvaluateAll(fragment: ElementFragment): void {\n setTimeout(() => {\n void Core.evaluateAll(fragment);\n }, 100);\n }\n}\n","/**\n * @fileoverview イベント振り分け機能\n *\n * クリック/変更/ロード/ポップステートイベントを検出し Procedure に委譲します。\n */\n\nimport Fragment, {ElementFragment} from './fragment';\nimport Procedure from './procedure';\nimport Log from './log';\n\n/**\n * イベントの振り分けを行うクラスです。\n */\nexport default class EventDispatcher {\n /** Haori が history.state に埋め込む状態キー */\n private static readonly HISTORY_STATE_KEY = '__haoriHistoryState__';\n\n /** ルート要素 */\n private readonly root: Document | HTMLElement;\n\n /** クリックデリゲータ */\n private readonly onClick = (event: Event) => this.delegate(event, 'click');\n\n /** 変更デリゲータ */\n private readonly onChange = (event: Event) => this.delegate(event, 'change');\n\n /** ロードデリゲータ(キャプチャで拾う) */\n private readonly onLoadCapture = (event: Event) =>\n this.delegate(event, 'load');\n\n /** ページ全体のロード完了時の処理 */\n private readonly onWindowLoad = () => {\n // ページロード時にも load を1回ディスパッチ\n const html = document.documentElement;\n const fragment = Fragment.get(html);\n if (fragment) {\n void new Procedure(fragment, 'load').run();\n }\n };\n\n /**\n * popstate デリゲータ(Haori が管理する履歴に戻った場合だけページをリロード)。\n *\n * @param event popstate イベント\n */\n private readonly onPopstate = (event: PopStateEvent) => {\n const state = event.state as Record<string, unknown> | null;\n if (!state || state[EventDispatcher.HISTORY_STATE_KEY] !== true) {\n return;\n }\n location.reload();\n };\n\n /**\n * コンストラクタ。\n *\n * @param root 監視対象のルート要素(デフォルトは document )\n */\n constructor(root: Document | HTMLElement = document) {\n this.root = root;\n }\n\n /**\n * イベントリスナーの登録を開始します。\n * クリック、変更、ロード、popstate イベントを監視し、対応するProcedureを実行します。\n */\n start(): void {\n this.root.addEventListener('click', this.onClick);\n this.root.addEventListener('change', this.onChange);\n // load は非バブルなのでキャプチャで拾う\n this.root.addEventListener('load', this.onLoadCapture, true);\n // ページ全体のロード\n window.addEventListener('load', this.onWindowLoad, {once: true});\n // ブラウザの戻る・進む操作\n window.addEventListener('popstate', this.onPopstate);\n }\n\n /**\n * イベントリスナーの登録を停止します。\n */\n stop(): void {\n this.root.removeEventListener('click', this.onClick);\n this.root.removeEventListener('change', this.onChange);\n this.root.removeEventListener('load', this.onLoadCapture, true);\n window.removeEventListener('load', this.onWindowLoad);\n window.removeEventListener('popstate', this.onPopstate);\n }\n\n /**\n * イベントを処理し、対応するProcedureを実行します。\n *\n * @param event 発生したイベント\n * @param type イベントタイプ('click', 'change', 'load'など)\n */\n private delegate(event: Event, type: string) {\n const element = this.getElementFromTarget(event.target);\n if (!element) {\n return;\n }\n const fragment = Fragment.get(element);\n if (!fragment) {\n return;\n }\n\n // changeイベントの場合、DOM値と同期\n if (type === 'change' && fragment instanceof ElementFragment) {\n fragment.syncValue();\n }\n\n new Procedure(fragment, type).run().catch(error => {\n Log.error('[Haori]', 'Procedure execution error:', error);\n });\n }\n\n /**\n * イベントのターゲットから HTMLElement を取得します。\n *\n * @param target イベントのターゲット\n * @returns HTMLElement または null\n */\n private getElementFromTarget(target: EventTarget | null): HTMLElement | null {\n if (!target) {\n return null;\n }\n if (target instanceof HTMLElement) {\n return target;\n }\n if (target instanceof Node) {\n return target.parentElement;\n }\n return null;\n }\n}\n","/**\n * @fileoverview IntersectionObserver based trigger dispatcher.\n */\n\nimport Env from './env';\nimport Fragment, {ElementFragment} from './fragment';\nimport Log from './log';\nimport Procedure from './procedure';\n\ninterface IntersectRegistration {\n fragment: ElementFragment;\n observer: IntersectionObserver;\n once: boolean;\n running: boolean;\n}\n\n/**\n * `data-intersect-*` 属性を監視し、交差時に Procedure を実行します。\n */\nexport default class IntersectObserver {\n private static readonly CONFIG_KEYS = new Set([\n 'root',\n 'root-margin',\n 'threshold',\n 'disabled',\n 'once',\n ]);\n\n private static readonly registrations = new Map<\n HTMLElement,\n IntersectRegistration\n >();\n\n public static syncTree(root: Node): void {\n if (!(root instanceof Element || root instanceof DocumentFragment)) {\n return;\n }\n if (root instanceof HTMLElement) {\n IntersectObserver.syncElement(root);\n }\n root.querySelectorAll<HTMLElement>('*').forEach(element => {\n IntersectObserver.syncElement(element);\n });\n }\n\n public static syncElement(element: HTMLElement): void {\n const registration = IntersectObserver.registrations.get(element);\n const fragment = Fragment.get(element);\n if (!fragment || !IntersectObserver.shouldObserve(fragment)) {\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n return;\n }\n\n if (typeof IntersectionObserver === 'undefined') {\n return;\n }\n\n const nextRoot = IntersectObserver.resolveRoot(fragment);\n const nextRootMargin = IntersectObserver.resolveRootMargin(fragment);\n const nextThreshold = IntersectObserver.resolveThreshold(fragment);\n const nextOnce = fragment.hasAttribute(`${Env.prefix}intersect-once`);\n\n if (\n registration &&\n registration.observer.root === nextRoot &&\n registration.observer.rootMargin === nextRootMargin &&\n IntersectObserver.sameThreshold(\n registration.observer.thresholds,\n nextThreshold,\n ) &&\n registration.once === nextOnce\n ) {\n registration.fragment = fragment;\n return;\n }\n\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n\n const observer = new IntersectionObserver(\n entries => {\n const current = IntersectObserver.registrations.get(element);\n if (!current) {\n return;\n }\n entries.forEach(entry => {\n if (!entry.isIntersecting || current.running) {\n return;\n }\n if (IntersectObserver.isDisabled(current.fragment)) {\n return;\n }\n current.running = true;\n void new Procedure(current.fragment, 'intersect')\n .runWithResult()\n .then(success => {\n if (success && current.once) {\n current.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n })\n .catch(error => {\n Log.error(\n '[Haori]',\n 'Intersect procedure execution error:',\n error,\n );\n })\n .finally(() => {\n const latest = IntersectObserver.registrations.get(element);\n if (latest) {\n latest.running = false;\n }\n });\n });\n },\n {\n root: nextRoot,\n rootMargin: nextRootMargin,\n threshold: nextThreshold,\n },\n );\n\n observer.observe(element);\n IntersectObserver.registrations.set(element, {\n fragment,\n observer,\n once: nextOnce,\n running: false,\n });\n }\n\n public static cleanupTree(root: Node): void {\n if (root instanceof HTMLElement) {\n const registration = IntersectObserver.registrations.get(root);\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(root);\n }\n }\n if (!(root instanceof Element || root instanceof DocumentFragment)) {\n return;\n }\n root.querySelectorAll<HTMLElement>('*').forEach(element => {\n const registration = IntersectObserver.registrations.get(element);\n if (registration) {\n registration.observer.disconnect();\n IntersectObserver.registrations.delete(element);\n }\n });\n }\n\n public static disconnectAll(): void {\n IntersectObserver.registrations.forEach(registration => {\n registration.observer.disconnect();\n });\n IntersectObserver.registrations.clear();\n }\n\n private static shouldObserve(fragment: ElementFragment): boolean {\n return fragment.getAttributeNames().some(name => {\n if (!name.startsWith(`${Env.prefix}intersect-`)) {\n return false;\n }\n const key = name.slice(`${Env.prefix}intersect-`.length);\n return !IntersectObserver.CONFIG_KEYS.has(key);\n });\n }\n\n private static resolveRoot(fragment: ElementFragment): HTMLElement | null {\n const attrName = `${Env.prefix}intersect-root`;\n if (!fragment.hasAttribute(attrName)) {\n return null;\n }\n const selector = fragment.getAttribute(attrName);\n if (typeof selector !== 'string' || selector.trim() === '') {\n return null;\n }\n const root = document.querySelector(selector);\n if (root instanceof HTMLElement) {\n return root;\n }\n Log.error('[Haori]', `Intersect root element not found: ${selector}`);\n return null;\n }\n\n private static resolveRootMargin(fragment: ElementFragment): string {\n const attrName = `${Env.prefix}intersect-root-margin`;\n const value = fragment.getAttribute(attrName);\n if (value === null || value === false || value === '') {\n return '0px';\n }\n return String(value);\n }\n\n private static resolveThreshold(fragment: ElementFragment): number {\n const attrName = `${Env.prefix}intersect-threshold`;\n const value = fragment.getAttribute(attrName);\n const threshold =\n typeof value === 'number' ? value : Number.parseFloat(String(value ?? 0));\n if (Number.isNaN(threshold)) {\n return 0;\n }\n return Math.min(1, Math.max(0, threshold));\n }\n\n private static isDisabled(fragment: ElementFragment): boolean {\n const attrName = `${Env.prefix}intersect-disabled`;\n const value = fragment.getAttribute(attrName);\n if (value === null || value === false) {\n return false;\n }\n if (typeof value === 'boolean') {\n return value;\n }\n const stringValue = String(value).trim().toLowerCase();\n return stringValue !== '' && stringValue !== 'false' && stringValue !== '0';\n }\n\n private static sameThreshold(\n thresholds: readonly number[],\n threshold: number,\n ): boolean {\n return thresholds.length === 1 && thresholds[0] === threshold;\n }\n}\n","/**\n * @fileoverview 監視機能\n *\n * Observerクラスは、DOMの変更を監視し、バインディングの更新を行います。\n * MutationObserverを使用して、属性の変更、ノードの追加・削除、テキストノードの変更を監視します。\n */\nimport Core from './core';\nimport EventDispatcher from './event_dispatcher';\nimport IntersectObserver from './intersect';\nimport Log from './log';\n\n/**\n * 監視対象の要素を管理するためのクラスです。\n */\nexport class Observer {\n private static _initialized = false;\n /**\n * 初期化メソッド。\n * ドキュメントのheadとbodyを監視対象として設定します。\n */\n public static async init() {\n if (Observer._initialized) {\n return;\n }\n Observer._initialized = true;\n const results = await Promise.allSettled([\n Core.scan(document.head),\n Core.scan(document.body),\n ]);\n const [headResult, bodyResult] = results;\n if (headResult.status !== 'fulfilled') {\n Log.error('[Haori]', 'Failed to build head fragment:', headResult.reason);\n }\n if (bodyResult.status !== 'fulfilled') {\n Log.error('[Haori]', 'Failed to build body fragment:', bodyResult.reason);\n }\n Observer.observe(document.head);\n Observer.observe(document.body);\n new EventDispatcher().start();\n IntersectObserver.syncTree(document.body);\n }\n\n /**\n * 指定された要素を監視します。\n *\n * @param root 監視対象の要素\n */\n public static observe(root: HTMLElement | Document) {\n const observer = new MutationObserver(async mutations => {\n for (const mutation of mutations) {\n try {\n switch (mutation.type) {\n case 'attributes': {\n // 属性の変更\n Log.info(\n '[Haori]',\n 'Attribute changed:',\n mutation.target,\n mutation.attributeName,\n );\n const element = mutation.target as HTMLElement;\n if (\n mutation.attributeName &&\n Core.isAliasedAttributeReflection(\n element,\n mutation.attributeName,\n )\n ) {\n break;\n }\n Core.setAttribute(\n element,\n mutation.attributeName!,\n element.getAttribute(mutation.attributeName!),\n );\n IntersectObserver.syncElement(element);\n break;\n }\n case 'childList': {\n // ノードの追加・削除\n Log.info(\n '[Haori]',\n 'Child list changed:',\n Array.from(mutation.removedNodes).map(node => node.nodeName),\n Array.from(mutation.addedNodes).map(node => node.nodeName),\n );\n Array.from(mutation.removedNodes).forEach(node => {\n IntersectObserver.cleanupTree(node);\n Core.removeNode(node);\n });\n Array.from(mutation.addedNodes).forEach(node => {\n if (!(node.parentElement instanceof HTMLElement)) {\n return;\n }\n Core.addNode(node.parentElement, node);\n IntersectObserver.syncTree(node);\n });\n break;\n }\n case 'characterData': {\n // テキストノードの変更\n Log.info(\n '[Haori]',\n 'Character data changed:',\n mutation.target,\n mutation.target.textContent,\n );\n if (\n mutation.target instanceof Text ||\n mutation.target instanceof Comment\n ) {\n Core.changeText(mutation.target, mutation.target.textContent!);\n } else {\n Log.warn(\n '[Haori]',\n 'Unsupported character data type:',\n mutation.target,\n );\n }\n break;\n }\n default:\n Log.warn('[Haori]', 'Unknown mutation type:', mutation.type);\n continue;\n }\n } catch (error) {\n Log.error('[Haori]', 'Error processing mutation:', error);\n }\n }\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n Log.info('[Haori]', 'Observer initialized for', root);\n }\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', Observer.init);\n} else {\n Observer.init();\n}\n","/**\n * @fileoverview Haori-js メインエントリーポイント\n *\n * Haori-jsライブラリのすべての機能を提供するメインファイルです。\n */\n\nimport Core from './core';\nimport Env from './env';\nimport Fragment from './fragment';\nimport Form from './form';\nimport Haori from './haori';\nimport Log from './log';\nimport Queue from './queue';\n// ブラウザ運用時の監視・自動起動(本番動作)は observer モジュールが担います\nimport './observer';\n\n// メインクラスとユーティリティをエクスポート\nexport {Core, Env, Fragment, Form, Haori, Log, Queue};\nexport type {HaoriRuntime} from './env';\n\n// デフォルトエクスポート(Haoriをメインとして提供)\nexport default Haori;\n\n// バージョン情報\nexport const version = '0.4.7';\n"],"names":["_Dev","enabled","Dev","DEFAULT_RUNTIME","isHaoriRuntime","runtime","resolveRuntimeAttribute","_Env","currentScript","prefix","host","Env","Log","message","args","AsyncQueue","task","prepend","resolve","reject","promise","res","rej","item","start","result","error","promises","_Queue","Queue","Haori","level","toast","element","target","recipient","parent","FORM_HAORI_METHOD_NAMES","resolveFormHaoriApi","candidate","methodName","Form","form","values","fragment","name","objectName","listName","child","childValues","childList","force","value","emitEvents","index","detach","children","i","next","Core","tasks","removeClones","f","isBefore","isAfter","processChildren","key","activeHaori","addMsgFn","doAdd","targetFragments","targetFragment","parts","results","firstPoint","lastPoint","rawKey","indexString","rows","_Expression","scope","candidates","bindKeys","bindKeySet","expression","bindedValues","cacheKey","evaluator","assignments","body","argValues","wrappedValues","pattern","tokens","groups","previous","token","activeGroup","beforePrevious","thirdPrevious","group","operators","singleCharacters","current","stringToken","operator","numberToken","identifierToken","quote","literal","_","code","escaped","cache","cachedValue","proxy","currentTarget","property","receiver","thisArg","argArray","newTarget","prototype","callback","originals","descriptor","obj","seen","forbidden","Expression","_Fragment","node","ElementFragment","TextFragment","CommentFragment","prevSkip","mounted","unmount","Fragment","contents","AttributeContents","childFragment","clone","childClone","data","template","dispatchEvents","isBooleanCheckbox","newChecked","rawName","targetName","syncValueProperty","string","TextContents","referenceChild","insertAfter","referenceNode","insertionReferenceNode","nextTrackedNode","childIndex","newChild","referenceNodeOverride","ancestors","ancestor","isSameParent","newChildIndex","referenceIndex","newChildParent","insertionPoint","siblings","text","_TextContents","matches","lastIndex","hasEvaluate","hasRawEvaluate","match","content","c","bindingValues","_AttributeContents","HaoriEvent","eventName","detail","options","event","version","url","bytes","startedAt","reason","changedKeys","prevKeys","nextKeys","allKeys","prevValue","nextValue","added","removed","order","from","to","payload","metadata","status","PROCEDURE_HAORI_METHOD_NAMES","PROCEDURE_HISTORY_STATE_KEY","resolveProcedureHaoriApi","QUERY_TRANSPORT_METHODS","isQueryTransportMethod","method","appendPayloadToSearchParams","params","appendPayloadToUrl","fetchUrl","_Procedure","hasFetchFallback","rawAttribute","_matched","rawExpression","source","offset","inString","char","attrName","dataAttribute","trimmed","formSelector","formElement","e","fetchAttrName","hasFetchAttr","fetchOptions","fetchMethodAttrEvent","fetchMethodAttrNonEvent","fetchHeadersAttrEvent","headersString","fetchHeadersAttrNonEvent","fetchCTAttrEvent","hasContentType","fetchCTAttrNonEvent","bindAttr","bindSelector","bindElements","bindArgAttrEvent","bindArgAttrNonEventLegacy","bindArgAttrNonEventNew","bindParamsAttr","paramsString","p","bindAppendAttr","copyParamsAttr","param","adjustSelector","adjustElements","valueString","rawLevel","isValidLevel","historyFormSelector","historyFormElement","attrKey","selector","list","el","frag","arg1","arg2","formValues","hasPayload","finalOptions","headers","requestedMethod","isDemoQueryNormalization","contentType","formData","k","v","queryString","fetchStartMetadata","response","formFragment","bindingData","merged","deferredPromises","hasHistoryUrl","hasHistoryData","hasHistoryForm","baseUrlString","errorMessage","appendParams","baseFragment","addGeneralMessage","targetEl","scrollToFirstError","root","entries","m","firstInvalid","found","newData","bindArg","currentValue","currentObject","resolvedData","currentData","incoming","existing","sourceData","copyData","filtered","adjustValue","rowFragment","newFragment","prevFragment","nextFragment","Procedure","Url","Import","init","doc","_Core","suffix","aliasPrefix","chain","rawValue","attributeChain","processedAttributes","childPromises","aliasedAttributeName","html","arg","parentElement","condition","templateTarget","newList","indexKey","keyArg","itemArg","keyDataMap","newKeys","itemIndex","listKey","removalPromises","childElements","srcKeys","baseInsertIndex","newKey","loopIndex","srcIndex","currentInsertIndex","validNewKeys","validSrcKeys","addedKeys","removedKeys","_EventDispatcher","state","type","EventDispatcher","_IntersectObserver","registration","nextRoot","nextRootMargin","nextThreshold","nextOnce","observer","entry","success","latest","threshold","stringValue","thresholds","IntersectObserver","_Observer","headResult","bodyResult","mutations","mutation","Observer"],"mappings":"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"}
|