haori 0.11.1 → 0.13.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.
Files changed (48) hide show
  1. package/README.ja.md +5 -1
  2. package/README.md +5 -1
  3. package/dist/haori.cjs.js +10 -10
  4. package/dist/haori.cjs.js.map +1 -1
  5. package/dist/haori.es.js +597 -440
  6. package/dist/haori.es.js.map +1 -1
  7. package/dist/haori.iife.js +10 -10
  8. package/dist/haori.iife.js.map +1 -1
  9. package/dist/index.d.ts +87 -1
  10. package/dist/package.json +1 -1
  11. package/dist/src/builtins.d.ts +100 -0
  12. package/dist/src/builtins.d.ts.map +1 -0
  13. package/dist/src/builtins.js +194 -0
  14. package/dist/src/builtins.js.map +1 -0
  15. package/dist/src/event_dispatcher.d.ts.map +1 -1
  16. package/dist/src/event_dispatcher.js +7 -0
  17. package/dist/src/event_dispatcher.js.map +1 -1
  18. package/dist/src/expression.d.ts +13 -0
  19. package/dist/src/expression.d.ts.map +1 -1
  20. package/dist/src/expression.js +26 -1
  21. package/dist/src/expression.js.map +1 -1
  22. package/dist/src/fragment.d.ts +12 -0
  23. package/dist/src/fragment.d.ts.map +1 -1
  24. package/dist/src/fragment.js +25 -2
  25. package/dist/src/fragment.js.map +1 -1
  26. package/dist/src/haori.d.ts +43 -0
  27. package/dist/src/haori.d.ts.map +1 -1
  28. package/dist/src/haori.js +51 -0
  29. package/dist/src/haori.js.map +1 -1
  30. package/dist/src/index.d.ts +1 -1
  31. package/dist/src/index.js +1 -1
  32. package/dist/tests/builtins.test.d.ts +2 -0
  33. package/dist/tests/builtins.test.d.ts.map +1 -0
  34. package/dist/tests/builtins.test.js +152 -0
  35. package/dist/tests/builtins.test.js.map +1 -0
  36. package/dist/tests/data-event-prevent.test.d.ts +2 -0
  37. package/dist/tests/data-event-prevent.test.d.ts.map +1 -0
  38. package/dist/tests/data-event-prevent.test.js +76 -0
  39. package/dist/tests/data-event-prevent.test.js.map +1 -0
  40. package/dist/tests/data-form-container.test.js +2 -1
  41. package/dist/tests/data-form-container.test.js.map +1 -1
  42. package/dist/tests/form-number-type.test.d.ts +2 -0
  43. package/dist/tests/form-number-type.test.d.ts.map +1 -0
  44. package/dist/tests/form-number-type.test.js +83 -0
  45. package/dist/tests/form-number-type.test.js.map +1 -0
  46. package/dist/tests/form.test.js +7 -6
  47. package/dist/tests/form.test.js.map +1 -1
  48. package/package.json +1 -1
package/README.ja.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Haori.js は、HTML 属性を中心にして動的な UI を実現する軽量なライブラリです。JavaScript をほとんど書かずに、データバインディング、条件分岐、繰り返し処理、フォームの双方向バインディング、サーバー通信などを HTML 属性で宣言できます。
4
4
 
5
- バージョン: 0.11.1
5
+ バージョン: 0.13.0
6
6
 
7
7
  ---
8
8
 
@@ -28,6 +28,7 @@ Haori.js は、HTML 属性を中心にして動的な UI を実現する軽量
28
28
  - 繰り返し表示(`data-each`)
29
29
  - フォーム双方向バインディング(`name` 属性による自動バインド)
30
30
  - `value="true"` を付けたチェックボックスの boolean 対応(チェック時 `true`、未チェック時 `false`)
31
+ - `type="number"` 入力の数値型対応(バインド・送信時に数値。空・数値化できない値は `null`)
31
32
  - イベント駆動アクション(`data-click-*`・`data-change-*`・`data-load-*`・`data-intersect-*`)
