fumadocs-core 16.2.5 → 16.3.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.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-PFNP6PEB.js";
4
4
  import {
5
5
  findPath
6
- } from "./chunk-XKUN7AUK.js";
6
+ } from "./chunk-L4JKQWCM.js";
7
7
  import "./chunk-U67V476Y.js";
8
8
 
9
9
  // src/breadcrumb.tsx
@@ -88,7 +88,7 @@ function findPath(nodes, matcher, options = {}) {
88
88
  }
89
89
  return run(nodes) ?? null;
90
90
  }
91
- var VisitBreak = Symbol("VisitBreak");
91
+ var VisitBreak = /* @__PURE__ */ Symbol("VisitBreak");
92
92
  function visit(root, visitor) {
93
93
  function onNode(node, parent) {
94
94
  const result = visitor(node, parent);
@@ -251,6 +251,12 @@ interface Meta<Data = MetaData> extends SharedFileInfo {
251
251
  interface LoaderOutput<Config extends LoaderConfig> {
252
252
  pageTree: Config['i18n'] extends I18nConfig ? Record<string, Root> : Root;
253
253
  getPageTree: (locale?: string) => Root;
254
+ /**
255
+ * get referenced page from href, supported:
256
+ *
257
+ * - relative file paths, like `./my/page.mdx`.
258
+ * - generated page pathname, like `/docs/my/page`.
259
+ */
254
260
  getPageByHref: (href: string, options?: {
255
261
  language?: string;
256
262
  /**
@@ -261,6 +267,12 @@ interface LoaderOutput<Config extends LoaderConfig> {
261
267
  page: Page<Config['source']['pageData']>;
262
268
  hash?: string;
263
269
  } | undefined;
270
+ /**
271
+ * resolve special hrefs in a page, including:
272
+ *
273
+ * - relative file paths, like `./my/page.mdx`.
274
+ */
275
+ resolveHref: (href: string, parent: Page<Config['source']['pageData']>) => string;
264
276
  /**
265
277
  * @internal
266
278
  */
@@ -5,7 +5,7 @@ import {
5
5
  getPageTreePeers,
6
6
  getPageTreeRoots,
7
7
  visit
8
- } from "../chunk-XKUN7AUK.js";
8
+ } from "../chunk-L4JKQWCM.js";
9
9
  import "../chunk-U67V476Y.js";
10
10
  export {
11
11
  findNeighbour,
@@ -3,7 +3,7 @@ import { StructuredData } from '../mdx-plugins/remark-structure.js';
3
3
  import { SortedResult } from './index.js';
4
4
  export { HighlightedText, ReactSortedResult, createContentHighlighter } from './index.js';
5
5
  import { I18nConfig } from '../i18n/index.js';
6
- import { f as LoaderOutput, b as LoaderConfig, I as InferPageType } from '../loader-BvlPPJX0.js';
6
+ import { b as LoaderConfig, f as LoaderOutput, d as Page } from '../loader-_E2HOdV0.js';
7
7
  import 'mdast';
8
8
  import 'unified';
9
9
  import 'mdast-util-mdx-jsx';
@@ -31,13 +31,13 @@ declare const advancedSchema: {
31
31
  };
32
32
 
33
33
  type Awaitable<T> = T | Promise<T>;
34
- interface Options<S extends LoaderOutput<LoaderConfig>> extends Omit<AdvancedOptions, 'indexes'> {
34
+ interface Options<C extends LoaderConfig> extends Omit<AdvancedOptions, 'indexes'> {
35
35
  localeMap?: {
36
- [K in S extends LoaderOutput<infer C> ? C['i18n'] extends I18nConfig<infer Languages> ? Languages : string : string]?: Partial<AdvancedOptions> | Language;
36
+ [K in C['i18n'] extends I18nConfig<infer Languages> ? Languages : string]?: Partial<AdvancedOptions> | Language;
37
37
  };
38
- buildIndex?: (page: InferPageType<S>) => Awaitable<AdvancedIndex>;
38
+ buildIndex?: (page: Page<C['source']['pageData']>) => Awaitable<AdvancedIndex>;
39
39
  }
40
- declare function createFromSource<S extends LoaderOutput<LoaderConfig>>(source: S, options?: Options<S>): SearchAPI;
40
+ declare function createFromSource<C extends LoaderConfig>(source: LoaderOutput<C>, options?: Options<C>): SearchAPI;
41
41
 
42
42
  type I18nOptions<O extends SimpleOptions | AdvancedOptions, Idx> = Omit<O, 'language' | 'indexes'> & {
43
43
  i18n: I18nConfig;
@@ -12,7 +12,7 @@ import {
12
12
  } from "../chunk-XZSI7AHE.js";
13
13
  import {
14
14
  findPath
15
- } from "../chunk-XKUN7AUK.js";
15
+ } from "../chunk-L4JKQWCM.js";
16
16
  import "../chunk-U67V476Y.js";
17
17
 
18
18
  // src/search/server.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  visit
3
- } from "../../chunk-XKUN7AUK.js";
3
+ } from "../../chunk-L4JKQWCM.js";
4
4
  import "../../chunk-U67V476Y.js";
5
5
 
6
6
  // src/source/client/index.tsx
@@ -1,4 +1,4 @@
1
- export { C as ContentStorage, p as ContentStorageFile, F as FileSystem, h as InferMetaType, I as InferPageType, b as LoaderConfig, c as LoaderOptions, f as LoaderOutput, L as LoaderPlugin, r as LoaderPluginOption, e as Meta, M as MetaData, d as Page, P as PageData, n as PageTreeBuilder, i as PageTreeBuilderContext, k as PageTreeOptions, j as PageTreeTransformer, R as ResolvedLoaderConfig, S as Source, a as SourceConfig, V as VirtualFile, _ as _ConfigUnion_, q as buildContentStorage, t as buildPlugins, g as createGetUrl, o as createPageTreeBuilder, l as loader, m as multiple, s as source, u as update } from '../loader-BvlPPJX0.js';
1
+ export { C as ContentStorage, p as ContentStorageFile, F as FileSystem, h as InferMetaType, I as InferPageType, b as LoaderConfig, c as LoaderOptions, f as LoaderOutput, L as LoaderPlugin, r as LoaderPluginOption, e as Meta, M as MetaData, d as Page, P as PageData, n as PageTreeBuilder, i as PageTreeBuilderContext, k as PageTreeOptions, j as PageTreeTransformer, R as ResolvedLoaderConfig, S as Source, a as SourceConfig, V as VirtualFile, _ as _ConfigUnion_, q as buildContentStorage, t as buildPlugins, g as createGetUrl, o as createPageTreeBuilder, l as loader, m as multiple, s as source, u as update } from '../loader-_E2HOdV0.js';
2
2
  import '../definitions-pJ7PybYY.js';
3
3
  import 'react';
4
4
  import '../i18n/index.js';
@@ -15,7 +15,7 @@ import {
15
15
  } from "../chunk-PFNP6PEB.js";
16
16
  import {
17
17
  visit
18
- } from "../chunk-XKUN7AUK.js";
18
+ } from "../chunk-L4JKQWCM.js";
19
19
  import "../chunk-U67V476Y.js";
20
20
 
21
21
  // src/source/source.ts
@@ -81,22 +81,22 @@ var FileSystem = class {
81
81
  this.folders.set("", []);
82
82
  }
83
83
  }
84
- read(path) {
85
- return this.files.get(path);
84
+ read(path2) {
85
+ return this.files.get(path2);
86
86
  }
87
87
  /**
88
88
  * get the direct children of folder (in virtual file path)
89
89
  */
90
- readDir(path) {
91
- return this.folders.get(path);
90
+ readDir(path2) {
91
+ return this.folders.get(path2);
92
92
  }
93
- write(path, file) {
94
- if (!this.files.has(path)) {
95
- const dir = dirname(path);
93
+ write(path2, file) {
94
+ if (!this.files.has(path2)) {
95
+ const dir = dirname(path2);
96
96
  this.makeDir(dir);
97
- this.readDir(dir)?.push(path);
97
+ this.readDir(dir)?.push(path2);
98
98
  }
99
- this.files.set(path, file);
99
+ this.files.set(path2, file);
100
100
  }
101
101
  /**
102
102
  * Delete files at specified path.
@@ -104,12 +104,12 @@ var FileSystem = class {
104
104
  * @param path - the target path.
105
105
  * @param [recursive=false] - if set to `true`, it will also delete directories.
106
106
  */
107
- delete(path, recursive = false) {
108
- if (this.files.delete(path)) return true;
107
+ delete(path2, recursive = false) {
108
+ if (this.files.delete(path2)) return true;
109
109
  if (recursive) {
110
- const folder = this.folders.get(path);
110
+ const folder = this.folders.get(path2);
111
111
  if (!folder) return false;
112
- this.folders.delete(path);
112
+ this.folders.delete(path2);
113
113
  for (const child of folder) {
114
114
  this.delete(child);
115
115
  }
@@ -120,8 +120,8 @@ var FileSystem = class {
120
120
  getFiles() {
121
121
  return Array.from(this.files.keys());
122
122
  }
123
- makeDir(path) {
124
- const segments = splitPath(path);
123
+ makeDir(path2) {
124
+ const segments = splitPath(path2);
125
125
  for (let i = 0; i < segments.length; i++) {
126
126
  const segment = segments.slice(0, i + 1).join("/");
127
127
  if (this.folders.has(segment)) continue;
@@ -136,23 +136,23 @@ function isLocaleValid(locale) {
136
136
  return locale.length > 0 && !/\d+/.test(locale);
137
137
  }
138
138
  var parsers = {
139
- dir(path) {
140
- const [locale, ...segs] = path.split("/");
139
+ dir(path2) {
140
+ const [locale, ...segs] = path2.split("/");
141
141
  if (locale && segs.length > 0 && isLocaleValid(locale))
142
142
  return [segs.join("/"), locale];
143
- return [path];
143
+ return [path2];
144
144
  },
145
- dot(path) {
146
- const dir = dirname(path);
147
- const base = basename(path);
145
+ dot(path2) {
146
+ const dir = dirname(path2);
147
+ const base = basename(path2);
148
148
  const parts = base.split(".");
149
- if (parts.length < 3) return [path];
149
+ if (parts.length < 3) return [path2];
150
150
  const [locale] = parts.splice(parts.length - 2, 1);
151
- if (!isLocaleValid(locale)) return [path];
151
+ if (!isLocaleValid(locale)) return [path2];
152
152
  return [joinPath(dir, parts.join(".")), locale];
153
153
  },
154
- none(path) {
155
- return [path];
154
+ none(path2) {
155
+ return [path2];
156
156
  }
157
157
  };
158
158
  function buildContentStorage(loaderConfig, defaultLanguage) {
@@ -221,8 +221,8 @@ function buildContentStorage(loaderConfig, defaultLanguage) {
221
221
  for (const lang of i18n.languages) scan(lang);
222
222
  return storages;
223
223
  }
224
- function normalizePath(path) {
225
- const segments = splitPath(slash(path));
224
+ function normalizePath(path2) {
225
+ const segments = splitPath(slash(path2));
226
226
  if (segments[0] === "." || segments[0] === "..")
227
227
  throw new Error("It must not start with './' or '../'");
228
228
  return segments.join("/");
@@ -334,15 +334,15 @@ function createPageTreeBuilderUtils(ctx) {
334
334
  const sortedPaths = paths.sort(
335
335
  (a, b) => a.localeCompare(b) * (reversed ? -1 : 1)
336
336
  );
337
- for (const path of sortedPaths) {
338
- const fileNode = this.file(path);
337
+ for (const path2 of sortedPaths) {
338
+ const fileNode = this.file(path2);
339
339
  if (fileNode) {
340
- if (basename(path, extname(path)) === "index")
340
+ if (basename(path2, extname(path2)) === "index")
341
341
  items.unshift(fileNode);
342
342
  else items.push(fileNode);
343
343
  continue;
344
344
  }
345
- const dirNode = this.folder(path, false);
345
+ const dirNode = this.folder(path2, false);
346
346
  if (dirNode) folders.push(dirNode);
347
347
  }
348
348
  items.push(...folders);
@@ -389,16 +389,16 @@ function createPageTreeBuilderUtils(ctx) {
389
389
  } else if (isExtract) {
390
390
  filename = item.slice(extractPrefix.length);
391
391
  }
392
- const path = resolveFlattenPath(joinPath(folderPath, filename), "page");
392
+ const path2 = resolveFlattenPath(joinPath(folderPath, filename), "page");
393
393
  if (isExcept) {
394
- visitedPaths.add(path);
394
+ visitedPaths.add(path2);
395
395
  return [];
396
396
  }
397
- const dirNode = this.folder(path, false);
397
+ const dirNode = this.folder(path2, false);
398
398
  if (dirNode) {
399
399
  return isExtract ? dirNode.children : [dirNode];
400
400
  }
401
- const fileNode = this.file(path);
401
+ const fileNode = this.file(path2);
402
402
  return fileNode ? [fileNode] : [];
403
403
  },
404
404
  folder(folderPath, isGlobalRoot) {
@@ -465,26 +465,26 @@ function createPageTreeBuilderUtils(ctx) {
465
465
  }
466
466
  return node;
467
467
  },
468
- file(path) {
468
+ file(path2) {
469
469
  const { options, getUrl, storage, locale, transformers } = ctx;
470
- const page = storage.read(path);
470
+ const page = storage.read(path2);
471
471
  if (page?.format !== "page") return;
472
472
  const { title, description, icon } = page.data;
473
473
  let item = {
474
- $id: nextNodeId(path),
474
+ $id: nextNodeId(path2),
475
475
  type: "page",
476
- name: title ?? pathToName(basename(path, extname(path))),
476
+ name: title ?? pathToName(basename(path2, extname(path2))),
477
477
  description,
478
478
  icon,
479
479
  url: getUrl(page.slugs, locale),
480
480
  $ref: !options.noRef ? {
481
- file: path
481
+ file: path2
482
482
  } : void 0
483
483
  };
484
- visitedPaths.add(path);
484
+ visitedPaths.add(path2);
485
485
  for (const transformer of transformers) {
486
486
  if (!transformer.file) continue;
487
- item = transformer.file.call(ctx, item, path);
487
+ item = transformer.file.call(ctx, item, path2);
488
488
  }
489
489
  return item;
490
490
  },
@@ -543,22 +543,22 @@ function slugsPlugin(slugsFn) {
543
543
  const indexFiles = /* @__PURE__ */ new Set();
544
544
  const taken = /* @__PURE__ */ new Set();
545
545
  const autoIndex = slugsFn === void 0;
546
- for (const path of storage.getFiles()) {
547
- const file = storage.read(path);
546
+ for (const path2 of storage.getFiles()) {
547
+ const file = storage.read(path2);
548
548
  if (!file || file.format !== "page" || file.slugs) continue;
549
- if (isIndex(path) && autoIndex) {
550
- indexFiles.add(path);
549
+ if (isIndex(path2) && autoIndex) {
550
+ indexFiles.add(path2);
551
551
  continue;
552
552
  }
553
- file.slugs = slugsFn ? slugsFn({ path }) : getSlugs(path);
553
+ file.slugs = slugsFn ? slugsFn({ path: path2 }) : getSlugs(path2);
554
554
  const key = file.slugs.join("/");
555
555
  if (taken.has(key)) throw new Error("Duplicated slugs");
556
556
  taken.add(key);
557
557
  }
558
- for (const path of indexFiles) {
559
- const file = storage.read(path);
558
+ for (const path2 of indexFiles) {
559
+ const file = storage.read(path2);
560
560
  if (file?.format !== "page") continue;
561
- file.slugs = getSlugs(path);
561
+ file.slugs = getSlugs(path2);
562
562
  if (taken.has(file.slugs.join("/"))) file.slugs.push("index");
563
563
  }
564
564
  }
@@ -581,6 +581,7 @@ function getSlugs(file) {
581
581
  }
582
582
 
583
583
  // src/source/loader.ts
584
+ import path from "path";
584
585
  function indexPages(storages, { url }) {
585
586
  const result = {
586
587
  // (locale.slugs -> page)
@@ -593,9 +594,9 @@ function indexPages(storages, { url }) {
593
594
  for (const [lang, storage] of Object.entries(storages)) {
594
595
  for (const filePath of storage.getFiles()) {
595
596
  const item = storage.read(filePath);
596
- const path = `${lang}.${filePath}`;
597
+ const path2 = `${lang}.${filePath}`;
597
598
  if (item.format === "meta") {
598
- result.pathToMeta.set(path, {
599
+ result.pathToMeta.set(path2, {
599
600
  path: item.path,
600
601
  absolutePath: item.absolutePath,
601
602
  data: item.data
@@ -610,7 +611,7 @@ function indexPages(storages, { url }) {
610
611
  data: item.data,
611
612
  locale: lang
612
613
  };
613
- result.pathToPage.set(path, page);
614
+ result.pathToPage.set(path2, page);
614
615
  result.pages.set(`${lang}.${page.slugs.join("/")}`, page);
615
616
  }
616
617
  }
@@ -659,9 +660,9 @@ function loader(...args) {
659
660
  getPageByHref(href, { dir = "", language = defaultLanguage } = {}) {
660
661
  const [value, hash] = href.split("#", 2);
661
662
  let target;
662
- if (value.startsWith(".") && (value.endsWith(".md") || value.endsWith(".mdx"))) {
663
- const path = joinPath(dir, value);
664
- target = walker.pathToPage.get(`${language}.${path}`);
663
+ if (value.startsWith("./")) {
664
+ const path2 = joinPath(dir, value);
665
+ target = walker.pathToPage.get(`${language}.${path2}`);
665
666
  } else {
666
667
  target = this.getPages(language).find((item) => item.url === value);
667
668
  }
@@ -671,6 +672,18 @@ function loader(...args) {
671
672
  hash
672
673
  };
673
674
  },
675
+ resolveHref(href, parent) {
676
+ if (href.startsWith("./")) {
677
+ const target = this.getPageByHref(href, {
678
+ dir: path.dirname(parent.path),
679
+ language: parent.locale
680
+ });
681
+ if (target) {
682
+ return target.hash ? `${target.page.url}#${target.hash}` : target.page.url;
683
+ }
684
+ }
685
+ return href;
686
+ },
674
687
  getPages(language) {
675
688
  const pages = [];
676
689
  for (const [key, value] of walker.pages.entries()) {
@@ -1,4 +1,4 @@
1
- import { L as LoaderPlugin } from '../../loader-BvlPPJX0.js';
1
+ import { L as LoaderPlugin } from '../../loader-_E2HOdV0.js';
2
2
  import { icons } from 'lucide-react';
3
3
  import '../../definitions-pJ7PybYY.js';
4
4
  import 'react';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "16.2.5",
3
+ "version": "16.3.0",
4
4
  "description": "The React.js library for building a documentation website",
5
5
  "keywords": [
6
6
  "Fumadocs",
@@ -154,8 +154,8 @@
154
154
  "vfile": "^6.0.3",
155
155
  "waku": "^0.27.4",
156
156
  "zod": "^4.1.13",
157
- "eslint-config-custom": "0.0.0",
158
- "tsconfig": "0.0.0"
157
+ "tsconfig": "0.0.0",
158
+ "eslint-config-custom": "0.0.0"
159
159
  },
160
160
  "peerDependencies": {
161
161
  "@mixedbread/sdk": "^0.19.0",