@docubook/flame 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/.docu/components/Context.tsx +6 -5
  2. package/.docu/components/DocsLayout.tsx +7 -4
  3. package/.docu/components/Menu.tsx +10 -9
  4. package/.docu/components/Navbar.tsx +24 -22
  5. package/.docu/components/Pagination.tsx +3 -2
  6. package/.docu/components/Search.tsx +6 -1
  7. package/.docu/components/Sidebar.tsx +22 -21
  8. package/.docu/components/Sublink.tsx +3 -3
  9. package/.docu/lib/build.deno.js +1 -1
  10. package/.docu/lib/{build.impl-BSt6Vikt.js → build.impl-DK485Nx1.js} +60 -31
  11. package/.docu/lib/build.impl-DK485Nx1.js.map +1 -0
  12. package/.docu/lib/build.impl-Dmybgcj2.js +2 -0
  13. package/.docu/lib/build.node.js +1 -1
  14. package/.docu/lib/clean.js +1 -1
  15. package/.docu/lib/deploy.deno.js +1 -1
  16. package/.docu/lib/deploy.node.js +1 -1
  17. package/.docu/lib/{deploy.shared-D6S_FE7d.js → deploy.shared-BW2KXFXs.js} +27 -8
  18. package/.docu/lib/deploy.shared-BW2KXFXs.js.map +1 -0
  19. package/.docu/lib/{html.shared-CsEFmy_Y.js → html.shared-RPCM1y5Q.js} +264 -73
  20. package/.docu/lib/html.shared-RPCM1y5Q.js.map +1 -0
  21. package/.docu/lib/{logger-DFKQUy8M.js → logger-DYFD47f8.js} +3 -3
  22. package/.docu/lib/{logger-DFKQUy8M.js.map → logger-DYFD47f8.js.map} +1 -1
  23. package/.docu/lib/paths-CHXABfXa.js +332 -0
  24. package/.docu/lib/paths-CHXABfXa.js.map +1 -0
  25. package/.docu/lib/preview.deno.js +1 -1
  26. package/.docu/lib/{preview.impl-BfESMUM7.js → preview.impl-DMXVsGs0.js} +4 -4
  27. package/.docu/lib/preview.impl-DMXVsGs0.js.map +1 -0
  28. package/.docu/lib/preview.node.js +1 -1
  29. package/.docu/lib/{utils-B_CoyKie.js → server-utils-BYWB7A6T.js} +3 -21
  30. package/.docu/lib/server-utils-BYWB7A6T.js.map +1 -0
  31. package/.docu/lib/server.deno.js +1 -1
  32. package/.docu/lib/{server.impl-CZ4eMe5L.js → server.impl-DcyZhPA_.js} +24 -19
  33. package/.docu/lib/server.impl-DcyZhPA_.js.map +1 -0
  34. package/.docu/lib/server.node.js +1 -1
  35. package/.docu/node/base-path.ts +306 -0
  36. package/.docu/node/build.impl.ts +50 -17
  37. package/.docu/node/build.ts +50 -17
  38. package/.docu/node/cache-key.ts +92 -4
  39. package/.docu/node/client-routes.ts +16 -1
  40. package/.docu/node/deploy.shared.ts +51 -15
  41. package/.docu/node/deploy.ts +7 -3
  42. package/.docu/node/html.shared.ts +33 -3
  43. package/.docu/node/html.ts +18 -3
  44. package/.docu/node/hydrate.node.ts +6 -0
  45. package/.docu/node/hydrate.ts +16 -1
  46. package/.docu/node/mdx.ts +102 -23
  47. package/.docu/node/paths.ts +115 -0
  48. package/.docu/node/preview.impl.ts +1 -1
  49. package/.docu/node/preview.ts +1 -1
  50. package/.docu/node/search-indexer.ts +20 -3
  51. package/.docu/node/seo.ts +41 -7
  52. package/.docu/node/server-routes.ts +34 -11
  53. package/.docu/node/server-utils.ts +152 -0
  54. package/.docu/node/server.impl.ts +22 -12
  55. package/.docu/node/server.ts +23 -27
  56. package/.docu/node/types.ts +13 -0
  57. package/.docu/node/utils.ts +56 -149
  58. package/.docu/pages/404.tsx +2 -1
  59. package/.docu/pages/index.tsx +6 -13
  60. package/bin/cli.js +5 -0
  61. package/docu.schema.json +10 -1
  62. package/package.json +5 -5
  63. package/template/docu.json +1 -0
  64. package/.docu/lib/build.impl-BSt6Vikt.js.map +0 -1
  65. package/.docu/lib/build.impl-xNDEh8DJ.js +0 -2
  66. package/.docu/lib/deploy.shared-D6S_FE7d.js.map +0 -1
  67. package/.docu/lib/html.shared-CsEFmy_Y.js.map +0 -1
  68. package/.docu/lib/paths-Cbz-dj4s.js +0 -72
  69. package/.docu/lib/paths-Cbz-dj4s.js.map +0 -1
  70. package/.docu/lib/preview.impl-BfESMUM7.js.map +0 -1
  71. package/.docu/lib/server.impl-CZ4eMe5L.js.map +0 -1
  72. package/.docu/lib/utils-B_CoyKie.js.map +0 -1
