haori 0.57.1 → 0.58.0

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Haori.js は、HTML 属性を中心にして動的な UI を実現する軽量なライブラリです。JavaScript をほとんど書かずに、データバインディング、条件分岐、繰り返し処理、フォームの双方向バインディング、サーバー通信などを HTML 属性で宣言できます。
4
4
 
5
- バージョン: 0.57.1
5
+ バージョン: 0.58.0
6
6
 
7
7
  ---
8
8
 
@@ -120,7 +120,7 @@ Haori.mount(document.body, {items: [{name: 'りんご'}, {name: 'みかん'}]});
120
120
  - `data-click-*`・`data-change-*`・`data-input-*`・`data-load-*`・`data-intersect-*` は、それぞれクリック・フォーム変更・逐次入力・要素ロード・ビューポート交差を契機に処理(fetch、bind、copy、ダイアログ操作など)を宣言します。`data-load-*` は `data-if` 要素が非表示→表示へ遷移した(`haori:show`)タイミングでも発火するため、ネイティブの `load` が発生しない `<button>` などでも利用できます。
121
121
  - `data-poll-*` — タイマーで手続きを繰り返し起動します(定期取得)。別端末や別プロセスでの操作完了を待つ画面に使います。アクション語彙は `data-{event}-*` と共通(`data-poll-fetch`・`data-poll-bind`・`data-poll-bind-arg` など)。設定属性は `data-poll-interval`(取得間隔ミリ秒。既定 5000、下限 100)、`data-poll-timeout`(打ち切りミリ秒。省略時は無制限)、`data-poll-until="{{式}}"`(真になった時点で恒久停止。各リクエスト前とバインド反映後に評価)、`data-poll-error-limit`(連続失敗回数の上限。省略時は継続)、`data-poll-disabled`(真の間は抑止)、`data-poll-state`(`_poll` 状態の注入先。`running`・`paused`・`stopped`・`timedOut`・`stopReason`・`count`・`elapsedMs`)です。初回は即時実行、2回目以降は前回完了時点から計測するためリクエストは多重化せず、`data-if` で非表示の間は一時停止して再表示で再開し、DOM から外れた時点で恒久停止します。バックグラウンドタブではブラウザがタイマーを抑制するため指定間隔は保証されません(タブが表示に戻った時点で即時に取得し直します)。
122
122
  - `data-input-*` — テキスト入力1文字ごと(`input` イベント)に手続きを起動します。逐次発火するため `data-input-*` を**明示した要素のみ**が対象(オプトイン)で、`change` 同様に先祖フォームを自動検出して双方向バインディングへ反映します。検索欄の逐次絞り込みなどに使えます(例: `<input name="q" data-input-form>`)。
123
- - `data-on="イベント名"` + `data-on-*` — `window` / `document` へ dispatch された**任意のカスタムイベント**を契機に手続きを起動します(アクション語彙は `data-{event}-*` と共通)。ネイティブ橋の準備完了通知など、組み込みイベント以外での初期化を宣言的に書けます(例: `<body data-on="appReady" data-on-fetch="/api/init.json" data-on-bind="#app">`)。イベント名は属性値で保持(属性名の小文字化対策)、`window` キャプチャ1本で二重発火なく購読、後挿入要素も追従。組み込みイベント名(click/change/input/load)は警告し購読しません。Haori 購読開始前に発火したイベントは受け取れない点に注意。
123
+ - `data-on="イベント名"` + `data-on-*` — `window` / `document` へ dispatch された**任意のカスタムイベント**を契機に手続きを起動します(アクション語彙は `data-{event}-*` と共通)。ネイティブ橋の準備完了通知など、組み込みイベント以外での初期化を宣言的に書けます(例: `<body data-on="appReady" data-on-fetch="/api/init.json" data-on-bind="#app">`)。イベント名は属性値で保持(属性名の小文字化対策)、`window` キャプチャ1本で二重発火なく購読、後挿入要素も追従。組み込みイベント名(click/change/input/load)は警告し購読しません。Haori 購読開始前に発火したイベントは受け取れない点に注意。`data-on-target="#sub-modal"` を足すと、指定した要素(とその子孫)から発火したイベントでだけ起動します(Bootstrap の `hidden.bs.modal` で、特定のモーダルが閉じたときだけ状態を戻すなど)。
124
124
  - `data-validity="{{式}}"` / `data-validity-message="…"` — 入力欄へ宣言するフィールド間検証です。条件を `setCustomValidity()` へ反映してネイティブ検証(`data-{event}-validate`)に相乗りするため、バブル表示・フォーカス移動・`:invalid` の装飾がそのまま使えます。「連絡先いずれか必須」「メールアドレスの一致」のようにネイティブの制約では表現できない条件を宣言できます。
