@docubook/flame 2.0.0-beta.5 → 2.0.1

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 (58) hide show
  1. package/.docu/components/Theme.tsx +42 -34
  2. package/.docu/components/home/BackgroundBlobs.tsx +31 -0
  3. package/.docu/components/home/index.tsx +1 -0
  4. package/.docu/lib/build.deno.js +1 -1
  5. package/.docu/lib/build.impl--Pm9uO30.js +2 -0
  6. package/.docu/lib/{build.impl-BBlR3si3.js → build.impl-CsP6pPug.js} +60 -29
  7. package/.docu/lib/build.impl-CsP6pPug.js.map +1 -0
  8. package/.docu/lib/build.node.js +1 -1
  9. package/.docu/lib/clean.js +1 -1
  10. package/.docu/lib/deploy.deno.js +1 -1
  11. package/.docu/lib/deploy.node.js +1 -1
  12. package/.docu/lib/{deploy.shared-Dxv3lsOb.js → deploy.shared-CsEa3L1D.js} +45 -17
  13. package/.docu/lib/deploy.shared-CsEa3L1D.js.map +1 -0
  14. package/.docu/lib/{html.shared-DBMwv_Z6.js → html.shared-CsEFmy_Y.js} +181 -158
  15. package/.docu/lib/html.shared-CsEFmy_Y.js.map +1 -0
  16. package/.docu/lib/{logger-DYmvFF1d.js → logger-DLU3A-z2.js} +4 -3
  17. package/.docu/lib/logger-DLU3A-z2.js.map +1 -0
  18. package/.docu/lib/{paths-Bl2cdp9E.js → paths-Cbz-dj4s.js} +5 -9
  19. package/.docu/lib/{paths-Bl2cdp9E.js.map → paths-Cbz-dj4s.js.map} +1 -1
  20. package/.docu/lib/preview.deno.js +1 -1
  21. package/.docu/lib/{preview.impl-anVcZv2Z.js → preview.impl-CaZTgmnB.js} +3 -3
  22. package/.docu/lib/{preview.impl-anVcZv2Z.js.map → preview.impl-CaZTgmnB.js.map} +1 -1
  23. package/.docu/lib/preview.node.js +1 -1
  24. package/.docu/lib/server.deno.js +1 -1
  25. package/.docu/lib/{server.impl-Cvoa6Diq.js → server.impl-D-CgD1bn.js} +43 -52
  26. package/.docu/lib/server.impl-D-CgD1bn.js.map +1 -0
  27. package/.docu/lib/server.node.js +1 -1
  28. package/.docu/node/build.impl.ts +71 -34
  29. package/.docu/node/build.ts +68 -34
  30. package/.docu/node/cache-key.ts +8 -4
  31. package/.docu/node/client.ts +36 -27
  32. package/.docu/node/deploy.shared.ts +44 -18
  33. package/.docu/node/deploy.ts +5 -20
  34. package/.docu/node/home-client.ts +6 -0
  35. package/.docu/node/html.shared.ts +5 -4
  36. package/.docu/node/html.ts +4 -3
  37. package/.docu/node/hydrate.node.ts +87 -115
  38. package/.docu/node/hydrate.ts +74 -80
  39. package/.docu/node/mdx-manifest.d.ts +2 -2
  40. package/.docu/node/paths.ts +2 -9
  41. package/.docu/node/plugin-builder.ts +25 -13
  42. package/.docu/node/plugin.ts +33 -9
  43. package/.docu/node/server-routes.ts +59 -50
  44. package/.docu/node/server.impl.ts +4 -2
  45. package/.docu/node/server.ts +12 -16
  46. package/.docu/node/types.ts +11 -0
  47. package/.docu/pages/404.tsx +12 -9
  48. package/.docu/pages/index.tsx +8 -29
  49. package/.docu/styles/base.css +128 -0
  50. package/.docu/styles/globals.css +5 -137
  51. package/.docu/styles/site.css +7 -0
  52. package/package.json +6 -5
  53. package/.docu/lib/build.impl-BBlR3si3.js.map +0 -1
  54. package/.docu/lib/build.impl-DpoDUmei.js +0 -2
  55. package/.docu/lib/deploy.shared-Dxv3lsOb.js.map +0 -1
  56. package/.docu/lib/html.shared-DBMwv_Z6.js.map +0 -1
  57. package/.docu/lib/logger-DYmvFF1d.js.map +0 -1
  58. package/.docu/lib/server.impl-Cvoa6Diq.js.map +0 -1
@@ -3,46 +3,54 @@
3
3
  import { Moon, Sun } from "lucide-react";
4
4
  import { ThemeControllerToggle } from "@docubook/ui-react/theme-controller";
5
5
 
