@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
@@ -1,23 +1,24 @@
1
- import { a as DOCS_DIR, c as PROJECT_ROOT, d as loadDocuConfig, f as resolveProjectFile, l as STYLES_DIR, o as FRAMEWORK_ROOT, s as LIB_DIR, t as ASSETS_DIR, u as cleanOldBundles } from "./paths-Bl2cdp9E.js";
1
+ import { a as DOCS_DIR, d as cleanOldBundles, f as loadDocuConfig, l as PROJECT_ROOT, o as FRAMEWORK_ROOT, p as resolveProjectFile, s as LIB_DIR, t as ASSETS_DIR, u as STYLES_DIR } from "./paths-Cbz-dj4s.js";
2
2
  import { c as scanMdxFiles, f as cspMeta, i as formatDate2, n as cn, o as isExternalUrl, r as docsHtmlHref, v as normalizeImporterPath } from "./utils-B_CoyKie.js";
3
3
  import { builtinModules, createRequire } from "node:module";
4
4
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
5
- import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
5
+ import { dirname, extname, join, relative, resolve, sep } from "node:path";
6
6
  import { mkdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
7
7
  import { execFile } from "node:child_process";
8
8
  import { promisify } from "node:util";
9
9
  import { build } from "vite";
10
- import { generateThemeCss, presetRegistry, resolveTheme } from "@docubook/themes-colors";
11
10
  import { createHash } from "node:crypto";
11
+ import { generateThemeCss, presetRegistry, resolveTheme } from "@docubook/themes-colors";
12
12
  import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
13
13
  import { z } from "zod";
14
14
  import { MDXRemote, createDefaultRehypePlugins, createDefaultRemarkPlugins, extractFrontmatter, extractFrontmatterWithContent, rehypeCollectTocs, serialize } from "@docubook/core";
15
15
  import { createMdxComponents } from "@docubook/markdown";
16
16
  import * as LucideIcons from "lucide-react";
17
- import { ArrowUpIcon, ArrowUpRight, ChevronDown, ChevronLeft, ChevronRight, ListIcon, SquarePen } from "lucide-react";
17
+ import { ArrowUpIcon, ArrowUpRight, ChevronDown, ChevronLeft, ChevronRight, ListIcon, Moon, SquarePen, Sun } from "lucide-react";
18
18
  import { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbPage } from "@docubook/ui-react/breadcrumbs";
19
- import { jsx, jsxs } from "react/jsx-runtime";
19
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
20
  import { PaginationDocs } from "@docubook/ui-react/pagination";
21
+ import { ThemeControllerToggle } from "@docubook/ui-react/theme-controller";
21
22
  //#region .docu/node/plugin-loader.ts
22
23
  var NPM_PACKAGE_RE = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
23
24
  /**
@@ -224,15 +225,15 @@ var BuildPluginBuilder = class {
224
225
  }
225
226
  /**
226
227
  * Register a callback to run once after all pages are built.
227
- * Receives the resolved config and aggregated page metadata.
228
- * Errors thrown by the callback propagate to the caller via `runOnEnd()`.
228
+ * Receives the resolved config, aggregated docs metadata, and final build metadata.
229
+ * Callback errors are logged by `runOnEnd()` and do not stop later callbacks.
229
230
  *
230
- * @param callback - Receives config and page metadata array. May return a Promise.
231
+ * @param callback - Receives config, page metadata, and emitted assets. May return a Promise.
231
232
  *
232
233
  * @example
233
- * build.onEnd(async (config, pages) => {
234
+ * build.onEnd(async (config, pages, { outDir }) => {
234
235
  * const xml = generateSitemap(pages, config.meta.baseURL);
235
- * const out = ".docu/dist/sitemap.xml";
236
+ * const out = join(outDir, "sitemap.xml");
236
237
  * // Bun.write on Bun for speed, writeFile on Node/Deno
237
238
  * await (typeof Bun !== "undefined"
238
239
  * ? Bun.write(out, xml)
@@ -246,7 +247,7 @@ var BuildPluginBuilder = class {
246
247
  * Register a callback to transform raw file content before MDX compilation.
247
248
  * Filtered by regex against the file's relative path — only the **first** matching
248
249
  * handler's result is used.
249
- * Errors thrown by the callback propagate to the caller via `runOnLoad()`.
250
+ * Callback errors are logged by `runOnLoad()` before trying later matching handlers.
250
251
  *
251
252
  * @param args.filter - RegExp matched against the file's relative path.
252
253
  * @param args.namespace - Optional namespace prefix (reserved for future use).
@@ -266,7 +267,7 @@ var BuildPluginBuilder = class {
266
267
  /**
267
268
  * Register a callback to run once before the build starts.
268
269
  * Receives the resolved DocuConfig for validation or resource initialization.
269
- * Errors thrown by the callback propagate to the caller via `runOnStart()`.
270
+ * Callback errors are logged by `runOnStart()` and do not stop later callbacks.
270
271
  *
271
272
  * @param callback - Receives the resolved config. May return a Promise.
272
273
  *
@@ -327,11 +328,12 @@ var BuildPluginBuilder = class {
327
328
  * Errors inside individual callbacks are caught and logged — execution
328
329
  * continues to the next callback without throwing.
329
330
  *
330
- * @param pages - Array of metadata for every built page.
331
+ * @param pages - Array of metadata for every built docs page.
332
+ * @param context - Final output directory and page-specific asset manifest.
331
333
  */
332
- async runOnEnd(pages) {
334
+ async runOnEnd(pages, context) {
333
335
  for (let i = 0; i < this._onEnd.length; i++) try {
334
- await this._onEnd[i](this.config, pages);
336
+ await this._onEnd[i](this.config, pages, context);
335
337
  } catch (err) {
336
338
  console.error(`[plugin] onEnd callback #${i + 1} error: ${err instanceof Error ? err.message : String(err)}`);
337
339
  }
@@ -637,13 +639,12 @@ function computeTailwindCacheKey(globals, themeSuffix, projectRoot = resolveProj
637
639
  h.update("\0");
638
640
  h.update(runtimeStamp());
639
641
  h.update("\0");
640
- h.update(`v4`);
642
+ h.update(`v5`);
641
643
  return h.digest("hex").slice(0, 16);
642
644
  }
643
- /** Read globals.css content ("" when missing). Shared by both hydrators. */
644
- function readGlobalsCss() {
645
- const globalsPath = join(STYLES_DIR, "globals.css");
646
- return existsSync(globalsPath) ? readFileSync(globalsPath, "utf-8") : "";
645
+ /** Read a Tailwind entry plus relative imports for cache invalidation. */
646
+ function readStyleCss(file = "globals.css") {
647
+ return readCssWithImports(join(STYLES_DIR, file), /* @__PURE__ */ new Set());
647
648
  }
648
649
  /**
649
650
  * Atomic file write: tmp + rename so a crash mid-write never leaves a
@@ -683,7 +684,7 @@ function hookMemoryPressure(clear) {
683
684
  function hashMdxSources(mdxSources) {
684
685
  const h = createHash("sha256");
685
686
  const slugs = Object.keys(mdxSources).sort();
686
- h.update(`v4:${runtimeStamp()}:`);
687
+ h.update(`v5:${runtimeStamp()}:`);
687
688
  for (const slug of slugs) {
688
689
  h.update(slug);
689
690
  h.update("\0");
@@ -808,6 +809,12 @@ function resolveRoutes(docuJsonRoutes) {
808
809
  //#endregion
809
810
  //#region .docu/node/hydrate.ts
810
811
  var themeRegistry = presetRegistry;
812
+ function createMdxModuleEntries(mdxSources) {
813
+ return Object.keys(mdxSources).sort().map((slug) => ({
814
+ slug,
815
+ id: `docubook-mdx-page-${createHash("sha256").update(slug).digest("hex").slice(0, 16)}`
816
+ }));
817
+ }
811
818
  /**
812
819
  * Read the effective theme config with this priority:
813
820
  * 1. FLAME_THEME env var (CLI --theme flag)
@@ -817,9 +824,7 @@ function getThemeConfig() {
817
824
  if (process.env.FLAME_THEME) return process.env.FLAME_THEME;
818
825
  return loadDocuConfig().themes?.colors;
819
826
  }
820
- /**
821
- * Append theme CSS to compiled Tailwind output based on theme config.
822
- */
827
+ /** Append theme CSS to compiled Tailwind output based on theme config. */
823
828
  function buildThemeCss(baseCss, themeConfig) {
824
829
  try {
825
830
  const resolved = resolveTheme(themeConfig, themeRegistry);
@@ -829,10 +834,7 @@ function buildThemeCss(baseCss, themeConfig) {
829
834
  return baseCss;
830
835
  }
831
836
  }
832
- /**
833
- * Compute inline theme CSS for FOUC prevention.
834
- * Returns undefined if no theme is configured or on error.
835
- */
837
+ /** Compute inline theme CSS for FOUC prevention. */
836
838
  function computeInlineThemeCss() {
837
839
  try {
838
840
  const themeColors = getThemeConfig();
@@ -846,33 +848,27 @@ function computeInlineThemeCss() {
846
848
  }
847
849
  //#endregion
848
850
  //#region .docu/node/hydrate.node.ts
849
- /**
850
- * Client bundle builder for Node/Deno runtimes.
851
- *
852
- * Uses Vite with Rolldown plugins to produce a browser-ready client
853
- * bundle (JS + CSS) from the same components Bun.build handles natively.
854
- * Theme helpers (getThemeConfig, buildThemeCss, computeInlineThemeCss)
855
- * are re-exported from `hydrate.ts` — that module's `buildClientBundle`
856
- * is Bun-only and unused here.
857
- */
851
+ /** Client bundle builder for Node/Deno runtimes. */
858
852
  /** Extract Lucide icon names from user docu.json configuration. */
859
853
  function extractConfigIcons(config) {
860
854
  const icons = [];
861
- const pushIf = (s) => {
862
- if (s) icons.push(s);
855
+ const pushIf = (value) => {
856
+ if (value) icons.push(value);
863
857
  };
864
- config.home?.hero?.actions?.forEach((a) => pushIf(a.icon));
865
- config.home?.features?.forEach((f) => pushIf(f.icon));
858
+ config.home?.hero?.actions?.forEach((action) => pushIf(action.icon));
859
+ config.home?.features?.forEach((feature) => pushIf(feature.icon));
866
860
  (function walk(routes) {
867
- for (const r of routes) {
868
- pushIf(r.context?.icon);
869
- if (r.items) walk(r.items);
861
+ for (const route of routes) {
862
+ pushIf(route.context?.icon);
863
+ if (route.items) walk(route.items);
870
864
  }
871
865
  })(config.routes ?? []);
872
- return [...new Set(icons.filter((n) => /^[A-Z]/.test(n)))];
866
+ return [...new Set(icons.filter((name) => /^[A-Z]/.test(name)))];
867
+ }
868
+ function viteChunkFileName(chunk) {
869
+ return `chunks/${chunk.name.replace(/^_docubook-mdx-page-/, "docubook-mdx-page-")}-[hash].js`;
873
870
  }
874
871
  var execFileAsync = promisify(execFile);
875
- /** Resolve the @tailwindcss/cli binary path from the installed package. */
876
872
  function resolveTailwindBin() {
877
873
  const require = createRequire(import.meta.url);
878
874
  const pkgPath = require.resolve("@tailwindcss/cli/package.json");
@@ -880,33 +876,30 @@ function resolveTailwindBin() {
880
876
  const binRel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin.tailwindcss;
881
877
  return join(dirname(pkgPath), binRel);
882
878
  }
883
- /** Compute a cache key from globals.css + theme + config + toolchain. */
884
- function tailwindCacheKey() {
885
- const globalsContent = readGlobalsCss();
886
- let themeSuffix = "";
879
+ function themeCacheSuffix() {
887
880
  try {
888
881
  const themeColors = getThemeConfig();
889
- if (themeColors) themeSuffix = JSON.stringify(themeColors);
890
- } catch {}
891
- return computeTailwindCacheKey(globalsContent, themeSuffix);
882
+ return themeColors ? JSON.stringify(themeColors) : "";
883
+ } catch {
884
+ return "";
885
+ }
892
886
  }
893
- /**
894
- * Build Tailwind CSS with content-based caching.
895
- * If a CSS file for the current input hash already exists, skip the subprocess.
896
- * Returns the filename (e.g. "client-abc123.css") and CSS content.
897
- */
898
- async function buildTailwindCss(key) {
899
- const cachedFile = `client-${key}.css`;
887
+ function tailwindCacheKey(styleFile) {
888
+ return computeTailwindCacheKey(readStyleCss(styleFile), `${styleFile}\0${themeCacheSuffix()}`);
889
+ }
890
+ async function buildTailwindCss(name, styleFile) {
891
+ const key = tailwindCacheKey(styleFile);
892
+ const cachedFile = `${name}-${key}.css`;
900
893
  const cachedPath = join(ASSETS_DIR, cachedFile);
901
894
  if (existsSync(cachedPath)) return {
902
895
  file: cachedFile,
903
896
  content: readFileSync(cachedPath, "utf-8")
904
897
  };
905
- const tmpCss = join(ASSETS_DIR, `_tmp-${key}.css`);
898
+ const tmpCss = join(ASSETS_DIR, `_tmp-${name}-${key}.css`);
906
899
  const bin = resolveTailwindBin();
907
- const twArgs = [
900
+ const tailwindArgs = [
908
901
  "-i",
909
- join(STYLES_DIR, "globals.css"),
902
+ join(STYLES_DIR, styleFile),
910
903
  "-o",
911
904
  tmpCss,
912
905
  "--minify"
@@ -915,8 +908,8 @@ async function buildTailwindCss(key) {
915
908
  "run",
916
909
  "-A",
917
910
  bin,
918
- ...twArgs
919
- ] : [bin, ...twArgs];
911
+ ...tailwindArgs
912
+ ] : [bin, ...tailwindArgs];
920
913
  try {
921
914
  await execFileAsync(process.execPath, args, { maxBuffer: 16777216 });
922
915
  } catch (err) {
@@ -929,38 +922,34 @@ async function buildTailwindCss(key) {
929
922
  const themeColors = getThemeConfig();
930
923
  if (themeColors) cssContent = buildThemeCss(cssContent, themeColors);
931
924
  } catch (err) {
932
- console.warn(`[flame] Failed to resolve theme config, falling back to globals.css only: ${err instanceof Error ? err.message : String(err)}`);
925
+ console.warn(`[flame] Failed to resolve theme config: ${err instanceof Error ? err.message : String(err)}`);
933
926
  }
934
- const cssFile = `client-${key}.css`;
935
- const outPath = join(ASSETS_DIR, cssFile);
936
- if (!existsSync(outPath)) await atomicWriteFile(writeFile, rename, unlink, outPath, cssContent);
927
+ if (!existsSync(cachedPath)) await atomicWriteFile(writeFile, rename, unlink, cachedPath, cssContent);
937
928
  return {
938
- file: cssFile,
929
+ file: cachedFile,
939
930
  content: cssContent
940
931
  };
941
932
  }
942
- var NODE_BUILTINS_RE = new RegExp(`^(node:.*|${builtinModules.map((m) => m.replace(/\//g, "\\/")).join("|")})$`);
933
+ var NODE_BUILTINS_RE = new RegExp(`^(node:.*|${builtinModules.map((module) => module.replace(/\//g, "\\/")).join("|")})$`);
943
934
  var lucideRealEntry;
944
- /** Resolve the real lucide-react entry path once (cached). */
945
935
  function getLucideRealEntry() {
946
936
  if (!lucideRealEntry) lucideRealEntry = createRequire(import.meta.url).resolve("lucide-react");
947
937
  return lucideRealEntry;
948
938
  }
949
939
  var LUCIDE_IMPORT_RE = /import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/g;
950
940
  var LUCIDE_ICON_RE = /^[A-Z]/;
951
- /** Walk a directory scanning JS/TS/TSX files for `lucide-react` named imports. */
952
941
  function scanDirLucideIcons(dir, set) {
953
942
  if (!existsSync(dir)) return;
954
943
  try {
955
944
  const entries = readdirSync(dir, { withFileTypes: true });
956
- for (const e of entries) {
957
- const full = join(dir, e.name);
958
- if (e.isDirectory()) {
959
- if (e.name !== "node_modules") scanDirLucideIcons(full, set);
960
- } else if (/\.(js|ts|tsx)$/.test(e.name)) {
945
+ for (const entry of entries) {
946
+ const full = join(dir, entry.name);
947
+ if (entry.isDirectory()) {
948
+ if (entry.name !== "node_modules") scanDirLucideIcons(full, set);
949
+ } else if (/\.(js|ts|tsx)$/.test(entry.name)) {
961
950
  const content = readFileSync(full, "utf-8");
962
- for (const m of content.matchAll(LUCIDE_IMPORT_RE)) for (const s of m[1].split(",")) {
963
- const name = s.trim().split(/\s+as\s+/)[0].trim();
951
+ for (const match of content.matchAll(LUCIDE_IMPORT_RE)) for (const specifier of match[1].split(",")) {
952
+ const name = specifier.trim().split(/\s+as\s+/)[0].trim();
964
953
  if (LUCIDE_ICON_RE.test(name)) set.add(name);
965
954
  }
966
955
  }
@@ -969,27 +958,27 @@ function scanDirLucideIcons(dir, set) {
969
958
  console.warn(`[flame] Failed to scan lucide icons: ${err instanceof Error ? err.message : String(err)}`);
970
959
  }
971
960
  }
972
- /** Collect every lucide icon name imported across flame sources and deps. */
973
961
  function collectAllLucideIcons() {
974
962
  const icons = /* @__PURE__ */ new Set();
975
963
  scanDirLucideIcons(join(FRAMEWORK_ROOT, ".docu/components"), icons);
976
964
  scanDirLucideIcons(join(FRAMEWORK_ROOT, ".docu/pages"), icons);
977
- const depDirs = [
965
+ const dependencyDirs = [
978
966
  join(FRAMEWORK_ROOT, "..", "mdx-content", "dist"),
979
967
  join(FRAMEWORK_ROOT, "..", "ui-react", "dist"),
980
968
  join(FRAMEWORK_ROOT, "..", "core", "dist"),
981
969
  join(FRAMEWORK_ROOT, "..", "themes-colors", "dist")
982
970
  ];
983
- for (const d of depDirs) scanDirLucideIcons(resolve(d), icons);
971
+ for (const dir of dependencyDirs) scanDirLucideIcons(resolve(dir), icons);
984
972
  return [...icons];
985
973
  }
986
- /** Build the client JS bundle and Tailwind CSS. */
987
974
  async function buildClientBundle(mdxSources = {}) {
988
975
  await mkdir(ASSETS_DIR, { recursive: true });
989
- const twKey = tailwindCacheKey();
990
- await cleanOldBundles(/* @__PURE__ */ new Set([`client-${twKey}.css`]));
976
+ await cleanOldBundles();
991
977
  const nodeEnv = process.env.NODE_ENV || "development";
992
- const entryPath = join(LIB_DIR, "client.ts");
978
+ const mdxEntries = createMdxModuleEntries(mdxSources);
979
+ const mdxEntriesById = new Map(mdxEntries.map((entry) => [entry.id, entry]));
980
+ const docsEntryPath = join(LIB_DIR, "client.ts");
981
+ const homeEntryPath = join(LIB_DIR, "home-client.ts");
993
982
  const bundle = await build({
994
983
  configFile: false,
995
984
  publicDir: false,
@@ -1046,21 +1035,15 @@ async function buildClientBundle(mdxSources = {}) {
1046
1035
  name: "mdx-hydrate",
1047
1036
  resolveId(id) {
1048
1037
  if (/mdx-manifest$/.test(id)) return "\0mdx-manifest";
1049
- if (id.startsWith("mdx-module:")) return `\0${id}`;
1038
+ if (/^docubook-mdx-page-[a-f0-9]{16}$/.test(id)) return `\0${id}`;
1050
1039
  return null;
1051
1040
  },
1052
1041
  load(id) {
1053
- if (id === "\0mdx-manifest") {
1054
- const slugs = Object.keys(mdxSources).sort();
1055
- return `${slugs.map((slug, i) => {
1056
- const key = slug.replace(/["\\]/g, "");
1057
- return `import * as _mdx${i} from ${JSON.stringify(`mdx-module:${key}`)};`;
1058
- }).join("\n")}\nexport const mdxModules = { ${slugs.map((slug, i) => `${JSON.stringify(slug)}: _mdx${i}`).join(", ")} };\n`;
1059
- }
1060
- if (!id.startsWith("\0mdx-module:")) return null;
1061
- const slug = id.slice(12);
1062
- const contents = mdxSources[slug];
1063
- if (contents == null) throw new Error(`unknown mdx module: ${slug}`);
1042
+ if (id === "\0mdx-manifest") return `export const mdxModules = { ${mdxEntries.map(({ slug, id }) => `${JSON.stringify(slug)}: () => import(${JSON.stringify(id)})`).join(", ")} };\n`;
1043
+ if (!id.startsWith("\0docubook-mdx-page-")) return null;
1044
+ const entry = mdxEntriesById.get(id.slice(1));
1045
+ const contents = entry == null ? void 0 : mdxSources[entry.slug];
1046
+ if (contents == null) throw new Error(`unknown mdx module: ${id}`);
1064
1047
  return contents;
1065
1048
  }
1066
1049
  }
@@ -1072,36 +1055,45 @@ async function buildClientBundle(mdxSources = {}) {
1072
1055
  minify: nodeEnv === "production",
1073
1056
  target: "es2020",
1074
1057
  rollupOptions: {
1075
- input: entryPath,
1058
+ input: {
1059
+ client: docsEntryPath,
1060
+ "home-client": homeEntryPath
1061
+ },
1076
1062
  output: {
1077
1063
  format: "es",
1078
- entryFileNames: "client-[hash].js",
1079
- chunkFileNames: "chunks/[name]-[hash].js",
1064
+ entryFileNames: "[name]-[hash].js",
1065
+ chunkFileNames: viteChunkFileName,
1080
1066
  assetFileNames: "assets/[name]-[hash][extname]"
1081
1067
  }
1082
1068
  }
1083
1069
  }
1084
1070
  });
1085
1071
  const outputs = Array.isArray(bundle) ? bundle : [bundle];
1086
- let jsFile;
1072
+ let docsJs;
1073
+ let homeJs;
1087
1074
  for (const item of outputs) {
1088
1075
  if (!("output" in item)) continue;
1089
- for (const output of item.output) if (output.type === "chunk" && output.isEntry && output.facadeModuleId && resolve(output.facadeModuleId) === entryPath) {
1090
- jsFile = basename(output.fileName);
1091
- break;
1076
+ for (const output of item.output) {
1077
+ if (output.type !== "chunk" || !output.isEntry) continue;
1078
+ if (output.name === "client") docsJs = output.fileName;
1079
+ if (output.name === "home-client") homeJs = output.fileName;
1092
1080
  }
1093
- if (jsFile) break;
1094
1081
  }
1095
- if (!jsFile) throw new Error("Client bundle produced no output files");
1096
- const { file: cssFile } = await buildTailwindCss(twKey);
1097
- await writeFile(join(ASSETS_DIR, "manifest.json"), JSON.stringify({
1098
- js: jsFile,
1099
- css: cssFile
1100
- }));
1101
- return {
1102
- js: jsFile,
1103
- css: cssFile
1082
+ if (!docsJs || !homeJs) throw new Error("Client bundle produced incomplete entry-point outputs");
1083
+ const [{ file: docsCss }, { file: siteCss }] = await Promise.all([buildTailwindCss("docs", "globals.css"), buildTailwindCss("site", "site.css")]);
1084
+ const manifest = {
1085
+ docs: {
1086
+ js: docsJs,
1087
+ css: docsCss
1088
+ },
1089
+ home: {
1090
+ js: homeJs,
1091
+ css: siteCss
1092
+ },
1093
+ notFound: { css: siteCss }
1104
1094
  };
1095
+ await writeFile(join(ASSETS_DIR, "manifest.json"), JSON.stringify(manifest));
1096
+ return manifest;
1105
1097
  }
1106
1098
  //#endregion
1107
1099
  //#region .docu/node/git.ts
@@ -2097,29 +2089,23 @@ function DocsPage({ slug, title, description, date, content, tocs, filePath, rep
2097
2089
  });
2098
2090
  }
2099
2091
  //#endregion
2100
- //#region .docu/pages/404.tsx
2101
- function NotFoundPage() {
2102
- return /* @__PURE__ */ jsx("div", {
2103
- className: "flex w-full flex-1 px-4 py-8 lg:h-[calc(100vh-4rem)] lg:px-8 lg:py-4",
2104
- children: /* @__PURE__ */ jsxs("div", {
2105
- className: "bg-base-100 border-base-300 flex min-h-[50vh] w-full flex-col items-center justify-center rounded-xl border shadow-md lg:min-h-0 lg:flex-1",
2106
- children: [
2107
- /* @__PURE__ */ jsx("h1", {
2108
- className: "text-6xl font-bold",
2109
- children: "404"
2110
- }),
2111
- /* @__PURE__ */ jsx("p", {
2112
- className: "text-base-content/60 py-4 text-xl",
2113
- children: "Page not found"
2114
- }),
2115
- /* @__PURE__ */ jsx("a", {
2116
- href: "/docs/",
2117
- className: "btn btn-primary mt-2",
2118
- children: "Go to Docs"
2119
- })
2120
- ]
2092
+ //#region .docu/components/home/BackgroundBlobs.tsx
2093
+ function BackgroundBlobs() {
2094
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
2095
+ "aria-hidden": "true",
2096
+ className: "pointer-events-none absolute -top-40 left-1/2 -z-10 -translate-x-1/2 blur-3xl sm:-top-80",
2097
+ children: /* @__PURE__ */ jsx("div", {
2098
+ style: { clipPath: "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%)" },
2099
+ className: "from-primary to-accent h-[40rem] w-[80rem] bg-gradient-to-tr opacity-20"
2121
2100
  })
2122
- });
2101
+ }), /* @__PURE__ */ jsx("div", {
2102
+ "aria-hidden": "true",
2103
+ className: "pointer-events-none absolute bottom-0 left-1/2 -z-10 translate-x-1/4 blur-3xl",
2104
+ children: /* @__PURE__ */ jsx("div", {
2105
+ style: { clipPath: "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%)" },
2106
+ className: "from-accent to-primary h-[30rem] w-[70rem] bg-gradient-to-tr opacity-20"
2107
+ })
2108
+ })] });
2123
2109
  }
2124
2110
  //#endregion
2125
2111
  //#region .docu/components/Lucide.tsx
@@ -2257,6 +2243,56 @@ function Features({ features, className }) {
2257
2243
  });
2258
2244
  }
2259
2245
  //#endregion
2246
+ //#region .docu/pages/404.tsx
2247
+ function NotFoundPage() {
2248
+ return /* @__PURE__ */ jsxs("main", {
2249
+ className: "bg-base-100 relative isolate flex min-h-screen w-full items-center justify-center overflow-hidden",
2250
+ children: [/* @__PURE__ */ jsx(BackgroundBlobs, {}), /* @__PURE__ */ jsx(Hero, { hero: {
2251
+ headline: "404",
2252
+ description: "Page not found",
2253
+ actions: [{
2254
+ text: "Go to Docs",
2255
+ link: "/docs/"
2256
+ }]
2257
+ } })]
2258
+ });
2259
+ }
2260
+ //#endregion
2261
+ //#region .docu/components/Theme.tsx
2262
+ function ThemeButtons({ className, isDark, toggle }) {
2263
+ return /* @__PURE__ */ jsxs("div", {
2264
+ 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 || ""}`,
2265
+ children: [/* @__PURE__ */ jsx("button", {
2266
+ type: "button",
2267
+ role: "switch",
2268
+ "aria-label": "Light mode",
2269
+ "aria-checked": !isDark,
2270
+ onClick: toggle ? () => toggle(false) : void 0,
2271
+ className: "bg-primary cursor-pointer rounded-full p-0.5 transition-all dark:bg-transparent",
2272
+ children: /* @__PURE__ */ jsx(Sun, { className: `h-4 w-4 transition-colors ${!isDark ? "text-primary-foreground" : "text-foreground"}` })
2273
+ }), /* @__PURE__ */ jsx("button", {
2274
+ type: "button",
2275
+ role: "switch",
2276
+ "aria-label": "Dark mode",
2277
+ "aria-checked": isDark,
2278
+ onClick: toggle ? () => toggle(true) : void 0,
2279
+ className: "dark:bg-primary cursor-pointer rounded-full p-0.5 transition-all",
2280
+ children: /* @__PURE__ */ jsx(Moon, { className: `h-4 w-4 transition-colors ${isDark ? "text-primary-foreground" : "text-base-content/60"}` })
2281
+ })]
2282
+ });
2283
+ }
2284
+ function ThemeToggle({ className }) {
2285
+ return /* @__PURE__ */ jsx(ThemeControllerToggle, {
2286
+ lightTheme: "light",
2287
+ darkTheme: "dark",
2288
+ children: ({ isDark, toggle }) => /* @__PURE__ */ jsx(ThemeButtons, {
2289
+ className,
2290
+ isDark,
2291
+ toggle
2292
+ })
2293
+ });
2294
+ }
2295
+ //#endregion
2260
2296
  //#region .docu/pages/index.tsx
2261
2297
  var docuConfig$2 = loadDocuConfig();
2262
2298
  function IndexPage() {
@@ -2291,26 +2327,14 @@ function IndexPage() {
2291
2327
  children: [
2292
2328
  /* @__PURE__ */ jsx("div", {
2293
2329
  className: "absolute top-4 right-4 z-10",
2294
- id: "theme-island"
2295
- }),
2296
- /* @__PURE__ */ jsx("div", {
2297
- "aria-hidden": "true",
2298
- className: "pointer-events-none absolute -top-40 left-1/2 -z-10 -translate-x-1/2 blur-3xl sm:-top-80",
2299
2330
  children: /* @__PURE__ */ jsx("div", {
2300
- style: { clipPath: "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%)" },
2301
- className: "from-primary to-accent h-[40rem] w-[80rem] bg-gradient-to-tr opacity-20"
2331
+ id: "theme-toggle-island",
2332
+ children: /* @__PURE__ */ jsx(ThemeToggle, {})
2302
2333
  })
2303
2334
  }),
2335
+ /* @__PURE__ */ jsx(BackgroundBlobs, {}),
2304
2336
  /* @__PURE__ */ jsx(Hero, { hero }),
2305
- /* @__PURE__ */ jsx(Features, { features }),
2306
- /* @__PURE__ */ jsx("div", {
2307
- "aria-hidden": "true",
2308
- className: "pointer-events-none absolute bottom-0 left-1/2 -z-10 translate-x-1/4 blur-3xl",
2309
- children: /* @__PURE__ */ jsx("div", {
2310
- style: { clipPath: "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%)" },
2311
- className: "from-accent to-primary h-[30rem] w-[70rem] bg-gradient-to-tr opacity-20"
2312
- })
2313
- })
2337
+ /* @__PURE__ */ jsx(Features, { features })
2314
2338
  ]
2315
2339
  });
2316
2340
  }
@@ -2640,6 +2664,7 @@ function htmlShell(opts) {
2640
2664
  const bodyInjection = bodyExtra?.length ? `\n ${bodyExtra.join("\n ")}` : "";
2641
2665
  const depthPrefix = depth === 0 ? "" : "../".repeat(depth);
2642
2666
  const assetPrefix = absoluteAssets ? "/assets/" : depthPrefix + "assets/";
2667
+ const clientScript = js ? `\n <link rel="modulepreload" href="${escapeHtml(assetPrefix + js)}">\n <script type="module"${nonceAttr} src="${escapeHtml(assetPrefix + js)}"><\/script>` : "";
2643
2668
  const resolvePath = (path) => absoluteAssets ? path : path.startsWith("/") ? depthPrefix + path.slice(1) : path;
2644
2669
  let seoTags = "";
2645
2670
  if (opts.seo) {
@@ -2663,9 +2688,7 @@ function htmlShell(opts) {
2663
2688
  <script${nonceAttr}>try{if(localStorage.getItem("theme")==="dark")document.documentElement.classList.add("dark")}catch(e){}<\/script>${headInjection}
2664
2689
  </head>
2665
2690
  <body>
2666
- <div id="root">${body}</div>
2667
- <link rel="modulepreload" href="${escapeHtml(assetPrefix + js)}">
2668
- <script type="module"${nonceAttr} src="${escapeHtml(assetPrefix + js)}"><\/script>${extraScripts ? `\n ${extraScripts}` : ""}${bodyInjection}
2691
+ <div id="root">${body}</div>${clientScript}${extraScripts ? `\n ${extraScripts}` : ""}${bodyInjection}
2669
2692
  </body>
2670
2693
  </html>`;
2671
2694
  }
@@ -2705,4 +2728,4 @@ function hmrScript(nonce) {
2705
2728
  //#endregion
2706
2729
  export { hashMdxSources as C, loadPlugins as D, BuildPluginBuilder as E, atomicWriteFile as S, runtimeStamp as T, getPageStripped as _, IndexPage as a, buildClientBundle as b, captureException as c, clearDerivedPageCaches as d, compileMdx as f, getPageFrontmatter as g, getPageContent as h, DocsLayout as i, initSentry as l, frontmatterField as m, hmrScript as n, NotFoundPage as o, compileMdxModule as p, htmlShell as r, DocsPage as s, errorHtml as t, generateSearchIndex as u, registerPageContent as v, hookMemoryPressure as w, computeInlineThemeCss as x, getGitLastModifiedBatch as y };
2707
2730
 
2708
- //# sourceMappingURL=html.shared-DBMwv_Z6.js.map
2731
+ //# sourceMappingURL=html.shared-CsEFmy_Y.js.map