draft-ole 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +134 -0
  3. package/README.md +128 -0
  4. package/dist/chunk-5BNNDTRT.js +95 -0
  5. package/dist/chunk-5BNNDTRT.js.map +1 -0
  6. package/dist/chunk-STLTIBMA.js +7658 -0
  7. package/dist/chunk-STLTIBMA.js.map +1 -0
  8. package/dist/chunk-YK4Y4ENL.js +389 -0
  9. package/dist/chunk-YK4Y4ENL.js.map +1 -0
  10. package/dist/entries/app.cjs +7337 -0
  11. package/dist/entries/app.cjs.map +1 -0
  12. package/dist/entries/app.d.cts +115 -0
  13. package/dist/entries/app.d.ts +115 -0
  14. package/dist/entries/app.js +10 -0
  15. package/dist/entries/app.js.map +1 -0
  16. package/dist/entries/page.cjs +7558 -0
  17. package/dist/entries/page.cjs.map +1 -0
  18. package/dist/entries/page.d.cts +2 -0
  19. package/dist/entries/page.d.ts +2 -0
  20. package/dist/entries/page.js +30 -0
  21. package/dist/entries/page.js.map +1 -0
  22. package/dist/index.cjs +10524 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +4700 -0
  25. package/dist/index.d.ts +4700 -0
  26. package/dist/index.js +2573 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/page-DylNkWXm.d.ts +366 -0
  29. package/dist/page-h3DPzs8l.d.cts +366 -0
  30. package/dist/transformer/call-detector.d.ts +38 -0
  31. package/dist/transformer/call-detector.d.ts.map +1 -0
  32. package/dist/transformer/call-detector.js +151 -0
  33. package/dist/transformer/call-detector.js.map +1 -0
  34. package/dist/transformer/command-injector.d.ts +27 -0
  35. package/dist/transformer/command-injector.d.ts.map +1 -0
  36. package/dist/transformer/command-injector.js +111 -0
  37. package/dist/transformer/command-injector.js.map +1 -0
  38. package/dist/transformer/diagnostic-reporter.d.ts +81 -0
  39. package/dist/transformer/diagnostic-reporter.d.ts.map +1 -0
  40. package/dist/transformer/diagnostic-reporter.js +330 -0
  41. package/dist/transformer/diagnostic-reporter.js.map +1 -0
  42. package/dist/transformer/each-scope-branch.d.ts +28 -0
  43. package/dist/transformer/each-scope-branch.d.ts.map +1 -0
  44. package/dist/transformer/each-scope-branch.js +95 -0
  45. package/dist/transformer/each-scope-branch.js.map +1 -0
  46. package/dist/transformer/each-state-rewriter.d.ts +117 -0
  47. package/dist/transformer/each-state-rewriter.d.ts.map +1 -0
  48. package/dist/transformer/each-state-rewriter.js +393 -0
  49. package/dist/transformer/each-state-rewriter.js.map +1 -0
  50. package/dist/transformer/format-diagnostics.d.ts +27 -0
  51. package/dist/transformer/format-diagnostics.d.ts.map +1 -0
  52. package/dist/transformer/format-diagnostics.js +50 -0
  53. package/dist/transformer/format-diagnostics.js.map +1 -0
  54. package/dist/transformer/handler-ir-extractor.d.ts +71 -0
  55. package/dist/transformer/handler-ir-extractor.d.ts.map +1 -0
  56. package/dist/transformer/handler-ir-extractor.js +171 -0
  57. package/dist/transformer/handler-ir-extractor.js.map +1 -0
  58. package/dist/transformer/handler-serializer.d.ts +56 -0
  59. package/dist/transformer/handler-serializer.d.ts.map +1 -0
  60. package/dist/transformer/handler-serializer.js +315 -0
  61. package/dist/transformer/handler-serializer.js.map +1 -0
  62. package/dist/transformer/helper-context-resolver.d.ts +180 -0
  63. package/dist/transformer/helper-context-resolver.d.ts.map +1 -0
  64. package/dist/transformer/helper-context-resolver.js +376 -0
  65. package/dist/transformer/helper-context-resolver.js.map +1 -0
  66. package/dist/transformer/helper-decl-utils.d.ts +28 -0
  67. package/dist/transformer/helper-decl-utils.d.ts.map +1 -0
  68. package/dist/transformer/helper-decl-utils.js +92 -0
  69. package/dist/transformer/helper-decl-utils.js.map +1 -0
  70. package/dist/transformer/identifier-collector.d.ts +28 -0
  71. package/dist/transformer/identifier-collector.d.ts.map +1 -0
  72. package/dist/transformer/identifier-collector.js +184 -0
  73. package/dist/transformer/identifier-collector.js.map +1 -0
  74. package/dist/transformer/index.d.ts +56 -0
  75. package/dist/transformer/index.d.ts.map +1 -0
  76. package/dist/transformer/index.js +333 -0
  77. package/dist/transformer/index.js.map +1 -0
  78. package/dist/transformer/inline-recovery.d.ts +109 -0
  79. package/dist/transformer/inline-recovery.d.ts.map +1 -0
  80. package/dist/transformer/inline-recovery.js +369 -0
  81. package/dist/transformer/inline-recovery.js.map +1 -0
  82. package/dist/transformer/label-injector.d.ts +105 -0
  83. package/dist/transformer/label-injector.d.ts.map +1 -0
  84. package/dist/transformer/label-injector.js +221 -0
  85. package/dist/transformer/label-injector.js.map +1 -0
  86. package/dist/transformer/package.json +3 -0
  87. package/dist/transformer/per-call-context.d.ts +95 -0
  88. package/dist/transformer/per-call-context.d.ts.map +1 -0
  89. package/dist/transformer/per-call-context.js +3 -0
  90. package/dist/transformer/per-call-context.js.map +1 -0
  91. package/dist/transformer/state-id-fallback.d.ts +85 -0
  92. package/dist/transformer/state-id-fallback.d.ts.map +1 -0
  93. package/dist/transformer/state-id-fallback.js +132 -0
  94. package/dist/transformer/state-id-fallback.js.map +1 -0
  95. package/dist/transformer/state-id-resolver.d.ts +104 -0
  96. package/dist/transformer/state-id-resolver.d.ts.map +1 -0
  97. package/dist/transformer/state-id-resolver.js +222 -0
  98. package/dist/transformer/state-id-resolver.js.map +1 -0
  99. package/dist/transformer/theme-class-detector.d.ts +47 -0
  100. package/dist/transformer/theme-class-detector.d.ts.map +1 -0
  101. package/dist/transformer/theme-class-detector.js +242 -0
  102. package/dist/transformer/theme-class-detector.js.map +1 -0
  103. package/dist/transformer/varname-resolver.d.ts +53 -0
  104. package/dist/transformer/varname-resolver.d.ts.map +1 -0
  105. package/dist/transformer/varname-resolver.js +231 -0
  106. package/dist/transformer/varname-resolver.js.map +1 -0
  107. package/dist/transformer/whitelist-registry.d.ts +68 -0
  108. package/dist/transformer/whitelist-registry.d.ts.map +1 -0
  109. package/dist/transformer/whitelist-registry.js +122 -0
  110. package/dist/transformer/whitelist-registry.js.map +1 -0
  111. package/dist/transformer/whitelist-validator.d.ts +59 -0
  112. package/dist/transformer/whitelist-validator.d.ts.map +1 -0
  113. package/dist/transformer/whitelist-validator.js +493 -0
  114. package/dist/transformer/whitelist-validator.js.map +1 -0
  115. package/dist/types-BXV3vhHS.d.cts +4590 -0
  116. package/dist/types-BXV3vhHS.d.ts +4590 -0
  117. package/package.json +121 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 object-zaseeta
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ja.md ADDED
@@ -0,0 +1,134 @@
1
+ # DraftOle
2
+
3
+ 静的ページのための TypeScript 製 View DSL。LP・ドキュメント・記事・レポートを 1 本の型安全な TypeScript プログラムとして記述する。`page first, App later` を方針とする。
4
+
5
+ > **現在のフェーズ:** DraftOle は *static page first* の View DSL です。`page()` と最小の View プリミティブ(`Page` / `Section` / `VStack` / `HStack` / `Text` ほか)でページを組み、HTML / CSS を生成します。インタラクティブなランタイム(`App`)は今フェーズでは意図的に二次的に位置づけています。詳しくは [docs/positioning.md](docs/positioning.md) を参照してください。
6
+
7
+ ## 特徴
8
+
9
+ - **page-first な View DSL** — `page()` + `Page` / `Section` / `VStack` / `HStack` / `Text` で静的ページを直接表現
10
+ - **modifier 主導のスタイリング** — `.padding()` / `.background()` / `.foregroundStyle()` / `.font()` / `.frame()` / `.cornerRadius()` を View ノード単位で適用
11
+ - **型安全な HTML 生成** — TypeScript ソースから出力まで完全に型チェック
12
+ - **既定でゼロランタイム** — `page()` は素の HTML / CSS のみを書き出し、`runtime.js` を生成しない
13
+ - **プロダクション依存ゼロ**
14
+
15
+ ## インストール
16
+
17
+ > ⚠️ まだ npm に公開していません。現時点ではソースから導入してください:
18
+
19
+ ```bash
20
+ git clone https://github.com/object-zaseeta/DraftOle.git
21
+ cd DraftOle
22
+ pnpm install
23
+ pnpm build
24
+ ```
25
+
26
+ 自分のプロジェクトからリンクする場合:
27
+
28
+ ```bash
29
+ # 自分のプロジェクト側で
30
+ pnpm link --global <DraftOleへのパス>
31
+ ```
32
+
33
+ ## クイックスタート
34
+
35
+ **1. スクリプトを作成**(例: `build-page.ts`):
36
+
37
+ ```typescript
38
+ import { page, Page, Section, VStack, Text } from 'draft-ole';
39
+
40
+ const hero = Section(
41
+ VStack({ spacing: 16 },
42
+ Text('Hello, DraftOle!')
43
+ .font({ size: '2rem', weight: '700' })
44
+ .foregroundStyle('#1a1a2e'),
45
+ Text('静的ページのための View DSL.')
46
+ .font({ size: '1.125rem' })
47
+ .foregroundStyle('#4a4a6a'),
48
+ )
49
+ .padding(48)
50
+ .frame({ maxWidth: 720 }),
51
+ )
52
+ .background('#f8f9ff');
53
+
54
+ const doc = page(
55
+ Page(hero),
56
+ {
57
+ lang: 'ja',
58
+ title: 'Hello, DraftOle',
59
+ },
60
+ );
61
+
62
+ console.log(doc.render());
63
+ ```
64
+
65
+ **2. 実行:**
66
+
67
+ ```bash
68
+ node --experimental-strip-types build-page.ts
69
+ ```
70
+
71
+ これで完全な静的 HTML ドキュメントが標準出力されます。`index.html` / `style.css` をディレクトリに書き出すには `doc.export('./dist')` を使ってください。
72
+
73
+ より長い動作例は [`examples/page-minimal.ts`](examples/page-minimal.ts)(hero + features 構成)と [`examples/page-landing.ts`](examples/page-landing.ts)(複数セクション LP)を参照してください。
74
+
75
+ ## コアコンセプト
76
+
77
+ | 概念 | 説明 |
78
+ |---|---|
79
+ | **`page(view, meta?)`** | 入口。`Page` View にドキュメントメタ情報(lang / title / charset / viewport / description)を付与し、`PageDocument` を返す。 |
80
+ | **`Page`, `Section`** | ページ構造の上位 View。`Page` はルート View、`Section` は意味のあるブロック。 |
81
+ | **`VStack`, `HStack`** | 縦方向 / 横方向のレイアウト View。`spacing` オプションあり。 |
82
+ | **`Text`** | テキスト View。文字コンテンツのリーフプリミティブ。 |
83
+ | **modifier** | `.padding()` / `.background()` / `.foregroundStyle()` / `.font({ size, weight, ... })` / `.frame({ maxWidth, ... })` / `.cornerRadius()` — View ノード単位の scoped スタイリング。 |
84
+ | **`PageDocument`** | `page()` の戻り値。`.render()` で HTML 文字列を取得、`.export(dir)` で `index.html` / `style.css` を書き出す。 |
85
+
86
+ ## サンプル
87
+
88
+ [`examples/`](examples/) に整理済みの読み順を用意しています。推奨の読み順:
89
+
90
+ 1. [`examples/page-minimal.ts`](examples/page-minimal.ts) — `page()` の最小例
91
+ 2. [`examples/page-landing.ts`](examples/page-landing.ts) — View modifier だけで組む複数セクション LP
92
+ 3. `examples/showcase-card.ts` / `showcase-button.ts` / `showcase-list.ts` — レイアウト / modifier ショーケース
93
+ 4. [`examples/interactive/mvp-demo.ts`](examples/interactive/mvp-demo.ts) — *advanced / interactive* な発展例(埋め込み JS の Todo アプリ)
94
+
95
+ 完全な読み順は [`examples/README.md`](examples/README.md) に記載しています。
96
+
97
+ ## スクリプト
98
+
99
+ ```bash
100
+ pnpm build # dist/ にコンパイル (ESM + CJS + .d.ts)
101
+ pnpm test # Vitest テスト実行
102
+ pnpm lint # ESLint
103
+ pnpm typecheck # tsc --noEmit
104
+ pnpm demo:mvp # MVP デモ実行 → .out/runs/mvp_demo/
105
+ ```
106
+
107
+ ## 想定ユースケース(現フェーズ)
108
+
109
+ `page first` は **静的ページ** を想定しています:
110
+
111
+ - ランディングページ(LP)
112
+ - ドキュメントページ
113
+ - 記事・長文レポート
114
+ - 静的なダッシュボード / ステータスページ
115
+
116
+ インタラクティブなランタイム(`App`、jQuery 風スクリプト、埋め込み JS)は引き続き利用可能ですが、本フェーズの主導線ではありません。主対象と現在の non-goals は [docs/positioning.md](docs/positioning.md) を参照してください。
117
+
118
+ ## Advanced / 互換目的
119
+
120
+ 旧来の `Root` + `html/body/div` + `FileExporter` API は後方互換および高度な利用のために残されていますが、新規利用の出発点としては推奨されません。新しいコードは `page()` から始めてください。該当パスは `examples/interactive/mvp-demo.ts` および `src/html/` 配下を参照してください。
121
+
122
+ ## 技術スタック
123
+
124
+ | 項目 | 選択 |
125
+ |------|------|
126
+ | 言語 | TypeScript 5.x (strict mode) |
127
+ | ランタイム | Node.js 18+ |
128
+ | ビルド | tsup (esbuildベース) |
129
+ | テスト | Vitest |
130
+ | 出力形式 | ESM + CJS + .d.ts |
131
+
132
+ ## ライセンス
133
+
134
+ MIT
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # DraftOle
2
+
3
+ A View DSL for static pages in TypeScript. Build LPs, docs, articles and reports as a single, fully type-checked TypeScript program — `page first, App later`.
4
+
5
+ > **What this is now:** DraftOle is a *static page first* View DSL. You compose pages with `page()` and a small set of View primitives (`Page`, `Section`, `VStack`, `HStack`, `Text`, ...), and DraftOle emits the HTML/CSS for you. Interactive runtime (`App`) is intentionally a secondary story for this phase — see [docs/positioning.md](docs/positioning.md).
6
+
7
+ ## Features
8
+
9
+ - **Page-first View DSL** — `page()` + `Page` / `Section` / `VStack` / `HStack` / `Text` express a static page directly
10
+ - **Modifier-driven styling** — `.padding()`, `.background()`, `.foregroundStyle()`, `.font()`, `.frame()`, `.cornerRadius()` produce scoped CSS per node
11
+ - **Type-safe HTML generation** — full TypeScript type checking from source to output
12
+ - **Zero runtime by default** — `page()` writes plain HTML/CSS, no `runtime.js` is generated
13
+ - **Zero production dependencies**
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install draft-ole
19
+ # or
20
+ pnpm add draft-ole
21
+ # or
22
+ yarn add draft-ole
23
+ ```
24
+
25
+ > 🧪 **0.9.0 (pre-1.0)** — public API は概ね固まっていますが、1.0 に向けて feedback を集めているフェーズです。Issues / Discussions 歓迎です。
26
+
27
+ ## Quick Start
28
+
29
+ **1. Create a script** (e.g. `build-page.ts`):
30
+
31
+ ```typescript
32
+ import { page, Page, Section, VStack, Text } from 'draft-ole';
33
+
34
+ const hero = Section(
35
+ VStack({ spacing: 16 },
36
+ Text('Hello, DraftOle!')
37
+ .font({ size: '2rem', weight: '700' })
38
+ .foregroundStyle('#1a1a2e'),
39
+ Text('A View DSL for static pages.')
40
+ .font({ size: '1.125rem' })
41
+ .foregroundStyle('#4a4a6a'),
42
+ )
43
+ .padding(48)
44
+ .frame({ maxWidth: 720 }),
45
+ )
46
+ .background('#f8f9ff');
47
+
48
+ const doc = page(
49
+ Page(hero),
50
+ {
51
+ lang: 'en',
52
+ title: 'Hello, DraftOle',
53
+ },
54
+ );
55
+
56
+ console.log(doc.render());
57
+ ```
58
+
59
+ **2. Run it:**
60
+
61
+ ```bash
62
+ node --experimental-strip-types build-page.ts
63
+ ```
64
+
65
+ This prints a complete static HTML document. To write `index.html` / `style.css` to a directory, use `doc.export('./dist')`.
66
+
67
+ For a longer working example see [`examples/page-minimal.ts`](examples/page-minimal.ts) (a hero + features section) and [`examples/page-landing.ts`](examples/page-landing.ts) (a multi-section LP).
68
+
69
+ ## Core Concepts
70
+
71
+ | Concept | Description |
72
+ |---|---|
73
+ | **`page(view, meta?)`** | Entry point. Wraps a `Page` view with document metadata (lang / title / charset / viewport / description) and returns a `PageDocument`. |
74
+ | **`Page`, `Section`** | Top-level structural views. `Page` is the root view, `Section` is a semantic block inside a page. |
75
+ | **`VStack`, `HStack`** | Vertical / horizontal layout primitives with `spacing` option. |
76
+ | **`Text`** | Text view, the leaf primitive for written content. |
77
+ | **Modifiers** | `.padding()`, `.background()`, `.foregroundStyle()`, `.font({ size, weight, ... })`, `.frame({ maxWidth, ... })`, `.cornerRadius()` — scoped, per-view styling. |
78
+ | **`PageDocument`** | The result of `page()`. Use `.render()` to get the HTML string, or `.export(dir)` to write `index.html` / `style.css`. |
79
+
80
+ ## Examples
81
+
82
+ See [`examples/`](examples/) for the curated read-order. Recommended path:
83
+
84
+ 1. [`examples/page-minimal.ts`](examples/page-minimal.ts) — minimum `page()` example
85
+ 2. [`examples/page-landing.ts`](examples/page-landing.ts) — multi-section LP using only View modifiers
86
+ 3. `examples/showcase-card.ts` / `showcase-button.ts` / `showcase-list.ts` — layout / modifier showcases
87
+ 4. [`examples/interactive/mvp-demo.ts`](examples/interactive/mvp-demo.ts) — *advanced / interactive* example (Todo app with embedded JS)
88
+
89
+ The full read order is documented in [`examples/README.md`](examples/README.md).
90
+
91
+ ## Scripts
92
+
93
+ ```bash
94
+ pnpm build # Compile to dist/ (ESM + CJS + .d.ts)
95
+ pnpm test # Run Vitest suite
96
+ pnpm lint # ESLint
97
+ pnpm typecheck # tsc --noEmit
98
+ pnpm demo:mvp # Run the MVP demo → .out/runs/mvp_demo/
99
+ ```
100
+
101
+ ## Use Cases (current phase)
102
+
103
+ `page first` is positioned for **static pages**:
104
+
105
+ - Landing pages
106
+ - Documentation pages
107
+ - Articles and long-form reports
108
+ - Static dashboards / status pages
109
+
110
+ Interactive runtime (`App`, jQuery-style scripts, embedded JS) remains available as advanced material but is *not* the primary path for this phase. See [docs/positioning.md](docs/positioning.md) for primary use cases and current non-goals.
111
+
112
+ ## Advanced / Compatibility
113
+
114
+ The legacy `Root` + `html/body/div` + `FileExporter` API is still present for back-compatibility and advanced use cases. It is **not** the recommended starting point for new users; new code should start from `page()`. See `examples/interactive/mvp-demo.ts` and the source under `src/html/` for that path.
115
+
116
+ ## Tech Stack
117
+
118
+ | Item | Choice |
119
+ |------|--------|
120
+ | Language | TypeScript 5.x (strict mode) |
121
+ | Runtime | Node.js 18+ |
122
+ | Build | tsup (esbuild-based) |
123
+ | Test | Vitest |
124
+ | Output | ESM + CJS + .d.ts |
125
+
126
+ ## License
127
+
128
+ MIT
@@ -0,0 +1,95 @@
1
+ import {
2
+ FileExporter,
3
+ Root,
4
+ body,
5
+ head,
6
+ html,
7
+ meta,
8
+ title
9
+ } from "./chunk-STLTIBMA.js";
10
+
11
+ // src/app/app-document.ts
12
+ var AppDocument = class {
13
+ _root;
14
+ _bodyEl;
15
+ _options;
16
+ _exported = false;
17
+ /** @internal `app()` ファクトリからのみ生成される */
18
+ constructor(root, bodyEl, options) {
19
+ this._root = root;
20
+ this._bodyEl = bodyEl;
21
+ this._options = options;
22
+ }
23
+ /**
24
+ * Req 2.1: リアクティブ state を生成する。
25
+ * `Root.runtimeContext.state()` へ委譲するため、生成された State は
26
+ * 同一ドキュメントの event handler / binding と同じ StateRegistry を参照する。
27
+ */
28
+ state(initialValue) {
29
+ return this._root.state(initialValue);
30
+ }
31
+ /**
32
+ * Req 3.1, 3.2, 3.3: content を `<body>` 直下に append し HTML/CSS/JS を出力する。
33
+ *
34
+ * - `<main>` で包まない(SPA 用途のためユーザーの view ツリーをそのまま body 直下に配置)
35
+ * - `wrapDOMReady: true` のとき生成 JS を `DOMContentLoaded` でラップする
36
+ * - 書き込み不可パスでは `ExportableError('invalidPath')` が透過する
37
+ *
38
+ * @throws {Error} 同一 AppDocument で 2 回目以降の呼び出し時
39
+ * @throws {ExportableError} outputPath が無効または書き込み失敗時
40
+ */
41
+ exportTo(content, outputPath) {
42
+ if (this._exported) {
43
+ throw new Error(
44
+ "AppDocument.exportTo can only be called once. Create a new app() instance to export again."
45
+ );
46
+ }
47
+ const views = Array.isArray(content) ? content : [content];
48
+ for (const view of views) {
49
+ this._bodyEl.addChild(view);
50
+ this._root.flushDescendants(view);
51
+ }
52
+ new FileExporter({ wrapDOMReady: this._options.wrapDOMReady ?? false }).exportFromRoot(
53
+ this._root,
54
+ outputPath
55
+ );
56
+ this._exported = true;
57
+ }
58
+ };
59
+
60
+ // src/app/build-document-skeleton.ts
61
+ function buildDocumentSkeleton(root, options) {
62
+ root.setDoctype(true);
63
+ const charsetMeta = meta({ charset: options.charset ?? "UTF-8" });
64
+ const viewportMeta = options.viewport !== void 0 ? meta({ name: "viewport", content: options.viewport }) : void 0;
65
+ const descriptionMeta = options.description !== void 0 ? meta({ name: "description", content: options.description }) : void 0;
66
+ const titleEl = title(options.title ?? "");
67
+ const metaList = [charsetMeta, viewportMeta, descriptionMeta, titleEl].filter(
68
+ (el) => el !== void 0
69
+ );
70
+ const headEl = head(...metaList);
71
+ const bodyEl = body();
72
+ const htmlEl = options.lang !== void 0 ? html({ lang: options.lang }, headEl, bodyEl) : html(headEl, bodyEl);
73
+ root.addChild(htmlEl);
74
+ return { bodyEl };
75
+ }
76
+
77
+ // src/app/app.ts
78
+ function app(options) {
79
+ const resolvedOptions = {
80
+ charset: "UTF-8",
81
+ lang: "en",
82
+ ...options
83
+ };
84
+ const { css } = resolvedOptions;
85
+ const cssArray = css === void 0 ? [] : Array.isArray(css) ? css : [css];
86
+ const root = new Root({ css: cssArray, cssConfig: resolvedOptions.cssConfig });
87
+ const { bodyEl } = buildDocumentSkeleton(root, resolvedOptions);
88
+ return new AppDocument(root, bodyEl, resolvedOptions);
89
+ }
90
+
91
+ export {
92
+ AppDocument,
93
+ app
94
+ };
95
+ //# sourceMappingURL=chunk-5BNNDTRT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/app/app-document.ts","../src/app/build-document-skeleton.ts","../src/app/app.ts"],"sourcesContent":["import type { HtmlTag } from '../html/elements/html-tag.js';\nimport type { Root } from '../html/elements/root.js';\nimport type { HTMLTagProtocol } from '../html/protocols/html-tag-protocol.js';\nimport type { State } from '../js/vanilla/state/state.js';\nimport { FileExporter } from '../publisher/file-exporter.js';\nimport type { AppContext } from './app.js';\nimport type { AppOptions } from './app-options.js';\n\n/**\n * `app()` ファクトリが返す対話型アプリのファサードオブジェクト。\n *\n * - `state<T>()`: `Root.runtimeContext.state<T>()` に委譲\n * - `exportTo()`: ユーザー content を `<body>` 直下に append し `FileExporter` 経由で出力\n *\n * **再 export 制限**: `exportTo()` は 1 インスタンスにつき 1 回のみ。\n * 2 回目以降は `Error` を throw する。\n *\n * Requirements: 1.3, 2.1, 2.2, 2.3, 3.1, 3.2, 3.3, 4.3\n * Boundary: src/app/app-document.ts\n */\n\n/** `exportTo()` に渡せるビュー要素の型 */\nexport type AppView = HtmlTag;\n\nexport class AppDocument implements AppContext {\n private readonly _root: Root;\n private readonly _bodyEl: HtmlTag;\n private readonly _options: AppOptions;\n private _exported = false;\n\n /** @internal `app()` ファクトリからのみ生成される */\n constructor(root: Root, bodyEl: HtmlTag, options: AppOptions) {\n this._root = root;\n this._bodyEl = bodyEl;\n this._options = options;\n }\n\n /**\n * Req 2.1: リアクティブ state を生成する。\n * `Root.runtimeContext.state()` へ委譲するため、生成された State は\n * 同一ドキュメントの event handler / binding と同じ StateRegistry を参照する。\n */\n state<T>(initialValue: T): State<T> {\n return this._root.state(initialValue);\n }\n\n /**\n * Req 3.1, 3.2, 3.3: content を `<body>` 直下に append し HTML/CSS/JS を出力する。\n *\n * - `<main>` で包まない(SPA 用途のためユーザーの view ツリーをそのまま body 直下に配置)\n * - `wrapDOMReady: true` のとき生成 JS を `DOMContentLoaded` でラップする\n * - 書き込み不可パスでは `ExportableError('invalidPath')` が透過する\n *\n * @throws {Error} 同一 AppDocument で 2 回目以降の呼び出し時\n * @throws {ExportableError} outputPath が無効または書き込み失敗時\n */\n exportTo(content: AppView | readonly AppView[], outputPath: string): void {\n if (this._exported) {\n throw new Error(\n 'AppDocument.exportTo can only be called once. Create a new app() instance to export again.',\n );\n }\n\n const views = Array.isArray(content) ? content : [content];\n for (const view of views) {\n this._bodyEl.addChild(view as unknown as HTMLTagProtocol);\n this._root.flushDescendants(view as unknown as HTMLTagProtocol);\n }\n\n new FileExporter({ wrapDOMReady: this._options.wrapDOMReady ?? false }).exportFromRoot(\n this._root,\n outputPath,\n );\n\n this._exported = true;\n }\n}\n","import type { Root } from '../html/elements/root.js';\nimport type { HtmlTag } from '../html/elements/html-tag.js';\nimport { body, head, html, meta, title } from '../html/tags/index.js';\nimport type { PageOptions } from '../view/types.js';\n\n/**\n * `Root` に html/head/(meta×N + title)/body を組み立てる純関数ヘルパー。\n *\n * - `body` は **空のまま** 返す(`app()` 用途は SPA なので `<main>` で包まない)\n * - `page()` の DOM 構築ロジックと同等の meta 生成を行う\n *\n * Requirements: 1.4, 3.4\n * Boundary: src/app/build-document-skeleton.ts\n */\nexport function buildDocumentSkeleton(\n root: Root,\n options: PageOptions,\n): { bodyEl: HtmlTag } {\n root.setDoctype(true);\n\n const charsetMeta = meta({ charset: options.charset ?? 'UTF-8' });\n\n const viewportMeta =\n options.viewport !== undefined\n ? meta({ name: 'viewport', content: options.viewport })\n : undefined;\n\n const descriptionMeta =\n options.description !== undefined\n ? meta({ name: 'description', content: options.description })\n : undefined;\n\n const titleEl = title(options.title ?? '');\n\n const metaList = [charsetMeta, viewportMeta, descriptionMeta, titleEl].filter(\n (el): el is NonNullable<typeof el> => el !== undefined,\n );\n\n const headEl = head(...metaList);\n const bodyEl = body();\n\n const htmlEl =\n options.lang !== undefined\n ? html({ lang: options.lang }, headEl, bodyEl)\n : html(headEl, bodyEl);\n\n root.addChild(htmlEl);\n\n return { bodyEl: bodyEl as unknown as HtmlTag };\n}\n","import type { GlobalCss } from '../css/variables/global-css.js';\nimport { Root } from '../html/elements/root.js';\nimport type { State } from '../js/vanilla/state/state.js';\nimport { AppDocument } from './app-document.js';\nimport type { AppOptions } from './app-options.js';\nimport { buildDocumentSkeleton } from './build-document-skeleton.js';\n\n/**\n * App state 操作の入口インターフェース。\n *\n * @internal 公開 API ではない(1.0.0 で公開面から除去済み)。利用者は `AppDocument`(`app()` の戻り値型)を使うこと。\n * 本インターフェースは `AppDocument implements AppContext` の構造的契約として内部実装で継続使用される。\n * 詳細は [docs/deprecation-policy.md](../../docs/deprecation-policy.md) 参照。\n */\nexport interface AppContext {\n /**\n * 初期値 `initialValue` を持つ State<T> を生成する。\n */\n state<T>(initialValue: T): State<T>;\n}\n\n/**\n * インタラクティブアプリのファサードを生成するファクトリ関数。\n *\n * 内部で `Root` を生成し、`html/head/body` の DOM スケルトンを組み立てて\n * `AppDocument` を返す。ユーザーは `Root` / `FileExporter` / `el.html` 等を\n * import する必要がなくなる。\n *\n * デフォルト値:\n * - `charset`: `\"UTF-8\"`\n * - `lang`: `\"en\"`\n * - `wrapDOMReady`: `false`\n *\n * `AppDocument` は `AppContext` の構造的サブタイプのため、\n * 既存の `const ctx: AppContext = app(); ctx.state(0)` は変更不要。\n *\n * Requirements: 1.1, 1.2, 1.3, 1.4, 4.3\n * Boundary: src/app/app.ts\n */\nexport function app(): AppDocument;\nexport function app(options: AppOptions): AppDocument;\nexport function app(options?: AppOptions): AppDocument {\n const resolvedOptions: AppOptions = {\n charset: 'UTF-8',\n lang: 'en',\n ...options,\n };\n\n const { css } = resolvedOptions;\n const cssArray: readonly GlobalCss[] = css === undefined ? []\n : Array.isArray(css) ? css\n : [css];\n\n const root = new Root({ css: cssArray, cssConfig: resolvedOptions.cssConfig });\n const { bodyEl } = buildDocumentSkeleton(root, resolvedOptions);\n return new AppDocument(root, bodyEl, resolvedOptions);\n}\n"],"mappings":";;;;;;;;;;;AAwBO,IAAM,cAAN,MAAwC;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACT,YAAY;AAAA;AAAA,EAGpB,YAAY,MAAY,QAAiB,SAAqB;AAC5D,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAS,cAA2B;AAClC,WAAO,KAAK,MAAM,MAAM,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,SAAS,SAAuC,YAA0B;AACxE,QAAI,KAAK,WAAW;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACzD,eAAW,QAAQ,OAAO;AACxB,WAAK,QAAQ,SAAS,IAAkC;AACxD,WAAK,MAAM,iBAAiB,IAAkC;AAAA,IAChE;AAEA,QAAI,aAAa,EAAE,cAAc,KAAK,SAAS,gBAAgB,MAAM,CAAC,EAAE;AAAA,MACtE,KAAK;AAAA,MACL;AAAA,IACF;AAEA,SAAK,YAAY;AAAA,EACnB;AACF;;;AC9DO,SAAS,sBACd,MACA,SACqB;AACrB,OAAK,WAAW,IAAI;AAEpB,QAAM,cAAc,KAAK,EAAE,SAAS,QAAQ,WAAW,QAAQ,CAAC;AAEhE,QAAM,eACJ,QAAQ,aAAa,SACjB,KAAK,EAAE,MAAM,YAAY,SAAS,QAAQ,SAAS,CAAC,IACpD;AAEN,QAAM,kBACJ,QAAQ,gBAAgB,SACpB,KAAK,EAAE,MAAM,eAAe,SAAS,QAAQ,YAAY,CAAC,IAC1D;AAEN,QAAM,UAAU,MAAM,QAAQ,SAAS,EAAE;AAEzC,QAAM,WAAW,CAAC,aAAa,cAAc,iBAAiB,OAAO,EAAE;AAAA,IACrE,CAAC,OAAqC,OAAO;AAAA,EAC/C;AAEA,QAAM,SAAS,KAAK,GAAG,QAAQ;AAC/B,QAAM,SAAS,KAAK;AAEpB,QAAM,SACJ,QAAQ,SAAS,SACb,KAAK,EAAE,MAAM,QAAQ,KAAK,GAAG,QAAQ,MAAM,IAC3C,KAAK,QAAQ,MAAM;AAEzB,OAAK,SAAS,MAAM;AAEpB,SAAO,EAAE,OAAqC;AAChD;;;ACRO,SAAS,IAAI,SAAmC;AACrD,QAAM,kBAA8B;AAAA,IAClC,SAAS;AAAA,IACT,MAAM;AAAA,IACN,GAAG;AAAA,EACL;AAEA,QAAM,EAAE,IAAI,IAAI;AAChB,QAAM,WAAiC,QAAQ,SAAY,CAAC,IACxD,MAAM,QAAQ,GAAG,IAAI,MACrB,CAAC,GAAG;AAER,QAAM,OAAO,IAAI,KAAK,EAAE,KAAK,UAAU,WAAW,gBAAgB,UAAU,CAAC;AAC7E,QAAM,EAAE,OAAO,IAAI,sBAAsB,MAAM,eAAe;AAC9D,SAAO,IAAI,YAAY,MAAM,QAAQ,eAAe;AACtD;","names":[]}