hono-decks 1.0.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +221 -3
- package/README.md +241 -3
- package/dist/adapters/hono-markdown.d.ts +39 -0
- package/dist/adapters/hono-markdown.js +47 -0
- package/dist/advanced.d.ts +8 -1
- package/dist/advanced.js +165 -118
- package/dist/bin.js +356 -86
- package/dist/cli.js +356 -86
- package/dist/file-transaction-NjDxX6Gt.js +80 -0
- package/dist/honox.d.ts +21 -0
- package/dist/honox.js +47 -0
- package/dist/init-vite-EA_L4k2H.js +441 -0
- package/dist/mod.d.ts +8 -1
- package/dist/mod.js +7 -2
- package/dist/node.d.ts +121 -98
- package/dist/node.js +474 -157
- package/dist/vite.d.ts +4 -2
- package/dist/vite.js +441 -53
- package/package.json +15 -2
- package/skills/hono-decks/references/getting-started.md +40 -1
- package/skills/hono-decks/references/integrating.md +12 -0
- package/skills/hono-decks/references/styling.md +10 -0
- package/vite-env.d.ts +7 -0
package/README.ja.md
CHANGED
|
@@ -4,7 +4,175 @@
|
|
|
4
4
|
|
|
5
5
|
Hono と Cloudflare Workers 上で MDX のスライドを配信するためのライブラリです。ビルド時に MDX を TypeScript module へ変換し、Worker runtime ではファイルシステムや compiler を読み込みません。
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Hono+Vite/HonoX:init で接続する
|
|
8
|
+
|
|
9
|
+
既存のアプリに `hono-decks` をインストールし、構成に合わせて初期設定します。
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install hono-decks
|
|
13
|
+
|
|
14
|
+
# Hono+Vite
|
|
15
|
+
npx hono-decks init --framework hono
|
|
16
|
+
|
|
17
|
+
# HonoX の場合はこちら
|
|
18
|
+
npx hono-decks init --framework honox
|
|
19
|
+
|
|
20
|
+
# 以後は既存のコマンドを使う
|
|
21
|
+
npm run dev
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
どちらも、既存の Vite 設定を保持して自動コンパイルを登録し、
|
|
26
|
+
`hono-decks.config.ts`、`src/decks.ts`、サンプルの
|
|
27
|
+
`decks/welcome/deck.mdx` を作ります。生成ファイルがない状態からでも
|
|
28
|
+
通常の `dev`/`build` だけで動き、手動 `compile` やビルドコマンドの変更は不要です。
|
|
29
|
+
生成コードは Vite の仮想モジュールとして扱い、ファイルへ出力しません。Void 用のアダプターは必要ありません。
|
|
30
|
+
|
|
31
|
+
| 構成 | アプリへの接続 |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `--framework hono` | 既存の Hono エントリーにルーターを追加。既存のミドルウェアとルートを保持 |
|
|
34
|
+
| `--framework honox` | `createApp()` に設定連動のルートを追加。既存のオプション、ページ、ミドルウェアを保持 |
|
|
35
|
+
|
|
36
|
+
公開先は `/slides/welcome` です。同名の既存デッキがあれば、サンプルには
|
|
37
|
+
空いている名前を選びます。既存の `.mdx`、コンポーネント、画像はそのまま使えます。
|
|
38
|
+
|
|
39
|
+
Hono では、`src/index.ts`/`.tsx`/`.js`/`.mts`/`.mjs` または
|
|
40
|
+
`src/app.ts`/`.tsx`/`.js` の候補が1つなら自動検出します。
|
|
41
|
+
独自の場所にある場合や複数の候補がある場合は、
|
|
42
|
+
`--entry src/server.ts` のように指定してください。
|
|
43
|
+
自動接続は `const app = new Hono()` で作ったアプリを default export する形式に対応します。
|
|
44
|
+
先行する catch-all/動的ルートなど、安全に接続できない構成ではファイルを変更せず、
|
|
45
|
+
手動接続の案内を表示します。
|
|
46
|
+
|
|
47
|
+
HonoX は標準の `app/routes` と、`app/server.ts` で `createApp()` を default export
|
|
48
|
+
する構成に対応します。`init` は `src/honox-decks.ts` を作り、既存の
|
|
49
|
+
`createApp()` オプションを包みます。HonoX の公開 `ROUTES` API に設定から
|
|
50
|
+
ルートを追加するため、**公開パスは `mountPath` 一か所の変更で切り替わります**。
|
|
51
|
+
ルート用ディレクトリを作成・改名する必要はありません。既存ルートと重なる場合はエラーにします。
|
|
52
|
+
開発中の公開パス変更では、コンパイル後に Vite を自動で再起動してルートを切り替えます。
|
|
53
|
+
生成する HonoX 接続ファイルには、`import.meta.glob` によるルート探索と
|
|
54
|
+
`hono-decks/honox` の `withHonoXDecks()` 呼び出しだけを置きます。
|
|
55
|
+
ルートの合成と衝突検査はパッケージが担当し、動的ルートや catch-all との衝突も検出します。
|
|
56
|
+
この処理の修正は、アプリ側を再生成せずパッケージ更新で受け取れます。
|
|
57
|
+
`createApp()` のオプション、ミドルウェア、明示的な `ROUTES` は保持します。
|
|
58
|
+
`--config config/slides.ts` で設定ファイルの場所を変えることもできます。
|
|
59
|
+
|
|
60
|
+
## Void:通常の dev/build で使う
|
|
61
|
+
|
|
62
|
+
既存の Void アプリに hono-decks と対応する Hono Markdown アダプターを
|
|
63
|
+
インストールし、初回だけ `init` を実行します。
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
npx hono-decks init --framework void --install
|
|
67
|
+
npm run dev
|
|
68
|
+
# 本番用のビルド
|
|
69
|
+
npm run build
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
この連携には `void-plugin-hono-jsx@^0.5.0` の standalone compiler/client export
|
|
73
|
+
が必要です。`--install` は対応範囲のアダプターを選びます。
|
|
74
|
+
`--install` を省略する場合は、Markdown 用の任意 peer も必要です:
|
|
75
|
+
`markdown-exit@^1.3.0 yaml@^2.9.1 markdown-it-container@^4.0.0 shiki@^4.5.0 @shikijs/transformers@^4.5.0`。
|
|
76
|
+
動作確認した組み合わせは Void 1.1.11、Vite 8.3.4、Hono 4.13.13 です。
|
|
77
|
+
|
|
78
|
+
`--install` は npm/pnpm/Yarn/Bun を packageManager または lockfile から判定し、
|
|
79
|
+
不足する依存だけを追加します。互換性のない既存バージョンは自動更新せずエラーにします。
|
|
80
|
+
Yarn は node_modules linker を対象とし、PnP は手動インストールを使ってください。
|
|
81
|
+
依存を自分で管理する場合は `--install` を省略できます。ローカルでビルドしたアダプターは
|
|
82
|
+
`--adapter /absolute/path/void-plugin-hono-jsx.tgz` で指定できます。
|
|
83
|
+
アプリ設定の衝突はインストール前に検査し、インストール失敗時は接続ファイルを作りません。
|
|
84
|
+
パッケージマネージャーによる依存・lockfileの変更は残る場合があります。
|
|
85
|
+
|
|
86
|
+
`init --framework void` は、既存のルート `vite.config.*` の default export を
|
|
87
|
+
`withHonoDecks()` で包み、次のファイルを作ります。
|
|
88
|
+
|
|
89
|
+
- `hono-decks.config.ts`:公開パス `/slides`、入力先 `decks`、Hono Markdown の有効化
|
|
90
|
+
- `src/decks.ts`:アプリ側で編集できる接続ファイル
|
|
91
|
+
- `middleware/hono-decks.ts`:スライド配下のルーティング、Markdown の CSS、開発時の自動更新
|
|
92
|
+
- `decks/welcome/deck.md` と `Counter.tsx`:`/slides/welcome` で開ける対話可能なサンプル
|
|
93
|
+
|
|
94
|
+
既存の `welcome` デッキがある場合は、`welcome-2` などの空いている名前を選び、
|
|
95
|
+
URL を表示します。既存の Markdown/MDX はそのまま保持します。
|
|
96
|
+
|
|
97
|
+
サンプルを編集するか、`decks` に `.md`/`.mdx` を追加してください。
|
|
98
|
+
既存の Vite の `dev`/`build` が自動でコンパイルします。生成ファイルが
|
|
99
|
+
ない状態から起動する場合も、手動 `compile`、別の監視プロセス、
|
|
100
|
+
`package.json` のコマンド変更は不要です。Vite が生成コードをメモリ上で扱うため、
|
|
101
|
+
生成用ディレクトリや、その `.gitignore` 登録も不要です。
|
|
102
|
+
既存の Void のエントリー、ルート、package scripts は保持します。
|
|
103
|
+
公開パスは既存ルートと重ならないものを選び、必要に応じてアプリのアクセス制御を適用してください。
|
|
104
|
+
|
|
105
|
+
書き込み前に依存パッケージと出力先の衝突を確認します。既存の接続ファイルは
|
|
106
|
+
上書きせず、hono-decks の二重登録も行いません。ESM の default export で
|
|
107
|
+
設定を返すオブジェクト、式、非同期関数に対応します。対応できない設定では
|
|
108
|
+
ファイルを変更せず、`honoDecks()` を手動で登録する方法を表示します。
|
|
109
|
+
`--config config/slides.ts` で設定ファイルの場所を変更できます。
|
|
110
|
+
`--out`/`--generated` は、以下の汎用 init 向けのオプションです。
|
|
111
|
+
|
|
112
|
+
## Markdown 内のクライアントコンポーネント
|
|
113
|
+
|
|
114
|
+
Hono Markdown では、別の登録ファイルを作らず、本文の import から自動登録できます。
|
|
115
|
+
|
|
116
|
+
```md
|
|
117
|
+
<script>
|
|
118
|
+
import Counter from "./Counter.tsx" with { island: "load" };
|
|
119
|
+
</script>
|
|
120
|
+
---
|
|
121
|
+
title: Interactive slide
|
|
122
|
+
---
|
|
123
|
+
# デモ
|
|
124
|
+
|
|
125
|
+
<Counter label="Count" initial="2" />
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`Counter.tsx` は Hono JSX の default export です。`hono/jsx` の `useState` を使えます。
|
|
129
|
+
island はサーバーで初期描画し、`load`/`visible`/`idle`/`media:(query)` の条件で
|
|
130
|
+
ブラウザー上で動かします。`visible` はスライドがアクティブになってから監視します。
|
|
131
|
+
CSS import はコンパイル時に回収し、SSR・印刷ページにも含めます。
|
|
132
|
+
`useFrontmatter()` と `useMarkdownHeadings()` は各スライドの情報を返します。
|
|
133
|
+
クライアントへ渡すメタデータに秘密情報を含めないでください。
|
|
134
|
+
|
|
135
|
+
対応範囲は相対 TSX/JSX の default import と、文字列・真偽値のリテラル属性です。
|
|
136
|
+
JSX 式、island タグの子要素、任意の script コードは未対応です。
|
|
137
|
+
静的な部品は引き続き `with { component: "static" }` を使います。
|
|
138
|
+
既存 MDX のクライアントコンポーネント登録方法は変わりません。
|
|
139
|
+
|
|
140
|
+
## Vite の生成物と型チェック
|
|
141
|
+
|
|
142
|
+
Hono+Vite/HonoX/Void は、共通の `virtual:hono-decks` を入口にします。
|
|
143
|
+
`init` が作る `src/decks.ts` は、この仮想モジュールへ接続します。
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
/// <reference types="hono-decks/vite-env" />
|
|
147
|
+
import { decks } from "virtual:hono-decks";
|
|
148
|
+
|
|
149
|
+
export { decks };
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`decks` は `hono-decks.config.ts` を適用したコレクションです。
|
|
153
|
+
`decks.router()`、`decks.paths()` などの API は従来どおり使えます。
|
|
154
|
+
仮想モジュールには必要に応じて設定を適用する `createDecks(config)` もあります。
|
|
155
|
+
型定義はパッケージに同梱しているため、初回の `dev`/`build` 前でも型チェックできます。
|
|
156
|
+
|
|
157
|
+
通常は `decks/` の原稿・画像・部品と設定ファイルを編集します。
|
|
158
|
+
Vite はコンパイル結果をメモリ上のモジュールとして読み込み、ビルド時にアプリへ取り込みます。
|
|
159
|
+
`src/generated` の作成や直接 import、`build.outDir` の指定は不要です。
|
|
160
|
+
明示的に設定した OGP メタデータキャッシュは、従来どおり保存します。
|
|
161
|
+
設定から import した別ファイルも監視するため、公開パスなどを分けて管理できます。
|
|
162
|
+
init の開発クライアントは Vite の `BASE_URL` を使います。ホストの開発サーバーが
|
|
163
|
+
Vite の URL を処理する構成では、base に合わせた既存のアセット除外設定も保持してください。
|
|
164
|
+
|
|
165
|
+
既存の Vite 接続ファイルが生成先を直接 import している場合も、プラグインが
|
|
166
|
+
設定された出力先を仮想モジュールへ解決します。生成 TypeScript を参照する
|
|
167
|
+
`.js` 拡張子の import も互換性を維持します。新しい接続では上記の固定の入口を推奨します。
|
|
168
|
+
|
|
169
|
+
Vite 以外で使う CLI の `hono-decks compile` と `compileDecks()` は、
|
|
170
|
+
従来どおり `build.outDir`/`out` へファイルを書き出します。
|
|
171
|
+
コンパイル処理は両方式で共通です。実行環境にコンパイラーや Node のファイル操作は持ち込みません。
|
|
172
|
+
|
|
173
|
+
## Hono/MDX の Quick start
|
|
174
|
+
|
|
175
|
+
Vite を使う Hono/HonoX/Void アプリでは、以下の手動コンパイル手順ではなく、上記の init を使ってください。
|
|
8
176
|
|
|
9
177
|
```bash
|
|
10
178
|
bun add hono hono-decks
|
|
@@ -197,7 +365,7 @@ decks/product/
|
|
|
197
365
|
index.tsx
|
|
198
366
|
```
|
|
199
367
|
|
|
200
|
-
`components/index.tsx` は server-side JSX component、`components/client/index.tsx` は browser で hydrate する component です。`theme.css` はその deck
|
|
368
|
+
`components/index.tsx` は server-side JSX component、`components/client/index.tsx` は browser で hydrate する component です。`theme.css` はその deck だけに適用されます。 テーマ未指定時は白背景と濃い文字色を使います。配色を変える場合は `theme.css` で `--hono-decks-background` と `--hono-decks-color` を合わせて指定してください。1920 × 1080 の固定キャンバス内では `px` や `rem` を使います。`vw` / `vh` はブラウザのズームに応じて内容の配置も変えてしまいます。画像は compile 時に検出され、`mountPath` と slug を使った public URL に書き換えられます。
|
|
201
369
|
|
|
202
370
|
## Embedding
|
|
203
371
|
|
|
@@ -243,7 +411,7 @@ export default defineDecksConfig({
|
|
|
243
411
|
|
|
244
412
|
独自CDNを使う場合は `imagePath: ({ deck }) => \`https://cdn.example.com/${deck.slug}.png\`` のように resolver で上書きできます。`false` または未指定なら social metadata は出力しません。
|
|
245
413
|
|
|
246
|
-
生成処理は core に含まれません。`examples/ogp` では `hono-decks/node` の `compileDecks()`
|
|
414
|
+
生成処理は core に含まれません。`examples/ogp` では `hono-decks/node` の `compileDecks()` が返すデッキのメタデータを Satori + resvg へ渡し、1200×630 PNG を Workers Static Assets へ保存します。Satori / resvg は example だけの依存で、Browser Rendering binding は不要です。Satori は TTF / OTF / WOFF を読み込めますが WOFF2 は扱えないため、対象言語の font file を build script から明示的に渡してください。
|
|
247
415
|
|
|
248
416
|
`build.ogpCacheFile` は `@[card](...)` が参照する外部サイトのメタデータキャッシュです。viewer 自身の share image とは別機能です。
|
|
249
417
|
|
|
@@ -290,3 +458,53 @@ app.route("/internal-slides", decksRouter({ source, dev: true }));
|
|
|
290
458
|
- `examples/minimal`: standalone Worker の最小構成
|
|
291
459
|
- `examples/basic`: R2、Browser Rendering、custom routes、client components
|
|
292
460
|
- `examples/honox`: HonoX integration
|
|
461
|
+
|
|
462
|
+
## Node ビルド結果と失敗時の復旧
|
|
463
|
+
|
|
464
|
+
`compileDecks()` の戻り値は `CompileDecksResult` です。出力先、生成された
|
|
465
|
+
`decks.ts` のパス、各デッキのメタデータ、スライドのモジュールパスを返します。
|
|
466
|
+
描画には、生成された `decks.ts` の `createDecks()` を使ってください。
|
|
467
|
+
戻り値をそのまま `defineDecks()` へ渡すコードは変更が必要です。
|
|
468
|
+
タイトル、警告、アセット、ノートを `result.decks` から読む処理は引き続き使えます。
|
|
469
|
+
|
|
470
|
+
同期レンダラーは同期の描画関数を実行します。非同期の本文には非同期版を使うよう
|
|
471
|
+
エラーで案内し、描画できないビルド結果を渡した場合も空表示にせずエラーにします。
|
|
472
|
+
|
|
473
|
+
生成処理とクライアント資産のビルドが完了してから、生成ファイルと OGP キャッシュを
|
|
474
|
+
反映します。反映中に失敗した場合は、直前の内容へ戻します。OS やプロセスの停止時の
|
|
475
|
+
一括反映、複数プロセスの同時実行は保証しません。復元自体に失敗した場合は、
|
|
476
|
+
復旧用ファイルを残し、その場所をエラーに表示します。
|
|
477
|
+
|
|
478
|
+
## Markdownアダプター
|
|
479
|
+
|
|
480
|
+
従来の `build.markdown: "void"` に加えて、ビルド時に読み込むアダプターを指定できます。
|
|
481
|
+
|
|
482
|
+
```ts
|
|
483
|
+
export default defineDecksConfig({
|
|
484
|
+
mountPath: "/slides",
|
|
485
|
+
router: { clientEntryAssetPath: "/_assets/client" },
|
|
486
|
+
build: {
|
|
487
|
+
root: "decks",
|
|
488
|
+
markdown: { adapter: "hono-decks/adapters/hono-markdown" },
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
このブリッジは共通の `@ts-76/hono-markdown` を利用します。共通パッケージはVoid・Viteに依存しません。このアダプターを選ぶ場合はコンパイラー用peer dependenciesも導入します。
|
|
494
|
+
既存の `markdown: "void"` は、既に導入したVoidアダプターの公開コンパイラーAPIでも引き続き動作します。
|
|
495
|
+
`init --framework void --install` の導入手順、既存のdev/buildコマンドは変わりません。
|
|
496
|
+
|
|
497
|
+
設定はサーバー実行時にも読み込むため、アダプターは文字列で指定し、Node用のfactoryを設定ファイルへimportしません。
|
|
498
|
+
Hono+Vite・HonoXは引き続きMDXが標準で、VoidやMarkdown用パーサーの追加は不要です。
|
|
499
|
+
これらでMarkdownを使う場合は、共通パッケージとコンパイラー用peer dependenciesを導入し、上記ブリッジを選択します。
|
|
500
|
+
Viteは仮想モジュールを利用し、既存の `hono-decks compile` はファイル出力を維持します。
|
|
501
|
+
|
|
502
|
+
独自アダプターは `createMarkdownAdapter({ cwd, options })` をexportし、`read(source)`、非同期の
|
|
503
|
+
`compile(source, { sourcePath })`、`client(islands)` を返します。型は `hono-decks/adapters/hono-markdown` からimportできます。
|
|
504
|
+
スライド分割・メタデータ・アセット・ルーティング・表示中スライドの判定はhono-decksが担当し、Markdownの変換とislandのスケジュールはアダプターが担当します。
|
|
505
|
+
同じVoidアプリにhonoxpressを組み込んでも、ドキュメントとスライドが互いの内部実装に依存する必要はありません。
|
|
506
|
+
|
|
507
|
+
Hono+Vite・HonoXのinitは、dev serverが標準で`.js`を除外するため、拡張子なしの
|
|
508
|
+
`/_assets/client`を設定します。配信は既存アプリのミドルウェア・認可を通ります。
|
|
509
|
+
既存CLI構成の標準パス`/_assets/client.js`は維持します。VoidなしのMarkdown実アプリ検証は、
|
|
510
|
+
`HONO_MARKDOWN_PACKAGE`に共通パッケージのtarballを指定し、`node scripts/verify-vite-init.mjs`で実行できます。
|
package/README.md
CHANGED
|
@@ -4,9 +4,173 @@ English | [日本語](https://github.com/ts-76/hono-decks/blob/main/packages/dec
|
|
|
4
4
|
|
|
5
5
|
hono-decks serves MDX slide decks from Hono applications and Cloudflare Workers. It compiles MDX into TypeScript modules at build time, so the Worker runtime does not load the filesystem or the compiler.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Hono + Vite / HonoX: connect with init
|
|
8
|
+
|
|
9
|
+
Install hono-decks in an existing app and choose its integration:
|
|
10
|
+
|
|
11
|
+
~~~sh
|
|
12
|
+
npm install hono-decks
|
|
13
|
+
|
|
14
|
+
# Hono + Vite
|
|
15
|
+
npx hono-decks init --framework hono
|
|
16
|
+
|
|
17
|
+
# Use this instead for HonoX
|
|
18
|
+
npx hono-decks init --framework honox
|
|
19
|
+
|
|
20
|
+
# Keep using the app's existing commands
|
|
21
|
+
npm run dev
|
|
22
|
+
npm run build
|
|
23
|
+
~~~
|
|
24
|
+
|
|
25
|
+
Both modes preserve the existing Vite config while adding automatic compilation,
|
|
26
|
+
create `hono-decks.config.ts`, `src/decks.ts`, and a sample
|
|
27
|
+
`decks/welcome/deck.mdx`. Generated code stays in Vite virtual modules and is not written to disk.
|
|
28
|
+
Normal `dev` and `build` work from a checkout without generated files. There is
|
|
29
|
+
no manual `compile` step or package script change. Neither mode needs the Void adapter.
|
|
30
|
+
|
|
31
|
+
| Mode | Application connection |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `--framework hono` | Adds the router to the existing Hono entry, preserving its middleware and routes |
|
|
34
|
+
| `--framework honox` | Adds a config-driven route to `createApp()`, preserving its options, pages, and middleware |
|
|
35
|
+
|
|
36
|
+
Open `/slides/welcome`. Init chooses another sample name if an existing deck has
|
|
37
|
+
that slug. Existing MDX decks, components, and images remain supported.
|
|
38
|
+
|
|
39
|
+
Hono init detects a single `src/index.ts`, `.tsx`, `.js`, `.mts`, `.mjs`, or
|
|
40
|
+
`src/app.ts`, `.tsx`, `.js` candidate. Use `--entry src/server.ts` for a custom
|
|
41
|
+
entry or multiple candidates. Automatic connection supports a default-exported
|
|
42
|
+
`const app = new Hono()`. It leaves files unchanged and explains manual mounting
|
|
43
|
+
when earlier catch-all/dynamic routes or another app shape prevent a safe edit.
|
|
44
|
+
|
|
45
|
+
HonoX init supports the standard `app/routes` layout and a default-exported
|
|
46
|
+
`createApp()` call in `app/server.ts`. It creates `src/honox-decks.ts` and wraps
|
|
47
|
+
the existing createApp options. The helper adds the deck route through the public
|
|
48
|
+
HonoX `ROUTES` API, so **changing `mountPath` alone changes the public path**.
|
|
49
|
+
There is no route directory to create or rename. Conflicts with existing routes
|
|
50
|
+
are errors. A mount change during development automatically restarts Vite after
|
|
51
|
+
compilation so route registrations switch together.
|
|
52
|
+
The generated HonoX file owns only `import.meta.glob` route discovery and a
|
|
53
|
+
call to `withHonoXDecks()` from `hono-decks/honox`. Route composition and conflict
|
|
54
|
+
checks are supplied by the package, including dynamic and catch-all conflicts.
|
|
55
|
+
Package updates therefore update this behavior without regenerating app code.
|
|
56
|
+
Custom `createApp()` options, middleware, and explicit `ROUTES` are preserved.
|
|
57
|
+
Both modes accept `--config config/slides.ts`.
|
|
58
|
+
|
|
59
|
+
## Void: use your existing dev and build commands
|
|
60
|
+
|
|
61
|
+
In an existing Void app, install hono-decks and a compatible Hono Markdown
|
|
62
|
+
adapter, then initialize once:
|
|
63
|
+
|
|
64
|
+
~~~sh
|
|
65
|
+
npx hono-decks init --framework void --install
|
|
66
|
+
npm run dev
|
|
67
|
+
# Production build:
|
|
68
|
+
npm run build
|
|
69
|
+
~~~
|
|
70
|
+
|
|
71
|
+
This integration requires `void-plugin-hono-jsx@^0.5.0` or a compatible adapter
|
|
72
|
+
with the `/markdown/compiler` and `/markdown/client` exports. `--install` selects
|
|
73
|
+
the supported adapter range. Without `--install`, also install the optional Markdown peers:
|
|
74
|
+
`markdown-exit@^1.3.0 yaml@^2.9.1 markdown-it-container@^4.0.0 shiki@^4.5.0 @shikijs/transformers@^4.5.0`.
|
|
75
|
+
The verified host versions are Void 1.1.11, Vite 8.3.4, and Hono 4.13.13.
|
|
76
|
+
|
|
77
|
+
`--install` selects npm/pnpm/Yarn/Bun from packageManager or lockfiles and installs
|
|
78
|
+
missing dependencies. Incompatible installed versions require an explicit update;
|
|
79
|
+
existing scripts are preserved. Yarn requires its node_modules linker; use manual
|
|
80
|
+
installation for PnP. Omit `--install` to manage dependencies yourself. To use a local adapter build, pass `--adapter /absolute/path/void-plugin-hono-jsx.tgz`.
|
|
81
|
+
Conflicting app files are checked before installation. Installation failures do not
|
|
82
|
+
write integration files; dependency and lockfile changes may remain.
|
|
83
|
+
|
|
84
|
+
`init --framework void` wraps the default export in the existing root
|
|
85
|
+
`vite.config.*` with `withHonoDecks()` and creates:
|
|
86
|
+
|
|
87
|
+
- `hono-decks.config.ts`: `/slides` mount, `decks` source directory, Hono Markdown enabled
|
|
88
|
+
- `src/decks.ts`: the app-owned facade
|
|
89
|
+
- `middleware/hono-decks.ts`: complete slide subtree routing, Markdown CSS, and dev reload support
|
|
90
|
+
- `decks/welcome/deck.md` and `Counter.tsx`: an interactive two-slide sample at `/slides/welcome`
|
|
91
|
+
|
|
92
|
+
If a `welcome` deck already exists, init chooses `welcome-2` (or the next free
|
|
93
|
+
name) and prints its URL, preserving the existing Markdown or MDX deck.
|
|
94
|
+
|
|
95
|
+
Edit the sample or add `.md` and `.mdx` decks under `decks`. Your existing Vite
|
|
96
|
+
`dev` and `build` commands perform compilation automatically, including from a
|
|
97
|
+
checkout without generated files. No manual `compile`, extra watch process, or
|
|
98
|
+
`package.json` script changes are needed. Generated code stays in memory, so no
|
|
99
|
+
generated directory or ignore entry is needed. Existing Void entry points, routes, and package scripts are preserved.
|
|
100
|
+
Choose a mount path that does not conflict with app routes; apply your app's
|
|
101
|
+
access policy to the slide subtree when needed.
|
|
102
|
+
|
|
103
|
+
The command checks dependencies and output conflicts before writing. It refuses
|
|
104
|
+
to overwrite integration files or add a second hono-decks integration. It accepts
|
|
105
|
+
ESM default-export config objects, expressions, and async config functions. For
|
|
106
|
+
an unsupported config, it leaves files unchanged and explains how to register
|
|
107
|
+
`honoDecks()` manually. `--config config/slides.ts` selects another config path;
|
|
108
|
+
`--out` and `--generated` apply only to the generic init below.
|
|
109
|
+
|
|
110
|
+
## Client components inside Markdown
|
|
111
|
+
|
|
112
|
+
Island imports register their components automatically; no separate registry is needed.
|
|
113
|
+
|
|
114
|
+
~~~md
|
|
115
|
+
<script>
|
|
116
|
+
import Counter from "./Counter.tsx" with { island: "load" };
|
|
117
|
+
</script>
|
|
118
|
+
---
|
|
119
|
+
title: Interactive slide
|
|
120
|
+
---
|
|
121
|
+
# Demo
|
|
122
|
+
|
|
123
|
+
<Counter label="Count" initial="2" />
|
|
124
|
+
~~~
|
|
125
|
+
|
|
126
|
+
Counter.tsx exports a default Hono JSX component and can use useState from hono/jsx.
|
|
127
|
+
The initial HTML is rendered on the server. Hydration supports load, visible, idle,
|
|
128
|
+
and media:(query); visible scheduling waits for the slide to become active.
|
|
129
|
+
Imported CSS is compiled into deck styles, including SSR and print output.
|
|
130
|
+
useFrontmatter() and useMarkdownHeadings() provide each slide's context on both
|
|
131
|
+
server and client. Do not place secrets in metadata delivered to client islands.
|
|
132
|
+
Only relative default TSX/JSX imports and literal string/boolean props are supported.
|
|
133
|
+
JSX expressions, island tag children and arbitrary script code are unsupported.
|
|
134
|
+
Static imports and the existing MDX client-component workflow remain available.
|
|
135
|
+
|
|
136
|
+
## Vite modules and typechecking
|
|
137
|
+
|
|
138
|
+
Hono + Vite, HonoX, and Void use the same `virtual:hono-decks` entry. Init creates
|
|
139
|
+
an app-owned `src/decks.ts` facade connected to it:
|
|
140
|
+
|
|
141
|
+
~~~ts
|
|
142
|
+
/// <reference types="hono-decks/vite-env" />
|
|
143
|
+
import { decks } from "virtual:hono-decks";
|
|
144
|
+
|
|
145
|
+
export { decks };
|
|
146
|
+
~~~
|
|
147
|
+
|
|
148
|
+
`decks` is configured with `hono-decks.config.ts`; its `router()`, `paths()`, and
|
|
149
|
+
other runtime APIs remain unchanged. The virtual module also exports
|
|
150
|
+
`createDecks(config)` when another configured kit is needed. Bundled ambient types
|
|
151
|
+
allow typechecking before the first dev or build run.
|
|
152
|
+
|
|
153
|
+
Edit sources, images, components, and themes under `decks/`, plus your config.
|
|
154
|
+
Vite reads compiled code from an in-memory module map and bundles it into the
|
|
155
|
+
application. There is no `src/generated` directory to create or import and no
|
|
156
|
+
need to set `build.outDir`. An explicitly configured OGP metadata cache is still
|
|
157
|
+
written to disk. Imported config inputs (for example a separate mount-path
|
|
158
|
+
settings file) are also watched. Init uses Vite's `BASE_URL` for its development
|
|
159
|
+
client script. If the host's dev server intercepts Vite URLs, keep its existing
|
|
160
|
+
asset exclusions configured for the chosen base.
|
|
161
|
+
|
|
162
|
+
Existing Vite facades that import their configured generated path also resolve
|
|
163
|
+
through the virtual graph, including `.js` imports that previously resolved to
|
|
164
|
+
generated TypeScript files. Prefer the stable entry above for new integrations.
|
|
165
|
+
|
|
166
|
+
The non-Vite CLI `hono-decks compile` and `compileDecks()` continue to write files
|
|
167
|
+
to `build.outDir` / `out`. Both destinations use the same compiler. Compiler and
|
|
168
|
+
Node filesystem code remain outside the application runtime.
|
|
169
|
+
|
|
170
|
+
## Hono / MDX quick start
|
|
8
171
|
|
|
9
172
|
The examples below use Bun. npm, pnpm, and Yarn are supported as well.
|
|
173
|
+
For a Vite-hosted Hono, HonoX, or Void app, use its init flow above instead of this manual compilation flow.
|
|
10
174
|
|
|
11
175
|
~~~bash
|
|
12
176
|
bun add hono hono-decks
|
|
@@ -203,7 +367,7 @@ decks/product/
|
|
|
203
367
|
index.tsx
|
|
204
368
|
~~~
|
|
205
369
|
|
|
206
|
-
<code>components/index.tsx</code> contains server-side JSX components. <code>components/client/index.tsx</code> contains components hydrated in the browser. <code>theme.css</code> applies only to that deck. Local images are detected during compilation and rewritten to public URLs based on the mount path and deck slug.
|
|
370
|
+
<code>components/index.tsx</code> contains server-side JSX components. <code>components/client/index.tsx</code> contains components hydrated in the browser. <code>theme.css</code> applies only to that deck. Without a theme, slides use a white background and dark text. Customize `--hono-decks-background` and `--hono-decks-color` together in `theme.css`. Use `px` or `rem` within the fixed 1920 × 1080 canvas; viewport units change the composition when browser zoom changes. Local images are detected during compilation and rewritten to public URLs based on the mount path and deck slug.
|
|
207
371
|
|
|
208
372
|
## Embedding
|
|
209
373
|
|
|
@@ -249,7 +413,7 @@ export default defineDecksConfig({
|
|
|
249
413
|
|
|
250
414
|
Override <code>imagePath</code> with a resolver when images are served from a separate CDN. Set Open Graph configuration to <code>false</code>, or omit it, to suppress social metadata.
|
|
251
415
|
|
|
252
|
-
Image generation is intentionally not part of the core package. The <code>examples/ogp</code> recipe
|
|
416
|
+
Image generation is intentionally not part of the core package. The <code>examples/ogp</code> recipe uses the deck metadata returned by <code>compileDecks()</code> from <code>hono-decks/node</code> to Satori and resvg, then stores 1200 by 630 PNG files in Workers Static Assets. Satori and resvg are example-only dependencies, and the recipe does not require Browser Rendering. Satori accepts TTF, OTF, and WOFF fonts but not WOFF2, so the build script must receive a font file that covers the target language.
|
|
253
417
|
|
|
254
418
|
<code>build.ogpCacheFile</code> stores external site metadata used by <code>@[card](...)</code>. It is separate from the viewer's share image.
|
|
255
419
|
|
|
@@ -259,6 +423,7 @@ Image generation is intentionally not part of the core package. The <code>exampl
|
|
|
259
423
|
- <code>hono-decks/advanced</code>: <code>defineDecks()</code>, <code>decksRouter()</code>, <code>deckContext()</code>, raw renderers, and other low-level pipeline APIs
|
|
260
424
|
- <code>hono-decks/client</code>: browser hydration
|
|
261
425
|
- <code>hono-decks/node</code>: the compiler and Node filesystem adapter
|
|
426
|
+
- <code>hono-decks/honox</code>: shared HonoX route composition and conflict checks; no HonoX dependency is required by Hono-only apps
|
|
262
427
|
- <code>hono-decks/vite</code>: Vite integration that compiles and watches decks during development
|
|
263
428
|
- <code>hono-decks/cli</code>: the programmatic CLI runner
|
|
264
429
|
|
|
@@ -296,3 +461,76 @@ At this level, the application owns the mount path, source policy, and option me
|
|
|
296
461
|
- <code>examples/minimal</code>: the smallest standalone Worker setup
|
|
297
462
|
- <code>examples/basic</code>: R2, Browser Rendering, custom routes, and client components
|
|
298
463
|
- <code>examples/honox</code>: HonoX integration
|
|
464
|
+
|
|
465
|
+
## Void Hono Markdown
|
|
466
|
+
|
|
467
|
+
Set `build.markdown: "void"` in `hono-decks.config.ts` to opt into `.md` decks
|
|
468
|
+
alongside MDX. This requires `void-plugin-hono-jsx@^0.5.0` with its standalone compiler and client exports.
|
|
469
|
+
See the [Void consumer fixture](https://github.com/ts-76/hono-decks/tree/main/fixtures/void-markdown)
|
|
470
|
+
for package verification, Void middleware hosting, supported syntax and limitations.
|
|
471
|
+
|
|
472
|
+
## Node build results and failure recovery
|
|
473
|
+
|
|
474
|
+
`compileDecks()` returns `CompileDecksResult`, containing `outDir`,
|
|
475
|
+
`routerModulePath` and deck build summaries. Each slide summary includes its
|
|
476
|
+
`modulePath` and metadata. This result is not a renderable `DeckManifest`.
|
|
477
|
+
Import `createDecks()` from the generated `decks.ts` for runtime routing.
|
|
478
|
+
Custom build scripts reading titles, warnings, assets or notes can continue
|
|
479
|
+
using `result.decks`; code passing the return value into `defineDecks()` must
|
|
480
|
+
switch to the generated module.
|
|
481
|
+
|
|
482
|
+
Synchronous renderers execute synchronous slide render functions and reject
|
|
483
|
+
async bodies with guidance to use the async renderer. Both renderers reject
|
|
484
|
+
build summaries without a renderable body instead of silently producing empty
|
|
485
|
+
slides.
|
|
486
|
+
|
|
487
|
+
The compiler completes slide generation, client bundling and OGP-cache
|
|
488
|
+
serialization before publishing. It stages all files and restores overwritten
|
|
489
|
+
files (including cache files) on a publication error. Application-owned files
|
|
490
|
+
are preserved. This guarantees rollback on reported build failure, not
|
|
491
|
+
crash-atomic publication or coordination between concurrent compiler processes.
|
|
492
|
+
If rollback itself fails, the error lists retained recovery directories.
|
|
493
|
+
|
|
494
|
+
## Markdown adapters
|
|
495
|
+
|
|
496
|
+
The deck compiler accepts a build-only module reference as well as the existing
|
|
497
|
+
`build.markdown: "void"` preset:
|
|
498
|
+
|
|
499
|
+
```ts
|
|
500
|
+
export default defineDecksConfig({
|
|
501
|
+
mountPath: "/slides",
|
|
502
|
+
router: { clientEntryAssetPath: "/_assets/client" },
|
|
503
|
+
build: {
|
|
504
|
+
root: "decks",
|
|
505
|
+
markdown: { adapter: "hono-decks/adapters/hono-markdown" },
|
|
506
|
+
},
|
|
507
|
+
});
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The Hono Markdown bridge uses `@ts-76/hono-markdown/compiler` and its browser
|
|
511
|
+
runtime. The common package has no Void or Vite dependency. Install its optional compiler peers when selecting this adapter. Existing
|
|
512
|
+
Void configurations continue to work with the adapter's public compiler API,
|
|
513
|
+
including compatible earlier adapter versions. `init --framework void
|
|
514
|
+
--install` retains the one-command setup and unchanged dev/build scripts.
|
|
515
|
+
|
|
516
|
+
Keep the adapter reference in config as a string: config is also imported by the
|
|
517
|
+
server runtime. The compiler loads adapters only during builds. Hono+Vite and
|
|
518
|
+
HonoX continue to default to MDX without installing Void or Markdown peers.
|
|
519
|
+
For Markdown in these hosts, install the common package and its compiler peers
|
|
520
|
+
and select the bridge above. Vite uses virtual modules; `hono-decks compile`
|
|
521
|
+
continues to emit files.
|
|
522
|
+
|
|
523
|
+
Custom build adapters export `createMarkdownAdapter({ cwd, options })`, returning
|
|
524
|
+
`read(source)`, asynchronous `compile(source, { sourcePath })`, and
|
|
525
|
+
`client(islands)`. Types are exported from `hono-decks/adapters/hono-markdown`.
|
|
526
|
+
The deck host owns splitting, metadata, assets, routing and the visible-slide
|
|
527
|
+
hydration gate; Markdown compilation and island scheduling belong to the adapter.
|
|
528
|
+
Document adapters such as honoxpress can use the same Markdown package in a Void
|
|
529
|
+
app without importing deck internals or changing their route ownership.
|
|
530
|
+
|
|
531
|
+
Hono+Vite/HonoX init selects the extensionless `/_assets/client` route because
|
|
532
|
+
`@hono/vite-dev-server` excludes `.js` requests by default. The client still goes
|
|
533
|
+
through the application's middleware and authorization. Existing standalone CLI
|
|
534
|
+
configurations retain their default `/_assets/client.js` route. For local
|
|
535
|
+
Markdown checks without Void, set `HONO_MARKDOWN_PACKAGE` to the common tarball
|
|
536
|
+
and run `node scripts/verify-vite-init.mjs`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import "hono";
|
|
2
|
+
import "hono/jsx";
|
|
3
|
+
import "hono/utils/html";
|
|
4
|
+
//#region src/node/markdown-adapter.d.ts
|
|
5
|
+
interface MarkdownIsland {
|
|
6
|
+
id: string;
|
|
7
|
+
modulePath: string;
|
|
8
|
+
hydrate: string;
|
|
9
|
+
}
|
|
10
|
+
interface DeckMarkdownAdapter {
|
|
11
|
+
read(source: string): {
|
|
12
|
+
frontmatter: Record<string, unknown>;
|
|
13
|
+
content: string;
|
|
14
|
+
script: string;
|
|
15
|
+
};
|
|
16
|
+
compile(source: string, input: {
|
|
17
|
+
sourcePath: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
code: string;
|
|
20
|
+
headings: {
|
|
21
|
+
depth: number;
|
|
22
|
+
slug: string;
|
|
23
|
+
text: string;
|
|
24
|
+
}[];
|
|
25
|
+
clientCode: string;
|
|
26
|
+
islands?: MarkdownIsland[];
|
|
27
|
+
}>;
|
|
28
|
+
client(islands: MarkdownIsland[]): string;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/adapters/hono-markdown.d.ts
|
|
32
|
+
/** Node-only bridge. Existing Void configs retain their original compiler/runtime pair. */
|
|
33
|
+
declare function createHonoMarkdownAdapter(cwd: string, legacy?: boolean, options?: Record<string, unknown>): Promise<DeckMarkdownAdapter>;
|
|
34
|
+
declare function createMarkdownAdapter({ cwd, options }: {
|
|
35
|
+
cwd: string;
|
|
36
|
+
options?: Record<string, unknown>;
|
|
37
|
+
}): Promise<DeckMarkdownAdapter>;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { type DeckMarkdownAdapter, type MarkdownIsland, createHonoMarkdownAdapter, createMarkdownAdapter };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
//#region src/adapters/hono-markdown.ts
|
|
5
|
+
/** Node-only bridge. Existing Void configs retain their original compiler/runtime pair. */
|
|
6
|
+
async function createHonoMarkdownAdapter(cwd, legacy = false, options) {
|
|
7
|
+
const require = createRequire(resolve(cwd, "package.json"));
|
|
8
|
+
const entry = legacy ? "void-plugin-hono-jsx/markdown/compiler" : "@ts-76/hono-markdown/compiler";
|
|
9
|
+
let compiler;
|
|
10
|
+
try {
|
|
11
|
+
compiler = await import(pathToFileURL(require.resolve(entry)).href);
|
|
12
|
+
} catch (cause) {
|
|
13
|
+
throw new Error(`Hono Markdown requires ${legacy ? "its public /markdown/compiler API" : "@ts-76/hono-markdown/compiler"} and Markdown peers installed in the app.`, { cause });
|
|
14
|
+
}
|
|
15
|
+
const read = compiler.readMarkdownModule ?? compiler.readStaticMarkdown;
|
|
16
|
+
const compile = compiler.compileMarkdownModule ?? compiler.compileStaticMarkdown;
|
|
17
|
+
if (typeof read !== "function" || typeof compile !== "function") throw new Error("Missing standalone compiler API");
|
|
18
|
+
const runtime = entry.startsWith("void-plugin") ? "void-plugin-hono-jsx/markdown/client" : "@ts-76/hono-markdown/client";
|
|
19
|
+
return {
|
|
20
|
+
read,
|
|
21
|
+
compile: (source, input) => compile(source, {
|
|
22
|
+
...input,
|
|
23
|
+
options
|
|
24
|
+
}),
|
|
25
|
+
client: (islands) => emitMarkdownClient(islands, runtime)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function createMarkdownAdapter({ cwd, options }) {
|
|
29
|
+
return createHonoMarkdownAdapter(cwd, false, options);
|
|
30
|
+
}
|
|
31
|
+
function emitMarkdownClient(islands, runtime) {
|
|
32
|
+
if (!islands.length) return "";
|
|
33
|
+
const literal = (value) => JSON.stringify(value).replace(/</g, "\\u003c");
|
|
34
|
+
return `import { hydrateMarkdownIslands } from ${literal(runtime)};
|
|
35
|
+
hydrateMarkdownIslands({ ${islands.map((island) => `${literal(island.id)}: () => import(${literal(island.modulePath)})`).join(",")} }, {
|
|
36
|
+
ready(element, start) {
|
|
37
|
+
const slide = element.closest('section[data-slide-state]');
|
|
38
|
+
if (!slide || slide.dataset.slideState === 'active') { start(); return; }
|
|
39
|
+
const observer = new MutationObserver(() => {
|
|
40
|
+
if (slide.dataset.slideState === 'active') { observer.disconnect(); start(); }
|
|
41
|
+
});
|
|
42
|
+
observer.observe(slide, { attributes: true, attributeFilter: ['data-slide-state'] });
|
|
43
|
+
}
|
|
44
|
+
});`;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { createHonoMarkdownAdapter, createMarkdownAdapter };
|
package/dist/advanced.d.ts
CHANGED
|
@@ -177,6 +177,8 @@ interface CompiledDeck {
|
|
|
177
177
|
meta: DeckFrontmatter;
|
|
178
178
|
themeStyle?: string;
|
|
179
179
|
themeSourcePath?: string;
|
|
180
|
+
/** Omit generated client code for explicitly static compiled decks. */
|
|
181
|
+
clientEntryRequired?: boolean;
|
|
180
182
|
slides: CompiledSlide[];
|
|
181
183
|
assets: AssetRef[];
|
|
182
184
|
componentRegistry?: Record<string, SlideComponentInput>;
|
|
@@ -542,9 +544,14 @@ interface DefinedDecks<E extends Env = any> {
|
|
|
542
544
|
}
|
|
543
545
|
/** File-system settings consumed by the CLI. */
|
|
544
546
|
interface DecksBuildConfig {
|
|
547
|
+
/** Build-only Markdown adapter reference. "void" retains the compatible preset. */
|
|
548
|
+
markdown?: "void" | {
|
|
549
|
+
adapter: string;
|
|
550
|
+
options?: Record<string, unknown>;
|
|
551
|
+
};
|
|
545
552
|
/** Deck source directory. @default "decks" */
|
|
546
553
|
root?: string;
|
|
547
|
-
/**
|
|
554
|
+
/** CLI output directory. Vite keeps modules in memory. @default "src/generated" */
|
|
548
555
|
outDir?: string;
|
|
549
556
|
/** Optional deterministic Open Graph metadata cache. */
|
|
550
557
|
ogpCacheFile?: string;
|