125
125
  - `data-{event}-if="{{式}}"`(非イベントは `data-fetch-if`)— 手続きの実行条件です。偽なら fetch・リダイレクト・`data-{event}-run` まで含めて実行しません。どちらも**実行時に同期評価**するため、属性の再描画(`requestAnimationFrame`)を待たず、直前に変更した入力を含めて判定されます(`data-attr-disabled` では「最後の欄を直してそのまま押す」操作で 1 フレーム古い判定になります)。押下のブロックに `disabled` を使わないでください。無効化されたボタンはクリックイベントを発火しないため、「直したのに押せない」方向は救えません。
126
126
  - 応答のバインドより**後**に実行されるアクション(`data-{event}-redirect`・`-redirect-replace`・`-redirect-return-param`・`-dialog`・`-toast`・`-history`・`-scroll`)は、実行する直前に属性を評価します。そのため遷移先やメッセージを応答の値で切り替えられます(`data-click-redirect="{{nextAction === 'pay' ? redirectUrl : '/complete.html'}}"`)。応答は `data-{event}-bind` で自要素または祖先へ反映してください(式のスコープに入る位置が必要です)。式が使っていたキーが手続きの途中で消えた場合(全置換の `data-{event}-bind`)は開始時の評価値を使い、開発モードで警告します(遷移が静かに止まりません)。`data-store` のミラーはバインディングと同期なので、遷移前に必ず完了しています。
@@ -130,8 +130,8 @@ Haori.mount(document.body, {items: [{name: 'りんご'}, {name: 'みかん'}]});
130
130
  - **CSS セレクタ**を値に取る属性(`data-{event}-bind`・`-form`・`-copy`・`-copy-source`・`-reset`・`-refetch`・`-click`・`-open`・`-close`・`-adjust`・`-row-*`・`data-fetch-bind`・`data-fetch-state` など)は、照会の前に `{{ ... }}` を評価します。`data-each` の行の中から「その行の要素」を対象にでき(`id="plan-scope-{{i}}"` と `data-change-bind="#plan-scope-{{i}}"` の組み合わせ)、行ごとのバインドや住所複写が属性だけで書けます。不正なセレクタは例外にせずログしてスキップし、単体プレースホルダの未解決参照は「値の指定なし」として扱います(値を省略したときの既定動作になります)。`-bind-arg`・`-copy-params` のようなキー名を並べる属性は評価しません。
131
131
  - `data-click-copy-source` — `data-click-copy` のコピー元要素を明示指定します(既定は `data-click-form` のフォーム、無ければイベント発火元の binding)。
132
132
  - `data-click-no-disabled` / `data-click-defer` — 他ライブラリとの併用補助です。`no-disabled` はクリック手続き実行中に `disabled` 属性を付与せず実行します(Bootstrap collapse など disabled 要素を無視するライブラリ・CSS が動作し続けます。多重実行は内部マーカーで防止)。`defer` はクリック手続きを次フレーム(`requestAnimationFrame`/`setTimeout(0)`)で実行し、他ライブラリの同期 click ハンドラを先に完了させます。遅延後は `preventDefault()` できないため、`<a href>` や `type="submit"` への `defer` 併用は避けてください。
