@unterberg/nivel 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,6 +45,8 @@ export default defineDocsConfig({
45
45
  siteTitle: 'My Docs',
46
46
  siteDescription: 'Documentation site powered by @unterberg/nivel.',
47
47
  basePath: '/docs',
48
+ // Optional project-relative root for page.source resolution.
49
+ // contentDir: 'docs',
48
50
  graph: docsGraph,
49
51
  })
50
52
  ```
@@ -60,7 +62,7 @@ Only `(nivel-generated)` stays engine-generated.
60
62
 
61
63
  ## Standard Vike Config
62
64
 
63
- Use the helper from `@unterberg/nivel/vike` for the standard Vike setup:
65
+ Keep `pages/+config.ts` looking like normal Vike config and spread in the engine-owned config from `@unterberg/nivel/vike`:
64
66
 
65
67
  ```ts
66
68
  // pages/+docs.ts
@@ -75,17 +77,39 @@ export default defineDocsConfig({
75
77
  })
76
78
  ```
77
79
 
80
+ `basePath` controls the public docs route prefix. `contentDir` is an optional project-relative filesystem root for resolving `page.source` entries and defaults to `docs`.
81
+
78
82
  ```ts
79
83
  // pages/+config.ts
80
- import { createNivelVikeConfig } from '@unterberg/nivel/vike'
84
+ import nivel from '@unterberg/nivel/vike'
85
+ import type { Config } from 'vike/types'
86
+ import vikeReact from 'vike-react/config'
81
87
  import docsConfig from './+docs'
82
88
 
83
89
  export { config }
84
90
 