32
33
  - サーバー通信(`data-fetch`)
33
34
  - HTML インポート(`data-import`)
@@ -111,6 +112,7 @@ Haori.mount(document.body, {items: [{name: 'りんご'}, {name: 'みかん'}]});
111
112
  - `data-click-*`・`data-change-*`・`data-load-*`・`data-intersect-*` は、それぞれクリック・フォーム変更・要素ロード・ビューポート交差を契機に処理(fetch、bind、copy、ダイアログ操作など)を宣言します。`data-load-*` は `data-if` 要素が非表示→表示へ遷移した(`haori:show`)タイミングでも発火するため、ネイティブの `load` が発生しない `<button>` などでも利用できます。
112
113
  - `data-click-copy-source` — `data-click-copy` のコピー元要素を明示指定します(既定は `data-click-form` のフォーム、無ければイベント発火元の binding)。
113
114
  - `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` 併用は避けてください。
115
+ - `data-{event}-prevent`(例: `data-click-prevent`)— そのイベントでブラウザのネイティブなデフォルト動作(`type="submit"` ボタンのフォーム送信、`<a href>` の遷移など)を抑止します。`preventDefault()` はクリックの同期区間で呼ぶため `data-click-defer` と併用しても確実に抑止でき、`stopPropagation()` は呼ばないので他ライブラリのイベント伝播には影響しません。これにより `type="submit"` のまま `data-click-fetch` 等を付けても、ページ再読込なしに動作します。
114
116
  - `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` 経由で渡し、呼び出す関数の内部で参照してください。
115
117
 
116
118
  ライフサイクルイベント:
@@ -119,6 +121,8 @@ Haori.mount(document.body, {items: [{name: 'りんご'}, {name: 'みかん'}]});
119
121
  - `haori:bindcomplete` — `data-*-bind` / `data-*-bind-arg` によるバインドと、対象要素配下の再評価が完了した後に対象要素で発火します(`detail.bindArg`)。
120
122
  - `haori:show` / `haori:hide` — `data-if` 要素の表示・非表示時に発火します。
121
123
 
124
+ 式中では予約名前空間 `haori` の組み込みヘルパーを利用できます。`haori.date(value, format?)` は ISO 文字列・エポックミリ秒・`Date` を整形し(既定 `yyyy/MM/dd HH:mm`、ローカル時刻)、`haori.number(value, decimals?)` は桁区切り付きで数値を整形、`haori.range(start, end?, step?)` は整数配列を生成し(終端排他)、`haori.pages(totalPages, current, {window?, boundary?})` は省略記号付きの番号ページ列を生成します(`current` は 0 始まり。各要素は `{page, label, active, ellipsis}` を持ち `label` は `page + 1`)。これにより番号ページネーション(`data-each="haori.pages(totalPages, number, {window: 2})"`)や値の整形(`{{ haori.date(lastUpdatedAt, 'yyyy/MM/dd HH:mm') }}`)を宣言的に書けます。同じ関数は `Haori.date` / `Haori.number` / `Haori.range` / `Haori.pages` としても公開されています。`haori` は予約名のため、同名の `data-bind` キーを与えても式中では組み込みが優先されます。
125
+
122
126
  テンプレート式では、プロパティアクセス、動的インデックスを含むブラケットアクセス、optional chaining、三項演算子、配列 `map` / `filter` のアロー関数、spread を伴う呼び出しなどの安全な構文を利用できます。一方で、グローバルオブジェクト、`eval` や `arguments`、`constructor`、`__proto__`、`prototype`、`Reflect`、`Object` などの脱出経路は使用できません。`Object` がブロックされるため、`Object.assign` の代わりにスプレッド構文 `{...a, ...b}` を使ってください。ブロックされた識別子を式で参照すると、コンソールに `blocked identifier(s): …` という警告が出力されます。