133
- - `data-{event}-click-await` — `data-{event}-click` が起動した手続きの完了を待ってから次の対象をクリックします。複数の更新を**宣言した順に直列で**送り、**いずれかが失敗した時点で後続を止めます**(HTTP エラー・通信の例外・検証エラー・確認ダイアログのキャンセル)。表示順を 2 件更新する並べ替えが JavaScript なしで書けます。止めた場合は呼び出し元の後続アクション(ダイアログ・トースト・リダイレクト)も実行しません。`data-{event}-if` が偽でスキップされた対象は失敗として扱いません。手続きが同期に起動しない対象(`data-click-defer`、クリックが発火しない `disabled` 要素)は待てず、その旨を記録します。
134
- - `data-{event}-error-click` / `-error-click-await` / `-error-close` / `-error-toast` / `-error-toast-level` / `-error-status` / `-error-no-message` — 取得が失敗したとき(2xx 以外の応答と通信の例外。認証ガードで遷移する 401 / 403 を除く)にだけ、別要素のクリック・ダイアログを閉じる・トーストをこの順に実行します。「取り直しが 404 なら、ダイアログを閉じて検索し直す」が JavaScript なしで書けます。`-error-status="404&410"` で対象のステータスを絞れます(宣言すると通信の例外は対象外)。実行しても手続きは失敗のままで、エラー表示も今までどおり行います(`-error-no-message` で止められます)。応答本文のサーバのメッセージは `_fetch.responseMessage` で参照でき、`data-click-error-toast="{{_fetch.responseMessage}}"` でトーストに出せます。`data-click-error-404-close` のようにステータスを付けた組(`-click` / `-click-await` / `-close` / `-toast` / `-toast-level` / `-no-message`)は、そのステータスの失敗でだけ、ステータスの付かない属性の代わりに使います。`-toast-level` と `-error-toast-level` には式を書けます(例: `{{_fetch.statusCode === 409 ? 'warning' : 'error'}}`)。`data-poll-*` と非イベントの `data-fetch` では使えません。
133
+ - `data-{event}-click-await` — `data-{event}-click` が起動した手続きの完了を待ってから次の対象をクリックします。複数の更新を**宣言した順に直列で**送り(`#b, #a` のようにカンマで区切った対象は、文書の並びによらず書いた順に押します)、**いずれかが失敗した時点で後続を止めます**(HTTP エラー・通信の例外・検証エラー・確認ダイアログのキャンセル)。表示順を 2 件更新する並べ替えが JavaScript なしで書けます。止めた場合は呼び出し元の後続アクション(ダイアログ・トースト・リダイレクト)も実行しません。`data-{event}-if` が偽でスキップされた対象は失敗として扱いません。手続きが同期に起動しない対象(`data-click-defer`、クリックが発火しない `disabled` 要素)は待てず、その旨を記録します。
134
+ - `data-{event}-error-click` / `-error-click-await` / `-error-close` / `-error-toast` / `-error-toast-level` / `-error-status` / `-error-no-message` / `-error-bind` — 取得が失敗したとき(2xx 以外の応答と通信の例外。認証ガードで遷移する 401 / 403 を除く)にだけ、別要素のクリック・ダイアログを閉じる・トーストをこの順に実行します。「取り直しが 404 なら、ダイアログを閉じて検索し直す」が JavaScript なしで書けます。`-error-status="404&410"` で対象のステータスを絞れます(宣言すると通信の例外は対象外)。実行しても手続きは失敗のままで、エラー表示も今までどおり行います(`-error-no-message` で止められます)。`-error-bind` を宣言すると、応答本文を表示する代わりに `data-{event}-bind` と同じ規則でバインドします(400 で返る検証結果を表に出すなど)。応答本文のサーバのメッセージは `_fetch.responseMessage` で参照でき、`data-click-error-toast="{{_fetch.responseMessage}}"` でトーストに出せます。`data-click-error-404-close` のようにステータスを付けた組(`-click` / `-click-await` / `-close` / `-toast` / `-toast-level` / `-no-message` / `-bind`)は、そのステータスの失敗でだけ、ステータスの付かない属性の代わりに使います。`-toast-level` と `-error-toast-level` には式を書けます(例: `{{_fetch.statusCode === 409 ? 'warning' : 'error'}}`)。`data-poll-*` と非イベントの `data-fetch` では、応答本文の表示を止める宣言(`data-fetch-error-no-message` / `data-poll-error-no-message` と、その `-error-status`・`-error-{ステータス}-no-message`)だけを使えます。
135
135
  - `data-{event}-prevent`(例: `data-click-prevent`)— そのイベントでブラウザのネイティブなデフォルト動作(`type="submit"` ボタンのフォーム送信、`<a href>` の遷移など)を抑止します。`preventDefault()` はクリックの同期区間で呼ぶため `data-click-defer` と併用しても確実に抑止でき、`stopPropagation()` は呼ばないので他ライブラリのイベント伝播には影響しません。これにより `type="submit"` のまま `data-click-fetch` 等を付けても、ページ再読込なしに動作します。