6
- interface ThemeToggleProps {
6
+ interface ThemeButtonsProps {
7
7
  className?: string;
8
+ isDark: boolean;
9
+ toggle?: (dark: boolean) => void;
8
10
  }
9
11
 
10
- export function ThemeToggle({ className }: ThemeToggleProps) {
12
+ function ThemeButtons({ className, isDark, toggle }: ThemeButtonsProps) {
13
+ return (
14
+ <div
15
+ className={`border-base-600 dark:border-base-content/20 bg-base-100/50 flex items-center gap-1 rounded-full border p-0.5 transition-all ${className || ""}`}
16
+ >
17
+ <button
18
+ type="button"
19
+ role="switch"
20
+ aria-label="Light mode"
21
+ aria-checked={!isDark}
22
+ onClick={toggle ? () => toggle(false) : undefined}
23
+ className="bg-primary cursor-pointer rounded-full p-0.5 transition-all dark:bg-transparent"
24
+ >
25
+ <Sun
26
+ className={`h-4 w-4 transition-colors ${
27
+ !isDark ? "text-primary-foreground" : "text-foreground"
28
+ }`}
29
+ />
30
+ </button>
31
+ <button
32
+ type="button"
33
+ role="switch"
34
+ aria-label="Dark mode"
35
+ aria-checked={isDark}
36
+ onClick={toggle ? () => toggle(true) : undefined}
37
+ className="dark:bg-primary cursor-pointer rounded-full p-0.5 transition-all"
38
+ >
39
+ <Moon
40
+ className={`h-4 w-4 transition-colors ${
41
+ isDark ? "text-primary-foreground" : "text-base-content/60"
42
+ }`}
43
+ />
44
+ </button>
45
+ </div>
46
+ );
47
+ }
48
+
49
+ export function ThemeToggle({ className }: { className?: string }) {
11
50
  return (
12
51
  <ThemeControllerToggle lightTheme="light" darkTheme="dark">
13
52
  {({ isDark, toggle }) => (
14
- <div
15
- className={`border-base-600 dark:border-base-content/20 bg-base-100/50 flex items-center gap-1 rounded-full border p-0.5 transition-all ${className || ""}`}
16
- >
17
- <button
18
- type="button"
19
- role="switch"
20
- aria-label="Light mode"
21
- aria-checked={!isDark}
22
- onClick={() => toggle(false)}
23
- className="bg-primary cursor-pointer rounded-full p-0.5 transition-all dark:bg-transparent"
24
- >
25
- <Sun
26
- className={`h-4 w-4 transition-colors ${
27
- !isDark ? "text-primary-foreground" : "text-foreground"
28
- }`}
29
- />
30
- </button>
31
- <button
32
- type="button"
33
- role="switch"
34
- aria-label="Dark mode"
35
- aria-checked={isDark}
36
- onClick={() => toggle(true)}
37
- className="dark:bg-primary cursor-pointer rounded-full p-0.5 transition-all"
38
- >
39
- <Moon
40
- className={`h-4 w-4 transition-colors ${
41
- isDark ? "text-primary-foreground" : "text-base-content/60"
42
- }`}
43
- />
44
- </button>
45
- </div>
53
+ <ThemeButtons className={className} isDark={isDark} toggle={toggle} />
46
54
  )}
47
55
  </ThemeControllerToggle>
48
56
  );
@@ -0,0 +1,31 @@
1
+ export function BackgroundBlobs() {
2
+ return (
3
+ <>
4
+ <div
5
+ aria-hidden="true"
6
+ className="pointer-events-none absolute -top-40 left-1/2 -z-10 -translate-x-1/2 blur-3xl sm:-top-80"
7
+ >
8
+ <div
9
+ style={{
10
+ clipPath:
11
+ "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
12
+ }}
13
+ className="from-primary to-accent h-[40rem] w-[80rem] bg-gradient-to-tr opacity-20"
14
+ />
15
+ </div>
16
+
17
+ <div
18
+ aria-hidden="true"
19
+ className="pointer-events-none absolute bottom-0 left-1/2 -z-10 translate-x-1/4 blur-3xl"
20
+ >
21
+ <div
22
+ style={{
23
+ clipPath:
24
+ "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
25
+ }}
26
+ className="from-accent to-primary h-[30rem] w-[70rem] bg-gradient-to-tr opacity-20"
27
+ />
28
+ </div>
29
+ </>
30
+ );
31
+ }
@@ -1,2 +1,3 @@
1
+ export { BackgroundBlobs } from "./BackgroundBlobs";
1
2
  export { Hero } from "./Hero";
2
3
  export { Features } from "./Features";
@@ -1,4 +1,4 @@
1
- import { n as runBuildCli } from "./build.impl-BBlR3si3.js";
1
+ import { n as runBuildCli } from "./build.impl-CsP6pPug.js";
2
2
  //#region .docu/node/build.deno.ts
3
3
  await runBuildCli();
4
4
  process.exit(0);
@@ -0,0 +1,2 @@
1
+ import { n as runBuildCli } from "./build.impl-CsP6pPug.js";
2
+ export { runBuildCli };
@@ -1,7 +1,7 @@
1
- import { a as DOCS_DIR, c as PROJECT_ROOT, d as loadDocuConfig, i as DOCS_ASSETS_DIR, n as CACHE_FILE, r as DIST_DIR, t as ASSETS_DIR } from "./paths-Bl2cdp9E.js";
2
- import { C as hashMdxSources, D as loadPlugins, E as BuildPluginBuilder, S as atomicWriteFile, T as runtimeStamp, _ as getPageStripped, a as IndexPage, b as buildClientBundle, c as captureException, d as clearDerivedPageCaches, f as compileMdx, g as getPageFrontmatter, h as getPageContent, i as DocsLayout, l as initSentry, m as frontmatterField, o as NotFoundPage, p as compileMdxModule, r as htmlShell, s as DocsPage, u as generateSearchIndex, v as registerPageContent, w as hookMemoryPressure, x as computeInlineThemeCss, y as getGitLastModifiedBatch } from "./html.shared-DBMwv_Z6.js";
1
+ import { a as DOCS_DIR, c as PAGES_DIR, f as loadDocuConfig, i as DOCS_ASSETS_DIR, l as PROJECT_ROOT, n as CACHE_FILE, r as DIST_DIR, t as ASSETS_DIR } from "./paths-Cbz-dj4s.js";
2
+ import { C as hashMdxSources, D as loadPlugins, E as BuildPluginBuilder, S as atomicWriteFile, T as runtimeStamp, _ as getPageStripped, a as IndexPage, b as buildClientBundle, c as captureException, d as clearDerivedPageCaches, f as compileMdx, g as getPageFrontmatter, h as getPageContent, i as DocsLayout, l as initSentry, m as frontmatterField, o as NotFoundPage, p as compileMdxModule, r as htmlShell, s as DocsPage, u as generateSearchIndex, v as registerPageContent, w as hookMemoryPressure, x as computeInlineThemeCss, y as getGitLastModifiedBatch } from "./html.shared-CsEFmy_Y.js";
3
3
  import { c as scanMdxFiles, d as cspHeader, p as generateNonce, s as resolveDocsIndexSource } from "./utils-B_CoyKie.js";
4
- import { t as logger } from "./logger-DYmvFF1d.js";
4
+ import { t as logger } from "./logger-DLU3A-z2.js";
5
5
  import { existsSync } from "node:fs";
6
6
  import { dirname, join } from "node:path";
7
7
  import { copyFile, mkdir, readFile, readdir, rename, unlink, writeFile } from "node:fs/promises";
@@ -60,7 +60,7 @@ async function readCache() {
60
60
  const data = await readFile(CACHE_FILE, "utf-8");
61
61
  const parsed = JSON.parse(data);
62
62
  const meta = parsed.__meta__;
63
- if (!meta || meta.version !== 4 || meta.runtime !== runtimeStamp()) return {};
63
+ if (!meta || meta.version !== 5 || meta.runtime !== runtimeStamp()) return {};
64
64
  return parsed;
65
65
  }
66
66
  } catch (err) {
@@ -70,10 +70,10 @@ async function readCache() {
70
70
  }
71
71
  function stampCache(cache) {
72
72
  cache.__meta__ = {
73
- hash: `4:${runtimeStamp()}`,
73
+ hash: `5:${runtimeStamp()}`,
74
74
  mtime: 0,
75
75
  builtAt: Date.now(),
76
- version: 4,
76
+ version: 5,
77
77
  runtime: runtimeStamp()
78
78
  };
79
79
  }
@@ -91,8 +91,15 @@ function shouldRebuild(path, mtime, cache) {
91
91
  return "no";
92
92
  }
93
93
  var assetManifest = {
94
- js: "client.js",
95
- css: "client.css"
94
+ docs: {
95
+ js: "client.js",
96
+ css: "docs.css"
97
+ },
98
+ home: {
99
+ js: "home-client.js",
100
+ css: "site.css"
101
+ },
102
+ notFound: { css: "site.css" }
96
103
  };
97
104
  /**
98
105
  * Reuse manifest.json on bundle cache hit; fall back to a full rebuild
@@ -102,10 +109,7 @@ async function resolveAssetManifest(bundleHit, mdxSources) {
102
109
  if (!bundleHit) return buildClientBundle(mdxSources);
103
110
  try {
104
111
  const manifest = JSON.parse(await readFile(join(ASSETS_DIR, "manifest.json"), "utf-8"));
105
- if (typeof manifest.js === "string" && typeof manifest.css === "string") return {
106
- js: manifest.js,
107
- css: manifest.css
108
- };
112
+ if (typeof manifest.docs?.js === "string" && typeof manifest.docs.css === "string" && typeof manifest.home?.js === "string" && typeof manifest.home.css === "string" && typeof manifest.notFound?.css === "string") return manifest;
109
113
  } catch {}
110
114
  return buildClientBundle(mdxSources);
111
115
  }
@@ -152,6 +156,8 @@ async function renderDocsPage(docuConfig, slug, rawMdx, filePath, gitDates, buil
152
156
  }));
153
157
  const body = renderToString(page);
154
158
  const ctx = {
159
+ pageType: "docs",
160
+ assets: assetManifest.docs,
155
161
  slug,
156
162
  filePath,
157
163
  frontmatter,
@@ -171,8 +177,8 @@ async function renderDocsPage(docuConfig, slug, rawMdx, filePath, gitDates, buil
171
177
  favicon,
172
178
  seo,
173
179
  csp,
174
- css: assetManifest.css,
175
- js: assetManifest.js,
180
+ css: ctx.assets.css,
181
+ js: ctx.assets.js,
176
182
  nonce,
177
183
  themeCss: inlineThemeCss,
178
184
  depth,
@@ -262,9 +268,10 @@ async function runBuild() {
262
268
  logger.bundleDone(Math.round(performance.now() - t));
263
269
  inlineThemeCss = computeInlineThemeCss();
264
270
  const lastManifest = cache["__assets__"];
265
- const assetsChanged = !isCacheEntry(lastManifest) || lastManifest.hash !== `${assetManifest.js}:${assetManifest.css}`;
271
+ const assetHash = JSON.stringify(assetManifest);
272
+ const assetsChanged = !isCacheEntry(lastManifest) || lastManifest.hash !== assetHash;
266
273
  if (assetsChanged) cache["__assets__"] = {
267
- hash: `${assetManifest.js}:${assetManifest.css}`,
274
+ hash: assetHash,
268
275
  mtime: 0,
269
276
  builtAt: Date.now()
270
277
  };
@@ -283,7 +290,7 @@ async function runBuild() {
283
290
  const errors = [];
284
291
  for (const file of mdxFiles) {
285
292
  const rebuildDecision = shouldRebuild(file.path, file.mtime, cache);
286
- if (rebuildDecision === "no") {
293
+ if (rebuildDecision === "no" && !builder) {
287
294
  const outputPath = join(DIST_DIR, "docs", `${file.path}.html`);
288
295
  if (existsSync(outputPath) && !assetsChanged) {
289
296
  skipped++;
@@ -297,7 +304,7 @@ async function runBuild() {
297
304
  if (err.code !== "ENOENT") throw err;
298
305
  continue;
299
306
  }
300
- if (rebuildDecision === "hash_check") {
307
+ if (rebuildDecision === "hash_check" && !builder) {
301
308
  const contentHash = hashContent(rawMdx);
302
309
  const cached = cache[file.path];
303
310
  if (isCacheEntry(cached) && cached.hash === contentHash) {
@@ -357,35 +364,56 @@ async function runBuild() {
357
364
  const landingFavicon = docuConfig.meta?.favicon || "/docs/assets/images/favicon.ico";
358
365
  const landingSeo = buildSeoMeta(docuConfig, docuConfig.meta, "");
359
366
  const landingNonce = generateNonce();
360
- const landingHtml = htmlShell({
367
+ const landingContext = {
368
+ pageType: "home",
369
+ assets: assetManifest.home,
370
+ slug: "",
371
+ filePath: join(PAGES_DIR, "index.tsx"),
372
+ frontmatter: { ...docuConfig.meta },
373
+ config: docuConfig
374
+ };
375
+ let landingHtml = htmlShell({
361
376
  title: docuConfig.meta?.title || "DocuBook",
362
377
  description: docuConfig.meta?.description || "",
363
378
  body: renderToString(landingPage),
364
379
  favicon: landingFavicon,
365
380
  seo: landingSeo,
366
381
  csp: cspHeader(landingNonce),
367
- css: assetManifest.css,
368
- js: assetManifest.js,
382
+ css: landingContext.assets.css,
383
+ js: landingContext.assets.js,
369
384
  nonce: landingNonce,
370
- themeCss: inlineThemeCss
385
+ themeCss: inlineThemeCss,
386
+ headExtra: builder?.collectHead(landingContext),
387
+ bodyExtra: builder?.collectBody(landingContext)
371
388
  });
389
+ if (builder) landingHtml = await builder.runTransformHtmlChain(landingHtml, landingContext);
372
390
  await writeFile(join(DIST_DIR, "index.html"), landingHtml);
373
- const notFoundPage = React.createElement(DocsLayout, { repoUrl: docuConfig.repo?.url }, React.createElement(NotFoundPage));
391
+ const notFoundPage = React.createElement(NotFoundPage);
374
392
  const notFoundFavicon = docuConfig.meta?.favicon || "/docs/assets/images/favicon.ico";
375
393
  const notFoundNonce = generateNonce();
376
- const notFoundHtml = htmlShell({
394
+ const notFoundContext = {
395
+ pageType: "notFound",
396
+ assets: assetManifest.notFound,
397
+ slug: "404",
398
+ filePath: join(PAGES_DIR, "404.tsx"),
399
+ frontmatter: {},
400
+ config: docuConfig
401
+ };
402
+ let notFoundHtml = htmlShell({
377
403
  title: "404 - Not Found",
378
404
  description: "",
379
405
  body: renderToString(notFoundPage),
380
406
  favicon: notFoundFavicon,
381
- headExtra: ["<meta name=\"robots\" content=\"noindex,follow\">"],
407
+ headExtra: ["<meta name=\"robots\" content=\"noindex,follow\">", ...builder?.collectHead(notFoundContext) ?? []],
408
+ bodyExtra: builder?.collectBody(notFoundContext),
382
409
  csp: cspHeader(notFoundNonce),
383
- css: assetManifest.css,
384
- js: assetManifest.js,
410
+ css: notFoundContext.assets.css,
411
+ js: notFoundContext.assets.js,
385
412
  nonce: notFoundNonce,
386
413
  themeCss: inlineThemeCss,
387
414
  absoluteAssets: true
388
415
  });
416
+ if (builder) notFoundHtml = await builder.runTransformHtmlChain(notFoundHtml, notFoundContext);
389
417
  await writeFile(join(DIST_DIR, "404.html"), notFoundHtml);
390
418
  logger.spinner.stop(`Built ${built} pages (${skipped} cached) \x1b[90m(${Math.round(performance.now() - t)}ms)\x1b[0m`);
391
419
  if (builder) {
@@ -395,7 +423,10 @@ async function runBuild() {
395
423
  filePath: join(DOCS_DIR, f.path),
396
424
  outputPath: join(DIST_DIR, "docs", `${f.path}.html`)
397
425
  }));
398
- await builder.runOnEnd(pages);
426
+ await builder.runOnEnd(pages, {
427
+ assetManifest,
428
+ outDir: DIST_DIR
429
+ });
399
430
  }
400
431
  logger.indexStart();
401
432
  t = performance.now();
@@ -422,4 +453,4 @@ async function runBuildCli() {
422
453
  //#endregion
423
454
  export { runBuildCli as n, runBuild as t };
424
455
 
425
- //# sourceMappingURL=build.impl-BBlR3si3.js.map
456
+ //# sourceMappingURL=build.impl-CsP6pPug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.impl-CsP6pPug.js","names":[],"sources":["../node/types.ts","../node/seo.ts","../node/build.impl.ts"],"sourcesContent":["import type { ThemeConfig } from \"@docubook/themes-colors\";\nimport type { PluginEntry } from \"./plugin\";\n\nexport interface DocuRouteContext {\n title?: string;\n icon?: string;\n description?: string;\n}\n\nexport interface DocuRoute {\n title: string;\n href: string;\n noLink?: boolean;\n items?: DocuRoute[];\n context?: DocuRouteContext;\n}\n\nexport interface DocuMeta {\n title: string;\n description: string;\n baseURL: string;\n favicon?: string;\n /** Default OG image path (e.g. /docs/assets/images/og.png). Used when page frontmatter has no image. */\n ogImage?: string;\n}\n\nexport interface SocialLink {\n name: string;\n url: string;\n}\n\nexport interface DocuNavbar {\n logoText: string;\n logo?: { src?: string; alt?: string };\n menu: { title: string; href: string }[];\n}\n\nexport interface DocuFooter {\n social: SocialLink[];\n}\n\nexport interface DocuSidebar {\n /** How context sections are displayed.\n * \"dropdown\" — context switcher dropdown (default)\n * \"separator\" — inline group headers in sidebar */\n context?: \"dropdown\" | \"separator\";\n}\n\nexport interface RepoConfig {\n url: string;\n path: string;\n edit: boolean;\n}\n\nexport interface HeroAction {\n text: string;\n link: string;\n theme?: \"primary\" | \"secondary\" | \"ghost\";\n icon?: string;\n}\n\nexport interface Hero {\n tagline?: string;\n headline: string;\n description?: string;\n actions?: HeroAction[];\n}\n\nexport interface HomeFeature {\n icon?: string;\n title: string;\n description: string;\n link?: string;\n}\n\nexport interface HomeConfig {\n hero?: Hero;\n features?: HomeFeature[];\n}\n\nexport interface DocuConfig {\n meta: DocuMeta;\n home?: HomeConfig;\n navbar: DocuNavbar;\n footer: DocuFooter;\n repo: RepoConfig;\n sidebar?: DocuSidebar;\n routes: DocuRoute[];\n themes?: {\n colors: ThemeConfig;\n };\n /** List of DocuBook plugins to load. Empty by default — no-op when absent. */\n plugins?: PluginEntry[];\n}\n\nexport interface AssetEntry {\n css: string;\n js?: string;\n}\n\nexport interface AssetManifest {\n docs: AssetEntry;\n home: AssetEntry;\n notFound: AssetEntry;\n}\n\nexport interface BuildCacheEntry {\n hash: string;\n mtime: number;\n builtAt: number;\n}\n\n/** Version stamp stored as `__meta__` — extends entry so the index signature stays valid. */\nexport interface BuildCacheMeta extends BuildCacheEntry {\n version: number;\n runtime: string;\n}\n\nexport interface BuildCache {\n [path: string]: BuildCacheEntry | undefined;\n __meta__?: BuildCacheMeta;\n __assets__?: BuildCacheEntry;\n __bundle__?: BuildCacheEntry;\n}\n\n/** Narrow a cache slot to a real page/asset entry (guards `__meta__` shape). */\nexport function isCacheEntry(value: unknown): value is BuildCacheEntry {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Record<string, unknown>;\n return typeof v.hash === \"string\" && typeof v.mtime === \"number\" && typeof v.builtAt === \"number\";\n}\n\nexport interface CliArgs {\n force?: boolean;\n clean?: boolean;\n ssr?: boolean;\n}\n\nexport interface ParsedDoc {\n compiledSource: string;\n frontmatter: Record<string, unknown>;\n raw: string;\n scope?: Record<string, unknown>;\n}\n\nexport type { TocItem } from \"@docubook/core\";\n","import type { DocuConfig } from \"./types\";\nimport { frontmatterField } from \"./mdx\";\n\nexport interface SeoMeta {\n /** Absolute canonical URL */\n url: string;\n /** Site name for og:site_name */\n siteName: string;\n /** Absolute OG image URL (from frontmatter.image, if set) */\n image?: string;\n}\n\n/**\n * Build SEO metadata from config and per-page frontmatter.\n * All fields are derived from existing data — no extra config required.\n */\nexport function buildSeoMeta(\n config: DocuConfig,\n frontmatter: Record<string, unknown>,\n slug: string\n): SeoMeta {\n const baseURL = config.meta?.baseURL?.replace(/\\/+$/, \"\") || \"\";\n const url = slug ? `${baseURL}/docs/${slug}` : `${baseURL}/`;\n\n const result: SeoMeta = {\n url,\n siteName: config.meta?.title || \"\",\n };\n\n // Per-page image from frontmatter, fallback to global default from config\n const image = frontmatterField(frontmatter, \"image\") || config.meta?.ogImage;\n if (image) {\n // Resolve using URL constructor — handles absolute, root-relative, and relative paths\n try {\n result.image = new URL(image, image.startsWith(\"/\") ? baseURL : `${baseURL}/docs/`).href;\n } catch {\n result.image = image;\n }\n }\n\n return result;\n}\n","/**\n * Runtime-neutral static build — mirror of `build.ts` (Bun-only via its\n * transitive imports, protected) with the Bun-coupled modules swapped for\n * their neutral counterparts: `html.shared` (pure escaping) and\n * `hydrate.node` (esbuild client bundling). Everything else is identical.\n * The Node/Deno build entries call `runBuildCli()`.\n */\n\nimport { readFile, writeFile, mkdir, readdir, copyFile, rename, unlink } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join, dirname } from \"node:path\";\nimport React from \"react\";\nimport { renderToString } from \"react-dom/server\";\nimport {\n compileMdx,\n compileMdxModule,\n frontmatterField,\n getGitLastModifiedBatch,\n getPageContent,\n getPageFrontmatter,\n getPageStripped,\n registerPageContent,\n} from \"./mdx\";\nimport {\n DOCS_DIR,\n DIST_DIR,\n ASSETS_DIR,\n CACHE_FILE,\n DOCS_ASSETS_DIR,\n PROJECT_ROOT,\n PAGES_DIR,\n loadDocuConfig,\n} from \"./paths\";\nimport { htmlShell } from \"./html.shared\";\nimport { generateSearchIndex } from \"./search-indexer\";\nimport { buildClientBundle, computeInlineThemeCss } from \"./hydrate.node\";\nimport { logger } from \"./logger\";\nimport { initSentry, captureException } from \"./sentry\";\nimport { loadPlugins } from \"./plugin-loader\";\nimport { BuildPluginBuilder } from \"./plugin-builder\";\nimport { scanMdxFiles, resolveDocsIndexSource, DEFAULT_FAVICON } from \"./utils\";\nimport type { AssetManifest, BuildCache, BuildCacheMeta, CliArgs } from \"./types\";\nimport { isCacheEntry } from \"./types\";\nimport {\n BUILD_CACHE_VERSION,\n atomicWriteFile,\n hashMdxSources,\n hookMemoryPressure,\n runtimeStamp,\n} from \"./cache-key\";\nimport { clearDerivedPageCaches } from \"./mdx\";\nimport { generateNonce, cspHeader } from \"./security\";\nimport type { PageMeta, PageContext } from \"./plugin\";\nimport { buildSeoMeta } from \"./seo\";\nimport DocsPage from \"../pages/docs/[[...slug]]\";\nimport IndexPage from \"../pages/index\";\nimport NotFoundPage from \"../pages/404\";\nimport { DocsLayout } from \"../components/DocsLayout\";\n\nfunction parseArgs(): CliArgs {\n const args = process.argv.slice(2);\n return {\n force: args.includes(\"--force\") || args.includes(\"-f\"),\n clean: args.includes(\"--clean\") || args.includes(\"-c\"),\n };\n}\n\nfunction hashContent(content: string): string {\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nasync function readCache(): Promise<BuildCache> {\n try {\n if (existsSync(CACHE_FILE)) {\n const data = await readFile(CACHE_FILE, \"utf-8\");\n const parsed = JSON.parse(data) as BuildCache;\n const meta = parsed.__meta__ as BuildCacheMeta | undefined;\n if (!meta || meta.version !== BUILD_CACHE_VERSION || meta.runtime !== runtimeStamp()) {\n return {};\n }\n return parsed;\n }\n } catch (err) {\n console.error(\"Failed to load build cache:\", (err as Error).message);\n }\n return {};\n}\n\nfunction stampCache(cache: BuildCache): void {\n cache.__meta__ = {\n hash: `${BUILD_CACHE_VERSION}:${runtimeStamp()}`,\n mtime: 0,\n builtAt: Date.now(),\n version: BUILD_CACHE_VERSION,\n runtime: runtimeStamp(),\n };\n}\n\nasync function writeCache(cache: BuildCache): Promise<void> {\n stampCache(cache);\n await atomicWriteFile(writeFile, rename, unlink, CACHE_FILE, JSON.stringify(cache, null, 2));\n}\n\nfunction parseConcurrency(): number {\n return Math.max(1, parseInt(process.env.BUILD_CONCURRENCY || \"4\", 10) || 4);\n}\n\ntype RebuildDecision = \"yes\" | \"hash_check\" | \"no\";\n\nfunction shouldRebuild(path: string, mtime: number, cache: BuildCache): RebuildDecision {\n const cached = cache[path];\n if (!isCacheEntry(cached)) return \"yes\";\n // Any mtime drift vs the recorded one — a newer edit, or mtime moving\n // backwards (rsync -a, cp -p, snapshot restore) — falls through to the\n // hash check: hashing an unchanged file is cheap, serving a stale page\n // is not. Only an untouched mtime skips without reading the file.\n if (mtime !== cached.mtime) return \"hash_check\";\n return \"no\";\n}\n\nlet assetManifest: AssetManifest = {\n docs: { js: \"client.js\", css: \"docs.css\" },\n home: { js: \"home-client.js\", css: \"site.css\" },\n notFound: { css: \"site.css\" },\n};\n\n/**\n * Reuse manifest.json on bundle cache hit; fall back to a full rebuild\n * when the manifest is missing or malformed.\n */\nasync function resolveAssetManifest(\n bundleHit: boolean,\n mdxSources: Record<string, string>\n): Promise<AssetManifest> {\n if (!bundleHit) return buildClientBundle(mdxSources);\n try {\n const manifest = JSON.parse(\n await readFile(join(ASSETS_DIR, \"manifest.json\"), \"utf-8\")\n ) as Partial<AssetManifest>;\n if (\n typeof manifest.docs?.js === \"string\" &&\n typeof manifest.docs.css === \"string\" &&\n typeof manifest.home?.js === \"string\" &&\n typeof manifest.home.css === \"string\" &&\n typeof manifest.notFound?.css === \"string\"\n ) {\n return manifest as AssetManifest;\n }\n } catch {\n // corrupt/missing manifest — rebuild below\n }\n return buildClientBundle(mdxSources);\n}\n\nlet inlineThemeCss: string | undefined;\n\nasync function renderDocsPage(\n docuConfig: ReturnType<typeof loadDocuConfig>,\n slug: string,\n rawMdx: string,\n filePath: string,\n gitDates?: Map<string, string>,\n builder?: BuildPluginBuilder | null,\n nonce?: string\n): Promise<string> {\n let content = rawMdx;\n if (builder) {\n const transformed = await builder.runOnLoad(filePath, content);\n if (transformed?.contents) {\n content = transformed.contents;\n }\n }\n\n let result;\n try {\n const remarkPlugins = builder?.collectRemarkPlugins();\n const rehypePlugins = builder?.collectRehypePlugins();\n // Parse-once: reuse the prePass frontmatter + stripped content so the\n // SSR phase does not re-extract them. Only when the prePass actually\n // registered them — otherwise compileMdx does its own extraction.\n const preFm = getPageFrontmatter(`/${slug}`);\n const preStripped = getPageStripped(`/${slug}`);\n const pre =\n preFm !== undefined && preStripped !== undefined\n ? { frontmatter: preFm, strippedContent: preStripped }\n : undefined;\n result = await compileMdx(\n content,\n filePath,\n gitDates,\n remarkPlugins,\n rehypePlugins,\n undefined,\n pre\n );\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Unknown MDX error\";\n throw new Error(`MDX Error in: docs/${slug}.mdx\\n${msg}`, { cause: err });\n }\n\n let frontmatter = result.frontmatter as Record<string, unknown>;\n if (builder) {\n frontmatter = await builder.runTransformFrontmatterChain(frontmatter, {\n slug,\n filePath,\n content,\n });\n }\n\n const title = frontmatterField(frontmatter, \"title\") || slug || \"Docs\";\n const description = frontmatterField(frontmatter, \"description\");\n const slugParts = slug ? slug.split(\"/\") : [];\n\n const page = React.createElement(\n DocsLayout,\n { repoUrl: docuConfig.repo?.url },\n React.createElement(DocsPage, {\n slug: slugParts,\n title,\n description,\n date: frontmatterField(frontmatter, \"date\") || undefined,\n // Render MDX content as its own root: client hydrates the island as a\n // separate root, so SSR must be root-relative too or useId-based ids\n // (mdx-compiler components) mismatch during hydration.\n content: renderToString(result.content),\n tocs: result.tocs,\n filePath,\n repoUrl: docuConfig.repo?.url,\n mdxSlug: slug,\n })\n );\n\n const body = renderToString(page);\n\n const ctx: PageContext = {\n pageType: \"docs\",\n assets: assetManifest.docs,\n slug,\n filePath,\n frontmatter,\n content,\n config: docuConfig,\n };\n const headExtra = builder?.collectHead(ctx);\n const bodyExtra = builder?.collectBody(ctx);\n\n const depth = slug ? slug.split(\"/\").length : 1;\n const favicon = docuConfig.meta?.favicon || DEFAULT_FAVICON;\n const seo = buildSeoMeta(docuConfig, frontmatter, slug || \"\");\n // MDX content hydrates from the bundled ESM module (mdx-hydrate), not\n // new Function — no 'unsafe-eval' needed in the CSP.\n const csp = nonce ? cspHeader(nonce) : undefined;\n let html = htmlShell({\n title,\n description,\n body,\n favicon,\n seo,\n csp,\n css: ctx.assets.css,\n js: ctx.assets.js,\n nonce,\n themeCss: inlineThemeCss,\n depth,\n headExtra,\n bodyExtra,\n });\n\n if (builder) {\n html = await builder.runTransformHtmlChain(html, ctx);\n }\n\n return html;\n}\n\nasync function copyDirectoryRecursive(src: string, dest: string): Promise<void> {\n if (!existsSync(src)) return;\n await mkdir(dest, { recursive: true });\n const entries = await readdir(src, { withFileTypes: true });\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n if (entry.isDirectory()) {\n await copyDirectoryRecursive(srcPath, destPath);\n } else {\n await copyFile(srcPath, destPath);\n }\n }\n}\n\nexport async function runBuild(): Promise<void> {\n const docuConfig = loadDocuConfig();\n const args = parseArgs();\n\n hookMemoryPressure(clearDerivedPageCaches);\n\n logger.buildStart();\n\n if (args.clean) {\n const { rm } = await import(\"node:fs/promises\");\n try {\n await rm(DIST_DIR, { recursive: true, force: true });\n } catch (err) {\n console.error(\"Failed to clean dist directory:\", (err as Error).message);\n }\n }\n\n await mkdir(DIST_DIR, { recursive: true });\n await mkdir(ASSETS_DIR, { recursive: true });\n\n await copyDirectoryRecursive(DOCS_ASSETS_DIR, join(DIST_DIR, \"docs\", \"assets\"));\n\n const mdxFiles = await scanMdxFiles(DOCS_DIR);\n const cache = args.force ? {} : await readCache();\n let built = 0;\n let skipped = 0;\n\n const pluginsConfig = docuConfig.plugins ?? [];\n const builder = pluginsConfig.length > 0 ? new BuildPluginBuilder(docuConfig) : null;\n if (builder) {\n const plugins = await loadPlugins(pluginsConfig);\n for (const plugin of plugins) {\n await plugin.setup(builder);\n }\n await builder.runOnStart();\n }\n\n // Pre-compile every page's MDX to an ESM module (program format) so the\n // client bundle can hydrate the content island statically — no new Function.\n // Mirrors the page loop's transform + plugin chain so SSR and client trees\n // match. Runs for all files regardless of cache; the bundle is shared by\n // every page, so a content change invalidates the page cache anyway.\n const mdxSources: Record<string, string> = {};\n const prePassTasks = mdxFiles.map(async (file) => {\n let raw: string;\n try {\n raw = await readFile(file.absPath, \"utf-8\");\n } catch {\n return;\n }\n // Cache the original content so the page loop does not re-read the file\n // (one disk read per file — the frontmatter is parsed once here too).\n registerPageContent(`/${file.path}`, raw);\n let content = raw;\n if (builder) {\n const relPath = file.absPath.replace(PROJECT_ROOT + \"/\", \"\");\n const transformed = await builder.runOnLoad(relPath, content);\n if (transformed?.contents) content = transformed.contents;\n }\n const remarkPlugins = builder?.collectRemarkPlugins();\n const rehypePlugins = builder?.collectRehypePlugins();\n mdxSources[file.path] = await compileMdxModule(\n content,\n remarkPlugins,\n rehypePlugins,\n `/${file.path}`\n );\n });\n await Promise.all(prePassTasks);\n\n // The docs root (index.mdx, or index.md) renders with slug \"\" — mirror that\n // key so the index page hydrates too. Its render has its own try/catch; skip\n // on error.\n const indexSource = resolveDocsIndexSource(DOCS_DIR);\n if (indexSource) {\n try {\n const indexRaw = await readFile(indexSource, \"utf-8\");\n let indexContent = indexRaw;\n if (builder) {\n const relPath = indexSource.replace(PROJECT_ROOT + \"/\", \"\");\n const transformed = await builder.runOnLoad(relPath, indexContent);\n if (transformed?.contents) indexContent = transformed.contents;\n }\n mdxSources[\"\"] = await compileMdxModule(\n indexContent,\n builder?.collectRemarkPlugins(),\n builder?.collectRehypePlugins()\n );\n } catch {\n // ignore — the index render reports its own error\n }\n }\n\n logger.bundleStart();\n let t = performance.now();\n // Skip the JS bundle when compiled MDX sources are unchanged: the bundle\n // is shared by every page, so its hash doubles as the content fingerprint.\n // CSS still builds via its own content-keyed cache inside the hydrator.\n const bundleHash = hashMdxSources(mdxSources);\n const lastBundle = cache[\"__bundle__\"];\n const bundleHit =\n isCacheEntry(lastBundle) &&\n lastBundle.hash === bundleHash &&\n existsSync(join(ASSETS_DIR, \"manifest.json\"));\n assetManifest = await resolveAssetManifest(bundleHit, mdxSources);\n logger.bundleDone(Math.round(performance.now() - t));\n\n inlineThemeCss = computeInlineThemeCss();\n\n const lastManifest = cache[\"__assets__\"];\n const assetHash = JSON.stringify(assetManifest);\n const assetsChanged = !isCacheEntry(lastManifest) || lastManifest.hash !== assetHash;\n if (assetsChanged) {\n cache[\"__assets__\"] = { hash: assetHash, mtime: 0, builtAt: Date.now() };\n }\n if (!bundleHit) {\n cache[\"__bundle__\"] = { hash: bundleHash, mtime: 0, builtAt: Date.now() };\n }\n\n logger.spinner.start(\"Building pages...\");\n t = performance.now();\n\n const allRelPaths = mdxFiles.map((f) => f.absPath.replace(PROJECT_ROOT + \"/\", \"\"));\n\n if (indexSource) {\n allRelPaths.push(indexSource.replace(PROJECT_ROOT + \"/\", \"\"));\n }\n const gitDates = await getGitLastModifiedBatch(allRelPaths);\n\n const CONCURRENCY = parseConcurrency();\n const buildTasks = [];\n const errors: string[] = [];\n\n for (const file of mdxFiles) {\n const rebuildDecision = shouldRebuild(file.path, file.mtime, cache);\n\n if (rebuildDecision === \"no\" && !builder) {\n const outputPath = join(DIST_DIR, \"docs\", `${file.path}.html`);\n if (existsSync(outputPath) && !assetsChanged) {\n skipped++;\n continue;\n }\n }\n\n let rawMdx = getPageContent(`/${file.path}`);\n if (rawMdx === undefined) {\n try {\n rawMdx = await readFile(file.absPath, \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\n continue;\n }\n }\n\n if (rebuildDecision === \"hash_check\" && !builder) {\n const contentHash = hashContent(rawMdx);\n const cached = cache[file.path];\n if (isCacheEntry(cached) && cached.hash === contentHash) {\n if (!assetsChanged) {\n const outputPath = join(DIST_DIR, \"docs\", `${file.path}.html`);\n if (existsSync(outputPath)) {\n cache[file.path] = { ...cached, mtime: file.mtime, builtAt: Date.now() };\n skipped++;\n continue;\n }\n }\n }\n }\n\n const relPath = file.absPath.replace(PROJECT_ROOT + \"/\", \"\");\n const capturedRawMdx = rawMdx;\n const capturedFile = file;\n\n buildTasks.push(async () => {\n try {\n const pageNonce = generateNonce();\n const html = await renderDocsPage(\n docuConfig,\n capturedFile.path,\n capturedRawMdx,\n relPath,\n gitDates,\n builder,\n pageNonce\n );\n const outputPath = join(DIST_DIR, \"docs\", `${capturedFile.path}.html`);\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, html);\n cache[capturedFile.path] = {\n hash: hashContent(capturedRawMdx),\n mtime: capturedFile.mtime,\n builtAt: Date.now(),\n };\n built++;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n errors.push(msg);\n console.error(`\\n\\u274C ${msg}\\n`);\n }\n });\n }\n\n for (let i = 0; i < buildTasks.length; i += CONCURRENCY) {\n await Promise.all(buildTasks.slice(i, i + CONCURRENCY).map((fn) => fn()));\n }\n\n if (indexSource) {\n try {\n const indexRaw = await readFile(indexSource, \"utf-8\");\n const indexRelPath = indexSource.replace(PROJECT_ROOT + \"/\", \"\");\n const indexHtml = await renderDocsPage(\n docuConfig,\n \"\",\n indexRaw,\n indexRelPath,\n gitDates,\n builder,\n generateNonce()\n );\n await mkdir(join(DIST_DIR, \"docs\"), { recursive: true });\n await writeFile(join(DIST_DIR, \"docs\", \"index.html\"), indexHtml);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n errors.push(`index: ${msg}`);\n console.error(`\\n❌ Failed to build index: ${msg}\\n`);\n }\n } else {\n const msg = \"docs root index: docs/index.mdx (or docs/index.md) not found\";\n errors.push(`index: ${msg}`);\n console.error(`\\n❌ Failed to build index: ${msg}\\n`);\n }\n\n const landingPage = React.createElement(IndexPage);\n const landingFavicon = docuConfig.meta?.favicon || DEFAULT_FAVICON;\n const landingSeo = buildSeoMeta(\n docuConfig,\n docuConfig.meta as unknown as Record<string, unknown>,\n \"\"\n );\n const landingNonce = generateNonce();\n const landingContext: PageContext = {\n pageType: \"home\",\n assets: assetManifest.home,\n slug: \"\",\n filePath: join(PAGES_DIR, \"index.tsx\"),\n frontmatter: { ...docuConfig.meta } as unknown as Record<string, unknown>,\n config: docuConfig,\n };\n let landingHtml = htmlShell({\n title: docuConfig.meta?.title || \"DocuBook\",\n description: docuConfig.meta?.description || \"\",\n body: renderToString(landingPage),\n favicon: landingFavicon,\n seo: landingSeo,\n csp: cspHeader(landingNonce),\n css: landingContext.assets.css,\n js: landingContext.assets.js,\n nonce: landingNonce,\n themeCss: inlineThemeCss,\n headExtra: builder?.collectHead(landingContext),\n bodyExtra: builder?.collectBody(landingContext),\n });\n if (builder) landingHtml = await builder.runTransformHtmlChain(landingHtml, landingContext);\n await writeFile(join(DIST_DIR, \"index.html\"), landingHtml);\n\n const notFoundPage = React.createElement(NotFoundPage);\n const notFoundFavicon = docuConfig.meta?.favicon || DEFAULT_FAVICON;\n const notFoundNonce = generateNonce();\n const notFoundContext: PageContext = {\n pageType: \"notFound\",\n assets: assetManifest.notFound,\n slug: \"404\",\n filePath: join(PAGES_DIR, \"404.tsx\"),\n frontmatter: {},\n config: docuConfig,\n };\n let notFoundHtml = htmlShell({\n title: \"404 - Not Found\",\n description: \"\",\n body: renderToString(notFoundPage),\n favicon: notFoundFavicon,\n headExtra: [\n '<meta name=\"robots\" content=\"noindex,follow\">',\n ...(builder?.collectHead(notFoundContext) ?? []),\n ],\n bodyExtra: builder?.collectBody(notFoundContext),\n csp: cspHeader(notFoundNonce),\n css: notFoundContext.assets.css,\n js: notFoundContext.assets.js,\n nonce: notFoundNonce,\n themeCss: inlineThemeCss,\n // Served as the static-host fallback at ANY requested path — relative\n // depth can never be right there, so use root-absolute asset URLs.\n absoluteAssets: true,\n });\n if (builder) notFoundHtml = await builder.runTransformHtmlChain(notFoundHtml, notFoundContext);\n await writeFile(join(DIST_DIR, \"404.html\"), notFoundHtml);\n\n logger.spinner.stop(\n `Built ${built} pages (${skipped} cached) \\x1b[90m(${Math.round(performance.now() - t)}ms)\\x1b[0m`\n );\n\n if (builder) {\n const pages: PageMeta[] = mdxFiles.map((f) => ({\n slug: f.path,\n title: f.path.split(\"/\").pop() || f.path,\n filePath: join(DOCS_DIR, f.path),\n outputPath: join(DIST_DIR, \"docs\", `${f.path}.html`),\n }));\n await builder.runOnEnd(pages, { assetManifest, outDir: DIST_DIR });\n }\n\n logger.indexStart();\n t = performance.now();\n // No content changed (all pages cached) → the aggregated index is\n // unchanged too; reuse the existing file instead of regenerating it.\n const indexSkipped = built === 0 && existsSync(join(ASSETS_DIR, \"search-index.json\"));\n const indexCount = indexSkipped ? 0 : await generateSearchIndex();\n logger.indexDone(indexCount, Math.round(performance.now() - t), indexSkipped);\n\n logger.routes();\n\n await writeCache(cache);\n\n if (errors.length > 0) {\n console.error(`\\n\\u274C Build completed with ${errors.length} error(s)\\n`);\n process.exit(1);\n }\n}\n\nexport async function runBuildCli(): Promise<void> {\n try {\n await initSentry();\n await runBuild();\n } catch (err) {\n captureException(err);\n console.error(\"Build failed:\", err);\n process.exit(1);\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as runBuildCli } from "./build.impl-BBlR3si3.js";
1
+ import { n as runBuildCli } from "./build.impl-CsP6pPug.js";
2
2
  //#region .docu/node/build.node.ts
3
3
  await runBuildCli();
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { t as logger } from "./logger-DYmvFF1d.js";
1
+ import { t as logger } from "./logger-DLU3A-z2.js";
2
2
  import { existsSync } from "node:fs";
3
3
  import { rm } from "node:fs/promises";
4
4
  //#region .docu/node/clean.ts
@@ -1,4 +1,4 @@
1
- import { t as runDeploy } from "./deploy.shared-Dxv3lsOb.js";
1
+ import { t as runDeploy } from "./deploy.shared-CsEa3L1D.js";
2
2
  //#region .docu/node/deploy.deno.ts
3
3
  try {
4
4
  await runDeploy();
@@ -1,4 +1,4 @@
1
- import { t as runDeploy } from "./deploy.shared-Dxv3lsOb.js";
1
+ import { t as runDeploy } from "./deploy.shared-CsEa3L1D.js";
2
2
  //#region .docu/node/deploy.node.ts
3
3
  runDeploy().catch((err) => {
4
4
  console.error("Deploy failed:", err);
@@ -1,4 +1,4 @@
1
- import { c as PROJECT_ROOT, o as FRAMEWORK_ROOT, r as DIST_DIR } from "./paths-Bl2cdp9E.js";
1
+ import { l as PROJECT_ROOT, o as FRAMEWORK_ROOT, r as DIST_DIR } from "./paths-Cbz-dj4s.js";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
4
  import { mkdir, writeFile } from "node:fs/promises";
@@ -12,7 +12,7 @@ import { mkdir, writeFile } from "node:fs/promises";
12
12
  * Mirror of deploy.ts (Bun-only, protected) for Node.js and Deno.
13
13
  * Runs the neutral build in-process, then prepares .docu/dist.
14
14
  */
15
- var FLAME_MAJOR = JSON.parse(readFileSync(resolve(FRAMEWORK_ROOT, "package.json"), "utf-8")).version.split(".")[0];
15
+ var FLAME_VERSION = JSON.parse(readFileSync(resolve(FRAMEWORK_ROOT, "package.json"), "utf-8")).version;
16
16
  var WORKFLOW_DIR = join(PROJECT_ROOT, ".github/workflows");
17
17
  var WORKFLOW_FILE = join(WORKFLOW_DIR, "deploy.yml");
18
18
  var NGINX_CONF = `server {
@@ -20,6 +20,7 @@ var NGINX_CONF = `server {
20
20
  server_name _;
21
21
  root /usr/share/nginx/html;
22
22
  index index.html;
23
+ error_page 404 /404.html;
23
24
 
24
25
  gzip on;
25
26
  gzip_types text/html text/css application/javascript image/svg+xml;
@@ -32,6 +33,16 @@ var NGINX_CONF = `server {
32
33
  add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
33
34
  add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'" always;
34
35
 
36
+ # Build metadata and search content use stable URLs, so clients must revalidate them.
37
+ location = /assets/manifest.json {
38
+ expires -1;
39
+ }
40
+
41
+ location = /assets/search-index.json {
42
+ expires -1;
43
+ }
44
+
45
+ # Generated JS, CSS, and chunks include content hashes in their filenames.
35
46
  location /assets/ {
36
47
  expires 1y;
37
48
  add_header Cache-Control "public, immutable";
@@ -54,6 +65,8 @@ var NGINX_CONF = `server {
54
65
  add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'" always;
55
66
  }
56
67
 
68
+ location = /404.html { }
69
+
57
70
  location / {
58
71
  try_files $uri $uri.html $uri/ =404;
59
72
  }
@@ -68,6 +81,18 @@ var DOCKERIGNORE = `node_modules
68
81
  .npmrc
69
82
  *.log
70
83
  `;
84
+ var DOCKERFILE = `FROM ghcr.io/docubook/flame:${FLAME_VERSION} AS builder
85
+ ENV NODE_ENV=production
86
+ WORKDIR /app
87
+ COPY . .
88
+ RUN flame build --bun
89
+
90
+ FROM nginx:alpine
91
+ COPY --from=builder /app/.docu/dist /usr/share/nginx/html
92
+ COPY nginx.conf /etc/nginx/conf.d/default.conf
93
+ EXPOSE 80
94
+ CMD ["nginx", "-g", "daemon off;"]
95
+ `;
71
96
  function detectPkgManager(dir) {
72
97
  const bunLockFile = existsSync(join(dir, "bun.lock")) ? "bun.lock" : existsSync(join(dir, "bun.lockb")) ? "bun.lockb" : null;
73
98
  if (bunLockFile) return {
@@ -111,8 +136,22 @@ var HEADERS_FILE = `/*
111
136
  Permissions-Policy: camera=(), microphone=(), geolocation=()
112
137
  Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'
113
138
 
114
- /assets/*
139
+ /assets/client-*
115
140
  Cache-Control: public, max-age=31536000, immutable
141
+ /assets/home-client-*
142
+ Cache-Control: public, max-age=31536000, immutable
143
+ /assets/docs-*
144
+ Cache-Control: public, max-age=31536000, immutable
145
+ /assets/site-*
146
+ Cache-Control: public, max-age=31536000, immutable
147
+ /assets/chunks/*
148
+ Cache-Control: public, max-age=31536000, immutable
149
+ /assets/assets/*
150
+ Cache-Control: public, max-age=31536000, immutable
151
+ /assets/manifest.json
152
+ Cache-Control: no-cache
153
+ /assets/search-index.json
154
+ Cache-Control: no-cache
116
155
  `;
117
156
  var isDocker = !!process.env.FLAME_DEPLOY_DOCKER;
118
157
  var isSilent = !!process.env.FLAME_DEPLOY_SILENT;
@@ -135,24 +174,13 @@ async function runBuild() {
135
174
  process.env.FLAME_BUILD_SILENT = "1";
136
175
  process.env.LOG_LEVEL = "error";
137
176
  }
138
- const { runBuildCli } = await import("./build.impl-DpoDUmei.js");
177
+ const { runBuildCli } = await import("./build.impl--Pm9uO30.js");
139
178
  await runBuildCli();
140
179
  }
141
180
  async function writeDockerFiles() {
142
181
  const dockerDir = PROJECT_ROOT;
143
182
  if (!existsSync(join(dockerDir, "Dockerfile"))) {
144
- await writeFile(join(dockerDir, "Dockerfile"), `FROM ghcr.io/docubook/flame:${FLAME_MAJOR} AS builder
145
- ENV NODE_ENV=production
146
- WORKDIR /app
147
- COPY . .
148
- RUN flame build
149
-
150
- FROM nginx:alpine
151
- COPY --from=builder /app/.docu/dist /usr/share/nginx/html
152
- COPY nginx.conf /etc/nginx/conf.d/default.conf
153
- EXPOSE 80
154
- CMD ["nginx", "-g", "daemon off;"]
155
- `);
183
+ await writeFile(join(dockerDir, "Dockerfile"), DOCKERFILE);
156
184
  log.created("📄 Created Dockerfile");
157
185
  }
158
186
  if (!existsSync(join(dockerDir, "nginx.conf"))) {
@@ -292,4 +320,4 @@ async function runDeploy() {
292
320
  //#endregion
293
321
  export { runDeploy as t };
294
322
 
295
- //# sourceMappingURL=deploy.shared-Dxv3lsOb.js.map
323
+ //# sourceMappingURL=deploy.shared-CsEa3L1D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.shared-CsEa3L1D.js","names":[],"sources":["../node/deploy.shared.ts"],"sourcesContent":["/**\n * Runtime-neutral deploy — 3 modes:\n * 1. `flame deploy` → build + generate GitHub Actions workflow\n * 2. `flame deploy --docker` → build + generate Docker deployment files\n * 3. `flame deploy --docker --silent` → same as #2, minimal output\n *\n * Mirror of deploy.ts (Bun-only, protected) for Node.js and Deno.\n * Runs the neutral build in-process, then prepares .docu/dist.\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { DIST_DIR, PROJECT_ROOT, FRAMEWORK_ROOT } from \"./paths\";\n\nconst FLAME_VERSION = JSON.parse(\n readFileSync(resolve(FRAMEWORK_ROOT, \"package.json\"), \"utf-8\")\n).version;\n\nconst WORKFLOW_DIR = join(PROJECT_ROOT, \".github/workflows\");\nconst WORKFLOW_FILE = join(WORKFLOW_DIR, \"deploy.yml\");\n\nexport const NGINX_CONF = `server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n error_page 404 /404.html;\n\n gzip on;\n gzip_types text/html text/css application/javascript image/svg+xml;\n\n # Security headers (HSTS effective when HTTPS is terminated upstream)\n add_header X-Frame-Options \"DENY\" always;\n add_header X-Content-Type-Options \"nosniff\" always;\n add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains\" always;\n add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\n add_header Permissions-Policy \"camera=(), microphone=(), geolocation=()\" always;\n add_header Content-Security-Policy \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'\" always;\n\n # Build metadata and search content use stable URLs, so clients must revalidate them.\n location = /assets/manifest.json {\n expires -1;\n }\n\n location = /assets/search-index.json {\n expires -1;\n }\n\n # Generated JS, CSS, and chunks include content hashes in their filenames.\n location /assets/ {\n expires 1y;\n add_header Cache-Control \"public, immutable\";\n add_header X-Frame-Options \"DENY\" always;\n add_header X-Content-Type-Options \"nosniff\" always;\n add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains\" always;\n add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\n add_header Permissions-Policy \"camera=(), microphone=(), geolocation=()\" always;\n add_header Content-Security-Policy \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'\" always;\n }\n\n location /docs/assets/ {\n expires 7d;\n add_header Cache-Control \"public\";\n add_header X-Frame-Options \"DENY\" always;\n add_header X-Content-Type-Options \"nosniff\" always;\n add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains\" always;\n add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\n add_header Permissions-Policy \"camera=(), microphone=(), geolocation=()\" always;\n add_header Content-Security-Policy \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'\" always;\n }\n\n location = /404.html { }\n\n location / {\n try_files $uri $uri.html $uri/ =404;\n }\n}\n`;\n\nexport const DOCKERIGNORE = `node_modules\n*.DS_Store\n.docu/dist\n.docu/lib\n.env\n.env.*\n.npmrc\n*.log\n`;\n\nexport const DOCKERFILE = `FROM ghcr.io/docubook/flame:${FLAME_VERSION} AS builder\nENV NODE_ENV=production\nWORKDIR /app\nCOPY . .\nRUN flame build --bun\n\nFROM nginx:alpine\nCOPY --from=builder /app/.docu/dist /usr/share/nginx/html\nCOPY nginx.conf /etc/nginx/conf.d/default.conf\nEXPOSE 80\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n`;\n\nexport function detectPkgManager(dir: string): {\n baseImage: string;\n lockFile: string;\n installCmd: string;\n runCmd: string;\n cache: string;\n setupAction: string;\n} {\n const bunLockFile = existsSync(join(dir, \"bun.lock\"))\n ? \"bun.lock\"\n : existsSync(join(dir, \"bun.lockb\"))\n ? \"bun.lockb\"\n : null;\n if (bunLockFile) {\n return {\n baseImage: \"oven/bun:1-debian\",\n lockFile: bunLockFile,\n installCmd: \"bun install --frozen-lockfile\",\n runCmd: \"bun\",\n cache: \"\",\n setupAction: \"bun\",\n };\n }\n if (existsSync(join(dir, \"pnpm-lock.yaml\"))) {\n return {\n baseImage: \"node:22-alpine\",\n lockFile: \"pnpm-lock.yaml\",\n installCmd: \"corepack enable && pnpm install --frozen-lockfile\",\n runCmd: \"pnpm\",\n cache: \"pnpm\",\n setupAction: \"pnpm\",\n };\n }\n if (existsSync(join(dir, \"yarn.lock\"))) {\n return {\n baseImage: \"node:22-alpine\",\n lockFile: \"yarn.lock\",\n installCmd: \"yarn install --frozen-lockfile\",\n runCmd: \"yarn\",\n cache: \"yarn\",\n setupAction: \"node\",\n };\n }\n // default: npm\n return {\n baseImage: \"node:22-alpine\",\n lockFile: \"package-lock.json\",\n installCmd: \"npm ci\",\n runCmd: \"npm\",\n cache: \"npm\",\n setupAction: \"node\",\n };\n}\n\nexport const HEADERS_FILE = `/*\n X-Frame-Options: DENY\n X-Content-Type-Options: nosniff\n Strict-Transport-Security: max-age=63072000; includeSubDomains; preload\n Referrer-Policy: strict-origin-when-cross-origin\n Permissions-Policy: camera=(), microphone=(), geolocation=()\n Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'\n\n/assets/client-*\n Cache-Control: public, max-age=31536000, immutable\n/assets/home-client-*\n Cache-Control: public, max-age=31536000, immutable\n/assets/docs-*\n Cache-Control: public, max-age=31536000, immutable\n/assets/site-*\n Cache-Control: public, max-age=31536000, immutable\n/assets/chunks/*\n Cache-Control: public, max-age=31536000, immutable\n/assets/assets/*\n Cache-Control: public, max-age=31536000, immutable\n/assets/manifest.json\n Cache-Control: no-cache\n/assets/search-index.json\n Cache-Control: no-cache\n`;\n\nconst isDocker = !!process.env.FLAME_DEPLOY_DOCKER;\nconst isSilent = !!process.env.FLAME_DEPLOY_SILENT;\nconst isCi = !!process.env.FLAME_DEPLOY_CI;\n\n/** Logger that no-ops all non-error output in silent mode. */\nconst log = isSilent\n ? { info: () => {}, ok: () => {}, created: () => {}, out: () => {} }\n : {\n info: (m: string) => console.log(m),\n ok: () => console.log(\"\\n✅ Ready to deploy!\"),\n created: (m: string) => console.log(m),\n out: (m: string) => console.log(m),\n };\n\nasync function runBuild() {\n process.env.NODE_ENV = \"production\";\n if (isSilent) {\n process.env.FLAME_BUILD_SILENT = \"1\";\n process.env.LOG_LEVEL = \"error\";\n }\n const { runBuildCli } = await import(\"./build.impl\");\n await runBuildCli();\n}\n\nasync function writeDockerFiles() {\n const dockerDir = PROJECT_ROOT;\n\n if (!existsSync(join(dockerDir, \"Dockerfile\"))) {\n await writeFile(join(dockerDir, \"Dockerfile\"), DOCKERFILE);\n log.created(\"📄 Created Dockerfile\");\n }\n\n if (!existsSync(join(dockerDir, \"nginx.conf\"))) {\n await writeFile(join(dockerDir, \"nginx.conf\"), NGINX_CONF);\n log.created(\"📄 Created nginx.conf\");\n }\n\n if (!existsSync(join(dockerDir, \".dockerignore\"))) {\n await writeFile(join(dockerDir, \".dockerignore\"), DOCKERIGNORE);\n log.created(\"📄 Created .dockerignore\");\n }\n}\n\nfunction generateWorkflowYml(): string {\n const pm = detectPkgManager(PROJECT_ROOT);\n\n const setupSteps: string[] = [\n \" - uses: actions/checkout@v7\",\n \" with:\",\n \" fetch-depth: 0\",\n \"\",\n ];\n\n if (pm.setupAction === \"bun\") {\n setupSteps.push(\n \" - uses: oven-sh/setup-bun@v2\",\n \" with:\",\n \" bun-version: latest\",\n \"\"\n );\n } else if (pm.setupAction === \"pnpm\") {\n setupSteps.push(\n \" - uses: pnpm/action-setup@v6\",\n \"\",\n \" - uses: actions/setup-node@v6\",\n \" with:\",\n \" node-version: 22\",\n ` cache: ${pm.cache}`,\n \"\"\n );\n } else {\n // npm / yarn\n setupSteps.push(\n \" - uses: actions/setup-node@v6\",\n \" with:\",\n \" node-version: 22\",\n ` cache: ${pm.cache}`,\n \"\"\n );\n }\n\n return [\n `name: Deploy to GitHub Pages`,\n \"\",\n \"on:\",\n \" push:\",\n \" branches: [main]\",\n \" workflow_dispatch:\",\n \"\",\n \"permissions:\",\n \" contents: read\",\n \" pages: write\",\n \" id-token: write\",\n \"\",\n \"concurrency:\",\n ' group: \"pages\"',\n \" cancel-in-progress: false\",\n \"\",\n \"jobs:\",\n \" build:\",\n \" runs-on: ubuntu-latest\",\n \" steps:\",\n ...setupSteps,\n ` - run: ${pm.installCmd}`,\n \"\",\n ` - run: ${pm.runCmd} run build`,\n \"\",\n \" - name: Add .nojekyll\",\n \" run: touch .docu/dist/.nojekyll\",\n \"\",\n \" - uses: actions/upload-pages-artifact@v3\",\n \" with:\",\n \" path: .docu/dist\",\n \"\",\n \" deploy:\",\n \" environment:\",\n \" name: github-pages\",\n \" url: ${{ steps.deployment.outputs.page_url }}\",\n \" runs-on: ubuntu-latest\",\n \" needs: build\",\n \" steps:\",\n \" - id: deployment\",\n \" uses: actions/deploy-pages@v4\",\n ].join(\"\\n\");\n}\n\nfunction generateDockerWorkflowYml(): string {\n const imageName = \"ghcr.io/${{ github.repository }}\";\n return [\n `name: Build & Push Docker Image`,\n \"\",\n \"on:\",\n \" push:\",\n \" branches: [main]\",\n \" workflow_dispatch:\",\n \"\",\n \"permissions:\",\n \" contents: read\",\n \" packages: write\",\n \"\",\n \"jobs:\",\n \" build:\",\n \" runs-on: ubuntu-latest\",\n \" steps:\",\n \" - uses: actions/checkout@v4\",\n \" with:\",\n \" fetch-depth: 0\",\n \"\",\n \" - name: Log in to GHCR\",\n \" uses: docker/login-action@v3\",\n \" with:\",\n \" registry: ghcr.io\",\n \" username: ${{ github.actor }}\",\n \" password: ${{ secrets.GITHUB_TOKEN }}\",\n \"\",\n \" - name: Build & push\",\n \" uses: docker/build-push-action@v5\",\n \" with:\",\n \" context: .\",\n ` tags: ${imageName}:latest`,\n \" push: true\",\n ].join(\"\\n\");\n}\n\nasync function writeGhaWorkflow() {\n if (!existsSync(WORKFLOW_FILE)) {\n await mkdir(WORKFLOW_DIR, { recursive: true });\n await writeFile(WORKFLOW_FILE, generateWorkflowYml());\n log.created(\"📄 Created .github/workflows/deploy.yml\");\n }\n}\n\nconst DOCKER_WORKFLOW_FILE = join(WORKFLOW_DIR, \"deploy-docker.yml\");\n\nasync function writeDockerWorkflow() {\n if (!existsSync(DOCKER_WORKFLOW_FILE)) {\n await mkdir(WORKFLOW_DIR, { recursive: true });\n await writeFile(DOCKER_WORKFLOW_FILE, generateDockerWorkflowYml());\n log.created(\"📄 Created .github/workflows/deploy-docker.yml\");\n }\n}\n\nexport async function runDeploy(): Promise<void> {\n log.info(\"📦 Building for production...\\n\");\n await runBuild();\n\n // Common: .nojekyll + _headers\n await writeFile(join(DIST_DIR, \".nojekyll\"), \"\");\n await writeFile(join(DIST_DIR, \"_headers\"), HEADERS_FILE);\n\n if (isDocker) {\n await writeDockerFiles();\n if (isCi) await writeDockerWorkflow();\n } else {\n await writeGhaWorkflow();\n }\n\n log.ok();\n log.out(\" Output: .docu/dist/\");\n if (isDocker) {\n log.out(\" Build locally: docker build -t my-docs . && docker run -p 80:80 my-docs\");\n if (isCi) {\n log.out(\" Push to GitHub — CI will build & push Docker image to GHCR\");\n log.out(\" Then pull latest image on your hosting platform (Coolify, etc.)\");\n } else {\n log.out(\" For Coolify: connect repo, set build pack to Dockerfile\");\n }\n } else {\n log.out(\" Push to GitHub and enable Pages (Settings → Pages → Source: GitHub Actions)\");\n }\n}\n"],"mappings":"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"}