85
- const config = createNivelVikeConfig(docsConfig)
91
+ const themePreference = docsConfig.theme?.defaultPreference ?? 'light'
92
+ const dataTheme =
93
+ themePreference === 'dark'
94
+ ? (docsConfig.theme?.dark ?? 'consumer-dark')
95
+ : (docsConfig.theme?.light ?? 'consumer-light')
96
+
97
+ const config: Config = {
98
+ ...nivel,
99
+ extends: [vikeReact],
100
+ title: docsConfig.siteTitle,
101
+ description: docsConfig.siteDescription ?? `${docsConfig.siteTitle} documentation`,
102
+ htmlAttributes: { 'data-theme': dataTheme },
103
+ passToClient: ['docs'],
104
+
105
+ // User-facing Vike levers stay visible here.
106
+ prerender: true,
107
+ // ssr: true,
108
+ // prefetchStaticAssets: 'viewport',
109
+ }
86
110
  ```
87
111
 
88
- `createNivelVikeConfig()` owns the standard `title`, `description`, Vike React extension, default `data-theme`, `passToClient`, and `prerender` wiring. Consumers can still spread or override it locally if they need extra Vike config.
112
+ The engine still owns the MDX, Vite, route-generation, and runtime wiring. The consumer keeps the normal Vike entry file and can adjust visible levers such as `prerender`, `ssr`, and prefetch-related settings directly in `+config.ts`.
89
113
 
90
114
  ## CLI
91
115
 
@@ -1,14 +1,16 @@
1
1
  import {
2
+ getDocsSourcePaths,
2
3
  isDocsSourcePath,
3
4
  loadDocsConfig,
4
5
  syncGeneratedDocsPages
5
- } from "./chunk-67GE3PJ6.js";
6
+ } from "./chunk-G7DN5RH7.js";
6
7
  import {
7
8
  nivelPublicRoute
8
- } from "./chunk-PYYPYIBD.js";
9
+ } from "./chunk-CL74JUQ4.js";
9
10
 
10
11
  // src/runtime/node/plugin.ts
11
12
  import fs2 from "fs";
13
+ import path2 from "path";
12
14
 
13
15
  // src/runtime/node/publicAssets.ts
14
16
  import fs from "fs";
@@ -109,15 +111,25 @@ var isNivelAssetPath = (filePath) => {
109
111
  };
110
112
 
111
113
  // src/runtime/node/plugin.ts
112
- var syncGeneratedPages = async (server, rootDir) => {
114
+ var syncGeneratedPages = async (server, rootDir, onDocsSourcesResolved) => {
113
115
  const docsConfig = await loadDocsConfig({
114
116
  rootDir,
115
117
  loadModule: (modulePath) => server.ssrLoadModule(modulePath)
116
118
  });
119
+ onDocsSourcesResolved(getDocsSourcePaths({ rootDir, docsConfig }));
117
120
  syncGeneratedDocsPages({ rootDir, docsConfig });
118
121
  };
122
+ var getDefaultDocsSourcePaths = (rootDir) => {
123
+ return {
124
+ contentRootPath: path2.join(rootDir, "docs"),
125
+ docsConfigPath: path2.join(rootDir, "pages", "+docs.ts"),
126
+ docsGraphPath: path2.join(rootDir, "docs", "docs.graph.ts"),
127
+ generatedRootPath: path2.join(rootDir, "pages", "(nivel-generated)")
128
+ };
129
+ };
119
130
  var nivelPagesPlugin = () => {
120
131
  let shouldEmitBuildAssets = false;
132
+ let docsSourcePaths = null;
121
133
  return {
122
134
  name: "nivel-pages-plugin",
123
135
  enforce: "pre",
@@ -140,13 +152,39 @@ var nivelPagesPlugin = () => {
140
152
  const rootDir = server.config.root;
141
153
  const assetsRoot = getNivelPublicAssetsRoot();
142
154
  let pendingSync = Promise.resolve();
155
+ docsSourcePaths = getDefaultDocsSourcePaths(rootDir);
143
156
  server.watcher.add(assetsRoot);
157
+ server.watcher.add([
158
+ docsSourcePaths.docsConfigPath,
159
+ docsSourcePaths.docsGraphPath,
160
+ docsSourcePaths.contentRootPath
161
+ ]);
162
+ const updateDocsSourcePaths = (nextDocsSourcePaths) => {
163
+ if (!docsSourcePaths) {
164
+ docsSourcePaths = nextDocsSourcePaths;
165
+ server.watcher.add(nextDocsSourcePaths.contentRootPath);
166
+ return;
167
+ }
168
+ if (nextDocsSourcePaths.contentRootPath !== docsSourcePaths.contentRootPath) {
169
+ server.watcher.unwatch(docsSourcePaths.contentRootPath);
170
+ server.watcher.add(nextDocsSourcePaths.contentRootPath);
171
+ }
172
+ docsSourcePaths = nextDocsSourcePaths;
173
+ };
174
+ void loadDocsConfig({
175
+ rootDir,
176
+ loadModule: (modulePath) => server.ssrLoadModule(modulePath)
177
+ }).then((docsConfig) => {
178
+ updateDocsSourcePaths(getDocsSourcePaths({ rootDir, docsConfig }));
179
+ }).catch((error) => {
180
+ console.error(error);
181
+ });
144
182
  const queueSync = (filePath) => {
145
- if (!isDocsSourcePath(filePath, rootDir)) {
183
+ if (!docsSourcePaths || !isDocsSourcePath(filePath, docsSourcePaths)) {
146
184
  return;
147
185
  }
148
186
  pendingSync = pendingSync.then(async () => {
149
- await syncGeneratedPages(server, rootDir);
187
+ await syncGeneratedPages(server, rootDir, updateDocsSourcePaths);
150
188
  server.ws.send({ type: "full-reload" });
151
189
  }).catch((error) => {
152
190
  console.error(error);
@@ -182,10 +220,14 @@ var nivelPagesPlugin = () => {
182
220
  ctx.server.ws.send({ type: "full-reload" });
183
221
  return [];
184
222
  }
185
- if (!isDocsSourcePath(ctx.file, ctx.server.config.root)) {
223
+ const rootDir = ctx.server.config.root;
224
+ const resolvedDocsSourcePaths = docsSourcePaths ?? getDefaultDocsSourcePaths(rootDir);
225
+ if (!isDocsSourcePath(ctx.file, resolvedDocsSourcePaths)) {
186
226
  return;
187
227
  }
188
- await syncGeneratedPages(ctx.server, ctx.server.config.root);
228
+ await syncGeneratedPages(ctx.server, rootDir, (nextDocsSourcePaths) => {
229
+ docsSourcePaths = nextDocsSourcePaths;
230
+ });
189
231
  ctx.server.ws.send({ type: "full-reload" });
190
232
  return [];
191
233
  }
@@ -195,4 +237,4 @@ var nivelPagesPlugin = () => {
195
237
  export {
196
238
  nivelPagesPlugin
197
239
  };
198
- //# sourceMappingURL=chunk-AURANIZE.js.map
240
+ //# sourceMappingURL=chunk-4XQN7OBV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/node/plugin.ts","../src/runtime/node/publicAssets.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin, ViteDevServer } from 'vite'\nimport { getDocsSourcePaths, isDocsSourcePath, syncGeneratedDocsPages, type DocsSourcePaths } from './codegen.js'\nimport {\n getNivelPublicAssetContentType,\n getNivelPublicAssetFilePath,\n getNivelPublicAssets,\n getNivelPublicAssetsRoot,\n isNivelAssetPath,\n isNivelAssetRequestUrl,\n} from './publicAssets.js'\nimport { loadDocsConfig } from './loadDocsConfig.js'\n\nconst syncGeneratedPages = async (\n server: ViteDevServer,\n rootDir: string,\n onDocsSourcesResolved: (docsSourcePaths: DocsSourcePaths) => void,\n) => {\n const docsConfig = await loadDocsConfig({\n rootDir,\n loadModule: (modulePath) => server.ssrLoadModule(modulePath),\n })\n onDocsSourcesResolved(getDocsSourcePaths({ rootDir, docsConfig }))\n syncGeneratedDocsPages({ rootDir, docsConfig })\n}\n\nconst getDefaultDocsSourcePaths = (rootDir: string): DocsSourcePaths => {\n return {\n contentRootPath: path.join(rootDir, 'docs'),\n docsConfigPath: path.join(rootDir, 'pages', '+docs.ts'),\n docsGraphPath: path.join(rootDir, 'docs', 'docs.graph.ts'),\n generatedRootPath: path.join(rootDir, 'pages', '(nivel-generated)'),\n }\n}\n\nexport const nivelPagesPlugin = (): Plugin => {\n let shouldEmitBuildAssets = false\n let docsSourcePaths: DocsSourcePaths | null = null\n\n return {\n name: 'nivel-pages-plugin',\n enforce: 'pre',\n configResolved(config) {\n shouldEmitBuildAssets = config.command === 'build' && !config.build.ssr\n },\n buildStart() {\n if (!shouldEmitBuildAssets) {\n return\n }\n\n for (const asset of getNivelPublicAssets()) {\n this.emitFile({\n fileName: asset.fileName,\n source: fs.readFileSync(asset.filePath),\n type: 'asset',\n })\n }\n },\n configureServer(server) {\n const rootDir = server.config.root\n const assetsRoot = getNivelPublicAssetsRoot()\n let pendingSync = Promise.resolve()\n docsSourcePaths = getDefaultDocsSourcePaths(rootDir)\n\n server.watcher.add(assetsRoot)\n server.watcher.add([\n docsSourcePaths.docsConfigPath,\n docsSourcePaths.docsGraphPath,\n docsSourcePaths.contentRootPath,\n ])\n\n const updateDocsSourcePaths = (nextDocsSourcePaths: DocsSourcePaths) => {\n if (!docsSourcePaths) {\n docsSourcePaths = nextDocsSourcePaths\n server.watcher.add(nextDocsSourcePaths.contentRootPath)\n return\n }\n\n if (nextDocsSourcePaths.contentRootPath !== docsSourcePaths.contentRootPath) {\n server.watcher.unwatch(docsSourcePaths.contentRootPath)\n server.watcher.add(nextDocsSourcePaths.contentRootPath)\n }\n\n docsSourcePaths = nextDocsSourcePaths\n }\n\n void loadDocsConfig({\n rootDir,\n loadModule: (modulePath) => server.ssrLoadModule(modulePath),\n })\n .then((docsConfig) => {\n updateDocsSourcePaths(getDocsSourcePaths({ rootDir, docsConfig }))\n })\n .catch((error: unknown) => {\n console.error(error)\n })\n\n const queueSync = (filePath: string) => {\n if (!docsSourcePaths || !isDocsSourcePath(filePath, docsSourcePaths)) {\n return\n }\n\n pendingSync = pendingSync\n .then(async () => {\n await syncGeneratedPages(server, rootDir, updateDocsSourcePaths)\n server.ws.send({ type: 'full-reload' })\n })\n .catch((error: unknown) => {\n console.error(error)\n })\n }\n\n server.watcher.on('add', queueSync)\n server.watcher.on('unlink', queueSync)\n\n server.watcher.on('change', (filePath) => {\n if (!isNivelAssetPath(filePath)) {\n return\n }\n\n server.ws.send({ type: 'full-reload' })\n })\n\n server.middlewares.use((req, res, next) => {\n const filePath = getNivelPublicAssetFilePath(req.url)\n\n if (filePath) {\n res.setHeader('Content-Type', getNivelPublicAssetContentType(filePath))\n res.setHeader('Cache-Control', 'no-store')\n res.end(fs.readFileSync(filePath))\n return\n }\n\n if (isNivelAssetRequestUrl(req.url)) {\n res.statusCode = 404\n res.setHeader('Cache-Control', 'no-store')\n res.end()\n return\n }\n\n next()\n })\n },\n async handleHotUpdate(ctx) {\n if (isNivelAssetPath(ctx.file)) {\n ctx.server.ws.send({ type: 'full-reload' })\n return []\n }\n\n const rootDir = ctx.server.config.root\n const resolvedDocsSourcePaths = docsSourcePaths ?? getDefaultDocsSourcePaths(rootDir)\n\n if (!isDocsSourcePath(ctx.file, resolvedDocsSourcePaths)) {\n return\n }\n\n await syncGeneratedPages(ctx.server, rootDir, (nextDocsSourcePaths) => {\n docsSourcePaths = nextDocsSourcePaths\n })\n ctx.server.ws.send({ type: 'full-reload' })\n return []\n },\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { nivelPublicRoute } from '../../shared/assets.js'\n\nconst toPosix = (value: string) => value.split(path.sep).join(path.posix.sep)\n\nconst collectPublicAssetFilePaths = (directoryPath: string): string[] => {\n return fs.readdirSync(directoryPath, { withFileTypes: true }).flatMap((entry) => {\n const entryPath = path.join(directoryPath, entry.name)\n return entry.isDirectory() ? collectPublicAssetFilePaths(entryPath) : [entryPath]\n })\n}\n\nconst getRequestPathname = (requestUrl: string | undefined) => {\n return requestUrl?.split('?')[0]?.split('#')[0] ?? ''\n}\n\nconst normalizeNivelAssetPathname = (pathname: string) => {\n if (pathname === nivelPublicRoute) {\n return pathname\n }\n\n if (!pathname.startsWith(`${nivelPublicRoute}/`)) {\n return null\n }\n\n const trimmedPathname = pathname.replace(/\\/+$/g, '')\n if (trimmedPathname !== pathname && path.extname(trimmedPathname)) {\n return trimmedPathname\n }\n\n return pathname\n}\n\nconst getPublicAssetsRootCandidates = (runtimeDir: string) => {\n let packageRoot: string | null = null\n\n try {\n const nivelConfigUrl = import.meta.resolve('@unterberg/nivel/vike')\n const nivelConfigPath = fileURLToPath(nivelConfigUrl)\n packageRoot = path.resolve(path.dirname(nivelConfigPath), '..')\n } catch {\n packageRoot = null\n }\n\n return [\n ...(packageRoot ? [path.join(packageRoot, 'assets')] : []),\n path.resolve(runtimeDir, '../assets'),\n path.resolve(runtimeDir, '../../assets'),\n ]\n}\n\nexport const getNivelPublicAssetsRoot = () => {\n const runtimeUrl = import.meta.url.startsWith('/') ? pathToFileURL(import.meta.url).href : import.meta.url\n const runtimeDir = path.dirname(fileURLToPath(runtimeUrl))\n\n for (const candidate of getPublicAssetsRootCandidates(runtimeDir)) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {\n return candidate\n }\n }\n\n throw new Error(`Unable to locate nivel public assets from ${runtimeDir}.`)\n}\n\nexport const getNivelPublicAssets = () => {\n const assetsRoot = getNivelPublicAssetsRoot()\n\n return collectPublicAssetFilePaths(assetsRoot).map((filePath) => ({\n fileName: toPosix(path.relative(assetsRoot, filePath)),\n filePath,\n }))\n}\n\nexport const getNivelPublicAssetFilePath = (requestUrl: string | undefined) => {\n const pathname = normalizeNivelAssetPathname(getRequestPathname(requestUrl))\n\n if (!pathname) {\n return null\n }\n\n const assetsRoot = getNivelPublicAssetsRoot()\n const relativePath = pathname.replace(/^\\/+/, '')\n const filePath = path.resolve(assetsRoot, relativePath)\n const relativeToRoot = path.relative(assetsRoot, filePath)\n\n if (\n relativeToRoot.startsWith('..') ||\n path.isAbsolute(relativeToRoot) ||\n !fs.existsSync(filePath) ||\n !fs.statSync(filePath).isFile()\n ) {\n return null\n }\n\n return filePath\n}\n\nexport const getNivelPublicAssetContentType = (filePath: string) => {\n switch (path.extname(filePath)) {\n case '.css':\n return 'text/css; charset=utf-8'\n case '.svg':\n return 'image/svg+xml'\n case '.png':\n return 'image/png'\n case '.ico':\n return 'image/x-icon'\n case '.woff2':\n return 'font/woff2'\n default:\n return 'application/octet-stream'\n }\n}\n\nexport const isNivelAssetRequestUrl = (requestUrl: string | undefined) => {\n return normalizeNivelAssetPathname(getRequestPathname(requestUrl)) !== null\n}\n\nexport const isNivelAssetPath = (filePath: string) => {\n const normalizedFilePath = toPosix(path.resolve(filePath))\n const assetsRoot = toPosix(getNivelPublicAssetsRoot())\n return normalizedFilePath.startsWith(`${assetsRoot}/`)\n}\n"],"mappings":"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","names":["fs","path","path","fs"]}
@@ -1,21 +1,125 @@
1
- import {
2
- nivelAssetUrl,
3
- resolvePublicAssetUrl,
4
- withSiteBaseUrl
5
- } from "./chunk-PYYPYIBD.js";
1
+ // src/shared/assets.ts
2
+ var normalizeSiteBasePath = (value) => {
3
+ const normalized = value?.trim().replace(/^\/+|\/+$/g, "") ?? "";
4
+ return normalized ? `/${normalized}/` : "/";
5
+ };
6
+ var importMetaEnv = import.meta.env;
7
+ var siteBasePath = normalizeSiteBasePath(importMetaEnv?.BASE_URL ?? process.env.PAGES_BASE_PATH);
8
+ var isExternalUrl = (value) => value.startsWith("//") || /^[a-z][a-z\d+.-]*:/i.test(value);
9
+ var prependSiteBaseUrl = (value) => {
10
+ if (value === "" || value.startsWith("#") || isExternalUrl(value)) {
11
+ return value;
12
+ }
13
+ const pathname = value.startsWith("/") ? value : `/${value.replace(/^\/+/, "")}`;
14
+ return siteBasePath === "/" ? pathname : `${siteBasePath.slice(0, -1)}${pathname}`;
15
+ };
16
+ var withSiteBaseUrl = (value) => {
17
+ if (value === "" || value.startsWith("#") || isExternalUrl(value)) {
18
+ return value;
19
+ }
20
+ if (!value.startsWith("/")) {
21
+ return value;
22
+ }
23
+ if (siteBasePath !== "/" && (value === siteBasePath.slice(0, -1) || value.startsWith(siteBasePath))) {
24
+ return value;
25
+ }
26
+ return siteBasePath === "/" ? value : `${siteBasePath.slice(0, -1)}${value}`;
27
+ };
28
+ var resolvePublicAssetUrl = (value) => {
29
+ if (!value) {
30
+ return void 0;
31
+ }
32
+ if (value.startsWith("#") || isExternalUrl(value)) {
33
+ return value;
34
+ }
35
+ const pathname = value.startsWith("/") ? value : `/${value.replace(/^\/+/, "")}`;
36
+ return withSiteBaseUrl(pathname);
37
+ };
38
+ var nivelPublicRoute = "/nivel";
39
+ var baseAssets = `${prependSiteBaseUrl(nivelPublicRoute).replace(/\/?$/, "/")}`;
40
+ var nivelAssetUrl = (assetPath) => `${baseAssets}${assetPath.replace(/^\/+/, "")}`;
6
41
 
7
42
  // src/docs/resolveDocsConfig.ts
43
+ var isExternalHref = (value) => {
44
+ return /^(?:[a-z]+:)?\/\//i.test(value) || value.startsWith("mailto:") || value.startsWith("tel:");
45
+ };
8
46
  var normalizeBasePath = (value) => {
9
- const normalized = value.trim().replace(/^\/+|\/+$/g, "");
10
- return `/${normalized}`;
47
+ const normalized = value.trim();
48
+ if (!normalized) {
49
+ throw new Error("Docs basePath must be a non-empty absolute path.");
50
+ }
51
+ if (!normalized.startsWith("/") || normalized.startsWith("//")) {
52
+ throw new Error(`Docs basePath must start with "/". Received ${JSON.stringify(value)}.`);
53
+ }
54
+ if (normalized.includes("?") || normalized.includes("#")) {
55
+ throw new Error(`Docs basePath cannot include query strings or hashes. Received ${JSON.stringify(value)}.`);
56
+ }
57
+ const collapsed = normalized.replace(/\/+/g, "/").replace(/\/+$/g, "");
58
+ return collapsed === "" ? "/" : collapsed;
59
+ };
60
+ var normalizeContentDir = (value) => {
61
+ const normalized = (value ?? "docs").trim();
62
+ if (!normalized) {
63
+ throw new Error("Docs contentDir must be a non-empty project-relative path.");
64
+ }
65
+ if (normalized.startsWith("/") || normalized.startsWith("\\")) {
66
+ throw new Error(`Docs contentDir must be project-relative. Received ${JSON.stringify(value)}.`);
67
+ }
68
+ if (/^[a-zA-Z]:[\\/]/.test(normalized)) {
69
+ throw new Error(`Docs contentDir must be project-relative. Received ${JSON.stringify(value)}.`);
70
+ }
71
+ const segments = normalized.replaceAll("\\", "/").split("/");
72
+ const resolvedSegments = [];
73
+ for (const segment of segments) {
74
+ if (segment === "" || segment === ".") {
75
+ continue;
76
+ }
77
+ if (segment === "..") {
78
+ throw new Error(`Docs contentDir cannot escape the project root. Received ${JSON.stringify(value)}.`);
79
+ }
80
+ resolvedSegments.push(segment);
81
+ }
82
+ if (resolvedSegments.length === 0) {
83
+ throw new Error(`Docs contentDir must contain at least one path segment. Received ${JSON.stringify(value)}.`);
84
+ }
85
+ return resolvedSegments.join("/");
11
86
  };
12
87
  var normalizeSlug = (value) => value.replace(/^\/+|\/+$/g, "");
13
- var joinHref = (basePath, slug) => `${basePath}/${normalizeSlug(slug)}/`;
88
+ var joinDocsHref = (basePath, slug) => {
89
+ const normalizedBasePath = normalizeBasePath(basePath);
90
+ const normalizedSlug = normalizeSlug(slug);
91
+ if (!normalizedSlug) {
92
+ return normalizedBasePath === "/" ? "/" : `${normalizedBasePath}/`;
93
+ }
94
+ return normalizedBasePath === "/" ? `/${normalizedSlug}/` : `${normalizedBasePath}/${normalizedSlug}/`;
95
+ };
14
96
  var normalizePathname = (value) => {
15
97
  const pathname = value.split("?")[0]?.split("#")[0] ?? value;
16
98
  const normalized = pathname.trim().replace(/\/+$/g, "");
17
99
  return normalized === "" ? "/" : `${normalized}/`.replace(/\/+/g, "/");
18
100
  };
101
+ var resolveDocsHref = (basePath, href) => {
102
+ const normalized = href.trim();
103
+ if (!normalized || normalized.startsWith("#") || isExternalHref(normalized)) {
104
+ return null;
105
+ }
106
+ const pathname = normalized.split("?")[0]?.split("#")[0] ?? normalized;
107
+ if (!pathname) {
108
+ return null;
109
+ }
110
+ if (pathname.startsWith("/")) {
111
+ const normalizedPathname = normalizePathname(pathname);
112
+ const normalizedBasePath = normalizeBasePath(basePath);
113
+ if (normalizedBasePath === "/") {
114
+ return normalizedPathname;
115
+ }
116
+ return normalizedPathname === `${normalizedBasePath}/` || normalizedPathname.startsWith(`${normalizedBasePath}/`) ? normalizedPathname : null;
117
+ }
118
+ if (pathname.startsWith("./") || pathname.startsWith("../")) {
119
+ return null;
120
+ }
121
+ return joinDocsHref(basePath, pathname);
122
+ };
19
123
  var normalizeSourcePath = (value) => {
20
124
  const segments = value.replaceAll("\\", "/").split("/");
21
125
  const normalizedSegments = [];
@@ -51,11 +155,17 @@ var getSectionHref = (items, visibleOnly = false) => {
51
155
  }
52
156
  return null;
53
157
  };
54
- var resolveNavigationHref = (value, fieldName) => {
158
+ var resolveNavigationHref = (value, fieldName, basePath) => {
55
159
  const normalized = value.trim();
56
160
  if (!normalized) {
57
161
  throw new Error(`Docs ${fieldName} must be a non-empty string.`);
58
162
  }
163
+ if (normalized.startsWith("#") || isExternalHref(normalized)) {
164
+ return normalized;
165
+ }
166
+ if (!normalized.startsWith("/")) {
167
+ return joinDocsHref(basePath, normalized);
168
+ }
59
169
  return normalizePathname(normalized);
60
170
  };
61
171
  var resolveThemeConfig = (theme) => {
@@ -154,9 +264,8 @@ var normalizeAliases = (aliases, slug) => {
154
264
  return [...normalizedAliases];
155
265
  };
156
266
  var resolveDocsConfig = (config) => {
157
- if (normalizeBasePath(config.basePath) !== "/docs") {
158
- throw new Error(`nivel currently requires basePath to be "/docs". Received ${JSON.stringify(config.basePath)}.`);
159
- }
267
+ const normalizedBasePath = normalizeBasePath(config.basePath);
268
+ const normalizedContentDir = normalizeContentDir(config.contentDir);
160
269
  const pageIds = /* @__PURE__ */ new Set();
161
270
  const pageSlugs = /* @__PURE__ */ new Set();
162
271
  const pageAliases = /* @__PURE__ */ new Set();
@@ -175,7 +284,7 @@ var resolveDocsConfig = (config) => {
175
284
  kind: "group",
176
285
  id: node.id,
177
286
  title: node.title,
178
- href: node.href ? resolveNavigationHref(node.href, `group "${node.id}" href`) : void 0,
287
+ href: node.href ? resolveNavigationHref(node.href, `group "${node.id}" href`, normalizedBasePath) : void 0,
179
288
  showInNav: node.showInNav ?? true,
180
289
  collapsible: node.collapsible,
181
290
  items: resolveSidebarNodes(node.items, sectionId)
@@ -206,13 +315,13 @@ var resolveDocsConfig = (config) => {
206
315
  for (const alias of aliases) {
207
316
  pageAliases.add(alias);
208
317
  }
209
- const href = joinHref("/docs", slug);
318
+ const href = joinDocsHref(normalizedBasePath, slug);
210
319
  const page = {
211
320
  ...pageNode,
212
321
  slug,
213
322
  aliases,
214
323
  href,
215
- aliasHrefs: aliases.map((alias) => joinHref("/docs", alias)),
324
+ aliasHrefs: aliases.map((alias) => joinDocsHref(normalizedBasePath, alias)),
216
325
  tableOfContents: pageNode.tableOfContents ?? true,
217
326
  sectionId,
218
327
  documentTitle: `${pageNode.title} | ${config.siteTitle}`,
@@ -239,7 +348,7 @@ var resolveDocsConfig = (config) => {
239
348
  sectionIds.add(section.id);
240
349
  const items = resolveSidebarNodes(section.items, section.id);
241
350
  const firstVisibleHref = getSectionHref(items, true);
242
- const href = section.href ? resolveNavigationHref(section.href, `section "${section.id}" href`) : firstVisibleHref ?? getSectionHref(items);
351
+ const href = section.href ? resolveNavigationHref(section.href, `section "${section.id}" href`, normalizedBasePath) : firstVisibleHref ?? getSectionHref(items);
243
352
  if (!href) {
244
353
  throw new Error(`Docs section "${section.id}" must contain at least one page.`);
245
354
  }
@@ -263,7 +372,8 @@ var resolveDocsConfig = (config) => {
263
372
  return {
264
373
  siteTitle: config.siteTitle,
265
374
  siteDescription: config.siteDescription ?? null,
266
- basePath: "/docs",
375
+ basePath: normalizedBasePath,
376
+ contentDir: normalizedContentDir,
267
377
  theme: resolveThemeConfig(config.theme),
268
378
  footer: resolveFooterConfig(config.footer),
269
379
  brand: resolveBrandConfig(config.brand, config.siteTitle),
@@ -310,69 +420,13 @@ var isSamePagePathname = (page, pathname) => {
310
420
  return page.aliasHrefs.some((aliasHref) => normalizePathname(aliasHref) === normalizedPathname);
311
421
  };
312
422
 
313
- // src/docs/docHeadings.ts
314
- var normalizeWhitespace = (value) => value.replace(/\s+/g, " ").trim();
315
- var slugifyHeading = (value) => {
316
- const normalized = normalizeWhitespace(value).normalize("NFKD").toLowerCase().replace(/['"]/g, "").replace(/[^\p{Letter}\p{Number}\s-]/gu, " ").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
317
- return normalized || "section";
318
- };
319
- var createHeadingSlugger = () => {
320
- const slugCounts = /* @__PURE__ */ new Map();
321
- return (value) => {
322
- const baseSlug = slugifyHeading(value);
323
- const count = slugCounts.get(baseSlug) ?? 0;
324
- slugCounts.set(baseSlug, count + 1);
325
- return count === 0 ? baseSlug : `${baseSlug}-${count}`;
326
- };
327
- };
328
- var stripInlineMarkdown = (value) => {
329
- return normalizeWhitespace(
330
- value.replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/<[^>]+>/g, " ").replace(/\\([\\`*_[\]{}()#+\-.!])/g, "$1").replace(/[*_~]/g, "").replace(/\{[^}]+\}/g, " ")
331
- );
332
- };
333
- var getFenceMarker = (line) => {
334
- const match = line.match(/^\s{0,3}(`{3,}|~{3,})/);
335
- return match?.[1]?.[0] ?? null;
336
- };
337
- var extractDocHeadings = (source, minDepth = 2, maxDepth = 3) => {
338
- const slugify = createHeadingSlugger();
339
- const headings = [];
340
- let activeFenceMarker = null;
341
- for (const line of source.split("\n")) {
342
- const fenceMarker = getFenceMarker(line);
343
- if (activeFenceMarker) {
344
- if (fenceMarker === activeFenceMarker) {
345
- activeFenceMarker = null;
346
- }
347
- continue;
348
- }
349
- if (fenceMarker) {
350
- activeFenceMarker = fenceMarker;
351
- continue;
352
- }
353
- const match = line.match(/^\s{0,3}(#{1,6})\s+(.*?)(?:\s+#+\s*)?$/);
354
- if (!match) {
355
- continue;
356
- }
357
- const depth = match[1].length;
358
- const title = stripInlineMarkdown(match[2] ?? "");
359
- if (!title || depth < minDepth || depth > maxDepth) {
360
- continue;
361
- }
362
- headings.push({
363
- depth,
364
- id: slugify(title),
365
- title
366
- });
367
- }
368
- return headings;
369
- };
370
- var normalizeHeadingTitle = (value) => normalizeWhitespace(value);
371
-
372
423
  export {
373
- createHeadingSlugger,
374
- extractDocHeadings,
375
- normalizeHeadingTitle,
424
+ withSiteBaseUrl,
425
+ nivelPublicRoute,
426
+ baseAssets,
427
+ nivelAssetUrl,
428
+ isExternalHref,
429
+ resolveDocsHref,
376
430
  resolveDocsConfig,
377
431
  getResolvedPageById,
378
432
  getResolvedSectionById,
@@ -380,4 +434,4 @@ export {
380
434
  getActiveSectionByPathname,
381
435
  isSamePagePathname
382
436
  };
383
- //# sourceMappingURL=chunk-D7IAGT53.js.map
437
+ //# sourceMappingURL=chunk-CL74JUQ4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/assets.ts","../src/docs/resolveDocsConfig.ts"],"sourcesContent":["const normalizeSiteBasePath = (value: string | undefined) => {\n const normalized = value?.trim().replace(/^\\/+|\\/+$/g, '') ?? ''\n return normalized ? `/${normalized}/` : '/'\n}\n\nconst importMetaEnv = (import.meta as ImportMeta & { env?: { BASE_URL?: string } }).env\n\nconst siteBasePath = normalizeSiteBasePath(importMetaEnv?.BASE_URL ?? process.env.PAGES_BASE_PATH)\n\nconst isExternalUrl = (value: string) => value.startsWith('//') || /^[a-z][a-z\\d+.-]*:/i.test(value)\n\nconst prependSiteBaseUrl = (value: string) => {\n if (value === '' || value.startsWith('#') || isExternalUrl(value)) {\n return value\n }\n\n const pathname = value.startsWith('/') ? value : `/${value.replace(/^\\/+/, '')}`\n return siteBasePath === '/' ? pathname : `${siteBasePath.slice(0, -1)}${pathname}`\n}\n\nexport const withSiteBaseUrl = (value: string) => {\n if (value === '' || value.startsWith('#') || isExternalUrl(value)) {\n return value\n }\n\n if (!value.startsWith('/')) {\n return value\n }\n\n if (siteBasePath !== '/' && (value === siteBasePath.slice(0, -1) || value.startsWith(siteBasePath))) {\n return value\n }\n\n return siteBasePath === '/' ? value : `${siteBasePath.slice(0, -1)}${value}`\n}\n\nexport const resolvePublicAssetUrl = (value: string | undefined) => {\n if (!value) {\n return undefined\n }\n\n if (value.startsWith('#') || isExternalUrl(value)) {\n return value\n }\n\n const pathname = value.startsWith('/') ? value : `/${value.replace(/^\\/+/, '')}`\n return withSiteBaseUrl(pathname)\n}\n\nexport const nivelPublicRoute = '/nivel'\n\n// Engine-owned assets always live under the site base, even if the public route\n// happens to match the repository base path on GitHub Pages.\nexport const baseAssets = `${prependSiteBaseUrl(nivelPublicRoute).replace(/\\/?$/, '/')}`\n\nexport const nivelAssetUrl = (assetPath: string) => `${baseAssets}${assetPath.replace(/^\\/+/, '')}`\n","import { nivelAssetUrl, resolvePublicAssetUrl, withSiteBaseUrl } from '../shared/assets.js'\nimport type {\n DocsAlgoliaConfig,\n DocsBrandConfig,\n DocsConfig,\n DocsFooterConfig,\n DocsHeadConfig,\n DocsPartnerConfig,\n DocsPageNode,\n DocsSectionNode,\n DocsSidebarNode,\n ResolvedDocsAlgoliaConfig,\n ResolvedDocsBrandConfig,\n ResolvedDocsConfig,\n ResolvedDocsPartnerConfig,\n ResolvedDocsPage,\n ResolvedDocsPartnersConfig,\n ResolvedDocsSection,\n ResolvedNavbarItem,\n ResolvedSidebarNode,\n ThemePreference,\n} from './types.js'\n\nexport const isExternalHref = (value: string) => {\n return /^(?:[a-z]+:)?\\/\\//i.test(value) || value.startsWith('mailto:') || value.startsWith('tel:')\n}\n\nconst normalizeBasePath = (value: string) => {\n const normalized = value.trim()\n\n if (!normalized) {\n throw new Error('Docs basePath must be a non-empty absolute path.')\n }\n\n if (!normalized.startsWith('/') || normalized.startsWith('//')) {\n throw new Error(`Docs basePath must start with \"/\". Received ${JSON.stringify(value)}.`)\n }\n\n if (normalized.includes('?') || normalized.includes('#')) {\n throw new Error(`Docs basePath cannot include query strings or hashes. Received ${JSON.stringify(value)}.`)\n }\n\n const collapsed = normalized.replace(/\\/+/g, '/').replace(/\\/+$/g, '')\n return collapsed === '' ? '/' : collapsed\n}\n\nconst normalizeContentDir = (value: string | undefined) => {\n const normalized = (value ?? 'docs').trim()\n\n if (!normalized) {\n throw new Error('Docs contentDir must be a non-empty project-relative path.')\n }\n\n if (normalized.startsWith('/') || normalized.startsWith('\\\\')) {\n throw new Error(`Docs contentDir must be project-relative. Received ${JSON.stringify(value)}.`)\n }\n\n if (/^[a-zA-Z]:[\\\\/]/.test(normalized)) {\n throw new Error(`Docs contentDir must be project-relative. Received ${JSON.stringify(value)}.`)\n }\n\n const segments = normalized.replaceAll('\\\\', '/').split('/')\n const resolvedSegments: string[] = []\n\n for (const segment of segments) {\n if (segment === '' || segment === '.') {\n continue\n }\n\n if (segment === '..') {\n throw new Error(`Docs contentDir cannot escape the project root. Received ${JSON.stringify(value)}.`)\n }\n\n resolvedSegments.push(segment)\n }\n\n if (resolvedSegments.length === 0) {\n throw new Error(`Docs contentDir must contain at least one path segment. Received ${JSON.stringify(value)}.`)\n }\n\n return resolvedSegments.join('/')\n}\n\nconst normalizeSlug = (value: string) => value.replace(/^\\/+|\\/+$/g, '')\n\nconst joinDocsHref = (basePath: string, slug: string) => {\n const normalizedBasePath = normalizeBasePath(basePath)\n const normalizedSlug = normalizeSlug(slug)\n\n if (!normalizedSlug) {\n return normalizedBasePath === '/' ? '/' : `${normalizedBasePath}/`\n }\n\n return normalizedBasePath === '/' ? `/${normalizedSlug}/` : `${normalizedBasePath}/${normalizedSlug}/`\n}\n\nconst normalizePathname = (value: string) => {\n const pathname = value.split('?')[0]?.split('#')[0] ?? value\n const normalized = pathname.trim().replace(/\\/+$/g, '')\n return normalized === '' ? '/' : `${normalized}/`.replace(/\\/+/g, '/')\n}\n\nexport const resolveDocsHref = (basePath: string, href: string) => {\n const normalized = href.trim()\n\n if (!normalized || normalized.startsWith('#') || isExternalHref(normalized)) {\n return null\n }\n\n const pathname = normalized.split('?')[0]?.split('#')[0] ?? normalized\n\n if (!pathname) {\n return null\n }\n\n if (pathname.startsWith('/')) {\n const normalizedPathname = normalizePathname(pathname)\n const normalizedBasePath = normalizeBasePath(basePath)\n\n if (normalizedBasePath === '/') {\n return normalizedPathname\n }\n\n return normalizedPathname === `${normalizedBasePath}/` || normalizedPathname.startsWith(`${normalizedBasePath}/`)\n ? normalizedPathname\n : null\n }\n\n if (pathname.startsWith('./') || pathname.startsWith('../')) {\n return null\n }\n\n return joinDocsHref(basePath, pathname)\n}\n\nconst normalizeSourcePath = (value: string) => {\n const segments = value.replaceAll('\\\\', '/').split('/')\n const normalizedSegments: string[] = []\n\n for (const segment of segments) {\n if (segment === '' || segment === '.') {\n continue\n }\n\n if (segment === '..') {\n normalizedSegments.pop()\n continue\n }\n\n normalizedSegments.push(segment)\n }\n\n return normalizedSegments.join('/')\n}\n\nconst getSectionHref = (items: ResolvedSidebarNode[], visibleOnly = false): string | null => {\n for (const item of items) {\n if (item.kind === 'page') {\n if (visibleOnly && !item.showInNav) {\n continue\n }\n\n return item.href\n }\n\n if (item.kind === 'group') {\n if (visibleOnly && !item.showInNav) {\n continue\n }\n\n const href = getSectionHref(item.items, visibleOnly)\n if (href) {\n return href\n }\n }\n }\n\n return null\n}\n\nconst resolveNavigationHref = (value: string, fieldName: string, basePath: string) => {\n const normalized = value.trim()\n\n if (!normalized) {\n throw new Error(`Docs ${fieldName} must be a non-empty string.`)\n }\n\n if (normalized.startsWith('#') || isExternalHref(normalized)) {\n return normalized\n }\n\n if (!normalized.startsWith('/')) {\n return joinDocsHref(basePath, normalized)\n }\n\n return normalizePathname(normalized)\n}\n\nconst resolveThemeConfig = (theme: DocsConfig['theme']) => {\n return {\n light: theme?.light ?? 'consumer-light',\n dark: theme?.dark ?? 'consumer-dark',\n defaultPreference: (theme?.defaultPreference ?? 'light') as ThemePreference,\n }\n}\n\nconst resolveFooterConfig = (footer: DocsFooterConfig | undefined) => {\n return {\n pagination: footer?.pagination ?? false,\n }\n}\n\nconst resolveBrandConfig = (brand: DocsBrandConfig | undefined, siteTitle: string): ResolvedDocsBrandConfig => {\n const text = brand?.text ?? siteTitle\n\n return {\n text,\n href: withSiteBaseUrl(brand?.href ?? '/'),\n logoLight: resolvePublicAssetUrl(brand?.logoLight),\n logoDark: resolvePublicAssetUrl(brand?.logoDark),\n logoAlt: brand?.logoAlt ?? `${text} logo`,\n }\n}\n\nconst resolveHeadConfig = (head: DocsHeadConfig | undefined) => {\n const fontPreset = head?.fontPreset ?? 'inter'\n const defaultFontStylesheetHref = fontPreset === 'inter' ? nivelAssetUrl('fonts/fonts-inter.css') : undefined\n const defaultFontPreloadHrefs =\n fontPreset === 'inter'\n ? [\n nivelAssetUrl('fonts/inter-v20-latin-regular.woff2'),\n nivelAssetUrl('fonts/inter-v20-latin-600.woff2'),\n nivelAssetUrl('fonts/inter-v20-latin-800.woff2'),\n ]\n : []\n\n return {\n faviconSvg: resolvePublicAssetUrl(head?.faviconSvg),\n faviconIco: resolvePublicAssetUrl(head?.faviconIco),\n appleTouchIcon: resolvePublicAssetUrl(head?.appleTouchIcon),\n fontPreset,\n fontStylesheetHref: head?.fontStylesheetHref ?? defaultFontStylesheetHref,\n fontPreloadHrefs: head?.fontPreloadHrefs ?? defaultFontPreloadHrefs,\n }\n}\n\nconst resolvePartnerAssetUrl = (value: string | undefined) => {\n if (!value) {\n return undefined\n }\n\n return resolvePublicAssetUrl(value)\n}\n\nconst resolvePartner = (partner: DocsPartnerConfig): ResolvedDocsPartnerConfig => {\n return {\n name: partner.name,\n href: withSiteBaseUrl(partner.href),\n logoLight: resolvePartnerAssetUrl(partner.logoLight) ?? partner.logoLight,\n logoDark: resolvePartnerAssetUrl(partner.logoDark),\n logoAlt: partner.logoAlt ?? `${partner.name} logo`,\n }\n}\n\nconst resolvePartnersConfig = (partners: DocsConfig['partners']): ResolvedDocsPartnersConfig => {\n return {\n primary: (partners?.primary ?? []).map(resolvePartner),\n gold: (partners?.gold ?? []).map(resolvePartner),\n }\n}\n\nconst requireTrimmedString = (value: string, fieldName: string) => {\n const normalized = value.trim()\n\n if (!normalized) {\n throw new Error(`Docs algolia config \"${fieldName}\" must be a non-empty string.`)\n }\n\n return normalized\n}\n\nconst resolveAlgoliaConfig = (algolia: DocsAlgoliaConfig | undefined): ResolvedDocsAlgoliaConfig | null => {\n if (!algolia) {\n return null\n }\n\n return {\n appId: requireTrimmedString(algolia.appId, 'appId'),\n apiKey: requireTrimmedString(algolia.apiKey, 'apiKey'),\n indexName: requireTrimmedString(algolia.indexName, 'indexName'),\n fields: {\n href: algolia.fields?.href?.trim() || 'href',\n title: algolia.fields?.title?.trim() || 'title',\n excerpt: algolia.fields?.excerpt?.trim() || 'excerpt',\n sectionTitle: algolia.fields?.sectionTitle?.trim() || 'sectionTitle',\n },\n searchParams: algolia.searchParams ?? {},\n }\n}\n\nconst normalizeAliases = (aliases: string[] | undefined, slug: string) => {\n const normalizedAliases = new Set<string>()\n\n for (const alias of aliases ?? []) {\n const normalizedAlias = normalizeSlug(alias)\n if (!normalizedAlias || normalizedAlias === slug) {\n continue\n }\n\n normalizedAliases.add(normalizedAlias)\n }\n\n return [...normalizedAliases]\n}\n\nexport const resolveDocsConfig = (config: DocsConfig): ResolvedDocsConfig => {\n const normalizedBasePath = normalizeBasePath(config.basePath)\n const normalizedContentDir = normalizeContentDir(config.contentDir)\n\n const pageIds = new Set<string>()\n const pageSlugs = new Set<string>()\n const pageAliases = new Set<string>()\n const groupIds = new Set<string>()\n const sectionIds = new Set<string>()\n const pages: ResolvedDocsPage[] = []\n const navbarItems: ResolvedNavbarItem[] = []\n\n const resolveSidebarNodes = (nodes: DocsSidebarNode[], sectionId: string): ResolvedSidebarNode[] => {\n return nodes.map((node) => {\n if (node.kind === 'group') {\n if (groupIds.has(node.id)) {\n throw new Error(`Duplicate docs group id \"${node.id}\".`)\n }\n\n groupIds.add(node.id)\n\n return {\n kind: 'group',\n id: node.id,\n title: node.title,\n href: node.href ? resolveNavigationHref(node.href, `group \"${node.id}\" href`, normalizedBasePath) : undefined,\n showInNav: node.showInNav ?? true,\n collapsible: node.collapsible,\n items: resolveSidebarNodes(node.items, sectionId),\n }\n }\n\n if (node.kind !== 'page') {\n throw new Error(`Invalid docs sidebar node: ${JSON.stringify(node)}`)\n }\n\n const pageNode = node as DocsPageNode\n const slug = normalizeSlug(pageNode.slug)\n const aliases = normalizeAliases(pageNode.aliases, slug)\n\n if (!slug) {\n throw new Error(`Docs page \"${pageNode.id}\" must define a non-empty slug.`)\n }\n\n if (pageIds.has(pageNode.id)) {\n throw new Error(`Duplicate docs page id \"${pageNode.id}\".`)\n }\n\n if (pageSlugs.has(slug)) {\n throw new Error(`Duplicate docs page slug \"${slug}\".`)\n }\n\n for (const alias of aliases) {\n if (pageSlugs.has(alias) || pageAliases.has(alias)) {\n throw new Error(`Duplicate docs page alias \"${alias}\".`)\n }\n }\n\n pageIds.add(pageNode.id)\n pageSlugs.add(slug)\n for (const alias of aliases) {\n pageAliases.add(alias)\n }\n\n const href = joinDocsHref(normalizedBasePath, slug)\n const page: ResolvedDocsPage = {\n ...pageNode,\n slug,\n aliases,\n href,\n aliasHrefs: aliases.map((alias) => joinDocsHref(normalizedBasePath, alias)),\n tableOfContents: pageNode.tableOfContents ?? true,\n sectionId,\n documentTitle: `${pageNode.title} | ${config.siteTitle}`,\n source: normalizeSourcePath(pageNode.source),\n }\n pages.push(page)\n\n return {\n kind: 'page',\n id: pageNode.id,\n title: pageNode.title,\n navTitle: pageNode.navTitle ?? pageNode.title,\n href,\n showInNav: pageNode.showInNav ?? true,\n }\n })\n }\n\n const sections: ResolvedDocsSection[] = config.graph.items.map((section: DocsSectionNode) => {\n if (section.kind !== 'section') {\n throw new Error(`Top-level docs graph items must be sections. Received ${JSON.stringify(section)}`)\n }\n\n if (sectionIds.has(section.id)) {\n throw new Error(`Duplicate docs section id \"${section.id}\".`)\n }\n\n sectionIds.add(section.id)\n\n const items = resolveSidebarNodes(section.items, section.id)\n const firstVisibleHref = getSectionHref(items, true)\n const href = section.href\n ? resolveNavigationHref(section.href, `section \"${section.id}\" href`, normalizedBasePath)\n : (firstVisibleHref ?? getSectionHref(items))\n\n if (!href) {\n throw new Error(`Docs section \"${section.id}\" must contain at least one page.`)\n }\n\n const resolvedSection: ResolvedDocsSection = {\n id: section.id,\n title: section.title,\n navTitle: section.navTitle ?? section.title,\n href,\n items,\n }\n\n navbarItems.push({\n id: section.id,\n title: resolvedSection.navTitle,\n href: resolvedSection.href,\n })\n\n return resolvedSection\n })\n\n if (pages.length === 0) {\n throw new Error('Docs graph must contain at least one page.')\n }\n\n return {\n siteTitle: config.siteTitle,\n siteDescription: config.siteDescription ?? null,\n basePath: normalizedBasePath,\n contentDir: normalizedContentDir,\n theme: resolveThemeConfig(config.theme),\n footer: resolveFooterConfig(config.footer),\n brand: resolveBrandConfig(config.brand, config.siteTitle),\n head: resolveHeadConfig(config.head),\n partners: resolvePartnersConfig(config.partners),\n algolia: resolveAlgoliaConfig(config.algolia),\n pages,\n sections,\n navbarItems,\n }\n}\n\nexport const getResolvedPageById = (config: { pages: ResolvedDocsPage[] }, pageId: string) => {\n const page = config.pages.find((candidate) => candidate.id === pageId)\n if (!page) {\n throw new Error(`Unknown docs page id \"${pageId}\".`)\n }\n return page\n}\n\nexport const getResolvedSectionById = (\n config: { sections?: ResolvedDocsSection[]; sidebarSections?: ResolvedDocsSection[] },\n sectionId: string,\n) => {\n const sections = config.sections ?? config.sidebarSections ?? []\n return sections.find((section) => section.id === sectionId) ?? null\n}\n\nexport const getResolvedPageByPathname = (config: { pages: ResolvedDocsPage[] }, pathname: string) => {\n const normalizedPathname = normalizePathname(pathname)\n\n return (\n config.pages.find((page) => {\n if (normalizePathname(page.href) === normalizedPathname) {\n return true\n }\n\n return page.aliasHrefs.some((aliasHref) => normalizePathname(aliasHref) === normalizedPathname)\n }) ?? null\n )\n}\n\nexport const getActiveSectionByPathname = (\n config: { pages: ResolvedDocsPage[]; sections?: ResolvedDocsSection[]; sidebarSections?: ResolvedDocsSection[] },\n pathname: string,\n) => {\n const activePage = getResolvedPageByPathname(config, pathname)\n\n if (!activePage) {\n return null\n }\n\n return getResolvedSectionById(config, activePage.sectionId)\n}\n\nexport const isSamePagePathname = (page: Pick<ResolvedDocsPage, 'href' | 'aliasHrefs'>, pathname: string) => {\n const normalizedPathname = normalizePathname(pathname)\n\n if (normalizePathname(page.href) === normalizedPathname) {\n return true\n }\n\n return page.aliasHrefs.some((aliasHref) => normalizePathname(aliasHref) === normalizedPathname)\n}\n"],"mappings":"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","names":[]}
@@ -1,18 +1,19 @@
1
1
  import {
2
2
  createHeadingSlugger,
3
- getActiveSectionByPathname,
4
- getResolvedPageByPathname,
5
- getResolvedSectionById,
6
- isSamePagePathname,
7
3
  normalizeHeadingTitle
8
- } from "./chunk-D7IAGT53.js";
4
+ } from "./chunk-SOVTSE5J.js";
9
5
  import {
10
6
  UniversalMdxProvider,
11
7
  renderInlineMarkdown
12
8
  } from "./chunk-L6ZVB6XH.js";