@@ -1,5 +1,5 @@
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
- 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";
1
+ import { C as isDocsPath, D as resolveDeployPath, E as resolveBasePath, T as rebaseContentPath, _ as loadDocuConfig, a as DOCS_DIR, b as servedDeployPath, c as LIB_DIR, d as STYLES_DIR, g as deployPath$1, m as cleanOldBundles, p as basePath$3, s as FRAMEWORK_ROOT, t as ASSETS_DIR, u as PROJECT_ROOT, v as resolveProjectFile, x as DEFAULT_BASE_PATH, y as servedBasePath } from "./paths-CHXABfXa.js";
2
+ import { f as normalizeImporterPath, o as cspMeta, r as scanMdxFiles } from "./server-utils-BYWB7A6T.js";
3
3
  import { builtinModules, createRequire } from "node:module";
4
4
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
5
5
  import { dirname, extname, join, relative, resolve, sep } from "node:path";
@@ -11,7 +11,7 @@ import { createHash } from "node:crypto";
11
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
- import { MDXRemote, createDefaultRehypePlugins, createDefaultRemarkPlugins, extractFrontmatter, extractFrontmatterWithContent, rehypeCollectTocs, serialize } from "@docubook/core";
14
+ import { MDXRemote, cn, createDefaultRehypePlugins, createDefaultRemarkPlugins, extractFrontmatter, extractFrontmatterWithContent, formatDate2, rehypeCollectTocs, serialize } from "@docubook/core";
15
15
  import { createMdxComponents } from "@docubook/markdown";
16
16
  import * as LucideIcons from "lucide-react";
17
17
  import { ArrowUpIcon, ArrowUpRight, ChevronDown, ChevronLeft, ChevronRight, ListIcon, Moon, SquarePen, Sun } from "lucide-react";
@@ -470,7 +470,31 @@ var BuildPluginBuilder = class {
470
470
  else console.warn(`[plugin] ${hookName} callback returned unexpected type (got ${typeof result}), expected string or string[], skipping`);
471
471
  }
472
472
  };
