hono-decks 1.1.0 → 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 +35 -1
- package/README.md +46 -2
- package/dist/adapters/hono-markdown.d.ts +39 -0
- package/dist/adapters/hono-markdown.js +47 -0
- package/dist/advanced.d.ts +5 -2
- package/dist/bin.js +77 -29
- package/dist/cli.js +77 -29
- package/dist/{init-vite-mLg3XlcN.js → init-vite-EA_L4k2H.js} +35 -27
- package/dist/mod.d.ts +5 -2
- package/dist/node.d.ts +115 -112
- package/dist/node.js +76 -28
- package/dist/vite.js +76 -28
- package/package.json +5 -1
|
@@ -6,6 +6,19 @@ import { dirname, join, relative, resolve } from "node:path";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { parse } from "@babel/parser";
|
|
8
8
|
import { execFile } from "node:child_process";
|
|
9
|
+
//#region src/adapters/void.ts
|
|
10
|
+
/** Dependency policy of the Void preset, outside the deck compiler. */
|
|
11
|
+
const voidDependencies = [
|
|
12
|
+
["void", "void@>=1.1.11 <1.2.0"],
|
|
13
|
+
["vite", "vite@^8.0.16"],
|
|
14
|
+
["hono", "hono@^4.13.13"],
|
|
15
|
+
["markdown-exit", "markdown-exit@^1.3.0"],
|
|
16
|
+
["yaml", "yaml@^2.9.1"],
|
|
17
|
+
["markdown-it-container", "markdown-it-container@^4.0.0"],
|
|
18
|
+
["shiki", "shiki@^4.5.0"],
|
|
19
|
+
["@shikijs/transformers", "@shikijs/transformers@^4.5.0"]
|
|
20
|
+
];
|
|
21
|
+
//#endregion
|
|
9
22
|
//#region src/node/install-void.ts
|
|
10
23
|
async function installVoidDependencies(cwd, options = {}) {
|
|
11
24
|
if (options.adapter?.startsWith("-")) throw new Error("--adapter must be a package specifier or tarball path.");
|
|
@@ -33,16 +46,7 @@ async function installVoidDependencies(cwd, options = {}) {
|
|
|
33
46
|
return true;
|
|
34
47
|
}
|
|
35
48
|
};
|
|
36
|
-
const required =
|
|
37
|
-
["void", "void@>=1.1.11 <1.2.0"],
|
|
38
|
-
["vite", "vite@^8.0.16"],
|
|
39
|
-
["hono", "hono@^4.13.13"],
|
|
40
|
-
["markdown-exit", "markdown-exit@^1.3.0"],
|
|
41
|
-
["yaml", "yaml@^2.9.1"],
|
|
42
|
-
["markdown-it-container", "markdown-it-container@^4.0.0"],
|
|
43
|
-
["shiki", "shiki@^4.5.0"],
|
|
44
|
-
["@shikijs/transformers", "@shikijs/transformers@^4.5.0"]
|
|
45
|
-
];
|
|
49
|
+
const required = voidDependencies;
|
|
46
50
|
for (const [id, spec] of required) {
|
|
47
51
|
if (missing(id)) continue;
|
|
48
52
|
const version = await installedVersion(require.resolve(id), id);
|
|
@@ -77,7 +81,7 @@ async function installVoidDependencies(cwd, options = {}) {
|
|
|
77
81
|
specs.push(`hono-decks@${requested}`);
|
|
78
82
|
}
|
|
79
83
|
if (options.adapter || missing("void-plugin-hono-jsx/markdown/compiler")) {
|
|
80
|
-
let adapter = options.adapter ?? "void-plugin-hono-jsx@^0.
|
|
84
|
+
let adapter = options.adapter ?? "void-plugin-hono-jsx@^0.5.0";
|
|
81
85
|
if (/^\d+\./.test(adapter)) adapter = "void-plugin-hono-jsx@" + adapter;
|
|
82
86
|
else if (modernYarn && (adapter.endsWith(".tgz") || adapter.startsWith("file:"))) adapter = "void-plugin-hono-jsx@file:" + resolve(cwd, adapter.replace(/^file:/, ""));
|
|
83
87
|
specs.push(adapter);
|
|
@@ -127,26 +131,30 @@ function compare(a, b) {
|
|
|
127
131
|
return 0;
|
|
128
132
|
}
|
|
129
133
|
//#endregion
|
|
134
|
+
//#region src/adapters/vite-presets.ts
|
|
135
|
+
/** Initialization policies belong to the host integration, not the compiler. */
|
|
136
|
+
const vitePresets = {
|
|
137
|
+
void: { dependencies: [...voidDependencies.map(([id]) => id), "void-plugin-hono-jsx/markdown/compiler"] },
|
|
138
|
+
hono: {
|
|
139
|
+
dependencies: ["vite", "hono"],
|
|
140
|
+
clientEntryAssetPath: "/_assets/client"
|
|
141
|
+
},
|
|
142
|
+
honox: {
|
|
143
|
+
dependencies: [
|
|
144
|
+
"vite",
|
|
145
|
+
"hono",
|
|
146
|
+
"honox"
|
|
147
|
+
],
|
|
148
|
+
clientEntryAssetPath: "/_assets/client"
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
//#endregion
|
|
130
152
|
//#region src/node/init-vite.ts
|
|
131
153
|
/** Configure an existing Vite app without changing its package scripts. */
|
|
132
154
|
async function initializeVite(cwd, framework, configFile = "hono-decks.config.ts", entry, installation) {
|
|
133
155
|
if (!configFile || configFile.startsWith("/") || configFile.includes("\\") || /^[A-Za-z]:/.test(configFile) || configFile.split("/").includes("..") || !/\.[cm]?[jt]s$/.test(configFile)) throw new Error("--config must be a JS/TS file inside the current working directory.");
|
|
134
156
|
const require = createRequire(join(cwd, "package.json"));
|
|
135
|
-
const dependencies = framework
|
|
136
|
-
"void",
|
|
137
|
-
"vite",
|
|
138
|
-
"hono",
|
|
139
|
-
"void-plugin-hono-jsx/markdown/compiler",
|
|
140
|
-
"markdown-exit",
|
|
141
|
-
"yaml",
|
|
142
|
-
"markdown-it-container",
|
|
143
|
-
"shiki",
|
|
144
|
-
"@shikijs/transformers"
|
|
145
|
-
] : [
|
|
146
|
-
"vite",
|
|
147
|
-
"hono",
|
|
148
|
-
...framework === "honox" ? ["honox"] : []
|
|
149
|
-
];
|
|
157
|
+
const dependencies = vitePresets[framework].dependencies;
|
|
150
158
|
for (const dependency of installation ? [] : dependencies) try {
|
|
151
159
|
require.resolve(dependency);
|
|
152
160
|
} catch {
|
|
@@ -177,7 +185,7 @@ async function initializeVite(cwd, framework, configFile = "hono-decks.config.ts
|
|
|
177
185
|
|
|
178
186
|
export default defineDecksConfig({
|
|
179
187
|
mountPath: "/slides",
|
|
180
|
-
build: { root: "decks"${framework === "void" ? ", markdown: \"void\"" : ""} }
|
|
188
|
+
build: { root: "decks"${framework === "void" ? ", markdown: \"void\"" : ""} },${vitePresets[framework].clientEntryAssetPath ? `\n router: { clientEntryAssetPath: ${JSON.stringify(vitePresets[framework].clientEntryAssetPath)} },` : ""}
|
|
181
189
|
});
|
|
182
190
|
`
|
|
183
191
|
},
|
package/dist/mod.d.ts
CHANGED
|
@@ -463,8 +463,11 @@ type DecksRouterOverrides<E extends Env = any> = Partial<Omit<DecksRouterOptions
|
|
|
463
463
|
type DecksRouterConfig<E extends Env = any> = Omit<DecksRouterOverrides<E>, "source">;
|
|
464
464
|
/** File-system settings consumed by the CLI. */
|
|
465
465
|
interface DecksBuildConfig {
|
|
466
|
-
/**
|
|
467
|
-
markdown?: "void"
|
|
466
|
+
/** Build-only Markdown adapter reference. "void" retains the compatible preset. */
|
|
467
|
+
markdown?: "void" | {
|
|
468
|
+
adapter: string;
|
|
469
|
+
options?: Record<string, unknown>;
|
|
470
|
+
};
|
|
468
471
|
/** Deck source directory. @default "decks" */
|
|
469
472
|
root?: string;
|
|
470
473
|
/** CLI output directory. Vite keeps modules in memory. @default "src/generated" */
|
package/dist/node.d.ts
CHANGED
|
@@ -236,116 +236,6 @@ declare class RenderError extends Error {
|
|
|
236
236
|
constructor(message: string, code: string, cause?: unknown);
|
|
237
237
|
}
|
|
238
238
|
//#endregion
|
|
239
|
-
//#region src/routing/file-routing.d.ts
|
|
240
|
-
interface ResolvedDeckFile {
|
|
241
|
-
slug: string;
|
|
242
|
-
sourcePath: string;
|
|
243
|
-
kind: DeckKind;
|
|
244
|
-
assetPaths: string[];
|
|
245
|
-
}
|
|
246
|
-
declare function resolveDeckFiles(paths: string[], root?: string, options?: {
|
|
247
|
-
markdown?: boolean;
|
|
248
|
-
}): ResolvedDeckFile[];
|
|
249
|
-
//#endregion
|
|
250
|
-
//#region src/generator/mdx/ogp.d.ts
|
|
251
|
-
interface LinkCardOgpMetadata {
|
|
252
|
-
title?: string;
|
|
253
|
-
description?: string;
|
|
254
|
-
image?: string;
|
|
255
|
-
siteName?: string;
|
|
256
|
-
}
|
|
257
|
-
//#endregion
|
|
258
|
-
//#region src/generator/component-registry.d.ts
|
|
259
|
-
interface DeckComponentExport {
|
|
260
|
-
slug: string;
|
|
261
|
-
sourcePath: string;
|
|
262
|
-
modulePath: string;
|
|
263
|
-
exportName: string;
|
|
264
|
-
}
|
|
265
|
-
interface ResolvedDeckComponentExport extends DeckComponentExport {
|
|
266
|
-
internalName: string;
|
|
267
|
-
}
|
|
268
|
-
interface ApplyDeckComponentRegistryInput {
|
|
269
|
-
manifest: DeckManifest;
|
|
270
|
-
components: DeckComponentExport[];
|
|
271
|
-
}
|
|
272
|
-
interface ApplyDeckComponentRegistryResult {
|
|
273
|
-
manifest: DeckManifest;
|
|
274
|
-
components: ResolvedDeckComponentExport[];
|
|
275
|
-
}
|
|
276
|
-
declare function applyDeckComponentRegistry(input: ApplyDeckComponentRegistryInput): ApplyDeckComponentRegistryResult;
|
|
277
|
-
declare function emitDeckComponentRegistryModule(components: ResolvedDeckComponentExport[]): string;
|
|
278
|
-
//#endregion
|
|
279
|
-
//#region src/node/compile-decks.d.ts
|
|
280
|
-
interface BuildDeckManifestFromFileSystemInput {
|
|
281
|
-
cwd: string;
|
|
282
|
-
root: string;
|
|
283
|
-
mountPath?: string;
|
|
284
|
-
}
|
|
285
|
-
interface WriteDeckManifestModuleInput {
|
|
286
|
-
manifest: DeckManifest;
|
|
287
|
-
outFile: string;
|
|
288
|
-
}
|
|
289
|
-
interface WriteDeckComponentRegistryModuleInput {
|
|
290
|
-
components: ResolvedDeckComponentExport[];
|
|
291
|
-
outFile: string;
|
|
292
|
-
}
|
|
293
|
-
interface WriteDecksRouterModuleInput {
|
|
294
|
-
manifestModulePath: string;
|
|
295
|
-
componentRegistryModulePath?: string;
|
|
296
|
-
outFile: string;
|
|
297
|
-
}
|
|
298
|
-
interface CompileDecksInput extends BuildDeckManifestFromFileSystemInput {
|
|
299
|
-
markdown?: "void";
|
|
300
|
-
out: string;
|
|
301
|
-
ogpCacheFile?: string;
|
|
302
|
-
refreshOgp?: boolean;
|
|
303
|
-
resolveOgp?(this: void, url: string): Promise<LinkCardOgpMetadata | undefined>;
|
|
304
|
-
}
|
|
305
|
-
/** Build information only; render using createDecks() from routerModulePath. */
|
|
306
|
-
interface CompileDecksResult {
|
|
307
|
-
outDir: string;
|
|
308
|
-
routerModulePath: string;
|
|
309
|
-
decks: DeckBuildSummary[];
|
|
310
|
-
}
|
|
311
|
-
interface DeckBuildSummary extends Omit<CompiledDeck, "slides" | "componentRegistry"> {
|
|
312
|
-
slides: (Pick<CompiledSlide, "index" | "meta" | "notes"> & {
|
|
313
|
-
modulePath: string;
|
|
314
|
-
})[];
|
|
315
|
-
}
|
|
316
|
-
declare function compileDecks(input: CompileDecksInput): Promise<CompileDecksResult>;
|
|
317
|
-
declare function buildDeckManifestFromFileSystem(input: BuildDeckManifestFromFileSystemInput): Promise<DeckManifest>;
|
|
318
|
-
declare function writeDeckManifestModule(input: WriteDeckManifestModuleInput): Promise<void>;
|
|
319
|
-
declare function writeDeckComponentRegistryModule(input: WriteDeckComponentRegistryModuleInput): Promise<void>;
|
|
320
|
-
declare function writeDecksRouterModule(input: WriteDecksRouterModuleInput): Promise<void>;
|
|
321
|
-
//#endregion
|
|
322
|
-
//#region src/node/local-deck-io.d.ts
|
|
323
|
-
interface CreateLocalDeckIOInput {
|
|
324
|
-
cwd: string;
|
|
325
|
-
root: string;
|
|
326
|
-
pathExists?(this: void, path: string): boolean;
|
|
327
|
-
watchFileSystem?(this: void, path: string, options: {
|
|
328
|
-
recursive: boolean;
|
|
329
|
-
}, listener: (eventType: "rename" | "change", filename: string | null) => void): {
|
|
330
|
-
close(): void;
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
declare function createLocalDeckIO(input: CreateLocalDeckIOInput): LocalDeckIO;
|
|
334
|
-
//#endregion
|
|
335
|
-
//#region src/node/local-dev-app.d.ts
|
|
336
|
-
interface CreateLocalDevSlidesAppInput {
|
|
337
|
-
cwd: string;
|
|
338
|
-
root: string;
|
|
339
|
-
mountPath?: string;
|
|
340
|
-
watchFileSystem?: CreateLocalDeckIOInput["watchFileSystem"];
|
|
341
|
-
}
|
|
342
|
-
interface LocalDevSlidesApp {
|
|
343
|
-
app: Hono;
|
|
344
|
-
localDeckIO: LocalDeckIO;
|
|
345
|
-
stop: () => void;
|
|
346
|
-
}
|
|
347
|
-
declare function createLocalDevSlidesApp(input: CreateLocalDevSlidesAppInput): Promise<LocalDevSlidesApp>;
|
|
348
|
-
//#endregion
|
|
349
239
|
//#region src/renderer/control-icons.d.ts
|
|
350
240
|
type DeckControlIconName = "deck-list" | "home" | "viewer" | "projection" | "presenter" | "previous" | "next" | "fullscreen" | "external-link" | "print" | "details" | "export-pdf" | "export-png";
|
|
351
241
|
//#endregion
|
|
@@ -646,8 +536,11 @@ type DecksRouterOverrides<E extends Env = any> = Partial<Omit<DecksRouterOptions
|
|
|
646
536
|
type DecksRouterConfig<E extends Env = any> = Omit<DecksRouterOverrides<E>, "source">;
|
|
647
537
|
/** File-system settings consumed by the CLI. */
|
|
648
538
|
interface DecksBuildConfig {
|
|
649
|
-
/**
|
|
650
|
-
markdown?: "void"
|
|
539
|
+
/** Build-only Markdown adapter reference. "void" retains the compatible preset. */
|
|
540
|
+
markdown?: "void" | {
|
|
541
|
+
adapter: string;
|
|
542
|
+
options?: Record<string, unknown>;
|
|
543
|
+
};
|
|
651
544
|
/** Deck source directory. @default "decks" */
|
|
652
545
|
root?: string;
|
|
653
546
|
/** CLI output directory. Vite keeps modules in memory. @default "src/generated" */
|
|
@@ -664,6 +557,116 @@ interface DecksConfig<E extends Env = any> {
|
|
|
664
557
|
router?: DecksRouterConfig<E>;
|
|
665
558
|
}
|
|
666
559
|
//#endregion
|
|
560
|
+
//#region src/routing/file-routing.d.ts
|
|
561
|
+
interface ResolvedDeckFile {
|
|
562
|
+
slug: string;
|
|
563
|
+
sourcePath: string;
|
|
564
|
+
kind: DeckKind;
|
|
565
|
+
assetPaths: string[];
|
|
566
|
+
}
|
|
567
|
+
declare function resolveDeckFiles(paths: string[], root?: string, options?: {
|
|
568
|
+
markdown?: boolean;
|
|
569
|
+
}): ResolvedDeckFile[];
|
|
570
|
+
//#endregion
|
|
571
|
+
//#region src/generator/mdx/ogp.d.ts
|
|
572
|
+
interface LinkCardOgpMetadata {
|
|
573
|
+
title?: string;
|
|
574
|
+
description?: string;
|
|
575
|
+
image?: string;
|
|
576
|
+
siteName?: string;
|
|
577
|
+
}
|
|
578
|
+
//#endregion
|
|
579
|
+
//#region src/generator/component-registry.d.ts
|
|
580
|
+
interface DeckComponentExport {
|
|
581
|
+
slug: string;
|
|
582
|
+
sourcePath: string;
|
|
583
|
+
modulePath: string;
|
|
584
|
+
exportName: string;
|
|
585
|
+
}
|
|
586
|
+
interface ResolvedDeckComponentExport extends DeckComponentExport {
|
|
587
|
+
internalName: string;
|
|
588
|
+
}
|
|
589
|
+
interface ApplyDeckComponentRegistryInput {
|
|
590
|
+
manifest: DeckManifest;
|
|
591
|
+
components: DeckComponentExport[];
|
|
592
|
+
}
|
|
593
|
+
interface ApplyDeckComponentRegistryResult {
|
|
594
|
+
manifest: DeckManifest;
|
|
595
|
+
components: ResolvedDeckComponentExport[];
|
|
596
|
+
}
|
|
597
|
+
declare function applyDeckComponentRegistry(input: ApplyDeckComponentRegistryInput): ApplyDeckComponentRegistryResult;
|
|
598
|
+
declare function emitDeckComponentRegistryModule(components: ResolvedDeckComponentExport[]): string;
|
|
599
|
+
//#endregion
|
|
600
|
+
//#region src/node/compile-decks.d.ts
|
|
601
|
+
interface BuildDeckManifestFromFileSystemInput {
|
|
602
|
+
cwd: string;
|
|
603
|
+
root: string;
|
|
604
|
+
mountPath?: string;
|
|
605
|
+
}
|
|
606
|
+
interface WriteDeckManifestModuleInput {
|
|
607
|
+
manifest: DeckManifest;
|
|
608
|
+
outFile: string;
|
|
609
|
+
}
|
|
610
|
+
interface WriteDeckComponentRegistryModuleInput {
|
|
611
|
+
components: ResolvedDeckComponentExport[];
|
|
612
|
+
outFile: string;
|
|
613
|
+
}
|
|
614
|
+
interface WriteDecksRouterModuleInput {
|
|
615
|
+
manifestModulePath: string;
|
|
616
|
+
componentRegistryModulePath?: string;
|
|
617
|
+
outFile: string;
|
|
618
|
+
}
|
|
619
|
+
interface CompileDecksInput extends BuildDeckManifestFromFileSystemInput {
|
|
620
|
+
markdown?: DecksBuildConfig["markdown"];
|
|
621
|
+
out: string;
|
|
622
|
+
ogpCacheFile?: string;
|
|
623
|
+
refreshOgp?: boolean;
|
|
624
|
+
resolveOgp?(this: void, url: string): Promise<LinkCardOgpMetadata | undefined>;
|
|
625
|
+
}
|
|
626
|
+
/** Build information only; render using createDecks() from routerModulePath. */
|
|
627
|
+
interface CompileDecksResult {
|
|
628
|
+
outDir: string;
|
|
629
|
+
routerModulePath: string;
|
|
630
|
+
decks: DeckBuildSummary[];
|
|
631
|
+
}
|
|
632
|
+
interface DeckBuildSummary extends Omit<CompiledDeck, "slides" | "componentRegistry"> {
|
|
633
|
+
slides: (Pick<CompiledSlide, "index" | "meta" | "notes"> & {
|
|
634
|
+
modulePath: string;
|
|
635
|
+
})[];
|
|
636
|
+
}
|
|
637
|
+
declare function compileDecks(input: CompileDecksInput): Promise<CompileDecksResult>;
|
|
638
|
+
declare function buildDeckManifestFromFileSystem(input: BuildDeckManifestFromFileSystemInput): Promise<DeckManifest>;
|
|
639
|
+
declare function writeDeckManifestModule(input: WriteDeckManifestModuleInput): Promise<void>;
|
|
640
|
+
declare function writeDeckComponentRegistryModule(input: WriteDeckComponentRegistryModuleInput): Promise<void>;
|
|
641
|
+
declare function writeDecksRouterModule(input: WriteDecksRouterModuleInput): Promise<void>;
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region src/node/local-deck-io.d.ts
|
|
644
|
+
interface CreateLocalDeckIOInput {
|
|
645
|
+
cwd: string;
|
|
646
|
+
root: string;
|
|
647
|
+
pathExists?(this: void, path: string): boolean;
|
|
648
|
+
watchFileSystem?(this: void, path: string, options: {
|
|
649
|
+
recursive: boolean;
|
|
650
|
+
}, listener: (eventType: "rename" | "change", filename: string | null) => void): {
|
|
651
|
+
close(): void;
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
declare function createLocalDeckIO(input: CreateLocalDeckIOInput): LocalDeckIO;
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region src/node/local-dev-app.d.ts
|
|
657
|
+
interface CreateLocalDevSlidesAppInput {
|
|
658
|
+
cwd: string;
|
|
659
|
+
root: string;
|
|
660
|
+
mountPath?: string;
|
|
661
|
+
watchFileSystem?: CreateLocalDeckIOInput["watchFileSystem"];
|
|
662
|
+
}
|
|
663
|
+
interface LocalDevSlidesApp {
|
|
664
|
+
app: Hono;
|
|
665
|
+
localDeckIO: LocalDeckIO;
|
|
666
|
+
stop: () => void;
|
|
667
|
+
}
|
|
668
|
+
declare function createLocalDevSlidesApp(input: CreateLocalDevSlidesAppInput): Promise<LocalDevSlidesApp>;
|
|
669
|
+
//#endregion
|
|
667
670
|
//#region src/node/config.d.ts
|
|
668
671
|
declare const DEFAULT_DECKS_CONFIG_FILE = "hono-decks.config.ts";
|
|
669
672
|
interface LoadedDecksConfig<E extends Env = any> {
|
package/dist/node.js
CHANGED
|
@@ -5,10 +5,10 @@ import { unified } from "unified";
|
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
6
|
import remarkMdx from "remark-mdx";
|
|
7
7
|
import remarkParse from "remark-parse";
|
|
8
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
9
8
|
import { compile } from "@mdx-js/mdx";
|
|
10
9
|
import remarkDirective from "remark-directive";
|
|
11
10
|
import { codeToHtml } from "shiki";
|
|
11
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
12
|
import { existsSync, watch } from "node:fs";
|
|
13
13
|
import { build } from "esbuild";
|
|
14
14
|
import { lookup } from "node:dns/promises";
|
|
@@ -1698,29 +1698,20 @@ function extractDeckPrelude(source) {
|
|
|
1698
1698
|
};
|
|
1699
1699
|
}
|
|
1700
1700
|
//#endregion
|
|
1701
|
-
//#region src/node/
|
|
1702
|
-
|
|
1703
|
-
async function compileVoidMarkdownDecks(input) {
|
|
1701
|
+
//#region src/node/markdown-decks.ts
|
|
1702
|
+
async function compileMarkdownDecks(input, adapter) {
|
|
1704
1703
|
const markdownEntries = input.decks.filter((entry) => entry.sourcePath.endsWith(".md"));
|
|
1705
1704
|
const mdx = await compileMdxModuleDecks({
|
|
1706
1705
|
...input,
|
|
1707
1706
|
decks: input.decks.filter((entry) => !entry.sourcePath.endsWith(".md"))
|
|
1708
1707
|
});
|
|
1709
1708
|
if (!markdownEntries.length) return mdx;
|
|
1710
|
-
let compiler;
|
|
1711
|
-
try {
|
|
1712
|
-
compiler = await import(pathToFileURL(createRequire(resolve(input.cwd ?? process.cwd(), "package.json")).resolve("void-plugin-hono-jsx/markdown/compiler")).href);
|
|
1713
|
-
if (typeof (compiler.compileMarkdownModule ?? compiler.compileStaticMarkdown) !== "function" || typeof (compiler.readMarkdownModule ?? compiler.readStaticMarkdown) !== "function") throw new Error("Missing standalone compiler API");
|
|
1714
|
-
} catch (error) {
|
|
1715
|
-
throw new Error("Void Markdown requires void-plugin-hono-jsx with the public /markdown/compiler API and its Markdown peers installed in the app.", { cause: error });
|
|
1716
|
-
}
|
|
1717
|
-
const readModule = compiler.readMarkdownModule ?? compiler.readStaticMarkdown;
|
|
1718
|
-
const compileModule = compiler.compileMarkdownModule ?? compiler.compileStaticMarkdown;
|
|
1719
1709
|
const decks = [...mdx.decks];
|
|
1720
1710
|
const clients = /* @__PURE__ */ new Set();
|
|
1721
1711
|
const markdownIslands = /* @__PURE__ */ new Map();
|
|
1722
1712
|
for (const entry of markdownEntries) try {
|
|
1723
|
-
const
|
|
1713
|
+
const source = await input.readText(entry.sourcePath);
|
|
1714
|
+
const parsed = adapter.read(source);
|
|
1724
1715
|
if (input.clientComponentIds?.[entry.slug] && Object.keys(input.clientComponentIds[entry.slug]).length) throw new Error("Void Markdown slides support static components only; use MDX for hono-decks client components.");
|
|
1725
1716
|
const warnings = [];
|
|
1726
1717
|
const meta = toDeckFrontmatter(parsed.frontmatter, warnings);
|
|
@@ -1741,12 +1732,13 @@ async function compileVoidMarkdownDecks(input) {
|
|
|
1741
1732
|
const slides = [];
|
|
1742
1733
|
for (const [index, slideSource] of splitMarkdownSlides(parsed.content).entries()) {
|
|
1743
1734
|
const prelude = parsed.script ? `<script>\n${parsed.script}\n<\/script>\n` : "";
|
|
1744
|
-
const slide =
|
|
1735
|
+
const slide = adapter.read(prelude + slideSource);
|
|
1745
1736
|
const path = `${input.outDir}/decks/${entry.slug}/slide-${index}.ts`;
|
|
1746
|
-
const
|
|
1737
|
+
const rewritten = rewriteAssetUrls(`${prelude}---\n${JSON.stringify({
|
|
1747
1738
|
...parsed.frontmatter,
|
|
1748
1739
|
...slide.frontmatter
|
|
1749
|
-
})}\n---\n${slide.content}`, assets)
|
|
1740
|
+
})}\n---\n${slide.content}`, assets);
|
|
1741
|
+
const result = await adapter.compile(rewritten, { sourcePath: resolve(input.cwd ?? process.cwd(), entry.sourcePath) });
|
|
1750
1742
|
clientEntryRequired ||= Boolean(result.clientCode || result.islands?.length);
|
|
1751
1743
|
if (result.clientCode) clients.add(result.clientCode);
|
|
1752
1744
|
for (const island of result.islands ?? []) markdownIslands.set(island.id, island);
|
|
@@ -1796,6 +1788,7 @@ async function compileVoidMarkdownDecks(input) {
|
|
|
1796
1788
|
decks,
|
|
1797
1789
|
routerModule: emitModuleDecksRouter({ decks }),
|
|
1798
1790
|
clientCode: [...clients].join("\n"),
|
|
1791
|
+
clientModules: [adapter.client([...markdownIslands.values()])].filter(Boolean),
|
|
1799
1792
|
markdownIslands: [...markdownIslands.values()]
|
|
1800
1793
|
};
|
|
1801
1794
|
}
|
|
@@ -1832,6 +1825,64 @@ function splitMarkdownSlides(source) {
|
|
|
1832
1825
|
return splitSlideSources(protectedLines.join("\n")).map((slide) => slide.replace(new RegExp(`${prefix}(\\d+)_END`, "g"), (_, id) => fences[Number(id)]));
|
|
1833
1826
|
}
|
|
1834
1827
|
//#endregion
|
|
1828
|
+
//#region src/adapters/hono-markdown.ts
|
|
1829
|
+
/** Node-only bridge. Existing Void configs retain their original compiler/runtime pair. */
|
|
1830
|
+
async function createHonoMarkdownAdapter(cwd, legacy = false, options) {
|
|
1831
|
+
const require = createRequire(resolve(cwd, "package.json"));
|
|
1832
|
+
const entry = legacy ? "void-plugin-hono-jsx/markdown/compiler" : "@ts-76/hono-markdown/compiler";
|
|
1833
|
+
let compiler;
|
|
1834
|
+
try {
|
|
1835
|
+
compiler = await import(pathToFileURL(require.resolve(entry)).href);
|
|
1836
|
+
} catch (cause) {
|
|
1837
|
+
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 });
|
|
1838
|
+
}
|
|
1839
|
+
const read = compiler.readMarkdownModule ?? compiler.readStaticMarkdown;
|
|
1840
|
+
const compile = compiler.compileMarkdownModule ?? compiler.compileStaticMarkdown;
|
|
1841
|
+
if (typeof read !== "function" || typeof compile !== "function") throw new Error("Missing standalone compiler API");
|
|
1842
|
+
const runtime = entry.startsWith("void-plugin") ? "void-plugin-hono-jsx/markdown/client" : "@ts-76/hono-markdown/client";
|
|
1843
|
+
return {
|
|
1844
|
+
read,
|
|
1845
|
+
compile: (source, input) => compile(source, {
|
|
1846
|
+
...input,
|
|
1847
|
+
options
|
|
1848
|
+
}),
|
|
1849
|
+
client: (islands) => emitMarkdownClient(islands, runtime)
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
function emitMarkdownClient(islands, runtime) {
|
|
1853
|
+
if (!islands.length) return "";
|
|
1854
|
+
const literal = (value) => JSON.stringify(value).replace(/</g, "\\u003c");
|
|
1855
|
+
return `import { hydrateMarkdownIslands } from ${literal(runtime)};
|
|
1856
|
+
hydrateMarkdownIslands({ ${islands.map((island) => `${literal(island.id)}: () => import(${literal(island.modulePath)})`).join(",")} }, {
|
|
1857
|
+
ready(element, start) {
|
|
1858
|
+
const slide = element.closest('section[data-slide-state]');
|
|
1859
|
+
if (!slide || slide.dataset.slideState === 'active') { start(); return; }
|
|
1860
|
+
const observer = new MutationObserver(() => {
|
|
1861
|
+
if (slide.dataset.slideState === 'active') { observer.disconnect(); start(); }
|
|
1862
|
+
});
|
|
1863
|
+
observer.observe(slide, { attributes: true, attributeFilter: ['data-slide-state'] });
|
|
1864
|
+
}
|
|
1865
|
+
});`;
|
|
1866
|
+
}
|
|
1867
|
+
//#endregion
|
|
1868
|
+
//#region src/node/markdown-adapter.ts
|
|
1869
|
+
async function loadMarkdownAdapter(selection, cwd) {
|
|
1870
|
+
if (selection === "void") return createHonoMarkdownAdapter(cwd, true);
|
|
1871
|
+
if (selection.adapter === "hono-decks/adapters/hono-markdown") return createHonoMarkdownAdapter(cwd, false, selection.options);
|
|
1872
|
+
const module = await import(pathToFileURL(createRequire(resolve(cwd, "package.json")).resolve(selection.adapter)).href);
|
|
1873
|
+
if (typeof module.createMarkdownAdapter !== "function") throw new Error("Markdown adapter must export createMarkdownAdapter.");
|
|
1874
|
+
const adapter = await module.createMarkdownAdapter({
|
|
1875
|
+
cwd,
|
|
1876
|
+
options: selection.options
|
|
1877
|
+
});
|
|
1878
|
+
if (![
|
|
1879
|
+
adapter?.read,
|
|
1880
|
+
adapter?.compile,
|
|
1881
|
+
adapter?.client
|
|
1882
|
+
].every((value) => typeof value === "function")) throw new Error("Markdown adapter must provide read, compile and client functions.");
|
|
1883
|
+
return adapter;
|
|
1884
|
+
}
|
|
1885
|
+
//#endregion
|
|
1835
1886
|
//#region src/generator/component-registry.ts
|
|
1836
1887
|
function applyDeckComponentRegistry(input) {
|
|
1837
1888
|
const components = input.components.map((component) => ({
|
|
@@ -1942,12 +1993,11 @@ async function emitClientEntryModule(input) {
|
|
|
1942
1993
|
registrations.push(`${JSON.stringify(clientId)}: ${localName}`);
|
|
1943
1994
|
}
|
|
1944
1995
|
}
|
|
1945
|
-
const
|
|
1946
|
-
if (registrations.length === 0 &&
|
|
1996
|
+
const clientModules = input.clientModules ?? [];
|
|
1997
|
+
if (registrations.length === 0 && clientModules.length === 0) return `export const decksClientEntry = ${JSON.stringify(input.extraCode ?? "")};\n`;
|
|
1947
1998
|
const result = await build({
|
|
1948
1999
|
stdin: {
|
|
1949
|
-
contents: `${
|
|
1950
|
-
hydrateMarkdownIslands({ ${markdown.map((entry) => `${javascriptString(entry.id)}: () => import(${javascriptString(entry.modulePath)})`).join(",")} });` : ""}
|
|
2000
|
+
contents: `${clientModules.join("\n")}
|
|
1951
2001
|
import { hydrateSlideIslands } from "hono-decks/client";
|
|
1952
2002
|
${imports.join("\n")}
|
|
1953
2003
|
|
|
@@ -2024,9 +2074,6 @@ function hashString(value) {
|
|
|
2024
2074
|
function safeIdentifier(value) {
|
|
2025
2075
|
return value.replace(/[^A-Za-z0-9_$]+/g, "_").replace(/^[^A-Za-z_$]+/, "_") || "_";
|
|
2026
2076
|
}
|
|
2027
|
-
function javascriptString(value) {
|
|
2028
|
-
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
2029
|
-
}
|
|
2030
2077
|
//#endregion
|
|
2031
2078
|
//#region src/node/path-utils.ts
|
|
2032
2079
|
function dirname(path) {
|
|
@@ -2369,7 +2416,7 @@ async function compileDeckModules(input) {
|
|
|
2369
2416
|
const out = normalizeRelativePath(input.out, "Output directory");
|
|
2370
2417
|
const root = normalizeDeckRoot(input.root);
|
|
2371
2418
|
const paths = await listFiles(input.cwd, join(input.cwd, root));
|
|
2372
|
-
const resolved = resolveDeckFiles(paths, root, { markdown: input.markdown
|
|
2419
|
+
const resolved = resolveDeckFiles(paths, root, { markdown: Boolean(input.markdown) });
|
|
2373
2420
|
const componentModulePaths = Object.fromEntries(resolved.flatMap((deck) => {
|
|
2374
2421
|
const path = deck.kind === "directory" ? findComponentModule(paths, root, deck.slug) : void 0;
|
|
2375
2422
|
return path ? [[deck.slug, path]] : [];
|
|
@@ -2397,7 +2444,8 @@ async function compileDeckModules(input) {
|
|
|
2397
2444
|
refresh: input.refreshOgp,
|
|
2398
2445
|
resolveOgp: input.resolveOgp ?? resolveOgpMetadata
|
|
2399
2446
|
});
|
|
2400
|
-
const
|
|
2447
|
+
const adapter = input.markdown && resolved.some((entry) => entry.sourcePath.endsWith(".md")) ? await loadMarkdownAdapter(input.markdown, input.cwd) : void 0;
|
|
2448
|
+
const generated = await (adapter ? (value) => compileMarkdownDecks(value, adapter) : compileMdxModuleDecks)({
|
|
2401
2449
|
cwd: input.cwd,
|
|
2402
2450
|
root,
|
|
2403
2451
|
outDir: out,
|
|
@@ -2416,7 +2464,7 @@ async function compileDeckModules(input) {
|
|
|
2416
2464
|
clientEntries: clientEntryPaths,
|
|
2417
2465
|
clientComponentIds,
|
|
2418
2466
|
extraCode: generated.clientCode,
|
|
2419
|
-
|
|
2467
|
+
clientModules: generated.clientModules,
|
|
2420
2468
|
onCss: (css) => {
|
|
2421
2469
|
clientCss = css;
|
|
2422
2470
|
}
|
|
@@ -5701,7 +5749,7 @@ async function loadDecksConfig(input) {
|
|
|
5701
5749
|
const config = (await import(`data:text/javascript;charset=utf-8,${encodeURIComponent(source)}#${Date.now()}`)).default;
|
|
5702
5750
|
if (!config || typeof config !== "object") throw new Error(`Config must have a default export: ${path}`);
|
|
5703
5751
|
if (typeof config.mountPath !== "string") throw new Error(`Config mountPath must be a string: ${path}`);
|
|
5704
|
-
if (config.build?.markdown !== void 0 && config.build.markdown !== "void") throw new Error("Config build.markdown must be \"void\".");
|
|
5752
|
+
if (config.build?.markdown !== void 0 && config.build.markdown !== "void" && (typeof config.build.markdown !== "object" || !config.build.markdown || typeof config.build.markdown.adapter !== "string" || !config.build.markdown.adapter.trim())) throw new Error("Config build.markdown must be \"void\" or an adapter reference.");
|
|
5705
5753
|
return {
|
|
5706
5754
|
path,
|
|
5707
5755
|
config,
|