136
136
  - `data-{event}-run`(例: `data-click-run`・`data-change-run`)— フェッチを伴わず任意の JavaScript をイベント時に実行します。属性値は `new Function` で実 JS として実行され(`-before-run`/`-after-run` と同方式)、`{{...}}` はレンダリング時に展開、`event` が引数で渡されます。本体が `false` を返すと `event.preventDefault()` を呼びます(`onclick="return false"` の慣習)。**セキュリティ**: 展開後の `{{...}}` は実行コードへ結合されるため、信頼できる値(数値 index・自前採番 ID 等)のみを入れてください。API レスポンスやユーザー入力などの信頼できない文字列を入れると任意コード実行(XSS)になり得ます。信頼できない値は `data-bind` 経由で渡し、呼び出す関数の内部で参照してください。
137
137
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Haori.js is a lightweight, HTML-first UI library that enables dynamic user interfaces primarily through HTML attributes. It lets you declare data bindings, conditional rendering, list rendering, form two-way binding, server fetches, and HTML imports without writing much JavaScript.
4
4
 
5
- Version: 0.57.1
5
+ Version: 0.58.0
6
6
 
7
7
  ---
8
8
 
@@ -120,7 +120,7 @@ Event-driven actions:
120
120
  - `data-click-*`, `data-change-*`, `data-input-*`, `data-load-*`, `data-intersect-*` declare actions (fetch, bind, copy, dialog control, etc.) triggered by click, form change, incremental input, element load, and viewport intersection respectively. `data-load-*` also fires when a `data-if` element transitions from hidden to shown (the `haori:show` timing), so it works on elements like `<button>` that never receive a native `load` event.
121
121
  - `data-poll-*` — run a procedure repeatedly on a timer (interval polling), for screens that wait until another device or process finishes. The action vocabulary is shared with `data-{event}-*` (`data-poll-fetch`, `data-poll-bind`, `data-poll-bind-arg`, …). Configuration is `data-poll-interval` (interval in ms, default 5000, floor 100), `data-poll-timeout` (give up after ms, unlimited when omitted), `data-poll-until="{{expr}}"` (stop permanently once true; evaluated before each request and after each bind), `data-poll-error-limit` (stop after N consecutive failures; keeps going when omitted), `data-poll-disabled` (suppress while truthy) and `data-poll-state` (inject `_poll` state — `running` / `paused` / `stopped` / `timedOut` / `stopReason` / `count` / `elapsedMs`). The first request runs immediately, later intervals are measured from the previous completion (so requests never overlap), polling pauses while hidden by `data-if` and resumes when shown, and stops permanently when the element leaves the DOM. Note that browsers throttle timers in background tabs, so the configured interval is not guaranteed there (an immediate refetch is issued when the tab becomes visible again).
122
122
  - `data-input-*` — run a procedure on each keystroke (the `input` event) for text inputs. Because `input` fires incrementally, only elements that explicitly declare a `data-input-*` attribute are handled (opt-in); like `change`, it auto-detects the ancestor form and reflects the value into two-way bindings. Useful for incremental search filtering (e.g. `<input name="q" data-input-form>`).
123
- - `data-on="eventName"` + `data-on-*` — run a procedure when an arbitrary **custom event** dispatched on `window` / `document` fires (the action vocabulary is shared with `data-{event}-*`). Lets you declaratively initialize on events other than the built-ins, e.g. a native-bridge ready signal (`<body data-on="appReady" data-on-fetch="/api/init.json" data-on-bind="#app">`). The event name is held in the attribute value (attribute names are lowercased), a single `window` capture subscription receives both `window`- and `document`-dispatched events without double-firing, and elements inserted later are picked up too. Built-in names (click/change/input/load) are warned and not subscribed. Note: events dispatched before Haori subscribes are not received (no replay).
123
+ - `data-on="eventName"` + `data-on-*` — run a procedure when an arbitrary **custom event** dispatched on `window` / `document` fires (the action vocabulary is shared with `data-{event}-*`). Lets you declaratively initialize on events other than the built-ins, e.g. a native-bridge ready signal (`<body data-on="appReady" data-on-fetch="/api/init.json" data-on-bind="#app">`). The event name is held in the attribute value (attribute names are lowercased), a single `window` capture subscription receives both `window`- and `document`-dispatched events without double-firing, and elements inserted later are picked up too. Built-in names (click/change/input/load) are warned and not subscribed. Note: events dispatched before Haori subscribes are not received (no replay). Add `data-on-target="#sub-modal"` to run the procedure only for events fired from that element or its descendants (for example, reset state only when a specific Bootstrap modal fires `hidden.bs.modal`).
124
124
  - `data-validity="{{expr}}"` / `data-validity-message="…"` — declarative cross-field validation on an input. The condition is pushed into `setCustomValidity()`, so it rides on native validation (`data-{event}-validate`): bubble message, focus move and `:invalid` styling all keep working. Conditions that native constraints cannot express ("either phone or e-mail", "the two addresses must match") become declarative.