473
- /** Toolchain fingerprint: Bun version on Bun, Deno version on Deno, Node elsewhere. */
473
+ /**
474
+ * Resolved docs URL prefix and deployment path, part of every cache key.
475
+ *
476
+ * The page cache is keyed by relative MDX path and the bundle/asset slots are
477
+ * hashed from MDX source alone — neither changes when only `meta.basePath` or
478
+ * `meta.baseURL`'s path changes. Without this stamp, editing either would leave
479
+ * every key untouched and the build would skip every page, emitting HTML that
480
+ * still points at the old prefix.
481
+ */
482
+ function basePathStamp() {
483
+ return prefixStamp(basePath$3(), deployPath$1());
484
+ }
485
+ /**
486
+ * Compose the cache stamp from both prefixes that shape generated URLs: the
487
+ * docs prefix and the host's deployment path (from `meta.baseURL`). Either one
488
+ * changing has to invalidate the cache, or a warm cache keeps serving HTML that
489
+ * points at the old location.
490
+ */
491
+ function prefixStamp(resolvedBasePath, deploymentPath) {
492
+ if (deploymentPath.length === 0) return resolvedBasePath;
493
+ return `${resolvedBasePath || "/"}@${deploymentPath}`;
494
+ }
495
+ /**
496
+ * Toolchain fingerprint: Bun version on Bun, Deno version on Deno, Node elsewhere.
497
+ */
474
498
  function runtimeStamp() {
475
499
  const g = globalThis;
476
500
  const bun = g.Bun;
@@ -482,6 +506,54 @@ function runtimeStamp() {
482
506
  return "node-unknown";
483
507
  }
484
508
  /**
509
+ * Framework source files that shape rendered HTML.
510
+ *
511
+ * Page cache entries are keyed by MDX source alone, so editing the renderer
512
+ * (a template tweak, a new meta tag, base-path plumbing) would otherwise leave
513
+ * every page a cache hit and keep serving HTML built by the old code. Hashing
514
+ * these sources makes a framework edit invalidate the pages it affects.
515
+ */
516
+ var RENDER_SOURCE_FILES = [
517
+ ".docu/node/html.ts",
518
+ ".docu/node/html.shared.ts",
519
+ ".docu/node/seo.ts",
520
+ ".docu/node/utils.ts",
521
+ ".docu/node/paths.ts",
522
+ ".docu/node/base-path.ts",
523
+ ".docu/node/mdx.ts",
524
+ ".docu/node/search-indexer.ts",
525
+ ".docu/node/build.ts",
526
+ ".docu/node/build.impl.ts",
527
+ ".docu/node/server-routes.ts",
528
+ ".docu/components/DocsLayout.tsx",
529
+ ".docu/components/Navbar.tsx",
530
+ ".docu/pages/index.tsx",
531
+ ".docu/pages/404.tsx",
532
+ ".docu/pages/docs/[[...slug]].tsx"
533
+ ];
534
+ var renderStampCache = null;
535
+ /**
536
+ * Fingerprint of the framework's rendering sources.
537
+ *
538
+ * Memoized per process — the files cannot change mid-build, and hashing them
539
+ * on every page would dominate build time. A missing file contributes nothing
540
+ * so a partial install still yields a stable (if weaker) stamp.
541
+ */
542
+ function renderToolchainStamp() {
543
+ if (renderStampCache !== null) return renderStampCache;
544
+ const h = createHash("sha256");
545
+ h.update(`v6`);
546
+ for (const rel of RENDER_SOURCE_FILES) {
547
+ const file = join(FRAMEWORK_ROOT, rel);
548
+ try {
549
+ if (!existsSync(file)) continue;
550
+ h.update(rel).update("\0").update(readFileSync(file, "utf-8"));
551
+ } catch {}
552
+ }
553
+ renderStampCache = h.digest("hex").slice(0, 16);
554
+ return renderStampCache;
555
+ }
556
+ /**
485
557
  * True when a CSS file can change Tailwind v4 output.
486
558
  * v4 is CSS-first: `@theme`, `@source`, `@plugin`, `@custom-variant`,
487
559
  * `@utility`, `@config`, `@apply`/`@variant`, and `@import "tailwindcss"`
@@ -639,7 +711,9 @@ function computeTailwindCacheKey(globals, themeSuffix, projectRoot = resolveProj
639
711
  h.update("\0");
640
712
  h.update(runtimeStamp());
641
713
  h.update("\0");
642
- h.update(`v5`);
714
+ h.update(basePathStamp());
715
+ h.update("\0");
716
+ h.update(`v6`);
643
717
  return h.digest("hex").slice(0, 16);
644
718
  }
645
719
  /** Read a Tailwind entry plus relative imports for cache invalidation. */
@@ -684,7 +758,7 @@ function hookMemoryPressure(clear) {
684
758
  function hashMdxSources(mdxSources) {
685
759
  const h = createHash("sha256");
686
760
  const slugs = Object.keys(mdxSources).sort();
687
- h.update(`v5:${runtimeStamp()}:`);
761
+ h.update(`v6:${runtimeStamp()}:${basePathStamp()}:${renderToolchainStamp()}:`);
688
762
  for (const slug of slugs) {
689
763
  h.update(slug);
690
764
  h.update("\0");
@@ -1027,7 +1101,9 @@ async function buildClientBundle(mdxSources = {}) {
1027
1101
  return [
1028
1102
  `const docuConfig = ${JSON.stringify(resolved)};`,
1029
1103
  `export const routes = docuConfig.routes || [];`,
1030
- `export const config = docuConfig;`
1104
+ `export const config = docuConfig;`,
1105
+ `export const basePath = ${JSON.stringify(resolveBasePath(config))};`,
1106
+ `export const deployPath = ${JSON.stringify(servedDeployPath())};`
1031
1107
  ].join("\n");
1032
1108
  }
1033
1109
  },
@@ -1179,35 +1255,92 @@ async function getGitLastModifiedBatch(filePaths) {
1179
1255
  //#endregion
1180
1256
  //#region .docu/node/mdx.ts
1181
1257
  /**
1182
- * Return the value with `.html` appended, or null if the value should be left
1183
- * unchanged. Rules:
1184
- * - Must be a string
1185
- * - Must start with /docs/ (the /docs root index needs no suffix)
1186
- * - Must not be an external URL, contain a fragment, or already end in .html
1258
+ * Does an author-written absolute path belong to the docs site?
1259
+ *
1260
+ * At a root deployment the docs own `/`, so every in-site path is a candidate
1261
+ * (the historical rule for authored content); otherwise the shared
1262
+ * {@link isDocsPath} gate applies and sibling app routes stay untouched.
1187
1263
  */
1188
- function appendHtml(value) {
1189
- if (typeof value !== "string") return null;
1190
- if (/^https?:\/\//.test(value)) return null;
1191
- if (!value.startsWith("/docs/")) return null;
1192
- if (value.includes("#")) return null;
1193
- if (value.endsWith(".html")) return null;
1194
- return `${value}.html`;
1264
+ function isContentPath(pathname, resolvedBasePath) {
1265
+ return resolvedBasePath.length === 0 || isDocsPath(pathname, resolvedBasePath);
1266
+ }
1267
+ /** Split an authored value into its pathname and any `?query`/`#fragment`. */
1268
+ function splitContentPath(value) {
1269
+ const cut = value.search(/[?#]/);
1270
+ if (cut === -1) return {
1271
+ pathname: value.replace(/\/+$/, "") || "/",
1272
+ suffix: ""
1273
+ };
1274
+ return {
1275
+ pathname: value.slice(0, cut).replace(/\/+$/, "") || "/",
1276
+ suffix: value.slice(cut)
1277
+ };
1195
1278
  }
1196
1279
  /**
1197
- * Rehype plugin: append `.html` to internal `/docs/` hrefs on HTML `<a>` nodes.
1280
+ * Resolve an author-written content **link** for the deployment.
1198
1281
  *
1199
- * This covers standard markdown links: `[text](/docs/page)` → `<a href="…">`.
1200
- * It runs in the HAST (HTML AST) phase, where `<a>` elements are real nodes.
1282
+ * Authors link to sibling pages the way they sit on disk (`/docs/guide/y`). The
1283
+ * static build serves those pages as flat `.html` files, and a non-default
1284
+ * `meta.basePath` — or a host that publishes the dist under a path (a GitHub
1285
+ * Pages project site) — moves the authored segment. Re-base it onto the
1286
+ * configured prefix, add the deployment path, and keep the `.html` suffix on
1287
+ * page links. Returns null when nothing moves, so the default `/docs`
1288
+ * deployment keeps emitting the same HTML.
1289
+ */
1290
+ function resolveContentHref(value, resolvedBasePath = basePath$3(), deploymentPath = servedDeployPath()) {
1291
+ if (typeof value !== "string") return null;
1292
+ if (/^[a-z][a-z\d+.-]*:|^\/\//i.test(value)) return null;
1293
+ if (!value.startsWith("/") || value === "/") return null;
1294
+ const { pathname, suffix } = splitContentPath(value);
1295
+ if (!isContentPath(pathname, resolvedBasePath)) return null;
1296
+ const rebased = rebaseContentPath(pathname, resolvedBasePath);
1297
+ const resolved = `${deploymentPath}${rebased === "/" || rebased === resolvedBasePath || /\.[a-z0-9]+$/i.test(rebased) || suffix.includes("#") ? rebased : `${rebased}.html`}${suffix}`;
1298
+ return resolved === value ? null : resolved;
1299
+ }
1300
+ /**
1301
+ * Resolve an author-written content **asset** path (`![alt](/docs/assets/x.png)`)
1302
+ * for the deployment. Same re-basing rules as {@link resolveContentHref}, minus
1303
+ * the `.html` suffix — assets are files, not routes.
1304
+ */
1305
+ function resolveContentSrc(value, resolvedBasePath = basePath$3(), deploymentPath = servedDeployPath()) {
1306
+ if (typeof value !== "string") return null;
1307
+ if (/^[a-z][a-z\d+.-]*:|^\/\//i.test(value)) return null;
1308
+ if (!value.startsWith("/") || value === "/") return null;
1309
+ const { pathname, suffix } = splitContentPath(value);
1310
+ if (!isContentPath(pathname, resolvedBasePath)) return null;
1311
+ const resolved = `${deploymentPath}${rebaseContentPath(pathname, resolvedBasePath)}${suffix}`;
1312
+ return resolved === value ? null : resolved;
1313
+ }
1314
+ /** Element → attribute pairs whose author-written values are content assets. */
1315
+ var CONTENT_ASSET_ATTRS = {
1316
+ img: "src",
1317
+ source: "src",
1318
+ video: "src",
1319
+ audio: "src"
1320
+ };
1321
+ /**
1322
+ * Rehype plugin: point author-written hrefs at the deployed docs paths, and
1323
+ * author-written asset paths at the deployed asset tree.
1201
1324
  *
1202
- * Skips: external URLs, anchor-only links, paths that already end in `.html`,
1203
- * and the `/docs` root index (no trailing slash segment).
1325
+ * Links cover both shapes — plain markdown `[text](/docs/page)` and images and
1326
+ * media (`![alt](/docs/assets/x.png)` → `<img src>`) — which only exist in the
1327
+ * HAST phase. Skips: external URLs, anchors, the root index, and anything the
1328
+ * resolver leaves unchanged.
1204
1329
  */
1205
1330
  function rehypeDocsHtmlLinks() {
1206
1331
  return (tree) => {
1207
1332
  function walk(node) {
1208
- if (node.type === "element" && node.tagName === "a") {
1209
- const fixed = appendHtml(node.properties?.href);
1210
- if (fixed) node.properties.href = fixed;
1333
+ if (node.type === "element" && node.properties) {
1334
+ if (node.tagName === "a") {
1335
+ const fixed = resolveContentHref(node.properties.href);
1336
+ if (fixed) node.properties.href = fixed;
1337
+ } else {
1338
+ const attr = node.tagName ? CONTENT_ASSET_ATTRS[node.tagName] : void 0;
1339
+ if (attr) {
1340
+ const fixed = resolveContentSrc(node.properties[attr]);
1341
+ if (fixed) node.properties[attr] = fixed;
1342
+ }
1343
+ }
1211
1344
  }
1212
1345
  if (node.children) for (const child of node.children) walk(child);
1213
1346
  }
@@ -1216,7 +1349,7 @@ function rehypeDocsHtmlLinks() {
1216
1349
  };
1217
1350
  }
1218
1351
  /**
1219
- * Remark plugin: append `.html` to internal `/docs/` hrefs on MDX JSX nodes.
1352
+ * Remark plugin: append `.html` to internal docs hrefs on MDX JSX nodes.
1220
1353
  *
1221
1354
  * MDX JSX elements (`<Card href="…">`, `<LinkCard href="…">`, etc.) live in
1222
1355
  * the MDAST as `mdxJsxFlowElement` / `mdxJsxTextElement` nodes. They are
@@ -1225,14 +1358,15 @@ function rehypeDocsHtmlLinks() {
1225
1358
  * intercepts them at the MDAST phase where their `attributes` array is still
1226
1359
  * accessible and mutable.
1227
1360
  *
1228
- * Skips: same rules as `appendHtml` (external URLs, anchors, already `.html`).
1361
+ * Skips: same rules as `resolveContentHref` (external URLs, anchors, already
1362
+ * resolved paths).
1229
1363
  */
1230
1364
  function remarkMdxJsxDocsHtmlLinks() {
1231
1365
  return (tree) => {
1232
1366
  function walk(node) {
1233
1367
  if ((node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") && node.attributes) {
1234
1368
  for (const attr of node.attributes) if (attr.type === "mdxJsxAttribute" && attr.name === "href") {
1235
- const fixed = appendHtml(attr.value);
1369
+ const fixed = resolveContentHref(attr.value);
1236
1370
  if (fixed) attr.value = fixed;
1237
1371
  }
1238
1372
  }
@@ -1399,6 +1533,43 @@ async function compileMdxModule(rawMdx, remarkPlugins, rehypePlugins, href) {
1399
1533
  return serialized.compiledSource;
1400
1534
  }
1401
1535
  //#endregion
1536
+ //#region .docu/node/utils.ts
1537
+ /**
1538
+ * Client-safe utilities shared by SSR and the browser bundle.
1539
+ *
1540
+ * This module MUST NOT import Node built-ins (`node:fs`, `node:path`, ...):
1541
+ * Bun's bundler injects a `node:path` polyfill into browser builds for any
1542
+ * bundled module that imports it. Filesystem/git helpers live in
1543
+ * `./server-utils` (server-only).
1544
+ */
1545
+ function isExternalUrl(url) {
1546
+ return /^(https?:\/\/|\/\/)/.test(url);
1547
+ }
1548
+ /** Suffix an internal docs link with `.html` to match the flat static build output. */
1549
+ function docsHtmlHref(path) {
1550
+ return `${path}.html`;
1551
+ }
1552
+ /**
1553
+ * Resolve an authored nav/menu link for the current deployment.
1554
+ *
1555
+ * Docs pages ship as flat `.html` files, so `/docs/guide/routing` has to request
1556
+ * `/docs/guide/routing.html`, while the docs root itself stays a directory index
1557
+ * and keeps no suffix. Authored `/docs/...` paths are re-based onto the
1558
+ * configured prefix, so one `docu.json` keeps working at a custom subpath
1559
+ * (`/repo`) or at a root deployment (`""`). External URLs, hash targets and
1560
+ * paths that already name a file pass through untouched.
1561
+ */
1562
+ function docsNavHref(link, resolvedBasePath = DEFAULT_BASE_PATH) {
1563
+ if (isExternalUrl(link) || !link.startsWith("/")) return link;
1564
+ const cut = link.search(/[?#]/);
1565
+ const suffix = cut === -1 ? "" : link.slice(cut);
1566
+ const pathname = (cut === -1 ? link : link.slice(0, cut)).replace(/\/+$/, "") || "/";
1567
+ if (!isDocsPath(pathname, resolvedBasePath)) return link;
1568
+ const rebased = rebaseContentPath(pathname, resolvedBasePath);
1569
+ if (rebased === "/" || rebased === resolvedBasePath || /\.[a-z0-9]+$/i.test(rebased)) return `${rebased}${suffix}`;
1570
+ return `${rebased}.html${suffix}`;
1571
+ }
1572
+ //#endregion
1402
1573
  //#region .docu/node/search-indexer.ts
1403
1574
  /**
1404
1575
  * Search Index Generator
@@ -1433,10 +1604,21 @@ function stripJsx(content) {
1433
1604
  }
1434
1605
  return result;
1435
1606
  }
1607
+ /**
1608
+ * Absolute URL for a search record.
1609
+ *
1610
+ * Records are clicked straight from the search modal, so they must carry both
1611
+ * prefixes: the docs prefix inside the dist and the host's deployment path
1612
+ * (e.g. `/repo` on a GitHub Pages project site), which no relative depth can
1613
+ * express.
1614
+ */
1615
+ function searchRecordUrl(filePath, resolvedBasePath = basePath$3(), deploymentPath = deployPath$1()) {
1616
+ return docsHtmlHref(`${deploymentPath}${resolvedBasePath}/${filePath}`);
1617
+ }
1436
1618
  function extractRecords(filePath, raw) {
1437
1619
  const { frontmatter, strippedContent: content } = extractFrontmatterWithContent(raw);
1438
1620
  const records = [];
1439
- const url = docsHtmlHref(`/docs/${filePath}`);
1621
+ const url = searchRecordUrl(filePath);
1440
1622
  const lvl0 = getSectionTitle(filePath);
1441
1623
  const lvl1 = frontmatterField(frontmatter, "title") || null;
1442
1624
  const hierarchy = {
@@ -1663,18 +1845,30 @@ function getPreviousNext(pathname) {
1663
1845
  };
1664
1846
  }
1665
1847
  //#endregion
1848
+ //#region .docu/node/client-routes.ts
1849
+ var docuConfig$3 = loadDocuConfig();
1850
+ resolveRoutes(docuConfig$3.routes || []);
1851
+ var config = docuConfig$3;
1852
+ /**
1853
+ * URL prefix the site is served under (`""` at the domain root, else `/prefix`).
1854
+ * Components use this instead of assuming `/docs`, so a subpath deployment does
1855
+ * not request assets from the domain root.
1856
+ */
1857
+ var basePath$2 = resolveBasePath(docuConfig$3);
1858
+ resolveDeployPath(docuConfig$3);
1859
+ //#endregion
1666
1860
  //#region .docu/components/Pagination.tsx
1667
1861
  function Pagination({ pathname, className, prevIcon, nextIcon, linkClassName }) {
1668
1862
  const { prev, next } = getPreviousNext(pathname);
1669
1863
  if (!prev && !next) return null;
1670
1864
  return /* @__PURE__ */ jsx(PaginationDocs, {
1671
1865
  prev: prev ? {
1672
- href: docsHtmlHref(`/docs${prev.href}`),
1866
+ href: docsHtmlHref(`${basePath$2}${prev.href}`),
1673
1867
  title: prev.title,
1674
1868
  description: prev.description
1675
1869
  } : void 0,
1676
1870
  next: next ? {
1677
- href: docsHtmlHref(`/docs${next.href}`),
1871
+ href: docsHtmlHref(`${basePath$2}${next.href}`),
1678
1872
  title: next.title,
1679
1873
  description: next.description
1680
1874
  } : void 0,
@@ -1694,9 +1888,9 @@ function Typography({ children }) {
1694
1888
  }
1695
1889
  //#endregion
1696
1890
  //#region .docu/node/helpers.ts
1697
- var docuConfig$3 = loadDocuConfig();
1891
+ var docuConfig$2 = loadDocuConfig();
1698
1892
  function getEditLink(url, filePath) {
1699
- const configPath = docuConfig$3?.repo?.path || detectPlatformPath(url);
1893
+ const configPath = docuConfig$2?.repo?.path || detectPlatformPath(url);
1700
1894
  const encodedPath = filePath.replace(/^\//, "").split("/").map(encodeURIComponent).join("/");
1701
1895
  return `${url}/${configPath}`.replace("{filePath}", encodedPath);
1702
1896
  }
@@ -1720,13 +1914,13 @@ function detectPlatformPath(url) {
1720
1914
  }
1721
1915
  }
1722
1916
  function isEditEnabled() {
1723
- return docuConfig$3?.repo?.edit ?? false;
1917
+ return docuConfig$2?.repo?.edit ?? false;
1724
1918
  }
1725
1919
  function getRepoUrl() {
1726
- return docuConfig$3?.repo?.url || "";
1920
+ return docuConfig$2?.repo?.url || "";
1727
1921
  }
1728
1922
  function getSocialLinks() {
1729
- return docuConfig$3?.footer?.social || [];
1923
+ return docuConfig$2?.footer?.social || [];
1730
1924
  }
1731
1925
  //#endregion
1732
1926
  //#region .docu/components/EditWith.tsx
@@ -2252,7 +2446,7 @@ function NotFoundPage() {
2252
2446
  description: "Page not found",
2253
2447
  actions: [{
2254
2448
  text: "Go to Docs",
2255
- link: "/docs/"
2449
+ link: `${servedBasePath()}/`
2256
2450
  }]
2257
2451
  } })]
2258
2452
  });
@@ -2294,29 +2488,25 @@ function ThemeToggle({ className }) {
2294
2488
  }
2295
2489
  //#endregion
2296
2490
  //#region .docu/pages/index.tsx
2297
- var docuConfig$2 = loadDocuConfig();
2491
+ var docuConfig$1 = loadDocuConfig();
2492
+ var basePath$1 = resolveBasePath(docuConfig$1);
2298
2493
  function IndexPage() {
2299
- const { meta, home } = docuConfig$2;
2300
- const routes = docuConfig$2.routes || [];
2301
- const linkWithHtml = (link) => {
2302
- if (isExternalUrl(link)) return link;
2303
- if (link.startsWith("/docs/")) return `${link}.html`;
2304
- return link;
2305
- };
2494
+ const { meta, home } = docuConfig$1;
2495
+ const routes = docuConfig$1.routes || [];
2306
2496
  const features = home?.features?.map((f) => ({
2307
2497
  ...f,
2308
- link: f.link ? linkWithHtml(f.link) : void 0
2498
+ link: f.link ? docsNavHref(f.link, basePath$1) : void 0
2309
2499
  })) || routes.filter((r) => r.context).map((route) => ({
2310
2500
  icon: route.context?.icon,
2311
2501
  title: route.context?.title || route.title,
2312
2502
  description: route.context?.description || "",
2313
- link: docsHtmlHref(`/docs${route.href}${route.items?.[0]?.href || ""}`)
2503
+ link: docsNavHref(`/docs${route.href}${route.items?.[0]?.href || ""}`, basePath$1)
2314
2504
  }));
2315
2505
  const hero = home?.hero ? {
2316
2506
  ...home.hero,
2317
2507
  actions: home.hero.actions?.map((a) => ({
2318
2508
  ...a,
2319
- link: linkWithHtml(a.link)
2509
+ link: docsNavHref(a.link, basePath$1)
2320
2510
  }))
2321
2511
  } : {
2322
2512
  headline: meta.title,
@@ -2371,11 +2561,6 @@ function Anchor({ href = "", className = "", activeClassName = "", activeWhen, d
2371
2561
  });
2372
2562
  }
2373
2563
  //#endregion
2374
- //#region .docu/node/client-routes.ts
2375
- var docuConfig$1 = loadDocuConfig();
2376
- resolveRoutes(docuConfig$1.routes || []);
2377
- var config = docuConfig$1;
2378
- //#endregion
2379
2564
  //#region .docu/components/Sublink.tsx
2380
2565
  /** Exclusive accordion for level >= 2 sidebar groups — opening one group
2381
2566
  * closes the previously open one. All level >= 2 groups default to closed
@@ -2400,8 +2585,8 @@ function GroupAccordionProvider({ children }) {
2400
2585
  });
2401
2586
  }
2402
2587
  function Sublink({ title, href, items, noLink, level, onNavigate, parentHref = "", pathname: pathnameProp }) {
2403
- const fullHref = parentHref ? `${parentHref}${href}` : `/docs${href}`;
2404
- const currentPathname = pathnameProp || (typeof window !== "undefined" ? window.location.pathname : "/docs");
2588
+ const fullHref = parentHref ? `${parentHref}${href}` : `${basePath$2}${href}`;
2589
+ const currentPathname = pathnameProp || (typeof window !== "undefined" ? window.location.pathname : basePath$2);
2405
2590
  const isSeparator = config.sidebar?.context === "separator";
2406
2591
  const { openId, open, toggle } = useContext(GroupAccordionContext);
2407
2592
  const isAccordionGroup = Boolean(items) && (isSeparator || level >= 1);
@@ -2515,8 +2700,8 @@ function SidebarGroupHeader({ icon, title }) {
2515
2700
  //#endregion
2516
2701
  //#region .docu/components/Menu.tsx
2517
2702
  function getCurrentContext(path) {
2518
- if (!path.startsWith("/docs")) return void 0;
2519
- const match = path.match(/^\/docs\/([^/]+)/);
2703
+ if (!path.startsWith(basePath$2)) return void 0;
2704
+ const match = path.match(new RegExp(`^${basePath$2}/([^/]+)`));
2520
2705
  return match ? match[1] : void 0;
2521
2706
  }
2522
2707
  function getContextRoute(contextPath, routeList) {
@@ -2526,15 +2711,15 @@ function getContextRoute(contextPath, routeList) {
2526
2711
  }
2527
2712
  function Menu({ onNavigate, className = "", pathname, routes = [] }) {
2528
2713
  const menuRoutes = routes;
2529
- const [currentPath] = useState(() => pathname || (typeof window !== "undefined" ? window.location.pathname : "/docs"));
2530
- if (!currentPath.startsWith("/docs")) return null;
2714
+ const [currentPath] = useState(() => pathname || (typeof window !== "undefined" ? window.location.pathname : basePath$2));
2715
+ if (basePath$2.length > 0 && !currentPath.startsWith(basePath$2)) return null;
2531
2716
  const mode = config.sidebar?.context || "dropdown";
2532
2717
  const navProps = {
2533
2718
  "aria-label": "Documentation navigation",
2534
2719
  className: cn("transition-all duration-200", className)
2535
2720
  };
2536
2721
  const renderBorderItem = (item, parentRouteHref, key) => {
2537
- const fullHref = `/docs${parentRouteHref}${item.href}`;
2722
+ const fullHref = `${basePath$2}${parentRouteHref}${item.href}`;
2538
2723
  const isActive = currentPath === fullHref || currentPath === `${fullHref}.html`;
2539
2724
  return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("div", {
2540
2725
  className: cn("-ml-[14px] border-l-2", isActive ? "border-primary" : "border-transparent"),
@@ -2545,7 +2730,7 @@ function Menu({ onNavigate, className = "", pathname, routes = [] }) {
2545
2730
  href: item.href,
2546
2731
  level: 0,
2547
2732
  onNavigate,
2548
- parentHref: `/docs${parentRouteHref}`
2733
+ parentHref: `${basePath$2}${parentRouteHref}`
2549
2734
  })
2550
2735
  })
2551
2736
  }) }, key);
@@ -2574,7 +2759,7 @@ function Menu({ onNavigate, className = "", pathname, routes = [] }) {
2574
2759
  }, route.href))
2575
2760
  }) });
2576
2761
  }
2577
- const isDocsRoot = currentPath === "/docs" || currentPath === "/docs/";
2762
+ const isDocsRoot = currentPath === basePath$2 || currentPath === `${basePath$2}/`;
2578
2763
  const currentContext = isDocsRoot ? menuRoutes[0]?.href.replace(/^\/+|\/+$/, "") : getCurrentContext(currentPath);
2579
2764
  const contextRoute = isDocsRoot && menuRoutes[0] ? currentContext ? getContextRoute(currentContext, menuRoutes) : menuRoutes[0] : currentContext ? getContextRoute(currentContext, menuRoutes) : void 0;
2580
2765
  if (!contextRoute) return null;
@@ -2587,7 +2772,7 @@ function Menu({ onNavigate, className = "", pathname, routes = [] }) {
2587
2772
  href: contextRoute.href,
2588
2773
  level: 0,
2589
2774
  onNavigate,
2590
- parentHref: "/docs"
2775
+ parentHref: basePath$2
2591
2776
  }) }, contextRoute.title)
2592
2777
  })
2593
2778
  }) });
@@ -2595,7 +2780,8 @@ function Menu({ onNavigate, className = "", pathname, routes = [] }) {
2595
2780
  //#endregion
2596
2781
  //#region .docu/components/DocsLayout.tsx
2597
2782
  var docuConfig = loadDocuConfig();
2598
- function DocsLayout({ children, repoUrl, pathname = "/docs" }) {
2783
+ var basePath = resolveBasePath(docuConfig);
2784
+ function DocsLayout({ children, repoUrl, pathname = basePath }) {
2599
2785
  return React.createElement("div", { className: "docs-layout flex flex-col min-h-screen w-full" }, React.createElement("div", { className: "flex flex-1 items-start w-full" }, React.createElement("aside", {
2600
2786
  id: "sidebar-island",
2601
2787
  className: "sticky top-0 hidden h-screen w-[280px] shrink-0 flex-col lg:flex border-r border-base-200 bg-base-100",
@@ -2607,10 +2793,11 @@ function DocsLayout({ children, repoUrl, pathname = "/docs" }) {
2607
2793
  routes: docuConfig.routes || []
2608
2794
  }))), React.createElement("main", { className: "flex-1 min-w-0 min-h-screen flex flex-col" }, React.createElement("div", { className: "hidden lg:flex items-center justify-end gap-6 h-14 px-8" }, React.createElement("nav", { className: "flex items-center gap-6 text-sm font-medium text-base-content/80" }, ...(docuConfig.navbar?.menu || []).map((item) => {
2609
2795
  const isExternal = /^https?:\/\//.test(item.href);
2610
- const isDocsActive = item.href === "/docs";
2796
+ const href = isExternal ? item.href : docsNavHref(item.href, basePath);
2797
+ const isDocsActive = href === basePath;
2611
2798
  return React.createElement("a", {
2612
2799
  key: item.title,
2613
- href: item.href,
2800
+ href,
2614
2801
  className: `flex items-center gap-1 hover:text-base-content transition-colors${isDocsActive ? " text-primary font-semibold" : ""}`,
2615
2802
  ...isExternal ? {
2616
2803
  target: "_blank",
@@ -2657,15 +2844,19 @@ function escapeHtml(input) {
2657
2844
  * `html.ts` untouched.
2658
2845
  */
2659
2846
  function htmlShell(opts) {
2660
- const { title, description, body, favicon, css, js, nonce, csp, extraScripts, themeCss, depth = 0, headExtra, bodyExtra, absoluteAssets = false } = opts;
2847
+ const { title, description, body, favicon, css, js, nonce, csp, extraScripts, themeCss, depth = 0, headExtra, bodyExtra, absoluteAssets = false, basePath = DEFAULT_BASE_PATH, deployPath = "" } = opts;
2661
2848
  const nonceAttr = nonce ? ` nonce="${escapeHtml(nonce)}"` : "";
2662
2849
  const themeStyle = themeCss ? `\n <style${nonceAttr}>${escapeHtml(themeCss)}</style>` : "";
2663
2850
  const headInjection = headExtra?.length ? `\n ${headExtra.join("\n ")}` : "";
2664
2851
  const bodyInjection = bodyExtra?.length ? `\n ${bodyExtra.join("\n ")}` : "";
2665
2852
  const depthPrefix = depth === 0 ? "" : "../".repeat(depth);
2666
- const assetPrefix = absoluteAssets ? "/assets/" : depthPrefix + "assets/";
2853
+ const assetPrefix = absoluteAssets ? `${deployPath}/assets/` : depthPrefix + "assets/";
2667
2854
  const clientScript = js ? `\n <link rel="modulepreload" href="${escapeHtml(assetPrefix + js)}">\n <script type="module"${nonceAttr} src="${escapeHtml(assetPrefix + js)}"><\/script>` : "";
2668
- const resolvePath = (path) => absoluteAssets ? path : path.startsWith("/") ? depthPrefix + path.slice(1) : path;
2855
+ const resolvePath = (path) => {
2856
+ if (!path.startsWith("/")) return path;
2857
+ const rebased = rebaseContentPath(path, basePath);
2858
+ return absoluteAssets ? `${deployPath}${rebased}` : depthPrefix + rebased.slice(1);
2859
+ };
2669
2860
  let seoTags = "";
2670
2861
  if (opts.seo) {
2671
2862
  const s = opts.seo;
@@ -2726,6 +2917,6 @@ function hmrScript(nonce) {
2726
2917
  <\/script>`;
2727
2918
  }
2728
2919
  //#endregion
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 };
2920
+ export { hashMdxSources as C, BuildPluginBuilder as D, runtimeStamp as E, loadPlugins as O, atomicWriteFile as S, renderToolchainStamp 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 };
2730
2921
 
2731
- //# sourceMappingURL=html.shared-CsEFmy_Y.js.map
2922
+ //# sourceMappingURL=html.shared-RPCM1y5Q.js.map