13
9
  import {
10
+ getActiveSectionByPathname,
11
+ getResolvedPageByPathname,
12
+ getResolvedSectionById,
13
+ isSamePagePathname,
14
+ resolveDocsHref,
14
15
  withSiteBaseUrl
15
- } from "./chunk-PYYPYIBD.js";
16
+ } from "./chunk-CL74JUQ4.js";
16
17
 
17
18
  // src/runtime/client/AppLayout.tsx
18
19
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
@@ -1400,26 +1401,13 @@ var splitHref = (href) => {
1400
1401
  hash: hash ? `#${hash}` : ""
1401
1402
  };
1402
1403
  };
1403
- var toDocsPathname = (basePath, href) => {
1404
- if (!href.startsWith("/")) {
1405
- return null;
1406
- }
1407
- if (href === basePath || href.startsWith(`${basePath}/`)) {
1408
- return href;
1409
- }
1410
- const normalizedPath = href.replace(/^\/+/, "");
1411
- if (!normalizedPath) {
1412
- return null;
1413
- }
1414
- return `${basePath}/${normalizedPath}`;
1415
- };
1416
1404
  var resolveDocLink = (options) => {
1417
1405
  const { currentPathname, href } = options;
1418
1406
  if (href.startsWith("#") || isExternalHref(href)) {
1419
1407
  return null;
1420
1408
  }
1421
1409
  const { pathname, hash } = splitHref(href);
1422
- const docsPathname = toDocsPathname(options.docs.basePath, pathname);
1410
+ const docsPathname = resolveDocsHref(options.docs.basePath, pathname);
1423
1411
  if (!docsPathname) {
1424
1412
  return null;
1425
1413
  }
@@ -1458,9 +1446,12 @@ var getMdxRuntimeValue = (options) => {
1458
1446
  return href;
1459
1447
  }
1460
1448
  const { pathname, hash } = splitHref(href);
1461
- const docsPathname = toDocsPathname(docs.basePath, pathname);
1449
+ const docsPathname = resolveDocsHref(docs.basePath, pathname);
1462
1450
  const page = docsPathname ? getResolvedPageByPathname(docs, docsPathname) : null;
1463
1451
  if (!page) {
1452
+ if (docsPathname && !pathname.startsWith("/")) {
1453
+ return withSiteBaseUrl(`${docsPathname}${hash}`);
1454
+ }
1464
1455
  return withSiteBaseUrl(href);
1465
1456
  }
1466
1457
  return withSiteBaseUrl(`${page.href}${hash}`);
@@ -1535,4 +1526,4 @@ export {
1535
1526
  ProseContainer,
1536
1527
  DocsPage
1537
1528
  };
1538
- //# sourceMappingURL=chunk-2EDJWL3U.js.map
1529
+ //# sourceMappingURL=chunk-DSQGGUBC.js.map