123
127
 
124
128
  テスト・デバッグ補助: `waitForRenders()`(`Haori.waitForRenders()` でも可)は、初期化・進行中のフェッチ・キューに積まれた描画タスクがすべて落ち着くまで待機します(E2E テストで描画完了を待つのに便利)。`Haori.Core.dumpScope(element)` は要素に解決されるスコープ(`resolved`)と各キーの由来(`sources`)を返します。開発モードでは falsy な `data-if` がその式と参照スコープを自動でログ出力します。
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.11.1
5
+ Version: 0.13.0
6
6
 
7
7
  ---
8
8
 
@@ -28,6 +28,7 @@ Contents
28
28
  - List rendering via `data-each`
29
29
  - Two-way form binding (automatic binding based on `name` attributes)
30
30
  - Boolean checkbox support with `value="true"` (`true` when checked, `false` when unchecked)
31
+ - `type="number"` inputs are bound and submitted as numbers (empty / non-numeric values become `null`)
31
32
  - Event-driven actions via `data-click-*`, `data-change-*`, `data-load-*`, `data-intersect-*`
32
33
  - Server fetches via `data-fetch`
33
34
  - HTML imports via `data-import`
@@ -111,6 +112,7 @@ Event-driven actions:
111
112
  - `data-click-*`, `data-change-*`, `data-load-*`, `data-intersect-*` declare actions (fetch, bind, copy, dialog control, etc.) triggered by click, form change, 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.
112
113
  - `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).
113
114
  - `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.
115
+ - `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.
114
116
  - `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.
115
117
 
116
118
  Lifecycle events:
@@ -119,6 +121,8 @@ Lifecycle events:
119
121
  - `haori:bindcomplete` — fired on the target element after a `data-*-bind` / `data-*-bind-arg` bind and the subsequent re-evaluation of its subtree complete (`detail.bindArg`).
120
122
  - `haori:show` / `haori:hide` — fired when a `data-if` element becomes shown or hidden.
121
123
 
124
+ Built-in helpers are available in expressions under the reserved namespace `haori`: `haori.date(value, format?)` formats an ISO string / epoch ms / `Date` (default `yyyy/MM/dd HH:mm`, local time), `haori.number(value, decimals?)` formats numbers with grouping, `haori.range(start, end?, step?)` builds an integer array (end-exclusive), and `haori.pages(totalPages, current, {window?, boundary?})` builds an ellipsis-aware page list (`current` is 0-based; each item exposes `{page, label, active, ellipsis}` with `label` = `page + 1`). These let you build number pagination (`data-each="haori.pages(totalPages, number, {window: 2})"`) and format values (`{{ haori.date(lastUpdatedAt, 'yyyy/MM/dd HH:mm') }}`) declaratively. The same functions are exposed as `Haori.date` / `Haori.number` / `Haori.range` / `Haori.pages`. `haori` is reserved: a `data-bind` key of the same name does not shadow the built-ins inside expressions.
125
+
122
126
  Template expressions support safe JavaScript-like syntax such as property access, bracket access with dynamic indexes, optional chaining, ternary expressions, and method chains including array `map`/`filter` with arrow functions and spread calls. Access to global objects, `eval` or `arguments`, and prototype escape paths such as `constructor`, `__proto__`, `prototype`, `Reflect`, or `Object` is blocked. Because `Object` is blocked, use spread syntax `{...a, ...b}` instead of `Object.assign`; when a blocked identifier is referenced in an expression, a `blocked identifier(s): …` warning is logged to the console.
123
127
 
124
128
  Helpers for tests and debugging: `waitForRenders()` (also `Haori.waitForRenders()`) resolves once initialization, in-flight fetches, and queued render tasks have all settled — useful for E2E tests. `Haori.Core.dumpScope(element)` returns the scope resolved for an element (`resolved`) and where each key comes from (`sources`); in dev mode a falsy `data-if` also logs its expression and referenced scope automatically.