{
  "__meta": {
    "name": "Sercrod man.json",
    "version": "0.2.6",
    "language": "ja",
    "purpose": "Sercrod の日本語 manual 本文。runtime inspection と人間向け参照に使用する。AI 専用の __ai_* entry は含めない。",
    "format": "mixed-string-and-structured",
    "primary_audience": [
      "human developers",
      "documentation tools",
      "runtime inspection tools"
    ],
    "notes": [
      "String entries contain Japanese manual text for Sercrod features.",
      "AI-only __ai_* entries are intentionally excluded from the Japanese man.json.",
      "The English man.json remains the source for AI-specific guidance.",
      "This file is intended for Japanese runtime manual display and human reference.",
      "Adds Japanese manual entries for *shadow, *host, *shadow-host, n-host, and n-shadow-host.",
      "Japanese man.json remains focused on runtime manual display and human reference; AI-only __ai_* entries remain excluded."
    ]
  },
  "__index": "### *man\n\n`*man` は、Sercrod に組み込まれた manual system です。短い説明は console に出力し、`<pre>` 要素で使うと長い manual text をページ内に表示できます。\n\nSercrod 本体は、小さな short text だけを fallback として持ちます。より詳しい説明は `man.json` から読み込めます。`*man` を使わない project は小さく保て、詳しい documentation が必要な project だけ外部 manual を opt-in できます。\n\n#### 使い方\n\n基本的な使い方です。\n\n    <pre *man></pre>\n    <pre *man=\"directives\"></pre>\n    <pre *man=\"'*post'\"></pre>\n    <pre *man=\"current_key\"></pre>\n    <p *man=\"@click\"></p>\n    <span *man=\":style\"></span>\n\n- `<pre>` 要素で使う場合:\n  - 値なしの `*man` は、Sercrod manual の top-level index または overview を表示します。\n  - `*man=\"directives\"` は、core directives の一覧を `<pre>` 内に表示します。\n  - `*man=\"expr\"` は、まず `expr` を現在の scope で Sercrod expression として評価します。\n    結果が空でない string、number、または true の場合、その値を key として使います。\n    それ以外の場合は、`expr` の source text 自体を key として使います。\n    対応する manual entry が `<pre>` 内に表示されます。\n\n- その他の要素で使う場合:\n  - `*man=\"expr\"` は、上記と同じ方法で key を解決します。\n  - 対応する short entry があれば、`*man` は短い説明と、必要に応じて example を JavaScript console に出力します。\n    その要素の DOM content は変更しません。\n  - `<pre>` 以外で `*man=\"directives\"` を使った場合、要素自体は変更せず、`<pre *man=\"directives\">` を使えば full directives list をページ内に表示できることを console に出します。\n\n#### key\n\n具体的な機能を参照する key では、必ず prefix を含めます。\n\n- Sercrod directive は `*` を使います。例: `*post`, `*fetch`, `*if`\n- event binding は `@` を使います。例: `@click`, `@submit`\n- attribute binding は `:` を使います。例: `:text`, `:html`, `:class`\n\n`*xxx` と `n-xxx` は同じ manual entry を共有します。たとえば、`*print` と `n-print` は同じ entry を使います。\n\nこれに加えて、`*man` はいくつかの special key を理解します。\n\n- `__index` - 値なし `*man` の default になる top-level index text\n- `__directives` - `*man=\"directives\"` の背後で使われる directives list\n- `__short` - console/fallback 用の short manual entries\n- `__debug` - `*man=\"debug\"` の背後で使われる runtime debugging guide\n- `__unknown` - key に manual entry がない場合に使う entry\n- `__invalid` - key string が `*man` として不正な場合に使う entry\n\n通常の project では、これらの internal key を直接使う必要はありません。\n\n#### 出力モード\n\n`<pre>` 以外の要素では、次のように動きます。\n\n- `*man` は DOM を変更しません。\n- console に短い summary と example を出力します。\n- log には検索しやすい prefix が付きます。\n\nconsole 出力例:\n\n    [Sercrod man] *print\n    式の結果を plain text として要素内に表示します。\n    Example: <span *print=\"user.name\"></span>\n\n`<pre>` 要素では、次のように動きます。\n\n- `*man` は指定 key に対応する full manual text を読み込もうとします。\n- `man.json` が利用可能で、対応する entry があれば、その text を使います。\n- 見つからない場合は、short summary に fallback し、full manual が読み込まれていないことを説明します。\n\ntext は `textContent` に書き込まれるため、`<` や `>` は HTML として解釈されず、そのまま表示されます。\n\n#### man.json と外部 manual\n\nSercrod は、長い manual text を JSON file から読み込めます。\n\n- runtime では `Sercrod.load_man(url)` を使って `man.json` を読み込みます。\n- `man.json` の各 key は、`*man` key ひとつに対応します。\n  例: `\"print\": \"### *print\\n...\"`\n\n`man.json` がある場合:\n\n- `<pre>` 上の `*man` は、外部 text を優先します。\n- Sercrod 本体に組み込まれた short text は fallback として残り、console output にも使われます。\n\n`man.json` がない場合:\n\n- `*man` は short text だけでも動作します。\n- `<pre *man=\"*post\"></pre>` は short summary と、full manual が読み込まれていないことを表示します。\n\nこの設計により、Sercrod core を小さく保ちながら、必要な project だけ rich manual を提供できます。\n\n#### 例\n\nindex entry を `<pre>` に表示します。\n\n    <pre *man></pre>\n\ndirective の manual entry を表示します。\n\n    <pre *man=\"*post\"></pre>\n\nevent について尋ねます。\n\n    <p *man=\"@click\"></p>\n\nattribute binding について尋ねます。\n\n    <span *man=\":style\"></span>\n\n実際に使っている要素と同じ要素に `*man` を付けます。\n\n    <button *post=\"/api/contact.php:result\" *man=\"*post\">\n      Send\n    </button>\n\nこの pattern では、button 上で実際に使っている directive を `*man` が説明します。\n\n#### 注意点\n\n- `*man` は data や DOM binding を変更しません。documentation と debugging のためだけの仕組みです。\n- Sercrod 本体に含まれる short text は意図的に小さく、どの環境でも安全に読み込めるようにしています。\n- 長い text は Sercrod 本体の外、たとえば `man.json` に置きます。\n- 判断に迷う場合、`*man` が説明する挙動は、現在の Sercrod runtime にもっとも近い説明として扱います。\n",
  "__directives": "### Sercrod directives\n\n`*man=\"directives\"` は、Sercrod で利用できる主な directive を一覧表示します。\n\n## Control\n\n- `*if`: expression が truthy のとき、この要素を条件付きで描画します。\n- `*elseif`: 直前の `*if` または `*elseif` と組になる else-if branch です。\n- `*else`: `*if` / `*elseif` group で、どの条件にも一致しなかった場合の fallback branch です。\n- `*for`: list の各 item に対して、この要素を繰り返します。\n- `*each`: 要素自身を container として残したまま、子 node を各 item に対して繰り返します。\n- `*switch`: expression に基づいて、`*case` / `*default` から branch を選択します。\n- `*case`: `*switch` expression が case value と一致したとき、この branch を描画します。\n- `*case.break`: `*case` と同様ですが、一致した branch の描画後に switch fallthrough を止めます。\n- `*break`: `*switch` の fallthrough flow で break point を示します。\n- `*default`: `*switch` でどの `*case` にも一致しなかった場合の fallback branch です。\n\n## Data and model\n\n- `*let`: この要素内の expression から利用できる local variable を定義します。\n- `*global`: 変数を Sercrod の global data scope に書き込みます。\n- `*input`: form control の値を data path に bind します。\n- `*lazy`: input-oriented flow 中の parent template refresh を遅らせます。\n- `*eager`: 通常は各 input event ごとに、bound data を積極的に更新します。\n- `*stage`: apply 前の編集用に、host data の staged copy を扱います。\n- `*apply`: stage 上の変更を host data に反映します。\n- `*restore`: stage 上の変更を破棄し、最後の安定状態から host data を復元します。\n- `*save`: 互換用の file save 形式です。新しい例では `*save.file`、`*save.session`、または `*save.store` を使います。\n- `*save.file`: host data または selected `*keys` を JSON file として保存します。\n- `*save.session`: host data または selected `*keys` を `sessionStorage` に保存します。\n- `*save.store`: host data または selected `*keys` を persistent browser storage に保存します。\n- `*load`: 互換用の file load 形式です。新しい例では `*load.file`、`*load.session`、または `*load.store` を使います。\n- `*load.file`: JSON file を読み込み、`*keys` と `*into` に従って data へ反映します。\n- `*load.session`: `sessionStorage` から JSON を読み込み、`*keys` と `*into` に従って data へ反映します。\n- `*load.store`: persistent browser storage から JSON を読み込み、`*keys` と `*into` に従って data へ反映します。\n- `*keys`: action directive が使う top-level data keys を選択します。\n\n## Remote data and IO\n\n- `*fetch`: URL から JSON を取得し、host data に merge または書き込みます。\n- `*post`: host data を JSON として POST し、JSON response を host data に書き戻します。\n- `*api`: endpoint に request を送り、response を `$download`、`$upload`、必要に応じて `*into` に保存します。\n- `*into`: API、fetch、WebSocket などの結果を、指定した data key に保存します。\n- `*upload`: 選択された file または data を server endpoint に upload します。\n- `*download`: server endpoint から data の download を開始します。\n- `*websocket`: この host の WebSocket connection を開き、管理します。\n- `*ws-send`: active な WebSocket connection を通じて message を送信します。\n- `*ws-to`: 複数 connection が開いている場合に、`*ws-send` が使う WebSocket URL を選択します。\n\n## Output\n\n- `*print`: expression の結果を plain text として要素内に表示します。\n- `*compose`: html filter を通じて、expression の結果からこの要素の `innerHTML` を設定します。\n- `*textContent`: expression の結果から DOM `textContent` property を設定します。\n- `*innerHTML`: expression の結果から DOM `innerHTML` property を設定します。\n\n## Hooks and utilities\n\n- `*prevent-default`: mode に応じて、Enter key の既定動作、form submit、またはその両方を抑止します。\n- `*prevent`: Enter key、submit、または all-mode prevention に使う `*prevent-default` の短縮形です。\n- `*updated`: この host が更新された後に handler を呼び出します。\n- `*update`: この host または要素の update 後に、target Sercrod host を強制 update します。\n- `*updated-propagate`: `*update` の互換 alias です。\n- `*methods`: この host 内の expression から呼び出せる methods を定義します。\n- `*log`: expression を評価し、その値、式、host snippet を log に出力します。\n- `*man`: directive、event、attribute binding の built-in または external manual text を表示します。\n\n## Shadow DOM bridge\n\n- `*shadow`: Shadow DOM 側の template を `<template>` 要素で定義します。\n- `*host`: host element を名前付き `*shadow` template に接続します。\n- `*shadow-host`: `*host` の説明的な alias です。\n- `n-host`: `*host` の namespace-style alias です。\n- `n-shadow-host`: `*host` の namespace-style alias です。\n\n## Template and inclusion\n\n- `*template`: この subtree を再利用可能な template として mark します。\n- `*include`: template または partial をこの位置に include して描画します。\n- `*import`: 外部 HTML を import し、通常の Sercrod template flow で描画します。\n\n## Literal and comment-like behavior\n\n- `*literal`: inner content を Sercrod 展開せず、literal string として扱います。\n- `*rem`: この要素を描画結果から除外します。Sercrod 専用 comment として使えます。\n",
  "__short": {
    "__index": {
      "short": "Sercrod の directive、event、binding を参照するための man index です。",
      "example": "<pre *man></pre>"
    },
    "__directives": {
      "short": "<pre *man=\"directives\"> を使うと、この要素内に Sercrod directive の一覧を表示できます。",
      "example": "<pre *man=\"directives\"></pre>"
    },
    "__debug": {
      "short": "Sercrod は runtime inspection hook として \"sercrod-change\" event を公開します。この event は render scheduler ではありません。非構造 change update は DOM diff ではなく、既知の data path を登録済み DOM command に route します。",
      "example": "document.addEventListener(\"sercrod-change\", (event)=> console.log(event.detail));"
    },
    "__unknown": {
      "short": "この Sercrod version には、この key に対応する *man entry が定義されていません。",
      "example": "key: *post, @click, :text"
    },
    "__invalid": {
      "short": "*man の key は、*, @, : のいずれかで始まる必要があります。",
      "example": "*man=\"*post\" / *man=\"@click\" / *man=\":text\""
    },
    "if": {
      "short": "式が truthy のとき、この要素を描画します。",
      "example": "<div *if=\"show\">Visible</div>"
    },
    "elseif": {
      "short": "直前の *if または *elseif と組になる else-if branch です。",
      "example": "<div *elseif=\"mode === 'edit'\">Edit</div>"
    },
    "else": {
      "short": "*if / *elseif group で、どの条件にも一致しなかった場合の fallback branch です。",
      "example": "<div *else>Fallback</div>"
    },
    "for": {
      "short": "list の各 item に対して、この要素を繰り返します。",
      "example": "<li *for=\"item in items\">%item%</li>"
    },
    "each": {
      "short": "要素自身を container として残したまま、子 node を各 item に対して繰り返します。",
      "example": "<ul *each=\"item of items\"><li>%item%</li></ul>"
    },
    "switch": {
      "short": "式に基づいて、*case / *default から branch を選択します。",
      "example": "<div *switch=\"status\">...</div>"
    },
    "case": {
      "short": "*switch expression が case value と一致したとき、この branch を描画します。",
      "example": "<p *case=\"'ready'\">Ready</p>"
    },
    "case.break": {
      "short": "*case と同様ですが、一致した branch の描画後に switch fallthrough を止めます。",
      "example": "<p *case.break=\"'ready'\">Ready</p>"
    },
    "break": {
      "short": "*switch の fallthrough flow で break point を示します。",
      "example": "<p *case=\"'ready'\" *break>Ready</p>"
    },
    "default": {
      "short": "*switch でどの *case にも一致しなかった場合の fallback branch です。",
      "example": "<p *default>Default</p>"
    },
    "let": {
      "short": "この要素内の式から利用できる local variable を定義します。",
      "example": "<div *let=\"total = price * qty\">%total%</div>"
    },
    "global": {
      "short": "変数を Sercrod の global data scope に書き込みます。",
      "example": "<div *global=\"appTitle = 'Sercrod'\"></div>"
    },
    "literal": {
      "short": "inner content を Sercrod 展開せず、literal string として扱います。",
      "example": "<pre *literal>%raw_markdown%</pre>"
    },
    "rem": {
      "short": "この要素を描画結果から除外します。Sercrod 専用 comment として使えます。",
      "example": "<div *rem>debug-only block</div>"
    },
    "input": {
      "short": "form control の値を data path に bind します。",
      "example": "<input type=\"text\" *input=\"form.name\">"
    },
    "lazy": {
      "short": "input 系 flow で、毎回の input ではなく後の event で bound data を更新します。",
      "example": "<input *input=\"form.name\" *lazy>"
    },
    "eager": {
      "short": "通常は各 input event ごとに、bound data を積極的に更新します。",
      "example": "<input *input=\"form.name\" *eager>"
    },
    "stage": {
      "short": "apply 前の編集用に、host data の staged copy を扱います。",
      "example": "<form *stage=\"draft\">...</form>"
    },
    "apply": {
      "short": "stage 上の変更を host data に反映します。",
      "example": "<button *apply>Apply</button>"
    },
    "restore": {
      "short": "stage 上の変更を破棄し、最後の安定状態から host data を復元します。",
      "example": "<button *restore>Reset</button>"
    },
    "save": {
      "short": "host data または staged view を JSON file、sessionStorage、persistent browser storage に保存します。",
      "example": "<button *save.file=\"'backup.json'\" *keys=\"profile\">Save</button>"
    },
    "load": {
      "short": "JSON data を file、sessionStorage、persistent browser storage から host data に読み込みます。",
      "example": "<button *load.file *keys=\"profile\" *into=\"draft\">Load</button>"
    },
    "post": {
      "short": "host data を JSON として POST し、JSON response を host data に書き戻します。",
      "example": "<button type=\"button\" *post=\"/api/contact.php:result\">Send</button>"
    },
    "fetch": {
      "short": "URL から JSON を取得し、Sercrod data に merge または書き込みます。",
      "example": "<div *fetch=\"/api/items.json:items\"></div>"
    },
    "print": {
      "short": "式の結果を plain text として要素内に表示します。",
      "example": "<span *print=\"user.name\"></span>"
    },
    "compose": {
      "short": "html filter を通じて、式の結果からこの要素の innerHTML を設定します。",
      "example": "<div *compose=\"layouts.card\"></div>"
    },
    "textContent": {
      "short": "式の結果から DOM textContent property を設定します。",
      "example": "<div *textContent=\"message\"></div>"
    },
    "innerHTML": {
      "short": "式の結果から DOM innerHTML property を設定します。",
      "example": "<div *innerHTML=\"html\"></div>"
    },
    "api": {
      "short": "endpoint に request を送り、response を $download、$upload、必要に応じて *into に保存します。",
      "example": "<button type=\"button\" *api=\"/api/contact.php\" method=\"POST\" body=\"form\" *into=\"result\">Send</button>"
    },
    "into": {
      "short": "API、fetch、WebSocket などの結果を、指定した data key に保存します。",
      "example": "<div *api=\"/api/user.json\" *into=\"user\"></div>"
    },
    "websocket": {
      "short": "この host の WebSocket connection を開き、管理します。",
      "example": "<div *websocket=\"wsUrl\"></div>"
    },
    "ws-send": {
      "short": "active な WebSocket connection を通じて message を送信します。",
      "example": "<button *ws-send=\"message\">Send</button>"
    },
    "ws-to": {
      "short": "複数 connection が開いている場合に、*ws-send が使う WebSocket URL を選択します。",
      "example": "<button *ws-send=\"msg\" *ws-to=\"%notifyUrl%\">Notify</button>"
    },
    "upload": {
      "short": "選択された file または data を server endpoint に upload します。",
      "example": "<input type=\"file\" *upload=\"'/api/upload'\">"
    },
    "download": {
      "short": "server endpoint から data の download を開始します。",
      "example": "<button *download=\"'/api/report.csv'\">Download</button>"
    },
    "prevent-default": {
      "short": "mode に応じて、Enter key の既定動作、form submit、またはその両方を抑止します。",
      "example": "<form *prevent-default=\"submit\" @submit=\"save()\">...</form>"
    },
    "prevent": {
      "short": "Enter key、submit、または all-mode prevention に使う *prevent-default の短縮形です。",
      "example": "<form *prevent=\"submit\" @submit=\"save()\">...</form>"
    },
    "updated": {
      "short": "この host が更新された後に handler を呼び出します。",
      "example": "<div *updated=\"onUpdated\"></div>"
    },
    "updated-propagate": {
      "short": "*update の互換 alias です。",
      "example": "<button *updated-propagate=\"root\">Refresh root</button>"
    },
    "methods": {
      "short": "この host 内の expression から呼び出せる methods を定義します。",
      "example": "<script type=\"application/sercrod-methods\" *methods>...</script>"
    },
    "log": {
      "short": "式を評価し、その値、式、host snippet を log に出力します。",
      "example": "<pre *log=\"data\"></pre>"
    },
    "template": {
      "short": "この subtree を再利用可能な template として mark します。",
      "example": "<template *template=\"card\">...</template>"
    },
    "include": {
      "short": "template または partial をこの位置に include して描画します。",
      "example": "<div *include=\"card\"></div>"
    },
    "import": {
      "short": "外部 HTML を import し、通常の Sercrod template flow で描画します。",
      "example": "<div *import=\"/partials/card.html\"></div>"
    },
    "man": {
      "short": "directive、event、attribute binding の built-in または external manual text を表示します。",
      "example": "<pre *man=\"*post\"></pre>"
    },
    "events": {
      "short": "Event binding attribute は、対応する DOM event が発生したときに Sercrod expression を評価します。",
      "example": "<button @click=\"doSomething($event)\">Click</button>"
    },
    "event-click": {
      "short": "@click は、この要素で click event が発生したときに式を評価します。",
      "example": "<button @click=\"doSomething($event)\">Click</button>"
    },
    "event-input": {
      "short": "@input は、この form control で input event が発生したときに式を評価します。",
      "example": "<input @input=\"onInput($event)\">"
    },
    "event-change": {
      "short": "@change は、change event が発生したときに式を評価します。",
      "example": "<select @change=\"onChange($event)\"></select>"
    },
    "event-submit": {
      "short": "@submit は、submit event が発生したときに式を評価します。",
      "example": "<form @submit=\"onSubmit($event)\">...</form>"
    },
    "event-focus": {
      "short": "@focus は、focus event が発生したときに式を評価します。",
      "example": "<input @focus=\"onFocus($event)\">"
    },
    "event-blur": {
      "short": "@blur は、blur event が発生したときに式を評価します。",
      "example": "<input @blur=\"onBlur($event)\">"
    },
    "event-keydown": {
      "short": "@keydown は、keydown event が発生したときに式を評価します。",
      "example": "<div tabindex=\"0\" @keydown=\"handle_key($event)\"></div>"
    },
    "event-keyup": {
      "short": "@keyup は、keyup event が発生したときに式を評価します。",
      "example": "<input @keyup=\"handle_key($event)\">"
    },
    "attributes": {
      "short": "Attribute binding は式を評価し、その結果を DOM attribute または property に書き込みます。",
      "example": "<a :href=\"url\">Link</a>"
    },
    "attribute-text": {
      "short": ":text は、式の結果を要素の text content に bind します。",
      "example": "<span :text=\"user.name\"></span>"
    },
    "attribute-html": {
      "short": ":html は、式の結果を innerHTML に bind します。文字列は HTML として挿入されます。",
      "example": "<div :html=\"html\"></div>"
    },
    "attribute-class": {
      "short": ":class は、string、array、object から class attribute を計算します。",
      "example": "<div :class=\"classList\"></div>"
    },
    "attribute-style": {
      "short": ":style は、式から style attribute または style property を計算します。",
      "example": "<div :style=\"styleText\"></div>"
    },
    "attribute-value": {
      "short": ":value は、form control の value property と value attribute を bind します。",
      "example": "<input type=\"text\" :value=\"form.name\">"
    },
    "attribute-href": {
      "short": ":href は、link や resource element の href attribute を bind します。",
      "example": "<a :href=\"url\">Link</a>"
    },
    "attribute-src": {
      "short": ":src は、image、script、media element の src attribute を bind します。",
      "example": "<img :src=\"imageUrl\" alt=\"\">"
    },
    "attribute-action": {
      "short": ":action は、form の action attribute を bind します。",
      "example": "<form :action=\"endpoint\"></form>"
    },
    "attribute-formaction": {
      "short": ":formaction は、submit button の formaction attribute を bind します。",
      "example": "<button type=\"submit\" :formaction=\"endpoint\">Submit</button>"
    },
    "attribute-xlink:href": {
      "short": ":xlink:href は、SVG element の xlink:href attribute を bind します。",
      "example": "<use :xlink:href=\"iconRef\"></use>"
    },
    "shadow": {
      "short": "Shadow DOM 側の template を定義します。`*host` から名前で接続できます。",
      "example": "<template *shadow=\"messagebox\">...</template>"
    },
    "host": {
      "short": "host element を名前付き `*shadow` template に接続します。slot assignment は browser 標準の挙動に任せます。",
      "example": "<message-box *host=\"messagebox\">...</message-box>"
    },
    "shadow-host": {
      "short": "`*host` の説明的な alias です。host element を名前付き `*shadow` template に接続します。",
      "example": "<message-box *shadow-host=\"messagebox\">...</message-box>"
    },
    "n-host": {
      "short": "`*host` の namespace-style alias です。通常の例では `*host` を推奨します。",
      "example": "<message-box n-host=\"messagebox\">...</message-box>"
    },
    "n-shadow-host": {
      "short": "`*host` の namespace-style alias です。通常の例では `*host` を推奨します。",
      "example": "<message-box n-shadow-host=\"messagebox\">...</message-box>"
    },
    "save.file": {
      "short": "host data または selected *keys を JSON file として保存します。",
      "example": "<button *save.file=\"'backup.json'\" *keys=\"profile\">Save</button>"
    },
    "save.session": {
      "short": "host data または selected *keys を browser sessionStorage に保存します。",
      "example": "<button *save.session=\"'draft'\" *keys=\"profile\">Save session</button>"
    },
    "load.file": {
      "short": "browser-selected file から JSON を読み込み、*keys と *into に従って反映します。",
      "example": "<button *load.file *keys=\"profile\" *into=\"draft\">Load</button>"
    },
    "load.session": {
      "short": "browser sessionStorage から JSON を読み込み、*keys と *into に従って反映します。",
      "example": "<button *load.session=\"'draft'\" *keys=\"profile\" *into=\"draft\">Load session</button>"
    },
    "keys": {
      "short": "save/load/WebSocket send などの action directive で top-level data keys を選択します。",
      "example": "<button *save.file=\"'backup.json'\" *keys=\"profile settings\">Save</button>"
    },
    "save.store": {
      "short": "host data または selected *keys を persistent browser storage に保存します。",
      "example": "<button *save.store=\"'draft'\" *keys=\"profile\">Save store</button>"
    },
    "load.store": {
      "short": "persistent browser storage から JSON を読み込み、*keys と *into に従って反映します。",
      "example": "<button *load.store=\"'draft'\" *keys=\"profile\" *into=\"draft\">Load store</button>"
    },
    "update": {
      "short": "この host または要素の update 後に、target Sercrod host を強制 update します。",
      "example": "<button *update=\"root\">Refresh root</button>"
    },
    "dominate": {
      "short": "*dominate は通常の automatic structural redraw を抑制しますが、登録済み non-structural change command は default で許可します。freeze / static / noupdate ではありません。",
      "example": "<serc-rod *dominate data='{\"title\":\"Alpha\"}'><h1 *print=\"title\"></h1></serc-rod>"
    },
    "dominant": {
      "short": "*dominant は *dominate の compatibility alias です。新しい template では *dominate を使ってください。",
      "example": "<serc-rod *dominate></serc-rod>"
    },
    "unit": {
      "short": "*iterate が使う *template 内で、選択可能な表示 unit 名を宣言します。",
      "example": "<section *unit=\"'card'\">%item.title%</section>"
    },
    "entry": {
      "short": "*entry は *unit の compatibility alias です。新しい template では *unit を使ってください。",
      "example": "<section *entry=\"'card'\">%item.title%</section>"
    }
  },
  "__data": "### Data and *let\n\n#### 概要\n\nこのリファレンスでは、`*let` が Sercrod の data とどのように関係するかを詳しく説明します。\n\n- `*let` が新しい変数を作る仕組み。\n- 既存 data が変更されずに残る場合。\n- ネストした代入がどのように振る舞うか。\n- loop 内で何が起きるか。\n- side effect の観点で、`*let` と `*global` がどのように違うか。\n\nここでは、runtime の実際の挙動を pattern ごとに整理します。これにより、Sercrod の host data、つまり `<serc-rod>` の `data` が変更される場合と、変更されない場合を予測しやすくします。\n\n\n### 1. Data model recap\n\npattern を見る前に、3つの層を分けて考えると理解しやすくなります。\n\n1. **Host data (`_data`)**\n\n   - 各 `<serc-rod>` は、`data=\"...\"` または `data='{...}'` 属性から作られた data object を保持します。\n   - これは scope を作るための基礎 object です。\n   - ここで「host data が変わる」と言う場合、この object が変更される、または新しい property を受け取る、という意味です。\n\n2. **Effective scope (`effScope`)**\n\n   - ある要素の位置で「expression から見えるもの」を表す plain object です。\n   - host data から始まります。\n   - Sercrod は、`item`、`index` などの loop 変数のような追加 entry を加えます。\n   - 各要素では、`effScope` が置き換えられたり拡張されたりすることがあります。たとえば `*let` がその例です。\n\n3. **Local *let scope (`letScope`)**\n\n   - 要素が `*let` を持つ場合、Sercrod は次のように `letScope` を作ります。\n\n     - `letScope = Object.assign(Object.create(effScope), effScope)`\n\n   - `*let` の code は、sandbox を通じてこの `letScope` に対して実行されます。\n   - 実行後は次のようになります。\n\n     - この要素とその子要素の `effScope` は `letScope` になります。\n     - `letScope` の新しい名前は、host data にコピー、つまり promoted される場合があります。\n\nPromotion rule、つまり現在の実装における昇格規則:\n\n- `*let` の終了後、Sercrod は `letScope` 内の各 property name を確認します。\n- 各 key `k` について、次のように扱います。\n\n  - `k` がすでに host data に存在する場合、上書きされません。\n  - `k` が host data に存在しない場合、`this._data[k] = letScope[k]` が代入されます。\n\nこの規則が、`*let` が data にどのように影響するかの中核です。\n\n\n### 2. Pattern reference\n\nこの section では、具体的な pattern を並べます。初期 data、`*let` code、local scope と host data の両方で何が起きるかを確認します。\n\n\n#### 2.1 パターン A - 新しい top-level 変数\n\nCase A1: 既存 data から新しい helper を作る場合。\n\n```html\n<serc-rod id=\"invoice\" data='{\"price\": 1200, \"qty\": 3}'>\n  <p *let=\"total = price * qty\">\n    <span *print=\"total\"></span>\n  </p>\n</serc-rod>\n```\n\n- Initial host data:\n\n  ```json\n  { \"price\": 1200, \"qty\": 3 }\n  ```\n\n- `*let` execution:\n\n  - `total` は、まだ `effScope` にも host data にも存在しません。\n  - sandbox は `total` を `letScope` に書き込みます。\n\n- Promotion:\n\n  - `*let` 後、runtime は `letScope` 内に `total` があることを見つけます。\n  - `total` は host data に存在しないため、host data は次のようになります。\n\n    ```json\n    { \"price\": 1200, \"qty\": 3, \"total\": 3600 }\n    ```\n\n- Visibility:\n\n  - `<p>` とその子要素の中では、`total` は `effScope`、つまり `letScope` を通じて利用できます。\n  - `<p>` の sibling elements も、`total` を通常の data field として使えます。\n\n\nCase A2: 複数の新しい名前を同時に作る場合。\n\n```html\n<serc-rod data='{\"a\": 2, \"b\": 3}'>\n  <p *let=\"\n    sum = a + b;\n    diff = a - b;\n  \">\n    <span *print=\"sum\"></span>\n    <span *print=\"diff\"></span>\n  </p>\n</serc-rod>\n```\n\n- New names: `sum`, `diff`.\n- 初回 render 後の data:\n\n  ```json\n  { \"a\": 2, \"b\": 3, \"sum\": 5, \"diff\": -1 }\n  ```\n\n- 以後の render では、`sum` と `diff` はすでに host data に存在します。そのため、`letScope` 内の local values だけが更新されます。host data の entries は、別の処理が更新しない限り、最初の値のまま残ります。\n\n\n#### 2.2 パターン B - 既存の top-level property の上書き\n\nCase B1: data にすでに存在する field を再代入する場合。\n\n```html\n<serc-rod id=\"priceBox\" data='{\"price\": 100}'>\n  <p *let=\"price = price * 1.1\">\n    <span *print=\"price\"></span>\n  </p>\n  <p>\n    Original price: <span *print=\"$data.price\"></span>\n  </p>\n</serc-rod>\n```\n\n- Initial host data:\n\n  ```json\n  { \"price\": 100 }\n  ```\n\n- `*let` execution:\n\n  - `price` は host data に存在します。\n  - `letScope` は、`price` を含む `effScope` の shallow copy から始まります。\n  - assignment は `letScope.price` を `110` に変更します。\n\n- Promotion:\n\n  - runtime は `letScope` 内の key `price` を確認します。\n  - `price` はすでに host data に存在するため、host data は上書きされません。\n\n- Result:\n\n  - `*let` が付いた `<p>` の中では、`price` は `110` です。\n  - `$data.price` は host data を指すため、`100` のままです。\n\nつまり、既存 top-level property の単純な再代入は、local shadowing になります。host data の値は変更されません。\n\n\nCase B2: 既存 data field から新しい名前を作る場合。\n\n```html\n<serc-rod data='{\"price\": 100}'>\n  <p *let=\"displayPrice = price * 1.1\">\n    <span *print=\"displayPrice\"></span>\n  </p>\n</serc-rod>\n```\n\n- `displayPrice` は新しい top-level name です。\n- 初回 render 後、host data は次のようになります。\n\n  ```json\n  { \"price\": 100, \"displayPrice\": 110 }\n  ```\n\nこれは Pattern A と同じです。\n\n\n#### 2.3 パターン C - 新しい nested object の作成\n\nCase C1: 存在しない object path を作る場合。\n\n```html\n<serc-rod data='{\"price\": 100}'>\n  <p *let=\"summary = {}; summary.total = price * 2\">\n    <span *print=\"summary.total\"></span>\n  </p>\n</serc-rod>\n```\n\n- `summary` は新しい top-level name です。\n- sandbox は `letScope.summary` を object として作ります。\n- `summary.total` はその object 上に設定されます。\n- Promotion により、`summary` は host data に追加されます。\n\n初回 render 後:\n\n```json\n{\n  \"price\": 100,\n  \"summary\": {\n    \"total\": 200\n  }\n}\n```\n\nCase C2: 1つの `*let` 内で複数の nested fields を作る場合。\n\n```html\n<p *let=\"\n  summary = {};\n  summary.total = price * qty;\n  summary.label = 'Total';\n\">\n  <span *print=\"summary.label\"></span>\n  <span *print=\"summary.total\"></span>\n</p>\n```\n\n- `summary` が host data に存在しなければ、最後に object 全体が promoted されます。\n- `summary` がすでに host data に存在する場合は、Pattern D に近い挙動になります。\n\n\n#### 2.4 パターン D - 既存の nested structure の更新\n\nCase D1: 既存 object の nested property を変更する場合。\n\n```html\n<serc-rod data='{\"user\": {\"name\": \"Alice\", \"role\": \"admin\"}}'>\n  <p *let=\"user.name = 'Bob'\">\n    <span *print=\"user.name\"></span>\n  </p>\n</serc-rod>\n```\n\n- `user` は host data に存在する object です。\n- `letScope.user` は、その同じ object への reference を保持します。\n- `user.name = 'Bob'` は、その object の property を変更します。\n\n結果:\n\n```json\n{ \"user\": { \"name\": \"Bob\", \"role\": \"admin\" } }\n```\n\nこれは top-level `user` を再代入しているのではありません。host data 内の object を reference 経由で変更しています。\n\nCase D2: 既存 object に新しい nested property を追加する場合。\n\n```html\n<serc-rod data='{\"user\": {\"name\": \"Alice\"}}'>\n  <p *let=\"user.role = 'admin'\">\n    <span *print=\"user.role\"></span>\n  </p>\n</serc-rod>\n```\n\n結果:\n\n```json\n{ \"user\": { \"name\": \"Alice\", \"role\": \"admin\" } }\n```\n\n`user` object は shared reference なので、nested update は host data に反映されます。\n\nCase D3: 既存 top-level property を新しい object で置き換える場合。\n\n```html\n<serc-rod data='{\"user\": {\"name\": \"Alice\"}}'>\n  <p *let=\"user = { name: 'Bob' }\">\n    <span *print=\"user.name\"></span>\n  </p>\n</serc-rod>\n```\n\n- `user` は host data にすでに存在します。\n- assignment は `letScope.user` を新しい object に置き換えます。\n- Promotion では、`user` が host data に存在するため、host data は上書きされません。\n\n結果:\n\n- local scope 内では `user.name` は `\"Bob\"` です。\n- host data では `$data.user.name` は `\"Alice\"` のままです。\n\nこの違いが重要です。\n\n\n#### 2.5 パターン E - `+=` などの演算子と未知の変数\n\nCase E1: 存在しない変数に `+=` を使う場合。\n\n```html\n<serc-rod data='{}'>\n  <p *let=\"count += 1\">\n    <span *print=\"count\"></span>\n  </p>\n</serc-rod>\n```\n\nJavaScript semantics と sandbox により、これは「undefined に 1 を加える」ような意味になります。\n\n典型的には、結果は `NaN` になる可能性があります。\n\n初回 render 後、`count` が `letScope` に作られた場合、promotion によって host data に入る可能性があります。\n\n結果は次のような形になる可能性があります。\n\n```json\n{ \"count\": null }\n```\n\nまたは、runtime の serialize/print の仕方によって `NaN` 相当として見える場合があります。\n\n推奨:\n\n```html\n<p *let=\"count = (count || 0) + 1\">\n```\n\nまたは、data で先に初期化します。\n\n```html\n<serc-rod data='{\"count\": 0}'>\n```\n\nCase E2: 存在する数値に `+=` を使う場合。\n\n```html\n<serc-rod data='{\"count\": 0}'>\n  <p *let=\"count += 1\">\n    <span *print=\"count\"></span>\n  </p>\n</serc-rod>\n```\n\n- `count` は host data に存在します。\n- `letScope.count` は `1` になります。\n- host data の `count` は promotion によって上書きされません。\n\nしたがって、local display は `1` ですが、host data は `0` のままです。\n\n\n#### 2.6 パターン F - loop 内の *for / *each\n\nCase F1: loop item から helper を作る場合。\n\n```html\n<serc-rod data='{\"items\": [{\"price\": 100}, {\"price\": 200}]}'>\n  <ul>\n    <li *for=\"item of items\" *let=\"taxed = item.price * 1.1\">\n      <span *print=\"taxed\"></span>\n    </li>\n  </ul>\n</serc-rod>\n```\n\n- 各 loop iteration には、それぞれの `effScope` があります。\n- `taxed` は各 item 用の local helper として有用です。\n- ただし、promotion rule により、初回に `taxed` が host data に追加される可能性があります。\n\nそのため、loop 内で作る helper name は、host data へ昇格される可能性があることを意識して名前を選ぶべきです。\n\nCase F2: item の nested property を変更する場合。\n\n```html\n<li *for=\"item of items\" *let=\"item.taxed = item.price * 1.1\">\n  <span *print=\"item.taxed\"></span>\n</li>\n```\n\n- `item` は `items` 配列内の object への reference です。\n- `item.taxed` を設定すると、その object に property が追加されます。\n- これは host data の `items` にも反映されます。\n\n結果例:\n\n```json\n{\n  \"items\": [\n    { \"price\": 100, \"taxed\": 110 },\n    { \"price\": 200, \"taxed\": 220 }\n  ]\n}\n```\n\nCase F3: loop variable 自体を再代入する場合。\n\n```html\n<li *for=\"item of items\" *let=\"item = { price: 0 }\">\n  <span *print=\"item.price\"></span>\n</li>\n```\n\n- `letScope.item` は新しい object になります。\n- 元の array item は置き換えられません。\n- host data の `items` は変更されません。\n\nこれは、nested property mutation と top-level local reassignment の違いです。\n\n\n#### 2.7 パターン G - *let 内での $parent の使用\n\n`$parent` を使うと、子 host から親 host の data を参照できます。\n\n例:\n\n```html\n<serc-rod data='{\"shared\": {\"count\": 1}}'>\n  <serc-rod data='{}'>\n    <p *let=\"localCount = $parent.shared.count\">\n      <span *print=\"localCount\"></span>\n    </p>\n  </serc-rod>\n</serc-rod>\n```\n\n- `localCount` は child host の `letScope` に作られます。\n- 新しい top-level name なので、child host data へ promoted される可能性があります。\n- `$parent.shared.count` は parent host data から読まれます。\n\nparent object を reference 経由で変更する場合は注意が必要です。\n\n```html\n<p *let=\"$parent.shared.count = $parent.shared.count + 1\">\n```\n\nこれは parent data object の nested property を変更します。意図が明確な場合にだけ使ってください。\n\n\n### 3. Comparison with *global\n\n`*let` と `*global` の違いは、side effect を意図しているかどうかです。\n\n`*let`:\n\n- local helper values を作るためのものです。\n- local scope を作ります。\n- new top-level names は promotion により host data へ追加される場合があります。\n- existing top-level names は上書きしません。\n- nested objects は reference によって変更される場合があります。\n\n`*global`:\n\n- 明示的な side effect 用です。\n- host data または global scope への書き込みを意図します。\n- state mutation を目的とする場合、`*let` より `*global` の方が意味として明確です。\n\n推奨:\n\n- 表示用の派生値には `*let` を使います。\n- data を意図的に変更する処理には、event handler、method、または `*global` を使います。\n- `*let` の promotion rule に依存して business logic を組まないでください。\n\n\n### 4. Cheat sheet\n\n- 新しい top-level name を `*let` で作る:\n  - 初回 render 後、host data へ追加される可能性があります。\n\n- 既存 top-level name を `*let` で再代入する:\n  - local shadowing になります。\n  - host data は上書きされません。\n\n- 既存 object の nested property を変更する:\n  - object reference 経由なので、host data が変更されます。\n\n- 既存 top-level object を新しい object で再代入する:\n  - local shadowing になります。\n  - host data の object は置き換わりません。\n\n- loop item の nested property を変更する:\n  - 配列内 object が変更されるため、host data に反映されます。\n\n- loop variable 自体を再代入する:\n  - local variable が変わるだけです。\n  - 元の配列 item は置き換わりません。\n\n- host data を明示的に更新したい:\n  - `*let` ではなく、event handler、method、または `*global` を検討します。\n",
  "__debug": "### Sercrod debug hook\n\n#### 概要\n\nSercrod は runtime inspection hook として `sercrod-change` event を公開します。\n\nこの event は、data のどの property が変わったかを利用者や外部 code が確認するための通知です。render scheduler ではありません。\n\nSercrod 自身が値を書き込み、その結果を扱います。この仕組みを Proxy-based change detection や MutationObserver-based change detection と説明してはいけません。Proxy と MutationObserver は不足している機構ではなく、この設計では不要です。\n\n非構造 change update も DOM diff ではありません。Sercrod がすでに変更された data path を知っている場合、その既知の変更を登録済み DOM command に route します。old DOM と new DOM を比較せず、DOM 内を検索して変更箇所を探しません。\n\n#### イベント詳細\n\n- `host` - data を所有する Sercrod element。\n- `parent` - 変更された property を持つ object。\n- `key` - 変更された property 名。\n- `old` - 以前の値。\n- `new` - 新しい値。\n\n#### 例\n\n```js\ndocument.addEventListener(\"sercrod-change\", (event)=>{\n\tconst detail = event.detail;\n\tconsole.log(\"[Sercrod change]\", detail.host, detail.key, detail.old, detail.new);\n});\n```",
  "api": "### *api / n-api\n\n#### 概要\n\n`*api` / `n-api` は、Sercrod における低レベルの HTTP gateway directive です。\n\nこれは次の責務を持ちます。\n\n- 現在の scope から HTTP request を組み立てます。URL、method、省略可能な JSON body を含みます。\n- `fetch` によって request を送信します。file input では `FormData` upload も扱います。\n- host 上の共有 status flags を更新します。\n  - `$pending` - request が進行中かどうか。\n  - `$error` - この host の最後の error object。\n  - `$download` - GET-like requests からの最後の値。\n  - `$upload` - non-GET または file uploads からの最後の値。\n- `*into` / `n-into` により、必要に応じて response を名前付き data slot へ書き込みます。\n- 外部 observer 向けに event、つまり `sercrod-api` と `sercrod-error` を dispatch します。\n- non-clickable elements では、deduplication 付きで自動的に1回発火します。\n\n`*download` や `*upload` のような高水準 helper も `$pending` / `$error` / `$download` / `$upload` の convention を共有します。しかし、通常要素上の ad-hoc HTTP calls に対しては、`*api` が単一の汎用 primitive です。\n\n\n#### 基本例\n\n`user` を埋め、status を children に公開する単純な GET です。\n\n```html\n<serc-rod id=\"app\" data='{\"user\": null}'>\n  <section\n    *api=\"/api/user.json\"\n    *into=\"user\">\n\n    <p *if=\"$pending\">Loading user...</p>\n\n    <p *if=\"$error\" class=\"error\">\n      <span *print=\"$error.message\"></span>\n    </p>\n\n    <pre *if=\"user\" *print=\"JSON.stringify(user, null, 2)\"></pre>\n  </section>\n</serc-rod>\n```\n\nこの例の要点:\n\n- `section` 要素は `*api` を通じて HTTP call を所有します。\n- response は `*into=\"user\"` により、そのまま `user` へ書き込まれます。\n- `$pending` と `$error` は host 上で共有され、どの child からも読めます。\n- `user` は `null` から始まりますが、存在しない場合でも `*api` によって明示的に初期化されます。\n\n\n#### 挙動\n\n##### 基本的な挙動\n\nSercrod が rendering 中に要素上の `*api` または `n-api` を見つけると、次の処理を行います。\n\n1. 要素を clone します。children を含まない shallow clone です。\n2. 関連する属性を読みます。\n   - `*api` / `n-api` - URL template string。\n   - `method` - HTTP method。default は `\"GET\"`。\n   - `body` または `payload` - request body 用の expression。non-GET の場合のみ。\n   - `*into` / `n-into` - host data 内の省略可能な destination key。\n3. file uploads を検出します。\n\n   - clone された要素が `<input type=\"file\">` の場合、`isFile` は `true` です。\n\n4. `this._data` 上に status fields が存在しない場合は初期化します。\n   - `$pending` - `false`\n   - `$error` - `null`\n   - `$download` - `null`\n   - `$upload` - `null`\n   - `into` key - 指定されていて存在しない場合、作成して `null` に設定します。\n5. clone を parent に append します。\n6. element type に応じて request logic を接続します。\n   - `<input type=\"file\">` - `change` で upload を準備します。\n   - Button-like elements - `click` で JSON-like request を trigger します。\n   - Other elements - one-shot automatic request を schedule します。\n7. 現在の scope で original children を clone 内へ render します。children は `$pending`、`$error`、`$download`、`$upload`、および `*into` variable を読めます。\n\n\n#### リクエスト URL とプレースホルダー\n\n##### URL の取得元\n\nURL template は正確に次のどちらかから取られます。\n\n- `*api` attribute、または\n- `*api` がない場合は `n-api` attribute。\n\nraw string は internal helper `_expand_text(urlRaw, scope, work)` に渡され、global delimiters に基づいて placeholder expansion が行われます。\n\ndefault delimiters は次の通りです。\n\n- `start: \"%\"`\n- `end: \"%\"`\n\nそのため、次のような URL は、\n\n```html\n<section\n  *api=\"/api/users/%userId%?ts=%Date.now()%\"\n  *into=\"user\">\n</section>\n```\n\ncurrent scope で delimiters の間の各 expression を評価し、その結果で置き換えることにより、具体的な URL になります。\n\n注意:\n\n- expression が throw した場合、placeholder filter により、その placeholder は空文字に置き換えられます。\n- Placeholder expansion は1回だけではなく、各 request 時に行われます。そのため timestamp や current data のような dynamic values が反映されます。\n\n\n#### HTTP メソッドと本文\n\n##### メソッド\n\n`method` attribute がなければ、default method は `\"GET\"` です。\n\n```html\n<section *api=\"/api/users\" *into=\"users\"></section>\n```\n\n明示的な method を指定できます。\n\n```html\n<button\n  type=\"button\"\n  *api=\"/api/save\"\n  method=\"POST\"\n  body=\"form\"\n  *into=\"result\">\n  Save\n</button>\n```\n\nmethod は uppercase に正規化されます。\n\n##### JSON 本文 - file 以外の要素\n\nnon-file elements では、body は `body` または `payload` attribute から読みます。\n\n- `body` が存在する場合、それを使います。\n- `body` がなく `payload` が存在する場合、`payload` を使います。\n- どちらもない場合、GET 以外の request でも body は `null` になります。\n\nbody expression は current scope で評価されます。\n\n```html\n<button\n  type=\"button\"\n  *api=\"/api/save\"\n  method=\"POST\"\n  body=\"form\"\n  *into=\"result\">\n  Save\n</button>\n```\n\n`method` が `\"GET\"` の場合、body expression は送信されません。\n\nnon-GET の場合、evaluated body が `null` または `undefined` でなければ、JSON として送られます。\n\n##### 応答の解析\n\nresponse parsing は Content-Type によって決まります。\n\n- Content-Type が `application/json` を含む場合:\n  - runtime は `res.json()` を使います。\n- それ以外の場合:\n  - runtime は text を読みます。\n  - text を JSON として parse しようとします。\n  - parse に失敗した場合は、text のまま扱います。\n\n\n#### `<input type=\"file\" *api>` によるファイルアップロード\n\n`*api` が `<input type=\"file\">` に付いている場合、runtime は upload mode を使います。\n\n```html\n<input\n  type=\"file\"\n  name=\"avatar\"\n  *api=\"/api/avatar\"\n  *into=\"uploadResult\">\n```\n\n挙動:\n\n- `change` event に handler が attach されます。\n- file が選ばれると、`FormData` object が作られます。\n- 各 file が `FormData` に追加されます。\n- input の `name` attribute がある場合、それを field name として使います。\n- `name` がない場合、fallback field name として `\"files[]\"` が使われます。\n- method は GET ではなく、通常 POST-like upload として扱われます。\n- response は `$upload` と `*into` destination に書かれます。\n\nupload error は `$error` に保存され、`sercrod-error` event が dispatch されます。\n\n\n#### 共有状態フラグと *into\n\n##### 状態フラグ\n\n`*api` は host data 上に shared status fields を作成または更新します。\n\n- `$pending`\n- `$error`\n- `$download`\n- `$upload`\n\nこれらは同じ `<serc-rod>` host 内の children から読めます。\n\n```html\n<p *if=\"$pending\">Loading...</p>\n<p *if=\"$error\" class=\"error\">%$error.message%</p>\n```\n\n`$download` は GET-like request の result を保持します。\n\n`$upload` は non-GET request または file upload の result を保持します。\n\n##### `*into` / `n-into` について\n\n`*into` は response を保存する host data key を指定します。\n\n```html\n<section\n  *api=\"/api/user\"\n  *into=\"user\">\n</section>\n```\n\n- `*into=\"user\"` は response を `data.user` に書き込みます。\n- `user` key がまだない場合は、初期化されます。\n- `*into` の値は destination key として扱われます。通常の expression として動的評価されるわけではありません。\n\n複数の `*api` elements が同じ `*into` key を使う場合、後から完了した request が値を上書きします。\n\n\n#### イベント\n\n##### `sercrod-api` event について\n\nrequest が成功した場合、runtime は `sercrod-api` event を dispatch します。\n\nevent detail には通常、次のような情報が含まれます。\n\n- `url`\n- `method`\n- `data`\n- `into`\n- `host`\n- `element`\n\n外部 code はこの event を監視して、logging、analytics、debugging、追加 side effects に使えます。\n\n##### `sercrod-error` event について\n\nrequest、response parsing、body evaluation、または upload で error が起きた場合、runtime は `$error` を更新し、`sercrod-error` event を dispatch します。\n\nevent detail には error、stage、url、host、element などが含まれる場合があります。\n\n`sercrod-error` は debugging と project-level error handling のために使えます。\n\n\n#### 評価タイミングとスコープ\n\n##### URL と本文で使われるスコープ\n\nURL placeholders と body expression は、request 実行時の current scope で評価されます。\n\nこれは重要です。\n\n- loop の中で `*api` を使う場合、URL や body はその row の `item` を読めます。\n- `*let` が ancestors で値を作っている場合、その値も見える場合があります。\n- 同じ要素上に書かれた `*let` の値が `*api` expression から読めるかどうかは、render pipeline の順序に依存します。安全のため、`*api` と同じ要素ではなく、ancestor 側で必要な値を作る方が明確です。\n\n##### 子要素の描画順\n\n`*api` 要素はまず clone され、request logic が接続され、parent に append されます。\n\nその後、original children が clone 内へ render されます。\n\nそのため children は次を読めます。\n\n- `$pending`\n- `$error`\n- `$download`\n- `$upload`\n- `*into` destination key\n\nただし、request が完了する前は、これらは initial values、たとえば `false` や `null` です。\n\n\n#### 実行モデルとトリガー\n\n##### file 以外の要素\n\nnon-file `*api` elements では trigger は element type に依存します。\n\n- Button-like elements:\n  - `button`\n  - `input[type=button]`\n  - `input[type=submit]`\n  - `input[type=reset]`\n  - `a` without `download`\n  - これらは `click` で request を trigger します。\n\n- Other elements:\n  - runtime は automatic one-shot request を schedule します。\n  - これは初期 data loading に使えます。\n\n##### 自動実行の重複排除キー\n\nautomatic request では、runtime は deduplication key を使います。\n\nkey は概念的に次から作られます。\n\n- host\n- method\n- expanded URL\n- body expression または body value\n\ndeduplication により、同じ render pass や近いタイミングで同じ automatic request が重複して発火することを避けます。\n\ntime-sensitive request が必要な場合は、URL placeholder に timestamp を含めるなど、意図的に key を変えます。\n\n##### file input について\n\nfile input では automatic request は行われません。\n\nrequest は user が file を選択した `change` event によって trigger されます。\n\n\n#### conditionals and loops との併用\n\n##### 読み込み中とエラーの表示\n\n```html\n<section *api=\"/api/list\" *into=\"items\">\n  <p *if=\"$pending\">Loading...</p>\n  <p *if=\"$error\">%$error.message%</p>\n\n  <ul>\n    <li *for=\"item of items\">%item.name%</li>\n  </ul>\n</section>\n```\n\n`items` が initially `null` の可能性がある場合は、template 側で guard するか、data で empty array として初期化します。\n\n##### ループ内\n\n```html\n<button\n  type=\"button\"\n  *for=\"item of items\"\n  *api=\"/api/items/%item.id%\"\n  *into=\"selected\">\n  Load %item.name%\n</button>\n```\n\nこの pattern では、各 button は自分の `item` を URL placeholder 内で使えます。\n\n注意:\n\n- すべての buttons が同じ `*into=\"selected\"` に書き込むため、最後に完了した request が `selected` を所有します。\n- row ごとに結果を保持したい場合は、server response と data structure をその用途に合わせて設計します。\n\n\n#### 他のディレクティブとの併用\n\n##### `*into` について\n\n`*into` は `*api` の response destination を指定する主要な companion directive です。\n\n##### 他のネットワークヘルパー\n\n`*fetch`、`*post`、`*download`、`*upload` は関連 helper ですが、同じ element に複数の network control directives を混在させることは避けます。\n\n1つの element は、1つの primary network behavior を持つ方が分かりやすくなります。\n\n##### イベントハンドラ - `@click` など\n\nButton-like `*api` elements は内部 click handler を attach します。\n\n同じ element に `@click` を追加すると、order や update timing が複雑になる場合があります。\n\n必要なら wrapper element や明示的な method に処理を分けます。\n\n\n#### サーバー側の契約と推奨 API 形式\n\nSercrod template と API response は、安定した contract を共有するべきです。\n\n推奨:\n\n```json\n{\n  \"ok\": true,\n  \"data\": {\n    \"id\": 1,\n    \"name\": \"Alice\"\n  },\n  \"message\": \"Loaded\"\n}\n```\n\nまたは、template が直接 array を期待する場合:\n\n```json\n[\n  { \"id\": 1, \"name\": \"Alice\" },\n  { \"id\": 2, \"name\": \"Bob\" }\n]\n```\n\n重要なのは、template が読む path と server が返す shape を一致させることです。\n\nたとえば、template が `user.name` を読むなら、`*into=\"user\"` の response は `{ \"name\": \"Alice\" }` のような object であるべきです。\n\nresponse shape を変える場合は、template path も一緒に変更します。\n\n\n#### 推奨される使い方\n\n- 初期 data loading には non-clickable element 上の `*api` を使います。\n- user-triggered request には button-like element 上の `*api` を使います。\n- simple GET loading には `*fetch` も検討します。\n- file upload には `<input type=\"file\" *api=\"...\">` を使います。\n- response destination には `*into` を明示します。\n- `$pending` と `$error` を UI に出し、request state を見えるようにします。\n- server response shape と template path を一致させます。\n- 複数の network directives を同じ element に置かないでください。\n- 同じ element 上で `*api` と複雑な `@click` handler を混在させないでください。\n\n\n#### 例\n\n##### 本文を無視する GET\n\n```html\n<section\n  *api=\"/api/items\"\n  method=\"GET\"\n  body=\"someData\"\n  *into=\"items\">\n</section>\n```\n\n`method=\"GET\"` なので、body expression は送信されません。\n\n##### ボタンで実行する POST\n\n```html\n<serc-rod data='{\"form\": {\"name\": \"Alice\"}, \"result\": null}'>\n  <button\n    type=\"button\"\n    *api=\"/api/save\"\n    method=\"POST\"\n    body=\"form\"\n    *into=\"result\">\n    Save\n  </button>\n\n  <p *if=\"result\">%result.message%</p>\n</serc-rod>\n```\n\n##### プレビュー付きの単純なファイルアップロード\n\n```html\n<serc-rod data='{\"uploadResult\": null}'>\n  <input\n    type=\"file\"\n    name=\"file\"\n    *api=\"/api/upload\"\n    *into=\"uploadResult\">\n\n  <pre *if=\"uploadResult\" *print=\"JSON.stringify(uploadResult, null, 2)\"></pre>\n</serc-rod>\n```\n\n\n#### 注意点\n\n- `*api` と `n-api` は同じ挙動です。\n- `*api` は汎用 HTTP primitive です。\n- `*fetch` は simple GET JSON loading 向けです。\n- `*post` はより simple な POST helper です。\n- `*download` と `*upload` は、より specialized helper です。\n- `$pending`、`$error`、`$download`、`$upload` は host-level shared status fields です。\n- `*into` は response を名前付き data slot へ保存します。\n",
  "apply": "### *apply / n-apply\n\n#### 概要\n\n`*apply` は `*stage` に対する commit counterpart です。staged host 上で、現在の staged data を host data object へ戻し、redraw を trigger します。これにより、編集された値が新しい committed state になります。alias の `n-apply` も同じように動作します。\n\n\n#### 説明\n\nSercrod host が `*stage` を使う場合、runtime は stage と呼ばれる別の buffer object を rendering と user edits のために保持し、元の data object は committed source of truth として残します。update 中、host の visible scope は、stage buffer が存在する場合は stage buffer から取得され、存在しない場合は data object に fallback します。\n\n`*apply` は、staged edit session を finalise するための単純な event-style directive です。要素が click されると、stage buffer の内容が host data に merge され、host が update されます。apply 直後、Sercrod は committed data の deep snapshot を取り、後で `*restore` がその snapshot から stage を再構築できるようにします。\n\nempty `*apply` / `n-apply` は、template を描画している host の stage を commit します。値がある場合は `*update` と同じ target syntax として扱われ、`2`、`root`、`(.editor)` のように対象 host を指定できます。\n\n\n#### 基本例\n\nstaging を使う最小の save / cancel form です。\n\n```html\n<serc-rod data=\"{ profile: { name: 'Alice' } }\" *stage>\n  <label>\n    Name:\n    <input type=\"text\" *input=\"profile.name\">\n  </label>\n\n  <p>Preview (staged): %profile.name%</p>\n\n  <button type=\"button\" *apply>Save</button>\n  <button type=\"button\" *restore>Cancel</button>\n</serc-rod>\n```\n\nこの pattern では次のようになります。\n\n- host は `*stage` を持つため、user edits は staged buffer に入ります。\n- Save button を click すると、staged values が host data に commit されます。\n- Cancel button を click すると、staged edits が破棄され、最後の committed snapshot から stage が再構築されます。\n\n\n#### 挙動\n\n- Target selection\n  - empty `*apply` / `n-apply` は、template を描画した host の stage を commit します。\n  - non-empty value は `*update` と同じ target syntax です。`1` は nearest host、`2` は1つ外側の host、`root` は最外 host、selector は closest matching Sercrod host を選びます。\n\n- Host selection\n  - directive は常に、rendering されている template を所有する直近の Sercrod host と通信します。click handler は、その host を internal target として bind され、その host data と stage を使います。\n\n- Click handling\n  - click 時、host が non null の stage buffer を持つ場合、runtime は stage から host data へ merge します。object / array 同士は既存 container に merge され、primitive や互換しない container は代入されます。\n  - object / array values は、両側が互換する container の場合、既存 object / array target へ merge されます。primitive values や互換しない containers は代入されます。\n  - stage に存在しない data keys は自動的には削除されません。\n\n- Redraw and snapshot\n  - merge 後、host update method が呼ばれ、新しい committed data または staged view に基づいて re render します。\n  - その後、committed data は、`*restore` が使う private snapshot field へ deep clone されます。structured cloning が使える場合はそれを使い、fallback として JSON round trip を使います。\n\n- No stage, no effect\n  - host が stage buffer を持たない場合、`*apply` または `n-apply` element を click しても何も起きません。error は発生せず、update も trigger されません。\n\n- Children and other directives inside the element\n  - renderer は `*apply` を control directive として扱います。original element を clone し、clone に click handler を接続し、その clone を output に append し、通常の attribute and text processing pipeline には送らずに return します。\n  - child nodes は通常の child rendering pipeline で処理されます。\n  - same-element `@event` attributes も bind されます。apply handler が先に登録されるため、同じ event の `@click` handler より先に実行されます。\n  - 同じ element 上の別 action directives は合成されません。`*apply` がその element の action branch です。\n\n- Aliases\n  - `n-apply` は `*apply` の直接 alias です。どちらの名前も同じ runtime path を通り、挙動は同一です。\n\n\n#### 評価タイミング\n\n- Template render time\n  - `*apply` は、template rendering 中に検出されます。\n  - attribute value は data expression としては評価されません。値がある場合は target syntax として扱われます。\n  - Sercrod は、clone を作り、internal click handler を接続し、child nodes を render して、出力へ append します。\n\n- Click time\n  - commit は click event が発生したときだけ実行されます。\n  - `*apply` が render されただけでは data は変更されません。\n  - click 時に stage buffer が存在すれば、stage は host data に merge されます。\n  - その後 host update と snapshot refresh が行われます。\n\n- Relation to `*stage`\n  - `*stage` が host 上にない場合、通常 stage buffer は存在しません。\n  - その場合、`*apply` click は no-op です。\n  - `*apply` 自体は stage を作りません。\n\n\n#### 実行モデル\n\n概念的な実行 model は次の通りです。\n\n1. Sercrod は element に `*apply` または `n-apply` があることを検出します。\n2. original element を clone します。\n3. clone から control attribute を削除します。\n4. clone に click listener を attach します。\n5. clone を output parent に append します。\n6. original child nodes を clone 内へ render します。\n7. click 時:\n   - host に stage がなければ return します。\n   - stage があれば、stage buffer を host data へ merge します。\n   - host を update します。\n   - committed snapshot を refresh します。\n\nこの model により、`*apply` element は commit control として非常に明示的になりますが、同じ element 上の他の Sercrod behavior と合成する用途には向きません。\n\n\n#### 変数の作成\n\n`*apply` は変数を作りません。\n\n- new scope names を導入しません。\n- `$data`、`$root`、`$parent` を作りません。\n- stage から data へ values を copy しますが、expression scope 自体を拡張しません。\n\n新しい data keys が staged buffer に存在する場合、merge により committed data へコピーされます。これは variable creation というより commit operation です。\n\n\n#### スコープの重なり\n\nstaged host には概念的に2つの data layers があります。\n\n- Committed data\n  - original data object。\n  - `*apply` 後の source of truth。\n  - `*restore` snapshot の基準。\n\n- Stage buffer\n  - edit session 中に rendering と input のために使われる temporary object。\n  - `*input` などの user edits はここに入ります。\n  - `*apply` によって committed data へ merge されます。\n\n`*apply` は stage buffer を committed data object へ merge します。stage に存在しない data keys は自動的には削除されません。\n\n\n#### 親へのアクセス\n\n`*apply` は parent data を直接読んだり変更したりするための directive ではありません。\n\nnested Sercrod hosts がある場合、`*apply` は rendering されている template を所有する nearest host の stage を commit します。\n\n親 host の staged data を commit するには、親 host の template 内に `*apply` control を置きます。\n\n\n#### conditionals and loops との併用\n\n`*apply` は `*if` や `*for` によって条件付きで表示できます。\n\n```html\n<button type=\"button\" *if=\"dirty\" *apply>Save</button>\n```\n\nただし、`*apply` が同じ element 上で control directive として処理される場合、同じ element 上の他の Sercrod directives との合成には注意が必要です。\n\nより読みやすくするには wrapper を使います。\n\n```html\n<span *if=\"dirty\">\n  <button type=\"button\" *apply>Save</button>\n</span>\n```\n\nloop 内に multiple apply controls を置くこともできますが、各 control は同じ nearest host stage を commit します。特定の row だけを commit するわけではありません。\n\n\n#### 推奨される使い方\n\n- `*apply` は `*stage` が付いた host の中で使います。\n- `*apply` button label には通常の child rendering を使えます。ただし同じ element 上に別 action directive を重ねないでください。\n- 同じ element 上に `*apply` と他の action directives を重ねるのは避けます。\n- conditional display が必要な場合は wrapper を使います。\n- staged edits を破棄するために `*restore` と組み合わせます。\n- staged edit session の意味を UI 上で明確にします。\n- row-level commit が必要な場合は、host 構造や data model を分けることを検討します。\n\n\n#### 例\n\n##### stage 編集と確定を使うダイアログ風フォーム\n\n```html\n<serc-rod data=\"{ profile: { name: 'Alice', email: 'a@example.com' } }\" *stage>\n  <dialog open>\n    <label>\n      Name:\n      <input type=\"text\" *input=\"profile.name\">\n    </label>\n\n    <label>\n      Email:\n      <input type=\"email\" *input=\"profile.email\">\n    </label>\n\n    <p>Preview: %profile.name% / %profile.email%</p>\n\n    <button type=\"button\" *apply>Save changes</button>\n    <button type=\"button\" *restore>Cancel</button>\n  </dialog>\n</serc-rod>\n```\n\n##### 複数箇所にある apply ボタン\n\n```html\n<serc-rod data=\"{ settings: { theme: 'light' } }\" *stage>\n  <select *input=\"settings.theme\">\n    <option value=\"light\">Light</option>\n    <option value=\"dark\">Dark</option>\n  </select>\n\n  <footer>\n    <button type=\"button\" *apply>Apply settings</button>\n  </footer>\n</serc-rod>\n```\n\nbutton の位置がどこであっても、同じ host の stage を commit します。\n\n\n#### 注意点\n\n- `*apply` と `n-apply` は同一です。\n- 値が空の場合は現在の host を対象にし、値がある場合は `*update` と同じ target syntax で対象 host を選びます。\n- `*apply` は `*stage` を必要とします。stage がなければ no-op です。\n- commit は stage buffer から committed data への merge です。object / array は可能な範囲で既存 container に merge されます。\n- committed snapshot は apply 後に更新され、`*restore` がその後に使えるようになります。\n- `*apply` element の child nodes は通常の child pipeline で処理されます。同じ element 上の別 action directive は合成しないでください。\n\n\n#### data=\"item\" *stage での apply\n\n`*iterate` 内の `<serc-rod data=\"item\" *stage>` は通常の staged host です。child host の `_data` root は item object そのものなので、child 内では `*input=\"title\"` のように root-relative に書きます。\n\nempty `*apply` は、その child host の stage を `_data`、つまり共有されている item object へ merge します。親配列内の item data は変わりますが、parent host の rendering は自動では強制されません。必要な場合は `*update` や明示的な `update()` で知らせます。\n\ndata なしの `<serc-rod *stage>` が `*iterate` item を stage する場合は iterate-item stage mode であり、`*apply` は staged item を元の item object へ merge します。\n",
  "attribute-action": "### :action\n\n#### 概要\n\n`:action` は、form 要素の `action` 属性を制御する属性バインディングディレクティブです。\nSercrod の式を評価し、その結果を form の action 属性へ書き込みます。値は、必要に応じて設定可能な url フィルターを通ります。\nこのバインディングは一方向です。data の更新は DOM 属性を変更しますが、DOM 属性の変更は data を更新しません。\n\n`:action` は汎用的な colon attribute family の一部であり、`:href` や `:src` など、他の colon bindings と同じ評価規則を共有します。\n\n\n#### 基本例\n\n単純な動的 form endpoint です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"endpoint\": \"/api/contact\"\n}'>\n  <form method=\"post\" :action=\"endpoint\">\n    <label>\n      Name:\n      <input type=\"text\" name=\"name\">\n    </label>\n    <button type=\"submit\">Send</button>\n  </form>\n</serc-rod>\n```\n\n挙動:\n\n- Sercrod host は、`endpoint` が `\"/api/contact\"` に設定された data を受け取ります。\n- form が描画されると、Sercrod は現在の scope で `endpoint` 式を評価します。\n- 結果は文字列へ変換され、form の action 属性へ書き込まれます。\n- data が変わり form が再描画されると、action 属性は最新の値に合わせて更新されます。\n\n\n#### 挙動\n\n基本ルール:\n\n- Target attribute\n  `:action` は標準 HTML の `action` 属性を対象にします。実用上は form 要素向けですが、Sercrod は tag name を強制しません。form 以外の要素で使った場合、その要素に action 属性を書き込むだけです。\n\n- Expression evaluation\n  Sercrod は、たとえば `:action=\"endpoint\"` や `:action=\"isEdit ? editUrl : createUrl\"` のような属性値を読みます。\n  その式を、attribute binding mode `attr:action` で現在の scope 内で評価します。\n\n- Value interpretation\n  評価後は次のように扱います。\n\n  - 値が厳密に `false`、または `null` / `undefined` の場合、Sercrod は要素から action 属性を削除します。\n  - それ以外の場合、値は文字列へ変換され、url フィルターへ渡されます。\n  - url フィルターが truthy な値を返した場合、その値が action 属性として設定されます。\n  - url フィルターが falsy な値を返した場合、action 属性は削除されます。\n\n- Error handling\n  `:action` 式の評価で例外が発生した場合、Sercrod は安全側へ倒し、属性を設定しません。project 側の logging や debug hooks が有効であれば、そこで確認できます。\n\nこの directive は form submission を実行しません。form の送信先を表す属性を更新するだけです。\n\n\n#### 評価タイミング\n\n`:action` は、要素の描画中に評価されます。\n\nおおまかな順序は次の通りです。\n\n1. Sercrod は template element を clone します。\n2. 構造ディレクティブによって、その element が描画されるかどうかが決まります。\n3. element が描画対象になると、colon attribute bindings が処理されます。\n4. `:action` の式が現在の scope で評価されます。\n5. 評価結果は url フィルターを通り、action 属性に反映されます。\n6. その後、children が処理されます。\n\nこのため、ancestor の `*let`、loop 変数、host data など、現在の scope で見える値は `:action` 式からも参照できます。\n\n\n#### 実行モデル\n\n概念的には、`:action` は次の処理に近いです。\n\n```js\nconst raw = evaluate(\":action expression\", scope);\nconst value = normalize_attribute_value(raw);\n\nif(value === false || value == null){\n        element.removeAttribute(\"action\");\n} else {\n        const filtered = Sercrod._filters.url(String(value), {\n                attr: \"action\",\n                el: element,\n                scope\n        });\n\n        if(filtered){\n                element.setAttribute(\"action\", filtered);\n        } else {\n                element.removeAttribute(\"action\");\n        }\n}\n```\n\n実際の runtime は共通の colon attribute pipeline を使いますが、意味としては、式の結果を action 属性へ安全に写す処理です。\n\n\n#### structural directives and loops との併用\n\n`:action` は `*if`、`*for`、`*each`、`*switch` などの中でも使えます。\n\n```html\n<form\n  *for=\"item of forms\"\n  method=\"post\"\n  :action=\"'/api/forms/' + item.id\">\n  <button type=\"submit\">Send %item.name%</button>\n</form>\n```\n\n各反復では、`item` が現在の scope に入るため、`:action` はその item に応じた URL を作れます。\n\nただし、ユーザー入力や外部 data から URL を作る場合は、url フィルターとサーバー側検証の両方を考慮します。\n\n\n#### 推奨される使い方\n\n- form の送信先を data から切り替える必要がある場合に使います。\n- action 候補は、できるだけ data 内で明示的な名前を付けて管理します。\n- 外部入力から action URL を作る場合は、url フィルターだけに頼らず、サーバー側でも検証します。\n- native form submission、`@submit`、`*post`、`*api` のどれが送信を所有するのかを明確にします。\n- action を消したい場合は、空文字より `null` または `false` を返す方が意図が明確です。\n\n\n#### 追加例\n\nEdit / create の endpoint を切り替える例です。\n\n```html\n<form\n  method=\"post\"\n  :action=\"mode === 'edit' ? editUrl : createUrl\">\n  <input type=\"text\" name=\"title\">\n  <button type=\"submit\">Save</button>\n</form>\n```\n\ndata から base path と id を組み立てる例です。\n\n```html\n<form\n  method=\"post\"\n  :action=\"basePath + '/users/' + user.id\">\n  <button type=\"submit\">Update</button>\n</form>\n```\n\n\n#### 注意点\n\n- `:action` は data-to-DOM の一方向バインディングです。\n- URL 系属性として、評価結果は url フィルターを通ります。\n- form 以外の要素にも属性として書けますが、通常意味があるのは form 要素です。\n- 送信処理そのものを制御するのではなく、送信先属性を制御します。\n",
  "attribute-class": "### :class\n\n#### 概要\n\n`:class` は、Sercrod の式から class 属性を計算する属性バインディングディレクティブです。\n要素の `className` property へ直接書き込み、主に次の3種類の値の形に対応します。\n\n- string: class list としてそのまま使われます。\n- array: filter され、空白区切りの class tokens として結合されます。\n- object: 対応する値が truthy である key だけが含まれます。\n\nこのバインディングは一方向です。Sercrod は data から要素の classes を更新しますが、DOM 側で `className` が変更されても data へは書き戻されません。\n\n\n#### 基本例\n\n単純な条件付き class です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"isActive\": true,\n  \"isDisabled\": false\n}'>\n  <button :class=\"[\n    'btn',\n    isActive && 'btn-active',\n    isDisabled && 'btn-disabled'\n  ]\">\n    Click me\n  </button>\n</serc-rod>\n```\n\n挙動:\n\n- 式は現在の scope で評価されます。\n- array は truthy な entry だけに filter され、空白で結合されます。\n- `isActive` が true、`isDisabled` が false の場合、結果の `className` は `\"btn btn-active\"` です。\n- data が変わり host が再描画されると、`className` は再計算されます。\n\n\n#### 挙動\n\n`:class` の core rules です。\n\n- 式は mode `attr:class` で評価され、現在の scope と element に access できます。\n- 結果は型によって調べられます。\n\n  - string:\n    - 文字列がそのまま `el.className` へ代入されます。\n  - array:\n    - falsy な値は `filter(Boolean)` により取り除かれます。\n    - 残った items は単一の空白で結合されます。\n    - JavaScript の `toString` が coercion に使われるため、文字列でない item も文字列に変換されます。\n  - object:\n    - `Object.keys(val)` が取得されます。\n    - 値が truthy、つまり Boolean coercion で true になる key だけが残ります。\n    - 残った key は単一の空白で結合されます。\n  - anything else:\n    - `el.className` は空文字に設定されます。\n\n- Evaluation error:\n  - `:class` 式の評価が throw した場合、Sercrod は `el.className` を空文字にします。\n\n\n#### 値形式の詳細\n\n文字列形式:\n\n```html\n<div :class=\"isActive ? 'card active' : 'card'\"></div>\n```\n\n式が string を返す場合、その文字列全体が最終的な class list になります。\n\n配列形式:\n\n```html\n<div :class=\"[\n  'card',\n  active && 'active',\n  disabled && 'disabled',\n  theme\n]\"></div>\n```\n\narray form は、常に付ける class と条件付き class を同じ list に並べる場合に便利です。\n\nオブジェクト形式:\n\n```html\n<div :class=\"{\n  card: true,\n  active: active,\n  disabled: disabled\n}\"></div>\n```\n\nobject form は、「class 名」と「付ける条件」を対で読みたい場合に便利です。\n\n注意:\n\n- object の key は class token として使われます。\n- dash を含む class 名は quote します。\n\n```html\n<div :class=\"{ 'is-active': active }\"></div>\n```\n\n\n#### 評価タイミング\n\n`:class` は element の描画中に評価されます。\n\nおおまかな順序は次の通りです。\n\n1. 構造ディレクティブが element の有無を決めます。\n2. element が clone されます。\n3. `:class` を含む attribute bindings が評価されます。\n4. `className` が設定されます。\n5. children が描画されます。\n\nこのため、ancestor `*let` values、loop variables、host data、methods など、現在の scope から見える値を `:class` 式で使えます。\n\n\n#### 実行モデル\n\n概念的には、`:class` は次のような処理に近いです。\n\n```js\nconst val = evaluate(\":class expression\", scope);\n\nif(typeof val === \"string\"){\n        el.className = val;\n} else if(Array.isArray(val)){\n        el.className = val.filter(Boolean).join(\" \");\n} else if(val && typeof val === \"object\"){\n        el.className = Object.keys(val).filter((key)=>Boolean(val[key])).join(\" \");\n} else {\n        el.className = \"\";\n}\n```\n\n実際の runtime は internal helpers と error handling を使いますが、型ごとの mapping はこのように考えられます。\n\n\n#### スコープとデータアクセス\n\n`:class` は現在の Sercrod scope で評価されます。\n\n例:\n\n```html\n<li *for=\"item of items\" :class=\"{ selected: item.id === selectedId }\">\n  %item.name%\n</li>\n```\n\nこの場合、`item` は loop scope から来ており、`selectedId` は host data から来ています。\n\n\n#### 静的 class 属性や他のディレクティブとの併用\n\n同じ要素に静的 `class` と `:class` がある場合、最終的な class は `:class` の結果によって管理されます。\n\n```html\n<div class=\"card\" :class=\"{ active: active }\"></div>\n```\n\nこの pattern では、静的 `card` が常に残るとは考えないでください。必要なら `card` を `:class` の中に含めます。\n\n推奨:\n\n```html\n<div :class=\"{ card: true, active: active }\"></div>\n```\n\nまたは array form です。\n\n```html\n<div :class=\"['card', active && 'active']\"></div>\n```\n\n\n#### 推奨される使い方\n\n- base class も `:class` 式に含めます。\n- 条件が複数ある場合は array form または object form を使います。\n- 長い文字列連結は避けます。\n- 複雑な state-to-class mapping は method へ移すか、data 側で派生値を作ります。\n- `:class` と外部 JavaScript による `className` 直接変更を競合させないでください。\n\n\n#### 追加例\n\n現在の navigation item:\n\n```html\n<a\n  *for=\"item of nav\"\n  :href=\"item.url\"\n  :class=\"['nav-link', item.id === current ? 'active' : '']\">\n  %item.label%\n</a>\n```\n\nフォーム項目の状態:\n\n```html\n<input\n  *input=\"email\"\n  :class=\"{\n    field: true,\n    invalid: email && !email.includes('@'),\n    empty: !email\n  }\">\n```\n\n状態 badge:\n\n```html\n<span :class=\"'badge badge-' + status\">%status%</span>\n```\n\n\n#### 注意点\n\n- `:class` は data-to-DOM の一方向バインディングです。\n- string、array、object の3つの main value forms に対応します。\n- その他の値や評価 error では、class list は空になります。\n- 静的 class と混在させる場合は、どちらが最終 class list を所有するかを意識してください。\n",
  "attribute-formaction": "### :formaction\n\n#### 概要\n\n`:formaction` は、`button` や `input type=\"submit\"` のような form submit controls 上の `formaction` 属性を制御する属性バインディングディレクティブです。\nSercrod の式を評価し、その結果を formaction 属性へ書き込みます。値は、必要に応じて設定可能な url フィルターを通ります。\nこのバインディングは一方向です。data の更新は DOM 属性を変更しますが、DOM 属性の変更は data を更新しません。\n\n`:formaction` は汎用的な colon attribute family の一部であり、`:href`、`:src`、`:action` などの他の colon bindings と同じ評価規則を共有します。\n\n\n#### 基本例\n\nbutton ごとに endpoint を持つ form です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"saveEndpoint\": \"/api/save\",\n  \"deleteEndpoint\": \"/api/delete\"\n}'>\n  <form method=\"post\" action=\"/api/default\">\n    <button type=\"submit\" :formaction=\"saveEndpoint\">\n      Save\n    </button>\n    <button type=\"submit\" :formaction=\"deleteEndpoint\">\n      Delete\n    </button>\n  </form>\n</serc-rod>\n```\n\n挙動:\n\n- form は default action 属性 `\"/api/default\"` を持ちます。\n- 各 button は、それぞれ独自の `:formaction` binding を持ちます。\n- Sercrod は `saveEndpoint` と `deleteEndpoint` を評価し、その結果を各 button の formaction 属性へ書き込みます。\n- ユーザーが Save を click すると browser は `/api/save` へ submit し、Delete を click すると `/api/delete` へ submit します。これは HTML の標準 formaction semantics に従います。\n\n\n#### 挙動\n\n基本ルール:\n\n- Target attribute\n  `:formaction` は、submit controls 上の標準 HTML `formaction` 属性を対象にします。\n  通常の HTML では、formaction はその control によって trigger された submission について、親 form の action を override します。\n  Sercrod はこの override を自前で実装しません。属性を設定するだけで、実際の behavior は browser が提供します。\n\n- Expression evaluation\n  Sercrod は、たとえば `:formaction=\"endpoint\"` や `:formaction=\"mode === 'archive' ? archiveUrl : saveUrl\"` のような `:formaction` 属性値を読みます。\n  現在の scope で式を評価し、attribute binding mode `attr:formaction` を使います。\n\n- Value interpretation\n  評価後は次のように扱います。\n\n  - 値が厳密に `false`、または `null` / `undefined` の場合、Sercrod は要素から formaction 属性を削除します。\n  - それ以外の場合、値は文字列へ変換され、url フィルターへ渡されます。\n  - url フィルターが truthy な値を返した場合、その値が formaction 属性として設定されます。\n  - url フィルターが falsy な値を返した場合、formaction 属性は削除されます。\n\n- Error handling\n  `:formaction` 式の評価が throw した場合、Sercrod は安全側へ倒し、属性を設定しません。\n\n\n#### 評価タイミング\n\n`:formaction` は element の描画中に評価されます。\n\n1. 構造ディレクティブによって element が描画されるかどうかが決まります。\n2. element が clone されます。\n3. attribute bindings が評価されます。\n4. `:formaction` の結果が url フィルターを通って、formaction 属性へ反映されます。\n5. children が描画されます。\n\nloop 変数、ancestor `*let` values、methods、host data など、現在の scope で見える値を式に使えます。\n\n\n#### 実行モデル\n\n概念的には、`:formaction` は次に近い処理です。\n\n```js\nconst raw = evaluate(\":formaction expression\", scope);\n\nif(raw === false || raw == null){\n        element.removeAttribute(\"formaction\");\n} else {\n        const filtered = Sercrod._filters.url(String(raw), {\n                attr: \"formaction\",\n                el: element,\n                scope\n        });\n\n        if(filtered){\n                element.setAttribute(\"formaction\", filtered);\n        } else {\n                element.removeAttribute(\"formaction\");\n        }\n}\n```\n\n実際の runtime は共通の colon attribute pipeline を使います。\n\n\n#### フォームや action との併用\n\n`:action` は form 全体の default endpoint を設定します。\n\n`:formaction` は、特定の submit control の endpoint を override します。\n\n```html\n<form method=\"post\" :action=\"defaultEndpoint\">\n  <button type=\"submit\">Save</button>\n  <button type=\"submit\" :formaction=\"previewEndpoint\">Preview</button>\n</form>\n```\n\nこの場合:\n\n- Save は `defaultEndpoint` を使います。\n- Preview は `previewEndpoint` を使います。\n\nSercrod は browser の form submission algorithm を置き換えません。属性を設定することで、標準 HTML behavior に任せます。\n\n\n#### structural directives and loops との併用\n\n`:formaction` は繰り返しの中でも使えます。\n\n```html\n<button\n  *for=\"item of items\"\n  type=\"submit\"\n  :formaction=\"'/api/items/' + item.id + '/delete'\">\n  Delete %item.name%\n</button>\n```\n\n各 button は現在の `item` に応じた endpoint を持ちます。\n\n\n#### 推奨される使い方\n\n- 同じ form で submit control ごとに異なる endpoint が必要な場合に使います。\n- default endpoint には `:action` を使い、button-specific endpoint には `:formaction` を使います。\n- server 側では、dangerous actions、たとえば delete に対して権限や CSRF protection を必ず検証します。\n- URL を外部入力から作る場合は、url フィルターと server validation を併用します。\n- JavaScript action と form submission のどちらを使うのかを明確にします。\n\n\n#### 追加例\n\nSave と publish を分ける例です。\n\n```html\n<form method=\"post\" :action=\"saveUrl\">\n  <button type=\"submit\">Save draft</button>\n  <button type=\"submit\" :formaction=\"publishUrl\">Publish</button>\n</form>\n```\n\nrow ごとの delete endpoint の例です。\n\n```html\n<form method=\"post\">\n  <button\n    *for=\"row of rows\"\n    type=\"submit\"\n    :formaction=\"'/admin/rows/' + row.id + '/delete'\">\n    Delete %row.title%\n  </button>\n</form>\n```\n\n\n#### 注意点\n\n- `:formaction` は data-to-DOM の一方向バインディングです。\n- URL 系属性として、評価結果は url フィルターを通ります。\n- 実際の submit behavior は browser の標準 HTML form semantics に従います。\n- Sercrod は属性を設定するだけで、submission algorithm を再実装しません。\n",
  "attribute-href": "### :href\n\n#### 概要\n\n`:href` は、link または resource element の `href` 属性を制御する属性バインディングディレクティブです。\nSercrod の式を評価し、その結果を href 属性へ書き込みます。値は、必要に応じて設定可能な url フィルターを通ります。\nこのバインディングは一方向です。data の更新は DOM 属性を変更しますが、DOM 属性の変更は data を更新しません。\n\n`:href` は汎用的な colon attribute family の一部であり、`:src` や `:action` などの colon bindings と同じ評価規則を共有します。\n\n\n#### 基本例\n\n単純な data driven link です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"url\": \"https://example.com/docs\"\n}'>\n  <a :href=\"url\">Open documentation</a>\n</serc-rod>\n```\n\n挙動:\n\n- Sercrod host は、`url` が `\"https://example.com/docs\"` に設定された data を受け取ります。\n- link が描画されると、Sercrod は現在の scope で `url` 式を評価します。\n- 結果は文字列へ変換され、url フィルターを通り、`a` 要素の href 属性へ書き込まれます。\n- `data.url` が変わり host が更新されると、href 属性は最新の値に合わせて更新されます。\n\n\n#### 挙動\n\n基本ルール:\n\n- Target attribute\n  `:href` は標準 HTML の `href` 属性を対象にします。通常は `a` 要素で使いますが、`area` や `link` のような href capable elements でも使えます。Sercrod は tag name に制限を強制しません。\n\n- Expression evaluation\n  Sercrod は、たとえば `:href=\"url\"` や `:href=\"base + '/users/' + userId\"` のような属性値を読みます。\n  その式を、attribute binding mode `attr:href` で現在の scope 内で評価します。\n\n- Value interpretation\n  評価後は次のように扱います。\n\n  - 値が厳密に `false`、または `null` / `undefined` の場合、Sercrod は要素から href 属性を削除します。\n  - それ以外の場合、値は文字列へ変換され、url フィルターへ渡されます。\n  - url フィルターが truthy な値を返した場合、Sercrod は href をその filtered value に設定します。\n  - url フィルターが falsy な値を返した場合、href 属性は削除されます。\n\n- Error handling\n  `:href` 式の評価が throw した場合、Sercrod は属性を設定しません。\n\n\n#### 評価タイミング\n\n`:href` は element の描画中に評価されます。\n\n1. element が構造ディレクティブを通過します。\n2. clone が作られます。\n3. `:href` 式が現在の scope で評価されます。\n4. 結果が url フィルターを通ります。\n5. href 属性が設定または削除されます。\n6. children が描画されます。\n\nしたがって、loop variables、ancestor `*let` values、host data、methods などを `:href` 式で使えます。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst raw = evaluate(\":href expression\", scope);\n\nif(raw === false || raw == null){\n        element.removeAttribute(\"href\");\n} else {\n        const filtered = Sercrod._filters.url(String(raw), {\n                attr: \"href\",\n                el: element,\n                scope\n        });\n\n        if(filtered){\n                element.setAttribute(\"href\", filtered);\n        } else {\n                element.removeAttribute(\"href\");\n        }\n}\n```\n\n実際には共通の colon attribute pipeline を通ります。\n\n\n#### structural directives and loops との併用\n\n`:href` は list rendering とよく組み合わせます。\n\n```html\n<a\n  *for=\"post of posts\"\n  :href=\"'/posts/' + post.slug\">\n  %post.title%\n</a>\n```\n\n各 link は、現在の `post` に基づいて href を計算します。\n\n`*if` の中でも同じように使えます。\n\n```html\n<a *if=\"user\" :href=\"'/users/' + user.id\">Profile</a>\n```\n\n\n#### 推奨される使い方\n\n- navigation には `a :href` を使います。\n- action-only behavior には `button` と `@click` を使います。\n- `href=\"#\"` を action placeholder として使わないでください。必要であれば `.prevent` を明示します。\n- URL を外部入力から作る場合は、url フィルターと server-side validation を考慮します。\n- href がない状態を表したい場合は、`null` または `false` を返します。\n\n\n#### 追加例\n\n内部 route:\n\n```html\n<a :href=\"'/users/' + user.id\">%user.name%</a>\n```\n\n外部 link:\n\n```html\n<a :href=\"websiteUrl\" target=\"_blank\" rel=\"noopener noreferrer\">\n  Website\n</a>\n```\n\n条件付き link:\n\n```html\n<a :href=\"enabled ? url : null\">Open</a>\n```\n\n\n#### 注意点\n\n- `:href` は data-to-DOM の一方向バインディングです。\n- URL 系属性として、評価結果は url フィルターを通ります。\n- link behavior は browser の標準 behavior に従います。\n- action-only behavior には `button` を優先します。\n",
  "attribute-src": "### :src\n\n#### 概要\n\n`:src` は、image、script、media element の `src` 属性を制御する属性バインディングディレクティブです。\nSercrod の式を評価し、その結果を src 属性へ書き込みます。値は、設定可能な url フィルターを通ります。\nこのバインディングは一方向です。data の変更は DOM 属性を更新しますが、DOM 属性の変更は data を更新しません。\n\n`:src` は、`:href`、`:action`、`:formaction`、`xlink:href` と同じ URL binding family に属します。\n\n\n#### 基本例\n\n単純な image binding です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"imageUrl\": \"/assets/logo.png\"\n}'>\n  <img :src=\"imageUrl\" alt=\"Logo\">\n</serc-rod>\n```\n\n挙動:\n\n- Sercrod は現在の scope で `imageUrl` 式を評価します。\n- 結果 `\"/assets/logo.png\"` は文字列化され、`\"src\"` 属性用の url フィルターを通ります。\n- filtered value が img 要素の src 属性に代入されます。\n- data 内の `imageUrl` が変わり host が再描画されると、Sercrod は式を再評価し、src を更新します。\n\n\n#### 挙動\n\n基本ルール:\n\n- Target attribute\n  `:src` は標準 HTML の `src` 属性を対象にします。Sercrod は tag name を強制しません。`img`、`script`、`iframe`、`video`、`audio`、`source` などの要素向けに設計されていますが、技術的には任意の要素が src 属性を受け取れます。\n\n- Expression evaluation\n  Sercrod は、たとえば `:src=\"imageUrl\"` や `:src=\"cdnBase + path\"` のような属性値を読みます。\n  その文字列を、evaluation mode `attr:src` で現在の scope 内の Sercrod 式として評価します。\n\n- Value interpretation\n  評価後は次のように扱います。\n\n  - 値が厳密に `false`、または `null` / `undefined` の場合、Sercrod は要素から src 属性を削除します。\n  - それ以外の場合、値は文字列へ変換され、url フィルターへ渡されます。\n  - url フィルターが truthy な文字列を返した場合、Sercrod は src をその文字列に設定します。\n\n- Error handling\n  `:src` 式の評価が throw した場合、Sercrod は src 属性を削除します。\n\n\n#### 評価タイミング\n\n`:src` は element の描画中に評価されます。\n\n1. element が構造ディレクティブを通過します。\n2. clone が作られます。\n3. `:src` 式が現在の scope で評価されます。\n4. 結果が url フィルターを通ります。\n5. src 属性が設定または削除されます。\n6. browser は通常の resource loading rules に従って resource を読み込みます。\n\nresource loading は Sercrod が独自に管理するものではありません。Sercrod は属性を設定し、browser が src に基づいて読み込みます。\n\n\n#### 実行モデル\n\n概念的には、`:src` は次の処理に近いです。\n\n```js\nconst raw = evaluate(\":src expression\", scope);\n\nif(raw === false || raw == null){\n        element.removeAttribute(\"src\");\n} else {\n        const filtered = Sercrod._filters.url(String(raw), {\n                attr: \"src\",\n                el: element,\n                scope\n        });\n\n        if(filtered){\n                element.setAttribute(\"src\", filtered);\n        } else {\n                element.removeAttribute(\"src\");\n        }\n}\n```\n\n実際の runtime は共通の attribute binding pipeline を使います。\n\n\n#### structural directives and loops との併用\n\n`:src` は list rendering の中でよく使われます。\n\n```html\n<img\n  *for=\"photo of photos\"\n  :src=\"photo.url\"\n  :alt=\"photo.alt\">\n```\n\n各 image は現在の `photo` の URL に基づきます。\n\nconditional rendering と組み合わせる場合:\n\n```html\n<img *if=\"user.avatar\" :src=\"user.avatar\" alt=\"Avatar\">\n```\n\n\n#### 推奨される使い方\n\n- 表示する resource がない場合は、空文字より `null` または `false` を返します。\n- 外部入力から URL を作る場合は、url フィルターと server-side validation を使います。\n- images では `alt` を明示します。\n- `script` や `iframe` の src は特に慎重に扱います。\n- layout shift を避けるため、images には可能なら width / height または CSS layout を用意します。\n\n\n#### 追加例\n\navatar 画像:\n\n```html\n<img :src=\"user.avatarUrl\" :alt=\"user.name\">\n```\n\n条件付き fallback:\n\n```html\n<img :src=\"photo ? photo.url : '/assets/placeholder.png'\" alt=\"\">\n```\n\nvideo source の例:\n\n```html\n<video controls :src=\"videoUrl\"></video>\n```\n\n\n#### 注意点\n\n- `:src` は data-to-DOM の一方向バインディングです。\n- URL 系属性として、評価結果は url フィルターを通ります。\n- Sercrod は属性を設定します。実際の resource loading は browser が行います。\n- `script`、`iframe`、media の src は security と privacy の観点で注意して扱います。\n",
  "attribute-style": "### :style\n\n#### 概要\n\n`:style` は、Sercrod の式を通じて要素の inline style を制御する属性バインディングディレクティブです。\n式を評価し、その結果を `element.style.cssText` へ直接代入します。\nこのバインディングは一方向です。data の変更は inline styles を更新しますが、DOM 側で style を変更しても data は変更されません。\n\n`*style` や `n-style` とは異なり、`:style` は style フィルターを使いません。\nこれは、式と要素の inline CSS string を直接つなぐ薄い橋渡しです。\n\n\n#### 基本例\n\n単純な inline style binding です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"highlight\": true\n}'>\n  <p :style=\"highlight ? 'color: red; font-weight: bold;' : ''\">\n    This paragraph is red when highlight is true.\n  </p>\n</serc-rod>\n```\n\n挙動:\n\n- `highlight` が true のとき、`:style` は inline styles を `color: red; font-weight: bold;` に設定します。\n- `highlight` が false になり host が再描画されると、`:style` は `style.cssText` を空文字に設定し、inline styles を削除します。\n- 要素の他の attributes や children は `:style` によって影響を受けません。\n\n\n#### 挙動\n\n`:style` は、`:style` 専用の処理を持ちながら、一般的な colon attribute-binding pipeline に従います。\n\n- Attribute detection\n  element が name exactly `:style` の属性を持つ場合に `:style` として認識されます。\n\n- Expression evaluation\n  Sercrod は、たとえば `:style=\"expr\"` のような属性値を読み、現在の scope 内で `expr` を評価します。mode は `attr:style` で、`el` は現在の要素に設定されます。\n\n- Value handling\n  評価に成功した場合:\n\n  - Sercrod は raw expression result を `val` として受け取ります。\n  - `element.style.cssText = val || \"\"` を代入します。\n  - `val` が空でない文字列の場合、inline style は書かれた通りに適用されます。\n  - `val` が falsy、たとえば `\"\"`、`0`、`null`、`undefined`、`false` の場合、inline style string は `\"\"` になり、inline styles は実質的に clear されます。\n\n- Error handling\n  式が評価中に throw した場合:\n\n  - Sercrod は `element.style.cssText` を `\"\"` に強制します。\n\n\n#### 評価タイミング\n\n`:style` は element の描画中に評価されます。\n\n1. element が描画対象として選ばれます。\n2. clone が作られます。\n3. `:style` の式が現在の scope で評価されます。\n4. `style.cssText` が評価結果または空文字へ設定されます。\n5. children が描画されます。\n\nancestor `*let` values、loop variables、host data、methods は、現在の scope にあれば使えます。\n\n\n#### 実行モデル\n\n概念的には、`:style` は次の処理に近いです。\n\n```js\ntry {\n        const val = evaluate(\":style expression\", scope);\n        element.style.cssText = val || \"\";\n} catch(error) {\n        element.style.cssText = \"\";\n}\n```\n\n`val` は object-to-style mapping には変換されません。\nobject を返した場合、JavaScript の通常の coercion によって useful CSS にはならないことが多いです。通常は string を返してください。\n\n\n#### *style / n-style との関係\n\n`:style` と `*style` / `n-style` は同じものではありません。\n\n- `:style`\n  - expression result を `style.cssText` へ直接書きます。\n  - style フィルターを使いません。\n  - 文字列ベースの inline CSS に適しています。\n\n- `*style` / `n-style`\n  - 別の style directive として扱われます。\n  - project または runtime の style processing rules や filters に関係する場合があります。\n\n同じ要素で複数の style-writing mechanisms を混在させると、最後に実行された処理が inline styles を上書きする可能性があります。1つの style ownership model を選ぶ方が分かりやすくなります。\n\n\n#### conditionals and loops との併用\n\n`:style` は loop 内で dynamic position や size を作る場合に使えます。\n\n```html\n<div\n  *for=\"item of items\"\n  :style=\"`left:${item.x}px; top:${item.y}px;`\">\n</div>\n```\n\nconditionals と組み合わせる場合:\n\n```html\n<p :style=\"error ? 'color:red;' : ''\">\n  %message%\n</p>\n```\n\n\n#### 推奨される使い方\n\n- `:style` には CSS string を返します。\n- 大きな状態変化には `:class` を優先します。\n- dynamic numeric values、position、size、transform などに使います。\n- 外部入力から CSS string を直接作らないでください。\n- 複雑な style logic は method へ移します。\n- `:style` と他の style-writing directives を同じ要素で競合させないでください。\n\n\n#### 追加例\n\n動的な位置:\n\n```html\n<div :style=\"`position:absolute; left:${x}px; top:${y}px;`\"></div>\n```\n\nprogress bar の例:\n\n```html\n<div class=\"bar\" :style=\"`width:${progress}%;`\"></div>\n```\n\n条件付き inline style:\n\n```html\n<p :style=\"disabled ? 'opacity:0.5; pointer-events:none;' : ''\">\n  Item\n</p>\n```\n\n\n#### 注意点\n\n- `:style` は `style.cssText` へ直接書き込みます。\n- style フィルターは使いません。\n- falsy な値は inline styles を clear します。\n- text や class で表現できる場合は、`*print` や `:class` の方が適していることがあります。\n",
  "attribute-value": "### :value\n\n#### 概要\n\n`:value` は、form control の value property と value attribute を制御する属性バインディングディレクティブです。\nSercrod の式を評価し、form elements では DOM property `el.value` と `value` 属性の両方へ結果を書き込みます。これにより、control の visible value を data と同期させます。\n\nform ではない要素では、`:value` は通常の colon attribute binding のように動き、value 属性だけを更新します。\n\n\n#### 基本例\n\ndata から text input を prefill する例です。\n\n```html\n<serc-rod id=\"app\" data='{\n  \"form\": { \"name\": \"Alice\" }\n}'>\n  <form method=\"post\" action=\"/submit\">\n    <label>\n      Name:\n      <input type=\"text\" name=\"name\" :value=\"form.name\">\n    </label>\n    <button type=\"submit\">Send</button>\n  </form>\n</serc-rod>\n```\n\n挙動:\n\n- Sercrod host は `form.name = \"Alice\"` を提供します。\n- template が描画されると、Sercrod は `form.name` 式を評価します。\n- input element は form control なので、Sercrod はその値を次の両方へ代入します。\n  - `el.value`、つまり DOM property。\n  - input の `value` 属性。\n- data が変わり host が再描画されると、input の value もそれに合わせて更新されます。\n\n`:value` は一方向です。DOM property と属性は data によって駆動されますが、input を編集しても、`*input` や `n-input` のような他の directives が使われていない限り、data は自動的に更新されません。\n\n\n#### 挙動\n\n基本ルール:\n\n- Target attribute and property\n  `:value` は value 属性を対象にします。form controls では、value property も更新します。\n\n  - element が `INPUT`、`SELECT`、`TEXTAREA`、`OPTION` の場合、Sercrod は次を行います。\n    - `el.value = String(result)` を設定します。\n    - その後、generic attribute pipeline を実行して value 属性を更新します。\n  - その他の tags では、value 属性だけが更新されます。\n\n- Expression evaluation\n  Sercrod は、たとえば `form.name`、`user.email`、`condition ? a : b` のような `:value` から式を読みます。\n  この式を現在の scope で評価し、mode `attr:value` を使います。\n\n- Value interpretation\n  form control の場合:\n\n  - 結果は `String(result)` で property へ書き込まれます。\n  - `null` や `undefined` を返す式では、`String(null)` や `String(undefined)` にならないよう、実用上は空文字などへ正規化する方が安全です。\n\n  属性出力の場合:\n\n  - generic attribute rules が適用されます。\n  - `false`、`null`、`undefined` は通常、属性削除として扱われます。\n\n- Error handling\n  evaluation error が起きた場合、runtime は安全側へ倒します。実際の visible value は、対象 control と既存 DOM state に依存します。\n\n\n#### 評価タイミング\n\n`:value` は element の描画中に評価されます。\n\n1. element が描画対象になります。\n2. clone が作られます。\n3. `:value` 式が現在の scope で評価されます。\n4. form control の場合、`el.value` が更新されます。\n5. value 属性も attribute pipeline によって更新されます。\n6. children が描画されます。\n\nこの処理は data-to-DOM です。user input を data へ戻すものではありません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst result = evaluate(\":value expression\", scope);\n\nif(element.tagName === \"INPUT\" ||\n   element.tagName === \"SELECT\" ||\n   element.tagName === \"TEXTAREA\" ||\n   element.tagName === \"OPTION\"){\n        element.value = String(result);\n}\n\napply_generic_attribute_binding(element, \"value\", result);\n```\n\n実際の runtime では、error handling や common attribute mapping が含まれます。\n\n\n#### structural directives and loops との併用\n\n`:value` は loop 内の form controls でも使えます。\n\n```html\n<input\n  *for=\"user of users\"\n  type=\"text\"\n  :value=\"user.name\">\n```\n\nこれは各 `user.name` を入力欄へ表示します。\n\n値を編集して `user.name` に戻したい場合は、`*input` も必要です。\n\n```html\n<input\n  *for=\"user of users\"\n  type=\"text\"\n  :value=\"user.name\"\n  *input=\"user.name\">\n```\n\n\n#### 推奨される使い方\n\n- `:value` は data-to-DOM として使います。\n- user edit を data へ反映するには `*input` を使います。\n- `:value` と `*input` を組み合わせる場合は、同じ path を使うのが最も分かりやすいです。\n- `null` や `undefined` が visible string にならないよう、式で空文字へ fallback させることを検討します。\n- checkbox、radio、select のような controls では、value と checked/selected state の意味を混同しないでください。\n\n\n#### 追加例\n\n空文字 fallback:\n\n```html\n<input type=\"text\" :value=\"user.name || ''\">\n```\n\ncontrolled input pattern の例:\n\n```html\n<input type=\"text\" :value=\"form.title\" *input=\"form.title\">\n```\n\noption value の例:\n\n```html\n<option *for=\"item of items\" :value=\"item.id\">%item.label%</option>\n```\n\n\n#### 注意点\n\n- `:value` は data-to-DOM の一方向バインディングです。\n- form controls では `el.value` と value 属性の両方を更新します。\n- non-form elements では value 属性だけを更新します。\n- user input を data に戻すには `*input` または `n-input` が必要です。\n",
  "attribute-xlink-href": "### :xlink:href\n\n#### 概要\n\n`:xlink:href` は、SVG 要素の `xlink:href` 属性を制御する属性バインディングディレクティブです。\nSercrod の式を評価し、その結果を `xlink:href` へ書き込みます。値は、設定可能な url フィルターを通ります。\nこのバインディングは一方向です。data の更新は DOM 属性を変更しますが、DOM 属性の変更は data を更新しません。\n\n`:xlink:href` は汎用的な colon attribute family の一部であり、`:href`、`:src`、`:action`、`:formaction` と同じ評価規則を共有します。\n\n\n#### 基本例\n\nid で SVG symbol を参照する例です。\n\n```html\n<serc-rod id=\"icons\" data='{\n  \"iconRef\": \"#icon-check\"\n}'>\n  <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n    <defs>\n      <symbol id=\"icon-check\" viewBox=\"0 0 24 24\">\n        <path d=\"M3 12l6 6L21 4\"></path>\n      </symbol>\n    </defs>\n\n    <use :xlink:href=\"iconRef\"></use>\n  </svg>\n</serc-rod>\n```\n\n挙動:\n\n- Sercrod は現在の scope で `iconRef` 式を評価します。\n- 文字列 `\"#icon-check\"` が `use` 要素の `xlink:href` 属性へ書き込まれます。\n- `iconRef` が変わり host が再描画されると、`xlink:href` はそれに合わせて更新されます。\n\n\n#### 挙動\n\n基本ルール:\n\n- Target attribute\n  `:xlink:href` は、SVG 1.1 で他の SVG content を参照するためによく使われる `xlink:href` 属性を対象にします。\n  Sercrod は要素が SVG であることを強制しませんが、想定用途は `use`、`image`、その他の SVG linking elements です。\n\n- Expression evaluation\n  Sercrod は、たとえば `:xlink:href=\"iconRef\"` や `:xlink:href=\"base + '#' + name\"` のような属性値を読みます。\n  その式を、attribute binding mode `attr:xlink:href` で現在の scope 内で評価します。\n\n- Value interpretation\n  評価後は次のように扱います。\n\n  - 値が厳密に `false`、または `null` / `undefined` の場合、Sercrod は要素から xlink:href 属性を削除します。\n  - それ以外の場合、値は文字列へ変換され、url フィルターへ渡されます。\n  - url フィルターが truthy な値を返した場合、その値が xlink:href として設定されます。\n  - url フィルターが falsy な値を返した場合、xlink:href 属性は削除されます。\n\n- Error handling\n  `:xlink:href` 式が throw した場合、Sercrod は属性を設定しません。\n\n\n#### 評価タイミング\n\n`:xlink:href` は element の描画中に評価されます。\n\n1. element が描画対象になります。\n2. clone が作られます。\n3. `:xlink:href` 式が現在の scope で評価されます。\n4. 結果が url フィルターを通ります。\n5. xlink:href 属性が設定または削除されます。\n6. browser と SVG engine が標準 SVG semantics に従って参照を解決します。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst raw = evaluate(\":xlink:href expression\", scope);\n\nif(raw === false || raw == null){\n        element.removeAttribute(\"xlink:href\");\n} else {\n        const filtered = Sercrod._filters.url(String(raw), {\n                attr: \"xlink:href\",\n                el: element,\n                scope\n        });\n\n        if(filtered){\n                element.setAttribute(\"xlink:href\", filtered);\n        } else {\n                element.removeAttribute(\"xlink:href\");\n        }\n}\n```\n\n実際の runtime は共通の colon attribute pipeline を使います。\n\n\n#### structural directives and loops との併用\n\n`:xlink:href` は icon lists で使えます。\n\n```html\n<svg *for=\"icon of icons\" viewBox=\"0 0 24 24\">\n  <use :xlink:href=\"'#icon-' + icon.name\"></use>\n</svg>\n```\n\n各 iteration では、現在の `icon` に基づいて参照先が決まります。\n\n\n#### 推奨される使い方\n\n- SVG symbol reference のように `xlink:href` が必要な場合に使います。\n- 通常の HTML link には `:href` を使います。\n- SVG 内参照、たとえば `#icon-check` を許可するよう url フィルターが設定されていることを確認します。\n- 外部入力から SVG reference を作る場合は、許可済み ID や URL だけを使います。\n- 新しい SVG で `href` が適している場合は、対象 browser と SVG markup に合わせて `:href` と使い分けます。\n\n\n#### 追加例\n\nsymbol sprite の例:\n\n```html\n<use :xlink:href=\"'#icon-' + name\"></use>\n```\n\n条件付き icon:\n\n```html\n<use :xlink:href=\"enabled ? '#icon-on' : '#icon-off'\"></use>\n```\n\nloop 内の icon:\n\n```html\n<svg *for=\"item of items\" viewBox=\"0 0 24 24\">\n  <use :xlink:href=\"item.iconRef\"></use>\n</svg>\n```\n\n\n#### 注意点\n\n- `:xlink:href` は data-to-DOM の一方向バインディングです。\n- URL 系属性として、評価結果は url フィルターを通ります。\n- SVG 用途を想定していますが、Sercrod は tag name を強制しません。\n- SVG の `href` と `xlink:href` のどちらを使うかは、target environment に合わせて決めます。\n",
  "attributes": "### Attribute bindings (fallback for :name)\n\n#### 概要\n\nこのページでは、専用の manual を持たない Sercrod の属性バインディングの一般的な挙動を説明します。\n\nname が `:` で始まる属性、たとえば `:title`、`:aria-label`、`:data-id` は、この仕組みに参加します。\n`=` の右側にある式が評価され、その結果が、描画後の要素上の plain HTML attribute へ対応付けられます。\n\nこの fallback を使う典型例です。\n\n- `:title`\n- `:aria-label`、`:aria-current`、`:aria-describedby`、`:aria-*`\n- `:data-id`、`:data-status`、`:data-role`、`:data-*`\n- `:role`\n- `:tabindex`\n- その他の custom attributes、つまり `:data-*`、`:foo-bar` など\n\n次のような属性は、\n\n- `:class`\n- `:style`\n- `:value`\n- `:href`\n- `:src`\n- `:action`\n- `:formaction`\n- `:xlink:href`\n- `:disabled`\n- `:readonly`\n- `:checked`\n\nadditional details を説明する専用 manual を持つ、または持つ可能性があります。\nただし、それらもここで説明する generic evaluation pipeline を共有します。\n\n予約済み key:\n\n- `:text` と `:html` は text/HTML bindings 用に予約されており、この fallback では明示的に skip されます。\n  ここでは処理されず、別に扱われます。この version では未実装の場合もあります。\n\n\n#### 基本例\n\nfallback attribute bindings の典型的な利用例です。\n\n```html\n<serc-rod id=\"user-card\" data='{\n  \"user\": {\n    \"id\": \"u-123\",\n    \"name\": \"Alice\",\n    \"role\": \"admin\",\n    \"active\": true\n  }\n}'>\n  <div\n    :data-id=\"user.id\"\n    :aria-label=\"user.name\"\n    :role=\"user.role\"\n    :tabindex=\"user.active ? 0 : -1\"\n  >\n    <span *print=\"user.name\"></span>\n  </div>\n</serc-rod>\n```\n\n挙動:\n\n- `:` で始まるすべての属性は、現在の scope に対して評価されます。\n- 式が値を生成すると、underlying attribute name は colon の後ろの部分になります。たとえば `data-id`、`aria-label` です。\n- falsy や boolean の結果は attribute presence または removal に対応付けられます。\n- data が変わり host が再描画されると、属性は再評価されます。\n\n\n#### 挙動\n\n一般的な fallback rule:\n\n- Attribute detection\n  Sercrod は、name が `:` で始まる属性を探します。\n  `:text` と `:html` はこの fallback から除外されます。\n  専用 handling がある attributes は、その専用 logic が優先される場合があります。\n\n- Attribute name mapping\n  leading colon は取り除かれます。\n\n  - `:title` は `title` になります。\n  - `:aria-label` は `aria-label` になります。\n  - `:data-id` は `data-id` になります。\n\n- Expression evaluation\n  属性値は現在の scope 内の Sercrod 式として評価されます。\n\n  例:\n\n  ```html\n  <div :title=\"user.name\"></div>\n  ```\n\n  ここで `user.name` が評価され、その結果が `title` 属性へ対応付けられます。\n\n- Value mapping\n  評価結果は attribute value または attribute removal に mapping されます。詳細は次の section で説明します。\n\n\n#### 値の割り当て\n\nGeneric attribute mapping は、値の種類に基づいて attribute を設定または削除します。\n\n- `false`\n  - attribute は削除されます。\n\n- `null` または `undefined`\n  - attribute は削除されます。\n\n- `true`\n  - boolean-like attribute として扱われます。\n  - 通常は attribute name が値として使われる、または attribute presence が表現されます。\n\n- その他の値\n  - 値は文字列へ変換されます。\n  - その文字列が attribute value として設定されます。\n\n例:\n\n```html\n<button :disabled=\"isSaving\">Save</button>\n```\n\n`isSaving` が true のとき、`disabled` は存在します。\n`isSaving` が false のとき、`disabled` は削除されます。\n\n```html\n<div :data-count=\"items.length\"></div>\n```\n\n`items.length` は文字列化され、`data-count` 属性に設定されます。\n\n注意:\n\n- 文字列 `\"false\"` は boolean false ではありません。これは truthy string であり、attribute value として設定されます。\n- boolean attributes には、文字列 `\"false\"` ではなく実際の boolean `false` を返してください。\n\n\n#### フィルターとカスタマイズ\n\n一部の属性は filters を通る場合があります。\n\n- URL 系属性、たとえば `href`、`src`、`action`、`formaction` は url フィルターを使う場合があります。\n- style や HTML 関連の出力は、それぞれ専用 directive または filter を持つ場合があります。\n\nこの fallback page は generic behavior を説明します。\n専用 manual が存在する属性については、その manual の規則を優先してください。\n\n\n#### エラー処理\n\n式の評価で error が起きた場合、Sercrod は属性を書かない、または削除する方向に倒します。\n\n実装や attribute type によって、詳細な error handling は異なる場合があります。\n\nAI が Sercrod template を生成するときは、存在しない path や未定義値で頻繁に throw する式を避けてください。\n\n推奨:\n\n```html\n<div :title=\"user ? user.name : ''\"></div>\n```\n\nまたは、data shape を安定させます。\n\n\n#### 評価タイミング\n\n属性バインディングは、element が描画されるときに評価されます。\n\n一般的な順序:\n\n1. 構造ディレクティブ、たとえば `*if`、`*for`、`*each` が element の描画有無や repetition を決めます。\n2. element が clone されます。\n3. colon attribute bindings が評価されます。\n4. 結果の attributes が clone へ書き込まれます。\n5. children が描画されます。\n\nそのため、次の値が現在の scope にあれば属性式から使えます。\n\n- host data fields\n- loop variables\n- `*let` values from ancestors\n- methods\n- special values such as `$data`, `$root`, `$parent` when available\n\n\n#### 実行モデル\n\n概念的には、fallback binding は次のように動きます。\n\n```js\nconst attrName = rawName.slice(1);\nconst value = evaluate(rawValue, scope);\n\nif(value === false || value == null){\n        element.removeAttribute(attrName);\n} else if(value === true){\n        element.setAttribute(attrName, attrName);\n} else {\n        element.setAttribute(attrName, String(value));\n}\n```\n\n実際の runtime は、special cases、filters、error handling、DOM property handling を含む場合があります。\n\n\n#### 変数の作成とスコープの重なり\n\nAttribute bindings は変数を作りません。\n\n- `:title=\"user.name\"` は `user.name` を読みます。\n- 新しい variable は導入しません。\n- host data に書き込みません。\n- DOM attribute を更新するだけです。\n\n新しい local values が必要な場合は、ancestor element に `*let` を使います。\n\n```html\n<div *let=\"label = user.name + ' (' + user.role + ')'\">\n  <button :aria-label=\"label\">Open</button>\n</div>\n```\n\n\n#### 親へのアクセス\n\nnested `<serc-rod>` の中では、`$parent` が使える場合があります。\n\n```html\n<serc-rod data='{ \"theme\": \"dark\" }'>\n  <serc-rod data='{ \"item\": { \"name\": \"A\" } }'>\n    <div :data-theme=\"$parent.theme\">\n      %item.name%\n    </div>\n  </serc-rod>\n</serc-rod>\n```\n\n`$parent` は親 host data を参照するため、attribute expressions からも読めます。\n\n\n#### conditionals and loops との併用\n\nFallback attribute bindings は、条件分岐や loop の中で自然に使えます。\n\n```html\n<li\n  *for=\"item of items\"\n  :data-id=\"item.id\"\n  :aria-selected=\"item.id === selectedId ? 'true' : 'false'\">\n  %item.label%\n</li>\n```\n\n各 iteration では、`item` が現在の scope に入ります。\n\n条件付き属性:\n\n```html\n<button :disabled=\"!canSubmit\">Submit</button>\n```\n\n`canSubmit` が false のとき、disabled が存在します。\n\n\n#### 推奨される使い方\n\n- HTML semantics に合った属性名を使います。\n- boolean attributes には boolean values を返します。\n- ARIA attributes では、必要に応じて `\"true\"` / `\"false\"` strings を返します。\n- 複雑な式は `*let` または method へ移します。\n- URL、style、HTML のような sensitive attributes では、専用 directive や dedicated manual の規則を確認します。\n- DOM attribute を data source of truth として使わないでください。source of truth は Sercrod data です。\n\n\n#### 例\n\n動的 title:\n\n```html\n<button :title=\"'Open ' + item.name\">Open</button>\n```\n\nARIA expanded の例:\n\n```html\n<button :aria-expanded=\"open ? 'true' : 'false'\">\n  Toggle\n</button>\n```\n\ndata 属性:\n\n```html\n<article\n  *for=\"post of posts\"\n  :data-id=\"post.id\"\n  :data-status=\"post.status\">\n  %post.title%\n</article>\n```\n\ntab index の例:\n\n```html\n<div :tabindex=\"active ? 0 : -1\"></div>\n```\n\n\n#### 注意点\n\n- Generic `:name` bindings are data-to-DOM only.\n- They do not write back to Sercrod data.\n- `:text` and `:html` are reserved and skipped by this fallback.\n- Dedicated bindings such as `:class`, `:style`, `:value`, `:href`, and `:src` may add extra behavior.\n- When in doubt, check the dedicated manual entry first.\n",
  "break": "### *break\n\n#### 概要\n\n`*break` は、`*switch` block 内の fallthrough を停止するための制御ディレクティブです。\n\nJavaScript の `switch` における `break` に近い役割を持ちます。Sercrod の `*switch` は、一致した `*case` から描画を始め、break に到達するまで後続の branch へ fallthrough します。`*break` は、その fallthrough を止める marker です。\n\nalias の `n-break` も同じ挙動です。\n\n`*case.break` は、`*case` と `*break` を1つの属性にまとめた短縮形です。\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n```\n\nこれは、概念的には次と同じです。\n\n```html\n<p *case=\"'ready'\" *break>Ready</p>\n```\n\n#### 基本例\n\n```html\n<serc-rod data='{\"status\":\"ready\"}'>\n  <div *switch=\"status\">\n    <p *case=\"'idle'\">Idle</p>\n    <p *case=\"'ready'\" *break>Ready</p>\n    <p *case=\"'ready'\">This is not rendered</p>\n    <p *default>Unknown</p>\n  </div>\n</serc-rod>\n```\n\nこの例では、`status` は `\"ready\"` です。\n\n- `*case=\"'idle'\"` は一致しません。\n- `*case=\"'ready'\" *break` が一致し、`Ready` が描画されます。\n- `*break` があるため、後続の `*case=\"'ready'\"` や `*default` は描画されません。\n\n#### 挙動\n\n`*break` は `*switch` / `n-switch` の処理中にだけ意味を持ちます。\n\n基本規則:\n\n- `*break` は、`*switch` host の直接の子 branch 上で使います。\n- branch が描画されたあと、その branch に `*break` または `n-break` があれば、switch rendering は停止します。\n- `*case.break` または `n-case.break` も break marker として扱われます。\n- `*break` の属性値は評価されません。presence が意味を持ちます。\n- `*switch` の外で使っても、独立した loop break や control break としては動きません。\n\n`*break` は、`*for` や `*each` の loop を止めるものではありません。\n\n#### 評価タイミング\n\n`*break` は、通常の式として評価されません。\n\n`*switch` の処理中に、runtime は branch 要素の属性を確認します。\n\n1. `*switch` 式を評価します。\n2. 直接の子 branch を上から走査します。\n3. 一致した `*case` または `*default` から描画を開始します。\n4. branch を clone して描画します。\n5. その元 branch に `*break`、`n-break`、`*case.break`、`n-case.break` があるかを確認します。\n6. break marker があれば、残りの branch の処理を停止します。\n\nこのため、`*break=\"condition\"` のように書いても、その condition は評価されません。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nfor(const branch of switchChildren){\n        if(!renderingStarted){\n                if(caseMatches(branch) || defaultReached(branch)){\n                        renderingStarted = true;\n                } else {\n                        continue;\n                }\n        }\n\n        renderBranch(branch);\n\n        if(hasBreak(branch)){\n                break;\n        }\n}\n```\n\n`hasBreak(branch)` は、次のような属性を確認します。\n\n```text\n*break\nn-break\n*case.break\nn-case.break\n```\n\n#### 変数の作成\n\n`*break` は変数を作りません。\n\n- scope に新しい名前を追加しません。\n- `$switch` を変更しません。\n- host data を変更しません。\n- `*let` のような local scope も作りません。\n\nこれは、純粋に switch branch の制御 marker です。\n\n#### スコープの重なり\n\n`*break` は scope layering に影響しません。\n\nbranch が描画されるときの scope は、`*switch` によって追加された `$switch` や、その branch の通常の rendering scope によって決まります。\n\n`*break` 自体は、scope を読むことも書くこともしません。\n\n#### 親へのアクセス\n\n`*break` は `$parent` を読みません。\n\nnested `<serc-rod>` がある場合でも、`*break` はそれが属する `*switch` block の branch control としてだけ働きます。\n\n親 host の switch を子 host から止めることはしません。\n\n#### conditionals and loops との併用\n\n`*break` は `*switch` branch に置くための directive です。\n\n`*if` などで branch 自体を条件付きにすることはできますが、`*break` はあくまで `*switch` の制御として扱います。\n\n```html\n<div *switch=\"status\">\n  <p *case=\"'ready'\" *break>Ready</p>\n  <p *default>Unknown</p>\n</div>\n```\n\nloop の中に `*switch` がある場合、各 iteration の switch に対して `*break` が働きます。\n\n```html\n<div *for=\"item of items\">\n  <div *switch=\"item.status\">\n    <span *case=\"'ok'\" *break>OK</span>\n    <span *default>Other</span>\n  </div>\n</div>\n```\n\nここで `*break` は、各 item の switch block を止めるだけです。outer loop は止まりません。\n\n#### 推奨される使い方\n\n- 通常の UI では、`*case.break` を使う方が読みやすい場合があります。\n- 明示的に branch と break を分けたい場合は、`*case=\"...\" *break` を使います。\n- `*break` は `*switch` の直接の子 branch に置きます。\n- loop を止める目的で `*break` を使わないでください。\n- `*break=\"expr\"` のように条件を持たせないでください。条件が必要なら `*case` 側の式で表します。\n\n#### 例\n\n`*case` と `*break` を分ける例です。\n\n```html\n<div *switch=\"kind\">\n  <p *case=\"'info'\" *break>Info</p>\n  <p *case=\"'warning'\" *break>Warning</p>\n  <p *default>Unknown</p>\n</div>\n```\n\n同じ内容を `*case.break` で書く例です。\n\n```html\n<div *switch=\"kind\">\n  <p *case.break=\"'info'\">Info</p>\n  <p *case.break=\"'warning'\">Warning</p>\n  <p *default>Unknown</p>\n</div>\n```\n\n意図的な fallthrough の例です。\n\n```html\n<div *switch=\"level\">\n  <p *case=\"'admin'\">Admin tools</p>\n  <p *case=\"'editor'\">Editor tools</p>\n  <p *case.break=\"'viewer'\">Viewer tools</p>\n</div>\n```\n\nこの例では、`admin` に一致すると `Admin tools` から始まり、`Viewer tools` の branch で止まります。\n\n#### 注意点\n\n- `*break` と `n-break` は同じ挙動です。\n- `*break` は `*switch` の fallthrough を止めるための marker です。\n- `*case.break` は `*case` と `*break` をまとめた短縮形です。\n- `*break` は `*for` / `*each` の loop break ではありません。\n",
  "case-break": "### *case.break\n\n#### 概要\n\n`*case.break` は、`*switch` / `n-switch` の中で使う case branch です。\n\n`*case` と同じように switch value と照合しますが、一致して branch が描画されたあと、同じ `*switch` block 内の後続 branch への fallthrough を停止します。\n\nつまり、`*case.break=\"expr\"` は、概念的には同じ要素に `*case=\"expr\"` と `*break` を置くのと同じです。\n\nalias の `n-case.break` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"status\":\"ready\"}'>\n  <div *switch=\"status\">\n    <p *case=\"'idle'\">Idle</p>\n    <p *case.break=\"'ready'\">Ready</p>\n    <p *case=\"'ready'\">This is not rendered</p>\n    <p *default>Unknown</p>\n  </div>\n</serc-rod>\n```\n\nこの例では、`status` は `\"ready\"` です。\n\n- `*case=\"'idle'\"` は一致しません。\n- `*case.break=\"'ready'\"` が一致します。\n- `Ready` が描画されます。\n- `*case.break` は break marker でもあるため、後続 branch は描画されません。\n\n#### 挙動\n\n`*case.break` は `*switch` / `n-switch` host の直接の子 branch として使います。\n\n基本規則:\n\n- 属性値は case expression として評価されます。\n- その評価結果が `$switch` と一致すると、その branch から描画が始まります。\n- branch が描画された直後に fallthrough が停止します。\n- 後続の `*case`、`*case.break`、`*default` は処理されません。\n- `*case.break` は `*switch` の外では特別な意味を持ちません。\n\n`*case.break` は、通常の `*case` と `*break` の組み合わせを短く明確に書くためのものです。\n\n#### 評価タイミング\n\n`*case.break` は `*switch` の子 branch 走査中に評価されます。\n\n1. `*switch` expression が評価され、結果が `$switch` として child scope に追加されます。\n2. `*switch` host の直接の子要素が DOM 順に確認されます。\n3. `*case.break` の属性値が現在の scope で評価されます。\n4. 評価結果が `$switch` と一致する場合、その branch が描画されます。\n5. 描画後、break marker として処理され、switch block の走査が停止します。\n\nbranch の中の children は、branch が選ばれた場合だけ描画されます。\n\n#### case 式の意味\n\n`*case.break` の式は、`*case` と同じ照合規則を使います。\n\n実用上は、次のような単純な値を使うのが分かりやすいです。\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n<p *case.break=\"1\">One</p>\n<p *case.break=\"statusCode\">Matching code</p>\n```\n\ncase expression は現在の scope で評価されます。`$switch` もその scope から参照できます。\n\n複雑な条件を case expression に詰め込みすぎると読みにくくなるため、必要なら `*if` または事前の data 整理を検討します。\n\n#### スコープと `$switch`\n\n`*switch` は、子 branch の scope に `$switch` を追加します。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'ready'\">\n    Current switch value: %$switch%\n  </p>\n</div>\n```\n\nこの branch が描画される場合、`$switch` は `status` の評価結果です。\n\n`*case.break` 自体は新しい変数を作りません。switch host が提供する `$switch` を利用します。\n\n#### *case, *default and *break との関係\n\n`*case.break` は、次の2つの意味を1つにまとめます。\n\n```html\n<p *case=\"'ready'\" *break>Ready</p>\n```\n\n同等の短縮形です。\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n```\n\n`*case`:\n\n- 一致すると描画開始点になります。\n- break がない限り後続 branch へ fallthrough します。\n\n`*case.break`:\n\n- 一致すると描画開始点になります。\n- 自分を描画したあと停止します。\n\n`*default`:\n\n- どの case も一致しなかった場合の開始 branch です。\n\n`*break`:\n\n- 通常の case branch に後付けで停止 marker を付けます。\n\n#### fallthrough と break の挙動\n\nSercrod の `*switch` は、JavaScript の `switch` に近い fallthrough model を持ちます。\n\n```html\n<div *switch=\"role\">\n  <p *case=\"'admin'\">Admin</p>\n  <p *case=\"'editor'\">Editor</p>\n  <p *case.break=\"'viewer'\">Viewer</p>\n</div>\n```\n\n`role` が `\"admin\"` の場合、`Admin` から描画が始まり、`Viewer` の branch で停止します。\n\n通常の UI で1つの branch だけを描画したい場合は、各 case に `*case.break` を使うと意図が明確になります。\n\n#### 推奨される使い方\n\n- 1つの branch だけ描画したい場合は `*case.break` を使います。\n- 意図的な fallthrough が必要な場合だけ、通常の `*case` を使います。\n- `*case.break` は `*switch` host の直接の子要素に置きます。\n- case expression は短く、比較しやすい値にします。\n- `*switch` の外で `*case.break` を使わないでください。\n\n#### 追加例\n\nstatus 表示です。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'loading'\">Loading...</p>\n  <p *case.break=\"'ready'\">Ready</p>\n  <p *case.break=\"'error'\">Error</p>\n  <p *default>Unknown</p>\n</div>\n```\n\nnumber code の例です。\n\n```html\n<div *switch=\"code\">\n  <p *case.break=\"200\">OK</p>\n  <p *case.break=\"404\">Not found</p>\n  <p *default>Other</p>\n</div>\n```\n\n#### 注意点\n\n- `*case.break` と `n-case.break` は同じ挙動です。\n- `*case.break` は `*case` と `*break` を合わせた短縮形です。\n- `$switch` は `*switch` から提供されます。\n- `*case.break` は loop control ではありません。\n",
  "case.break": "### *case.break\n\n#### 概要\n\n`*case.break` は、`*switch` / `n-switch` の中で使う case branch です。\n\n`*case` と同じように switch value と照合しますが、一致して branch が描画されたあと、同じ `*switch` block 内の後続 branch への fallthrough を停止します。\n\nつまり、`*case.break=\"expr\"` は、概念的には同じ要素に `*case=\"expr\"` と `*break` を置くのと同じです。\n\nalias の `n-case.break` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"status\":\"ready\"}'>\n  <div *switch=\"status\">\n    <p *case=\"'idle'\">Idle</p>\n    <p *case.break=\"'ready'\">Ready</p>\n    <p *case=\"'ready'\">This is not rendered</p>\n    <p *default>Unknown</p>\n  </div>\n</serc-rod>\n```\n\nこの例では、`status` は `\"ready\"` です。\n\n- `*case=\"'idle'\"` は一致しません。\n- `*case.break=\"'ready'\"` が一致します。\n- `Ready` が描画されます。\n- `*case.break` は break marker でもあるため、後続 branch は描画されません。\n\n#### 挙動\n\n`*case.break` は `*switch` / `n-switch` host の直接の子 branch として使います。\n\n基本規則:\n\n- 属性値は case expression として評価されます。\n- その評価結果が `$switch` と一致すると、その branch から描画が始まります。\n- branch が描画された直後に fallthrough が停止します。\n- 後続の `*case`、`*case.break`、`*default` は処理されません。\n- `*case.break` は `*switch` の外では特別な意味を持ちません。\n\n`*case.break` は、通常の `*case` と `*break` の組み合わせを短く明確に書くためのものです。\n\n#### 評価タイミング\n\n`*case.break` は `*switch` の子 branch 走査中に評価されます。\n\n1. `*switch` expression が評価され、結果が `$switch` として child scope に追加されます。\n2. `*switch` host の直接の子要素が DOM 順に確認されます。\n3. `*case.break` の属性値が現在の scope で評価されます。\n4. 評価結果が `$switch` と一致する場合、その branch が描画されます。\n5. 描画後、break marker として処理され、switch block の走査が停止します。\n\nbranch の中の children は、branch が選ばれた場合だけ描画されます。\n\n#### case 式の意味\n\n`*case.break` の式は、`*case` と同じ照合規則を使います。\n\n実用上は、次のような単純な値を使うのが分かりやすいです。\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n<p *case.break=\"1\">One</p>\n<p *case.break=\"statusCode\">Matching code</p>\n```\n\ncase expression は現在の scope で評価されます。`$switch` もその scope から参照できます。\n\n複雑な条件を case expression に詰め込みすぎると読みにくくなるため、必要なら `*if` または事前の data 整理を検討します。\n\n#### スコープと `$switch`\n\n`*switch` は、子 branch の scope に `$switch` を追加します。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'ready'\">\n    Current switch value: %$switch%\n  </p>\n</div>\n```\n\nこの branch が描画される場合、`$switch` は `status` の評価結果です。\n\n`*case.break` 自体は新しい変数を作りません。switch host が提供する `$switch` を利用します。\n\n#### *case, *default and *break との関係\n\n`*case.break` は、次の2つの意味を1つにまとめます。\n\n```html\n<p *case=\"'ready'\" *break>Ready</p>\n```\n\n同等の短縮形です。\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n```\n\n`*case`:\n\n- 一致すると描画開始点になります。\n- break がない限り後続 branch へ fallthrough します。\n\n`*case.break`:\n\n- 一致すると描画開始点になります。\n- 自分を描画したあと停止します。\n\n`*default`:\n\n- どの case も一致しなかった場合の開始 branch です。\n\n`*break`:\n\n- 通常の case branch に後付けで停止 marker を付けます。\n\n#### fallthrough と break の挙動\n\nSercrod の `*switch` は、JavaScript の `switch` に近い fallthrough model を持ちます。\n\n```html\n<div *switch=\"role\">\n  <p *case=\"'admin'\">Admin</p>\n  <p *case=\"'editor'\">Editor</p>\n  <p *case.break=\"'viewer'\">Viewer</p>\n</div>\n```\n\n`role` が `\"admin\"` の場合、`Admin` から描画が始まり、`Viewer` の branch で停止します。\n\n通常の UI で1つの branch だけを描画したい場合は、各 case に `*case.break` を使うと意図が明確になります。\n\n#### 推奨される使い方\n\n- 1つの branch だけ描画したい場合は `*case.break` を使います。\n- 意図的な fallthrough が必要な場合だけ、通常の `*case` を使います。\n- `*case.break` は `*switch` host の直接の子要素に置きます。\n- case expression は短く、比較しやすい値にします。\n- `*switch` の外で `*case.break` を使わないでください。\n\n#### 追加例\n\nstatus 表示です。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'loading'\">Loading...</p>\n  <p *case.break=\"'ready'\">Ready</p>\n  <p *case.break=\"'error'\">Error</p>\n  <p *default>Unknown</p>\n</div>\n```\n\nnumber code の例です。\n\n```html\n<div *switch=\"code\">\n  <p *case.break=\"200\">OK</p>\n  <p *case.break=\"404\">Not found</p>\n  <p *default>Other</p>\n</div>\n```\n\n#### 注意点\n\n- `*case.break` と `n-case.break` は同じ挙動です。\n- `*case.break` は `*case` と `*break` を合わせた短縮形です。\n- `$switch` は `*switch` から提供されます。\n- `*case.break` は loop control ではありません。\n",
  "case": "### *case / *case.break\n\n#### 概要\n\n`*case` は、`*switch` / `n-switch` block 内で branch を定義するディレクティブです。\n\n`*switch` 式の値が case expression の結果と一致した場合、その branch から描画が始まります。\n\nSercrod の `*switch` は fallthrough model を持ちます。つまり、branch が一致したあと、`*break` または `*case.break` に到達するまで後続 branch も描画されます。\n\n`*case.break` は、`*case` と break marker をまとめた短縮形です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"status\":\"ready\"}'>\n  <div *switch=\"status\">\n    <p *case=\"'idle'\">Idle</p>\n    <p *case=\"'ready'\">Ready</p>\n    <p *default>Unknown</p>\n  </div>\n</serc-rod>\n```\n\n`status` は `\"ready\"` なので、`*case=\"'ready'\"` が一致します。\n\nこの例では後続に default がありますが、break がない場合、fallthrough して後続 branch が描画される可能性があります。通常の UI で1つだけ描画したい場合は、`*case.break` を使います。\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n```\n\n#### 挙動\n\n`*case` は `*switch` host の直接の子要素で使います。\n\n基本規則:\n\n- `*switch` は式を評価し、その結果を `$switch` として子 scope に渡します。\n- `*case` の属性値は case expression として評価されます。\n- case expression の結果が `$switch` と一致すると、その branch から描画が始まります。\n- break marker がない場合、後続 branch へ fallthrough します。\n- `*case.break` は、自分の branch を描画したあと fallthrough を停止します。\n- `*case` は `*switch` の外では特別な意味を持ちません。\n\n#### case 式の意味\n\n`*case` の属性値は Sercrod 式として評価されます。\n\n例:\n\n```html\n<p *case=\"'ready'\">Ready</p>\n<p *case=\"200\">OK</p>\n<p *case=\"statusCode\">Status code matched</p>\n```\n\n推奨:\n\n- string literal には quote を付けます。\n- number literal はそのまま書けます。\n- host data や scope variable も使えます。\n\n複雑な条件判定を `*case` に詰め込みすぎると読みにくくなります。必要なら `*if` か、事前に `*let` / data 側で比較用の値を用意します。\n\n#### 評価タイミング\n\n`*case` は、`*switch` host の rendering 中に評価されます。\n\n1. `*switch` 式が評価されます。\n2. 結果が `$switch` として child scope に追加されます。\n3. 直接の子 branch が DOM 順に確認されます。\n4. まだ branch が開始していなければ、`*case` expression が評価されます。\n5. 一致すれば、その branch から描画が始まります。\n6. 描画開始後は、break に到達するまで後続 branch が描画されます。\n\n`*case` は選択された branch を決めるために評価されます。選ばれなかった branch の children は描画されません。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst switchValue = evaluate(switchExpression, scope);\nconst childScope = { ...scope, $switch: switchValue };\n\nlet active = false;\n\nfor(const child of directChildren){\n        if(!active){\n                if(hasCase(child) && matches(child, switchValue, childScope)){\n                        active = true;\n                } else if(hasDefault(child)){\n                        active = true;\n                } else {\n                        continue;\n                }\n        }\n\n        renderBranch(child, childScope);\n\n        if(hasBreak(child)){\n                break;\n        }\n}\n```\n\n実際の runtime は clone、attribute cleanup、child rendering を含みます。\n\n#### 変数の作成とスコープの重なり\n\n`*case` は新しい変数を作りません。\n\n`$switch` は `*switch` host によって追加されます。\n\nbranch が描画されるとき、その branch の children は `$switch` を含む scope を使えます。\n\n```html\n<div *switch=\"status\">\n  <p *case=\"'ready'\">Value: %$switch%</p>\n</div>\n```\n\n#### *default と *break との併用\n\n`*default` は、どの `*case` も一致しなかった場合の fallback branch です。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'ready'\">Ready</p>\n  <p *default>Unknown</p>\n</div>\n```\n\n`*break` は通常の `*case` branch に停止 marker を付けます。\n\n```html\n<p *case=\"'ready'\" *break>Ready</p>\n```\n\n短縮形:\n\n```html\n<p *case.break=\"'ready'\">Ready</p>\n```\n\n#### conditionals and loops との併用\n\n`*case` は `*switch` の直接の子である必要があります。\n\nloop の中で switch を使う場合は、各 iteration に switch block を作ります。\n\n```html\n<div *for=\"item of items\">\n  <div *switch=\"item.status\">\n    <p *case.break=\"'ok'\">OK</p>\n    <p *default>Other</p>\n  </div>\n</div>\n```\n\nbranch の内側では、通常通り `*if`、`*for`、`*print` などを使えます。\n\n#### 推奨される使い方\n\n- 通常の UI では `*case.break` を使い、1 branch だけを描画する意図を明確にします。\n- fallthrough が必要な場合だけ、break なしの `*case` を使います。\n- `*case` は `*switch` host の直接の子に置きます。\n- case expression は短く明確にします。\n- 文字列 case は quote します。\n\n#### 追加例\n\n明示的に break する status switch です。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'loading'\">Loading</p>\n  <p *case.break=\"'ready'\">Ready</p>\n  <p *case.break=\"'error'\">Error</p>\n  <p *default>Unknown</p>\n</div>\n```\n\nfallthrough を意図する例です。\n\n```html\n<div *switch=\"role\">\n  <p *case=\"'admin'\">Admin</p>\n  <p *case=\"'editor'\">Editor</p>\n  <p *case.break=\"'viewer'\">Viewer</p>\n</div>\n```\n\n#### 注意点\n\n- `*case` は `*switch` の中だけで意味を持ちます。\n- `*case.break` は `*case` と `*break` の短縮形です。\n- `$switch` は `*switch` によって branch scope に追加されます。\n- break がない場合は fallthrough します。\n",
  "compose": "### *compose\n\n#### 概要\n\n`*compose` は、式の結果から要素の inner HTML を構成する出力ディレクティブです。\n\nこれは `*innerHTML` に近い機能ですが、名前の通り、project 側の `html` filter や template composition の仕組みと組み合わせて、HTML 断片を構成する用途を想定しています。\n\nalias の `n-compose` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"body\":\"<strong>Hello</strong>\"}'>\n  <div *compose=\"body\"></div>\n</serc-rod>\n```\n\nこの例では、`body` が評価され、その結果が html filter を通ったうえで `div` の inner HTML として設定されます。\n\n#### 挙動\n\n`*compose` の基本動作:\n\n- 属性値を現在の scope で評価します。\n- 結果を raw HTML candidate として扱います。\n- その値を `html` filter に渡します。\n- filter の結果を要素の `innerHTML` として設定します。\n- element 自体は残り、その内容が置き換わります。\n\n`null` や `false` のような値は、空の HTML として扱われます。\n\n#### 評価タイミング\n\n`*compose` は element が描画されるときに評価されます。\n\n1. element が構造ディレクティブを通過します。\n2. clone が作られます。\n3. `*compose` の式が現在の scope で評価されます。\n4. 結果が html filter に渡されます。\n5. filtered HTML が clone の `innerHTML` に設定されます。\n6. 通常の child rendering とは異なる処理になるため、同じ要素内に複雑な child directives を混在させない方が安全です。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst raw = evaluate(composeExpression, scope);\nconst html = Sercrod._filters.html(raw == null || raw === false ? \"\" : raw, {\n        el,\n        scope,\n        expr: composeExpression\n});\n\nelement.innerHTML = html;\n```\n\n実際の runtime は clone、attribute cleanup、error handling を含みます。\n\n#### html フィルターとの連携\n\n`*compose` は html filter と密接に関係します。\n\ndefault の html filter が raw value をそのまま返す場合、`*compose` は実質的に raw HTML insertion になります。\n\nproject が html filter を customize している場合、次のような処理ができます。\n\n- HTML sanitize。\n- template name から HTML fragment への解決。\n- 許可済み component のみの展開。\n- project 固有の markup normalization。\n\nAI が `*compose` を使う場合は、その project の html filter が何を保証しているかを確認する必要があります。\n\n#### 安全上の注意\n\n`*compose` は HTML を挿入します。\n\nそのため、信頼できない外部入力やユーザー入力をそのまま渡すと危険です。\n\n安全に使うための原則:\n\n- 信頼済みの HTML だけを渡します。\n- 外部入力を使う場合は、server 側または html filter で sanitize します。\n- text で十分な場合は、`*print` や `*textContent` を使います。\n- user-generated content を raw HTML として扱わないでください。\n\n#### 変数の作成とスコープの重なり\n\n`*compose` は変数を作りません。\n\n- 現在の scope を読みます。\n- host data を直接書き換えません。\n- `*let` のような local scope は作りません。\n- output として DOM の inner HTML を更新します。\n\n#### 親へのアクセス\n\nnested host の中で `$parent` が利用できる場合、`*compose` の式からも参照できます。\n\n```html\n<div *compose=\"$parent.sharedHtml\"></div>\n```\n\nただし、親 data から HTML を挿入する場合も、信頼できる content であることを確認します。\n\n#### conditionals and loops との併用\n\n`*compose` は conditionals や loops と組み合わせられます。\n\n```html\n<div *if=\"html\" *compose=\"html\"></div>\n```\n\nloop 内で使う例:\n\n```html\n<div *for=\"block of blocks\" *compose=\"block.html\"></div>\n```\n\nこの場合、各 block の HTML が挿入されます。外部 data 由来の HTML であれば、必ず sanitize を考慮します。\n\n#### *include and *import との併用\n\n`*compose` は HTML 文字列や filter 経由の構成に向きます。\n\n再利用可能な template fragment を扱う場合は、`*include` や `*import` の方が適している場合があります。\n\n目安:\n\n- HTML 文字列を評価して入れる: `*compose`\n- 名前付き partial を含める: `*include`\n- 外部 template を取り込む: `*import`\n\n#### 推奨される使い方\n\n- text 出力には使わず、`*print` / `*textContent` を使います。\n- HTML の出所を明確にします。\n- project の html filter の役割を確認します。\n- `*compose` を持つ要素には、複雑な child directives を置かないでください。\n- template reuse には、必要に応じて `*include` / `*import` を検討します。\n\n#### 例\n\n安全化済み HTML fragment:\n\n```html\n<div *compose=\"article.safeHtml\"></div>\n```\n\nproject filter による component composition:\n\n```html\n<section *compose=\"{ type: 'card', data: item }\"></section>\n```\n\nfallback の例:\n\n```html\n<div *compose=\"html || ''\"></div>\n```\n\n#### 注意点\n\n- `*compose` と `n-compose` は同じ挙動です。\n- `*compose` は HTML output 用です。\n- `html` filter と組み合わせて扱います。\n- 信頼できない HTML をそのまま挿入しないでください。\n",
  "default": "### *default\n\n#### 概要\n\n`*default` は、`*switch` / `n-switch` block 内で、どの `*case` も一致しなかった場合の fallback branch を定義します。\n\nJavaScript の `switch` における `default` に近い役割です。\n\nalias の `n-default` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"status\":\"unknown\"}'>\n  <div *switch=\"status\">\n    <p *case.break=\"'ready'\">Ready</p>\n    <p *case.break=\"'error'\">Error</p>\n    <p *default>Unknown</p>\n  </div>\n</serc-rod>\n```\n\n`status` は `\"ready\"` でも `\"error\"` でもないため、`*default` branch が描画されます。\n\n#### 挙動\n\n`*default` は `*switch` host の直接の子 branch として使います。\n\n基本規則:\n\n- `*default` は式を評価しません。\n- それまでの `*case` / `*case.break` がどれも一致しなかった場合、`*default` から描画が始まります。\n- switch rendering がすでに開始している場合、`*default` も fallthrough branch として描画される可能性があります。\n- `*break` または `*case.break` に到達すると、fallthrough は停止します。\n- `*default` は `*switch` の外では特別な意味を持ちません。\n\n#### 評価タイミング\n\n`*default` 自体は式を評価しません。\n\n`*switch` の branch 走査中に、runtime は `*default` の presence を確認します。\n\n1. `*switch` 式が評価されます。\n2. 直接の子 branch が DOM 順に走査されます。\n3. `*case` が一致すれば、その branch から描画が始まります。\n4. 一致する `*case` がないまま `*default` に到達すると、その branch から描画が始まります。\n5. branch 描画後、break marker があるか確認します。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nlet active = false;\n\nfor(const branch of switchChildren){\n        if(!active){\n                if(hasMatchingCase(branch)){\n                        active = true;\n                } else if(hasDefault(branch)){\n                        active = true;\n                } else {\n                        continue;\n                }\n        }\n\n        renderBranch(branch);\n\n        if(hasBreak(branch)){\n                break;\n        }\n}\n```\n\n`*default` は、case が見つからなかった場合の開始点です。\n\n#### 変数の作成とスコープの重なり\n\n`*default` は変数を作りません。\n\n`$switch` は `*switch` host によって追加されます。default branch の中でも `$switch` を参照できます。\n\n```html\n<p *default>Unknown value: %$switch%</p>\n```\n\n#### 親へのアクセス\n\n`*default` は `$parent` を直接扱いません。\n\ndefault branch 内の通常の Sercrod expressions では、現在の scope に `$parent` があれば参照できます。\n\n#### conditionals and loops との併用\n\n`*default` は `*switch` host の直接の子である必要があります。\n\nloop 内で使う場合は、各 iteration に switch block を持たせます。\n\n```html\n<div *for=\"item of items\">\n  <div *switch=\"item.kind\">\n    <p *case.break=\"'a'\">A</p>\n    <p *default>Other</p>\n  </div>\n</div>\n```\n\n#### *case・*case.break・*break との併用\n\n`*default` は通常、branch list の最後に置きます。\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'ready'\">Ready</p>\n  <p *case.break=\"'error'\">Error</p>\n  <p *default>Unknown</p>\n</div>\n```\n\nbreak なしの `*case` を使うと、default まで fallthrough する可能性があります。\n\n```html\n<div *switch=\"status\">\n  <p *case=\"'ready'\">Ready</p>\n  <p *default>Also rendered by fallthrough</p>\n</div>\n```\n\nfallthrough を意図しない場合は `*case.break` を使います。\n\n#### 推奨される使い方\n\n- `*default` は通常、switch branch list の最後に置きます。\n- 通常の UI では、各 `*case` に `*case.break` を使い、default への意図しない fallthrough を避けます。\n- `*default` は式を持たないため、条件が必要なら `*case` または `*if` を使います。\n- `*default` は `*switch` host の直接の子に置きます。\n- default branch では fallback text や fallback UI を明確にします。\n\n#### 追加例\n\nstatus fallback の例:\n\n```html\n<div *switch=\"status\">\n  <p *case.break=\"'loading'\">Loading</p>\n  <p *case.break=\"'ready'\">Ready</p>\n  <p *default>Unknown status</p>\n</div>\n```\n\nrole fallback の例:\n\n```html\n<div *switch=\"role\">\n  <p *case.break=\"'admin'\">Admin</p>\n  <p *case.break=\"'editor'\">Editor</p>\n  <p *default>Viewer</p>\n</div>\n```\n\n#### 注意点\n\n- `*default` と `n-default` は同じ挙動です。\n- `*default` は式を評価しません。\n- `*switch` の外では特別な意味を持ちません。\n- break がない case から default へ fallthrough する場合があります。\n",
  "download": "### *download / n-download\n\n#### 概要\n\n`*download` は、任意の要素を accessible な download trigger にするディレクティブです。\n\n式を評価して download configuration を取得し、指定された URL から resource を取得し、Blob backed object URL と `<a download>` を使って browser download を開始します。\n\nalias の `n-download` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\n  \"report\": {\n    \"url\": \"/api/report.csv\",\n    \"filename\": \"report.csv\"\n  }\n}'>\n  <button type=\"button\" *download=\"report\">\n    Download report\n  </button>\n</serc-rod>\n```\n\nこの例では、button を click すると `/api/report.csv` が取得され、`report.csv` として download されます。\n\n#### 説明\n\n`*download` は HTTP response を Sercrod data に保存するのではなく、user agent の download flow を開始します。\n\nこれは次の処理をまとめたものです。\n\n- download option の評価。\n- `fetch` または XHR fallback による resource の取得。\n- response body の Blob 化。\n- object URL の作成。\n- 一時的な `<a download>` 要素による download 開始。\n- object URL の cleanup。\n\n`*download` は `$download` data slot へ値を書き込むためのものではありません。名前は似ていますが、`$download` は主に network helpers 側の status convention です。\n\n#### 挙動\n\nrendering 中に `*download` または `n-download` が見つかると、Sercrod はその要素を download trigger として準備します。\n\n基本動作:\n\n- directive の属性値を現在の scope で評価します。\n- 評価結果を download options として正規化します。\n- 要素に accessibility 用の role や tabindex を必要に応じて補います。\n- click と keyboard activation、つまり Enter / Space に handler を取り付けます。\n- activation 時に download request を実行します。\n\ndownload option は、string または object として書けます。\n\n```html\n<button *download=\"'/file/report.csv'\">Download</button>\n```\n\n```html\n<button *download=\"{ url: '/file/report.csv', filename: 'report.csv' }\">\n  Download\n</button>\n```\n\n#### download オプション\n\n主な option:\n\n- `url`\n  - download 対象の URL です。\n  - 必須です。\n\n- `method`\n  - HTTP method です。\n  - 省略時は GET です。\n\n- `headers`\n  - request headers です。\n\n- `credentials`\n  - `fetch` の credentials option に相当します。\n  - cookie を含める必要がある場合などに使います。\n\n- `filename`\n  - browser に渡す download filename です。\n  - response header から推定される場合もありますが、安定させたい場合は指定します。\n\n- `transport`\n  - 通常は `fetch` です。\n  - fallback として `xhr` を使う場合があります。\n\n#### 評価タイミング\n\n`*download` の式は、rendering 中に評価されます。\n\n1. element が描画対象になります。\n2. `*download` の式が現在の scope で評価されます。\n3. option が正規化されます。\n4. element が download trigger として準備されます。\n5. user activation 時に、保存された option に基づいて request が実行されます。\n\ndata が変わり host が再描画されると、download option も再評価されます。\n\n#### 実行モデル\n\nactivation 時の概念的な処理です。\n\n```js\nevent.preventDefault();\n\nconst response = await fetch(options.url, {\n        method: options.method || \"GET\",\n        headers: options.headers || {},\n        credentials: options.credentials\n});\n\nconst blob = await response.blob();\nconst objectUrl = URL.createObjectURL(blob);\n\nconst a = document.createElement(\"a\");\na.href = objectUrl;\na.download = options.filename || \"\";\na.click();\n\nURL.revokeObjectURL(objectUrl);\n```\n\n実際の runtime は error handling、transport fallback、filename 決定、event dispatch を含みます。\n\n#### 変数の作成\n\n`*download` は変数を作りません。\n\n- host data に response を保存しません。\n- scope に新しい名前を追加しません。\n- `$download` を更新するものではありません。\n\ndownload の進行状況や結果を data として扱いたい場合は、別の state 管理や event listener を使います。\n\n#### スコープの重なり\n\n`*download` の option expression は現在の scope で評価されます。\n\nそのため、host data、loop variables、ancestor `*let` values、methods を使えます。\n\n```html\n<button *for=\"file of files\" *download=\"{ url: file.url, filename: file.name }\">\n  Download %file.name%\n</button>\n```\n\n各 button は自分の `file` に基づく download option を持ちます。\n\n#### 親へのアクセス\n\nnested host の中では、現在の scope に `$parent` があれば `*download` の式から参照できます。\n\n```html\n<button *download=\"{ url: $parent.downloadUrl, filename: name }\">\n  Download\n</button>\n```\n\nただし、親 data 由来の URL でも、信頼できる値であることを確認します。\n\n#### conditionals and loops との併用\n\n`*download` は conditionals や loops と組み合わせられます。\n\n```html\n<button *if=\"reportReady\" *download=\"reportOptions\">\n  Download report\n</button>\n```\n\n```html\n<button *for=\"file of files\" *download=\"{ url: file.url, filename: file.name }\">\n  Download %file.name%\n</button>\n```\n\nloop 内では、各 trigger が自分の option を持ちます。\n\n#### 推奨される使い方\n\n- download trigger にはできるだけ `button type=\"button\"` を使います。\n- URL は明示的で、server 側で権限確認される endpoint にします。\n- private files では authentication、authorization、rate limiting を server 側で行います。\n- filename を安定させたい場合は option で指定します。\n- download の完了や失敗を UI に表示したい場合は、event listener や独自 state を設計します。\n- `*download` を data loading 用の `*fetch` や `*api` と混同しないでください。\n\n#### 例\n\n##### 1. data 内の単純な設定\n\n```html\n<serc-rod data='{\"file\": {\"url\": \"/files/a.pdf\", \"filename\": \"a.pdf\"}}'>\n  <button type=\"button\" *download=\"file\">Download</button>\n</serc-rod>\n```\n\n##### 2. credentials と headers を使う安全な download\n\n```html\n<button\n  type=\"button\"\n  *download=\"{\n    url: '/api/private/export',\n    filename: 'export.csv',\n    credentials: 'include',\n    headers: { 'X-Requested-With': 'Sercrod' }\n  }\">\n  Download export\n</button>\n```\n\n##### 3. XHR transport フォールバック\n\n```html\n<button\n  type=\"button\"\n  *download=\"{\n    url: '/api/legacy-download',\n    filename: 'legacy.zip',\n    transport: 'xhr'\n  }\">\n  Download legacy file\n</button>\n```\n\n##### 4. download event の監視\n\n```js\ndocument.addEventListener(\"sercrod-error\", (event)=>{\n        console.log(event.detail);\n});\n```\n\nproject が download event を追加で扱う場合は、その event detail を debug logs と合わせて確認します。\n\n#### 注意点\n\n- `*download` と `n-download` は同じ挙動です。\n- `*download` は browser download を開始します。\n- response を data slot へ保存するための directive ではありません。\n- `button type=\"button\"` を trigger として使う設計が分かりやすいです。\n",
  "each": "### *each\n\n#### 概要\n\n`*each` は、container 要素を1つ残したまま、その children を data collection に対して繰り返し描画するディレクティブです。\n\n`*for` が directive の付いた要素そのものを繰り返すのに対し、`*each` は directive の付いた要素を container として残し、その内部 template を繰り返します。\n\nalias の `n-each` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"items\":[\"Apple\",\"Orange\",\"Grape\"]}'>\n  <ul *each=\"item of items\">\n    <li>%item%</li>\n  </ul>\n</serc-rod>\n```\n\n結果として、`ul` は1つだけ残り、その中に `li` が3つ描画されます。\n\n#### 挙動\n\n`*each` は container-oriented loop です。\n\n基本規則:\n\n- `*each=\"item of items\"` のように書きます。\n- 右辺の collection expression、ここでは `items` を現在の scope で評価します。\n- collection の各 item について、container の original children を描画します。\n- 各 iteration では loop variable、ここでは `item` が scope に追加されます。\n- directive の付いた container element 自体は1つだけ描画されます。\n\n#### 式の構文\n\n一般的な形式は次の通りです。\n\n```html\n<div *each=\"item of items\">\n```\n\nまたは alias:\n\n```html\n<div n-each=\"item of items\">\n```\n\n`item` は loop variable name です。\n\n`items` は collection expression です。\n\n実用上は、collection expression は短く読みやすいものにします。\n\n```html\n<ul *each=\"post of posts\">\n```\n\n```html\n<tbody *each=\"row of rows\">\n```\n\n#### 値の扱い\n\ncollection expression は array-like または iterable な値を返すことを想定します。\n\n`null` や `undefined` の可能性がある場合は、data 側で空配列にしておくか、式で fallback します。\n\n```html\n<ul *each=\"item of (items || [])\">\n```\n\ncollection の shape は template と一致している必要があります。\n\n```html\n<li>%item.name%</li>\n```\n\nこのように読むなら、各 item は `name` を持つ object であるべきです。\n\n#### 評価タイミング\n\n`*each` は structural directive として、children の描画前に評価されます。\n\n1. container element が clone されます。\n2. `*each` expression が現在の scope で評価されます。\n3. container 自身から `*each` / `n-each` 属性が削除されます。\n4. container は parent に追加されます。\n5. original children が collection の各 item に対して繰り返し描画されます。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst collection = evaluate(eachExpression, scope);\nconst container = cloneElementWithoutEach(original);\n\nparent.appendChild(container);\n\nfor(const item of collection){\n        const childScope = Object.create(scope);\n        childScope[itemName] = item;\n\n        renderChildren(original.childNodes, container, childScope);\n}\n```\n\n実際の runtime は index、parent/root data、error handling、nested directives を含みます。\n\n#### 変数の作成とスコープの重なり\n\n`*each` は各 iteration ごとに loop variable を作ります。\n\n```html\n<ul *each=\"post of posts\">\n  <li>%post.title%</li>\n</ul>\n```\n\nこの例では、`post` が各 iteration の scope に追加されます。\n\nloop variable はその iteration の children から利用できます。\n\n`*each` 自体は host data を変更しません。ただし、children の中の `*let` や event handlers が object references を変更する場合は、その変更が data に反映される可能性があります。\n\n#### 親へのアクセス\n\nnested host の中で `$parent` が利用できる場合、`*each` の collection expression や children の expressions から参照できます。\n\n```html\n<div *each=\"item of $parent.items\">\n  %item.name%\n</div>\n```\n\nただし、parent data を loop source にする場合は、どの host が data を所有しているのかを明確にします。\n\n#### conditionals and loops との併用\n\n`*each` は `*if` と組み合わせられます。\n\n```html\n<ul *if=\"items.length\" *each=\"item of items\">\n  <li>%item.name%</li>\n</ul>\n```\n\nnested loops も可能です。\n\n```html\n<section *each=\"group of groups\">\n  <h2>%group.name%</h2>\n  <ul *each=\"item of group.items\">\n    <li>%item.name%</li>\n  </ul>\n</section>\n```\n\nloop variable 名が衝突しないようにします。\n\n#### templates, *include and *import との併用\n\n`*each` は container を残し、その children を繰り返します。\n\nそのため、同じ要素に `*include` や `*import` を置くと、役割が衝突しやすくなります。\n\n避ける例:\n\n```html\n<div *each=\"item of items\" *include=\"'item-card'\"></div>\n```\n\n推奨:\n\n```html\n<div *each=\"item of items\">\n  <div *include=\"'item-card'\"></div>\n</div>\n```\n\nこの形では、outer `div` が container で、inner `div` が include declaration になります。\n\n#### *for との比較\n\n`*for`:\n\n```html\n<li *for=\"item of items\">%item%</li>\n```\n\n- `li` 自体が繰り返されます。\n\n`*each`:\n\n```html\n<ul *each=\"item of items\">\n  <li>%item%</li>\n</ul>\n```\n\n- `ul` は1つだけ残ります。\n- `li` が繰り返されます。\n\n選び方:\n\n- 要素そのものが1つの item を表す場合は `*for`。\n- 要素が repeated children の container である場合は `*each`。\n\n#### 推奨される使い方\n\n- `ul`、`ol`、`tbody`、`select`、`section` など、container を残したい場合に使います。\n- loop variable は `item`、`post`、`row` など短く明確にします。\n- collection が `null` になる可能性がある場合は fallback を用意します。\n- `*each` と `*include` / `*import` を同じ要素に置かないでください。\n- `*for` との違いを意識して選びます。\n\n#### 追加例\n\ntable body の例:\n\n```html\n<table>\n  <tbody *each=\"row of rows\">\n    <tr>\n      <td>%row.name%</td>\n      <td>%row.value%</td>\n    </tr>\n  </tbody>\n</table>\n```\n\nselect options の例:\n\n```html\n<select *each=\"option of options\">\n  <option :value=\"option.value\">%option.label%</option>\n</select>\n```\n\ncard container の例:\n\n```html\n<section class=\"cards\" *each=\"card of cards\">\n  <article>\n    <h2>%card.title%</h2>\n  </article>\n</section>\n```\n\n#### 注意点\n\n- `*each` と `n-each` は同じ挙動です。\n- `*each` は container を残し、children を繰り返します。\n- `*for` は要素そのものを繰り返します。\n- reusable parts は children 側に置くと構造が分かりやすくなります。\n",
  "eager": "### *eager\n\n#### 概要\n\n`*eager` は、`*input` / `n-input` と組み合わせて、入力中の値を即時に data と surrounding UI へ反映したい場合に使う timing directive です。\n\n`*lazy` が type-then-action flow を重視するのに対し、`*eager` は live update を重視します。\n\n典型的な用途:\n\n- live search。\n- live filtering。\n- live preview。\n- character counter。\n- immediate validation。\n- slug preview。\n\nalias の `n-eager` も同じ挙動です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"keyword\": \"\"}'>\n  <input type=\"search\" *input=\"keyword\" *eager>\n\n  <p>Search keyword: %keyword%</p>\n</serc-rod>\n```\n\nこの例では、ユーザーが入力している間に `keyword` が更新され、表示も即時に変わります。\n\n#### 挙動\n\n`*eager` は、input binding の update timing を live update 側へ寄せる marker です。\n\n基本的な考え方:\n\n- `*input` が値の書き戻し先を決めます。\n- `*eager` は、入力中の変化を即時に反映する意図を示します。\n- 周囲の UI は、入力のたびに更新されることを前提にできます。\n\n`*eager` だけでは入力先は決まりません。通常は `*input` と一緒に使います。\n\n#### 有効化と値の扱い\n\n`*eager` は値そのものを変換するものではありません。\n\nvalue semantics は `*input` 側に従います。\n\n- text input なら文字列。\n- checkbox や radio なら、その control type の規則。\n- select なら選択値。\n- multiple select なら配列になる場合があります。\n\n`*eager` は、「いつ周囲に反映するか」に関わります。\n\n#### *input / n-input との関係\n\n典型的な組み合わせです。\n\n```html\n<input type=\"text\" *input=\"name\" *eager>\n```\n\n`*input=\"name\"` は、値を `name` に書き戻すことを示します。\n\n`*eager` は、その変更を live に反映することを示します。\n\n`*input` なしの `*eager` は、ほとんどの場合意味がありません。\n\n#### *lazy との関係\n\n`*lazy` と `*eager` は反対の意図を持ちます。\n\n`*lazy`:\n\n- type-then-action flow に向きます。\n- 入力後の Send / Submit / Apply を自然に実行したい場合。\n- 入力のたびに親 template を更新したくない場合。\n\n`*eager`:\n\n- live update に向きます。\n- 入力中の値をすぐに表示や検索に使いたい場合。\n- 周囲の UI が入力ごとに変わることが目的の場合。\n\n同じ input に両方を付けるべきではありません。どちらの timing が目的かを選びます。\n\n#### *stage との関係\n\nstaged editing の中でも `*eager` は使えます。\n\n```html\n<serc-rod data='{ \"profile\": { \"name\": \"\" } }' *stage>\n  <input type=\"text\" *input=\"profile.name\" *eager>\n  <p>Preview: %profile.name%</p>\n</serc-rod>\n```\n\nこの場合、live preview は staged buffer に基づいて更新されます。\n\nただし、各入力で preview を更新したいか、apply まで静かにしておきたいかは UI 設計によります。\n\n#### 評価タイミング\n\n`*eager` は入力 event の handling に影響します。\n\nおおまかな流れ:\n\n1. input element が描画されます。\n2. `*input` により、書き戻し先 data path が決まります。\n3. `*eager` により、入力中の変化を即時に反映する設定になります。\n4. user が入力します。\n5. 値が data に反映されます。\n6. 必要に応じて host または関連 UI が更新されます。\n\n#### 実行モデル\n\n概念的には次のような intent です。\n\n```js\nonInput(event){\n        writeInputValueToData(path, event.target.value);\n        updateNow();\n}\n```\n\n実際の runtime は input type、stage、lazy/eager flags、update batching を考慮します。\n\n#### 推奨される使い方\n\n- live search、live preview、counter、immediate validation に使います。\n- type-then-submit の form には安易に使わないでください。\n- 大きな DOM や重い expression がある場合は、入力ごとの更新コストに注意します。\n- `*input` と組み合わせて使います。\n- `*lazy` と同じ input に同時に置かないでください。\n\n#### 例\n\nlive preview の例:\n\n```html\n<serc-rod data='{\"title\": \"\"}'>\n  <input type=\"text\" *input=\"title\" *eager>\n  <h2>%title%</h2>\n</serc-rod>\n```\n\n文字数 counter:\n\n```html\n<serc-rod data='{\"message\": \"\"}'>\n  <textarea *input=\"message\" *eager></textarea>\n  <p>%message.length% characters</p>\n</serc-rod>\n```\n\nlive filter の例:\n\n```html\n<serc-rod data='{\"q\": \"\", \"items\": [\"Apple\", \"Orange\", \"Grape\"]}'>\n  <input type=\"search\" *input=\"q\" *eager>\n\n  <ul>\n    <li *for=\"item of items.filter(v => v.toLowerCase().includes(q.toLowerCase()))\">\n      %item%\n    </li>\n  </ul>\n</serc-rod>\n```\n\n#### 注意点\n\n- `*eager` と `n-eager` は同じ挙動です。\n- `*eager` は通常 `*input` と一緒に使います。\n- live update が目的の場合に使います。\n- type-then-action flow には `*lazy` を検討します。\n",
  "else": "### *else / n-else\n\n#### 概要\n\n`*else` / `n-else` は、`*if` / `*elseif` chain の fallback branch です。\n\n同じ parent 内で直前の `*if` / `*elseif` chain がどの branch も選ばなかった場合、`*else` branch が描画されます。\n\n`*else` は式を持ちません。presence が意味を持ちます。\n\n#### 説明\n\n`*else` は、条件が false だった場合の代替 UI を表します。\n\n```html\n<p *if=\"loggedIn\">Welcome</p>\n<p *else>Please log in</p>\n```\n\nこの2つは1つの chain です。\n\n- `loggedIn` が truthy なら、最初の branch が描画されます。\n- `loggedIn` が falsy なら、`*else` branch が描画されます。\n\n`*else` は、直前の chain に属するため、無関係な要素を間に挟むと chain が分断される可能性があります。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"loggedIn\": false}'>\n  <p *if=\"loggedIn\">Welcome back.</p>\n  <p *else>Please log in.</p>\n</serc-rod>\n```\n\n`loggedIn` が false のため、`Please log in.` が描画されます。\n\n#### 挙動\n\n基本規則:\n\n- `*else` は、同じ parent 内の `*if` / `*elseif` chain に続く branch として扱われます。\n- 属性値は評価されません。\n- chain の前の branch がどれも選ばれなかった場合にだけ描画されます。\n- chain の前の branch が選ばれた場合、`*else` は描画されません。\n- `*else` は chain の head にはなれません。対応する `*if` が必要です。\n\n`n-else` は `*else` と同じ alias です。\n\n#### 評価タイミング\n\n`*else` は自分の式を評価しません。\n\nSercrod は chain の head である `*if` を見つけ、その後に続く `*elseif` と `*else` をまとめて扱います。\n\n1. `*if` の条件を評価します。\n2. false であれば、後続の `*elseif` 条件を順に評価します。\n3. どれも選ばれなければ、`*else` があればその branch を選びます。\n4. 選ばれた branch だけが描画されます。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst chain = collectIfChain(headIfElement);\n\nfor(const branch of chain){\n        if(branch.type === \"if\" || branch.type === \"elseif\"){\n                if(evaluate(branch.condition, scope)){\n                        render(branch);\n                        return;\n                }\n        } else if(branch.type === \"else\"){\n                render(branch);\n                return;\n        }\n}\n```\n\n`*else` は条件を持たない最後の fallback です。\n\n#### 変数の作成\n\n`*else` は変数を作りません。\n\n- 新しい scope name を追加しません。\n- host data を変更しません。\n- `$data`、`$root`、`$parent` を作りません。\n\nbranch が描画される場合、branch 内の通常の directives がそれぞれの規則で処理されます。\n\n#### スコープの重なり\n\n`*else` 自体は scope を変更しません。\n\nbranch 内では、現在の scope がそのまま使われます。\n\n`*let` を branch 内に置けば、その branch の中だけで local values を作れます。\n\n#### 親へのアクセス\n\nnested host 内で `$parent` が利用できる場合、`*else` branch 内の式から参照できます。\n\n`*else` 自体は `$parent` を直接扱いません。\n\n#### conditionals and loops との併用\n\n`*else` は condition chain の一部です。\n\n```html\n<p *if=\"score >= 80\">Great</p>\n<p *elseif=\"score >= 60\">Good</p>\n<p *else>Try again</p>\n```\n\nloop 内でも使えます。\n\n```html\n<div *for=\"item of items\">\n  <span *if=\"item.visible\">%item.name%</span>\n  <span *else>Hidden</span>\n</div>\n```\n\n各 iteration ごとに chain が評価されます。\n\n#### 推奨される使い方\n\n- `*if` / `*elseif` / `*else` は連続して置きます。\n- `*else` に条件式を書かないでください。\n- 条件が必要な branch には `*elseif` を使います。\n- chain が長すぎる場合は、`*switch` も検討します。\n- `*else` は fallback として読みやすい内容にします。\n\n#### 例\n\n##### 同じ親内の複数 chain\n\n```html\n<p *if=\"user\">User: %user.name%</p>\n<p *else>No user</p>\n\n<p *if=\"error\">Error: %error.message%</p>\n<p *else>No error</p>\n```\n\nこの場合、2つの separate chains です。\n\n##### 混在 prefix での `n-else` の使用\n\n```html\n<p *if=\"ready\">Ready</p>\n<p n-else>Not ready</p>\n```\n\n`n-else` は `*else` と同じです。ただし、同じ project 内では表記を統一する方が読みやすくなります。\n\n#### 注意点\n\n- `*else` と `n-else` は同じ挙動です。\n- `*else` は式を評価しません。\n- 対応する `*if` / `*elseif` chain が必要です。\n- 選ばれた branch だけが描画されます。\n",
  "elseif": "### *elseif\n\n#### 概要\n\n`*elseif` は、`*if` chain に追加の条件 branch を作るディレクティブです。\n\n`*if` が false の場合に、後続の `*elseif` 条件が順に評価されます。最初に truthy になった branch だけが描画されます。\n\nalias の `n-elseif` も同じ挙動です。\n\n#### 説明\n\n`*elseif` は単独の独立した condition ではありません。\n\n常に直前の `*if` chain に属します。\n\n```html\n<p *if=\"score >= 90\">Excellent</p>\n<p *elseif=\"score >= 70\">Good</p>\n<p *elseif=\"score >= 50\">Pass</p>\n<p *else>Retry</p>\n```\n\nこの chain では、最初に条件を満たした branch だけが描画されます。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"score\": 72}'>\n  <p *if=\"score >= 90\">Excellent</p>\n  <p *elseif=\"score >= 70\">Good</p>\n  <p *elseif=\"score >= 50\">Pass</p>\n  <p *else>Retry</p>\n</serc-rod>\n```\n\n`score` は 72 なので、`score >= 70` が最初に truthy になり、`Good` が描画されます。\n\n#### 挙動\n\n##### chain の形成 - *elseif が *if に接続される仕組み\n\nSercrod は、`*if` を chain の head として扱い、その直後に続く `*elseif` / `n-elseif` / `*else` / `n-else` を同じ chain として集めます。\n\n`*elseif` は chain の途中 branch です。\n\n対応する `*if` がない `*elseif` は、有効な chain になりません。\n\n##### 先頭だけの評価\n\ncondition chain は、head である `*if` の処理中にまとめて評価されます。\n\n各 `*elseif` が独立して通常 rendering pass を開始するのではありません。\n\nこのため、chain の構造が崩れると意図した分岐になりません。\n\n##### chain の収集\n\nSercrod は同じ parent 内で連続する conditional siblings を集めます。\n\n```html\n<p *if=\"a\">A</p>\n<p *elseif=\"b\">B</p>\n<p *else>C</p>\n```\n\nこれは1つの chain です。\n\n無関係な要素を間に挟むと、chain がそこで終わる可能性があります。\n\n##### branch 選択と *elseif 条件\n\nbranch 選択は上から順に行われます。\n\n1. `*if` condition を評価します。\n2. false なら、最初の `*elseif` condition を評価します。\n3. false なら、次の `*elseif` condition を評価します。\n4. どれも truthy でなければ、`*else` があればそれを選びます。\n\n最初に truthy になった branch だけが描画されます。\n\n##### 選択された branch の描画\n\n選ばれた branch は clone され、通常の Sercrod rendering pipeline で描画されます。\n\n選ばれなかった branch の children は描画されません。\n\n##### n-elseif について\n\n`n-elseif` は `*elseif` の alias です。\n\n```html\n<p *if=\"a\">A</p>\n<p n-elseif=\"b\">B</p>\n<p *else>C</p>\n```\n\n表記は混在できますが、project 内では統一する方が読みやすいです。\n\n#### 評価タイミング\n\n`*elseif` の条件は、`*if` chain が評価されるときに評価されます。\n\n`*elseif` element に到達したときに単独で評価されるのではなく、chain head の `*if` からまとめて処理されます。\n\n評価は DOM 順です。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst chain = collectChainStartingAtIf(head);\n\nfor(const branch of chain){\n        if(branch.type === \"if\" || branch.type === \"elseif\"){\n                if(evaluate(branch.expression, scope)){\n                        render(branch);\n                        break;\n                }\n        } else if(branch.type === \"else\"){\n                render(branch);\n                break;\n        }\n}\n```\n\n#### 変数の作成\n\n`*elseif` は変数を作りません。\n\nbranch が選ばれた場合、その branch 内の `*let` やその他の directives が通常どおり実行されます。\n\n#### スコープの重なり\n\n`*elseif` の条件式は、現在の scope で評価されます。\n\nbranch が選ばれた場合、その branch の children も同じ scope から描画されます。\n\nancestor `*let` values、loop variables、host data、methods は、scope に存在すれば使えます。\n\n#### 親へのアクセス\n\nnested host で `$parent` が利用できる場合、`*elseif` condition から参照できます。\n\n```html\n<p *elseif=\"$parent.mode === 'edit'\">Edit mode</p>\n```\n\nただし、parent data への依存は template の読みやすさに影響するため、必要な場合に限ります。\n\n#### conditionals and loops との併用\n\n`*elseif` は `*if` / `*else` と組み合わせます。\n\nloop 内の例です。\n\n```html\n<div *for=\"item of items\">\n  <span *if=\"item.status === 'ok'\">OK</span>\n  <span *elseif=\"item.status === 'warn'\">Warning</span>\n  <span *else>Other</span>\n</div>\n```\n\n各 iteration で chain が評価されます。\n\n#### 推奨される使い方\n\n- `*if`、`*elseif`、`*else` を連続した siblings として置きます。\n- `*elseif` を chain の最初に置かないでください。\n- 条件は短く読みやすくします。\n- branch が多い場合は `*switch` の方が読みやすい場合があります。\n- `n-elseif` と `*elseif` の表記は project 内で統一します。\n\n#### 例\n\n##### 例1 - 複数 mode の表示\n\n```html\n<p *if=\"mode === 'view'\">View</p>\n<p *elseif=\"mode === 'edit'\">Edit</p>\n<p *elseif=\"mode === 'preview'\">Preview</p>\n<p *else>Unknown mode</p>\n```\n\n##### 例2 - branch 内だけの *let\n\n```html\n<div *if=\"user\" *let=\"label = user.name\">\n  %label%\n</div>\n<div *elseif=\"guest\">\n  Guest\n</div>\n<div *else>\n  Anonymous\n</div>\n```\n\n`*let` は選ばれた branch 内でだけ意味を持ちます。\n\n##### 例3 - 不正な chain の回避\n\n避ける例です。\n\n```html\n<p *if=\"a\">A</p>\n<hr>\n<p *elseif=\"b\">B</p>\n```\n\n`hr` が chain を分断する可能性があります。\n\n推奨:\n\n```html\n<p *if=\"a\">A</p>\n<p *elseif=\"b\">B</p>\n```\n\n#### 注意点\n\n- `*elseif` と `n-elseif` は同じ挙動です。\n- `*elseif` は `*if` chain の一部です。\n- 最初に truthy になった branch だけが描画されます。\n- 独立した条件として使いたい場合は、別の `*if` を使います。\n",
  "event-blur": "### @blur\n\n#### 概要\n\n`@blur` は、要素の native `blur` event に Sercrod expression を接続します。\n\nこの event は、要素が focus を失ったときに発生します。典型的には、入力欄を離れたタイミングで値を確定したり、検証を実行したり、focus state を解除したりするために使います。\n\n`@blur` は `@click`、`@input`、`@change` などと同じ event handler family の一部です。属性値には Sercrod expression を書き、event 発生時に現在の scope で評価されます。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"name\":\"\",\"touched\":false}'>\n  <input\n    type=\"text\"\n    *input=\"name\"\n    @blur=\"touched = true\">\n\n  <p *if=\"touched && !name\">Name is required.</p>\n</serc-rod>\n```\n\nこの例では、input が focus を失うと `touched` が `true` になります。`name` が空であれば、エラーメッセージが表示されます。\n\n#### 挙動\n\n`@blur` は、対象要素に `blur` event listener を取り付けます。\n\n基本規則:\n\n- 属性名は event prefix `@` と event name `blur` から成ります。\n- 属性値は Sercrod expression として評価されます。\n- expression は event が発生したときに実行されます。\n- `$event` と `$e` は native event object を指します。\n- `el` と `$el` は event handler を宣言した要素を指します。\n- expression 実行後、通常の update flow により host が再描画されます。\n\n`blur` は browser の native focus event です。一般的に bubbling しません。そのため、親要素に置いて子要素の blur をまとめて拾う用途には向きません。必要な要素に直接書くのが基本です。\n\n#### 評価タイミング\n\n`@blur` の expression は、要素が focus を失ったタイミングで評価されます。\n\n大まかな流れは次の通りです。\n\n1. Sercrod が template を描画します。\n2. `@blur` を持つ要素に `blur` listener を取り付けます。\n3. user がその要素に focus します。\n4. user が別の要素へ移動するなどして、その要素が focus を失います。\n5. `blur` event が発生します。\n6. `@blur` expression が現在の scope で評価されます。\n7. expression 実行後、host の update が行われます。\n\n`@blur` は入力値が変わったかどうかに関係なく、focus を失ったときに発生します。値の変化そのものを見たい場合は `@change` や `@input` を使います。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nelement.addEventListener(\"blur\", (event)=>{\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: element,\n                $el: element\n        });\n\n        evaluate(blurExpression, scope);\n        host.update();\n});\n```\n\n実際の runtime は、event modifiers、error handling、update scheduling、stage handling などを含みます。\n\n#### form fields and data bindings との併用\n\n`@blur` は `*input` とよく組み合わせます。\n\n```html\n<input\n  type=\"email\"\n  *input=\"email\"\n  @blur=\"emailTouched = true\">\n```\n\nこの pattern では、入力値の管理は `*input` が行い、focus を離れたかどうかの状態は `@blur` が記録します。\n\n`*lazy` と組み合わせると、入力欄を離れるタイミングで値の確定や表示更新を扱いやすくなります。\n\n```html\n<input\n  type=\"text\"\n  *input=\"title\"\n  *lazy\n  @blur=\"titleTouched = true\">\n```\n\nこの場合、`@blur` は focus timing の side effect を表します。値の書き戻し timing は `*input` / `*lazy` 側の規則に従います。\n\n#### conditionals and loops との併用\n\n`@blur` は `*for` や `*each` の中でも使えます。\n\n```html\n<input\n  *for=\"field of fields\"\n  :value=\"field.value\"\n  @blur=\"field.touched = true\">\n```\n\n各 iteration では、`field` が現在の scope に入ります。`field.touched = true` は、その item object を変更します。\n\n条件付き rendering と組み合わせる場合は、blur によって data が変わったあと、その要素が再描画で消える可能性に注意します。\n\n```html\n<input\n  *if=\"editing\"\n  *input=\"name\"\n  @blur=\"editing = false\">\n```\n\nこの例では、blur すると `editing` が false になり、input 自体が表示されなくなることがあります。\n\n#### Sercrod 固有の制限\n\n- `@blur` は native `blur` event を扱います。\n- `blur` は一般的に bubbling しないため、delegation 的な使い方には向きません。\n- `@blur` expression は短く保ちます。複雑な処理は method に移します。\n- `@blur` は value binding そのものではありません。値の書き戻しには `*input` を使います。\n- `@blur` で form submission や network request を直接複雑に扱うより、button、`@submit`、`*api` などと責務を分ける方が分かりやすくなります。\n\n#### 推奨される使い方\n\n- touched / visited / editing state の更新に使います。\n- 入力確定後の軽い検証に使います。\n- `@blur` だけで入力値を管理しようとせず、`*input` と組み合わせます。\n- form 全体の submit 処理には `@submit` を使います。\n- blur によって要素が消える UI では、次に focus される要素や click timing に注意します。\n\n#### 追加例\n\nFocus state を解除する例です。\n\n```html\n<input\n  @focus=\"focused = true\"\n  @blur=\"focused = false\">\n```\n\nfield 単位で touched flag を立てる例です。\n\n```html\n<input\n  *for=\"field of fields\"\n  *input=\"field.value\"\n  @blur=\"field.touched = true\">\n```\n\nmethod を呼ぶ例です。\n\n```html\n<input\n  *input=\"email\"\n  @blur=\"validateEmail(email)\">\n```\n\n#### 注意点\n\n- `@blur` は data-to-DOM binding ではなく event binding です。\n- event 発生時に expression を評価します。\n- `blur` は focus を失ったときに発生します。\n- 値が変わったかどうかとは別の概念です。\n",
  "event-change": "### @change\n\n#### 概要\n\n`@change` は、要素の native `change` event に Sercrod expression を接続します。\n\nこの event は、form control の値が user によって変更され、その変更が browser によって確定したときに発生します。text input では focus を離れたとき、select や checkbox では選択が変わったときなど、control type によって timing が異なります。\n\n`@change` は、`@click`、`@input`、`@blur` などと同じ event handler family の一部です。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"country\":\"jp\",\"changed\":false}'>\n  <select *input=\"country\" @change=\"changed = true\">\n    <option value=\"jp\">Japan</option>\n    <option value=\"us\">United States</option>\n  </select>\n\n  <p *if=\"changed\">Country changed to %country%</p>\n</serc-rod>\n```\n\nこの例では、select の選択が変わると `changed` が `true` になります。`*input` によって `country` も更新されます。\n\n#### 挙動\n\n`@change` は、対象要素に `change` event listener を取り付けます。\n\n基本規則:\n\n- 属性値は Sercrod expression として評価されます。\n- expression は `change` event が発生したときに実行されます。\n- `$event` と `$e` は native event object を指します。\n- `el` と `$el` は event handler を宣言した要素を指します。\n- expression 実行後、通常の update flow により host が再描画されます。\n\n`@change` 自体は入力値を data に書き戻すものではありません。値の binding は `*input` / `n-input` が担当します。\n\n#### 評価タイミング\n\n`@change` の timing は control type に依存します。\n\n一般的な例:\n\n- text input:\n  - user が値を編集し、focus を離れたときに change が発生することが多いです。\n- textarea:\n  - text input と同様に、編集確定時に発生します。\n- select:\n  - 選択が変わったときに発生します。\n- checkbox / radio:\n  - checked state が変わったときに発生します。\n- file input:\n  - file selection が変わったときに発生します。\n\nSercrod は native event を受け取るため、この timing は browser の標準挙動に従います。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nelement.addEventListener(\"change\", (event)=>{\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: element,\n                $el: element\n        });\n\n        evaluate(changeExpression, scope);\n        host.update();\n});\n```\n\n実際の runtime は、error handling、stage handling、event modifiers、update scheduling などを含みます。\n\n#### @change 後の更新挙動\n\n`@change` expression の実行後、Sercrod は通常の update flow に入ります。\n\nこれは、expression が data を変更した場合、その変更を UI に反映するためです。\n\n```html\n<select @change=\"selected = $event.target.value\">\n```\n\nこのように書くと、change 後に `selected` が更新され、その値を読む他の表示も再描画されます。\n\nただし、form control の値そのものを data に戻す用途では、`*input` を使う方が一貫しています。\n\n```html\n<select *input=\"selected\" @change=\"changed = true\">\n```\n\nこの形では、値の同期と side effect の役割が分かれます。\n\n#### form fields and data bindings との併用\n\n`@change` は、値の確定後に実行したい処理に向いています。\n\n例:\n\n```html\n<input\n  type=\"text\"\n  *input=\"name\"\n  @change=\"nameChanged = true\">\n```\n\n```html\n<select\n  *input=\"category\"\n  @change=\"loadCategory(category)\">\n</select>\n```\n\n`*input` は data path を更新します。`@change` は追加の action や flag 更新を行います。\n\n#### conditionals and loops との併用\n\nloop 内でも使えます。\n\n```html\n<select\n  *for=\"row of rows\"\n  *input=\"row.status\"\n  @change=\"row.dirty = true\">\n</select>\n```\n\n各 row の select が変更されると、その row object の `dirty` が true になります。\n\n条件付き rendering と組み合わせる場合、change によって表示対象が変わる可能性があります。\n\n#### Sercrod 固有の制限\n\n- `@change` は native `change` event を扱います。\n- 値の書き戻しには `*input` を使うのが基本です。\n- `@change` expression は短く保ちます。\n- heavy な network action を直接 `@change` に書くより、method や `*api` と組み合わせて責務を分けます。\n- control type によって event timing が異なることを前提にします。\n\n#### 推奨される使い方\n\n- 値が確定したタイミングで flag を立てる用途に使います。\n- select、checkbox、radio、file input と相性がよいです。\n- text input の逐次更新には `@input` や `*eager` を使います。\n- value binding は `*input` に任せ、`@change` は side effect に使います。\n- browser の native change timing に依存することを明示的に意識します。\n\n#### 追加例\n\ncheckbox 状態:\n\n```html\n<input\n  type=\"checkbox\"\n  *input=\"accepted\"\n  @change=\"acceptedChanged = true\">\n```\n\nfile input の例:\n\n```html\n<input\n  type=\"file\"\n  @change=\"selectedFileName = $event.target.files[0]?.name || ''\">\n```\n\nmethod を使う select:\n\n```html\n<select *input=\"category\" @change=\"refreshItems(category)\">\n</select>\n```\n\n#### 注意点\n\n- `@change` は event binding です。\n- `change` event の timing は form control type によって異なります。\n- 値の同期は `*input` に任せる方が分かりやすいです。\n- `@input` は入力中、`@change` は変更確定後、という使い分けが基本です。\n",
  "event-click": "### @click\n\n#### 概要\n\n`@click` は、要素の native `click` event に Sercrod expression を接続します。\n\nbutton、link、card、toggle、action control など、user が click して何かを実行する UI に使います。\n\n`@click` は Sercrod の event handler family の中心的な directive です。式は click event が発生したときに現在の scope で評価され、data を更新した場合は通常の update flow によって UI が再描画されます。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"count\":0}'>\n  <button type=\"button\" @click=\"count = count + 1\">\n    Count: %count%\n  </button>\n</serc-rod>\n```\n\nbutton を click するたびに `count` が増え、表示が更新されます。\n\n#### event と要素へのアクセス\n\n`@click` expression では、event と要素を参照できます。\n\n- `$event` - native click event。\n- `$e` - `$event` の短い alias。\n- `el` - event handler を宣言した要素。\n- `$el` - `el` の alias。\n\n例:\n\n```html\n<button\n  type=\"button\"\n  @click=\"lastClicked = $event.target.textContent\">\n  Save\n</button>\n```\n\nevent object が必要ない場合は、data assignment だけを書くのが読みやすいです。\n\n#### 挙動\n\n基本規則:\n\n- Sercrod は `@click` を持つ要素に click listener を取り付けます。\n- 属性値は Sercrod expression として評価されます。\n- expression は click event 発生時に実行されます。\n- expression の中では現在の scope、event、要素を参照できます。\n- 実行後、host は通常の update flow に入ります。\n\n`@click` は native click event を使います。keyboard activation で click が発生する button などでは、browser の標準挙動に従って動きます。\n\n#### 評価タイミングと再描画\n\n`@click` は user interaction によって発火します。\n\n大まかな流れ:\n\n1. template が描画されます。\n2. `@click` element に listener が接続されます。\n3. user が element を click します。\n4. expression が評価されます。\n5. data が変更された場合、再描画で UI に反映されます。\n\nclick 後の再描画によって、click された要素自体が作り直されることがあります。これは Sercrod の通常の rendering flow です。\n\n#### button・link・その他 control との併用\n\naction-only behavior には、通常 `button type=\"button\"` を使います。\n\n```html\n<button type=\"button\" @click=\"open = !open\">Toggle</button>\n```\n\nlink navigation が目的なら `a` と `:href` を使います。\n\n```html\n<a :href=\"url\">Open</a>\n```\n\n`a` を action として使う場合は、browser navigation を止めるために `.prevent` または `*prevent-default` を明示する必要があります。\n\n```html\n<a href=\"#\" @click.prevent=\"open = true\">Open</a>\n```\n\n#### フォームと送信との併用\n\nform の submit 処理には、通常 `@submit` を使います。\n\n`@click` は button 単体の action に向いています。\n\n```html\n<button type=\"button\" @click=\"draft = true\">Save draft</button>\n```\n\nsubmit button に `@click` を置くと、click handler と form submit の両方が関わるため、timing が複雑になる場合があります。form 全体の送信制御は `@submit` に寄せる方が分かりやすくなります。\n\n#### 修飾子\n\nSercrod の event attributes は modifiers を持てます。\n\n代表例:\n\n- `.prevent`\n- `.preventDefault`\n- `.stop`\n- `.once`\n\n実際に利用可能な modifiers は runtime 設定と event pipeline に依存します。\n\n例:\n\n```html\n<a href=\"/fallback\" @click.prevent=\"open = true\">Open modal</a>\n```\n\n`.prevent` は event の default behavior を抑止します。\n\n#### conditionals and loops との併用\n\nloop 内で使う例です。\n\n```html\n<button\n  *for=\"item of items\"\n  type=\"button\"\n  @click=\"selected = item\">\n  Select %item.name%\n</button>\n```\n\n各 button の expression は、その iteration の `item` を参照できます。\n\n条件付き rendering と組み合わせる例です。\n\n```html\n<button *if=\"canDelete\" type=\"button\" @click=\"deleteItem(item)\">\n  Delete\n</button>\n```\n\n#### 推奨される使い方\n\n- action-only UI には `button type=\"button\"` を使います。\n- navigation には `a :href` を使います。\n- expression は短く保ち、複雑な処理は method に移します。\n- form submission の主制御には `@submit` を使います。\n- `a href=\"#\"` を使う場合は `.prevent` を明示します。\n- data path の変更は template 内の表示 path と一致させます。\n\n#### 追加例\n\ntoggle の例:\n\n```html\n<button type=\"button\" @click=\"open = !open\">\n  Toggle\n</button>\n```\n\nmethod 呼び出し:\n\n```html\n<button type=\"button\" @click=\"save(form)\">\n  Save\n</button>\n```\n\nloop item selection の例:\n\n```html\n<li *for=\"item of items\">\n  <button type=\"button\" @click=\"selectedId = item.id\">\n    %item.name%\n  </button>\n</li>\n```\n\nlink navigation の抑止:\n\n```html\n<a href=\"/fallback\" @click.prevent=\"showModal = true\">\n  Show modal\n</a>\n```\n\n#### 注意点\n\n- `@click` は native click event を扱います。\n- expression は event 発生時に評価されます。\n- data を変更すると、通常は host が再描画されます。\n- action-only control には `button` が最も分かりやすいです。\n",
  "event-focus": "### @focus\n\n#### 概要\n\n`@focus` は、要素の native `focus` event に Sercrod expression を接続します。\n\n要素が focus を受け取ったときに、focus state を記録したり、補助 UI を表示したり、入力開始の状態を作るために使います。\n\n`@focus` は `@blur` と対になることが多く、field highlighting、editing state、validation state などに利用できます。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"focused\":false}'>\n  <input\n    type=\"text\"\n    @focus=\"focused = true\"\n    @blur=\"focused = false\">\n\n  <p *if=\"focused\">Input is focused.</p>\n</serc-rod>\n```\n\ninput が focus を受け取ると `focused` が true になり、focus を失うと false になります。\n\n#### 挙動\n\n`@focus` は対象要素に `focus` event listener を取り付けます。\n\n基本規則:\n\n- 属性値は Sercrod expression として評価されます。\n- expression は focus event 発生時に実行されます。\n- `$event` / `$e` は native event object です。\n- `el` / `$el` は handler を宣言した要素です。\n- expression 実行後、通常の update flow に入ります。\n\n`focus` は native focus event であり、通常は bubbling しません。親要素で子要素の focus をまとめて扱いたい場合は、native `focusin` event の方が適している場合があります。ただし Sercrod の専用 entry がない event では fallback event binding として扱われます。\n\n#### 評価タイミング\n\n`@focus` の expression は、要素が focus を受け取ったときに評価されます。\n\n1. Sercrod が element を描画します。\n2. `@focus` listener が取り付けられます。\n3. user が click、Tab 移動、script などで要素に focus します。\n4. native focus event が発生します。\n5. expression が現在の scope で評価されます。\n6. 必要に応じて host が再描画されます。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nelement.addEventListener(\"focus\", (event)=>{\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: element,\n                $el: element\n        });\n\n        evaluate(focusExpression, scope);\n        host.update();\n});\n```\n\n#### フォーム項目と UI 状態との併用\n\n`@focus` は、入力補助 UI と相性がよいです。\n\n```html\n<label>\n  Email\n  <input\n    type=\"email\"\n    *input=\"email\"\n    @focus=\"activeField = 'email'\"\n    @blur=\"activeField = null\">\n</label>\n\n<p *if=\"activeField === 'email'\">\n  We will never share your email.\n</p>\n```\n\nfield ごとの help text、highlight、editing indicator などに使えます。\n\n#### conditionals and loops との併用\n\nloop 内でも使えます。\n\n```html\n<input\n  *for=\"field of fields\"\n  :value=\"field.value\"\n  @focus=\"activeField = field.name\">\n```\n\n各 field が focus されたとき、その field name を記録できます。\n\n条件付き rendering と組み合わせる場合、focus によって DOM が再描画され、その要素自体が作り直される可能性があります。focus の維持が重要な UI では、更新範囲や `*lazy` の利用を検討します。\n\n#### Sercrod 固有の注意点と制限\n\n- `@focus` は value binding ではありません。\n- 入力値の書き戻しには `*input` を使います。\n- `focus` は通常 bubbling しません。\n- focus event で大きな redraw を発生させると、focus が動く場合があります。\n- expression は短くし、複雑な処理は method に移します。\n\n#### 推奨される使い方\n\n- focus state、active field、help text の表示に使います。\n- `@blur` と組み合わせて状態を戻します。\n- 入力値の管理は `*input` と分けます。\n- focus によって対象要素が消えるような UI では注意します。\n- 多数の input がある場合は、active field name を data に持つと扱いやすくなります。\n\n#### 追加例\n\nactive field の例:\n\n```html\n<input @focus=\"active = 'name'\" @blur=\"active = null\">\n```\n\nhelp text の例:\n\n```html\n<input @focus=\"showHelp = true\" @blur=\"showHelp = false\">\n<p *if=\"showHelp\">Enter your full name.</p>\n```\n\nloop field focus の例:\n\n```html\n<input\n  *for=\"row of rows\"\n  @focus=\"focusedRow = row.id\">\n```\n\n#### 注意点\n\n- `@focus` は native focus event を扱います。\n- focus を受け取ったときに expression を評価します。\n- `@blur` と対で使うことが多いです。\n- data binding そのものではありません。\n",
  "event-input": "### @input\n\n#### 概要\n\n`@input` は、要素の native `input` event に Sercrod expression を接続します。\n\n`input` event は、text input、textarea、range、その他の form controls で、値が入力中に変化したときに発生します。\n\n`@input` は、入力中の side effect、live validation、manual value handling などに使えます。ただし、値を data path へ同期する基本機能には、通常 `*input` / `n-input` を使います。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"message\":\"\",\"length\":0}'>\n  <textarea\n    *input=\"message\"\n    @input=\"length = $event.target.value.length\">\n  </textarea>\n\n  <p>%length% characters</p>\n</serc-rod>\n```\n\nこの例では、`*input` が `message` を更新し、`@input` が文字数を更新します。\n\n#### 挙動\n\n`@input` は対象要素に native `input` listener を取り付けます。\n\n基本規則:\n\n- 属性値は Sercrod expression として評価されます。\n- expression は input event 発生時に実行されます。\n- `$event` / `$e` は native event object です。\n- `el` / `$el` は handler を宣言した要素です。\n- expression 実行後、通常の update flow に入ります。\n\n`@input` は high-frequency event です。user が文字を入力するたびに発生する場合があります。そのため、重い処理を直接書くのは避けます。\n\n#### 評価タイミング\n\n`@input` の expression は、native input event のタイミングで評価されます。\n\n1. user が form control の値を変更します。\n2. browser が input event を dispatch します。\n3. `@input` expression が評価されます。\n4. data が変更されれば、UI が更新されます。\n\ntext input では、keydown ごとに発生することがあります。ただし IME や browser の挙動により、実際の timing は入力方式によって異なります。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nelement.addEventListener(\"input\", (event)=>{\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: element,\n                $el: element\n        });\n\n        evaluate(inputExpression, scope);\n        host.update();\n});\n```\n\n実際の runtime は `*input`、`*lazy`、`*eager` などの input handling と組み合わされる場合があります。\n\n#### form fields and data bindings との併用\n\n値の書き戻しは、通常 `*input` で行います。\n\n```html\n<input type=\"text\" *input=\"name\">\n```\n\n入力中に追加処理をしたい場合に `@input` を足します。\n\n```html\n<input\n  type=\"text\"\n  *input=\"name\"\n  @input=\"dirty = true\">\n```\n\nlive update を明示したい場合は、`*eager` を使います。\n\n```html\n<input type=\"search\" *input=\"q\" *eager>\n```\n\n`@input` は、`*input` の代替ではなく、追加の event side effect として考える方が分かりやすいです。\n\n#### conditionals and loops との併用\n\nloop 内で使えます。\n\n```html\n<input\n  *for=\"row of rows\"\n  *input=\"row.name\"\n  @input=\"row.dirty = true\">\n```\n\n入力のたびに、対象 row の `dirty` が true になります。\n\n条件付き rendering と組み合わせる場合、入力による再描画で focus や caret position に影響が出る場合があります。type-then-action flow では `*lazy`、live preview では `*eager` を検討します。\n\n#### Sercrod 固有の制限\n\n- `@input` は high-frequency event です。\n- heavy processing や network request を直接書くのは避けます。\n- data path への基本的な書き戻しには `*input` を使います。\n- `@input` と `*input` が同じ data を別々に書くと、timing が分かりにくくなる場合があります。\n- IME 入力や composition timing は browser の native input behavior に従います。\n\n#### 推奨される使い方\n\n- `*input` と組み合わせて、dirty flag や validation flag を更新します。\n- live search / live preview には `*eager` を検討します。\n- type-then-submit には `*lazy` を検討します。\n- expression は短く保ちます。\n- 複雑な validation は method に移します。\n\n#### 追加例\n\ndirty flag の例:\n\n```html\n<input *input=\"title\" @input=\"dirty = true\">\n```\n\n文字数 counter:\n\n```html\n<textarea\n  *input=\"body\"\n  @input=\"count = $event.target.value.length\">\n</textarea>\n```\n\nlive method の例:\n\n```html\n<input\n  type=\"search\"\n  *input=\"q\"\n  @input=\"filter(q)\">\n```\n\n#### 注意点\n\n- `@input` は native input event を扱います。\n- 値の同期には通常 `*input` を使います。\n- high-frequency event なので軽く保ちます。\n- `*lazy` / `*eager` とあわせて timing を設計します。\n",
  "event-keydown": "### @keydown\n\n#### 概要\n\n`@keydown` は、要素の native `keydown` event に Sercrod expression を接続します。\n\nkey が押された瞬間に発生するため、keyboard shortcuts、arrow-key movement、Enter action、Escape close、Ctrl / Shift combinations などに向いています。\n\nSercrod の `@keydown` は通常の event binding であると同時に、keyboard-specific syntax を持ちます。\n\n例:\n\n```html\n<div tabindex=\"0\" @keydown.arrowup.prevent=\"y = y - 1\"></div>\n```\n\n`.arrowup` は key condition、`.prevent` は default behavior の抑止を表します。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"x\":0,\"y\":0}'>\n  <div\n    tabindex=\"0\"\n    @keydown.arrowleft.prevent=\"x = x - 1\"\n    @keydown.arrowright.prevent=\"x = x + 1\"\n    @keydown.arrowup.prevent=\"y = y - 1\"\n    @keydown.arrowdown.prevent=\"y = y + 1\">\n    Use arrow keys.\n  </div>\n\n  <p>x: %x%, y: %y%</p>\n</serc-rod>\n```\n\nこの例では、focus された `div` が arrow keys を受け取り、`x` と `y` を更新します。\n\n#### 挙動\n\n基本規則:\n\n- `@keydown` は native `keydown` event listener を取り付けます。\n- 属性値は keydown 時に Sercrod expression として評価されます。\n- `$event` / `$e` は native keyboard event です。\n- `el` / `$el` は handler を宣言した要素です。\n- key condition がある場合、条件に一致したときだけ expression が実行されます。\n- expression 実行後、通常の update flow に入ります。\n- `.window` がある場合は、listener は element ではなく `window` に取り付けられます。\n\n`@keydown` は key が押されている間に repeat することがあります。repeat を避けたい場合は `$event.repeat` を確認します。\n\n#### event 修飾子\n\n`@keydown` は通常の event modifiers を使えます。\n\n代表例:\n\n- `.prevent`\n- `.preventDefault`\n- `.stop`\n- `.once`\n- `.window`\n\n`.prevent` と `.preventDefault` は同義です。推奨表記は `.prevent` です。\n\n```html\n<div tabindex=\"0\" @keydown.enter.prevent=\"submit()\"></div>\n```\n\n`preventDefault()` は、key condition が一致した場合にだけ実行されるべきです。たとえば `@keydown.arrowup.prevent` は ArrowUp の default behavior だけを抑止します。\n\n#### keyboard 固有の構文\n\nkey name は modifier として書けます。\n\n```html\n@keydown.enter\n@keydown.escape\n@keydown.arrowup\n@keydown.arrowdown\n@keydown.arrowleft\n@keydown.arrowright\n```\n\nkey names は大文字小文字を区別せずに照合します。公式の `KeyboardEvent.key` names である `ArrowUp`、`Enter`、`Escape`、`Shift` なども受け入れます。\n\n推奨表記は lowercase です。\n\nmodifier key combinations は `+` で書きます。\n\n```html\n@keydown.arrowup+shift\n@keydown.shift+arrowup\n@keydown.s+ctrl\n@keydown.enter+ctrl+shift\n```\n\ncombination 内の order は意味を持ちません。`arrowup+shift` と `shift+arrowup` は同じ条件として扱います。\n\n初期仕様では、`a+b` のような non-modifier keys 同士の任意の組み合わせは support しません。これは true multi-key state management が必要になるためです。そのような指定は `[Sercrod warn]` を出すべきです。\n\n#### window key 宣言\n\n`.window` を付けると、key event は `window` で監視されます。\n\n```html\n<div\n  @keydown.window.escape=\"open = false\"\n  @keydown.window.arrowup.prevent=\"y = y - 1\">\n</div>\n```\n\nこの場合、属性を書いた element は declaration location です。実際の event target ではありません。\n\n- listener は `window` に取り付けられます。\n- expression は直近の `<serc-rod>` host の context で実行されます。\n- update もその host に閉じます。\n- declaration element が focus を持つ必要はありません。\n\n`input type=\"hidden\"` を invisible declaration location として使うこともできます。\n\n```html\n<input type=\"hidden\" @keydown.window.escape=\"open = false\">\n```\n\n#### 評価タイミング\n\nlocal `@keydown` の場合:\n\n1. element が描画されます。\n2. keydown listener が element に取り付けられます。\n3. element が focus を持っているときに key が押されます。\n4. key condition が確認されます。\n5. 一致すれば modifiers が適用され、expression が評価されます。\n6. host が update されます。\n\n`.window` の場合:\n\n1. declaration element が描画されます。\n2. window listener が登録されます。\n3. window 上で keydown が発生します。\n4. key condition が確認されます。\n5. 一致すれば expression が declaration element の nearest host context で評価されます。\n6. その host が update されます。\n\n#### 実行モデルと更新\n\n概念的には次のような処理です。\n\n```js\ntarget.addEventListener(\"keydown\", (event)=>{\n        if(!matchesKeyCondition(event, modifiers)){\n                return;\n        }\n\n        if(shouldPrevent){\n                event.preventDefault();\n        }\n\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: declarationElement,\n                $el: declarationElement\n        });\n\n        evaluate(expression, scope);\n        host.update();\n});\n```\n\n`target` は、通常は declaration element ですが、`.window` がある場合は `window` です。\n\n`@keydown` による update で、focus 中の element が再描画されることがあります。focus を維持しながら子 host だけを更新したい場合は、project の設計や `*lazy` の利用を検討します。\n\n#### focus 可能な control や form との併用\n\nlocal keydown を使う場合、要素が key events を受け取れる必要があります。\n\n- input、textarea、select、button などは focusable です。\n- div などの通常要素は、必要なら `tabindex=\"0\"` を付けます。\n\n```html\n<div tabindex=\"0\" @keydown.escape=\"open = false\"></div>\n```\n\nform control 上で `.prevent` を使うと、browser の通常の key behavior を止める場合があります。Arrow keys、Enter、Space、Escape などは標準操作と衝突しやすいため、意図が明確なときだけ使います。\n\n#### conditionals and loops との併用\n\nloop 内でも使えます。\n\n```html\n<div\n  *for=\"item of items\"\n  tabindex=\"0\"\n  @keydown.enter=\"selected = item\">\n  %item.name%\n</div>\n```\n\n各 item は自分の scope を持ちます。\n\n`.window` を loop 内に置くと、複数の window listener が登録される可能性があります。window-level shortcut は、通常は host 内の1か所にまとめる方が分かりやすいです。\n\n#### Sercrod 固有の制限\n\n- key names は大文字小文字を区別せずに扱います。\n- `.prevent` と `.preventDefault` は同義です。\n- `.window` は declaration element を event target にしません。\n- arbitrary non-modifier multi-key combinations、たとえば `a+b` は初期仕様では support しません。\n- `.window` listener は owning host が DOM から外れたときに cleanup されるべきです。\n- `keypress` はこの仕様の中心ではありません。shortcuts には `keydown` を使います。\n\n#### 推奨される使い方\n\n- shortcut や movement には `@keydown` を使います。\n- release timing には `@keyup` を使います。\n- key name は lowercase で書きます。\n- `.window` は global shortcut が必要な場合だけ使います。\n- `.prevent` は browser default behavior を意図的に引き受ける場合だけ使います。\n- complex logic は method に移します。\n\n#### 追加例\n\nEscape で閉じる例です。\n\n```html\n<div @keydown.window.escape=\"open = false\"></div>\n```\n\nShift + ArrowUp の例:\n\n```html\n<div tabindex=\"0\" @keydown.arrowup+shift.prevent=\"y = y - 10\"></div>\n```\n\nCtrl + S の例:\n\n```html\n<div @keydown.window.s+ctrl.prevent=\"save()\"></div>\n```\n\nRepeat を無視する例です。\n\n```html\n<div tabindex=\"0\" @keydown.enter=\"if(!$event.repeat) submit()\"></div>\n```\n\n#### 注意点\n\n- `@keydown` は native keydown event を扱います。\n- shortcuts と movement controls では通常 `keydown` を使います。\n- key modifiers と event modifiers は order-independent です。\n- `.window.prevent` は一致した key の default behavior を window level で抑止します。ページスクロールや focus 中 form control の標準 key behavior も止まる場合があります。\n",
  "event-keyup": "### @keyup\n\n#### 概要\n\n`@keyup` は、要素の native `keyup` event に Sercrod expression を接続します。\n\nkey が離されたタイミングで発生するため、release timing、cleanup、key-up 後の検証、押下状態の解除などに向いています。\n\nSercrod の `@keyup` は `@keydown` と同じ keyboard-specific syntax を使えます。ただし、shortcuts や movement controls の主な例では、通常 `@keydown` を使います。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"pressed\":false}'>\n  <input\n    type=\"text\"\n    @keydown.enter=\"pressed = true\"\n    @keyup.enter=\"pressed = false\">\n\n  <p *if=\"pressed\">Enter is down.</p>\n</serc-rod>\n```\n\nこの例では、Enter が押されると `pressed` が true になり、離されると false に戻ります。\n\n#### 挙動\n\n基本規則:\n\n- `@keyup` は native `keyup` event listener を取り付けます。\n- 属性値は keyup 時に Sercrod expression として評価されます。\n- `$event` / `$e` は native keyboard event です。\n- `el` / `$el` は handler を宣言した要素です。\n- key condition がある場合、一致した keyup でだけ expression が実行されます。\n- expression 実行後、通常の update flow に入ります。\n- `.window` がある場合は、listener は `window` に取り付けられます。\n\n`keyup` は key が離されたときに発生します。長押し repeat の中心は `keydown` であり、keyup は release に対して通常1回です。\n\n#### keyboard 固有の構文\n\n`@keyup` は `@keydown` と同じ key syntax を使います。\n\n```html\n@keyup.enter\n@keyup.escape\n@keyup.arrowup\n@keyup.arrowup+shift\n@keyup.s+ctrl\n```\n\nkey names は大文字小文字を区別せずに照合します。`ArrowUp`、`Enter`、`Escape`、`Shift` などの official `KeyboardEvent.key` names も受け入れます。\n\nmodifier-key combinations は `+` で表します。order は意味を持ちません。\n\n```html\n@keyup.arrowup+shift\n@keyup.shift+arrowup\n```\n\n初期仕様では、`a+b` のような arbitrary non-modifier key combinations は support しません。modifier combinations を使います。\n\n#### 評価タイミング\n\nlocal `@keyup` の場合:\n\n1. element が描画されます。\n2. keyup listener が element に取り付けられます。\n3. element が focus を持っている状態で key が離されます。\n4. key condition が確認されます。\n5. 一致すれば expression が評価されます。\n6. host が update されます。\n\n`.window` の場合:\n\n1. declaration element が描画されます。\n2. window keyup listener が登録されます。\n3. window 上で keyup が発生します。\n4. key condition が確認されます。\n5. 一致すれば nearest `<serc-rod>` context で expression が評価されます。\n6. その host が update されます。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\ntarget.addEventListener(\"keyup\", (event)=>{\n        if(!matchesKeyCondition(event, modifiers)){\n                return;\n        }\n\n        if(shouldPrevent){\n                event.preventDefault();\n        }\n\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: declarationElement,\n                $el: declarationElement\n        });\n\n        evaluate(expression, scope);\n        host.update();\n});\n```\n\n`target` は通常 element ですが、`.window` がある場合は `window` です。\n\n#### key data と $event\n\n`@keyup` expression では、native event から key 情報を読めます。\n\n```html\n<input @keyup=\"lastKey = $event.key\">\n```\n\n利用しやすい properties:\n\n- `$event.key`\n- `$event.code`\n- `$event.ctrlKey`\n- `$event.shiftKey`\n- `$event.altKey`\n- `$event.metaKey`\n- `$event.repeat`\n\nkey condition modifier を使う方が読みやすい場合もあります。\n\n```html\n<input @keyup.enter=\"submitted = true\">\n```\n\n#### @keyup の更新挙動\n\n`@keyup` expression が data を変更すると、host は update されます。\n\n```html\n<input @keyup.escape=\"editing = false\">\n```\n\nこの場合、Escape を離したときに `editing` が false になり、関連 UI が再描画されます。\n\nkeyup 後に focus 中の element が再描画で置き換わる場合があります。focus 維持が重要なら、更新範囲や lazy design を検討します。\n\n#### ループや条件分岐との併用\n\nloop 内で使えます。\n\n```html\n<input\n  *for=\"row of rows\"\n  @keyup.enter=\"saveRow(row)\">\n```\n\n各 row の input は、自分の `row` を scope で参照できます。\n\n条件付き rendering と組み合わせる場合、keyup によって要素が消える可能性があります。\n\n```html\n<input\n  *if=\"editing\"\n  @keyup.escape=\"editing = false\">\n```\n\n#### form input と stage 更新との併用\n\ntext input で `@keyup` を使うと、key release timing に合わせて処理できます。\n\nただし、値の data binding は `*input` 側で扱います。\n\n```html\n<input\n  *input=\"query\"\n  @keyup.enter=\"search(query)\">\n```\n\nstaged editing の中では、`*input` の timing、`*lazy` / `*eager`、`@keyup` の timing が関係します。type-then-action flow では、最終的にどの値を action が読むのかを明確にします。\n\n#### Sercrod 固有の制限\n\n- shortcuts や movement controls の主な形式は `@keydown` です。\n- `@keyup` は release timing に適しています。\n- `.window` は window listener を使い、declaration element は event target ではありません。\n- `.prevent` と `.preventDefault` は同義です。\n- arbitrary non-modifier key combinations は初期仕様では support しません。\n- keyup は key repeat の中心ではありません。\n\n#### 推奨される使い方\n\n- key を離した後の cleanup に使います。\n- pressed flag の解除に使います。\n- Enter release 後の action など、release timing が必要な場合に使います。\n- shortcut detection は通常 `@keydown` で書きます。\n- key names は lowercase を推奨します。\n- `.window` は必要な場合だけ使います。\n\n#### 追加例\n\nEscape release の例:\n\n```html\n<input @keyup.escape=\"editing = false\">\n```\n\npressed flag の例:\n\n```html\n<div\n  tabindex=\"0\"\n  @keydown.space=\"spaceDown = true\"\n  @keyup.space=\"spaceDown = false\">\n</div>\n```\n\nwindow keyup の例:\n\n```html\n<input type=\"hidden\" @keyup.window.escape=\"open = false\">\n```\n\nCtrl + Enter release の例:\n\n```html\n<textarea @keyup.enter+ctrl=\"submit()\"></textarea>\n```\n\n#### 注意点\n\n- `@keyup` は native keyup event を扱います。\n- release timing が必要な場合に使います。\n- shortcuts の主な例は `@keydown` で説明します。\n- key syntax は `@keydown` と揃っています。\n",
  "keyboard-events": "### Keyboard events\n\n#### 概要\n\nSercrod は `@keydown` と `@keyup` による keyboard actions を support します。\n\ncomponent が `ArrowUp`、`ArrowDown`、`Enter`、`Escape`、または `Shift + ArrowUp` のような modifier combinations に反応する必要がある場合に使います。\n\nshortcuts や movement patterns の多くでは `keydown` を使います。\n\n`keyup` も support されますが、通常は release timing、cleanup、key が離されたあとに実行したい action 向けです。\n\nkey event attributes は通常の `@event` family の一部ですが、key name modifiers と `.window` keyboard actions という特別な規則を持ちます。\n\n#### local key event について\n\nlocal key event は、属性を書いた要素で key event を受け取ります。\n\n```html\n<div\n  tabindex=\"0\"\n  @keydown.arrowup.prevent=\"y = y - 1\"\n  @keydown.arrowdown.prevent=\"y = y + 1\">\n  Use arrow keys.\n</div>\n```\n\nこの場合、`div` が focus を持っているときだけ keydown を受け取ります。\n\n普通の `div` など、標準では focusable ではない要素には `tabindex=\"0\"` が必要です。\n\n#### window key event について\n\n`.window` modifier を付けると、key event は `window` で監視されます。\n\n```html\n<div\n  @keydown.window.escape=\"open = false\"\n  @keydown.window.arrowup.prevent=\"y = y - 1\">\n</div>\n```\n\nこの場合、属性を書いた要素は declaration location です。実際の event target ではありません。\n\n- listener は `window` に取り付けられます。\n- expression は直近の `<serc-rod>` host の context で実行されます。\n- update はその host に閉じます。\n- declaration element が focus を持つ必要はありません。\n\n#### 1つの要素で複数の window key を宣言する\n\n複数の window key declarations を同じ要素にまとめられます。\n\n```html\n<div\n  @keydown.window.arrowleft.prevent=\"x = x - 1\"\n  @keydown.window.arrowright.prevent=\"x = x + 1\"\n  @keydown.window.arrowup.prevent=\"y = y - 1\"\n  @keydown.window.arrowdown.prevent=\"y = y + 1\">\n</div>\n```\n\nこの形式は、component の global key actions を1か所にまとめたい場合に向いています。\n\n#### hidden input で window key を宣言する\n\n不可視の declaration location として hidden input を使うこともできます。\n\n```html\n<input type=\"hidden\" @keydown.window.escape=\"open = false\">\n<input type=\"hidden\" @keydown.window.arrowup.prevent=\"y = y - 1\">\n```\n\n`input type=\"hidden\"` は focus を受けませんが、`.window` が付いているため問題ありません。key event は `window` で監視されます。\n\n#### key 名\n\nkey names は case-insensitive に照合されます。\n\n推奨表記は lowercase です。\n\n```html\n@keydown.arrowup\n@keydown.enter\n@keydown.escape\n@keydown.shift\n```\n\n公式の `KeyboardEvent.key` names も受け入れます。\n\n```html\n@keydown.ArrowUp\n@keydown.Enter\n@keydown.Escape\n```\n\nSercrod は attribute token と `event.key` の両方を正規化して比較します。\n\n#### 修飾 key\n\nmodifier-key combinations は `+` で書きます。\n\n```html\n@keydown.arrowup+shift\n@keydown.shift+arrowup\n@keydown.s+ctrl\n@keydown.enter+ctrl+shift\n```\n\norder は意味を持ちません。たとえば次の2つは同じです。\n\n```html\n@keydown.arrowup+shift\n@keydown.shift+arrowup\n```\n\n修飾 key:\n\n- `shift`\n- `ctrl`\n- `alt`\n- `meta`\n\n#### 修飾 key ではない複数 key\n\n初期仕様では、複数の non-modifier keys の同時押しは support しません。\n\n次のような pattern は避けます。\n\n```html\n@keydown.a+b\n```\n\nこれは true multi-key state management を必要とするためです。Sercrod はこのような指定に対して `[Sercrod warn]` を出すべきです。\n\nmodifier combinations は support されます。\n\n```html\n@keydown.s+ctrl\n@keydown.enter+ctrl+shift\n```\n\n#### ブラウザ既定動作の抑止\n\n`.prevent` と `.preventDefault` は同義です。\n\n推奨表記は `.prevent` です。\n\n```html\n@keydown.arrowup.prevent\n@keydown.prevent.arrowup\n```\n\nmodifier order は意味を持ちません。\n\n`preventDefault()` は key condition が一致した場合にだけ適用されます。\n\nたとえば、`@keydown.window.arrowup.prevent` は `ArrowUp` の default behavior を抑止します。すべての key を抑止するわけではありません。\n\n`.window.prevent` を使うと、一致した key の browser default behavior は window level で抑止されます。\n\nこれにより、ページスクロールや、focus 中の form control における通常の key behavior も止まる場合があります。\n\nその key operation を Sercrod 側で引き受ける意図がある場合にだけ使います。\n\n#### keyup について\n\n`@keyup` は `@keydown` と同じ key syntax を support します。\n\n```html\n@keyup.escape\n@keyup.enter+ctrl\n@keyup.window.arrowup\n```\n\nただし、shortcuts や movement controls の多くは `keydown` で扱います。\n\n`keyup` は次の用途に向いています。\n\n- key を離したときの cleanup。\n- pressed flag の解除。\n- release 後に実行する action。\n- keydown repeat を避けたい処理。\n\n#### window listener の cleanup\n\n`.window` key declarations は owning `<serc-rod>` host に紐付けられます。\n\nhost が DOM から削除された場合、Sercrod は Custom Element lifecycle を使って、その host の window key registrations を cleanup するべきです。\n\nこれにより、削除済み component の shortcut が残り続けることを避けます。\n\n#### 注意点\n\n- keyboard shortcuts では通常 `@keydown` を使います。\n- `@keyup` は release timing 向けです。\n- key names は case-insensitive です。\n- `.window` は key event を window で監視します。\n- declaration element は `.window` event の target ではありません。\n- hidden input は `.window` declarations の置き場所として使えます。\n- `.prevent` と `.preventDefault` は同義です。\n- arbitrary non-modifier multi-key combinations は初期仕様では support しません。\n",
  "event-submit": "### @submit\n\n#### 概要\n\n`@submit` は、form の native `submit` event に Sercrod expression を接続します。\n\nform が送信されるときに、検証、flag 更新、custom submission logic、default submission の抑止などを行うために使います。\n\n`@submit` は `@click`、`@input`、`@change`、`@keydown` などと同じ event handler family の一部です。form submission に関する主制御は、button の `@click` より form の `@submit` に寄せる方が分かりやすくなります。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"sent\":false,\"name\":\"\"}'>\n  <form @submit.prevent=\"sent = true\">\n    <input type=\"text\" name=\"name\" *input=\"name\">\n    <button type=\"submit\">Send</button>\n  </form>\n\n  <p *if=\"sent\">Submitted: %name%</p>\n</serc-rod>\n```\n\nこの例では、form submit 時に default submission を止め、`sent` を true にします。\n\n#### 挙動\n\n基本規則:\n\n- `@submit` は form など submit event を受ける要素に listener を取り付けます。\n- 属性値は Sercrod expression として評価されます。\n- `$event` / `$e` は native submit event です。\n- `el` / `$el` は handler を宣言した要素です。\n- `.prevent` を使うと browser の default form submission を止めます。\n- expression 実行後、通常の update flow に入ります。\n\n`@submit` 自体は HTTP request を送る directive ではありません。request を Sercrod 側で扱う場合は、method、`*api`、`*post`、または project の JavaScript function と組み合わせます。\n\n#### 評価タイミング\n\nnative submit event が発生したときに評価されます。\n\nsubmit event は次の場合に発生します。\n\n- submit button が click されたとき。\n- form 内の input で Enter が押されたとき。\n- script によって requestSubmit などが呼ばれたとき。\n\n大まかな流れ:\n\n1. user が form submission を開始します。\n2. browser が submit event を dispatch します。\n3. `@submit` expression が評価されます。\n4. `.prevent` があれば default submission が抑止されます。\n5. data 変更があれば host が update されます。\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nform.addEventListener(\"submit\", (event)=>{\n        if(hasPreventModifier){\n                event.preventDefault();\n        }\n\n        const scope = createEventScope({\n                $event: event,\n                $e: event,\n                el: form,\n                $el: form\n        });\n\n        evaluate(submitExpression, scope);\n        host.update();\n});\n```\n\n実際の runtime は modifier handling、error handling、update timing を含みます。\n\n#### form 送信との関係\n\nbrowser の default submission を使う場合:\n\n```html\n<form method=\"post\" :action=\"actionUrl\" @submit=\"submitted = true\">\n```\n\nこの場合、`@submit` が実行されたあと、prevent されていなければ browser が通常の submit を続けます。\n\nSercrod 側で処理したい場合:\n\n```html\n<form @submit.prevent=\"save(form)\">\n```\n\n`.prevent` を付けて default submission を止め、custom logic を呼びます。\n\n`button @click` で submit を制御するより、form の `@submit` を使うと、Enter key submission なども含めて一貫して扱えます。\n\n#### 更新方針と性能\n\n`@submit` は high-frequency event ではありません。通常は user action ごとに1回です。\n\nそのため、submit 時の validation や state update に向いています。\n\nただし、submit によって form 自体が再描画されると、focus や button state が変わる場合があります。送信中 state を表示する場合は、`$pending` や project-specific flags と組み合わせると分かりやすくなります。\n\n#### 属性バインディングと stage 付き form との併用\n\nform の endpoint を data から設定する場合:\n\n```html\n<form method=\"post\" :action=\"endpoint\" @submit=\"submitted = true\">\n```\n\nstaged editing と組み合わせる場合:\n\n```html\n<serc-rod data='{ \"profile\": { \"name\": \"\" } }' *stage>\n  <form @submit.prevent=\"submitted = true\">\n    <input *input=\"profile.name\">\n    <button type=\"submit\" *apply>Apply</button>\n  </form>\n</serc-rod>\n```\n\nこのような構成では、`@submit`、`*apply`、`*input` の責務と timing を明確にします。\n\n#### conditionals and loops との併用\n\n`@submit` は通常 form に1つ置きます。\n\nloop の中に form が複数ある場合、それぞれの form が自分の scope を持ちます。\n\n```html\n<form *for=\"item of items\" @submit.prevent=\"saveItem(item)\">\n  <button type=\"submit\">Save %item.name%</button>\n</form>\n```\n\n各 form は、自分の `item` に対して submit handler を実行します。\n\n#### Sercrod 固有の制限\n\n- `@submit` は request を自動で送る directive ではありません。\n- default submission を止めるには `.prevent` を使います。\n- form submission の主制御には、button の `@click` より `@submit` が適しています。\n- `@submit` expression は短く保ち、複雑な送信処理は method や `*api` に分けます。\n- `.prevent` を付け忘れると browser の通常 submit が発生します。\n\n#### 推奨される使い方\n\n- custom submit logic には `@submit.prevent` を使います。\n- native submit を使う場合は `method` と `:action` を明確にします。\n- Enter key submission も含めて扱うため、form に `@submit` を置きます。\n- validation は submit handler または method にまとめます。\n- network request は `*api`、`*post`、または project method に分けます。\n\n#### 追加例\n\nvalidation の例:\n\n```html\n<form @submit.prevent=\"valid = !!email\">\n  <input type=\"email\" *input=\"email\">\n  <button type=\"submit\">Check</button>\n</form>\n```\n\nmethod 呼び出し:\n\n```html\n<form @submit.prevent=\"save(form)\">\n  <button type=\"submit\">Save</button>\n</form>\n```\n\nflag 付き native submit:\n\n```html\n<form method=\"post\" :action=\"actionUrl\" @submit=\"submitted = true\">\n  <button type=\"submit\">Send</button>\n</form>\n```\n\nloop 内の form:\n\n```html\n<form *for=\"row of rows\" @submit.prevent=\"saveRow(row)\">\n  <button type=\"submit\">Save %row.name%</button>\n</form>\n```\n\n#### 注意点\n\n- `@submit` は native submit event を扱います。\n- default submission を止めるには `.prevent` を使います。\n- form-level logic は `@submit` に置く方が一貫します。\n- network request の責務は別途設計します。\n",
  "events": "### Event bindings (fallback for @name)\n\n#### keyboard event の例外\n\n`@keydown` と `@keyup` は、通常の fallback event binding に加えて、keyboard-specific syntax を持ちます。\n\nたとえば次のような属性です。\n\n```html\n@keydown.arrowup.prevent\n@keydown.window.escape\n@keyup.enter+ctrl\n```\n\nこれらでは、`.arrowup`、`.escape`、`.enter+ctrl` などが key condition として扱われます。`.window` は window-level key monitoring を表します。\n\n詳しくは `keyboard-events`、`event-keydown`、`event-keyup` の manual entry を参照してください。\n\n#### 概要\n\nこのページでは、専用 manual がない `@name` event bindings の一般的な挙動を説明します。\n\n典型例:\n\n- `@pointerdown`, `@pointerup`, `@pointermove`\n- `@mousedown`, `@mouseup`, `@mousemove`\n- `@dragstart`, `@dragover`, `@drop`\n- `@wheel`\n- `element.dispatchEvent(new CustomEvent(\"...\"))` で dispatch される custom events\n\n`@click`、`@submit`、`@input`、`@change`、`@keydown`、`@keyup` など、専用 entry がある events は、その entry の説明を優先してください。\n\n#### 構文\n\n一般形は次の通りです。\n\n```html\n<div @event-name=\"expression\"></div>\n```\n\nevent name は、leading `@` を取り除いた部分です。\n\n```html\n<div @pointerdown=\"dragging = true\"></div>\n```\n\nこの場合、native event name は `pointerdown` です。\n\nmodifier を付けることもできます。\n\n```html\n<div @wheel.prevent=\"zoom($event)\"></div>\n```\n\nmodifier は event binding pipeline によって解釈されます。\n\n##### 認識される修飾子と分類\n\n代表的な modifiers:\n\n- `.prevent` / `.preventDefault`\n  - `event.preventDefault()` を呼びます。\n- `.stop`\n  - `event.stopPropagation()` を呼びます。\n- `.once`\n  - handler を一度だけ実行する intent を表します。\n- `.window`\n  - keyboard events など、一部の event family で特別な target を表す場合があります。\n\nすべての modifiers がすべての event で同じ意味になるとは限りません。専用 manual がある event では、そちらの説明を優先します。\n\n#### event object と要素へのアクセス\n\nevent expression では、次の値を参照できます。\n\n- `$event`\n  - native event object。\n- `$e`\n  - `$event` の短い alias。\n- `el`\n  - event handler を宣言した element。\n- `$el`\n  - `el` の alias。\n\n例:\n\n```html\n<div @pointerdown=\"startX = $event.clientX\"></div>\n```\n\n```html\n<div @custom-event=\"lastDetail = $event.detail\"></div>\n```\n\n#### data 更新と再描画タイミング\n\nevent expression が data を変更すると、Sercrod は通常の update flow に入ります。\n\n```html\n<button type=\"button\" @click=\"open = !open\"></button>\n```\n\nこの場合、`open` が変わり、関連する UI が再描画されます。\n\nhigh-frequency events、たとえば `pointermove`、`mousemove`、`scroll`、`wheel` などでは、毎回大きな update を起こすと重くなる場合があります。必要に応じて throttling、method 化、または data 更新範囲の設計を検討します。\n\n#### *input や他の helper との関係\n\nevent binding は、`*input`、`*api`、`*fetch` などの helper directives と同じ element に置ける場合があります。\n\nただし、役割が重なると timing が分かりにくくなることがあります。\n\n例:\n\n```html\n<input *input=\"name\" @input=\"dirty = true\">\n```\n\nこの場合、`*input` は値の書き戻し、`@input` は side effect として dirty flag を扱います。\n\n同じ element 上で network directive と event handler を複雑に組み合わせる場合は、wrapper や method に分けると読みやすくなります。\n\n#### *prevent-default / *prevent との関係\n\ndefault behavior を抑止したい場合は、event modifier または dedicated directive を使います。\n\n```html\n<a href=\"/fallback\" @click.prevent=\"open = true\">Open</a>\n```\n\nまたは project の記法として `*prevent-default` / `*prevent` を使う場合があります。\n\nevent modifier と dedicated directive を重ねると意味が重複することがあります。基本的には、1つの意図に対して1つの方法を選びます。\n\n#### custom event について\n\ncustom event も fallback event binding で扱えます。\n\n```html\n<div @sercrod-change=\"last = $event.detail\"></div>\n```\n\nただし、document level や window level で dispatch される event は、通常の element listener では拾えない場合があります。どの target に event が dispatch されるのかを確認します。\n\ncustom event の detail shape は project によって異なります。template は、その detail shape と一致している必要があります。\n\n#### エラー処理と例外的なケース\n\nevent expression が throw した場合、runtime は error handling path に入ります。project の logging や debug hooks が有効であれば、そこで確認できます。\n\n注意点:\n\n- 存在しない data path を前提にした式は避けます。\n- event.detail の shape を確認します。\n- high-frequency events では重い処理を避けます。\n- browser default behavior と Sercrod update の両方が発生する場合、順序を明確にします。\n\n#### 個別 event manual との関係\n\n専用 manual がある event では、その entry を優先します。\n\n関連 entry:\n\n- `event-click`\n- `event-submit`\n- `event-input`\n- `event-change`\n- `event-blur`\n- `event-focus`\n- `event-keydown`\n- `event-keyup`\n- `keyboard-events`\n\nこの fallback は、専用 entry がない event の一般的な読み方を示すためのものです。\n",
  "fetch": "### *fetch\n\n#### 概要\n\n`*fetch` は URL から JSON を読み込み、Sercrod host data へ書き込む directive です。\n\nJSON response は root data object 全体を置き換えることも、特定の property path へ merge または代入することもできます。\n\nalias の `n-fetch` も同じ挙動です。\n\nSercrod host element、つまり `<serc-rod>` 上では、`*fetch` は通常 initial data loading に使われます。\n通常要素、たとえば `<button>` や `<div>` 上では、明示的な reload button や one-time auto fetch として使えます。\n\n主なポイント:\n\n- URL spec は plain string です。\n- `URL:path` 形式で response destination を指定できます。\n- URL 内の `%expr%` placeholders は current scope で展開されます。\n- GET request を行います。\n- response は JSON として parse されます。\n- host data が更新されると、host は再描画されます。\n\n#### 基本例\n\nhost 上で初期 data を読み込む例です。\n\n```html\n<serc-rod *fetch=\"/api/posts.json:posts\">\n  <ul>\n    <li *for=\"post of posts\">%post.title%</li>\n  </ul>\n</serc-rod>\n```\n\nこの例では、`/api/posts.json` から JSON を読み込み、その結果を `posts` に保存します。\n\n#### URL 指定形式\n\n`*fetch` の値は URL spec です。\n\n基本形:\n\n```html\n<serc-rod *fetch=\"/api/data.json\">\n```\n\ndestination 付き:\n\n```html\n<serc-rod *fetch=\"/api/posts.json:posts\">\n```\n\nこの場合:\n\n- URL は `/api/posts.json`\n- destination path は `posts`\n\nURL に placeholder を含めることもできます。\n\n```html\n<div *fetch=\"/api/users/%userId%.json:user\"></div>\n```\n\n`%userId%` は current scope で評価され、URL に展開されます。\n\nURL に `:` が含まれる場合、URL と destination の区切り方に注意します。複雑な URL では、query parameter や設計を明確にします。\n\n#### 挙動\n\n基本動作:\n\n1. `*fetch` / `n-fetch` の URL spec を読みます。\n2. placeholder を current scope で展開します。\n3. URL と destination path を分解します。\n4. GET request を送ります。\n5. response を JSON として parse します。\n6. destination path があれば、その path へ result を書き込みます。\n7. destination がなければ、root data object を response で置き換える、または merge します。\n8. host を update します。\n9. 成功または error event を dispatch します。\n\n`*fetch` は simple GET JSON loading 向けです。method、body、upload、headers などが必要な場合は `*api` を使います。\n\n#### host と通常要素\n\n`<serc-rod>` host 上の `*fetch`:\n\n```html\n<serc-rod *fetch=\"/api/data.json\">\n```\n\nこれは initial data loading として扱われます。host の data source を外部 JSON から取得する用途に向きます。\n\n通常要素上の `*fetch`:\n\n```html\n<button type=\"button\" *fetch=\"/api/posts.json:posts\">\n  Reload\n</button>\n```\n\nbutton のような clickable element 上では、user action によって fetch を実行する用途に向きます。\n\nnon-clickable normal element 上では、one-shot auto fetch として実行される場合があります。\n\n#### once-key と `ts` parameter\n\nautomatic fetch では、同じ request が不要に繰り返されないよう、runtime は once-key で deduplication を行います。\n\n同じ host、URL、destination などに対して、同じ automatic fetch が何度も実行されることを避けます。\n\n再取得を意図的に発生させたい場合は、URL に変化する値を含めます。\n\n```html\n<div *fetch=\"`/api/data.json?ts=${Date.now()}:data`\"></div>\n```\n\nまたは Sercrod の placeholder を使います。\n\n```html\n<div *fetch=\"/api/data.json?ts=%Date.now()%:data\"></div>\n```\n\nただし、timestamp を使うと cache を無効化しやすくなるため、必要な場合にだけ使います。\n\n#### イベント\n\n`*fetch` は、成功時や error 時に event を dispatch する場合があります。\n\n典型的には:\n\n- `sercrod-fetch`\n- `sercrod-error`\n\nevent detail には URL、destination、data、error、host、element などが含まれる場合があります。\n\ndebug や logging では、これらの events を利用して fetch の成否を確認できます。\n\n#### *api・*post・*into との関係\n\n`*fetch` は simple GET JSON loading に向きます。\n\n`*api` は、method、body、headers、upload、status flags、`*into` などを扱う汎用 HTTP primitive です。\n\n`*post` は simple POST helper です。\n\n`*into` は `*api` などで response destination を指定する companion directive として使われます。`*fetch` では URL spec の `:path` が destination 指定に相当します。\n\n使い分け:\n\n- simple GET JSON:\n  - `*fetch`\n- POST や method 指定:\n  - `*api` または `*post`\n- file upload:\n  - `*api` または `*upload`\n- status flags が必要:\n  - `*api`\n\n#### conditionals and loops との併用\n\n`*fetch` は conditionals と組み合わせられます。\n\n```html\n<div *if=\"userId\" *fetch=\"/api/users/%userId%.json:user\">\n  <p *if=\"user\">%user.name%</p>\n</div>\n```\n\nloop 内で使うこともできますが、各 iteration で request が発生する可能性があるため注意が必要です。\n\n```html\n<div *for=\"item of items\" *fetch=\"/api/items/%item.id%.json:detail\">\n</div>\n```\n\nこのような pattern では大量 request になりやすいため、server API や data shape を見直す方がよい場合があります。\n\n#### サーバー側の契約と推奨 API 形式\n\nSercrod template と server response は data path で一致している必要があります。\n\n`*fetch=\"/api/posts.json:posts\"` の場合、template が次のように読むなら、\n\n```html\n<li *for=\"post of posts\">%post.title%</li>\n```\n\nserver response は posts に入れる配列である必要があります。\n\n```json\n[\n  { \"title\": \"First\" },\n  { \"title\": \"Second\" }\n]\n```\n\nresponse が object wrapper を持つ場合は、template 側もそれに合わせます。\n\n```json\n{\n  \"items\": [\n    { \"title\": \"First\" }\n  ]\n}\n```\n\nこの場合、destination や template path を `posts.items` などに合わせる設計が必要です。\n\n#### 推奨される使い方\n\n- simple GET JSON loading には `*fetch` を使います。\n- request method や body が必要なら `*api` を使います。\n- destination path を明示して、template が読む path と一致させます。\n- loop 内で大量 fetch を起こさないようにします。\n- cache busting の timestamp は必要な場合だけ使います。\n- server response shape を安定させます。\n- error state を UI に出す必要がある場合は、`*api` や event listener も検討します。\n\n#### 追加例\n\nroot data loading の例:\n\n```html\n<serc-rod *fetch=\"/api/page.json\">\n  <h1>%title%</h1>\n</serc-rod>\n```\n\n保存先 path:\n\n```html\n<serc-rod data='{\"posts\":[]}'>\n  <button type=\"button\" *fetch=\"/api/posts.json:posts\">Reload</button>\n\n  <ul>\n    <li *for=\"post of posts\">%post.title%</li>\n  </ul>\n</serc-rod>\n```\n\n動的 URL:\n\n```html\n<div *fetch=\"/api/users/%userId%.json:user\"></div>\n```\n\none-shot element fetch の例:\n\n```html\n<section *fetch=\"/api/sidebar.json:sidebar\">\n  <h2>%sidebar.title%</h2>\n</section>\n```\n\n#### 注意点\n\n- `*fetch` と `n-fetch` は同じ挙動です。\n- `*fetch` は GET JSON loading 向けです。\n- URL spec の `:path` で destination を指定できます。\n- method や body が必要なら `*api` を使います。\n- response shape と template path を一致させます。\n",
  "for": "### *for\n\n#### 概要\n\n`*for` は、list、object、またはその他の iterable の各 entry に対して、host element を繰り返します。\ndirective が付いた element そのものが必要な回数だけ複製され、それぞれの clone が独自の iteration scope で描画されます。\nこの directive は JavaScript 風の `in` と `of` の loop syntax を理解し、alias として `n-for` も持ちます。\n\n`*for` を Sercrod host (`<serc-rod>`) に直接置いた場合には、特別な host-level form もあります。この場合、host 自体は繰り返されません。代わりに inner template が繰り返し描画され、data source の各 entry が子 scope として使われます。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"items\":[\"Apple\",\"Orange\",\"Grape\"]}'>\n  <ul>\n    <li *for=\"item of items\">%item%</li>\n  </ul>\n</serc-rod>\n```\n\nこの例では、`li` 要素そのものが `items` の各 entry に対して繰り返されます。\n\n結果として、`li` が3つ描画されます。\n\n```html\n<li>Apple</li>\n<li>Orange</li>\n<li>Grape</li>\n```\n\n#### 挙動\n\n`*for` は element-level loop です。\n\n基本規則:\n\n- `*for=\"item of items\"` のように書きます。\n- 右側の collection expression、ここでは `items` が現在の scope で評価されます。\n- 各 item について、directive の付いた element が clone されます。\n- 各 clone は、その iteration 専用の scope で描画されます。\n- loop variable、ここでは `item` は、その clone と children の中で参照できます。\n- alias の `n-for` も同じ挙動です。\n\n`*for` は directive が置かれた element 自体を繰り返します。container を1つ残して children だけを繰り返したい場合は `*each` を使います。\n\n\n#### 式の構文\n\n一般的な形式は次の通りです。\n\n```html\n<li *for=\"item of items\">\n```\n\nまたは alias です。\n\n```html\n<li n-for=\"item of items\">\n```\n\n`of` syntax は、array や iterable の値を順番に扱う用途に向いています。\n\n```html\n<li *for=\"post of posts\">%post.title%</li>\n```\n\n`in` syntax は、object key や index を扱う用途に使えます。\n\n```html\n<li *for=\"key in object\">%key%</li>\n```\n\nproject の readability を優先し、loop variable name と collection expression は短く明確にします。\n\n\n#### 値の扱い - 要素レベルの *for\n\ncollection expression の結果は、array、object、または iterable として扱われます。\n\n典型的には array を使います。\n\n```html\n<li *for=\"item of items\">%item.name%</li>\n```\n\nobject を扱う場合は、key または value をどう扱うかを template 側で明確にします。\n\n`null` や `undefined` の可能性がある場合は、data 側で空配列にしておくか、式で fallback します。\n\n```html\n<li *for=\"item of (items || [])\">%item.name%</li>\n```\n\ntemplate が `item.name` を読むなら、各 item は `name` property を持つ object である必要があります。server response shape と template path は一致させます。\n\n\n#### 評価タイミング\n\n`*for` は structural directive として、element の通常描画より先に処理されます。\n\n大まかな流れ:\n\n1. `*for` の expression が現在の scope で評価されます。\n2. collection が iteration 用に正規化されます。\n3. 各 entry について original element が clone されます。\n4. clone から `*for` / `n-for` attribute が取り除かれます。\n5. iteration scope が作られます。\n6. clone と children が、その iteration scope で描画されます。\n\n選ばれた各 clone だけが DOM に追加されます。original template element 自体はそのまま output には使われません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst collection = evaluate(forExpressionRightSide, scope);\n\nfor(const entry of normalize(collection)){\n        const childScope = Object.create(scope);\n        childScope[itemName] = entry.value;\n\n        const clone = original.cloneNode(false);\n        renderElementAndChildren(clone, childScope);\n        parent.appendChild(clone);\n}\n```\n\n実際の runtime は、`in` / `of` syntax、index、object entries、parent/root access、nested directives、error handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*for` は iteration scope に loop variable を作ります。\n\n```html\n<li *for=\"post of posts\">\n  %post.title%\n</li>\n```\n\nこの例では、各 iteration の scope に `post` が追加されます。\n\nloop variable は host data に追加されるわけではありません。あくまでその iteration の描画中に見える local value です。\n\nchildren の中では、host data、ancestor scope、loop variable、`$parent` や `$root` などの special values が、runtime の scope rules に従って参照できます。\n\n\n#### 親へのアクセス\n\nnested `<serc-rod>` の中で `$parent` が利用できる場合、`*for` expression や children の expression から親 host data を参照できます。\n\n```html\n<li *for=\"item of $parent.items\">%item.name%</li>\n```\n\nただし、どの host が data を所有しているかを明確にするため、できるだけ現在の host data に collection を持たせる方が読みやすくなります。\n\n\n#### conditionals and loops との併用\n\n`*for` は `*if` と組み合わせられます。\n\n```html\n<li *for=\"item of items\" *if=\"item.visible\">\n  %item.name%\n</li>\n```\n\nこの場合、各 item に対して clone が作られ、`*if` によって表示するかどうかが決まります。\n\nnested loops も可能です。\n\n```html\n<section *for=\"group of groups\">\n  <h2>%group.name%</h2>\n\n  <p *for=\"item of group.items\">%item.name%</p>\n</section>\n```\n\nloop variable name の衝突を避けるため、`group`、`item`、`row` など意味のある名前を使います。\n\n\n#### template と *include との併用\n\n`*for` は element 自体を繰り返すため、再利用 template を各 item に適用する場合にも使えます。\n\n```html\n<div *for=\"item of items\" *include=\"'item-card'\"></div>\n```\n\nただし、`*include` が同じ element の innerHTML を置き換える場合、構造が読みにくくなることがあります。より明確にするには wrapper を分けます。\n\n```html\n<div *for=\"item of items\">\n  <div *include=\"'item-card'\"></div>\n</div>\n```\n\nこの形では、outer element が loop、inner element が include を担当します。\n\n\n#### *each との比較\n\n`*for` と `*each` は繰り返し対象が違います。\n\n`*for`:\n\n```html\n<li *for=\"item of items\">%item%</li>\n```\n\n- `li` element 自体が繰り返されます。\n\n`*each`:\n\n```html\n<ul *each=\"item of items\">\n  <li>%item%</li>\n</ul>\n```\n\n- `ul` は1つだけ残ります。\n- `ul` の children が item ごとに繰り返されます。\n\n選び方:\n\n- element そのものが1つの item を表す場合は `*for`。\n- element が repeated children の container である場合は `*each`。\n\n\n#### <serc-rod> 上の host-level *for - 応用\n\n`*for` を `<serc-rod>` host 自体に置く場合、通常の element-level `*for` とは少し異なります。\n\nhost-level form では、host element 自体を複数に複製するのではなく、host の内側 template が collection に対して繰り返し描画されます。\n\nこれは、同じ Sercrod host 内で collection 全体を扱いながら、children を item ごとに描画したい場合の advanced form です。\n\n通常の UI では、まず element-level `*for` または `*each` を使う方が分かりやすいです。host-level `*for` は、host data と template scope の関係を明確に理解している場合に使います。\n\n\n#### 推奨される使い方\n\n- item element を繰り返したい場合に `*for` を使います。\n- container を残したい場合は `*each` を使います。\n- loop variable name は短く意味のある名前にします。\n- collection が `null` になる可能性がある場合は、空配列へ fallback します。\n- server response shape と template path を一致させます。\n- `*for` と `*include` / `*import` を同じ要素に置く場合は、構造が読みやすいか確認します。\n- host-level `*for` は advanced pattern として扱います。\n\n\n#### 追加例\n\nオブジェクト配列:\n\n```html\n<article *for=\"post of posts\">\n  <h2>%post.title%</h2>\n  <p>%post.summary%</p>\n</article>\n```\n\n空リストの fallback:\n\n```html\n<li *for=\"item of (items || [])\">%item.name%</li>\n```\n\n表の行:\n\n```html\n<tr *for=\"row of rows\">\n  <td>%row.name%</td>\n  <td>%row.value%</td>\n</tr>\n```\n\nネストしたグループ:\n\n```html\n<section *for=\"group of groups\">\n  <h2>%group.name%</h2>\n  <p *for=\"item of group.items\">%item.name%</p>\n</section>\n```\n\n\n#### 注意点\n\n- `*for` と `n-for` は同じ挙動です。\n- `*for` は element 自体を繰り返します。\n- `*each` は container の children を繰り返します。\n- loop variable は iteration scope に属し、host data へ自動追加されるものではありません。\n- host-level `*for` は通常の element-level `*for` とは別の advanced form です。\n",
  "global": "### *global\n\n#### 概要\n\n`*global` は、Sercrod の共有 data または JavaScript global object へ書き込む side effect を持つ JavaScript statements を実行します。\n`*let` とは異なり、children 用の local scope を作るのではありません。既存 data または `globalThis` を更新し、その後 rendering を続けます。\n\n`*global` は次のような場合に使います。\n\n- template 内から共有 Sercrod data を更新したい場合。特に nested components から更新したい場合。\n- global functions、global libraries、既存の scripts と Sercrod をつなぐ場合。\n- rendering 中に、明示的な side effect を実行する必要がある場合。\n\nalias の `n-global` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"count\":0}'>\n  <p *global=\"count = count + 1\">\n    Count: %count%\n  </p>\n</serc-rod>\n```\n\nこの例では、`count` が共有 data 上で更新されます。\n\n`*let` と違い、`count` の top-level assignment は local shadowing として扱われるのではなく、既存 data への書き込みとして扱われます。\n\n\n#### 挙動\n\n`*global` は、属性値を JavaScript statements として現在の Sercrod scope で実行します。\n\n基本規則:\n\n- 属性値は expression ではなく、side effect を持つ statements として扱います。\n- 既存の Sercrod data property へ書き込む用途に向きます。\n- 既存 data に該当する名前がない場合は、global object への書き込みになる可能性があります。\n- `*global` は children 用の local scope を作りません。\n- `*global` の結果値は描画出力として使われません。\n\n`*global` は便利ですが、template の読みやすさを下げやすいため、必要な場合だけ使います。\n\n\n#### 式の評価モデル\n\n`*global` の属性値には、1つ以上の JavaScript statements を書けます。\n\n```html\n<div *global=\"\n  count = count + 1;\n  lastUpdated = Date.now();\n\"></div>\n```\n\nSercrod は、この code を Sercrod-managed scope で実行します。\n\nこの scope では、host data、loop variables、methods、special values などが参照できる場合があります。\n\n通常の JavaScript module scope と同じものとして扱わないでください。Sercrod expressions と同じく、runtime が管理する expression scope の中で評価されます。\n\n\n#### data と global の書き込み先\n\n`*global` の目的は、local helper ではなく、共有 state への明示的な書き込みです。\n\n例:\n\n```html\n<div *global=\"status = 'ready'\"></div>\n```\n\n`status` が host data に存在する場合、その data property が更新されます。\n\n存在しない名前に書き込む場合、runtime の scope resolution によっては `globalThis` 側へ向かう可能性があります。\n\nこのため、`*global` で使う target は事前に data に用意しておく方が安全です。\n\n```html\n<serc-rod data='{\"status\":\"idle\"}'>\n  <div *global=\"status = 'ready'\"></div>\n</serc-rod>\n```\n\n未知の名前を `*global` で作る設計は避けます。\n\n\n#### スコープと特別な helper\n\n`*global` の中では、Sercrod の通常の expression scope と同様に、次のような値が使える場合があります。\n\n- host data fields\n- loop variables\n- methods\n- `$data`\n- `$root`\n- `$parent`\n- `$event` や `$e`、event context がある場合\n- `el` / `$el`、element context がある場合\n\n利用できる値は、`*global` がどの rendering context で実行されるかに依存します。\n\n\n#### 評価タイミング\n\n`*global` は element の描画中に評価されます。\n\n1. element が rendering pipeline に入ります。\n2. `*global` または `n-global` が検出されます。\n3. 属性値の statements が現在の scope で実行されます。\n4. 必要に応じて data が変更されます。\n5. element と children の rendering が続きます。\n\n`*global` は rendering 中に side effect を起こすため、再描画のたびに実行される可能性があります。これが意図したものかどうかを必ず確認します。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nexecuteGlobalStatements(globalCode, scope);\nrenderElementAndChildren(element, scope);\n```\n\n`*global` は値を返して表示するものではありません。\n\nside effect が目的であるため、実行回数や実行 timing に注意します。\n\n\n#### 条件分岐・ループ・event との併用\n\n`*global` は conditionals の中で使えます。\n\n```html\n<div *if=\"ready\" *global=\"status = 'ready'\"></div>\n```\n\nこの場合、`ready` が truthy で branch が描画されるときだけ実行されます。\n\nloop 内で使うこともできますが、各 iteration で実行されます。\n\n```html\n<div *for=\"item of items\" *global=\"total = total + item.price\"></div>\n```\n\nこのような accumulation は、render 回数に依存しやすいため注意が必要です。計算だけなら `*let` や method、事前に整えた data の方が適していることが多いです。\n\nevent handler 内で shared data を更新したい場合は、`@click` などの event expression に直接書く方が分かりやすい場合もあります。\n\n```html\n<button type=\"button\" @click=\"count = count + 1\">Add</button>\n```\n\n\n#### 推奨される使い方\n\n- 既存 data property を明示的に更新する場合に使います。\n- target property は事前に data に定義しておきます。\n- render のたびに実行されることを前提にします。\n- accumulation や network request のような重い side effect には慎重に使います。\n- local helper value には `*let` を使います。\n- user action による変更には event handler や method を検討します。\n- 複雑な code は method に移します。\n\n\n#### 追加例\n\nNested component から parent data を更新する例です。\n\n```html\n<serc-rod data='{\"shared\":{\"count\":0}}'>\n  <serc-rod data='{}'>\n    <button type=\"button\" @click=\"$parent.shared.count = $parent.shared.count + 1\">\n      Add\n    </button>\n  </serc-rod>\n</serc-rod>\n```\n\nrendering 中に状態を設定する例です。\n\n```html\n<div *if=\"loaded\" *global=\"status = 'loaded'\"></div>\n```\n\nglobal function と連携する例です。\n\n```html\n<div *global=\"globalThis.externalState = $data\"></div>\n```\n\n\n#### 注意点\n\n- `*global` と `n-global` は同じ挙動です。\n- `*global` は local scope を作りません。\n- `*let` は local helper、`*global` は明示的な side effect として考えます。\n- rendering 中に実行されるため、実行回数に注意します。\n",
  "if": "### *if\n\n#### 概要\n\n`*if` は、式が truthy のときに要素を条件付きで描画します。\n`*elseif` と `*else` は、直前の `*if` と chain を作り、1つの branch だけが選ばれるようにします。\nchain は sibling elements の並びとして定義され、左から右へ評価されます。\n\nalias の例:\n\n- `*if` と `n-if` は alias です。\n- `*elseif` と `n-elseif` は alias です。\n- `*else` と `n-else` は alias です。\n\n1つの chain では、branches のうち1つだけが描画され、他は skip されます。\n\n\n#### 基本例\n\n単純な visible / hidden の例です。\n\n```html\n<serc-rod data='{\"loggedIn\":true}'>\n  <p *if=\"loggedIn\">Welcome back.</p>\n  <p *else>Please log in.</p>\n</serc-rod>\n```\n\n`loggedIn` が true の場合、最初の paragraph だけが描画されます。\n\n`loggedIn` が false の場合、`*else` branch が描画されます。\n\n\n#### 挙動\n\n`*if` は condition chain の head です。\n\n基本規則:\n\n- `*if` の属性値は Sercrod expression として評価されます。\n- 結果が truthy であれば、その element が描画されます。\n- 結果が falsy であれば、その element は skip されます。\n- 直後に `*elseif` / `n-elseif` / `*else` / `n-else` siblings がある場合、それらは同じ chain に属します。\n- chain 内では、最初に条件を満たした branch だけが描画されます。\n- `*else` は条件を持たない fallback branch です。\n\n`*if` は structural directive です。条件が false の場合、element とその children は描画されません。\n\n\n#### 条件評価の意味\n\n`*if` の condition は JavaScript の truthiness に従います。\n\ntruthy な値:\n\n- non-empty string\n- non-zero number\n- object\n- array\n- true\n\nfalsy な値:\n\n- false\n- null\n- undefined\n- 0\n- empty string\n- NaN\n\n例:\n\n```html\n<p *if=\"items.length\">Items exist</p>\n```\n\n`items.length` が 0 の場合、この branch は描画されません。\n\ncondition は現在の scope で評価されます。host data、loop variables、ancestor `*let` values、methods などを参照できます。\n\n\n#### 評価タイミング\n\n`*if` は element の描画前に評価されます。\n\n1. rendering pipeline が `*if` を持つ element に到達します。\n2. Sercrod は、同じ parent 内で続く `*elseif` / `*else` siblings を集めます。\n3. `*if` condition を評価します。\n4. false なら、`*elseif` conditions を順に評価します。\n5. どれも true でなければ、`*else` があればそれを選びます。\n6. 選ばれた branch だけが clone され、描画されます。\n\n選ばれなかった branch の children は評価されません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst chain = collectIfChain(headIfElement);\n\nfor(const branch of chain){\n        if(branch.type === \"if\" || branch.type === \"elseif\"){\n                if(evaluate(branch.expression, scope)){\n                        render(branch);\n                        break;\n                }\n        } else if(branch.type === \"else\"){\n                render(branch);\n                break;\n        }\n}\n```\n\n実際の runtime は clone、attribute cleanup、nested directives、error handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*if` は変数を作りません。\n\n- condition を評価します。\n- branch を描画するかどうかを決めます。\n- host data を直接変更しません。\n- local scope を作りません。\n\nbranch 内で `*let` を使えば、その branch 内に local helper values を作れます。\n\n```html\n<div *if=\"user\" *let=\"label = user.name\">\n  %label%\n</div>\n```\n\n\n#### 親へのアクセス\n\nnested host で `$parent` が利用できる場合、`*if` condition から参照できます。\n\n```html\n<p *if=\"$parent.ready\">Parent is ready</p>\n```\n\nただし、parent data への依存が強い template は読みづらくなることがあります。必要な data を現在の host に渡す設計も検討します。\n\n\n#### conditionals and loops との併用\n\n`*if` は `*for` の中で使えます。\n\n```html\n<li *for=\"item of items\" *if=\"item.visible\">\n  %item.name%\n</li>\n```\n\nこの場合、各 item ごとに condition が評価されます。\n\n`*if` と `*elseif` / `*else` chain は siblings として連続させます。\n\n```html\n<p *if=\"score >= 90\">Excellent</p>\n<p *elseif=\"score >= 70\">Good</p>\n<p *else>Retry</p>\n```\n\nchain の途中に無関係な要素を挟むと、chain が分断される可能性があります。\n\n\n#### template・include・import との併用\n\n`*if` は `*include` や `*import` の wrapper として使えます。\n\n```html\n<div *if=\"showCard\">\n  <div *include=\"'card'\"></div>\n</div>\n```\n\n同じ element 上に複数の structural directives を重ねると読みづらくなる場合があります。必要なら wrapper を分けます。\n\n```html\n<div *if=\"show\">\n  <section *for=\"item of items\">\n    %item.name%\n  </section>\n</div>\n```\n\n\n#### 推奨される使い方\n\n- condition は短く読みやすくします。\n- chain は連続した siblings として書きます。\n- 複数の state を明確に分けたい場合は `*switch` を検討します。\n- `*if` で存在しない path を深く読む場合は、data shape を安定させるか guard を書きます。\n- branch 内の複雑な計算は `*let` または method に分けます。\n- `*else` に条件を書かず、条件付き fallback には `*elseif` を使います。\n\n\n#### 追加例\n\nloading / ready / error の例:\n\n```html\n<p *if=\"loading\">Loading...</p>\n<p *elseif=\"error\">Error: %error.message%</p>\n<p *else>Ready</p>\n```\n\nuser object の guard:\n\n```html\n<section *if=\"user\">\n  <h2>%user.name%</h2>\n</section>\n```\n\nloop item の表示制御:\n\n```html\n<li *for=\"item of items\" *if=\"item.visible\">\n  %item.label%\n</li>\n```\n\n\n#### 注意点\n\n- `*if` と `n-if` は同じ挙動です。\n- `*elseif` / `*else` は preceding `*if` chain に属します。\n- 選ばれなかった branch の children は描画されません。\n- chain は sibling order に依存します。\n",
  "import": "### *import\n\n#### 概要\n\n`*import` は外部 URL から HTML を読み込み、現在の要素の `innerHTML` に注入します。\nimport された HTML は同じ render pass の中で Sercrod によって処理されるため、import された content 内の directives、たとえば `*if`、`*for`、`*each`、`*include`、`*template` なども通常どおり評価されます。\n\n要点:\n\n- `*import` と `n-import` は alias です。\n- directive は URL string を解決し、同期 XMLHttpRequest で HTML を取得し、URL ごとに response を cache します。\n- 読み込まれた HTML は、現在の要素の innerHTML として挿入されます。\n- 挿入後の content は、Sercrod template として再び処理されます。\n- 再帰 import や深すぎる import を避けるため、depth guard が使われます。\n\n`*import` は、外部 HTML fragment を Sercrod template に取り込むための directive です。名前付き template を同じ document または Sercrod world から取り込む場合は `*include` を使います。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"title\":\"Hello\"}'>\n  <section *import=\"'/partials/card.html'\"></section>\n</serc-rod>\n```\n\n`/partials/card.html` の内容が `section` の中へ読み込まれます。\n\nimport された HTML が次のような内容なら、\n\n```html\n<h2>%title%</h2>\n```\n\nSercrod はそれを現在の scope で処理し、`Hello` を出力します。\n\n\n#### 挙動\n\n`*import` は、directive を持つ要素を wrapper として残し、その innerHTML を外部 HTML で置き換えます。\n\n基本的な処理:\n\n1. `*import` / `n-import` の属性値を現在の scope で評価します。\n2. 評価結果を URL として解決します。\n3. URL が cache にあれば、その cached HTML を使います。\n4. cache にない場合は、同期 XMLHttpRequest で HTML を読み込みます。\n5. 読み込んだ HTML を cache に保存します。\n6. 現在の要素の innerHTML に HTML を設定します。\n7. その HTML を Sercrod の child content として処理します。\n\n属性値が falsy な場合、import は実行されません。\n\n読み込みに失敗した場合、runtime は warning または error path に入る場合があります。project の debug 設定や error handling に従って確認します。\n\n\n#### URL の解決\n\n`*import` の属性値は Sercrod expression として評価されます。\n\n```html\n<div *import=\"'/partials/user.html'\"></div>\n```\n\n文字列 literal を使う場合は quote が必要です。\n\ndata から URL を作ることもできます。\n\n```html\n<div *import=\"partialUrl\"></div>\n```\n\n```html\n<div *import=\"'/partials/' + name + '.html'\"></div>\n```\n\nURL は外部 HTML の取得先です。template name ではありません。名前付き template を探す `*include` とは役割が違います。\n\n外部入力から URL を作る場合は、許可された path だけを使うように設計します。\n\n\n#### ネットワーク読み込みと cache\n\n`*import` は external HTML を読み込むため、network loading を伴います。\n\n実装上の要点:\n\n- URL ごとに cache されます。\n- 同じ URL が再度 import される場合、cached response が使われます。\n- 読み込みは同期 XMLHttpRequest で行われます。\n- 同期 loading は UI を block する可能性があります。\n\nこのため、`*import` は少量の静的 partial や、あらかじめ読み込みが安定している fragment に向いています。\n\n大きな HTML や頻繁に変わる content を動的に読む用途では、別の loading strategy を検討します。\n\n\n#### 深さ管理と再帰防止\n\n`*import` は、読み込んだ HTML の中でさらに `*import` を含む場合があります。\n\n無限再帰や過度に深い import を避けるため、runtime は depth を管理します。\n\nたとえば次のような構成は危険です。\n\n```html\n<!-- a.html -->\n<div *import=\"'/partials/a.html'\"></div>\n```\n\nまたは相互参照です。\n\n```html\n<!-- a.html -->\n<div *import=\"'/partials/b.html'\"></div>\n\n<!-- b.html -->\n<div *import=\"'/partials/a.html'\"></div>\n```\n\nこのような pattern は recursion guard によって止められるべきです。\n\ntemplate の設計では、import graph が明確で、循環しないようにします。\n\n\n#### 評価タイミング\n\n`*import` は、要素の描画中に評価されます。\n\n大まかな順序:\n\n1. element が描画対象になります。\n2. `*import` expression が現在の scope で評価されます。\n3. URL が決まります。\n4. HTML が cache または network から取得されます。\n5. element の innerHTML に設定されます。\n6. 挿入された HTML が、同じ render pass 内で Sercrod により処理されます。\n\nimport された content は、現在の scope を使って描画されます。したがって、host data、loop variables、ancestor `*let` values などを利用できます。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst url = evaluate(importExpression, scope);\n\nif(url){\n        const html = loadHtmlWithCache(url);\n        element.innerHTML = html;\n        renderChildren(element.childNodes, element, scope);\n}\n```\n\n実際の runtime は、URL normalization、cache、depth guard、error handling、attribute cleanup を含みます。\n\n\n#### スコープと取り込まれた HTML との関係\n\nimport された HTML は、現在の Sercrod scope で処理されます。\n\n```html\n<serc-rod data='{\"user\":{\"name\":\"Alice\"}}'>\n  <div *import=\"'/partials/user-card.html'\"></div>\n</serc-rod>\n```\n\n`user-card.html` が次を含む場合、\n\n```html\n<p>%user.name%</p>\n```\n\n`user.name` は host data から解決されます。\n\nimport された HTML は独立した data source を持つわけではありません。必要な data は import 元の scope から見える必要があります。\n\n\n#### *template・*include・*each との併用\n\n`*import` と `*include` は似ていますが、取得元が違います。\n\n- `*import`\n  - URL から外部 HTML を読み込みます。\n  - network / cache / depth guard が関係します。\n\n- `*include`\n  - 現在の document または Sercrod world に登録された named template の inner content を使います。\n  - URL 読み込みは行いません。\n\n`*each` や `*for` と組み合わせる場合、同じ URL を大量に import しないよう注意します。\n\n```html\n<div *for=\"item of items\">\n  <div *include=\"'item-card'\"></div>\n</div>\n```\n\n同じ template を繰り返す用途では、`*include` の方が分かりやすい場合があります。\n\n\n#### 設定\n\n`*import` の挙動は、runtime の設定により影響を受ける場合があります。\n\n考慮点:\n\n- import cache の扱い。\n- 最大 import depth。\n- URL の許可または制限。\n- warning / error logging。\n- Sercrod world ごとの template lookup との関係。\n\nproject が独自の loader や security policy を持つ場合は、その方針に合わせます。\n\n\n#### 推奨される使い方\n\n- 小さく安定した HTML partial の取り込みに使います。\n- dynamic URL はできるだけ避け、許可済み URL に制限します。\n- recursive import を作らないようにします。\n- 同じ partial を template として繰り返すだけなら `*include` を検討します。\n- import された HTML が必要とする data を明確にします。\n- 大きな content や頻繁な network loading には慎重に使います。\n- 外部入力で import URL を直接作らないでください。\n\n\n#### 追加例\n\nstatic partial の例:\n\n```html\n<div *import=\"'/partials/header.html'\"></div>\n```\n\ndata-driven partial URL の例:\n\n```html\n<section *import=\"'/partials/' + sectionName + '.html'\"></section>\n```\n\n条件内での import:\n\n```html\n<div *if=\"showHelp\" *import=\"'/partials/help.html'\"></div>\n```\n\n現在の scope を使う import:\n\n```html\n<serc-rod data='{\"title\":\"About\"}'>\n  <main *import=\"'/partials/page-title.html'\"></main>\n</serc-rod>\n```\n\n\n#### 注意点\n\n- `*import` と `n-import` は同じ挙動です。\n- `*import` は URL から HTML を読み込みます。\n- 読み込まれた HTML は Sercrod によって再処理されます。\n- `*include` は named template 用です。\n- import URL と recursion には注意が必要です。\n",
  "include": "### *include\n\n#### 概要\n\n`*include` は、名前付き template の inner content を現在の要素に注入します。\nhost element は1つの wrapper として DOM に残り、その `innerHTML` だけが置き換えられます。\nalias として `n-include` も持ちます。\n\n`*include` は、現在の Sercrod world または ancestor worlds に `*template` / `n-template` で宣言された template を対象にします。\ntemplate content を注入したあと、Sercrod はその content を通常の children として処理します。conditions、loops、bindings、events なども通常どおり評価されます。\n\n\n#### 基本例\n\ntemplate を定義し、別の場所で include する例です。\n\n```html\n<template *template=\"'user-card'\">\n  <article>\n    <h2>%user.name%</h2>\n  </article>\n</template>\n\n<serc-rod data='{\"user\":{\"name\":\"Alice\"}}'>\n  <div *include=\"'user-card'\"></div>\n</serc-rod>\n```\n\n`div` の innerHTML は `user-card` template の内容で置き換えられ、その後 Sercrod によって処理されます。\n\n#### 挙動\n\n`*include` の基本動作:\n\n1. `*include` / `n-include` の属性値を現在の scope で評価します。\n2. 結果を template name として扱います。\n3. 現在の Sercrod world から template を探します。\n4. 見つからなければ ancestor worlds も検索します。\n5. 見つかった template の inner content を clone します。\n6. 現在の要素の innerHTML を template content で置き換えます。\n7. 注入された content を通常の Sercrod children として処理します。\n\n`*include` は wrapper element を残します。wrapper 自体を置き換えるわけではありません。\n\n\n#### template 名と式の構文\n\n`*include` の値は Sercrod expression です。\n\n文字列 literal を使う場合は quote が必要です。\n\n```html\n<div *include=\"'card'\"></div>\n```\n\ndata から template name を選べます。\n\n```html\n<div *include=\"templateName\"></div>\n```\n\n条件式で切り替えることもできます。\n\n```html\n<div *include=\"compact ? 'card-small' : 'card-full'\"></div>\n```\n\ntemplate name は、登録された `*template` 名と一致している必要があります。\n\n\n#### template 検索と world\n\nSercrod は world 単位で templates を管理できます。\n\n`*include` は、まず現在の Sercrod world で template を探します。\n見つからない場合、ancestor worlds の template を利用できる場合があります。\n\nこの lookup により、component や custom element prefix ごとに template name を分けながら、必要に応じて上位の template を再利用できます。\n\n同じ name の template が複数ある場合、現在の world に近いものが優先されます。\n\n\n#### 評価タイミング\n\n`*include` は element の描画中に評価されます。\n\n1. element が描画対象になります。\n2. `*include` expression が現在の scope で評価されます。\n3. template name が決まります。\n4. template lookup が行われます。\n5. template content が現在の element の innerHTML として注入されます。\n6. 注入された content が Sercrod によって処理されます。\n\ninclude された content は、現在の scope を使って描画されます。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst name = evaluate(includeExpression, scope);\nconst template = findTemplateInWorlds(name);\n\nif(template){\n        element.innerHTML = template.innerHTML;\n        renderChildren(element.childNodes, element, scope);\n}\n```\n\n実際の runtime は、template registry、world lookup、clone、attribute cleanup、error handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*include` 自体は新しい変数を作りません。\n\ninclude された content は、include 宣言があった場所の scope で処理されます。\n\n```html\n<div *for=\"user of users\">\n  <div *include=\"'user-card'\"></div>\n</div>\n```\n\nこの場合、`user-card` template の中では、その iteration の `user` を参照できます。\n\ntemplate 側で `*let` を使えば、template 内部の local helper values を作れます。\n\n\n#### 親へのアクセス\n\nnested host の中で `$parent` が利用できる場合、include された template content からも参照できます。\n\n```html\n<div *include=\"'child-view'\"></div>\n```\n\n`child-view` template 内で `$parent` を読む場合は、どの host の data を参照しているのかを明確にします。\n\n\n#### conditionals and loops との併用\n\n`*include` は conditionals と組み合わせられます。\n\n```html\n<div *if=\"showCard\" *include=\"'card'\"></div>\n```\n\nloop 内で使うこともできます。\n\n```html\n<div *for=\"item of items\">\n  <div *include=\"'item-card'\"></div>\n</div>\n```\n\n各 iteration の scope は include された content に渡されます。\n\n同じ要素に `*each` と `*include` を置くのは避けます。container と include の責務が衝突しやすくなります。\n\n#### *import との関係\n\n`*include` と `*import` は content を注入する点では似ていますが、source が違います。\n\n- `*include`\n  - named template から取得します。\n  - network request は行いません。\n  - world/template registry を使います。\n\n- `*import`\n  - URL から HTML を取得します。\n  - network loading と cache が関係します。\n\n同じ project 内で再利用する partial には `*include`、外部 HTML を読む必要がある場合には `*import` を使います。\n\n\n#### 構造上の制限\n\n`*include` は、wrapper element の innerHTML を置き換えます。\n\nそのため、同じ element に次のような structural directives を重ねる場合は注意します。\n\n- `*each`\n- `*import`\n- `*innerHTML`\n- `*compose`\n\n複数の directive が同じ element の content ownership を持つと、どれが children を生成するのか分かりにくくなります。\n\n読みやすい構造にするには、wrapper を分けます。\n\n```html\n<div *for=\"item of items\">\n  <div *include=\"'item-card'\"></div>\n</div>\n```\n\n\n#### 比較 - *include と *import\n\n`*include`:\n\n- local / registered template を使います。\n- network loading はありません。\n- 同じ template を繰り返し使う用途に向きます。\n- world lookup が関係します。\n\n`*import`:\n\n- external URL から HTML を読み込みます。\n- cache や recursion guard が関係します。\n- 外部 partial を読み込む用途に向きます。\n\n迷った場合、同じ document / same app 内で定義できる template なら `*include` を優先します。\n\n\n#### 推奨される使い方\n\n- 再利用する UI fragment には `*template` と `*include` を使います。\n- template name は短く明確にします。\n- include された content が期待する data shape を明確にします。\n- loop 内で include する場合、template 内で loop variable を読むことを前提にできます。\n- 同じ要素で content ownership を持つ directives を混在させないでください。\n- external HTML が必要な場合だけ `*import` を使います。\n\n\n#### 追加例\n\ntemplate switching の例:\n\n```html\n<div *include=\"mode === 'compact' ? 'card-compact' : 'card-full'\"></div>\n```\n\nloop 内の include:\n\n```html\n<div *for=\"post of posts\">\n  <div *include=\"'post-card'\"></div>\n</div>\n```\n\n条件付き include:\n\n```html\n<section *if=\"ready\">\n  <div *include=\"'ready-view'\"></div>\n</section>\n```\n\n\n#### 注意点\n\n- `*include` と `n-include` は同じ挙動です。\n- `*include` は named template の inner content を注入します。\n- wrapper element は残ります。\n- include された content は現在の scope で処理されます。\n- external URL から読み込む場合は `*import` を使います。\n",
  "innerHTML": "### *innerHTML\n\n#### 概要\n\n`*innerHTML` は、Sercrod expression の結果から要素の DOM `innerHTML` property を設定します。\nこれは、HTML markup を文字列として挿入するための低レベル directive です。\nalias の `n-innerHTML` も同じ挙動です。\n\nすでに HTML string を持っていて、それを plain text ではなく markup として挿入したい場合に使います。\n`*print` や `*textContent` と違い、`*innerHTML` は値を escape しません。global `html` filter を通し、その結果を `el.innerHTML` に直接代入します。\n\n#### 基本例\n\n```html\n<serc-rod data='{\"html\":\"<strong>Hello</strong>\"}'>\n  <div *innerHTML=\"html\"></div>\n</serc-rod>\n```\n\nこの例では、`html` の値が `div.innerHTML` に設定され、`strong` element として描画されます。\n\n#### 挙動\n\n基本規則:\n\n- 属性値は現在の scope で評価されます。\n- 評価結果は HTML candidate として扱われます。\n- 値は global `html` filter を通ります。\n- filter の結果が要素の `innerHTML` に設定されます。\n- element 自体は残り、その children が置き換えられます。\n- `n-innerHTML` は `*innerHTML` と同じ alias です。\n\n`null`、`undefined`、`false` のような値は、空の HTML として扱うのが安全です。実際の正規化は runtime の filter と assignment に従います。\n\n#### 評価タイミング\n\n`*innerHTML` は element の描画中に評価されます。\n\n1. element が描画対象になります。\n2. `*innerHTML` expression が現在の scope で評価されます。\n3. 結果が `html` filter に渡されます。\n4. filter result が `innerHTML` に代入されます。\n5. 通常の child template は、その element では置き換えられます。\n\n`*innerHTML` を持つ element の children は、通常の template content としては扱わない方が明確です。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst raw = evaluate(innerHTMLExpression, scope);\nconst safeHtml = Sercrod._filters.html(raw, {\n        el,\n        scope,\n        expr: innerHTMLExpression\n});\n\nelement.innerHTML = safeHtml;\n```\n\n実際の runtime は、error handling、clone、attribute cleanup、null handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*innerHTML` は変数を作りません。\n\n- 現在の scope を読みます。\n- host data を直接変更しません。\n- local helper scope を作りません。\n- DOM の innerHTML を更新します。\n\n必要な HTML string を作るために、ancestor `*let` や method を使えます。\n\n```html\n<div *let=\"body = article.html\">\n  <section *innerHTML=\"body\"></section>\n</div>\n```\n\n\n#### 親へのアクセス\n\nnested host の中で `$parent` が利用できる場合、`*innerHTML` expression からも参照できます。\n\n```html\n<div *innerHTML=\"$parent.safeHtml\"></div>\n```\n\nただし、親 data から HTML を挿入する場合でも、HTML の出所と安全性を確認します。\n\n\n#### conditionals and loops との併用\n\nconditionals と組み合わせられます。\n\n```html\n<div *if=\"html\" *innerHTML=\"html\"></div>\n```\n\nloop 内でも使えます。\n\n```html\n<div *for=\"block of blocks\" *innerHTML=\"block.html\"></div>\n```\n\n各 block の HTML が挿入されます。user-generated content の場合は、必ず sanitize された値だけを使います。\n\n\n#### template・*include・*import との併用\n\n`*innerHTML` は HTML string を直接挿入します。\n\n再利用可能な template content を扱うなら、`*include` の方が適している場合があります。\n\n外部 URL から HTML を読みたい場合は `*import` を使います。\n\n使い分け:\n\n- 既に data にある HTML string を挿入する: `*innerHTML`\n- named template を挿入する: `*include`\n- URL から HTML を読み込む: `*import`\n- plain text を出す: `*print` または `*textContent`\n\n#### 安全性と html フィルター\n\n`*innerHTML` は HTML を挿入するため、security 上の注意が必要です。\n\n信頼できない入力をそのまま渡すと XSS の危険があります。\n\n原則:\n\n- user-generated content を raw HTML として扱わない。\n- HTML を許可する場合は server 側または `html` filter で sanitize する。\n- text で十分なら `*print` / `*textContent` を使う。\n- HTML を含む data field の命名で、safe な HTML かどうかを明確にする。\n\nSercrod は `html` filter を通しますが、その filter が何を保証するかは project 設定に依存します。\n\n\n#### 推奨される使い方\n\n- safe HTML として確認済みの値だけを渡します。\n- user input は直接入れません。\n- text 出力には `*print` / `*textContent` を使います。\n- reusable UI fragment には `*include` を検討します。\n- 外部 partial には `*import` を検討します。\n- `*innerHTML` を持つ要素に複雑な child directives を置かないでください。\n\n#### 追加例\n\n安全な article body:\n\n```html\n<article *innerHTML=\"article.safeHtml\"></article>\n```\n\n条件付き HTML:\n\n```html\n<div *if=\"messageHtml\" *innerHTML=\"messageHtml\"></div>\n```\n\nmethod 由来の HTML:\n\n```html\n<div *innerHTML=\"renderMarkdown(markdown)\"></div>\n```\n\n#### 注意点\n\n- `*innerHTML` と `n-innerHTML` は同じ挙動です。\n- `*innerHTML` は HTML string を DOM markup として挿入します。\n- 値は `html` filter を通ります。\n- plain text には使わないでください。\n- 信頼できない HTML は直接挿入しないでください。\n",
  "input": "### *input\n\n#### 概要\n\n`*input` は、form control の value を data path に bind します。\n`<input>`、`<textarea>`、`<select>` などの DOM control を、Sercrod の data または staged data 内の field と同期させます。\nalias の `n-input` も同じ挙動です。\n\n`*input` は value-level binding に焦点を当てています。また、変更後に host をどの頻度で再描画するかを制御するために、`*lazy` や `*eager` と一緒に使われます。\n\n\n#### 基本例\n\n`form.name` に bind された単純な text field です。\n\n```html\n<serc-rod id=\"app\" data='{\"form\":{\"name\":\"Alice\"}}'>\n  <label>\n    Name:\n    <input type=\"text\" *input=\"form.name\">\n  </label>\n\n  <p>Hello, %form.name%</p>\n</serc-rod>\n```\n\nuser が input の値を変更すると、Sercrod はその値を `form.name` に書き戻します。\nhost が update されると、`%form.name%` を読む表示も更新されます。\n\n\n#### 挙動\n\n`*input` は、対象 form control の値を指定された data path へ書き戻します。\n\n基本規則:\n\n- 属性値は data path または assignment target として扱われます。\n- `*input=\"form.name\"` は、control の値を `form.name` に書き戻します。\n- `n-input` は `*input` の alias です。\n- control の種類により、読み取られる値が変わります。\n- `*stage` が有効な host では、書き込み先は staged data になります。\n- `*lazy` / `*eager` が timing を調整します。\n\n`*input` は user input から data への書き戻しを担当します。\ndata から DOM value へ明示的に出す場合は `:value` と組み合わせることもできます。\n\n\n#### 式の構文\n\n一般的な形式:\n\n```html\n<input *input=\"name\">\n```\n\nnested path の例:\n\n```html\n<input *input=\"form.email\">\n```\n\narray item や loop item:\n\n```html\n<input *for=\"item of items\" *input=\"item.name\">\n```\n\n`*input` の値は、通常は代入可能な data path にします。\n\n複雑な式や関数呼び出しを左辺のように使う設計は避けます。読みやすく、Sercrod が書き戻せる path を指定します。\n\n\n#### 評価タイミング\n\n`*input` の書き戻し timing は、control type と timing directives によって変わります。\n\n通常の考え方:\n\n- user が値を変更します。\n- Sercrod が control の現在値を読みます。\n- 指定された data path に値を書き込みます。\n- 必要に応じて host が update されます。\n\n`*lazy` がある場合、type-then-action flow を優先し、入力中の親 template refresh を抑える方向に働きます。\n\n`*eager` がある場合、入力中の変更を即時に UI へ反映する方向に働きます。\n\ntext input では、`*lazy` と `*eager` の違いが特に重要です。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\ncontrol.addEventListener(inputOrChangeEvent, (event)=>{\n        const value = readControlValue(control);\n        writeValueToDataPath(scope, inputPath, value);\n        updateAccordingToTimingRules();\n});\n```\n\n実際の runtime は、input type、stage buffer、lazy/eager flags、checkbox/radio/select の value rules、update scheduling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*input` は新しい variable を作るための directive ではありません。\n\n指定された path に値を書き込みます。\n\n```html\n<input *input=\"profile.name\">\n```\n\nこの場合、`profile.name` が書き込み先です。\n\npath の途中の object が存在しない場合、runtime がどこまで補完するかに依存するため、data shape はあらかじめ安定させるのが安全です。\n\n```html\n<serc-rod data='{\"profile\":{\"name\":\"\"}}'>\n```\n\nloop 内では、loop item の property を書き換えることがあります。\n\n```html\n<input *for=\"item of items\" *input=\"item.name\">\n```\n\nここで `item` が data 内 object への reference であれば、変更はその object に反映されます。\n\n\n#### 親へのアクセス\n\nnested host で `$parent` が利用できる場合、`*input` path から親 data を参照できる場合があります。\n\n```html\n<input *input=\"$parent.form.name\">\n```\n\nただし、input が親 data を直接変更する構造は、data ownership が分かりにくくなる可能性があります。必要な場合に限り、明示的に使います。\n\n\n#### conditionals and loops との併用\n\n条件分岐:\n\n```html\n<input *if=\"editing\" *input=\"name\">\n```\n\nこの input は、`editing` が true のときだけ存在します。\n\nloop の例:\n\n```html\n<input\n  *for=\"field of fields\"\n  *input=\"field.value\">\n```\n\n各 input は、それぞれの `field.value` を更新します。\n\nloop item が object reference の場合、変更は元の collection に反映されます。\n\n\n#### *stage・*lazy・*eager との併用\n\n`*stage` と組み合わせると、input edits は committed data ではなく stage buffer に入ります。\n\n```html\n<serc-rod data='{\"profile\":{\"name\":\"Alice\"}}' *stage>\n  <input *input=\"profile.name\">\n  <button type=\"button\" *apply>Save</button>\n  <button type=\"button\" *restore>Cancel</button>\n</serc-rod>\n```\n\n`*lazy`:\n\n- type-then-submit / type-then-send のような flow に向きます。\n- 入力ごとの親 template refresh を抑えます。\n- Send button など次の action を自然に扱いやすくします。\n\n`*eager`:\n\n- live preview、live search、counter、即時 validation に向きます。\n- 入力中の変更をすぐに周辺 UI へ反映します。\n\n同じ input に `*lazy` と `*eager` を同時に付けるべきではありません。\n\n\n#### 推奨される使い方\n\n- data shape をあらかじめ用意します。\n- `*input` の path は短く、代入可能な形にします。\n- user input の同期には `*input` を使い、単なる表示には `:value` を使います。\n- type-then-action には `*lazy` を検討します。\n- live update には `*eager` を検討します。\n- staged editing では `*stage`、`*apply`、`*restore` と組み合わせます。\n- 複雑な value conversion は method に分けます。\n\n\n#### 追加例\n\ntextarea の例:\n\n```html\n<textarea *input=\"message\"></textarea>\n```\n\nselect の例:\n\n```html\n<select *input=\"category\">\n  <option value=\"news\">News</option>\n  <option value=\"blog\">Blog</option>\n</select>\n```\n\ncheckbox の例:\n\n```html\n<input type=\"checkbox\" *input=\"accepted\">\n```\n\nloop 内の field:\n\n```html\n<input *for=\"row of rows\" *input=\"row.name\">\n```\n\nlazy な message send:\n\n```html\n<input type=\"text\" *input=\"message\" *lazy>\n<button type=\"button\" @click=\"send(message)\">Send</button>\n```\n\neager な preview:\n\n```html\n<input type=\"text\" *input=\"title\" *eager>\n<h2>%title%</h2>\n```\n\n\n#### 注意点\n\n- `*input` と `n-input` は同じ挙動です。\n- `*input` は form control value を data path へ書き戻します。\n- `*lazy` と `*eager` は update timing を調整します。\n- staged host では、書き込み先は stage buffer になります。\n",
  "into": "### *into\n\n#### 概要\n\n`*into` は、外部と通信する一部の Sercrod directives の結果を受け取る data slot を選びます。\n主に `*api`、`*upload`、`*websocket` と一緒に使われ、response や message を root data object 上の named field に保存します。\n\n`*into` には alias として `n-into` があります。どちらも同じ挙動です。\n\n要点:\n\n- `*into` は単独では何もしません。\n- `*api`、`*upload`、`*websocket` など、明示的に `*into` を読む directives によって参照されます。\n- 値は destination key または path として扱われます。\n- 結果を template から読める data field に保存するために使います。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"user\":null}'>\n  <section *api=\"/api/user.json\" *into=\"user\">\n    <p *if=\"user\">Hello, %user.name%</p>\n  </section>\n</serc-rod>\n```\n\nこの例では、`*api` の response が `user` に保存されます。\n`user` が更新されると、children はその値を読めます。\n\n\n#### 挙動\n\n`*into` は destination を宣言する companion directive です。\n\n基本規則:\n\n- `*into` の値は保存先の名前として扱われます。\n- それ自体では request や update を実行しません。\n- `*api`、`*upload`、`*websocket` などが response を保存する際に参照します。\n- destination が存在しない場合、runtime が初期化する場合があります。\n- 同じ destination に複数の directive が書き込むと、後から完了したものが上書きします。\n\n`*into=\"result\"` は、通常 `data.result` に値を保存するという意味です。\n\n\n#### 評価タイミング\n\n`*into` 自体は request timing を決めません。\n\ntiming は companion directive によって決まります。\n\n- `*api` なら request 完了時。\n- `*upload` なら upload 完了時。\n- `*websocket` なら message 受信時、または接続状態更新時。\n- その他の directive では、その directive が `*into` を読むかどうかに依存します。\n\nrendering 中には、runtime が `*into` の値を読み、destination を準備します。\n\n\n#### 実行モデル\n\n概念的には、`*api` などの directive の中で次のように使われます。\n\n```js\nconst into = element.getAttribute(\"*into\") || element.getAttribute(\"n-into\");\n\nif(into){\n        data[into] = responseData;\n}\n```\n\n実際の runtime は path handling、stage handling、status flags、events、error handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*into` は expression scope に local variable を作りません。\n\nただし、destination が host data に存在しない場合、response 保存時にその data field が作られることがあります。\n\n```html\n<section *api=\"/api/user\" *into=\"user\">\n```\n\nこの場合、`user` が data に存在しない場合でも、request 完了後に `user` が作られる可能性があります。\n\n安定した template にするには、初期 data に destination を用意しておく方が分かりやすいです。\n\n```html\n<serc-rod data='{\"user\":null}'>\n```\n\n\n#### スコープの重なりと親へのアクセス\n\n`*into` は通常、現在の host data に書き込みます。\n\nnested host で親 data へ保存したい場合は、project の設計を慎重に考える必要があります。`*into` の destination は、通常の expression ではなく destination key として扱われるため、`$parent.foo` のような書き方が常に意図通り動くとは限りません。\n\n親 data へ明示的に書く必要がある場合は、event handler や method で扱う方が明確です。\n\n\n#### *api との併用\n\n`*api` との基本形:\n\n```html\n<section *api=\"/api/items.json\" *into=\"items\">\n  <ul>\n    <li *for=\"item of items\">%item.name%</li>\n  </ul>\n</section>\n```\n\n`*api` の response が `items` に入ります。\n\n`$pending`、`$error`、`$download`、`$upload` などの status fields と一緒に使うと、loading / error UI を作れます。\n\n\n#### *upload との併用\n\nupload result を保存する例です。\n\n```html\n<input type=\"file\" *api=\"/api/upload\" *into=\"uploadResult\">\n```\n\nまたは `*upload` が `*into` を読む設計の場合:\n\n```html\n<input type=\"file\" *upload=\"/api/upload\" *into=\"uploadResult\">\n```\n\nupload 完了後、result が `uploadResult` に保存されます。\n\n\n#### *websocket との併用\n\nWebSocket message を保存する場合にも `*into` を使えます。\n\n```html\n<div *websocket=\"wsUrl\" *into=\"lastMessage\">\n  <p>%lastMessage%</p>\n</div>\n```\n\n実際に何が保存されるかは、`*websocket` の仕様と message handling に依存します。\n\n\n#### 推奨される使い方\n\n- response を template から読む場合は `*into` を明示します。\n- 初期 data に destination を用意しておきます。\n- 同じ `*into` を複数の request が共有する場合、上書き timing を理解します。\n- destination name は response の意味が分かる名前にします。\n- `*into` 単独では何もしないことを理解します。\n- parent data への書き込み用途には安易に使わないでください。\n\n\n#### 例\n\nAPI result の例:\n\n```html\n<section *api=\"/api/profile\" *into=\"profile\">\n  <h2 *if=\"profile\">%profile.name%</h2>\n</section>\n```\n\nupload result の例:\n\n```html\n<input type=\"file\" *api=\"/api/avatar\" *into=\"avatarResult\">\n```\n\nWebSocket message の例:\n\n```html\n<div *websocket=\"socketUrl\" *into=\"message\">\n  <p>%message%</p>\n</div>\n```\n\n\n#### 注意点\n\n- `*into` と `n-into` は同じ挙動です。\n- `*into` は destination を宣言するだけです。\n- 実際に値を書き込むのは `*api`、`*upload`、`*websocket` などの companion directive です。\n- destination は初期 data に用意しておくと安全です。\n",
  "lazy": "### *lazy\n\n#### 概要\n\n`*lazy` は、Sercrod が full re-render を過度に行わないようにする小さな flag directive です。\n\n主な役割は2つあります。\n\n- Sercrod host (`<serc-rod>`) 上:\n  - `*lazy` が有効な場合、通常の internal update では host template 全体を再構築しません。\n  - host は child Sercrod instances への変更伝播と `*updated` hooks の実行を中心に行います。\n  - forced update では full rebuild が行われます。\n\n- `*input` / `n-input` を持つ form control 上:\n  - `*lazy` は、change event を使って入力値を commit するかどうかを制御します。\n  - text input や textarea では、入力中の親 template refresh を抑え、type-then-action flow を自然にします。\n\nalias の `n-lazy` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"message\":\"\"}'>\n  <input type=\"text\" *input=\"message\" *lazy>\n  <button type=\"button\" @click=\"send(message)\">Send</button>\n</serc-rod>\n```\n\nこの pattern では、ユーザーが入力してから Send を押す流れを優先します。\n入力中の各 keystroke で親 template 全体を再描画しないため、click 前に focus や DOM が不自然に作り直されることを避けやすくなります。\n\n\n#### 挙動\n\n`*lazy` は timing と update 範囲を調整する flag です。\n\nhost 上の `*lazy`:\n\n- 通常 update で full template rebuild を抑えます。\n- child Sercrod hosts への update propagation を行います。\n- `*updated` hooks を実行します。\n- forced update では full rebuild を許可します。\n\nform control 上の `*lazy`:\n\n- `*input` の値書き戻し timing を、入力中の即時更新から commit 寄りにします。\n- text editing 中の parent refresh を避けます。\n- user が入力後に button を押す flow で、最初の click が入力 commit だけで消費されにくくなります。\n\n`*lazy` は値を無視するという意味ではありません。値は必要な timing で data に反映されます。\n\n\n#### 評価タイミング\n\n`*lazy` 自体は式を評価しません。\n\npresence が意味を持つ flag です。\n\n```html\n<input *input=\"name\" *lazy>\n```\n\nまたは alias:\n\n```html\n<input *input=\"name\" n-lazy>\n```\n\n`*lazy=\"false\"` のような値を runtime がどう扱うかは実装方針に依存しますが、通常は presence-based directive として考えます。\n\n入力 event や update timing において、Sercrod はその要素または host が lazy かどうかを見ます。\n\n\n#### 実行モデル\n\nhost-level lazy の概念的な処理です。\n\n```js\nif(hostIsLazy && !forced){\n        updateChildren();\n        runUpdatedHooks();\n        finalize();\n} else {\n        rebuildHostTemplate();\n}\n```\n\nform-control lazy の概念的な処理です。\n\n```js\nonInputOrChange(event){\n        writeValueWhenCommitted();\n        avoidImmediateParentRefreshWhenAppropriate();\n}\n```\n\n実際の runtime は、input type、stage buffer、eager/lazy flags、keyboard event、forced updates を考慮します。\n\n\n#### 変数の作成\n\n`*lazy` は変数を作りません。\n\n- host data に新しい property を追加しません。\n- scope に local name を追加しません。\n- 値の変換を行いません。\n\nこれは update timing と rendering strategy のための flag です。\n\n\n#### スコープの重なり\n\n`*lazy` は scope layering を直接変更しません。\n\nただし、host-level lazy では update 時に full rebuild を避けるため、どの子 host が更新されるか、どの hook が呼ばれるかに影響します。\n\nform control 上では、`*input` の書き込み先は通常どおり現在の scope / stage に従います。`*lazy` はその timing を調整します。\n\n\n#### 親へのアクセス\n\n`*lazy` は `$parent` を直接扱いません。\n\nnested host で lazy update を使う場合、親 host と子 host の更新範囲が分かれることがあります。\n親全体を再描画せず、子 Sercrod instances を更新したい場合に useful です。\n\n\n#### conditionals and loops との併用\n\n`*lazy` は conditionals や loops の中の input に使えます。\n\n```html\n<input *for=\"field of fields\" *input=\"field.value\" *lazy>\n```\n\n各 input は、その field の値を lazy timing で扱います。\n\n条件付きに表示される input では、表示/非表示の切り替えで DOM が作り直されるため、lazy timing と focus behavior を意識します。\n\n\n#### 推奨される使い方\n\n- type-then-submit、type-then-send、type-then-apply の flow に使います。\n- 入力中の live preview が必要な場合は `*eager` を使います。\n- `*input` と組み合わせて使います。\n- host-level lazy は、full rebuild を避けたい host で使います。\n- `*lazy` と `*eager` を同じ input に同時に付けないでください。\n- 値を無視する機能ではなく、update timing を変える機能として説明します。\n\n\n#### 追加例\n\nlazy な form field:\n\n```html\n<input type=\"text\" *input=\"title\" *lazy>\n```\n\nsend button 付き lazy textarea:\n\n```html\n<textarea *input=\"message\" *lazy></textarea>\n<button type=\"button\" @click=\"send(message)\">Send</button>\n```\n\nlazy host の例:\n\n```html\n<serc-rod data='{\"count\":0}' *lazy>\n  <button type=\"button\" @click=\"count = count + 1\">Add</button>\n  <serc-rod>\n    <p>%$parent.count%</p>\n  </serc-rod>\n</serc-rod>\n```\n\n#### 注意点\n\n- `*lazy` と `n-lazy` は同じ挙動です。\n- `*lazy` は値を無視する directive ではありません。\n- input 上では commit timing と parent refresh の抑制に関係します。\n- host 上では full rebuild を抑える update strategy に関係します。\n- live update には `*eager` を使います。\n",
  "let": "### *let\n\n#### 概要\n\n`*let` は、Sercrod の sandbox 内で小さな JavaScript を実行し、local helper variables を定義します。\n\nここで作られた変数は、同じ要素と、そのすべての子孫要素の式から利用できます。\n\n新しく作られた変数名は host data にも昇格されるため、同じ `<serc-rod>` の中で後に続く要素もそれらを読むことができます。\n\n`*let` は、template の中で派生値を作るための仕組みです。既存の host data を直接上書きするための仕組みではありません。\n\nalias の `n-let` も同じ挙動です。\n\n\n#### 基本例\n\n派生値を一度計算し、その要素の subtree 内で再利用する例です。\n\n```html\n<serc-rod id=\"invoice\" data='{\"price\": 1200, \"qty\": 3}'>\n  <p *let=\"total = price * qty\">\n    Total: <span *print=\"total\"></span>\n  </p>\n</serc-rod>\n```\n\nこの例では、`total` が現在の scope 内で作られ、`p` の中の `*print` から参照できます。\n\n同じ host の後続要素でも、promotion 後の `total` を読めます。\n\n\n#### 挙動\n\n大まかに言うと、`*let` は「現在の data scope でこの code を実行し、新しく作られた変数を保持する」仕組みです。\n\n- host `<serc-rod>` の現在の data と、scope 内の iteration variables を読みます。\n- `*let` の文字列を JavaScript として sandboxed scope 内で実行します。\n- 新しく作られた名前は local scope に追加されます。\n- その local scope は、同じ要素と descendants の effective scope になります。\n- host data にまだ存在しない top-level names は host data に promoted されます。\n- host data にすでに存在する top-level names は、promotion では上書きされません。\n\nそのため、`*let` は「一時的な helper を作る」用途と、「後続の template から読める派生値を作る」用途の両方に使えます。\n\n\n#### 式の評価モデル\n\n`*let` の値は JavaScript code として扱われます。\n\n- code は Sercrod の expression sandbox の中で、専用の scope object を使って実行されます。\n- 1つまたは複数の simple statements を書けます。\n- assignments によって新しい helper names を作れます。\n- `Math` などの組み込み global object を読むことはできます。\n- 書き込みは本物の global object ではなく、local scope に入ります。\n\n例:\n\n```html\n<div *let=\"\n  subtotal = price * qty;\n  total = subtotal * taxRate;\n\">\n  %total%\n</div>\n```\n\n複雑な処理や再利用される処理は、`*methods` や外部関数へ移す方が読みやすくなります。\n\n\n#### 評価タイミング\n\n`*let` は、要素ごとの pipeline の早い段階で評価されます。\n\n- 同じ要素上の structural directives より前に処理されます。\n- `*let` が作った values は、同じ要素の `*if`、`*for`、bindings、children から利用できる場合があります。\n- loop の中では、各 iteration ごとに current item を含む scope で評価されます。\n\nこの timing により、`*let` は「この要素以下で使う準備値」を作るのに向いています。\n\n\n#### 実行モデル\n\n概念的には、Sercrod は要素上の `*let` を次のように処理します。\n\n1. この要素の current effective scope `effScope` を計算します。\n   - `<serc-rod>` の host data が基礎になります。\n   - loop variables や parent scope values も含まれます。\n2. `effScope` をもとに local `letScope` を作ります。\n3. `*let` の code を `letScope` に対して実行します。\n4. 実行後、その要素と descendants の effective scope を `letScope` にします。\n5. `letScope` 内の keys を確認します。\n6. host data に存在しない keys は host data に promoted されます。\n7. host data にすでに存在する keys は上書きされません。\n\nこのため、既存 data の top-level property を代入しても、それは local shadowing になりやすく、host data の直接上書きにはなりません。\n\n\n#### 変数の作成と promotion\n\n`*let` は、次の2種類を区別します。\n\n- `*let` によって新しく作られた variable names。\n- host data にすでに存在している data properties。\n\n新しい名前:\n\n```html\n<p *let=\"total = price * qty\">%total%</p>\n```\n\n`total` が host data に存在しなければ、初回 render 後に host data へ promoted されます。\n\n既存の名前:\n\n```html\n<p *let=\"price = price * 1.1\">%price%</p>\n```\n\n`price` がすでに host data にある場合、`letScope.price` は変わりますが、host data の `price` は promotion によって上書きされません。\n\nただし、既存 object の nested property を変更する場合は reference 経由の変更になることがあります。\n\n```html\n<p *let=\"user.name = 'Bob'\">%user.name%</p>\n```\n\nこの場合、`user` object が host data の object と同じ reference であれば、nested property は変更されます。\n\n\n#### スコープの重なりと親へのアクセス\n\n`*let` 内では、通常の expression から見える値と同じものを参照できます。\n\n- host data fields。\n- loop variables。\n- ancestor `*let` values。\n- `$data`。\n- `$root`。\n- `$parent`。\n- imported methods。\n\nnested `<serc-rod>` の中では、`$parent` が親 host data を指す場合があります。\n\n```html\n<serc-rod data='{\"shared\": {\"count\": 1}}'>\n  <serc-rod data='{}'>\n    <p *let=\"localCount = $parent.shared.count\">\n      %localCount%\n    </p>\n  </serc-rod>\n</serc-rod>\n```\n\n親 data の object を reference 経由で変更する式を書くこともできますが、意図が明確な場合だけにします。\n\n\n#### conditionals and loops との併用\n\n`*let` は conditionals や loops と組み合わせて使えます。\n\n同じ要素に `*if` を置く例です。\n\n```html\n<div *let=\"canShow = user && user.active\" *if=\"canShow\">\n  %user.name%\n</div>\n```\n\nloop 内で派生値を作る例です。\n\n```html\n<li *for=\"item of items\" *let=\"total = item.price * taxRate\">\n  %item.name%: %total%\n</li>\n```\n\n各 iteration で別々の `total` が作られます。\n\nただし、new top-level names は host data へ promoted される可能性があるため、loop 内の helper names は衝突しにくい名前にするか、children 内だけで使う設計にします。\n\n\n#### 推奨される使い方\n\n- 新しい helper variables を作る用途に使います。\n  - `total`、`label`、`normalizedUsers` などの派生値に適しています。\n- 既存 host data を上書きするために使わないでください。\n- 永続的な data mutation には `*global`、event handler、method などを使います。\n- complex logic は外部 method に移します。\n- loop 内では helper name の promotion に注意します。\n- nested property mutation は host data を変更する可能性があるため、意図を明確にします。\n\n\n#### 追加例\n\nsiblings と派生値を共有する例です。\n\n```html\n<serc-rod id=\"totals\" data='{\"items\":[{\"name\":\"A\",\"price\":100},{\"name\":\"B\",\"price\":200}]}'>\n  <div *let=\"total = items.reduce((sum, item) => sum + item.price, 0)\">\n    Total: %total%\n  </div>\n\n  <p>Again: %total%</p>\n</serc-rod>\n```\n\nloop item から表示用 label を作る例です。\n\n```html\n<li *for=\"user of users\" *let=\"label = user.name + ' (' + user.role + ')'\">\n  %label%\n</li>\n```\n\n親 data を読む例です。\n\n```html\n<div *let=\"themeName = $parent.theme\">\n  %themeName%\n</div>\n```\n\n\n#### 注意点\n\n- `*let` と `n-let` は aliases です。\n- code は Sercrod の sandbox 内で実行され、通常の global script に直接書く場合とは違います。\n- `*let` は既存の host data properties を上書きしません。host data に promoted されるのは新しく作られた名前です。\n- `Math` などの global built-in objects を読むことはできますが、書き込みは本物の global environment ではなく local scope に入ります。\n- nested object への変更は reference 経由で host data に反映される場合があります。\n",
  "literal": "### *literal\n\n#### 概要\n\n`*literal` は、Sercrod 風の markup や template 風の text を、Sercrod に展開または解釈させず、書いた通りに保持したい場合に使います。\n\n典型的な用途は次の通りです。\n\n- Sercrod の例を documentation 内に表示する。\n- `%name%` のような placeholder を文字として表示する。\n- 他の template engine 用の markup を、そのまま残す。\n- `*if` や `*for` のように見える文字列を実行させずに表示する。\n\nalias の `n-literal` も同じ挙動です。\n\n\n#### 基本例\n\nSercrod markup を実行せず、code として表示する例です。\n\n```html\n<serc-rod id=\"docs\">\n  <pre *literal>\n    <p *if=\"visible\">%message%</p>\n  </pre>\n</serc-rod>\n```\n\nこの場合、`*if` や `%message%` は Sercrod によって処理されません。文字として残ります。\n\n\n#### 挙動\n\n基本ルール:\n\n- 要素に `*literal` または `n-literal` がある場合、Sercrod はその要素の content を plain text として扱います。\n- その要素内の directives や interpolation markers は実行されず、文字として保存されます。\n- `*literal` が付いた要素自体は clone されます。\n- `*literal` / `n-literal` 属性は出力から取り除かれます。\n- inner markup は、Sercrod の通常の child rendering pipeline には入りません。\n\nつまり、`*literal` はその要素内で Sercrod の解釈を短絡させます。\n\n\n#### Sercrod を text として保持する用途\n\n`*literal` の主な設計目的は、Sercrod markup 自体を表示することです。\n\n- Sercrod templates を例としてページ内に書けます。\n- `%user.name%` や `%item.price%` を placeholder の文字として保持できます。\n- documentation、playground、template preview などで、実行前の markup を見せられます。\n\n例:\n\n```html\n<code *literal>\n  <button @click=\"count++\">%count%</button>\n</code>\n```\n\nこの中の `@click` や `%count%` は実行されません。\n\n\n#### 属性 source と innerHTML source\n\nよく使う pattern は2つあります。\n\n1. Boolean-style `*literal`、つまり innerHTML source。\n\n```html\n<pre *literal>\n  <p *if=\"ok\">OK</p>\n</pre>\n```\n\nこの場合、要素の中身が literal text として扱われます。\n\n2. Attribute value source。\n\n```html\n<pre *literal=\"<p *if='ok'>OK</p>\"></pre>\n```\n\nこの場合、属性値を literal output として使う設計が可能です。\n\nどちらを使うかは、project の表示形式や escaping のしやすさで決めます。長い HTML 例では、innerHTML source の方が読みやすいことが多いです。\n\n\n#### 評価タイミング\n\n`*literal` は rendering pipeline の早い段階で処理されます。\n\nmain render flow では、Sercrod は次のように扱います。\n\n- element に `*literal` / `n-literal` があるかを確認します。\n- 見つかった場合、その element の内部を通常の Sercrod template としては処理しません。\n- literal content を text として出力します。\n- その後、その element の child directives は実行されません。\n\nこのため、`*literal` の内側に `*if`、`*for`、`@click` などを書いても、それらは directive として働きません。\n\n\n#### 実行モデル\n\n概念的には、`*literal` を持つ要素は次のように処理されます。\n\n1. Sercrod が要素上の `*literal` / `n-literal` を検出します。\n2. literal source を読みます。\n   - 属性値が使われる場合があります。\n   - そうでなければ要素の inner markup が source になります。\n3. output element を clone します。\n4. `*literal` / `n-literal` 属性を削除します。\n5. source を text として挿入します。\n6. child rendering は行いません。\n\n実際の runtime では escaping や text insertion の細部が含まれます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*literal` は変数を作成または変更しません。\n\n- 新しい local variables は導入しません。\n- `$data`、`$root`、`$parent` などの scope entries には影響しません。\n- host data を読み書きしません。\n- 内側の template 風 text も scope を持ちません。\n\n`*literal` の内側に見える `%value%` は、あくまで文字です。\n\n\n#### 親へのアクセス\n\nSercrod は `*literal` block の中へ降りていかないため、内部には nested Sercrod scope がありません。\n\n- 内側の markup が Sercrod のように見えても、ただの text です。\n- `$parent` や `$root` を参照しているように見える文字列も評価されません。\n- 内側の `<serc-rod>` のような文字列も、通常は実行される template ではありません。\n\n親 data に基づいて literal block の外側を切り替えたい場合は、親要素で `*if` などを使います。\n\n\n#### conditionals and loops との併用\n\n`*literal` を「内側をすべて plain text にする」と考えると、規則は単純です。\n\n- `*literal` と他の directives を同じ要素で組み合わせるのは概念的に衝突します。\n- 外側の wrapper に `*if` や `*for` を置き、内側の要素に `*literal` を置く方が安全です。\n\n推奨:\n\n```html\n<section *if=\"showExample\">\n  <pre *literal>\n    <button @click=\"count++\">%count%</button>\n  </pre>\n</section>\n```\n\nloop 内で例を表示する場合:\n\n```html\n<div *for=\"example of examples\">\n  <pre *literal=\"example.source\"></pre>\n</div>\n```\n\nただし、attribute value source を使う場合は escaping に注意します。\n\n\n#### 推奨される使い方\n\n- Sercrod markup や `%placeholders%` を text として表示したい場合に使います。\n  - Sercrod 自体の documentation。\n  - email template previews。\n  - 別の template engine の placeholder を含む content。\n- `*literal` の内側に動かしたい Sercrod directives を置かないでください。\n- condition や loop は外側の wrapper に置きます。\n- 長い code examples では `<pre *literal>` を使うと読みやすくなります。\n- user-generated HTML を literal 表示する場合でも、表示先が text として扱われることを確認します。\n\n\n#### 追加例\n\nouter logic と literal block の組み合わせです。\n\n```html\n<serc-rod id=\"examples\" data='{\"show\":\"counter\"}'>\n  <section *if=\"show === 'counter'\">\n    <pre *literal>\n      <serc-rod data='{\"count\":0}'>\n        <button @click=\"count++\">%count%</button>\n      </serc-rod>\n    </pre>\n  </section>\n</serc-rod>\n```\n\nplaceholder を保持する例です。\n\n```html\n<pre *literal>\nDear %customer.name%,\nYour order %order.id% has shipped.\n</pre>\n```\n\nattribute source の例です。\n\n```html\n<code *literal=\"`<p *print=&quot;message&quot;></p>`\"></code>\n```\n\n\n#### 注意点\n\n- `*literal` と `n-literal` は aliases です。project 内ではどちらかに統一します。\n- `*literal` は早い段階で評価され、その要素内の Sercrod 解釈を止めます。\n- 主目的は、Sercrod-style markup や他の template を text として残すことです。\n- 同じ要素上で他の directives と組み合わせることは実用上 support されません。外側の要素で制御します。\n",
  "load": "### *load / *load.file / *load.session / *load.store\n\n#### 概要\n\n`*load.file` は、ユーザーが選択した JSON file を読み込み、Sercrod host の data に merge します。\n`*load.session` は、browser の `sessionStorage` から JSON を読み込み、同じ merge rules で data に反映します。\n`*load.store` は、persistent browser storage、現在は IndexedDB、から JSON を読み込み、同じ merge rules で data に反映します。\n`*load` は互換用の古い file load 形式として残ります。\n\n`*keys` で読み込む top-level keys を選べます。`*into` がある場合だけ、その property に読み込み結果を入れます。\n\n#### 基本例\n\nfile から読み込みます。\n\n```html\n<button type=\"button\" *load.file *keys=\"profile\" *into=\"draft\">\n  Load file\n</button>\n```\n\nsessionStorage から読み込みます。\n\n```html\n<button type=\"button\" *load.session=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load session\n</button>\n```\n\npersistent browser storage から読み込みます。\n\n```html\n<button type=\"button\" *load.store=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load store\n</button>\n```\n\n#### merge rules\n\n- `*keys` も `*into` もない場合: 読み込んだ JSON object 全体を `_stage` または `_data` に `Object.assign` します。\n- `*keys` だけがある場合: 指定された top-level keys だけを `_stage` または `_data` に copy します。\n- `*into` がある場合: 読み込んだ全体、または `*keys` で選んだ値を、その property に入れます。\n- `*keys` が 1 個で `*into` がある場合: `json[key]` を `data[into]` に入れます。\n- `*keys` が複数で `*into` がある場合: 選択 key だけを持つ object を `data[into]` に入れます。\n\n#### 挙動\n\n- `*load.file` は file picker と `FileReader` を使います。\n- `*load.session` の値は `sessionStorage` key です。\n- `*load.store` の値は persistent browser storage key です。\n- `*load.store` は既定で IndexedDB database `sercrod-store` の object store `json` から JSON string を読みます。\n- key が存在しない場合、JSON parse に失敗した場合、IndexedDB が使えない場合は、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-loaded` event を dispatch し、host を update します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"load\"`、session では `\"load.session\"`、store では `\"load.store\"`。\n- `detail.fileName`: file load の file name。\n- `detail.storage`: session/store load では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*load.session` または `*load.store` の key。\n- `detail.into`: `*into` の destination、なければ `null`。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 読み込まれた JSON object。\n\n#### 互換性\n\n古い形式の `*load=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*load.file` / `*load.session` / `*load.store` と `*keys` / `*into` を使ってください。\n",
  "log": "### *log\n\n#### 概要\n\n`*log` は式を評価し、その結果を、式そのものと短い host snippet とあわせて log に出力します。\n\nSercrod template 向けの軽量 debugging helper です。\n\nalias の `n-log` も同じ挙動です。\n\n`*log` は application logic のための directive ではなく、inspection と debugging のためのものです。\n\n\n#### 基本例\n\n値を console に出す例です。\n\n```html\n<serc-rod id=\"app\" data='{\"user\":{\"name\":\"Alice\",\"age\":30}}'>\n  <pre *log=\"user\"></pre>\n</serc-rod>\n```\n\nrender 後、`user` の評価結果が debugging output として表示または console に出力されます。\n\n\n#### 挙動\n\n基本的な挙動:\n\n- `*log` は現在の Sercrod scope で expression を評価します。\n- 次の3つの情報を整形します。\n  - 評価した expression。\n  - 評価結果。\n  - 対象 host の短い snippet。\n- `<pre>` など、表示用 element の場合は、debug text として出力される場合があります。\n- console logging にも使われます。\n- data は変更しません。\n\n`*log` は描画結果の確認、scope の確認、data path の確認に使います。\n\n\n#### 式の規則\n\n`*log` の属性値は通常の Sercrod expression です。\n\n典型的な使い方:\n\n```html\n<pre *log=\"user\"></pre>\n<pre *log=\"items.length\"></pre>\n<pre *log=\"{ user, items }\"></pre>\n```\n\n式は現在の scope で評価されます。\n\n利用できるもの:\n\n- host data。\n- loop variables。\n- `*let` values。\n- `$data`、`$root`、`$parent`。\n- imported methods。\n\n評価 error が起きた場合は、debug output または warning で確認します。\n\n\n#### 評価タイミング\n\n`*log` は Sercrod host の lifecycle に結び付いています。\n\n- host が通常 render、つまり `_renderTemplate` を完了した後、internal flag index が再構築されます。\n- その後、Sercrod は log evaluation を schedule します。\n- 実際の logging は `requestAnimationFrame` callback 内で trigger されます。\n- これにより、render 完了後の状態に近い context で log を確認できます。\n\nつまり、`*log` は element を見つけた瞬間に即座に console 出力するというより、render 後の inspection hook として動きます。\n\n\n#### 実行モデル\n\n内部的には、Sercrod は `*log` をおおよそ次のように実行します。\n\n1. render 中に、`*log` または `n-log` を持つ elements の index を作ります。\n2. host render と index rebuild の後、`requestAnimationFrame` 内で `_call_log_hooks(scope)` を schedule します。\n3. 各 log element について、属性値の expression を読みます。\n4. 現在の scope で expression を評価します。\n5. expression、result、host snippet を整形します。\n6. console または element text として出力します。\n\n実際の runtime は error handling と output formatting を含みます。\n\n\n#### スコープと変数\n\n`*log` は新しい変数を導入せず、既存の変数も変更しません。\n\n- current scope をそのまま読み、expression をその scope で評価します。\n- 通常の scope features を使えます。\n  - data fields。\n  - loop variables。\n  - `*let` values。\n  - `$data`、`$root`、`$parent`。\n  - methods。\n\n`*log` は read-only diagnostic として扱います。debug のために data mutation を含む式を書くのは避けてください。\n\n\n#### conditionals and loops との併用\n\n`*log` は他の directives と自然に組み合わせられます。\n\n`*if` と使う例:\n\n```html\n<pre *if=\"debug\" *log=\"form\"></pre>\n```\n\nloop 内で使う例:\n\n```html\n<pre *for=\"item of items\" *log=\"item\"></pre>\n```\n\n各 iteration では、その iteration の `item` を log できます。\n\nただし、loop 内の大量 log は console を汚しやすいため、必要なときだけ使います。\n\n\n#### 推奨される使い方\n\n- visible debug output が必要な場合は `<pre *log>` を使います。\n  - browser console を見にくい環境で便利です。\n  - JSON や structured data の inspection に向きます。\n- production UI に残さないでください。\n- data mutation を含む expression は書かないでください。\n- 大量 loop 内での log は避けます。\n- 複雑な object は `JSON.stringify(value, null, 2)` なども検討します。\n- 問題切り分けでは、`*log` と `sercrod-change` debug hook を併用できます。\n\n\n#### 例\n\nhost data 全体を確認する例です。\n\n```html\n<serc-rod id=\"app\" data='{\"user\":{\"name\":\"Alice\"},\"debug\":true}'>\n  <pre *if=\"debug\" *log=\"$data\"></pre>\n</serc-rod>\n```\n\nloop item を確認する例です。\n\n```html\n<div *for=\"row of rows\">\n  <pre *log=\"row\"></pre>\n</div>\n```\n\n計算結果を確認する例です。\n\n```html\n<pre *log=\"items.map(item => item.id)\"></pre>\n```\n\n\n#### 注意点\n\n- `*log` と `n-log` は aliases です。project 内では表記を統一します。\n- `*log` は diagnostic directive です。\n  - data を更新しません。\n  - `*if`、`*for`、`*each` のような structural decision には参加しません。\n- render 後の確認に使うため、timing は通常の inline expression とは少し異なります。\n- debug 完了後は削除するか、debug flag で制御します。\n",
  "man": "### *man / n-man\n\n#### 概要\n\n`*man` は、Sercrod の組み込み manual / inspection directive です。\n\n短い built-in help を console に表示でき、`<pre>` 要素上では `man.json` から読み込んだ長い manual text を表示できます。\n\n日本語版 `man.json` では、人間向け・Sercrod 参照用の manual entry を置きます。AI 専用の `__ai_*` entries は含めません。\n\n\n#### 出力挙動\n\n`<pre>` 要素上では次のように動きます。\n\n- 値なしの `*man` は top-level manual index を表示します。\n- `*man=\"directives\"` は directive list を表示します。\n- `*man=\"debug\"` は debug manual entry を表示します。\n- `*man=\"*post\"` や `*man=\"@click\"` は、対応する detailed entry を表示します。\n\n`<pre>` 以外の要素では、短い help や console output として使われる場合があります。\n\nexternal `man.json` が使える場合、`<pre>` では外部 manual text が優先されます。\n\n\n#### 重要なルール\n\n具体的な feature keys には prefix を含めます。\n\n- Sercrod directives:\n  - `*post`\n  - `*fetch`\n  - `*input`\n- event bindings:\n  - `@click`\n  - `@submit`\n  - `@input`\n- その他の named entries:\n  - `debug`\n  - `keyboard-events`\n  - `attributes`\n\nruntime は `*man=\"*post\"` のような request を、manual key `post` などに解決する場合があります。\n\n`*case.break` のような dotted directive は、`case.break` のような key に対応します。\n\n互換性のための alias がある場合でも、正本の key を優先します。\n\n\n#### 外部 man.json\n\nSercrod は長い manual text を `man.json` から読み込めます。\n\n外部 file が利用可能な場合、`<pre *man=\"...\">` は requested key に対応する external full text を優先します。built-in short help は fallback や console output 用として残ります。\n\ni18n 対応の manual file が存在する場合は、その file を優先して読みます。存在しない場合だけ共通の `man.json` に fallback します。\n\nどちらも存在しない場合は、manual の外部説明がないものとして扱います。\n\n\n#### 例\n\n```html\n<pre *man></pre>\n<pre *man=\"directives\"></pre>\n<pre *man=\"debug\"></pre>\n<pre *man=\"*post\"></pre>\n<pre *man=\"@click\"></pre>\n<pre *man=\"keyboard-events\"></pre>\n```\n\nbutton で manual key を切り替えるような UI も作れます。\n\n```html\n<serc-rod data='{\"topic\":\"*input\"}'>\n  <pre *man=\"topic\"></pre>\n</serc-rod>\n```\n\n\n#### AI assistant 向けの注意\n\n- 外部 manual entry が存在する場合は、詳細な external manual を優先します。\n- built-in short help は fallback または quick inspection aid として使います。\n- `*man` が存在することから、未定義の directive behavior を推測してはいけません。\n- `*man` は documentation を説明・表示するものであり、documented directive の action を実行するものではありません。\n- 日本語版 `man.json` では AI 専用の `__ai_*` entries は除外します。\n",
  "methods": "### *methods\n\n#### 概要\n\n`*methods` と `n-methods` は、global functions を Sercrod host に import し、その host 内の expressions から呼び出せるようにします。\n\n- 属性値は space-separated list of names です。\n- 各 name は次のいずれかを指します。\n  - `window[name]` が function の場合、その function。\n  - `window[name]` が object の場合、その object 内の functions。\n- imported methods は、host 内の Sercrod expressions から名前で呼び出せます。\n\nこれは、template 内の inline expression を短くし、複雑な logic を JavaScript 側に置くための仕組みです。\n\n\n#### 基本例\n\nsingle global function の例です。\n\n```html\n<script>\nwindow.formatPrice = function(value){\n        return value.toLocaleString() + \" yen\";\n};\n</script>\n\n<serc-rod data='{\"price\":1200}' *methods=\"formatPrice\">\n  <p>%formatPrice(price)%</p>\n</serc-rod>\n```\n\n`formatPrice` が expression scope に入り、interpolation から呼び出せます。\n\n\n#### 挙動\n\n`*methods` は Sercrod host element 上の属性です。\n\n- custom element class の `observedAttributes` によって監視されます。\n- 属性が変わると、値が tokens に分割され `_methods_names` として保存されます。\n- expression evaluation 時に、Sercrod はそれらの names を `window` から解決します。\n- function はその名前で scope に追加されます。\n- object container の場合は、その object 内の function members を scope に追加する場合があります。\n\n`*methods` は一般要素用の directive ではなく、host configuration です。\n\n\n#### 設定構文\n\n`*methods` と `n-methods` は space-separated list of identifiers を受け取ります。\n\nhost 上:\n\n```html\n<serc-rod *methods=\"formatPrice validateEmail\">\n</serc-rod>\n```\n\nmethod container の例:\n\n```html\n<script>\nwindow.AppMethods = {\n        formatPrice(value){\n                return value.toLocaleString();\n        },\n        isValidEmail(value){\n                return value.includes(\"@\");\n        }\n};\n</script>\n\n<serc-rod *methods=\"AppMethods\">\n</serc-rod>\n```\n\n複数指定もできます。\n\n```html\n<serc-rod *methods=\"AppMethods MoreMethods helperFunction\">\n</serc-rod>\n```\n\n名前は whitespace で分割されます。\n\n\n#### 評価タイミング\n\n`*methods` は、Sercrod が各 expression の sandbox を作る時点で expression evaluation に影響します。\n\n- `*if`、`*for`、`*each`、`*input`、interpolations、bindings などの general expressions では、Sercrod は `eval_expr(expr, scope, opt)` を呼びます。\n  - current `scope` から `merged` scope object を作ります。\n  - host data と stage を含めます。\n  - `*methods` から解決された functions を追加します。\n  - expression はこの merged scope で評価されます。\n\n- `*let` では、`eval_let` の scope に methods が入り、helper code から呼び出せるようになります。\n\nつまり、`*methods` は render 時に一度だけ値を固定するのではなく、expression evaluation ごとに解決される scope に関係します。\n\n\n#### 実行モデル\n\npseudocode では、`*methods` 付きの evaluation は次のようになります。\n\n- `eval_expr` の場合:\n\n```js\nconst merged = createScopeFrom(scope, hostData, stage);\n\nfor(const name of host._methods_names){\n        const value = window[name];\n\n        if(typeof value === \"function\"){\n                merged[name] = value;\n        } else if(value && typeof value === \"object\"){\n                for(const key of Object.keys(value)){\n                        if(typeof value[key] === \"function\"){\n                                merged[key] = value[key];\n                        }\n                }\n        }\n}\n\nreturn evaluateExpression(expr, merged);\n```\n\n実際の runtime は error handling や sandboxing を含みます。\n\n重要なのは、method names は expression scope に追加され、template から呼べるようになるという点です。\n\n\n#### スコープと解決順\n\n`*methods` を持つ host 上で expression 内の `foo()` を呼ぶ場合、Sercrod は実質的に次の順で `foo` を解決します。\n\n1. Local scope。\n   - loop variables。\n   - `*let` bindings。\n   - その他の近い scope entries。\n2. Host `data` と、それに関連する stage buffer。\n3. Imported methods from `*methods`。\n4. sandbox が許可する built-ins や global read fallback。\n\nこの順序により、local scope や data property が method name と衝突すると、method が隠れる場合があります。\n\nmethod names は data fields と衝突しにくい名前にします。\n\n\n#### 条件分岐・ループ・バインディングとの併用\n\n`*methods` は、この host 内で `eval_expr` や `eval_let` に依存する directives に影響します。たとえば次です。\n\n- Conditional directives:\n  - `*if`\n  - `*elseif`\n  - `*else` chain の conditions。\n- Loop directives:\n  - `*for`\n  - `*each`\n- Output:\n  - `%expr%` interpolation。\n  - `*print`。\n  - `*textContent`。\n- Attribute bindings:\n  - `:class`\n  - `:style`\n  - `:href`\n  - generic `:name` bindings。\n- `*let` expressions。\n\n例:\n\n```html\n<serc-rod data='{\"items\":[1,2,3]}' *methods=\"isEven\">\n  <p *for=\"n of items\" *if=\"isEven(n)\">\n    %n%\n  </p>\n</serc-rod>\n```\n\n\n#### event との併用\n\nevent handlers、たとえば `@click`、`@input` などは、別の helper `eval_event` で評価されます。この helper は built-in window fallback を持ちます。\n\n- event expressions は default で `window` を見られる場合があります。\n- そのため、event handler からは `*methods` がなくても global functions を直接呼べることがあります。\n- ただし、render expressions でも同じ function を使うなら、`*methods` に入れておく方が一貫します。\n\n例:\n\n```html\n<button type=\"button\" @click=\"save(form)\">Save</button>\n```\n\n`save` が global function なら、event handler からは呼べる場合があります。ただし、`%saveLabel(form)%` のような rendering expression で使うなら `*methods` が必要です。\n\n\n#### 推奨される使い方\n\n- 関連 helper は method containers にまとめます。\n  - `AppMethods`\n  - `Formatters`\n  - `Validators`\n- inline expression は短く保ちます。\n- data fields と method names が衝突しないようにします。\n- event handlers と rendering expressions の両方で使う functions は `*methods` に明示します。\n- host element に書き、普通の子要素には書かないでください。\n- project 内で `*methods` と `n-methods` の表記を統一します。\n\n\n#### 例\n\n複数 container の例です。\n\n```html\n<script>\nwindow.Formatters = {\n        price(value){\n                return value.toLocaleString() + \" yen\";\n        }\n};\n\nwindow.Validators = {\n        required(value){\n                return value != null && value !== \"\";\n        }\n};\n</script>\n\n<serc-rod data='{\"price\":1200,\"name\":\"\"}' *methods=\"Formatters Validators\">\n  <p>%price(price)%</p>\n  <p *if=\"!required(name)\">Name is required.</p>\n</serc-rod>\n```\n\nsingle function と container を混ぜる例です。\n\n```html\n<serc-rod *methods=\"formatDate AppMethods\">\n</serc-rod>\n```\n\n\n#### 注意点\n\n- `*methods` と `n-methods` は Sercrod host 上の属性です。任意の要素に付ける汎用 directive ではありません。\n- 属性値は変更されるたびに space-separated list として parse されます。\n- 各 name について、Sercrod は evaluation time に `window[name]` を見ます。\n  - function はその名前で import されます。\n  - object の中の function members は scope に展開される場合があります。\n- `*methods` は inline JavaScript を増やすためではなく、template expression を短く安全に保つための仕組みです。\n",
  "post": "### *post\n\n#### 概要\n\n`*post` は、現在の Sercrod host data を JSON として指定 URL へ HTTP POST し、JSON response を host data へ書き戻します。\n\n通常は、Sercrod host 内の button や同種の control に付けます。\n\n`*post` と `n-post` は aliases です。\n\nsimple form submit や contact form のように、「現在の data をそのまま送信し、response を data に戻す」用途に向いています。\n\n\n#### 基本例\n\nすべての data を post し、response を `result` に保存する最小 contact form です。\n\n```html\n<serc-rod id=\"contact\" data='{\n  \"form\": {\n    \"name\": \"\",\n    \"email\": \"\"\n  },\n  \"result\": null\n}'>\n  <input type=\"text\" *input=\"form.name\">\n  <input type=\"email\" *input=\"form.email\">\n\n  <button type=\"button\" *post=\"/api/contact:result\">\n    Send\n  </button>\n\n  <p *if=\"result\">%result.message%</p>\n</serc-rod>\n```\n\nbutton を click すると、host data が JSON として `/api/contact` に送られ、response が `result` に書き込まれます。\n\n\n#### 挙動\n\nattachment と rendering:\n\n- `*post` は、Sercrod host 内の通常要素を描画するときに評価されます。\n- runtime は attributes と children を含めて element を deep clone します。\n- clone から `*post` / `n-post` を削除します。\n- clone に click handler を取り付けます。\n- clone は output DOM に追加されます。\n- click 時に POST request が実行されます。\n\n`*post` element は action trigger として扱います。同じ要素の中に複雑な Sercrod directives を重ねるのは避けます。\n\n\n#### request 指定\n\n`*post` の属性値は compact な `URL[:prop]` 形式です。\n\n- `URL` は HTTP POST の送信先です。\n- `prop` は response をどこへ書き戻すかを指定する optional data path です。\n\n例:\n\n```html\n<button *post=\"/api/save\">Save</button>\n```\n\nresponse は host data 全体または default handling に従って扱われます。\n\n```html\n<button *post=\"/api/save:result\">Save</button>\n```\n\nresponse は `result` に書き込まれます。\n\n`*post` の属性値は literal string として扱われます。`*fetch` のような URL placeholder expansion は行わないものとして考えます。\n\n\n#### data source と JSON encoding\n\nrequest body を作るとき、`*post` は次の source を使います。\n\n- host が staged data を持つ場合:\n  - `_stage` を優先します。\n- stage がなければ:\n  - `_data` を使います。\n\nつまり、staged editing 中は user が編集している staged values が送信されます。\n\nbody は JSON として encode されます。\n\n典型的な headers:\n\n```text\nContent-Type: application/json\n```\n\n送信される object は host data/stage そのものなので、server 側はその data shape を受け取る前提で実装します。\n\n\n#### response handling と書き戻し\n\nPOST request が完了すると、response は2段階で処理されます。\n\n1. HTTP response から `value` と `text` を導きます。\n2. `prop` に従って `value` を host data へ書き戻します。\n\nresponse が JSON として parse できる場合:\n\n- JSON value が writeback 対象になります。\n\nJSON として parse できない場合:\n\n- text response が fallback として扱われる場合があります。\n\n`prop` がある場合:\n\n```html\n<button *post=\"/api/save:result\">Save</button>\n```\n\nresponse は `data.result` に入ります。\n\n`prop` がない場合、runtime の default rule に従って data 全体への merge や writeback が行われます。template と server response の shape を揃えることが重要です。\n\n\n#### 状態フラグとエラー報告\n\n`*post` は `*api` や `*fetch` と同じ state slots を共有します。\n\n初回利用時に、host data 上に次の properties が存在することを保証します。\n\n- `$pending`\n- `$error`\n- `$download`\n- `$upload`\n\nPOST request 中:\n\n- `$pending` は true になります。\n\n成功後:\n\n- `$pending` は false になります。\n- response は `$upload` や指定 prop へ保存される場合があります。\n\nerror 時:\n\n- `$pending` は false になります。\n- `$error` に error object が入ります。\n- `sercrod-error` event が dispatch される場合があります。\n\nUI では次のように状態を表示できます。\n\n```html\n<p *if=\"$pending\">Sending...</p>\n<p *if=\"$error\">%$error.message%</p>\n```\n\n\n#### イベント\n\n`*post` は lifecycle 中に3つの dedicated events を emit します。\n\n- `sercrod-post-start`\n- `sercrod-post-success`\n- `sercrod-post-error`\n\nこれらの event detail には、URL、host、element、response data、error などが含まれる場合があります。\n\ndebugging、logging、analytics、project-level error handling で利用できます。\n\n```js\ndocument.addEventListener(\"sercrod-post-error\", (event)=>{\n        console.log(event.detail);\n});\n```\n\n\n#### stage data との連携 - *stage・*apply・*restore\n\n`*post` は Sercrod の staging directives と連携するように設計されています。\n\n- host が `*stage` または `n-stage` を使う場合、host は editable snapshot を持つ staging buffer `_stage` を保持します。\n- `*post` は request body を作るとき、この buffer を先に見ます。\n- `_stage` が存在すれば、committed `_data` ではなく `_stage` が送信されます。\n\nこれにより、user は staged form を編集し、その staged values を server へ送信できます。\n\n`*apply` は staged values を committed data に反映します。\n\n`*restore` は staged edits を破棄します。\n\n送信と apply のどちらを先に行うかは、UI の設計として明確にします。\n\n\n#### *fetch と *api との関係\n\n`*post` は `*fetch` や `*api` といくつかの概念を共有しますが、責務は異なります。\n\n- `*post`:\n  - host data を JSON として POST する simple helper。\n  - click trigger に向く。\n  - response を data へ書き戻す。\n- `*fetch`:\n  - GET JSON loading 向け。\n  - URL から data を取得する。\n- `*api`:\n  - method、body、headers、upload、status flags、`*into` などを扱う汎用 HTTP primitive。\n\nmethod や body を細かく指定したい場合は `*api` を使います。\n\n\n#### サーバー側の契約と推奨 API 形式\n\n`*post`、`*fetch`、`*api` はどれも HTTP communication を「JSON in, JSON out」として扱い、state flags も共有するため、server-side handlers も一定の response shape に揃えると扱いやすくなります。\n\nserver 側の推奨 approach:\n\n```json\n{\n  \"ok\": true,\n  \"message\": \"Saved\",\n  \"data\": {\n    \"id\": 1\n  }\n}\n```\n\ntemplate が `result.message` を読むなら、`*post=\"/api/save:result\"` の response は `message` を持つ object である必要があります。\n\n```html\n<p *if=\"result\">%result.message%</p>\n```\n\nserver response shape を変更する場合は、template path も同時に変更します。\n\n\n#### 推奨される使い方\n\n- `*post` element は simple に保ちます。\n  - static content を持つ button または link として扱います。\n  - 同じ要素やその内部に他の Sercrod directives を多く置くのは避けます。\n- action-only control には `button type=\"button\"` を使います。\n- response destination には `:result` のような prop を明示します。\n- `$pending` と `$error` を UI に出します。\n- server response shape と template path を一致させます。\n- staged editing と組み合わせる場合、送信対象が stage なのか committed data なのかを説明します。\n- method や request body を細かく制御したい場合は `*api` を使います。\n\n\n#### 注意点\n\n- `*post` と `n-post` は exact aliases です。1つの要素ではどちらか一方だけを使います。\n- `*post` は Sercrod host 内の通常要素でのみ処理されます。host-level behavior はありません。\n- `*post` 属性は literal string として扱われます。expression expansion や base URL resolution は行われません。\n- response は読み取れる限り data perspective では成功として扱われる場合があります。HTTP status と application-level success は server response shape で明確にします。\n- `*post` は simple JSON POST helper です。より複雑な HTTP 操作には `*api` を使います。\n",
  "prevent-default": "### *prevent-default\n\n#### 概要\n\n`*prevent-default` は、要素に passive helper を取り付け、指定された browser default behavior を抑止するための directive です。\n\n主に link click、form submit、drag/drop、keyboard 操作などで、browser の既定動作を止めたい場合に使います。\n\nalias の `n-prevent-default` も同じ挙動です。\n\nevent attribute の `.prevent` modifier と似ていますが、`*prevent-default` は要素側に declarative に付ける helper です。\n\n\n#### 基本例\n\nlink の navigation を止める例です。\n\n```html\n<a href=\"/fallback\" *prevent-default @click=\"open = true\">\n  Open modal\n</a>\n```\n\nこの例では、click 時に browser の link navigation を抑止し、`@click` expression で `open` を true にします。\n\n\n#### 挙動\n\n`*prevent-default` は、対象要素に default prevention 用の event listener を取り付けます。\n\n基本規則:\n\n- 属性が存在することに意味があります。\n- 属性値が空の場合、主に click や submit などの標準的な default action を止める用途になります。\n- 属性値がある場合、mode や event name を指定する場合があります。\n- 実際に抑止する event は runtime の実装規則に従います。\n- `event.preventDefault()` を呼び、必要に応じて browser default behavior を止めます。\n\n`*prevent-default` は Sercrod data を直接変更しません。data を変更する場合は、`@click` や `@submit` などの event handler を組み合わせます。\n\n\n#### モード\n\nmode を使うことで、どの default behavior を止めるかを明示できる場合があります。\n\n例:\n\n```html\n<form *prevent-default=\"submit\" @submit=\"save()\">\n```\n\n```html\n<a *prevent-default=\"click\" @click=\"open = true\">\n```\n\nよくある対象:\n\n- `click`\n- `submit`\n- `dragover`\n- `drop`\n- keyboard 系 event\n\nproject の runtime が support する mode に合わせて使います。\n\n何を止めたいのかが明確な場合は、event modifier の `.prevent` の方が読みやすい場合もあります。\n\n\n#### 評価タイミング\n\n`*prevent-default` は element が描画されるときに処理されます。\n\n1. Sercrod が element を clone します。\n2. `*prevent-default` / `n-prevent-default` を検出します。\n3. clone に default prevention 用 listener を取り付けます。\n4. clone が DOM に追加されます。\n5. 対象 event が発生すると、listener が `preventDefault()` を呼びます。\n\n属性値を expression として評価する用途ではなく、主に declarative helper として扱います。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nelement.addEventListener(targetEvent, (event)=>{\n        event.preventDefault();\n});\n```\n\n実際の runtime は、mode、event type、listener options、他の event handlers との順序を考慮します。\n\n`@click.prevent` のような event modifier とは別の経路ですが、結果として `preventDefault()` を呼ぶ点は同じです。\n\n\n#### スコープと変数\n\n`*prevent-default` は scope variables を作りません。\n\n- host data を読みません。\n- host data を書きません。\n- `$event` を expression として処理しません。\n- `*let` のような local scope を作りません。\n\nこの directive は DOM event の default behavior にだけ関わります。\n\n\n#### event handler と modifier との併用\n\n`*prevent-default` は `@event` と組み合わせて使えます。\n\n```html\n<a href=\"/fallback\" *prevent-default @click=\"open = true\">\n  Open\n</a>\n```\n\n同じ意味を event modifier で書くこともできます。\n\n```html\n<a href=\"/fallback\" @click.prevent=\"open = true\">\n  Open\n</a>\n```\n\n通常は、どちらか1つに統一する方が読みやすくなります。\n\n- event handler と同じ場所で止めたい場合:\n  - `.prevent`\n- 要素の基本性質として default を止めたい場合:\n  - `*prevent-default`\n\n#### 推奨される使い方\n\n- navigation や submit を意図的に止める場合だけ使います。\n- 可能なら、`button type=\"button\"` を使って、そもそも不要な default action を避けます。\n- `a href=\"#\"` を action control として使う場合は、必ず default prevention を明示します。\n- `@click.prevent` と `*prevent-default` を重複させないようにします。\n- form submit の制御には `@submit.prevent` も検討します。\n\n\n#### 追加例\n\nform submit を止める例です。\n\n```html\n<form *prevent-default=\"submit\" @submit=\"save(form)\">\n  <button type=\"submit\">Save</button>\n</form>\n```\n\ndragover を許可するために default を止める例です。\n\n```html\n<div *prevent-default=\"dragover\" @drop=\"handleDrop($event)\">\n  Drop files here\n</div>\n```\n\nlink action の例:\n\n```html\n<a href=\"/fallback\" *prevent-default @click=\"showHelp = true\">\n  Help\n</a>\n```\n\n\n#### 注意点\n\n- `*prevent-default` と `n-prevent-default` は aliases です。\n- data binding ではなく DOM event helper です。\n- `event.preventDefault()` を呼ぶことが主目的です。\n- event modifier `.prevent` と役割が重なる場合があります。\n",
  "prevent": "### *prevent\n\n#### 概要\n\n`*prevent` は `*prevent-default` の短縮形です。\n\nbrowser default behavior を止めたい要素に付けます。`n-prevent` も同じ挙動です。\n\nより明示的な名前が必要な場合は `*prevent-default` を使い、短く書きたい場合は `*prevent` を使います。\n\n\n#### 基本例\n\n```html\n<a href=\"/fallback\" *prevent @click=\"open = true\">\n  Open modal\n</a>\n```\n\nこの例では、click 時の navigation が抑止され、Sercrod の `@click` expression が実行されます。\n\n\n#### 挙動\n\n`*prevent` は `*prevent-default` と同じ default prevention helper として扱われます。\n\n- 属性が存在することに意味があります。\n- browser default action を止めるために `event.preventDefault()` を呼びます。\n- 属性値がある場合は、mode または event name として扱われる場合があります。\n- data は直接変更しません。\n- event handler と組み合わせて使うことが多いです。\n\n`*prevent` は意味として短い alias なので、詳細な挙動は `*prevent-default` と同じと考えます。\n\n\n#### *prevent-default との関係\n\n次の2つは同等です。\n\n```html\n<a *prevent @click=\"open = true\">Open</a>\n```\n\n```html\n<a *prevent-default @click=\"open = true\">Open</a>\n```\n\nproject 内では、読みやすさのためにどちらかの表記へ統一します。\n\n- documentation や明示性重視:\n  - `*prevent-default`\n- 短さ重視:\n  - `*prevent`\n\nevent modifier の `.prevent` も同じ目的に使えます。\n\n```html\n<a @click.prevent=\"open = true\">Open</a>\n```\n\n#### mode の詳細\n\n`*prevent` に値を指定することで、どの event の default behavior を止めるかを表せる場合があります。\n\n```html\n<form *prevent=\"submit\" @submit=\"save()\">\n```\n\n```html\n<div *prevent=\"dragover\" @drop=\"drop($event)\">\n```\n\nmode の詳細は runtime の対応に依存します。\n\n明確な event handler がある場合は、次のように modifier を使う方が自然な場合もあります。\n\n```html\n<form @submit.prevent=\"save()\">\n```\n\n#### 評価タイミング\n\n`*prevent` は、要素の描画時に処理されます。\n\n1. element が clone されます。\n2. `*prevent` / `n-prevent` が検出されます。\n3. default prevention 用 listener が取り付けられます。\n4. DOM event 発生時に `preventDefault()` が呼ばれます。\n\n`*prevent` の値は通常の data expression として使うものではありません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nelement.addEventListener(targetEvent, (event)=>{\n        event.preventDefault();\n});\n```\n\n`targetEvent` は属性値や element type から決まる場合があります。\n\n実際の runtime は、`*prevent-default` と同じ path を使います。\n\n\n#### Sercrod event handler との関係\n\n`*prevent` は `@click` や `@submit` と組み合わせて使えます。\n\n```html\n<a href=\"/fallback\" *prevent @click=\"open = true\">\n  Open\n</a>\n```\n\nただし、同じ要素で次のように重ねると重複します。\n\n```html\n<a *prevent @click.prevent=\"open = true\">Open</a>\n```\n\n通常は片方で十分です。\n\nSercrod の event modifier と同じ意図なら、event attribute 側に `.prevent` を付ける方が読みやすい場合があります。\n\n\n#### 使用例\n\nよくある用途:\n\n- link navigation を止めて modal を開く。\n- form submission を止めて custom validation を行う。\n- dragover の default を止めて drop を受け付ける。\n- keyboard operation の default を止める。\n- browser default behavior と Sercrod action が衝突しないようにする。\n\nただし、可能な場合は HTML element の選び方で default action を避ける方が安全です。action button には `button type=\"button\"` を使います。\n\n\n#### 推奨される使い方\n\n- `*prevent` と `*prevent-default` の表記を project 内で統一します。\n- event handler と同じ場所で意味を示したい場合は `.prevent` を使います。\n- link を action として使う場合は default prevention を必ず明示します。\n- form submit では `@submit.prevent` を優先することも検討します。\n- browser default behavior を本当に止める必要があるか確認します。\n\n\n#### 追加例\n\nlink action の例:\n\n```html\n<a href=\"/help\" *prevent @click=\"showHelp = true\">Help</a>\n```\n\nsubmit 抑止:\n\n```html\n<form *prevent=\"submit\" @submit=\"validateAndSave()\">\n  <button type=\"submit\">Save</button>\n</form>\n```\n\ndrag/drop の例:\n\n```html\n<div *prevent=\"dragover\" @drop=\"dropFiles($event)\">\n  Drop here\n</div>\n```\n\n\n#### 注意点\n\n- `*prevent` と `n-prevent` は aliases です。\n- `*prevent` は `*prevent-default` の短縮形です。\n- data を変更する directive ではありません。\n- `.prevent` event modifier と役割が重なるため、重複しないようにします。\n",
  "print": "### *print\n\n#### 概要\n\n`*print` は Sercrod expression を評価し、その結果を text として要素内に出力します。\n\n出力は HTML として解釈されず、text として扱われます。\n\n単純な値、計算結果、JSON 文字列、debug 用の値などを表示する基本的な output directive です。\n\nalias の `n-print` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"message\":\"Hello\"}'>\n  <p *print=\"message\"></p>\n</serc-rod>\n```\n\n結果として、`p` の text content は `Hello` になります。\n\n\n#### 挙動\n\n基本規則:\n\n- `*print` の属性値は現在の scope で expression として評価されます。\n- 評価結果は text として正規化されます。\n- 要素の text content がその値に置き換えられます。\n- HTML は実行または展開されません。\n- element 自体は残ります。\n- `*print` は data を変更しません。\n\n`*print` は安全な text output の基本形です。HTML を挿入する必要がある場合は `*innerHTML` や `*compose` を使いますが、trusted content に限ります。\n\n\n#### 値の正規化と filter\n\n`*print` は、評価結果を text に変換します。\n\n典型的な扱い:\n\n- string:\n  - そのまま表示します。\n- number:\n  - 文字列に変換します。\n- boolean:\n  - `true` / `false` として表示されます。\n- `null` / `undefined`:\n  - 空文字になる、または空に近い表示になります。\n- object / array:\n  - runtime の正規化規則に従い、文字列化または JSON 風に表示される場合があります。\n\nproject が text filter を持つ場合、出力前にその filter を通る場合があります。\n\nHTML として扱いたくない値は `*print` を使います。\n\n\n#### 評価タイミング\n\n`*print` は element の描画中に評価されます。\n\n1. element が描画対象になります。\n2. `*print` の expression が現在の scope で評価されます。\n3. 結果が text に正規化されます。\n4. 要素の text content が更新されます。\n5. element の children は、通常は `*print` によって置き換えられるため、複雑な child directives と同じ要素で混在させない方が安全です。\n\ndata が変わり host が update されると、`*print` は再評価されます。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst value = evaluate(printExpression, scope);\nconst text = normalizeText(value);\n\nelement.textContent = text;\n```\n\n実際の runtime は clone、filters、error handling を含みます。\n\n\n#### 変数の作成\n\n`*print` は変数を作りません。\n\n- scope に新しい names を追加しません。\n- host data を変更しません。\n- `$data`、`$root`、`$parent` を変更しません。\n- expression の結果を DOM text として出力するだけです。\n\n\n#### スコープの重なり\n\n`*print` の expression は現在の scope で評価されます。\n\n参照できるもの:\n\n- host data。\n- loop variables。\n- ancestor `*let` values。\n- `$data`。\n- `$root`。\n- `$parent`。\n- imported methods。\n\n例:\n\n```html\n<li *for=\"item of items\">\n  <span *print=\"item.name\"></span>\n</li>\n```\n\n\n#### 親へのアクセス\n\nnested host 内で `$parent` が使える場合、`*print` からも参照できます。\n\n```html\n<span *print=\"$parent.title\"></span>\n```\n\nただし、親 data への依存が増えると template の見通しが悪くなるため、必要な場合に限ります。\n\n\n#### conditionals and loops との併用\n\n`*print` は `*if` や `*for` とよく組み合わせます。\n\n```html\n<p *if=\"user\" *print=\"user.name\"></p>\n```\n\n```html\n<li *for=\"item of items\" *print=\"item.label\"></li>\n```\n\n同じ要素で `*print` と children を併用すると、children が置き換えられるため注意します。\n\n必要なら wrapper を使います。\n\n```html\n<li *for=\"item of items\">\n  <span *print=\"item.label\"></span>\n</li>\n```\n\n\n#### text interpolation - %expr% との比較\n\n`%expr%` interpolation は text の一部に expression を埋め込みます。\n\n```html\n<p>Hello, %user.name%.</p>\n```\n\n`*print` は要素全体の text content を expression result で置き換えます。\n\n```html\n<p *print=\"user.name\"></p>\n```\n\n使い分け:\n\n- sentence の一部に値を埋めたい:\n  - `%expr%`\n- 要素全体に値を表示したい:\n  - `*print`\n- JSON や computed value を単独で出したい:\n  - `*print`\n\n#### 関連ディレクティブ - *textContent と *innerHTML\n\n`*textContent` は text content を設定する点で `*print` に近い directive です。\n\n`*innerHTML` は HTML として挿入します。\n\n使い分け:\n\n- plain text:\n  - `*print`\n  - `*textContent`\n- HTML:\n  - `*innerHTML`\n  - `*compose`\n\nHTML 出力は security risk があるため、trusted content か sanitize 済み content に限定します。\n\n\n#### 推奨される使い方\n\n- text output の基本には `*print` を使います。\n- HTML を出したいだけで `*print` を避ける必要はありません。`*print` は HTML を text として安全に表示します。\n- sentence 内の小さな値には `%expr%` を使います。\n- 同じ要素に複雑な children を置く場合は、`*print` を child `<span>` などに分けます。\n- object を表示する場合は `JSON.stringify(value, null, 2)` などで明示します。\n\n\n#### 追加例\n\nnumber の例:\n\n```html\n<span *print=\"count\"></span>\n```\n\ncomputed expression の例:\n\n```html\n<span *print=\"price * qty\"></span>\n```\n\nmethod の例:\n\n```html\n<span *print=\"formatPrice(total)\"></span>\n```\n\nJSON debug の例:\n\n```html\n<pre *print=\"JSON.stringify($data, null, 2)\"></pre>\n```\n\n\n#### 注意点\n\n- `*print` と `n-print` は aliases です。\n- `*print` は text output です。\n- HTML として解釈されません。\n- data を変更しません。\n- element の text content を置き換えます。\n",
  "rem": "### *rem\n\n#### 概要\n\n`*rem` は、Sercrod template 内に comment や memo を残すための directive です。\n\nruntime 出力では、その要素を実質的に無視または削除する用途に使います。\n\nalias の `n-rem` も同じ挙動です。\n\nSercrod 用の説明、作業メモ、temporary notes を template 内に置きたいが、rendered DOM には出したくない場合に使います。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"name\":\"Alice\"}'>\n  <p *rem=\"This is a note for developers.\"></p>\n  <p>%name%</p>\n</serc-rod>\n```\n\n`*rem` を持つ要素は rendered output に表示されません。\n\n\n#### 挙動\n\n基本規則:\n\n- `*rem` / `n-rem` を持つ要素は、Sercrod の render output から除外されます。\n- 属性値は memo text として扱われます。\n- 式として評価するものではありません。\n- children も通常は描画されません。\n- host data は変更されません。\n\nHTML comment に近い用途ですが、Sercrod の directive として template 上に書けます。\n\n\n#### 典型的な用途\n\nよくある用途:\n\n- Sercrod template 内の developer memo。\n- AI や人間向けの短い補足。\n- 一時的に要素を render から外す。\n- 後で戻す予定の block の marker。\n- 大きな section の説明。\n\nただし、公開 HTML に残ることを期待する comment ではありません。表示や出力に残したい説明には通常の HTML や `*literal` を使います。\n\n\n#### 評価タイミング\n\n`*rem` は rendering pipeline の早い段階で処理されます。\n\n1. element が検出されます。\n2. `*rem` / `n-rem` の presence が確認されます。\n3. その element は output に追加されません。\n4. children も処理されません。\n\nそのため、`*rem` 内に書いた Sercrod directives は実行されません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nif(element.hasAttribute(\"*rem\") || element.hasAttribute(\"n-rem\")){\n        return;\n}\n```\n\nつまり、rendering を短絡し、output には何も追加しません。\n\n\n#### 変数の作成とスコープの重なり\n\n`*rem` は変数を作りません。\n\n- host data を読み書きしません。\n- scope を拡張しません。\n- `$data`、`$root`、`$parent` に影響しません。\n- children の directives も実行されません。\n\n\n#### 親へのアクセス\n\n`*rem` は `$parent` を使いません。\n\n`*rem` の内部は描画されないため、inner content が `$parent` を参照していても評価されません。\n\n\n#### conditionals and loops との併用\n\n`*rem` は、他の directives と同じ要素で組み合わせるより、単独の memo element として使う方が分かりやすくなります。\n\n避ける例:\n\n```html\n<div *if=\"debug\" *rem=\"temporary\"></div>\n```\n\n`*rem` が output を止めるため、`*if` の意味は実用上ありません。\n\n推奨:\n\n```html\n<p *rem=\"This section is intentionally hidden in the runtime output.\"></p>\n```\n\n\n#### 推奨される使い方\n\n- template 内の人間向け memo に使います。\n- 表示したい説明には使わないでください。\n- 中に実行したい Sercrod code を置かないでください。\n- temporary disable として使う場合は、後で削除することを忘れないようにします。\n- 長い documentation を出したい場合は `*literal` や通常の HTML を検討します。\n\n\n#### 追加例\n\nsection memo の例:\n\n```html\n<p *rem=\"The following list is generated from posts.\"></p>\n<ul>\n  <li *for=\"post of posts\">%post.title%</li>\n</ul>\n```\n\ntemporary disable の例:\n\n```html\n<div *rem=\"Disabled until API endpoint is ready\">\n  <button *api=\"/api/new-feature\">Run</button>\n</div>\n```\n\nAI 向け template note:\n\n```html\n<p *rem=\"Do not change this data path without updating the API response.\"></p>\n```\n\n\n#### 注意点\n\n- `*rem` と `n-rem` は aliases です。\n- `*rem` は runtime output に表示するための comment ではありません。\n- `*rem` 内の directives は実行されません。\n- data や scope には影響しません。\n",
  "restore": "### *restore\n\n#### 概要\n\n`*restore` は、`*stage` によって作られた staged edits を破棄し、最後の committed snapshot から stage を復元する directive です。\n\n`*apply` が staged data を committed data に反映するのに対し、`*restore` は staged changes を捨て、編集前または最後に apply された状態へ戻します。\n\nalias の `n-restore` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{ \"profile\": { \"name\": \"Alice\" } }' *stage>\n  <input type=\"text\" *input=\"profile.name\">\n\n  <p>Preview: %profile.name%</p>\n\n  <button type=\"button\" *apply>Save</button>\n  <button type=\"button\" *restore>Cancel</button>\n</serc-rod>\n```\n\n`Cancel` を click すると、staged edits は破棄され、stage は committed snapshot から再作成されます。\n\n\n#### 挙動\n\n`*restore` は staged host 内の action control として働きます。\n\n基本規則:\n\n- `*restore` / `n-restore` の属性値は使われません。\n- click handler が取り付けられます。\n- click 時、host が stage を持っていれば、stage を最後の committed snapshot から復元します。\n- その後 host を update します。\n- stage がない場合は no-op です。\n\n`*restore` は committed data を直接書き換えるための directive ではありません。stage を元に戻すためのものです。\n\n\n#### *stage と *apply との関係\n\n`*stage`、`*apply`、`*restore` は一組で考えると分かりやすくなります。\n\n- `*stage`\n  - host data の editable copy、つまり stage buffer を作ります。\n- `*apply`\n  - stage buffer の内容を committed data に merge します。\n  - その後、新しい committed snapshot を保存します。\n- `*restore`\n  - stage buffer を最後の committed snapshot から作り直します。\n  - 未 apply の edits を破棄します。\n\nこれにより、form editing、preview、cancel、save の flow を作れます。\n\n\n#### 評価タイミング\n\n`*restore` は render 時に検出され、click 時に実行されます。\n\n1. Sercrod が element を描画します。\n2. `*restore` / `n-restore` を検出します。\n3. clone に click handler を取り付けます。\n4. user が click します。\n5. host に stage があれば snapshot から stage を復元します。\n6. host を update します。\n\n属性値は expression として評価されません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nbutton.addEventListener(\"click\", ()=>{\n        if(!host._stage){\n                return;\n        }\n\n        host._stage = deepClone(host._stage_snapshot);\n        host.update();\n});\n```\n\n実際の runtime では、snapshot の field 名、clone 方法、finalize 処理などが含まれます。\n\ndeep clone には structured clone や JSON round trip が使われる場合があります。\n\n\n#### 変数の作成とスコープの重なり\n\n`*restore` は新しい変数を作りません。\n\n- scope を拡張しません。\n- local variables を追加しません。\n- expression を評価しません。\n- stage buffer を復元し、host rendering に反映します。\n\n復元後の template は、stage buffer を現在の effective data として再描画されます。\n\n\n#### 親へのアクセス\n\n`*restore` は nearest Sercrod host の stage を対象にします。\n\nnested hosts がある場合、子 host 内の `*restore` はその子 host の stage を復元します。親 host の stage を復元するには、親 host の template 内に `*restore` control を置きます。\n\n`$parent` を直接読む directive ではありません。\n\n\n#### conditionals and loops との併用\n\n`*restore` は conditional UI の中に置けます。\n\n```html\n<button *if=\"dirty\" type=\"button\" *restore>Cancel</button>\n```\n\nただし、same element に multiple Sercrod directives を重ねるより、wrapper を使う方が安全な場合があります。\n\n```html\n<span *if=\"dirty\">\n  <button type=\"button\" *restore>Cancel</button>\n</span>\n```\n\nloop 内に複数の restore buttons を置いた場合も、各 button は nearest host の stage 全体を restore します。row だけを restore するものではありません。\n\n\n#### 推奨される使い方\n\n- `*stage` が付いた host の中で使います。\n- `*apply` と対にして、Save / Cancel flow を作ります。\n- label は明確にします。例: `Cancel`、`Discard changes`。\n- row-level restore が必要な場合は、host 構造や data model を分けます。\n- stage がない host では意味がないため、使わないでください。\n\n\n#### 追加例\n\nsettings form の例:\n\n```html\n<serc-rod data='{ \"settings\": { \"theme\": \"light\" } }' *stage>\n  <select *input=\"settings.theme\">\n    <option value=\"light\">Light</option>\n    <option value=\"dark\">Dark</option>\n  </select>\n\n  <button type=\"button\" *apply>Apply</button>\n  <button type=\"button\" *restore>Restore</button>\n</serc-rod>\n```\n\nconditional cancel の例:\n\n```html\n<span *if=\"dirty\">\n  <button type=\"button\" *restore>Cancel changes</button>\n</span>\n```\n\n\n#### 注意点\n\n- `*restore` と `n-restore` は aliases です。\n- `*restore` は stage を snapshot から復元します。\n- committed data を直接変更するための directive ではありません。\n- stage がない場合は no-op です。\n\n\n#### data=\"item\" *stage での restore\n\n`<serc-rod data=\"item\" *stage>` は、item object を data root にした通常 staged host です。この場合、`*restore` は child host の stage を、最後に apply された item snapshot、または現在の item data から復元します。\n\nchild 内の式は root-relative です。つまり `title` を使い、`item.title` とは書きません。\n\n一方、data なしの `<serc-rod *stage>` が `*iterate` item を stage している場合、`*restore` は inherited parent scope 全体ではなく、その staged item だけを復元します。\n",
  "save": "### *save / *save.file / *save.session / *save.store\n\n#### 概要\n\n`*save.file` は、host data または staged view を JSON file として browser から download します。\n`*save.session` は、同じ JSON payload を browser の `sessionStorage` に保存します。\n`*save.store` は、同じ JSON payload を persistent browser storage、現在は IndexedDB、に保存します。\n`*save` は互換用の古い file save 形式として残ります。\n\n保存する data は `*keys` で選択できます。`*keys` を省略した場合は、host data または stage 全体を保存します。\n\n#### 基本例\n\nfile として保存します。\n\n```html\n<button type=\"button\" *save.file=\"'profile.json'\" *keys=\"profile settings\">\n  Save file\n</button>\n```\n\nsessionStorage に保存します。\n\n```html\n<button type=\"button\" *save.session=\"'profile-draft'\" *keys=\"profile settings\">\n  Save session\n</button>\n```\n\npersistent browser storage に保存します。\n\n```html\n<button type=\"button\" *save.store=\"'profile-draft'\" *keys=\"profile settings\">\n  Save store\n</button>\n```\n\n#### 挙動\n\n- `*save.file` の値は file name です。\n- `*save.session` の値は `sessionStorage` key です。\n- `*save.store` の値は persistent browser storage key です。\n- `*save.store` は既定で IndexedDB database `sercrod-store` の object store `json` に JSON string を保存します。\n- `*keys` は whitespace 区切りの top-level key list です。\n- `*keys` がない場合は、`this._stage ?? this._data` 全体を JSON 化します。\n- `*save.session` は `window.sessionStorage.setItem(storageKey, json)` を使います。\n- `*save.store` は IndexedDB が使えない場合や書き込みに失敗した場合、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-saved` event を dispatch します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"save\"`、session では `\"save.session\"`、store では `\"save.store\"`。\n- `detail.fileName`: file save の file name。\n- `detail.storage`: session/store save では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*save.session` または `*save.store` の key。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 保存した JSON string。\n\n#### 互換性\n\n古い形式の `*save=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*save.file` / `*save.session` / `*save.store` と `*keys` を使ってください。\n",
  "stage": "### *stage\n\n#### 概要\n\n`*stage` は、Sercrod host に staged editing mode を有効にする directive です。\n\nhost data の editable copy、つまり stage buffer を作り、user edits を committed data にすぐ反映せず、いったん stage に保持できるようにします。\n\n`*apply` で stage を committed data へ反映し、`*restore` で stage を最後の committed snapshot に戻します。\n\nalias の `n-stage` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{ \"profile\": { \"name\": \"Alice\" } }' *stage>\n  <input type=\"text\" *input=\"profile.name\">\n\n  <p>Preview: %profile.name%</p>\n\n  <button type=\"button\" *apply>Save</button>\n  <button type=\"button\" *restore>Cancel</button>\n</serc-rod>\n```\n\nこの host では、入力による変更は stage に入り、`*apply` するまで committed data には反映されません。\n\n\n#### 挙動\n\n`*stage` は host-level directive です。\n\n基本規則:\n\n- `<serc-rod>` host に付けます。\n- host data から deep copy を作り、stage buffer として保持します。\n- render 時の effective data は、stage があれば stage を優先します。\n- `*input` などの user edits は stage を更新します。\n- `*apply` は stage を committed data に merge します。\n- `*restore` は stage を snapshot から復元します。\n\n`*stage` により、編集可能な preview と committed source of truth を分けられます。\n\n\n#### 評価タイミング\n\n`*stage` は host の初期化や attribute handling の段階で処理されます。\n\n1. host が data を読み込みます。\n2. `*stage` / `n-stage` の presence を確認します。\n3. host data の snapshot を作ります。\n4. stage buffer を初期化します。\n5. render では stage buffer を effective data として使います。\n\ndata や `*stage` attribute が変わった場合、stage の再構築や snapshot 更新が発生する場合があります。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nif(host.hasAttribute(\"*stage\") || host.hasAttribute(\"n-stage\")){\n        host._stage_snapshot = deepClone(host._data);\n        host._stage = deepClone(host._data);\n}\n```\n\nrender 時:\n\n```js\nconst effectiveData = host._stage || host._data;\n```\n\napply 時:\n\n```js\nObject.assign(host._data, host._stage);\nhost._stage_snapshot = deepClone(host._data);\n```\n\nrestore 時:\n\n```js\nhost._stage = deepClone(host._stage_snapshot);\n```\n\n実際の runtime は proxy、update、clone fallback などを含みます。\n\n\n#### 変数の作成\n\n`*stage` は template variable を作りません。\n\n- `$stage` のような新しい public variable を作るものではありません。\n- host 内部に stage buffer を持ちます。\n- expressions は通常どおり data fields を読むように見えます。\n- ただし、その data fields は stage から来ている場合があります。\n\n\n#### スコープの重なり\n\n`*stage` が有効な host では、effective scope は staged data を優先します。\n\n- committed data:\n  - source of truth。\n  - apply 後の状態。\n- stage buffer:\n  - editing session 用の copy。\n  - render と input の現在値。\n- snapshot:\n  - restore 用の committed copy。\n\ntemplate からは、多くの場合、通常の data を読んでいるように見えます。\n\n```html\n%profile.name%\n```\n\nしかし、その値は stage buffer から来ている場合があります。\n\n\n#### binding や data directive との関係\n\n`*input`:\n\n- staged host 内では、input changes は stage に書き込まれます。\n- committed data へ直接書き込むわけではありません。\n\n`*print` や interpolation:\n\n- stage がある場合、stage の値を表示します。\n\n`:value`、`:class`、`:style` など:\n\n- stage を含む effective scope で評価されます。\n\n`*let`:\n\n- staged scope から値を読み、local helpers を作ります。\n- nested object mutation には注意します。\n\n#### *apply と *restore との関係\n\n`*apply`:\n\n- stage の top-level properties を committed data に merge します。\n- apply 後、snapshot を更新します。\n\n`*restore`:\n\n- stage を snapshot から再作成します。\n- 未 apply の edits を破棄します。\n\nこの3つを組み合わせることで、Save / Cancel flow を作れます。\n\n```html\n<button type=\"button\" *apply>Save</button>\n<button type=\"button\" *restore>Cancel</button>\n```\n\n\n#### conditionals and loops との併用\n\n`*stage` は host-level なので、通常は `<serc-rod>` に置きます。\n\n```html\n<serc-rod data='{ \"items\": [] }' *stage>\n```\n\nhost 内の conditionals や loops は staged data に基づいて描画されます。\n\n```html\n<li *for=\"item of items\">%item.name%</li>\n```\n\nloop item の編集も stage 内の item object に対して行われます。\n\nnested host を使う場合は、どの host が stage を持つかを明確にします。\n\n\n#### 推奨される使い方\n\n- form editing、settings editing、preview/cancel flow に使います。\n- `*apply` と `*restore` を UI 上で明確に配置します。\n- stage があることを user に伝える label や button text を使います。\n- row-level editing が必要な場合は、host を分けることを検討します。\n- server submit では、stage を送るのか apply 後の data を送るのかを明確にします。\n- deep object mutation の扱いに注意します。\n\n\n#### 追加例\n\nsettings form の例:\n\n```html\n<serc-rod data='{ \"settings\": { \"theme\": \"light\" } }' *stage>\n  <select *input=\"settings.theme\">\n    <option value=\"light\">Light</option>\n    <option value=\"dark\">Dark</option>\n  </select>\n\n  <button type=\"button\" *apply>Apply</button>\n  <button type=\"button\" *restore>Cancel</button>\n</serc-rod>\n```\n\ndraft preview の例:\n\n```html\n<serc-rod data='{ \"post\": { \"title\": \"\" } }' *stage>\n  <input *input=\"post.title\">\n  <h1>%post.title%</h1>\n</serc-rod>\n```\n\n\n#### 注意点\n\n- `*stage` と `n-stage` は aliases です。\n- `*stage` は host-level staged editing mode です。\n- template から見る data は通常どおりですが、stage 由来の場合があります。\n- `*apply` と `*restore` と組み合わせて使います。\n- stage は committed data の代替ではなく、editing buffer です。\n\n\n#### data=\"item\" と通常 stage\n\n`*iterate` 内で child host に `data=\"item\" *stage` を付けた場合、その child host の `_data` は現在の `item` object そのものになります。これは通常の host stage として扱われ、iterate-item stage mode ではありません。\n\nそのため child host 内の式は root-relative に書きます。\n\n```html\n<serc-rod data=\"item\" *stage>\n  <input *input=\"title\">\n  <button type=\"button\" *apply>Apply</button>\n  <button type=\"button\" *restore>Restore</button>\n</serc-rod>\n```\n\nこの形では `title` は `item.title` と同じ object 上の値を指します。`*apply` は staged copy をその `item` object に merge します。親の配列内 item と object は共有されるため、parent data は変わります。ただし parent host の rendering は自動では強制されません。必要な場合は `*update`、`updated` hook、または明示的な `update()` で知らせます。\n\n一方、child host に `data` を付けない場合は inherited iterate scope を使うため、empty `*stage` は iterate-item stage mode になります。この場合は次のように `item.title` と書きます。\n\n```html\n<serc-rod *stage>\n  <input *input=\"item.title\">\n</serc-rod>\n```\n\n#### update() 中の stage buffer\n\n通常 stage では、`update()` のたびに同じ `__sercrod_scope` から `_stage` を作り直すことはありません。`_stage` がまだない場合、または source scope の参照が別 object に変わった場合だけ、`_stage` を再初期化します。\n\nこれにより、`data=\"item\" *stage` の child host で編集中に `update()` が走っても、未 apply の stage edits は保持されます。`*restore` は最後の committed snapshot から stage を復元し、`*apply` は stage を `_data` へ merge します。\n",
  "switch": "### *switch\n\n#### 概要\n\n`*switch` は、1つの値に基づいて複数の branch から描画開始位置を選ぶ制御ディレクティブです。\n\n`*case`、`*case.break`、`*default`、`*break` と組み合わせて使います。\n\nSercrod の `*switch` は fallthrough model を持ちます。一致した `*case` から描画を始め、`*break` または `*case.break` に到達するまで後続 branch を描画します。\n\nalias の `n-switch` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"status\":\"ready\"}'>\n  <div *switch=\"status\">\n    <p *case.break=\"'loading'\">Loading...</p>\n    <p *case.break=\"'ready'\">Ready</p>\n    <p *case.break=\"'error'\">Error</p>\n    <p *default>Unknown</p>\n  </div>\n</serc-rod>\n```\n\nこの例では `status` が `\"ready\"` なので、`Ready` branch だけが描画されます。\n\n\n#### 挙動\n\n基本規則:\n\n- `*switch` の式を現在の scope で評価します。\n- 評価結果は branch scope に `$switch` として渡されます。\n- `*switch` の直接の子要素が branch として扱われます。\n- `*case` または `*case.break` が `$switch` と一致すると、その branch から描画が始まります。\n- break がない場合は後続 branch へ fallthrough します。\n- `*default` は、どの case も一致しなかった場合の fallback branch です。\n- `*case.break` は、case と break を1つにした短縮形です。\n\n`*switch` は、状態名、mode、role、status code など、1つの値に応じて UI を切り替える場合に向きます。\n\n\n#### case 式\n\n`*case` と `*case.break` の属性値は Sercrod expression として評価されます。\n\n```html\n<p *case=\"'ready'\">Ready</p>\n<p *case=\"200\">OK</p>\n<p *case=\"statusCode\">Matched</p>\n```\n\n文字列は quote します。\n\n`$switch` は branch scope から参照できます。\n\n```html\n<p *default>Unknown: %$switch%</p>\n```\n\n複雑な条件式を case に詰め込みすぎると読みにくくなるため、必要なら事前に `*let` や data 側で比較用の値を作ります。\n\n\n#### 評価タイミング\n\n`*switch` は structural directive として、children の描画前に評価されます。\n\n1. `*switch` expression を現在の scope で評価します。\n2. `$switch` を child scope に追加します。\n3. 直接の子 branch を DOM 順に確認します。\n4. 一致する `*case`、または fallback の `*default` を探します。\n5. active branch から描画を始めます。\n6. `*break` または `*case.break` に到達すると停止します。\n\n選ばれなかった branch の children は描画されません。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst switchValue = evaluate(switchExpression, scope);\nconst childScope = { ...scope, $switch: switchValue };\n\nlet active = false;\n\nfor(const branch of directChildren){\n        if(!active){\n                if(caseMatches(branch, switchValue, childScope)){\n                        active = true;\n                } else if(defaultMatches(branch)){\n                        active = true;\n                } else {\n                        continue;\n                }\n        }\n\n        renderBranch(branch, childScope);\n\n        if(hasBreak(branch)){\n                break;\n        }\n}\n```\n\n実際の runtime は clone、attribute cleanup、child rendering、error handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*switch` は `$switch` を branch scope に追加します。\n\nそれ以外の新しい host data は作りません。\n\nbranch の中では通常の Sercrod scope が使われます。\n\n- host data。\n- loop variables。\n- ancestor `*let` values。\n- `$switch`。\n- `$parent` や `$root` が利用可能な場合はそれら。\n\n`$switch` はその switch block の branch 内で参照するための値です。\n\n\n#### 親へのアクセス\n\nnested host 内では、`$parent` が使える場合があります。\n\n```html\n<div *switch=\"$parent.mode\">\n  <p *case.break=\"'edit'\">Edit</p>\n  <p *default>Other</p>\n</div>\n```\n\nただし、親 data に依存する switch は読み手に伝わりにくい場合があるため、必要な場合だけ使います。\n\n\n#### conditionals and loops との併用\n\n`*switch` は `*for` や `*each` の中で使えます。\n\n```html\n<div *for=\"item of items\">\n  <span *switch=\"item.status\">\n    <b *case.break=\"'ok'\">OK</b>\n    <b *case.break=\"'ng'\">NG</b>\n    <b *default>Other</b>\n  </span>\n</div>\n```\n\n各 iteration で別々の `$switch` が作られます。\n\n`*if` と組み合わせる場合は、wrapper を使うと読みやすくなります。\n\n\n#### templates, *include and *import との併用\n\nswitch branch の中で `*include` や `*import` を使えます。\n\n```html\n<div *switch=\"view\">\n  <section *case.break=\"'list'\">\n    <div *include=\"'list-view'\"></div>\n  </section>\n  <section *case.break=\"'detail'\">\n    <div *include=\"'detail-view'\"></div>\n  </section>\n</div>\n```\n\n`*switch` の直接の子 branch と、include/import の責務を分けると構造が読みやすくなります。\n\n\n#### 推奨される使い方\n\n- 通常の UI では `*case.break` を使い、1 branch だけ描画する意図を明確にします。\n- fallthrough が必要な場合だけ `*case` と `*break` を分けます。\n- `*case`、`*case.break`、`*default` は `*switch` の直接の子に置きます。\n- case expression は短くします。\n- branch が多い場合は、view 名や status 名を data 側で整理します。\n\n\n#### 追加例\n\nrole switch の例:\n\n```html\n<div *switch=\"role\">\n  <p *case.break=\"'admin'\">Admin</p>\n  <p *case.break=\"'editor'\">Editor</p>\n  <p *default>Viewer</p>\n</div>\n```\n\nfallthrough を使う例:\n\n```html\n<div *switch=\"role\">\n  <p *case=\"'admin'\">Admin tools</p>\n  <p *case=\"'editor'\">Editor tools</p>\n  <p *case.break=\"'viewer'\">Viewer tools</p>\n</div>\n```\n\n\n#### 注意点\n\n- `*switch` と `n-switch` は aliases です。\n- `$switch` は branch scope に追加されます。\n- `*case.break` は `*case` と `*break` の短縮形です。\n- break がない場合は fallthrough します。\n",
  "template": "### *template\n\n#### 概要\n\n`*template` は、Sercrod 内で名前付き template fragment を登録する directive です。\n\n登録された template は、`*include` や `*import` などから参照できます。\n\n表示するための要素ではなく、再利用可能な template source を定義するためのものです。\n\nalias の `n-template` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<template *template=\"user-card\">\n  <article>\n    <h2>%user.name%</h2>\n    <p>%user.email%</p>\n  </article>\n</template>\n\n<div *include=\"'user-card'\"></div>\n```\n\nこの例では、`user-card` という名前で template を登録し、別の場所から include します。\n\n\n#### 挙動\n\n基本規則:\n\n- `*template` の属性値は template name として使われます。\n- element の content が named template として登録されます。\n- 登録用 element 自体は通常の output として描画されません。\n- 同じ world または host context 内から参照できます。\n- duplicate names がある場合は、runtime の登録規則に従います。\n\n`*template` は template definition であり、表示 directive ではありません。\n\n\n#### 名前解決\n\ntemplate name は `*include` や `*import` から参照されます。\n\n```html\n<div *include=\"'user-card'\"></div>\n```\n\nname は通常 string として扱われます。\n\nproject によっては、world-local registration や component prefix に基づいた resolution が行われる場合があります。\n\n名前は衝突しにくく、用途が分かるものにします。\n\n\n#### world 単位の登録と重複\n\nSercrod が world 単位の管理を持つ場合、template registration も world-local に扱われます。\n\n- 同じ world 内で name が解決されます。\n- 別 world の同名 template とは独立する場合があります。\n- duplicate names がある場合、後勝ち、先勝ち、warning などの扱いは runtime 実装に従います。\n\n重複を避けるため、template name は明確に付けます。\n\n\n#### 評価タイミング\n\n`*template` は rendering の早い段階で登録されます。\n\n1. Sercrod が `*template` / `n-template` を持つ element を検出します。\n2. template name を読みます。\n3. content を template registry に登録します。\n4. 登録用 element は通常 output には描画しません。\n5. 後続の `*include` / `*import` がその name を参照できるようになります。\n\nregistration timing に依存するため、template definitions は参照より前、または初期化時に読み込める場所に置くのが安全です。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nconst name = element.getAttribute(\"*template\") || element.getAttribute(\"n-template\");\nregistry.set(name, element.content || element.childNodes);\nreturn;\n```\n\n実際の runtime は clone、world registry、duplicates、template element 以外の要素への対応を含みます。\n\n\n#### 変数の作成\n\n`*template` は data variables を作りません。\n\n- host data を更新しません。\n- local scope を追加しません。\n- template registry に template source を登録します。\n\ntemplate 内の expressions は登録時ではなく、include/import によって実際に描画されるときの scope で評価されます。\n\n\n#### スコープの重なり\n\n`*template` による登録時点では、内部 expressions は実行されません。\n\n`*include` や `*import` によって使われるとき、その呼び出し場所の scope が使われます。\n\nこのため、template fragment は reusable です。\n\n```html\n<template *template=\"row\">\n  <li>%item.name%</li>\n</template>\n\n<ul *each=\"item of items\">\n  <div *include=\"'row'\"></div>\n</ul>\n```\n\nここでは、`item` は include された場所の loop scope から来ます。\n\n\n#### 親へのアクセス\n\ntemplate 内で `$parent` が利用できるかは、template が実際に描画される場所の host 関係に依存します。\n\n登録場所の parent ではなく、include/import された場所の context を基準に考えます。\n\n\n#### conditionals and loops との併用\n\n`*template` definition 自体を conditional や loop の中に置くことは避けます。\n\ntemplate definitions は安定した場所に置き、使用側で conditionals や loops を使います。\n\n推奨:\n\n```html\n<template *template=\"item-row\">\n  <li>%item.name%</li>\n</template>\n\n<ul *each=\"item of items\">\n  <div *include=\"'item-row'\"></div>\n</ul>\n```\n\n#### *include and *import との併用\n\n`*template` は `*include` と `*import` の source になります。\n\n- `*template`:\n  - reusable fragment を登録します。\n- `*include`:\n  - 登録済み template を現在の場所へ含めます。\n- `*import`:\n  - 外部 template や別の source から取り込む用途に使われます。\n\nproject の設計に応じて使い分けます。\n\n\n#### 比較 - *include と *import\n\n`*include` は、すでに登録された local template fragment を参照する用途に向きます。\n\n`*import` は、外部 source や別管理の template を取り込む用途に向きます。\n\n`*template` は、その元になる named fragment を定義します。\n\n\n#### 推奨される使い方\n\n- template definitions は安定した場所に置きます。\n- name は明確で衝突しにくいものにします。\n- template 内の expressions は呼び出し側 scope に依存することを意識します。\n- duplicate names を避けます。\n- `*include` と組み合わせる場合、loop variable 名を分かりやすくします。\n\n\n#### 追加例\n\ncard template の例:\n\n```html\n<template *template=\"card\">\n  <article class=\"card\">\n    <h2>%item.title%</h2>\n    <p>%item.body%</p>\n  </article>\n</template>\n```\n\n使用:\n\n```html\n<section *each=\"item of cards\">\n  <div *include=\"'card'\"></div>\n</section>\n```\n\n\n#### 注意点\n\n- `*template` と `n-template` は aliases です。\n- 登録用であり、通常の出力用ではありません。\n- template 内の expressions は、使用時の scope で評価されます。\n- `*include` / `*import` と組み合わせて使います。\n",
  "shadow": "### *shadow\n\n#### 概要\n\n`*shadow` は、`*host` から接続できる Shadow DOM 用の template を定義するディレクティブです。\n\nこのディレクティブは `<template>` 要素に書きます。`<template *shadow=\"name\">` は、Shadow DOM 側の構造を名前付きで定義します。その後、host 要素が `*host=\"name\"` でその template を参照できます。\n\nSercrod は slot の挙動を再実装しません。標準の `<slot>` と `slot=\"...\"` の割り当ては browser が処理します。\n\n`*shadow` は Shadow DOM bridge の一部です。Sercrod の役割は、見える HTML template と host 要素を接続することです。Light DOM の子要素を Shadow DOM に移動したり、独自の component renderer を作ったりするものではありません。\n\n#### 基本例\n\n名前付き shadow template と、それを使う host element の例です。\n\n```html\n<template *shadow=\"messagebox\">\n  <section class=\"message-box\">\n    <div class=\"message-box-title\">\n      <slot name=\"title\"></slot>\n    </div>\n\n    <div class=\"message-box-message\">\n      <slot name=\"message\"></slot>\n    </div>\n  </section>\n</template>\n\n<message-box *host=\"messagebox\">\n  <p slot=\"message\">Maintenance will be performed on May 20.</p>\n  <h2 slot=\"title\">Notice</h2>\n</message-box>\n```\n\n挙動:\n\n- `<template *shadow=\"messagebox\">` は、`messagebox` という名前の shadow template を定義します。\n- `<message-box *host=\"messagebox\">` は、host 要素をその shadow template に接続します。\n- `slot=\"title\"` は `<slot name=\"title\">` の位置に表示されます。\n- `slot=\"message\"` は `<slot name=\"message\">` の位置に表示されます。\n- host 側では message を先に、title を後に書いていますが、表示位置は shadow template 側の slot によって決まります。\n- slot の割り当ては browser 標準の挙動です。\n\n#### 推奨構文\n\n明示的な接続名を使う形を推奨します。\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n```\n\nこの形は、template と host の関係が人間、documentation tools、AI assistants にとって読み取りやすくなります。\n\n#### *shadow を書く場所\n\n`*shadow` は `<template>` 要素に書きます。\n\n推奨:\n\n```html\n<template *shadow=\"messagebox\">...</template>\n<message-box *host=\"messagebox\">...</message-box>\n```\n\n避ける形:\n\n```html\n<message-box *shadow>...</message-box>\n```\n\n`*shadow` は host 側のディレクティブではありません。host 要素に直接 `*shadow` を書くと、host の子要素が Shadow DOM に移動する、または host 要素自身が shadow 側の構造になる、という誤解を生みやすくなります。\n\nshadow 側の構造は `<template *shadow=\"...\">` に置きます。host 側の接続は `*host` に置きます。\n\n#### 接続名\n\n`*shadow` の値は、`*host` が参照する接続名です。\n\n```html\n<template *shadow=\"profilecard\">\n  ...\n</template>\n\n<profile-card *host=\"profilecard\">\n  ...\n</profile-card>\n```\n\nこの例では、`profilecard` が接続名です。\n\n推奨される書き方は、両側に同じ明示名を書く形です。\n\n- template 側に `*shadow=\"profilecard\"` を書きます。\n- host 側に `*host=\"profilecard\"` を書きます。\n\n#### 値なし *host との関係\n\n値なしの `*host` は shorthand として許可されますが、推奨ではありません。\n\n```html\n<template *shadow=\"MessageBox\">\n  ...\n</template>\n\n<message-box *host>\n  ...\n</message-box>\n```\n\n`*host` に値がない場合、Sercrod は host element name から constructor-style の接続名を導出します。\n\n```text\nmessage-box\n  ->\nMessageBox\n```\n\nその後、Sercrod は `<template *shadow=\"MessageBox\">` を探します。\n\nこの shorthand は許可されますが、明示的な名前の方が読みやすく、誤解されにくいため推奨されます。\n\n#### shadow template の内容\n\nshadow template には、通常、次の内容を置きます。\n\n- Shadow DOM 側の構造。\n- Shadow DOM 側の `<style>`。\n- 標準の `<slot>` 要素。\n\n```html\n<template *shadow=\"messagebox\">\n  <style>\n    :host {\n      display: block;\n    }\n\n    .message-box {\n      border: 1px solid #ccc;\n      padding: 1rem;\n    }\n  </style>\n\n  <section class=\"message-box\">\n    <div class=\"message-box-title\">\n      <slot name=\"title\"></slot>\n    </div>\n\n    <div class=\"message-box-message\">\n      <slot name=\"message\"></slot>\n    </div>\n  </section>\n</template>\n```\n\nshadow template の内容は、shadow root に mount される前に通常の Sercrod render pipeline を通ります。\n\nそのため、`<template *shadow=\"...\">` の中では、通常の Sercrod directives を使って Shadow DOM 内の実体 DOM を生成できます。\n\n```html\n<template *shadow=\"previewbox\">\n  <style>\n    .preview-title { color: red; }\n  </style>\n\n  <article class=\"preview-card\">\n    <h2 class=\"preview-title\" *print=\"title\"></h2>\n    <p *print=\"body\"></p>\n  </article>\n</template>\n\n<preview-box *host=\"previewbox\" data=\"{ title: `Notice`, body: `Shadow-rendered text.` }\"></preview-box>\n```\n\nこの pattern では、`<h2>` と `<p>` は slot 経由ではなく shadow root 内に生成されます。外側 page CSS は、通常 selector ではこれらを選択しません。\n\ncontent そのものを外側 page CSS から分けたい場合はこの形を使います。Light DOM children を page-owned content として残したい場合は slot を使います。\n\n`*shadow` は template 宣言、`*host` は host 側接続のままです。この2つを shadow template 内の通常の nested behavior として使わないでください。\n\nshadow template 内に置かれた bridge 専用 directive は無視されます。`<template *shadow>` の内側に `*shadow`、`*host`、`*shadow-host`、`n-host`、`n-shadow-host` がある場合、warnings が有効なら Sercrod は警告を出し、その bridge behavior を実行しません。`*shadow` は外側の宣言 template に、`*host` とその aliases は ShadowRoot を受け取る外側 host element に書いてください。\n\n#### shadow template 内の directive coverage\n\nshadow template content は、通常の Light DOM content と同じ directive pipeline で処理されます。`*print`、`*if`、`*switch`、`*for`、`*each`、`*input`、`@event`、`:attribute`、`*template`、`*include`、同期 `*import`、`*fetch`、`*api`、`*post`、`*upload`、`*download`、`*websocket`、`*websocket.send`、`*stage`、`*apply`、`*restore`、`*save.file`、`*save.session`、`*save.store`、`*load.file`、`*load.session`、`*load.store` などの render、control-flow、form、event、action、template 系 directives を shadow root 内で使えます。\n\nowning `<serc-rod>` は data、stage、network state、WebSocket connections、save/load events、update lifecycle の owner のままです。shadow template 内の directive は、nested `<serc-rod>` の内側でない限り、その owning Sercrod host の一部として実行されます。\n\nSercrod 内部で必要な traversal は ShadowRoot boundary をまたぐ composed-aware な探索を使います。child `<serc-rod>` hosts、`*updated`、`*updated-propagate`、`*log`、`*man`、include depth tracking、parent template lookup は、同じ Sercrod host に属する shadow-root content を扱えます。\n\n#### Light DOM 側の directives との併用\n\nhost 側は、通常の Sercrod scope として使えます。\n\n```html\n<template *shadow=\"profilecard\">\n  <section class=\"profile-card\">\n    <header>\n      <slot name=\"name\"></slot>\n    </header>\n\n    <main>\n      <slot name=\"body\"></slot>\n    </main>\n  </section>\n</template>\n\n<profile-card *host=\"profilecard\" data=\"{ first_name: `Taro`, last_name: `Yamada`, message: `Hello.` }\">\n  <h2 slot=\"name\" *let=\"full_name = `${last_name} ${first_name}`\" *print=\"full_name\"></h2>\n  <p slot=\"body\" *print=\"message\"></p>\n</profile-card>\n```\n\nSercrod は Light DOM 側の directives を通常通り処理します。処理済みの Light DOM content は、browser 標準の slot behavior によって shadow template 内の slot 位置に表示されます。\n\n#### CSS scope\n\n`*shadow` は browser 標準の Shadow DOM を使うため、shadow template 内に書いた CSS は標準の Shadow DOM の scope に入ります。\n\n通常の外側 CSS は、普通の selector では shadow root 内部の要素を直接選択しません。shadow template 内に書いた CSS は、外側の page へ漏れません。slot に入る Light DOM children は別です。実体は Light DOM nodes のままなので、外側の page CSS は普通に適用されます。\n\nこれは、preview component、editor panel、admin screen などで、外側 UI の CSS と preview layout の CSS を分けやすくしたい場合に有効です。\n\n```html\n<preview-box *host=\"previewbox\">\n  <div class=\"same-box\" slot=\"content\">\n    <h2 class=\"same-title\">Light DOM article title</h2>\n    <p class=\"same-body\">Light DOM article body.</p>\n  </div>\n</preview-box>\n\n<template *shadow=\"previewbox\">\n  <style>\n    .same-box {\n      border: 1px solid #ccc;\n      padding: 1rem;\n    }\n\n    .same-title {\n      font-size: 1.25rem;\n    }\n\n    .same-body {\n      line-height: 1.7;\n    }\n  </style>\n\n  <article class=\"same-box\">\n    <header class=\"same-title\">Shadow-side title frame</header>\n\n    <main class=\"same-body\">\n      <slot name=\"content\"></slot>\n    </main>\n  </article>\n</template>\n```\n\nこの例では、Light DOM 側と Shadow DOM 側の両方で同じ class names を使っていますが、同じ styling surface ではありません。\n\n- shadow template 内の `.same-box`、`.same-title`、`.same-body` rules は、shadow root 内に生成された要素を style します。\n- 外側 page の `.same-box`、`.same-title`、`.same-body` rules は、`<slot>` に割り当てられた nodes を含む Light DOM nodes を style します。\n- 通常の selectors は page から shadow root 内部へ越えません。また、shadow root 内の通常 selectors も、割り当て済み Light DOM children へは届きません。\n\nSercrod が CSS isolation を独自実装するわけではありません。Sercrod は shadow template と host element を接続します。CSS scoping は、標準 Shadow DOM の一部として browser が処理します。\n\n#### slotted content に関する重要な注意\n\nslot に入る要素は、表示上は shadow layout 内の slot 位置に見えても、実体としては Light DOM nodes のままです。\n\nそのため、slot に入れた要素そのものには外側の page CSS が普通に適用されます。\n\nshadow root 内の CSS は、通常 selectors では割り当て済み Light DOM nodes を style しません。slot 側から限定的に style したい場合は、標準 Shadow DOM の `::slotted(...)` を使うか、Light DOM 側から slotted children を style します。\n\npreview content そのものまで外側 CSS から分けたい場合は、その content を slotted Light DOM として渡すのではなく、Shadow DOM 内で描画する形にします。\n\n#### 挙動\n\n概念的には、Sercrod は `*shadow` について次の処理を行います。\n\n1. `<template *shadow=\"name\">` 要素を収集します。\n2. 各 shadow template を名前で登録します。\n3. `*host`、`*shadow-host`、`n-host`、`n-shadow-host` がその名前を参照できるようにします。\n4. matching host が見つかった場合、可能であれば host に open Shadow DOM を attach します。\n5. shadow template の content を host の shadow root 内へ render します。\n6. Light DOM children は元の場所に残します。\n7. 標準 slot assignment は browser に任せます。\n8. shadow template content 内の通常 Sercrod directives と、Light DOM 側の Sercrod directives を通常通り処理します。\n\n#### 重複した名前\n\n同じ effective registry 内で、同じ `*shadow` 名を複数回定義しないでください。\n\n```html\n<template *shadow=\"messagebox\">\n  A\n</template>\n\n<template *shadow=\"messagebox\">\n  B\n</template>\n```\n\nこの形は推奨されません。\n\n想定される方針:\n\n- 最初の定義を採用します。\n- 後続の重複定義は無視します。\n- warnings が有効な場合、Sercrod は warning を出します。\n\n```text\n[Sercrod warn] duplicate *shadow template: messagebox\n```\n\n`*shadow` は構造定義であり、CSS のような override rule ではありません。後から黙って置き換わる挙動は、人間にも AI tools にも追いにくくなります。\n\n#### host がない場合\n\n`*shadow` template は、host より前にあっても、後にあっても、すぐに host がなくても構いません。template 自体は再利用可能な shadow structure を定義するだけです。\n\nどの host からも参照されない場合、その template だけでは visible output を作りません。\n\n#### *shadow がしないこと\n\n`*shadow` は次のことをしません。\n\n- `*host` なしで自分自身を host に接続しません。\n- Light DOM children を Shadow DOM に移動しません。\n- slot assignment を再実装しません。\n- `<slot>` 要素を自動追加しません。\n- Sercrod を component renderer にしません。\n- CSS isolation を独自実装しません。\n\n#### 推奨される使い方\n\n- `*shadow` は `<template>` 要素に書きます。\n- できるだけ明示的な接続名を使います。\n- shadow template content は、構造、style、slots に集中させます。\n- 生成 content を shadow root 内に置きたい場合は、shadow template 内で通常の Sercrod directives を使います。\n- host element 側には `*host` を書いて template に接続します。\n- `*shadow` 名の重複を避けます。\n- slotted content は Light DOM content のままであることを忘れないでください。\n\n#### 注意点\n\n- `*shadow` は visible shadow template を定義します。\n- `*host` は host element を名前付き shadow template に接続します。\n- `*shadow-host`、`n-host`、`n-shadow-host` は host 側 alias として `*host` の項目で説明します。\n- 標準 `<slot>` と `slot=\"...\"` の挙動は browser が処理します。\n- CSS scoping も標準 Shadow DOM の挙動です。\n- Sercrod の役割は、shadow template と host element を接続することです。\n",
  "host": "### *host\n\n#### 概要\n\n`*host` は、host element を名前付きの `*shadow` template に接続するディレクティブです。\n\nhost element は Light DOM children を保持します。Sercrod は可能であれば host に Shadow DOM を attach し、matching shadow template をそこへ render し、標準の `<slot>` assignment は browser に任せます。\n\nSercrod は slot behavior を再実装しません。また、Light DOM children を Shadow DOM に物理的に移動しません。\n\n#### 基本例\n\nhost element を shadow template に接続する例です。\n\n```html\n<template *shadow=\"messagebox\">\n  <section class=\"message-box\">\n    <div class=\"message-box-title\">\n      <slot name=\"title\"></slot>\n    </div>\n\n    <div class=\"message-box-message\">\n      <slot name=\"message\"></slot>\n    </div>\n  </section>\n</template>\n\n<message-box *host=\"messagebox\">\n  <p slot=\"message\">Maintenance will be performed on May 20.</p>\n  <h2 slot=\"title\">Notice</h2>\n</message-box>\n```\n\n挙動:\n\n- `<template *shadow=\"messagebox\">` は、`messagebox` という名前の shadow template を定義します。\n- `<message-box *host=\"messagebox\">` は、host element をその template に接続します。\n- `slot=\"title\"` は `<slot name=\"title\">` に表示されます。\n- `slot=\"message\"` は `<slot name=\"message\">` に表示されます。\n- slot assignment は browser 標準の挙動です。\n\n#### 推奨構文\n\n明示的な接続名を使う形を推奨します。\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n```\n\n`*shadow=\"messagebox\"` は名前付き shadow template を定義します。\n\n`*host=\"messagebox\"` は host element をその名前付き template に接続します。\n\n明示的な名前は、template と host の関係を読みやすくし、documentation や AI tools にとっても誤解を減らします。\n\n#### alias\n\n次の host 側 directives は同等です。\n\n```text\n*host\n*shadow-host\nn-host\nn-shadow-host\n```\n\n推奨形は `*host` です。\n\n- `*host` は標準の推奨形です。\n- `*shadow-host` は、より説明的な alias です。\n- `n-host` と `n-shadow-host` は namespace-style aliases です。\n\n通常の examples では、特別な理由がない限り `*host` を使ってください。\n\n#### *host を書く場所\n\n`*host` は host element に書きます。template 側には書きません。\n\n推奨:\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n```\n\n避ける形:\n\n```html\n<template *host=\"messagebox\">\n  ...\n</template>\n```\n\ntemplate 側は `*shadow` で shadow structure を定義します。host 側は `*host` でその structure に接続します。\n\n#### 接続名\n\n`*host` の値は、接続する shadow template の名前です。\n\n```html\n<template *shadow=\"profilecard\">\n  ...\n</template>\n\n<profile-card *host=\"profilecard\">\n  ...\n</profile-card>\n```\n\nこの例では、`profilecard` が接続名です。\n\nSercrod は matching `<template *shadow=\"profilecard\">` を探します。\n\n#### 値なし *host shorthand\n\n値なしの `*host` は shorthand として許可されますが、推奨ではありません。\n\n```html\n<template *shadow=\"MessageBox\">\n  ...\n</template>\n\n<message-box *host>\n  ...\n</message-box>\n```\n\n`*host` に値がない場合、Sercrod は host element name から constructor-style の接続名を導出します。\n\n```text\nmessage-box\n  ->\nMessageBox\n```\n\nその後、Sercrod は `<template *shadow=\"MessageBox\">` を探します。\n\nこの shorthand は便利な場合もありますが、明示名の方が推奨されます。\n\n推奨:\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n```\n\n明示形は hidden name conversion を避けられ、接続関係を追いやすくします。\n\n#### 標準 slot との併用\n\n`*host` は browser 標準の slot behavior とともに使います。\n\n```html\n<template *shadow=\"fieldbox\">\n  <div class=\"field-box\">\n    <label class=\"field-box-label\">\n      <slot name=\"label\"></slot>\n    </label>\n\n    <div class=\"field-box-control\">\n      <slot name=\"control\"></slot>\n    </div>\n\n    <div class=\"field-box-help\">\n      <slot name=\"help\"></slot>\n    </div>\n  </div>\n</template>\n\n<field-box *host=\"fieldbox\">\n  <span slot=\"label\">Email</span>\n  <input slot=\"control\" type=\"email\" name=\"email\">\n  <small slot=\"help\">Enter a valid email address.</small>\n</field-box>\n```\n\n`slot=\"label\"`、`slot=\"control\"`、`slot=\"help\"` は、matching named slots に browser が割り当てます。\n\nSercrod は host element を shadow template に接続するだけです。\n\n#### default slot\n\n`slot` 属性を持たない要素は、default `<slot></slot>` に表示されます。\n\n```html\n<template *shadow=\"messagebox\">\n  <section class=\"message-box\">\n    <header>\n      <slot name=\"title\"></slot>\n    </header>\n\n    <main>\n      <slot></slot>\n    </main>\n  </section>\n</template>\n\n<message-box *host=\"messagebox\">\n  <h2 slot=\"title\">Notice</h2>\n  <p>Maintenance will be performed on May 20.</p>\n</message-box>\n```\n\n`<h2>` は named slot に表示されます。paragraph は `slot` 属性を持たないため、default slot に表示されます。\n\n#### Light DOM directives\n\nhost 側は、通常の Sercrod scope として使えます。\n\n`data`、`*let`、`*print`、`*input` などの Light DOM directives を host 側に書けます。\n\n```html\n<template *shadow=\"profilecard\">\n  <section class=\"profile-card\">\n    <header>\n      <slot name=\"name\"></slot>\n    </header>\n\n    <main>\n      <slot name=\"body\"></slot>\n    </main>\n  </section>\n</template>\n\n<profile-card *host=\"profilecard\" data=\"{ first_name: `Taro`, last_name: `Yamada`, message: `Hello.` }\">\n  <h2 slot=\"name\" *let=\"full_name = `${last_name} ${first_name}`\" *print=\"full_name\"></h2>\n  <p slot=\"body\" *print=\"message\"></p>\n</profile-card>\n```\n\nSercrod は Light DOM directives を通常通り処理します。処理済みの Light DOM content は、browser 標準の slot behavior によって slot 位置に表示されます。\n\n#### shadow template directive coverage\n\nmatching shadow template も通常の directive pipeline で render されます。render、control-flow、form、event、action、network、save/load、template、include、nested `<serc-rod>` directives は shadow root 内で実行できます。directive が nested `<serc-rod>` の内側にある場合を除き、owning `<serc-rod>` が data と lifecycle の owner です。\n\nshadow template 内の `*host`、`*shadow-host`、`n-host`、`n-shadow-host` は misplaced bridge directive です。warnings が有効なら Sercrod は警告を出し、そこでの bridge connection は無視します。host directive は ShadowRoot を受け取る外側 host element にだけ書いてください。\n\n#### CSS scope\n\nhost が shadow template に接続されると、shadow template 内に書いた CSS は browser 標準の Shadow DOM behavior によって scoped されます。\n\n通常の外側 CSS は、普通の selector では shadow root 内部の要素を直接選択しません。shadow template 内に書いた CSS は外側の page へ漏れません。slot に入る Light DOM children は別です。実体は Light DOM nodes のままなので、外側の page CSS は普通に適用されます。\n\n```html\n<preview-box *host=\"previewbox\">\n  <div class=\"same-box\" slot=\"content\">\n    <h2 class=\"same-title\">Light DOM article title</h2>\n    <p class=\"same-body\">Light DOM article body.</p>\n  </div>\n</preview-box>\n\n<template *shadow=\"previewbox\">\n  <style>\n    .same-box {\n      border: 1px solid #ccc;\n      padding: 1rem;\n    }\n\n    .same-title {\n      font-size: 1.25rem;\n    }\n\n    .same-body {\n      line-height: 1.7;\n    }\n  </style>\n\n  <article class=\"same-box\">\n    <header class=\"same-title\">Shadow-side title frame</header>\n\n    <main class=\"same-body\">\n      <slot name=\"content\"></slot>\n    </main>\n  </article>\n</template>\n```\n\nこの例では、両側に同じ class names を使っていますが、同じ styling surface ではありません。\n\n- shadow template 内の `.same-box`、`.same-title`、`.same-body` rules は、shadow root 内に生成された要素を style します。\n- 外側 page の `.same-box`、`.same-title`、`.same-body` rules は、`<slot>` に割り当てられた nodes を含む Light DOM nodes を style します。\n- 通常の selectors は page から shadow root 内部へ越えません。また、shadow root 内の通常 selectors も、割り当て済み Light DOM children へは届きません。\n\nSercrod が CSS isolation を独自実装するわけではありません。Sercrod は host element を shadow template に接続します。CSS scoping は、標準 Shadow DOM の一部として browser が処理します。\n\n#### slotted content に関する重要な注意\n\nslot に入る要素は Light DOM nodes のままです。\n\n表示上は shadow layout 内の slot 位置に見えても、実体としての node は Light DOM 側に残ります。そのため、slotted elements には外側 page CSS が普通に適用されます。\n\nshadow root 内の CSS は、通常 selectors では割り当て済み Light DOM nodes を style しません。slot 側から限定的に style したい場合は、標準 Shadow DOM の `::slotted(...)` を使うか、Light DOM 側から slotted children を style します。\n\npreview content そのものまで外側 CSS から分けたい場合は、その content を slotted Light DOM として渡すのではなく、Shadow DOM 内で描画する形にします。\n\n#### 挙動\n\n概念的には、Sercrod は `*host` について次の処理を行います。\n\n1. `*host`、`*shadow-host`、`n-host`、`n-shadow-host` を持つ element を見つけます。\n2. directive value から shadow template 名を解決します。\n3. directive に値がない場合、host element name から constructor-style name を導出します。\n4. matching `<template *shadow=\"name\">` を探します。\n5. matching template があり、host に既存の `shadowRoot` がなければ、open Shadow DOM を attach します。\n6. template content を host の shadow root 内へ render します。\n7. 標準 slot assignment は browser に任せます。\n8. shadow template content 内の通常 Sercrod directives と、Light DOM 側の Sercrod directives を通常通り処理します。\n\n#### template が見つからない場合\n\nhost が存在しない shadow template を参照している場合、warnings が有効なら Sercrod は warning を出すべきです。\n\n```html\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n```\n\nmatching `<template *shadow=\"messagebox\">` がない場合、想定 warning は次です。\n\n```text\n[Sercrod warn] *host requires a matching *shadow template: messagebox\n```\n\n値なし `*host` の場合:\n\n```html\n<message-box *host>\n  ...\n</message-box>\n```\n\nSercrod は `MessageBox` を導出します。matching `<template *shadow=\"MessageBox\">` がない場合、想定 warning は次です。\n\n```text\n[Sercrod warn] *host requires a matching *shadow template: MessageBox\n```\n\n#### 既存 shadowRoot\n\nhost がすでに `shadowRoot` を持っている場合、Sercrod はそれを上書きしないでください。\n\n想定 warning は次です。\n\n```text\n[Sercrod warn] shadowRoot already exists: message-box\n```\n\nこれは、外部 Web Components や user scripts が同じ element にすでに Shadow DOM を作っている場合に、それを壊さないためです。\n\n#### Shadow mode\n\n初期仕様では open Shadow DOM のみを扱います。\n\n```js\nattachShadow({ mode: \"open\" })\n```\n\nclosed Shadow DOM は初期の `*host` behavior には含めません。\n\n理由は、closed Shadow DOM は inspection、debugging、Sercrod や AI tools による確認が難しくなるためです。初期設計では、bridge を見える状態、調べられる状態に保ちます。\n\n#### HTML 上の順序\n\nhost element は、matching shadow template より前にあっても後にあっても構いません。\n\n```html\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n\n<template *shadow=\"messagebox\">\n  ...\n</template>\n```\n\n想定実装は、宣言順に依存しない方が安全です。\n\n安全な実装では、まず `<template *shadow=\"...\">` declarations を収集し、その後で `*host` elements を接続します。\n\n#### customElements.define() との関係\n\n`*host` は `customElements.define()` の置き換えではありません。\n\n`*shadow` / `*host` bridge は、見える shadow template を host element に接続します。Sercrod を custom element framework にする必要はありません。\n\nSercrod は、user scripts や external libraries が定義する custom elements を再定義しないよう注意するべきです。custom element name がすでに登録されている場合、Sercrod は再定義しません。\n\n最小の bridge behavior は、`attachShadow({ mode: \"open\" })` を使って host を shadow template に接続し、template content を shadow root 内へ render することです。\n\n#### *host がしないこと\n\n`*host` は次のことをしません。\n\n- shadow template を自分だけで定義しません。\n- slot assignment を再実装しません。\n- Light DOM children を Shadow DOM に移動しません。\n- missing `<slot>` 要素を自動生成しません。\n- 既存の `shadowRoot` を上書きしません。\n- CSS isolation を独自実装しません。\n- `customElements.define()` を置き換えません。\n\n#### 推奨される使い方\n\n- できるだけ明示的な接続名を使います。\n- `*shadow` は `<template>` 要素に書きます。\n- `*host` は host element に書きます。\n- 推奨形は `*host` であり、`*shadow-host`、`n-host`、`n-shadow-host` は alias として扱います。\n- content placement には標準 `<slot>` と `slot=\"...\"` を使います。\n- 生成 content を shadow root 内に置きたい場合は、shadow template 内で通常の Sercrod directives を使います。\n- slotted content は Light DOM content のままであることを忘れないでください。\n\n#### 注意点\n\n- `*host` は host element を名前付き `*shadow` template に接続します。\n- `*shadow-host`、`n-host`、`n-shadow-host` は host-side connection の alias です。\n- 値なし `*host` は許可されますが、明示名を推奨します。\n- 標準 slot assignment は browser が処理します。\n- CSS scoping は標準 Shadow DOM の挙動です。\n- Sercrod の役割は、host element と shadow template を接続することです。\n",
  "shadow-host": "### *shadow-host\n\n#### 概要\n\n`*shadow-host` は、`*host` の説明的な alias です。\n\nhost element を名前付き `*shadow` template に接続します。挙動は `*host` と同じです。\n\n推奨される通常の書き方は `*host` です。\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box *shadow-host=\"messagebox\">\n  ...\n</message-box>\n```\n\n上の例は、概念的には次と同じです。\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box *host=\"messagebox\">\n  ...\n</message-box>\n```\n\n#### 注意点\n\n- `*shadow-host` は host 側に書きます。\n- template 側には `*shadow` を書きます。\n- slot assignment は browser 標準の挙動です。\n- Sercrod は Light DOM children を Shadow DOM に移動しません。\n- 詳細は `*host` の manual entry を参照してください。\n",
  "n-host": "### n-host\n\n#### 概要\n\n`n-host` は、`*host` の namespace-style alias です。\n\nhost element を名前付き `*shadow` template に接続します。挙動は `*host` と同じです。\n\n通常の documentation や examples では、`*host` を推奨します。\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box n-host=\"messagebox\">\n  ...\n</message-box>\n```\n\n#### 注意点\n\n- `n-host` は host 側に書きます。\n- template 側には `*shadow` を書きます。\n- slot assignment は browser 標準の挙動です。\n- Sercrod は CSS isolation を独自実装しません。\n- 詳細は `*host` の manual entry を参照してください。\n",
  "n-shadow-host": "### n-shadow-host\n\n#### 概要\n\n`n-shadow-host` は、`*host` の namespace-style alias です。\n\nhost element を名前付き `*shadow` template に接続します。挙動は `*host` と同じです。\n\n通常の documentation や examples では、`*host` を推奨します。\n\n```html\n<template *shadow=\"messagebox\">\n  ...\n</template>\n\n<message-box n-shadow-host=\"messagebox\">\n  ...\n</message-box>\n```\n\n#### 注意点\n\n- `n-shadow-host` は host 側に書きます。\n- template 側には `*shadow` を書きます。\n- slot assignment は browser 標準の挙動です。\n- slotted content は Light DOM nodes のままです。\n- 詳細は `*host` の manual entry を参照してください。\n",
  "textContent": "### *textContent\n\n#### 概要\n\n`*textContent` は Sercrod expression を評価し、その結果を要素の `textContent` に設定する directive です。\n\nHTML として解釈せず、plain text として出力します。\n\n`*print` に近い役割ですが、DOM property としての `textContent` を明示的に扱います。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"message\":\"Hello\"}'>\n  <p *textContent=\"message\"></p>\n</serc-rod>\n```\n\n`p` の textContent は `Hello` になります。\n\n\n#### 挙動\n\n基本規則:\n\n- 属性値を現在の scope で expression として評価します。\n- 結果を text に変換します。\n- 要素の `textContent` に設定します。\n- HTML は実行されません。\n- children は textContent によって置き換えられます。\n- data は変更しません。\n\ntext を安全に出力する用途に向きます。\n\n\n#### 式の評価\n\n`*textContent` の属性値は Sercrod expression です。\n\n```html\n<span *textContent=\"user.name\"></span>\n<span *textContent=\"price * qty\"></span>\n<span *textContent=\"formatDate(date)\"></span>\n```\n\n現在の scope にある data、loop variables、`*let` values、methods を参照できます。\n\n\n#### 評価タイミング\n\n`*textContent` は element の描画中に評価されます。\n\n1. element が clone されます。\n2. expression が評価されます。\n3. 結果が文字列化されます。\n4. clone の `textContent` に設定されます。\n5. children は通常の child rendering ではなく、text として置き換えられます。\n\ndata update があると再評価されます。\n\n\n#### 実行モデル\n\n概念的には次の通りです。\n\n```js\nconst value = evaluate(textContentExpression, scope);\nelement.textContent = value == null ? \"\" : String(value);\n```\n\n実際の runtime は error handling や filters を含む場合があります。\n\n\n#### 変数の作成とスコープの重なり\n\n`*textContent` は変数を作りません。\n\n- host data を書きません。\n- scope を拡張しません。\n- 現在の scope を読んで DOM text に出力するだけです。\n\n\n#### 親へのアクセス\n\nnested host で `$parent` が利用できる場合、`*textContent` の expression から参照できます。\n\n```html\n<span *textContent=\"$parent.title\"></span>\n```\n\n親依存が多くなる場合は、data flow を明確にします。\n\n\n#### conditionals and loops との併用\n\nconditionals や loops と組み合わせられます。\n\n```html\n<span *if=\"user\" *textContent=\"user.name\"></span>\n```\n\n```html\n<li *for=\"item of items\" *textContent=\"item.label\"></li>\n```\n\nchildren を置き換えるため、同じ要素の中に他の表示用 children を置かない方が分かりやすいです。\n\n\n#### 他の content directive との関係\n\n`*textContent` は content を所有します。\n\n同じ要素に次のような directives を重ねると意味が競合します。\n\n- `*print`\n- `*innerHTML`\n- `*compose`\n- child directives\n\nplain text は `*textContent` または `*print`、HTML は `*innerHTML` または `*compose` と分けて使います。\n\n\n#### 推奨される使い方\n\n- plain text output に使います。\n- HTML を挿入したい場合は使わず、trusted HTML 用の directive を検討します。\n- 同じ要素に children を持たせない構造にします。\n- sentence 内の部分的な値には `%expr%` interpolation を使います。\n- element 全体の text を式で決めたい場合に使います。\n\n\n#### 追加例\n\ncomputed text の例:\n\n```html\n<span *textContent=\"firstName + ' ' + lastName\"></span>\n```\n\nfallback の例:\n\n```html\n<span *textContent=\"title || 'Untitled'\"></span>\n```\n\ndebug の例:\n\n```html\n<pre *textContent=\"JSON.stringify($data, null, 2)\"></pre>\n```\n\n\n#### 注意点\n\n- `*textContent` は text output です。\n- HTML として解釈されません。\n- data を変更しません。\n- children は textContent によって置き換えられます。\n",
  "unwrap": "### *unwrap\n\n#### 概要\n\n`*unwrap` は、要素自体を出力せず、その children だけを親へ展開する directive です。\n\nwrapper を template 上には置きたいが、rendered DOM には残したくない場合に使います。\n\nalias の `n-unwrap` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"items\":[\"A\",\"B\"]}'>\n  <template *unwrap>\n    <p *for=\"item of items\">%item%</p>\n  </template>\n</serc-rod>\n```\n\n`template` 要素自体は出力されず、children だけが描画されます。\n\n\n#### 挙動\n\n基本規則:\n\n- `*unwrap` を持つ要素は、出力 DOM にその要素自体を残しません。\n- その children は、親の中へ直接描画されます。\n- wrapper 用の要素を消したい場合に使います。\n- host data は変更しません。\n- scope は通常どおり children へ伝わります。\n\n`*unwrap` は構造上の wrapper を取り除くための directive です。\n\n\n#### 評価タイミング\n\n`*unwrap` は rendering 中に処理されます。\n\n1. element に `*unwrap` / `n-unwrap` があることを検出します。\n2. element 自体は clone して出力しません。\n3. original children を現在の parent に対して描画します。\n4. children 内の directives は通常どおり処理されます。\n\nこのため、wrapper を消しても children の Sercrod behavior は残ります。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nif(hasUnwrap(element)){\n        renderChildren(element.childNodes, parent, scope);\n        return;\n}\n```\n\n実際の runtime は clone、scope、structural directives を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*unwrap` は変数を作りません。\n\n- host data を変更しません。\n- local scope を追加しません。\n- children は現在の scope を引き継ぎます。\n\nもし wrapper に `*let` なども置く必要がある場合は、実行順や組み合わせに注意します。通常は wrapper と scope creation の役割を分ける方が安全です。\n\n\n#### 親へのアクセス\n\n`*unwrap` 自体は `$parent` を扱いません。\n\nchildren は通常の scope で描画されるため、nested host などで `$parent` が使える場合は参照できます。\n\n\n#### conditionals and loops との併用\n\n`*unwrap` は conditionals と組み合わせて wrapper を消す用途に使えます。\n\n```html\n<div *if=\"show\" *unwrap>\n  <p>Visible</p>\n</div>\n```\n\nただし、同じ要素に structural directives を重ねる場合、runtime の処理順に注意します。\n\nloop では、wrapper を残さず children を繰り返したい場合に役立ちます。\n\n\n#### 推奨される使い方\n\n- 不要な wrapper DOM を残したくない場合に使います。\n- semantic な wrapper が必要な場合は使わないでください。\n- 同じ要素に多くの structural directives を重ねないでください。\n- children の scope を保ったまま wrapper だけ消したいときに使います。\n\n\n#### 追加例\n\nfragment output の例:\n\n```html\n<div *unwrap>\n  <h2>%title%</h2>\n  <p>%body%</p>\n</div>\n```\n\nconditional fragment の例:\n\n```html\n<div *if=\"visible\" *unwrap>\n  <span>A</span>\n  <span>B</span>\n</div>\n```\n\n\n#### 注意点\n\n- `*unwrap` と `n-unwrap` は aliases です。\n- 要素自体を出力せず、children だけを描画します。\n- data や scope を直接変更しません。\n- DOM 構造を軽くしたい場合に使います。\n",
  "updated-propagate": "### *updated-propagate\n\n#### 概要\n\n`*updated-propagate` は `*update` の互換 alias です。\n\n新しい template では `*update` を使ってください。挙動、target spec、timing、error handling は `*update` と同じです。\n\naliases:\n\n- `*updated-propagate`\n- `n-updated-propagate`\n\npreferred aliases:\n\n- `*update`\n- `n-update`\n\n#### 例\n\n古い書き方:\n\n```html\n<button *updated-propagate=\"root\">Refresh root</button>\n```\n\n推奨される新しい書き方:\n\n```html\n<button *update=\"root\">Refresh root</button>\n```\n\n#### target spec\n\n`*updated-propagate` の値は `*update` と同じ literal target spec です。\n\n- 空値: `\"1\"` として扱います。\n- `root`: outermost Sercrod host を更新します。\n- 数字: Sercrod host だけを数えます。\n- `(selector)`: closest matching Sercrod host を探します。\n- その他: bare CSS selector として扱います。\n\nJavaScript expression ではありません。data や scope は直接変更しません。\n",
  "updated": "### *updated\n\n#### 概要\n\n`*updated` は、Sercrod host または要素の update 後に handler を実行するための lifecycle directive です。\n\nrendering が終わったあとに DOM inspection、外部 widget の再初期化、debug、post-render adjustment などを行いたい場合に使います。\n\nalias の `n-updated` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"count\":0}' *updated=\"afterUpdate()\">\n  <button type=\"button\" @click=\"count++\">Increment</button>\n  <p>%count%</p>\n</serc-rod>\n```\n\nhost が update された後、`afterUpdate()` が呼ばれます。\n\n\n#### 挙動\n\n基本規則:\n\n- `*updated` は update 後に handler を実行します。\n- host 上に置いた場合、host update lifecycle に紐付きます。\n- ordinary element 上に置いた場合、その element の描画後または更新後に handler を呼びます。\n- 属性値は handler expression または function reference として扱われます。\n- data を直接作る directive ではありませんが、handler が data を変更することはできます。\n\nただし、updated handler 内で data を変更すると update loop を作る可能性があるため注意します。\n\n\n#### Sercrod host 上の handler 解決\n\n`<serc-rod>` host 上の `*updated` は host lifecycle に結び付きます。\n\n```html\n<serc-rod *updated=\"onHostUpdated()\">\n```\n\nhandler は host の scope で解決されます。\n\n`*methods` で import された functions や global functions を呼べます。\n\nhost が再描画されたあとに実行されるため、DOM が存在する状態で処理できます。\n\n\n#### 通常要素上の handler 解決\n\nordinary element 上に `*updated` を置く場合、その element の更新後 hook として扱われます。\n\n```html\n<div *updated=\"initWidget($el)\"></div>\n```\n\n`$el` または `el` を使って対象 element を参照できます。\n\nただし、element が再描画で作り直される場合は、handler が複数回実行される可能性があります。\n\n\n#### 評価タイミング\n\n`*updated` は render 後に実行されます。\n\n1. data change や event により host update が始まります。\n2. template が描画されます。\n3. DOM が更新されます。\n4. `*updated` hooks が呼ばれます。\n5. 必要に応じて `*updated-propagate` が後続 target へ伝播します。\n\nこれは render 前処理ではなく post-render hook です。\n\n\n#### 実行モデル\n\n概念的には次のような処理です。\n\n```js\nafterRender(){\n        for(const hook of updatedHooks){\n                evaluate(hook.expression, hook.scopeWithElement);\n        }\n}\n```\n\n実際の runtime は hook index、event detail、host/element context、error handling を含みます。\n\n\n#### 変数の作成とスコープの重なり\n\n`*updated` は変数を作りません。\n\n- update 後に expression を実行します。\n- scope は通常の Sercrod expression と同様です。\n- `el` / `$el` によって対象 element を参照できる場合があります。\n- handler が data を変更すれば、その変更は別の update を引き起こす可能性があります。\n\nそのため、状態変更よりも post-render integration に使う方が安全です。\n\n\n#### 親へのアクセス\n\nnested host 内では、scope に `$parent` がある場合、`*updated` expression から参照できます。\n\nただし、parent data を updated hook から変更すると update chain が複雑になりやすいため、慎重に扱います。\n\n\n#### conditionals and loops との併用\n\nconditional element に `*updated` を置くと、その element が描画されるたびに handler が実行される可能性があります。\n\n```html\n<div *if=\"visible\" *updated=\"init($el)\"></div>\n```\n\nloop 内では、各 item の element ごとに handler が実行されます。\n\n```html\n<div *for=\"item of items\" *updated=\"initRow($el, item)\"></div>\n```\n\n大量要素では performance に注意します。\n\n\n#### 推奨される使い方\n\n- DOM が描画された後に必要な処理に限定します。\n- data mutation を繰り返して update loop を作らないようにします。\n- 外部 widget 初期化では、重複初期化を避ける guard を入れます。\n- loop 内では必要な場合だけ使います。\n- 可能なら通常の Sercrod binding で解決し、`*updated` は最後の補助にします。\n\n\n#### 例\n\nDOM inspection の例:\n\n```html\n<div *updated=\"console.log($el.offsetHeight)\"></div>\n```\n\nwidget init の例:\n\n```html\n<div class=\"chart\" *updated=\"initChart($el, data)\"></div>\n```\n\nhost updated の例:\n\n```html\n<serc-rod *updated=\"afterSercrodUpdate($data)\">\n  ...\n</serc-rod>\n```\n\n\n#### 注意点\n\n- `*updated` と `n-updated` は aliases です。\n- render 後 hook です。\n- data binding の代替ではありません。\n- data mutation を行う場合は update loop に注意します。\n",
  "upload": "### *upload\n\n#### 概要\n\n`*upload` は、file input や upload trigger から files を送信するための directive です。\n\n`FormData` を作成し、指定 endpoint へ file を upload します。response は data に書き込むことができ、upload 状態は `$pending`、`$error`、`$upload` などの shared state と連携します。\n\nalias の `n-upload` も同じ挙動です。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"result\":null}'>\n  <input type=\"file\" *upload=\"{ url: '/api/upload', into: 'result' }\">\n\n  <pre *if=\"result\" *print=\"JSON.stringify(result, null, 2)\"></pre>\n</serc-rod>\n```\n\nfile を選択すると upload が実行され、response が `result` に入ります。\n\n\n#### 挙動\n\n基本規則:\n\n- file input または upload control に behavior を取り付けます。\n- upload options を評価します。\n- `FormData` を作ります。\n- 選択された files を追加します。\n- fetch または XHR で送信します。\n- response を parse します。\n- `$upload` や `*into` 相当の destination に response を保存します。\n- error 時は `$error` を更新し、error event を dispatch する場合があります。\n\n`*upload` は file upload に特化した helper です。汎用 HTTP 操作には `*api` を使います。\n\n\n#### option object について\n\n`*upload` の値は option object として扱えます。\n\n主な keys:\n\n- `url`\n  - upload endpoint。\n- `method`\n  - 通常は POST。\n- `name`\n  - FormData field name。\n- `headers`\n  - request headers。\n- `credentials`\n  - cookie などの送信設定。\n- `into`\n  - response destination。\n- `multiple`\n  - 複数 file の扱い。\n\n例:\n\n```html\n<input\n  type=\"file\"\n  *upload=\"{ url: '/api/upload', name: 'file', into: 'result' }\">\n```\n\n#### hidden input と host 属性\n\nvisible button から hidden file input を使う構成も考えられます。\n\nhost や wrapper に upload options を置き、hidden input を実際の file selector として使う設計です。\n\nこの場合、どの element が file selection を持ち、どの element が upload trigger なのかを明確にします。\n\n複雑になる場合は、plain `<input type=\"file\" *upload=\"...\">` を使う方が安全です。\n\n\n#### 評価タイミング\n\nrender 時:\n\n1. `*upload` / `n-upload` を持つ element を検出します。\n2. option expression を評価します。\n3. file selection または click handler を取り付けます。\n\nuser interaction 時:\n\n1. user が file を選択します。\n2. `FormData` が作られます。\n3. request が送信されます。\n4. response が parse されます。\n5. data と state flags が更新されます。\n6. host が update されます。\n\n\n#### 実行モデル\n\n概念的には次の通りです。\n\n```js\nconst formData = new FormData();\n\nfor(const file of input.files){\n        formData.append(fieldName, file);\n}\n\nconst response = await fetch(url, {\n        method: method || \"POST\",\n        body: formData\n});\n\nconst data = await parseResponse(response);\nwriteUploadResult(data);\n```\n\n実際の runtime は option handling、events、errors、fallback transport を含みます。\n\n\n#### 変数の作成と *into\n\n`*upload` は loop variables のような template variables を作りません。\n\nただし response を data に書き込むことがあります。\n\n- `$upload`\n  - 最後の upload response。\n- destination key:\n  - `into` や `*into` 相当の設定がある場合、指定先に response を保存します。\n\n保存先 path と template が読む path を一致させます。\n\n\n#### スコープの重なりと親へのアクセス\n\nupload option expression は現在の scope で評価されます。\n\nhost data、loop variables、`*let` values、`$parent` などを参照できる場合があります。\n\n```html\n<input type=\"file\" *upload=\"{ url: '/api/users/' + user.id + '/avatar' }\">\n```\n\nnested host では、どの host の data に response を書くかを明確にします。\n\n\n#### conditionals and loops との併用\n\nconditionals と組み合わせられます。\n\n```html\n<input *if=\"canUpload\" type=\"file\" *upload=\"uploadOptions\">\n```\n\nloop 内で row ごとの upload を作ることもできます。\n\n```html\n<input\n  *for=\"item of items\"\n  type=\"file\"\n  *upload=\"{ url: '/api/items/' + item.id + '/file' }\">\n```\n\n大量の input や複雑な upload state では、data model を慎重に設計します。\n\n\n#### event と UI 連携\n\nupload lifecycle では event が dispatch される場合があります。\n\n- upload start。\n- upload success。\n- upload error。\n- `sercrod-error`。\n\nUI では shared state を使えます。\n\n```html\n<p *if=\"$pending\">Uploading...</p>\n<p *if=\"$error\">%$error.message%</p>\n<pre *if=\"$upload\" *print=\"JSON.stringify($upload, null, 2)\"></pre>\n```\n\nproject 側で progress 表示が必要な場合は、XHR transport や custom method を検討します。\n\n\n#### *upload のサーバー側契約\n\nserver は multipart/form-data を受け取る前提で実装します。\n\n推奨 response:\n\n```json\n{\n  \"ok\": true,\n  \"message\": \"Uploaded\",\n  \"file\": {\n    \"name\": \"example.png\",\n    \"url\": \"/uploads/example.png\"\n  }\n}\n```\n\ntemplate が `result.file.url` を読むなら、response shape と destination を合わせます。\n\n\n#### 推奨される使い方\n\n- simple file upload には `<input type=\"file\" *upload=\"...\">` を使います。\n- response destination を明確にします。\n- `$pending` と `$error` を表示します。\n- server 側で file type、size、権限を検証します。\n- sensitive files では認証・認可を必ず行います。\n- progress が必要なら transport と UI を別途設計します。\n\n\n#### 注意点\n\n- `*upload` と `n-upload` は aliases です。\n- file upload 専用 helper です。\n- `FormData` を使います。\n- response は `$upload` や destination に保存されます。\n- server-side validation が必須です。\n",
  "websocket": "### *websocket\n\n#### 概要\n\n`*websocket` は、Sercrod host または element に WebSocket connection を設定する directive です。\n\n接続状態、受信メッセージ、送信用 helper を Sercrod data や element controller と連携させます。\n\n`*ws-send` と `*ws-to` と組み合わせることで、template から WebSocket message を送信できます。\n\n\n#### 基本例\n\nhost に接続を持たせる例です。\n\n```html\n<serc-rod data='{\"message\":\"\"}' *websocket=\"'wss://example.com/ws'\">\n  <input *input=\"message\">\n  <button type=\"button\" *ws-send=\"message\">Send</button>\n</serc-rod>\n```\n\n受信先を指定する例です。\n\n```html\n<serc-rod *websocket=\"{ url: 'wss://example.com/ws', into: 'lastMessage' }\">\n  <p>%lastMessage%</p>\n</serc-rod>\n```\n\n\n#### host と element での使用\n\nhost 上に `*websocket` を置く場合、connection はその host の data scope と連携します。\n\nordinary element 上に置く場合、その element に WebSocket controller が紐付くことがあります。\n\nどちらの場合も、`*ws-send` がどの connection に送るのかを明確にします。複数 connection がある場合は `*ws-to` を使います。\n\n\n#### 指定式と URL 解決\n\n`*websocket` の値は URL string または option object として扱えます。\n\n```html\n<serc-rod *websocket=\"'wss://example.com/ws'\">\n```\n\n```html\n<serc-rod *websocket=\"{ url: wsUrl, name: 'main', into: 'last' }\">\n```\n\nURL は current scope で評価されます。\n\noption object では、name、into、protocols、reconnect などの設定を持つ場合があります。\n\n\n#### data 連携と状態 field\n\nWebSocket connection は、host data に状態を反映する場合があります。\n\n代表例:\n\n- `$ws_ready`\n- `$ws_open`\n- `$ws_last`\n- `$ws_error`\n- `$ws_count`\n\n実際の field names は runtime 実装に従います。\n\ntemplate はこれらの state を使って UI を出せます。\n\n```html\n<p *if=\"$ws_ready\">Connected</p>\n<p *if=\"$ws_last\">%$ws_last%</p>\n```\n\n\n#### *websocket での *into の使用\n\n`into` または `*into` を使うと、受信メッセージの保存先を指定できます。\n\n```html\n<serc-rod *websocket=\"{ url: wsUrl, into: 'lastMessage' }\">\n  <p>%lastMessage%</p>\n</serc-rod>\n```\n\n受信 data の shape と template path を一致させます。\n\nJSON message を受け取る場合は、parse 後の object か raw text かを明確にします。\n\n\n#### event と lifecycle hook\n\nWebSocket lifecycle では event が発生する場合があります。\n\n- open。\n- message。\n- close。\n- error。\n- reconnect。\n\nSercrod はこれらを data state や custom events として公開する場合があります。\n\ndebug では、browser console、network panel、Sercrod state fields を合わせて確認します。\n\n\n#### WebSocket controller - `el.websocket` について\n\nelement に WebSocket controller が紐付く場合、`el.websocket` のような helper API から接続を操作できることがあります。\n\n例:\n\n```js\nel.websocket.send(\"hello\");\n```\n\nこれは project/runtime の API に依存します。template からは通常 `*ws-send` を使う方が安全です。\n\n\n#### *ws-send / *ws-to との関係\n\n`*ws-send` は message を送ります。\n\n`*ws-to` は、複数 connection がある場合に送信先を指定します。\n\n```html\n<button *ws-to=\"main\" *ws-send=\"message\">Send</button>\n```\n\nsingle connection なら `*ws-to` が不要な場合があります。\n\n複数 connection では、name を明確に付けます。\n\n\n#### 評価タイミングと再接続\n\n`*websocket` は render または host initialization 時に connection spec を評価します。\n\nURL や options が変わる場合、既存 connection の扱い、再接続、close の timing は runtime 実装に従います。\n\nreconnection を有効にする場合は、server 側負荷や backoff を考慮します。\n\n\n#### 推奨される使い方\n\n- connection name を明確にします。\n- `into` で受信 data の保存先を明示します。\n- UI に connection state を表示します。\n- server message format を安定させます。\n- reconnect を使う場合は backoff を考慮します。\n- sensitive data を送る場合は認証・認可・TLS を確認します。\n\n\n#### 注意点\n\n- `*websocket` は WebSocket connection を扱います。\n- `*ws-send` と組み合わせて送信します。\n- 複数 connection では `*ws-to` を使います。\n- 受信 data と template path の契約を明確にします。\n",
  "ws-send": "### *ws-send\n\n#### 概要\n\n`*ws-send` は、Sercrod の WebSocket connection へ message を送信する directive です。\n\n通常は button などの clickable element に付け、click 時に expression を評価して payload を作り、対象 WebSocket へ送ります。\n\n`*websocket` と組み合わせて使います。\n\n\n#### 基本例\n\n```html\n<serc-rod data='{\"message\":\"\"}' *websocket=\"'wss://example.com/ws'\">\n  <input *input=\"message\">\n  <button type=\"button\" *ws-send=\"message\">Send</button>\n</serc-rod>\n```\n\nbutton を click すると、`message` の現在値が WebSocket へ送られます。\n\n\n#### 挙動\n\n基本規則:\n\n- `*ws-send` は送信 trigger を作ります。\n- 属性値は payload expression として評価されます。\n- clickable element では click により送信します。\n- payload は string または JSON へ変換される場合があります。\n- 対象 WebSocket は nearest host や `*ws-to` によって決まります。\n- 送信できない状態では warning または error になる場合があります。\n\n\n#### click 可能性と event wiring\n\n`*ws-send` は通常 clickable element に付けます。\n\n```html\n<button type=\"button\" *ws-send=\"message\">Send</button>\n```\n\n`a` を使う場合は navigation と衝突するため、`button` を優先します。\n\nclick handler は runtime が取り付けます。同じ要素に複雑な `@click` を重ねると timing が分かりにくくなる場合があります。\n\n\n#### 式と payload の評価\n\n`*ws-send` の属性値は現在の scope で評価されます。\n\n```html\n<button *ws-send=\"{ type: 'chat', text: message }\">Send</button>\n```\n\npayload が object の場合、runtime が JSON.stringify する場合があります。server が期待する message format と一致させます。\n\nstring を送る場合:\n\n```html\n<button *ws-send=\"message\">Send</button>\n```\n\n\n#### `*ws-to` 属性による送信先選択\n\n複数 WebSocket connection がある場合は、`*ws-to` で送信先を指定します。\n\n```html\n<button *ws-to=\"main\" *ws-send=\"message\">Send</button>\n```\n\n`*ws-to` がない場合、nearest host の default connection が使われる場合があります。\n\ntarget name と `*websocket` の connection name を一致させます。\n\n\n#### 評価タイミング\n\nrender 時:\n\n1. `*ws-send` element を検出します。\n2. click handler を取り付けます。\n\nclick 時:\n\n1. payload expression を current scope で評価します。\n2. `*ws-to` または default から target connection を解決します。\n3. connection が open であれば payload を送信します。\n4. 必要に応じて state や events を更新します。\n\n\n#### 実行モデル\n\n概念的には次の通りです。\n\n```js\nbutton.addEventListener(\"click\", ()=>{\n        const payload = evaluate(wsSendExpression, scope);\n        const socket = resolveWebSocketTarget(element, scope);\n\n        socket.send(normalizePayload(payload));\n});\n```\n\n実際の runtime は readiness check、serialization、error handling を含みます。\n\n\n#### スコープの重なりと変数\n\n`*ws-send` の expression は current scope で評価されます。\n\n- host data。\n- loop variables。\n- `*let` values。\n- `$parent`。\n- methods。\n\nloop 内では、各 item の値を payload に含められます。\n\n```html\n<button *for=\"item of items\" *ws-send=\"{ id: item.id }\">Send</button>\n```\n\n\n#### *websocket と WebSocket metrics との併用\n\n`*ws-send` は `*websocket` が作る connection と state fields に依存します。\n\nUI では connection state を見て button を制御できます。\n\n```html\n<button type=\"button\" *if=\"$ws_ready\" *ws-send=\"message\">Send</button>\n```\n\n送信数や最終送信時刻などの metrics を runtime が提供する場合は、それに合わせて表示できます。\n\n\n#### 推奨される使い方\n\n- `button type=\"button\"` に付けます。\n- payload shape を server と合わせます。\n- 複数 connection では `*ws-to` を明示します。\n- connection ready state を UI で確認します。\n- 大きな object や sensitive data を安易に送らないでください。\n- click handler と送信責務を混ぜすぎないようにします。\n\n\n#### 追加例\n\nJSON message の例:\n\n```html\n<button *ws-send=\"{ type: 'ping', at: Date.now() }\">Ping</button>\n```\n\nloop item の例:\n\n```html\n<button *for=\"row of rows\" *ws-send=\"{ type: 'select', id: row.id }\">\n  Select\n</button>\n```\n\ntargeted send の例:\n\n```html\n<button *ws-to=\"chat\" *ws-send=\"{ text: message }\">Send chat</button>\n```\n\n\n#### 注意点\n\n- `*ws-send` は WebSocket message 送信用です。\n- `*websocket` による connection が必要です。\n- `*ws-to` で送信先を指定できます。\n- payload serialization は server contract と合わせます。\n",
  "ws-to": "### *ws-to\n\n#### 概要\n\n`*ws-to` は、`*ws-send` が message を送る WebSocket connection を指定する companion directive です。\n\n複数の `*websocket` connection がある場合に、どの connection へ送るかを明示します。\n\n\n#### *ws-send と *websocket との関係\n\n- `*websocket`\n  - connection を作ります。\n- `*ws-send`\n  - message を送ります。\n- `*ws-to`\n  - 送信先 connection を指定します。\n\n`*ws-to` は単独では送信しません。通常は `*ws-send` と同じ要素に置きます。\n\n\n#### 基本例 - 1つの host で2つの WebSocket を使う\n\n```html\n<serc-rod\n  *websocket=\"{ url: 'wss://example.com/chat', name: 'chat' }\"\n  data='{\"message\":\"\"}'>\n\n  <button type=\"button\" *ws-to=\"chat\" *ws-send=\"message\">\n    Send\n  </button>\n</serc-rod>\n```\n\n`*ws-to=\"chat\"` により、`chat` という名前の connection へ送ります。\n\n\n#### 挙動\n\n基本規則:\n\n- 属性値は connection target name として扱われます。\n- `*ws-send` の target resolution で参照されます。\n- `*ws-to` だけでは event handler を作りません。\n- target が見つからない場合、warning または error になる場合があります。\n- 複数 connection を扱う template で送信先を明確にします。\n\ntarget name は connection definition 側の name と一致させます。\n\n\n#### 評価タイミング\n\n`*ws-to` は `*ws-send` の送信時に参照されます。\n\n1. user が `*ws-send` element を click します。\n2. runtime が同じ element または関連 element の `*ws-to` を読みます。\n3. target name を解決します。\n4. 対象 WebSocket connection を取得します。\n5. payload を送信します。\n\nrender 時に static target として登録される場合もありますが、実際に意味を持つのは送信時です。\n\n\n#### text expansion との関係\n\n`*ws-to` の値を literal target name として扱うか、expression として扱うかは runtime 実装に従います。\n\nstatic name の例:\n\n```html\n<button *ws-to=\"chat\" *ws-send=\"message\">Send</button>\n```\n\ndynamic target が必要な場合は、仕様に沿って expression または data field を使います。\n\n```html\n<button *ws-to=\"targetName\" *ws-send=\"message\">Send</button>\n```\n\nどちらの意味になるかを project 内で明確にします。\n\n\n#### host ごとの複数 connection\n\nhost に複数 connection がある場合、`*ws-to` は特に重要です。\n\n例:\n\n```html\n<serc-rod\n  *websocket=\"{ url: chatUrl, name: 'chat' }\"\n  data='{\"message\":\"\"}'>\n  <button *ws-to=\"chat\" *ws-send=\"message\">Send chat</button>\n</serc-rod>\n```\n\n別 connection を追加する場合は、それぞれに明確な name を付けます。\n\n#### *into と受信 message との関係\n\n`*into` や `into` は受信 message の保存先を指定します。\n\n`*ws-to` は送信先を指定します。\n\nこの2つは役割が違います。\n\n- `into`:\n  - received data destination。\n- `*ws-to`:\n  - outgoing message target。\n\n混同しないようにします。\n\n\n#### websocket helper API との併用\n\nruntime が `el.websocket` などの helper API を提供する場合でも、template からの送信では `*ws-to` と `*ws-send` を使う方が宣言的です。\n\ncustom JavaScript で直接送る場合は、helper API を使うこともできます。\n\n```js\nel.websocket.send(\"hello\");\n```\n\nただし、template の見通しを保つには declarative attributes を優先します。\n\n\n#### 推奨される使い方\n\n- 複数 connection がある場合は `*ws-to` を必ず明示します。\n- target name は短く、用途が分かるものにします。\n- connection name と `*ws-to` の値を一致させます。\n- `into` と `*ws-to` を混同しないでください。\n- dynamic target は必要な場合だけ使います。\n\n\n#### 追加例\n\nchat connection の例:\n\n```html\n<button *ws-to=\"chat\" *ws-send=\"{ text: message }\">Send</button>\n```\n\nnotification connection の例:\n\n```html\n<button *ws-to=\"notify\" *ws-send=\"{ type: 'ping' }\">Ping</button>\n```\n\nloop item の例:\n\n```html\n<button *for=\"room of rooms\" *ws-to=\"room.socketName\" *ws-send=\"{ room: room.id }\">\n  Send to %room.name%\n</button>\n```\n\n\n#### 注意点\n\n- `*ws-to` は送信先指定用です。\n- 単独では送信しません。\n- `*ws-send` と組み合わせます。\n- `into` は受信先、`*ws-to` は送信先です。\n",
  "save.file": "### *save / *save.file / *save.session / *save.store\n\n#### 概要\n\n`*save.file` は、host data または staged view を JSON file として browser から download します。\n`*save.session` は、同じ JSON payload を browser の `sessionStorage` に保存します。\n`*save.store` は、同じ JSON payload を persistent browser storage、現在は IndexedDB、に保存します。\n`*save` は互換用の古い file save 形式として残ります。\n\n保存する data は `*keys` で選択できます。`*keys` を省略した場合は、host data または stage 全体を保存します。\n\n#### 基本例\n\nfile として保存します。\n\n```html\n<button type=\"button\" *save.file=\"'profile.json'\" *keys=\"profile settings\">\n  Save file\n</button>\n```\n\nsessionStorage に保存します。\n\n```html\n<button type=\"button\" *save.session=\"'profile-draft'\" *keys=\"profile settings\">\n  Save session\n</button>\n```\n\npersistent browser storage に保存します。\n\n```html\n<button type=\"button\" *save.store=\"'profile-draft'\" *keys=\"profile settings\">\n  Save store\n</button>\n```\n\n#### 挙動\n\n- `*save.file` の値は file name です。\n- `*save.session` の値は `sessionStorage` key です。\n- `*save.store` の値は persistent browser storage key です。\n- `*save.store` は既定で IndexedDB database `sercrod-store` の object store `json` に JSON string を保存します。\n- `*keys` は whitespace 区切りの top-level key list です。\n- `*keys` がない場合は、`this._stage ?? this._data` 全体を JSON 化します。\n- `*save.session` は `window.sessionStorage.setItem(storageKey, json)` を使います。\n- `*save.store` は IndexedDB が使えない場合や書き込みに失敗した場合、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-saved` event を dispatch します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"save\"`、session では `\"save.session\"`、store では `\"save.store\"`。\n- `detail.fileName`: file save の file name。\n- `detail.storage`: session/store save では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*save.session` または `*save.store` の key。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 保存した JSON string。\n\n#### 互換性\n\n古い形式の `*save=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*save.file` / `*save.session` / `*save.store` と `*keys` を使ってください。\n",
  "save.session": "### *save / *save.file / *save.session / *save.store\n\n#### 概要\n\n`*save.file` は、host data または staged view を JSON file として browser から download します。\n`*save.session` は、同じ JSON payload を browser の `sessionStorage` に保存します。\n`*save.store` は、同じ JSON payload を persistent browser storage、現在は IndexedDB、に保存します。\n`*save` は互換用の古い file save 形式として残ります。\n\n保存する data は `*keys` で選択できます。`*keys` を省略した場合は、host data または stage 全体を保存します。\n\n#### 基本例\n\nfile として保存します。\n\n```html\n<button type=\"button\" *save.file=\"'profile.json'\" *keys=\"profile settings\">\n  Save file\n</button>\n```\n\nsessionStorage に保存します。\n\n```html\n<button type=\"button\" *save.session=\"'profile-draft'\" *keys=\"profile settings\">\n  Save session\n</button>\n```\n\npersistent browser storage に保存します。\n\n```html\n<button type=\"button\" *save.store=\"'profile-draft'\" *keys=\"profile settings\">\n  Save store\n</button>\n```\n\n#### 挙動\n\n- `*save.file` の値は file name です。\n- `*save.session` の値は `sessionStorage` key です。\n- `*save.store` の値は persistent browser storage key です。\n- `*save.store` は既定で IndexedDB database `sercrod-store` の object store `json` に JSON string を保存します。\n- `*keys` は whitespace 区切りの top-level key list です。\n- `*keys` がない場合は、`this._stage ?? this._data` 全体を JSON 化します。\n- `*save.session` は `window.sessionStorage.setItem(storageKey, json)` を使います。\n- `*save.store` は IndexedDB が使えない場合や書き込みに失敗した場合、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-saved` event を dispatch します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"save\"`、session では `\"save.session\"`、store では `\"save.store\"`。\n- `detail.fileName`: file save の file name。\n- `detail.storage`: session/store save では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*save.session` または `*save.store` の key。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 保存した JSON string。\n\n#### 互換性\n\n古い形式の `*save=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*save.file` / `*save.session` / `*save.store` と `*keys` を使ってください。\n",
  "load.file": "### *load / *load.file / *load.session / *load.store\n\n#### 概要\n\n`*load.file` は、ユーザーが選択した JSON file を読み込み、Sercrod host の data に merge します。\n`*load.session` は、browser の `sessionStorage` から JSON を読み込み、同じ merge rules で data に反映します。\n`*load.store` は、persistent browser storage、現在は IndexedDB、から JSON を読み込み、同じ merge rules で data に反映します。\n`*load` は互換用の古い file load 形式として残ります。\n\n`*keys` で読み込む top-level keys を選べます。`*into` がある場合だけ、その property に読み込み結果を入れます。\n\n#### 基本例\n\nfile から読み込みます。\n\n```html\n<button type=\"button\" *load.file *keys=\"profile\" *into=\"draft\">\n  Load file\n</button>\n```\n\nsessionStorage から読み込みます。\n\n```html\n<button type=\"button\" *load.session=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load session\n</button>\n```\n\npersistent browser storage から読み込みます。\n\n```html\n<button type=\"button\" *load.store=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load store\n</button>\n```\n\n#### merge rules\n\n- `*keys` も `*into` もない場合: 読み込んだ JSON object 全体を `_stage` または `_data` に `Object.assign` します。\n- `*keys` だけがある場合: 指定された top-level keys だけを `_stage` または `_data` に copy します。\n- `*into` がある場合: 読み込んだ全体、または `*keys` で選んだ値を、その property に入れます。\n- `*keys` が 1 個で `*into` がある場合: `json[key]` を `data[into]` に入れます。\n- `*keys` が複数で `*into` がある場合: 選択 key だけを持つ object を `data[into]` に入れます。\n\n#### 挙動\n\n- `*load.file` は file picker と `FileReader` を使います。\n- `*load.session` の値は `sessionStorage` key です。\n- `*load.store` の値は persistent browser storage key です。\n- `*load.store` は既定で IndexedDB database `sercrod-store` の object store `json` から JSON string を読みます。\n- key が存在しない場合、JSON parse に失敗した場合、IndexedDB が使えない場合は、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-loaded` event を dispatch し、host を update します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"load\"`、session では `\"load.session\"`、store では `\"load.store\"`。\n- `detail.fileName`: file load の file name。\n- `detail.storage`: session/store load では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*load.session` または `*load.store` の key。\n- `detail.into`: `*into` の destination、なければ `null`。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 読み込まれた JSON object。\n\n#### 互換性\n\n古い形式の `*load=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*load.file` / `*load.session` / `*load.store` と `*keys` / `*into` を使ってください。\n",
  "load.session": "### *load / *load.file / *load.session / *load.store\n\n#### 概要\n\n`*load.file` は、ユーザーが選択した JSON file を読み込み、Sercrod host の data に merge します。\n`*load.session` は、browser の `sessionStorage` から JSON を読み込み、同じ merge rules で data に反映します。\n`*load.store` は、persistent browser storage、現在は IndexedDB、から JSON を読み込み、同じ merge rules で data に反映します。\n`*load` は互換用の古い file load 形式として残ります。\n\n`*keys` で読み込む top-level keys を選べます。`*into` がある場合だけ、その property に読み込み結果を入れます。\n\n#### 基本例\n\nfile から読み込みます。\n\n```html\n<button type=\"button\" *load.file *keys=\"profile\" *into=\"draft\">\n  Load file\n</button>\n```\n\nsessionStorage から読み込みます。\n\n```html\n<button type=\"button\" *load.session=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load session\n</button>\n```\n\npersistent browser storage から読み込みます。\n\n```html\n<button type=\"button\" *load.store=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load store\n</button>\n```\n\n#### merge rules\n\n- `*keys` も `*into` もない場合: 読み込んだ JSON object 全体を `_stage` または `_data` に `Object.assign` します。\n- `*keys` だけがある場合: 指定された top-level keys だけを `_stage` または `_data` に copy します。\n- `*into` がある場合: 読み込んだ全体、または `*keys` で選んだ値を、その property に入れます。\n- `*keys` が 1 個で `*into` がある場合: `json[key]` を `data[into]` に入れます。\n- `*keys` が複数で `*into` がある場合: 選択 key だけを持つ object を `data[into]` に入れます。\n\n#### 挙動\n\n- `*load.file` は file picker と `FileReader` を使います。\n- `*load.session` の値は `sessionStorage` key です。\n- `*load.store` の値は persistent browser storage key です。\n- `*load.store` は既定で IndexedDB database `sercrod-store` の object store `json` から JSON string を読みます。\n- key が存在しない場合、JSON parse に失敗した場合、IndexedDB が使えない場合は、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-loaded` event を dispatch し、host を update します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"load\"`、session では `\"load.session\"`、store では `\"load.store\"`。\n- `detail.fileName`: file load の file name。\n- `detail.storage`: session/store load では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*load.session` または `*load.store` の key。\n- `detail.into`: `*into` の destination、なければ `null`。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 読み込まれた JSON object。\n\n#### 互換性\n\n古い形式の `*load=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*load.file` / `*load.session` / `*load.store` と `*keys` / `*into` を使ってください。\n",
  "keys": "### *keys\n\n#### 概要\n\n`*keys` は action directive で使う top-level data keys を選択します。\n\n```html\n<button *save.file=\"'backup.json'\" *keys=\"profile settings\">Save</button>\n<button *load.file *keys=\"profile\" *into=\"draft\">Load</button>\n<button *save.session=\"'draft'\" *keys=\"profile settings\">Save session</button>\n<button *load.session=\"'draft'\" *keys=\"profile\" *into=\"draft\">Load session</button>\n<button *save.store=\"'draft'\" *keys=\"profile settings\">Save store</button>\n<button *load.store=\"'draft'\" *keys=\"profile\" *into=\"draft\">Load store</button>\n<button *websocket.send=\"wsUrl\" *keys=\"message\">Send</button>\n```\n\n#### 役割\n\n- `*save.file`、`*load.file`、`*save.session`、`*load.session`、`*save.store`、`*load.store`、`*websocket.send` は action の行き先または読み込み元を表します。\n- `*keys` は、どの data を使うかを表します。\n- `*keys` を省略した場合、その action で自然な全体 data を使います。\n\n#### ルール\n\n- key は whitespace 区切りの top-level names です。\n- nested path は解釈しません。\n- alias は `n-keys` です。\n- 旧 `*save=\"profile settings\"` と `*load=\"profile settings\"` は互換用に残りますが、新しい例では `*keys` を使います。\n",
  "save.store": "### *save / *save.file / *save.session / *save.store\n\n#### 概要\n\n`*save.file` は、host data または staged view を JSON file として browser から download します。\n`*save.session` は、同じ JSON payload を browser の `sessionStorage` に保存します。\n`*save.store` は、同じ JSON payload を persistent browser storage、現在は IndexedDB、に保存します。\n`*save` は互換用の古い file save 形式として残ります。\n\n保存する data は `*keys` で選択できます。`*keys` を省略した場合は、host data または stage 全体を保存します。\n\n#### 基本例\n\nfile として保存します。\n\n```html\n<button type=\"button\" *save.file=\"'profile.json'\" *keys=\"profile settings\">\n  Save file\n</button>\n```\n\nsessionStorage に保存します。\n\n```html\n<button type=\"button\" *save.session=\"'profile-draft'\" *keys=\"profile settings\">\n  Save session\n</button>\n```\n\npersistent browser storage に保存します。\n\n```html\n<button type=\"button\" *save.store=\"'profile-draft'\" *keys=\"profile settings\">\n  Save store\n</button>\n```\n\n#### 挙動\n\n- `*save.file` の値は file name です。\n- `*save.session` の値は `sessionStorage` key です。\n- `*save.store` の値は persistent browser storage key です。\n- `*save.store` は既定で IndexedDB database `sercrod-store` の object store `json` に JSON string を保存します。\n- `*keys` は whitespace 区切りの top-level key list です。\n- `*keys` がない場合は、`this._stage ?? this._data` 全体を JSON 化します。\n- `*save.session` は `window.sessionStorage.setItem(storageKey, json)` を使います。\n- `*save.store` は IndexedDB が使えない場合や書き込みに失敗した場合、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-saved` event を dispatch します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"save\"`、session では `\"save.session\"`、store では `\"save.store\"`。\n- `detail.fileName`: file save の file name。\n- `detail.storage`: session/store save では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*save.session` または `*save.store` の key。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 保存した JSON string。\n\n#### 互換性\n\n古い形式の `*save=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*save.file` / `*save.session` / `*save.store` と `*keys` を使ってください。\n",
  "load.store": "### *load / *load.file / *load.session / *load.store\n\n#### 概要\n\n`*load.file` は、ユーザーが選択した JSON file を読み込み、Sercrod host の data に merge します。\n`*load.session` は、browser の `sessionStorage` から JSON を読み込み、同じ merge rules で data に反映します。\n`*load.store` は、persistent browser storage、現在は IndexedDB、から JSON を読み込み、同じ merge rules で data に反映します。\n`*load` は互換用の古い file load 形式として残ります。\n\n`*keys` で読み込む top-level keys を選べます。`*into` がある場合だけ、その property に読み込み結果を入れます。\n\n#### 基本例\n\nfile から読み込みます。\n\n```html\n<button type=\"button\" *load.file *keys=\"profile\" *into=\"draft\">\n  Load file\n</button>\n```\n\nsessionStorage から読み込みます。\n\n```html\n<button type=\"button\" *load.session=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load session\n</button>\n```\n\npersistent browser storage から読み込みます。\n\n```html\n<button type=\"button\" *load.store=\"'profile-draft'\" *keys=\"profile\" *into=\"draft\">\n  Load store\n</button>\n```\n\n#### merge rules\n\n- `*keys` も `*into` もない場合: 読み込んだ JSON object 全体を `_stage` または `_data` に `Object.assign` します。\n- `*keys` だけがある場合: 指定された top-level keys だけを `_stage` または `_data` に copy します。\n- `*into` がある場合: 読み込んだ全体、または `*keys` で選んだ値を、その property に入れます。\n- `*keys` が 1 個で `*into` がある場合: `json[key]` を `data[into]` に入れます。\n- `*keys` が複数で `*into` がある場合: 選択 key だけを持つ object を `data[into]` に入れます。\n\n#### 挙動\n\n- `*load.file` は file picker と `FileReader` を使います。\n- `*load.session` の値は `sessionStorage` key です。\n- `*load.store` の値は persistent browser storage key です。\n- `*load.store` は既定で IndexedDB database `sercrod-store` の object store `json` から JSON string を読みます。\n- key が存在しない場合、JSON parse に失敗した場合、IndexedDB が使えない場合は、warnings が有効なら警告を出し、data は変更しません。\n- 成功時は `sercrod-loaded` event を dispatch し、host を update します。\n\n#### event detail\n\n- `detail.stage`: file/legacy では `\"load\"`、session では `\"load.session\"`、store では `\"load.store\"`。\n- `detail.fileName`: file load の file name。\n- `detail.storage`: session/store load では `\"session\"` または `\"store\"`。\n- `detail.storageKey`: `*load.session` または `*load.store` の key。\n- `detail.into`: `*into` の destination、なければ `null`。\n- `detail.keys` / `detail.props`: `*keys` の list、なければ `null`。\n- `detail.json`: 読み込まれた JSON object。\n\n#### 互換性\n\n古い形式の `*load=\"profile settings\"` は互換用に残ります。この場合、値は旧式の key selection として扱われます。新しい例では `*load.file` / `*load.session` / `*load.store` と `*keys` / `*into` を使ってください。\n",
  "update": "### *update\n\n#### 概要\n\n`*update` は、現在の host または要素の update が終わったあと、指定した Sercrod host に強制 update を回す routing directive です。\n\nJavaScript expression は評価しません。属性値は literal な target spec として読み、対象 host が見つかった場合に runtime が次を呼びます。\n\n```js\ntarget.update(true, caller)\n```\n\naliases:\n\n- `*update`\n- `n-update`\n- `*updated-propagate`\n- `n-updated-propagate`\n\n`*updated-propagate` は互換用の古い名前です。新しい template では `*update` を使ってください。\n\n#### 基本例\n\nchild host から parent data を変更し、parent host を refresh します。\n\n```html\n<serc-rod id=\"parent\" data='{\"message\":\"parent_message\"}'>\n  <serc-rod data='{\"child_message\":\"hello\"}'>\n    <button\n      type=\"button\"\n      @click=\"$parent.message = child_message\"\n      *update=\"2\">\n      Send to parent\n    </button>\n  </serc-rod>\n\n  <p *print=\"message\"></p>\n</serc-rod>\n```\n\nこの button は child host の内側にあります。\n\n- `*update=\"1\"` は一番近い host、つまり child を更新します。\n- `*update=\"2\"` は次の外側の host、つまり parent を更新します。\n- parent が再描画されるため、`<p *print=\"message\">` が変更後の parent data を表示できます。\n\n#### 挙動\n\n`*update` は次の場所に書けます。\n\n- `<serc-rod *update=\"root\">` のような Sercrod host。\n- `<button *update=\"2\">` のような Sercrod host 内の ordinary element。\n\nSercrod host 上では、host の update が完了し、`*updated` / `n-updated` hook が実行されたあとに、`*update` の target を解決して `target.update(true, callerHost)` を呼びます。\n\nordinary element 上では、containing host の update 完了後、host が通常要素を scan します。同じ要素に `*updated` がある場合は先に実行し、そのあと `*update` の target を解決して `target.update(true, scanningHost)` を呼びます。\n\nこの directive は routing のみを行います。\n\n- 変数を作りません。\n- `$event` を公開しません。\n- `data`、`_stage`、`$root`、`$parent` を直接読み書きしません。\n- 属性値を expression として評価しません。\n\n#### target spec\n\n属性値は次の順で解釈されます。\n\n##### 空値\n\n値なしの `*update` は `\"1\"` として扱います。\n\n```html\n<button *update>Refresh nearest host</button>\n```\n\n##### parenthesized selector\n\n`\"(selector)\"` は closest matching Sercrod host を探します。\n\n```html\n<button *update=\"(#parent)\">Refresh #parent</button>\n<button *update=\"(.panel)\">Refresh nearest .panel host</button>\n```\n\nruntime は外側の parentheses を外し、composed tree で `closest(selector)` を行います。match した要素は Sercrod host である必要があります。\n\n##### root\n\n`\"root\"` は現在位置を含む一番外側の Sercrod host を更新します。\n\n```html\n<button *update=\"root\">Refresh root</button>\n```\n\nnested host や要素の update 後に、top-level UI container を再計算させたい場合に使います。\n\n##### numeric depth\n\n数字は Sercrod host だけを数えます。\n\n```html\n<button *update=\"1\">Refresh nearest host</button>\n<button *update=\"2\">Refresh parent host</button>\n```\n\n`div`、`p`、`button`、`span` などの通常要素は数えません。\n\nordinary element 上では、`\"1\"` は nearest containing Sercrod host、`\"2\"` は次の外側の Sercrod host です。\n\nSercrod host 自身の上では、`\"1\"` はその host 自身、`\"2\"` は parent Sercrod host です。\n\n##### bare selector\n\nそれ以外の値は CSS selector として扱い、composed-tree `closest(spec)` で解決します。\n\n```html\n<button *update=\".panel-root\">Refresh nearest .panel-root host</button>\n```\n\nselector であることを明確にしたい場合は `*update=\"(.panel-root)\"` のように parentheses を使う方が読みやすくなります。\n\n#### *updated との関係\n\n`*updated` と `*update` は役割が違います。\n\n- `*updated` は local post-render code を実行します。\n- `*update` は別の Sercrod host へ forced update を route します。\n\n同じ host または ordinary element に両方ある場合、`*updated` が先に実行され、そのあと `*update` が実行されます。\n\n#### error handling\n\ntarget が解決できない場合、update は行われません。\n\n例:\n\n- selector が不正。\n- selector が Sercrod host ではない要素に match した。\n- numeric depth が available ancestor chain より大きい。\n- `*update=\"targetName\"` のように data expression のつもりで書いたが、CSS selector として解釈された。\n\nruntime error は catch されます。warnings が有効なら警告を出し、処理を継続します。\n\n#### notes\n\n- 1 回の directive evaluation で更新される target host は 1 つだけです。\n- space や comma で複数 spec を並べる形式はありません。\n- 属性値は literal です。`*update=\"root\"` は keyword の root ですが、`*update=\"state.target\"` は CSS selector の `state.target` として扱われます。\n- 可能なら `root` または明示的な parenthesized selector を使ってください。\n- forced update は nested-host coordination には有用ですが、使いすぎると update cascade が重くなります。\n",
  "dominate": "### *dominate / n-dominate\n\n#### 概要\n\n`*dominate` は、`<serc-rod>` host に、自分自身の redraw timing の権限を持たせる host-level directive です。\n\ndata assignment、通常 event handling、input-driven update path のあとに起きる通常の automatic structural redraw を抑制します。initial connection での render は通常通り行われ、`*update`、`*apply`、`*restore`、直接の `el.update()` などの explicit redraw command は引き続き使えます。\n\n`*dominate` は freeze、static、noupdate ではありません。update method を dominate します。\n\n#### change は許可される\n\n`*dominate` 配下でも、登録済みの non-structural change command は default で実行されます。\n\nSercrod が変更された data key/path をすでに知っている場合、text output、attribute、class、style、form value binding などの登録済み DOM command へ、その既知の変更を route できます。その場合、host template を rebuild する必要はありません。\n\nこれは DOM diff ではありません。Sercrod は old DOM と new DOM を比較せず、DOM を検索して変更箇所を探しません。変更された location はすでに分かっています。\n\n#### structural behavior\n\n`*dominate` は、`*for`、`*each`、`*iterate`、`*if`、`*condition`、template cloning、insertion、removal、reorder の structural rendering model を変更しません。\n\n`*iterate=\"place\"` の placement sync は、suppressed automatic redraw の間でも動作できます。parent template を clear せず、既存 placement record を同期できます。\n\n#### Notes\n\n- 大きな outer host に redraw authority を持たせたい場合に `*dominate` を使います。\n- 独立して interactive な領域は child `<serc-rod>` に分けると、update flow の所有権が明確になります。\n- structural change を反映する必要がある場合は explicit update command を使います。\n- 古い `*dominant` / `n-dominant` spelling は compatibility alias として残っています。",
  "dominant": "### *dominant\n\n`*dominant` は [`*dominate`](#dominate) の compatibility alias です。新しい template では `*dominate` を使ってください。",
  "iterate": "# *iterate\n\nAliases: `*iterate`, `n-iterate`\nCategory: placement\n\n## 概要\n\n`*iterate=\"place\"` は、host が所有する配置 region を宣言します。data 配列を読み、parent host 全体を clear / rebuild せずに、その region 内の children を配列と同期します。\n\n基本形は native `<template>` anchor です。\n\n```html\n<serc-rod id=\"contents\" *dominate data=\"contents_data\">\n  <template\n    *let=\"place = { list: `items`, as: `item`, template: `content-template`, unit: `item.type` }\"\n    *iterate=\"place\">\n  </template>\n\n  <div *template=\"'content-template'\">\n    <section *unit=\"'content-a'\" class=\"content-a\">%item.title%</section>\n\n    <serc-rod *unit=\"'content-b'\" class=\"content-b\" data=\"item\">\n      <p>%title%</p>\n      <button @click=\"count++\">%count%</button>\n    </serc-rod>\n\n    <section *unit=\"'content-c'\" class=\"content-c\">%item.title%</section>\n  </div>\n</serc-rod>\n```\n\n`template` は、Sercrod の `*template` で登録された template source 名を指定します。DOM id ではありません。hyphen を含む名前は、たとえば `*template=\"'content-template'\"` のように string expression として書きます。\n\n`unit` は item ごとに評価されます。その結果が、template source の direct child にある `*unit` / `n-unit` の値と一致したものを使います。\n\n## place\n\n`place` は次の fields を持つ object です。\n\n- `list`: 現在の host data 内の array name または path。\n- `as`: 現在 item を表す local variable 名。\n- `template`: Sercrod `*template` で登録された template source 名。\n- `unit`: item ごとに評価される expression。その結果が表示 unit を選びます。\n\n各 item について、Sercrod は parent host data と `as` で指定された local name を含む scope で `unit` を評価します。\n\nCompatibility aliases:\n\n- `from` は `template` の alias として引き続き使えます。\n- `use` は `unit` の alias として引き続き使えます。\n\n新しい code では、place 側と template 側の対応が分かるように、`template` / `*template` と `unit` / `*unit` を使ってください。\n\n## Registered Template Source\n\nTemplate source は、placement sync より前に同じ Sercrod host から登録されます。candidate になるのは `*template` 要素の direct child elements だけです。grandchildren は candidate ではありません。\n\nCandidate selection は、評価された `unit` result と direct child の `*unit` / `n-unit` value を比較します。\n\n```html\n<div *template=\"'content-template'\">\n  <section *unit=\"'content-a'\" class=\"content-a\">%item.title%</section>\n  <section *unit=\"'content-c'\" class=\"content-c\">%item.title%</section>\n</div>\n```\n\n`unit` が `\"content-a\"` になった場合、`*unit=\"'content-a'\"` を持つ direct child が clone され、その item 用に render されます。\n\n互換のため、`*entry` / `n-entry` は `*unit` / `n-unit` の alias として引き続き使えます。`*unit`, `n-unit`, `*entry`, `n-entry` のどれにも一致しない場合は、古い class-name lookup に fallback します。新しい template では、style class と placement unit name を分離するために `*unit` を使ってください。\n\n## Scope\n\n通常の candidate elements は、parent host scope に local item variable を足した scope を使います。\n\n```html\n<section *unit=\"'content-a'\" class=\"content-a\">%item.title%</section>\n```\n\n`data` のない child `<serc-rod>` は、initial render 用に同じ local scope を受け取ります。\n\n`<serc-rod data=\"item\">` は parent placement logic によって扱われます。parent は local scope 内で `item` を評価し、その object を child host data root として渡します。\n\n```html\n<serc-rod *unit=\"'content-b'\" class=\"content-b\" data=\"item\">\n  <p>%title%</p>\n  <button @click=\"count++\">%count%</button>\n</serc-rod>\n```\n\nこの child host 内では、`%title%` と `%count%` は item object を参照します。\n\n## Staged item editing\n\niterate candidate 内の data-less child `<serc-rod *stage>` は、item を child host の data root にせず、現在の object item を stage できます。\n\n```html\n<div *template=\"'content-template'\">\n  <serc-rod *unit=\"'content-b'\" class=\"content-b\" *stage>\n    <input *input=\"item.title\">\n    <p>%item.title%</p>\n\n    <button type=\"button\" *apply>Apply</button>\n    <button type=\"button\" *restore>Restore</button>\n  </serc-rod>\n</div>\n```\n\nRules:\n\n- child host は `data` attribute を持たない必要があります。\n- `*stage` は空である必要があります。\n- child は `*iterate=\"place\"` の object item から生成されている必要があります。\n- `place.as` で指定された current item variable は、child host 内で staged item を指します。\n- `*apply` は staged item を元の item object に merge します。\n- `*restore` はその staged item だけを reset します。\n- string や number などの primitive items は staged item editing の対象外で、warn します。\n\n## Identity And Placement\n\n`*iterate=\"place\"` は高速な `*for` ではありません。`*for` は render 中に1つの template を繰り返します。`*iterate=\"place\"` は placement region を所有し、現在の browser run 内で item-to-DOM records を保持します。\n\nRules:\n\n- Array order が source of truth です。\n- `id`, `key`, `*keys` は placement には使われません。\n- 同じ item object は、移動しても同じ DOM record を保持します。\n- 新しい item object は新しい item として扱われます。\n- 同じ item の `unit` result が変わった場合、古い DOM は削除され、新しい candidate がその位置に挿入されます。\n- 削除された items は通常の Sercrod removal path で cleanup されます。\n\n## With *dominate\n\n`*dominate` は parent host の automatic full redraw を抑制しますが、placement sync は抑制しません。dominate host の automatic update では、Sercrod は parent template を clear / rebuild する代わりに、registered iterate regions を同期します。\n\nこれにより、大きな parent host を安定させたまま、item children の追加、削除、移動、置換、局所更新を扱えます。\n\n## Warnings\n\nMissing template sources、missing candidates、duplicate candidate unit names、invalid `place` objects、non-`template` anchors は `[Sercrod warn]` で警告し、可能な範囲で処理を続けます。\n",
  "unit": "# *unit\n\nAliases: `*unit`, `n-unit`\nCategory: placement unit\n\n## 概要\n\n`*unit` は、`*iterate` が使う `*template` source の direct child に、選択可能な表示 unit 名を宣言します。\n\n`*iterate` は item ごとに place object の `unit` expression を評価します。その結果が、template source の direct child にある `*unit` / `n-unit` value と一致した場合、その child が clone され、その item 用に render されます。\n\n`*unit` は item identity key ではありません。object item identity と primitive item matching は、`*iterate` の placement records が扱います。\n\n## Example\n\n```html\n<template *iterate=\"place\" *let=\"place = { list: 'items', as: 'item', template: 'item-tpl', unit: 'item.type' }\"></template>\n\n<template *template=\"'item-tpl'\">\n  <section *unit=\"'text'\" class=\"text-item\">%item.title%</section>\n  <section *unit=\"'image'\" class=\"image-item\">%item.title%</section>\n</template>\n```\n\n`item.type` が `\"text\"` になる場合、Sercrod は `*unit` value が `\"text\"` の direct child を使います。\n\n## Compatibility\n\n`*entry` / `n-entry` は、`*unit` / `n-unit` の compatibility alias として引き続き使えます。\n\n互換のため、`*unit`, `n-unit`, `*entry`, `n-entry` のどれにも一致しない場合、`*iterate` は古い class-name candidate lookup に fallback できます。\n\n## Notes\n\n- `*unit` は、`*iterate` に消費される template source 内の direct candidate marker としてだけ意味を持ちます。\n- 新しい template では、candidate selection に CSS class name ではなく `*unit` を使ってください。\n- iterate 側では place `unit`、template 側では `*unit` を使います。\n",
  "entry": "# *entry\n\nAliases: `*entry`, `n-entry`\nCategory: compatibility alias\n\n## 概要\n\n`*entry` は、`*iterate` が使う `*template` source 内での `*unit` の compatibility alias です。\n\n新しい template では `*unit` / `n-unit` を使ってください。既存の `*entry` / `n-entry` template は引き続き動作します。\n\n## Example\n\n```html\n<template *iterate=\"place\" *let=\"place = { list: 'items', as: 'item', template: 'item-tpl', unit: 'item.type' }\"></template>\n\n<template *template=\"'item-tpl'\">\n  <section *entry=\"'text'\" class=\"text-item\">%item.title%</section>\n</template>\n```\n\nこれは次と同じ意味です。\n\n```html\n<section *unit=\"'text'\" class=\"text-item\">%item.title%</section>\n```\n",
  "adapters": "### Adapters\n\n#### 概要\n\nruntime capability adapter は、明示的な Sercrod または app action を外部 capability へ接続します。Sercrod core は host data、directive evaluation、update routing、DOM rendering を所有します。browser API、Capacitor bridge、project bridge、build tool は core の外側に置きます。\n\n#### 配置\n\n通常の runtime capability adapter は `dist/adapters/` 直下に置きます。\n\n- `filesystem.js`\n- `navigation.js`\n- `camera.js`\n- `clipboard.js`\n- `media-playback.js`\n- `audio-capture.js`\n- `geolocation.js`\n\n通常 capability のために `dist/adapters/browser/` や `dist/adapters/capacitor/` の分割を増やしません。`dist/adapters/playwright/` は別の build support です。\n\n#### Registry\n\n```js\nSercrod.set_adapter(\"sercrod.filesystem\", adapter);\nSercrod.use_adapter(\"file\", \"sercrod.filesystem\");\nSercrod._get_adapter(\"file\");\n```\n\nadapter は `window.__Sercrod.adapters` にも公開され、default role mapping は `window.__Sercrod.adapter_map` に置かれます。\n\n#### capability boundary\n\n- `sercrod.filesystem`: JSON/file/asset persistence。upload は行いません。\n- `sercrod.navigation.browser`: 明示的な `*navigate` と一致する `*page` activation。route table や global link interceptor ではありません。\n- `sercrod.camera`: image capture/selection のみ。save/upload は行いません。\n- `sercrod.clipboard`: user action による clipboard text read/write。\n- `sercrod.media_playback`: 既存の native `<audio>` / `<video>` を制御します。browser policy block では shared playback dialog を使えます。\n- `sercrod.audio_capture`: `getUserMedia()` と `MediaRecorder` による microphone recording。Blob/File/Object URL metadata を返します。playback、save、upload、transcription、mixing、background recording は行いません。\n- `sercrod.geolocation`: foreground の current position、position watch/clear、permission status/request、status、diagnostics を提供します。project bridge、Capacitor Geolocation、browser Geolocation API を内部で選び、accuracy を含む共通形式の coordinates を返します。\n\ngeolocation は background tracking、map UI、住所/geocoding lookup、IP estimation、route history、persistence、upload を所有しません。単発の current position は device の精度が改善する前に速く返る場合があります。より正確な位置を継続的に受け取りたい app は position watch を使い、不要になったら明示的に clear します。`coords.accuracy` は値が小さいほど高精度です。\n\napp は adapter と UI を明示的に組み合わせます。たとえば audio capture result を native `<audio>` で preview したり、geolocation coordinates を Leaflet/OpenStreetMap で表示したりできます。playback と map は adapter ではなく app layer の責務です。\n\n#### app sandbox\n\nすべての `sandbox/app/<app>/` は `app.json` を持ちます。`capacitor.plugins` が native package の正本で、Android-only permission は `capacitor.android.permissions` に書けます。geolocation app は `@capacitor/geolocation` と `ACCESS_COARSE_LOCATION` / `ACCESS_FINE_LOCATION` を宣言します。各 app の `www/` は absolute `sercrod.js` / `adapters` symlink を持ちます。Windows `build.bat` は選択前に shared app root 全体を同期し、安全に自己更新し、`app.json` を持つ folder だけを表示し、plugin install、Android permission 反映、Capacitor sync、build を行います。\n"
}