125
125
  - `data-{event}-if="{{expr}}"` (`data-fetch-if` for the non-event form) — an execution condition for the procedure. When false, nothing runs — fetch, redirect and `data-{event}-run` included. Both are evaluated **synchronously at run time**, so they do not wait for attribute re-rendering (`requestAnimationFrame`) and always see the input the user just changed — unlike `data-attr-disabled`, which is one frame stale when you fix the last field and press straight away. Do not use `disabled` to block a click: a disabled button fires no click event at all, so the "fixed it but cannot press" direction cannot be recovered at run time.
126
126
  - Actions that run **after** the response is bound (`data-{event}-redirect`, `-redirect-replace`, `-redirect-return-param`, `-dialog`, `-toast`, `-history`, `-scroll`) evaluate their attribute right before they run, so the destination or message can be decided by the response (`data-click-redirect="{{nextAction === 'pay' ? redirectUrl : '/complete.html'}}"`). Bind the response to the element itself or an ancestor so the keys are in scope. If a key the expression used disappears mid-procedure (a full-replace `data-{event}-bind`), the value evaluated at procedure start is used instead and a warning is logged in dev mode — navigation is never silently dropped. `data-store` mirroring is synchronous with the binding, so it always completes before the redirect.
@@ -130,8 +130,8 @@ Event-driven actions:
130
130
  - Attributes that take a **CSS selector** (`data-{event}-bind`, `-form`, `-copy`, `-copy-source`, `-reset`, `-refetch`, `-click`, `-open`, `-close`, `-adjust`, `-row-*`, `data-fetch-bind`, `data-fetch-state`, …) evaluate `{{ ... }}` before querying, so a row inside `data-each` can target *its own* elements (`data-change-bind="#plan-scope-{{i}}"` paired with `id="plan-scope-{{i}}"`). An invalid selector is logged and skipped instead of throwing, and an unresolved single placeholder is treated as "no value given" (falling back to the attribute's default behaviour). Key-list attributes such as `-bind-arg` / `-copy-params` are not evaluated.
131
131
  - `data-click-copy-source` — explicitly set the copy source element for `data-click-copy` (defaults to the form given by `data-click-form`, otherwise the event element's binding).
132
132
  - `data-click-no-disabled` / `data-click-defer` — coexistence helpers for other libraries. `no-disabled` runs the click procedure without adding the `disabled` attribute (so libraries/CSS that ignore disabled elements, e.g. Bootstrap collapse, keep working; double execution is still prevented internally). `defer` runs the click procedure on the next frame (`requestAnimationFrame`/`setTimeout(0)`) so other libraries' synchronous click handlers complete first. Avoid `defer` on `<a href>` / `type="submit"` because the deferred procedure cannot `preventDefault()` the default action.
133
- - `data-{event}-click-await` — wait for the procedure started by `data-{event}-click` before clicking the next target, so several updates are sent **serially in declaration order** and **the rest is stopped as soon as one fails** (HTTP error, network exception, validation error, or a cancelled confirmation). Row reordering that has to persist two display orders no longer needs JavaScript. When it stops, the calling procedure also skips its remaining actions (dialog, toast, redirect). A target skipped by a false `data-{event}-if` is not a failure. Targets whose procedure does not start synchronously (`data-click-defer`, or a `disabled` element that fires no click) cannot be waited for; that is logged.
134
- - `data-{event}-error-click` / `-error-click-await` / `-error-close` / `-error-toast` / `-error-toast-level` / `-error-status` / `-error-no-message` — run a click on another element, a dialog close and a toast, in that order, only when the fetch fails (a non-2xx response or a network exception, except 401 / 403 handled by the auth guard redirect). "If the reload returns 404, close the dialog and search again" no longer needs JavaScript. `-error-status="404&410"` narrows the statuses (once declared, network exceptions are excluded). The procedure still ends as a failure and the error display works as before, unless `-error-no-message` turns it off. The server's message in the response body is available as `_fetch.responseMessage`, so `data-click-error-toast="{{_fetch.responseMessage}}"` shows it in a toast. A group with a status in its name, such as `data-click-error-404-close` (`-click` / `-click-await` / `-close` / `-toast` / `-toast-level` / `-no-message`), replaces the attributes without a status only for failures with that status. `-toast-level` and `-error-toast-level` accept expressions (for example `{{_fetch.statusCode === 409 ? 'warning' : 'error'}}`). Not available on `data-poll-*` or the non-event `data-fetch`.
133
+ - `data-{event}-click-await` — wait for the procedure started by `data-{event}-click` before clicking the next target, so several updates are sent **serially in declaration order** (comma-separated targets such as `#b, #a` are clicked in the written order, regardless of document order) and **the rest is stopped as soon as one fails** (HTTP error, network exception, validation error, or a cancelled confirmation). Row reordering that has to persist two display orders no longer needs JavaScript. When it stops, the calling procedure also skips its remaining actions (dialog, toast, redirect). A target skipped by a false `data-{event}-if` is not a failure. Targets whose procedure does not start synchronously (`data-click-defer`, or a `disabled` element that fires no click) cannot be waited for; that is logged.
134
+ - `data-{event}-error-click` / `-error-click-await` / `-error-close` / `-error-toast` / `-error-toast-level` / `-error-status` / `-error-no-message` / `-error-bind` — run a click on another element, a dialog close and a toast, in that order, only when the fetch fails (a non-2xx response or a network exception, except 401 / 403 handled by the auth guard redirect). "If the reload returns 404, close the dialog and search again" no longer needs JavaScript. `-error-status="404&410"` narrows the statuses (once declared, network exceptions are excluded). The procedure still ends as a failure and the error display works as before, unless `-error-no-message` turns it off. `-error-bind` binds the response body by the same rules as `data-{event}-bind` instead of showing it (for example, a validation result returned with 400). The server's message in the response body is available as `_fetch.responseMessage`, so `data-click-error-toast="{{_fetch.responseMessage}}"` shows it in a toast. A group with a status in its name, such as `data-click-error-404-close` (`-click` / `-click-await` / `-close` / `-toast` / `-toast-level` / `-no-message` / `-bind`), replaces the attributes without a status only for failures with that status. `-toast-level` and `-error-toast-level` accept expressions (for example `{{_fetch.statusCode === 409 ? 'warning' : 'error'}}`). On `data-poll-*` and the non-event `data-fetch`, only the declarations that turn off the error display are read (`data-fetch-error-no-message` / `data-poll-error-no-message`, with their `-error-status` and `-error-{status}-no-message`).
135
135
  - `data-{event}-prevent` (e.g. `data-click-prevent`) — suppress the browser's native default action for the event (form submission for a `type="submit"` button, navigation for `<a href>`). `preventDefault()` is called synchronously during the click, so it works even together with `data-click-defer`, and `stopPropagation()` is never called (other libraries' event propagation is unaffected). This lets you keep `type="submit"` and still attach `data-click-fetch` etc. without the page reloading.
136
136
  - `data-{event}-run` (e.g. `data-click-run`, `data-change-run`) — run arbitrary JavaScript on the event without a fetch. The value is executed as real JS via `new Function` (like `-before-run`/`-after-run`), with `{{...}}` expanded at render time and `event` passed as an argument. Returning `false` calls `event.preventDefault()` (the `onclick="return false"` convention). **Security:** the expanded `{{...}}` is concatenated into executable code, so only interpolate trusted values (numeric indexes, IDs you control) — never untrusted strings (API/user input), which would run as code (XSS). Pass untrusted values via `data-bind` and read them inside the called function instead.
137
137