fumadocs-core 16.2.4 → 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
@@ -0,0 +1,12 @@
1
+ // src/content/mdx/util.ts
2
+ async function resolvePlugins(def, options = []) {
3
+ const list = (await Promise.all(def(Array.isArray(options) ? options : []))).filter((v) => v !== false);
4
+ if (typeof options === "function") {
5
+ return Promise.all(options(list));
6
+ }
7
+ return list;
8
+ }
9
+
10
+ export {
11
+ resolvePlugins
12
+ };
@@ -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);
@@ -0,0 +1,31 @@
1
+ import { ProcessorOptions } from '@mdx-js/mdx';
2
+ import { RehypeCodeOptions } from '../../mdx-plugins/rehype-code.js';
3
+ import { RemarkImageOptions } from '../../mdx-plugins/remark-image.js';
4
+ import { StructureOptions } from '../../mdx-plugins/remark-structure.js';
5
+ import { RemarkHeadingOptions } from '../../mdx-plugins/remark-heading.js';
6
+ import { RemarkCodeTabOptions } from '../../mdx-plugins/remark-code-tab.js';
7
+ import { RemarkNpmOptions } from '../../mdx-plugins/remark-npm.js';
8
+ import { R as ResolvePlugins } from '../../util-bZU2QeJ2.js';
9
+ import 'hast';
10
+ import '@shikijs/rehype';
11
+ import 'unified';
12
+ import 'shiki';
13
+ import 'mdast';
14
+ import 'mdast-util-mdx-jsx';
15
+
16
+ type MDXBundlerPresetOptions = Omit<NonNullable<ProcessorOptions>, 'rehypePlugins' | 'remarkPlugins'> & {
17
+ rehypePlugins?: ResolvePlugins;
18
+ remarkPlugins?: ResolvePlugins;
19
+ remarkStructureOptions?: StructureOptions | false;
20
+ remarkHeadingOptions?: RemarkHeadingOptions;
21
+ remarkImageOptions?: RemarkImageOptions | false;
22
+ remarkCodeTabOptions?: RemarkCodeTabOptions | false;
23
+ remarkNpmOptions?: RemarkNpmOptions | false;
24
+ rehypeCodeOptions?: RehypeCodeOptions | false;
25
+ };
26
+ /**
27
+ * apply MDX processor presets
28
+ */
29
+ declare function mdxPreset(options?: MDXBundlerPresetOptions): Promise<ProcessorOptions>;
30
+
31
+ export { type MDXBundlerPresetOptions, mdxPreset };
@@ -0,0 +1,72 @@
1
+ import {
2
+ resolvePlugins
3
+ } from "../../chunk-GINBKBVQ.js";
4
+ import "../../chunk-U67V476Y.js";
5
+
6
+ // src/content/mdx/preset-bundler.ts
7
+ async function mdxPreset(options = {}) {
8
+ const {
9
+ rehypeCodeOptions,
10
+ remarkImageOptions,
11
+ remarkHeadingOptions,
12
+ remarkStructureOptions,
13
+ remarkCodeTabOptions,
14
+ remarkNpmOptions,
15
+ ...mdxOptions
16
+ } = options;
17
+ const remarkPlugins = await resolvePlugins(
18
+ (v) => [
19
+ import("remark-gfm").then((mod) => mod.default),
20
+ import("../../mdx-plugins/remark-heading.js").then((mod) => [
21
+ mod.remarkHeading,
22
+ {
23
+ generateToc: false,
24
+ ...remarkHeadingOptions
25
+ }
26
+ ]),
27
+ remarkImageOptions !== false && import("../../mdx-plugins/remark-image.js").then((mod) => [
28
+ mod.remarkImage,
29
+ {
30
+ ...remarkImageOptions,
31
+ useImport: remarkImageOptions?.useImport ?? true
32
+ }
33
+ ]),
34
+ remarkCodeTabOptions !== false && import("../../mdx-plugins/remark-code-tab.js").then((mod) => [
35
+ mod.remarkCodeTab,
36
+ remarkCodeTabOptions
37
+ ]),
38
+ remarkNpmOptions !== false && import("../../mdx-plugins/remark-npm.js").then((mod) => [
39
+ mod.remarkNpm,
40
+ remarkNpmOptions
41
+ ]),
42
+ ...v,
43
+ remarkStructureOptions !== false && import("../../mdx-plugins/remark-structure.js").then((mod) => [
44
+ mod.remarkStructure,
45
+ {
46
+ exportAs: "structuredData",
47
+ ...remarkStructureOptions
48
+ }
49
+ ])
50
+ ],
51
+ mdxOptions.remarkPlugins
52
+ );
53
+ const rehypePlugins = await resolvePlugins(
54
+ (v) => [
55
+ rehypeCodeOptions !== false && import("../../mdx-plugins/rehype-code.js").then((mod) => [
56
+ mod.rehypeCode,
57
+ rehypeCodeOptions
58
+ ]),
59
+ ...v,
60
+ import("../../mdx-plugins/rehype-toc.js").then((mod) => mod.rehypeToc)
61
+ ],
62
+ mdxOptions.rehypePlugins
63
+ );
64
+ return {
65
+ ...mdxOptions,
66
+ remarkPlugins,
67
+ rehypePlugins
68
+ };
69
+ }
70
+ export {
71
+ mdxPreset
72
+ };
@@ -0,0 +1,31 @@
1
+ import { ProcessorOptions } from '@mdx-js/mdx';
2
+ import { RehypeCodeOptions } from '../../mdx-plugins/rehype-code.js';
3
+ import { RemarkImageOptions } from '../../mdx-plugins/remark-image.js';
4
+ import { StructureOptions } from '../../mdx-plugins/remark-structure.js';
5
+ import { RemarkHeadingOptions } from '../../mdx-plugins/remark-heading.js';
6
+ import { RemarkCodeTabOptions } from '../../mdx-plugins/remark-code-tab.js';
7
+ import { RemarkNpmOptions } from '../../mdx-plugins/remark-npm.js';
8
+ import { R as ResolvePlugins } from '../../util-bZU2QeJ2.js';
9
+ import 'hast';
10
+ import '@shikijs/rehype';
11
+ import 'unified';
12
+ import 'shiki';
13
+ import 'mdast';
14
+ import 'mdast-util-mdx-jsx';
15
+
16
+ type MDXRuntimePresetOptions = Omit<NonNullable<ProcessorOptions>, 'rehypePlugins' | 'remarkPlugins'> & {
17
+ rehypePlugins?: ResolvePlugins;
18
+ remarkPlugins?: ResolvePlugins;
19
+ remarkStructureOptions?: StructureOptions | false;
20
+ remarkHeadingOptions?: RemarkHeadingOptions;
21
+ remarkImageOptions?: RemarkImageOptions | false;
22
+ remarkCodeTabOptions?: RemarkCodeTabOptions | false;
23
+ remarkNpmOptions?: RemarkNpmOptions | false;
24
+ rehypeCodeOptions?: RehypeCodeOptions | false;
25
+ };
26
+ /**
27
+ * apply MDX processor presets
28
+ */
29
+ declare function mdxPreset(options?: MDXRuntimePresetOptions): Promise<ProcessorOptions>;
30
+
31
+ export { type MDXRuntimePresetOptions, mdxPreset };
@@ -0,0 +1,71 @@
1
+ import {
2
+ resolvePlugins
3
+ } from "../../chunk-GINBKBVQ.js";
4
+ import "../../chunk-U67V476Y.js";
5
+
6
+ // src/content/mdx/preset-runtime.ts
7
+ async function mdxPreset(options = {}) {
8
+ const {
9
+ rehypeCodeOptions,
10
+ remarkImageOptions,
11
+ remarkHeadingOptions,
12
+ remarkStructureOptions,
13
+ remarkCodeTabOptions,
14
+ remarkNpmOptions,
15
+ outputFormat = "function-body",
16
+ ...mdxOptions
17
+ } = options;
18
+ const remarkPlugins = await resolvePlugins(
19
+ (v) => [
20
+ import("remark-gfm").then((mod) => mod.default),
21
+ import("../../mdx-plugins/remark-heading.js").then((mod) => [
22
+ mod.remarkHeading,
23
+ {
24
+ generateToc: false,
25
+ ...remarkHeadingOptions
26
+ }
27
+ ]),
28
+ remarkImageOptions !== false && import("../../mdx-plugins/remark-image.js").then((mod) => [
29
+ mod.remarkImage,
30
+ remarkImageOptions
31
+ ]),
32
+ remarkCodeTabOptions !== false && import("../../mdx-plugins/remark-code-tab.js").then((mod) => [
33
+ mod.remarkCodeTab,
34
+ remarkCodeTabOptions
35
+ ]),
36
+ remarkNpmOptions !== false && import("../../mdx-plugins/remark-npm.js").then((mod) => [
37
+ mod.remarkNpm,
38
+ remarkNpmOptions
39
+ ]),
40
+ ...v,
41
+ remarkStructureOptions !== false && import("../../mdx-plugins/remark-structure.js").then((mod) => [
42
+ mod.remarkStructure,
43
+ {
44
+ exportAs: "structuredData",
45
+ ...remarkStructureOptions
46
+ }
47
+ ])
48
+ ],
49
+ mdxOptions.remarkPlugins
50
+ );
51
+ const rehypePlugins = await resolvePlugins(
52
+ (v) => [
53
+ rehypeCodeOptions !== false && import("../../mdx-plugins/rehype-code.js").then((mod) => [
54
+ mod.rehypeCode,
55
+ rehypeCodeOptions
56
+ ]),
57
+ ...v,
58
+ import("../../mdx-plugins/rehype-toc.js").then((mod) => mod.rehypeToc)
59
+ ],
60
+ mdxOptions.rehypePlugins
61
+ );
62
+ return {
63
+ ...mdxOptions,
64
+ outputFormat,
65
+ remarkPlugins,
66
+ rehypePlugins
67
+ };
68
+ }
69
+ export {
70
+ mdxPreset
71
+ };
@@ -59,18 +59,30 @@ type _ConfigUnion_<T extends Record<string, Source>> = {
59
59
  } : never;
60
60
  }[keyof T];
61
61
  declare function multiple<T extends Record<string, Source>>(sources: T): Source<_ConfigUnion_<T>>;
62
+ declare function source<Page extends PageData, Meta extends MetaData>(config: {
63
+ pages: VirtualPage<Page>[];
64
+ metas: VirtualMeta<Meta>[];
65
+ }): Source<{
66
+ pageData: Page;
67
+ metaData: Meta;
68
+ }>;
62
69
  /**
63
- * map virtual files in source
70
+ * update a source object in-place.
64
71
  */
65
- declare function map<Config extends SourceConfig>(source: Source<Config>): {
66
- page<$Page extends PageData>(fn: (entry: VirtualPage<Config["pageData"]>) => VirtualPage<$Page>): Source<{
67
- pageData: $Page;
72
+ declare function update<Config extends SourceConfig>(source: Source<Config>): {
73
+ files<Page extends PageData, Meta extends MetaData>(fn: (files: VirtualFile<Config>[]) => (VirtualPage<Page> | VirtualMeta<Meta>)[]): typeof update<{
74
+ pageData: Page;
75
+ metaData: Meta;
76
+ }>;
77
+ page<V extends PageData>(fn: (page: VirtualPage<Config["pageData"]>) => VirtualPage<V>): typeof update<{
78
+ pageData: V;
68
79
  metaData: Config["metaData"];
69
80
  }>;
70
- meta<$Meta extends MetaData>(fn: (entry: VirtualMeta<Config["metaData"]>) => VirtualMeta<$Meta>): Source<{
81
+ meta<V extends MetaData>(fn: (meta: VirtualMeta<Config["metaData"]>) => VirtualMeta<V>): typeof update<{
71
82
  pageData: Config["pageData"];
72
- metaData: $Meta;
83
+ metaData: V;
73
84
  }>;
85
+ build(): Source<Config>;
74
86
  };
75
87
 
76
88
  /**
@@ -239,6 +251,12 @@ interface Meta<Data = MetaData> extends SharedFileInfo {
239
251
  interface LoaderOutput<Config extends LoaderConfig> {
240
252
  pageTree: Config['i18n'] extends I18nConfig ? Record<string, Root> : Root;
241
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
+ */
242
260
  getPageByHref: (href: string, options?: {
243
261
  language?: string;
244
262
  /**
@@ -249,6 +267,12 @@ interface LoaderOutput<Config extends LoaderConfig> {
249
267
  page: Page<Config['source']['pageData']>;
250
268
  hash?: string;
251
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;
252
276
  /**
253
277
  * @internal
254
278
  */
@@ -306,4 +330,4 @@ declare function loader<Config extends SourceConfig, I18n extends I18nConfig | u
306
330
  type InferPageType<Utils extends LoaderOutput<any>> = Utils extends LoaderOutput<infer Config> ? Page<Config['source']['pageData']> : never;
307
331
  type InferMetaType<Utils extends LoaderOutput<any>> = Utils extends LoaderOutput<infer Config> ? Meta<Config['source']['metaData']> : never;
308
332
 
309
- export { type ContentStorage as C, FileSystem as F, type InferPageType as I, type LoaderPlugin as L, type MetaData as M, type PageData as P, type ResolvedLoaderConfig as R, type Source as S, type VirtualFile as V, type _ConfigUnion_ as _, type SourceConfig as a, map as b, type LoaderConfig as c, type LoaderOptions as d, type Page as e, type Meta as f, type LoaderOutput as g, createGetUrl as h, type InferMetaType as i, type PageTreeBuilderContext as j, type PageTreeTransformer as k, loader as l, multiple as m, type PageTreeOptions as n, type PageTreeBuilder as o, createPageTreeBuilder as p, type ContentStorageFile as q, buildContentStorage as r, type LoaderPluginOption as s, buildPlugins as t };
333
+ export { type ContentStorage as C, FileSystem as F, type InferPageType as I, type LoaderPlugin as L, type MetaData as M, type PageData as P, type ResolvedLoaderConfig as R, type Source as S, type VirtualFile as V, type _ConfigUnion_ as _, type SourceConfig as a, type LoaderConfig as b, type LoaderOptions as c, type Page as d, type Meta as e, type LoaderOutput as f, createGetUrl as g, type InferMetaType as h, type PageTreeBuilderContext as i, type PageTreeTransformer as j, type PageTreeOptions as k, loader as l, multiple as m, type PageTreeBuilder as n, createPageTreeBuilder as o, type ContentStorageFile as p, buildContentStorage as q, type LoaderPluginOption as r, source as s, buildPlugins as t, update as u };
@@ -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 { g as LoaderOutput, c as LoaderConfig, I as InferPageType } from '../loader-qkSHi822.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, q as ContentStorageFile, F as FileSystem, i as InferMetaType, I as InferPageType, c as LoaderConfig, d as LoaderOptions, g as LoaderOutput, L as LoaderPlugin, s as LoaderPluginOption, f as Meta, M as MetaData, e as Page, P as PageData, o as PageTreeBuilder, j as PageTreeBuilderContext, n as PageTreeOptions, k as PageTreeTransformer, R as ResolvedLoaderConfig, S as Source, a as SourceConfig, V as VirtualFile, _ as _ConfigUnion_, r as buildContentStorage, t as buildPlugins, h as createGetUrl, p as createPageTreeBuilder, l as loader, b as map, m as multiple } from '../loader-qkSHi822.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,14 +15,14 @@ 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
22
22
  function multiple(sources) {
23
23
  const out = { files: [] };
24
- for (const [type, source] of Object.entries(sources)) {
25
- for (const file of source.files) {
24
+ for (const [type, source2] of Object.entries(sources)) {
25
+ for (const file of source2.files) {
26
26
  out.files.push({
27
27
  ...file,
28
28
  data: {
@@ -34,21 +34,33 @@ function multiple(sources) {
34
34
  }
35
35
  return out;
36
36
  }
37
- function map(source) {
37
+ function source(config) {
38
38
  return {
39
+ files: [...config.pages, ...config.metas]
40
+ };
41
+ }
42
+ function update(source2) {
43
+ return {
44
+ files(fn) {
45
+ source2.files = fn(source2.files);
46
+ return this;
47
+ },
39
48
  page(fn) {
40
- return {
41
- files: source.files.map(
42
- (file) => file.type === "page" ? fn(file) : file
43
- )
44
- };
49
+ for (let i = 0; i < source2.files.length; i++) {
50
+ const file = source2.files[i];
51
+ if (file.type === "page") source2.files[i] = fn(file);
52
+ }
53
+ return this;
45
54
  },
46
55
  meta(fn) {
47
- return {
48
- files: source.files.map(
49
- (file) => file.type === "meta" ? fn(file) : file
50
- )
51
- };
56
+ for (let i = 0; i < source2.files.length; i++) {
57
+ const file = source2.files[i];
58
+ if (file.type === "meta") source2.files[i] = fn(file);
59
+ }
60
+ return this;
61
+ },
62
+ build() {
63
+ return source2;
52
64
  }
53
65
  };
54
66
  }
@@ -69,22 +81,22 @@ var FileSystem = class {
69
81
  this.folders.set("", []);
70
82
  }
71
83
  }
72
- read(path) {
73
- return this.files.get(path);
84
+ read(path2) {
85
+ return this.files.get(path2);
74
86
  }
75
87
  /**
76
88
  * get the direct children of folder (in virtual file path)
77
89
  */
78
- readDir(path) {
79
- return this.folders.get(path);
90
+ readDir(path2) {
91
+ return this.folders.get(path2);
80
92
  }
81
- write(path, file) {
82
- if (!this.files.has(path)) {
83
- const dir = dirname(path);
93
+ write(path2, file) {
94
+ if (!this.files.has(path2)) {
95
+ const dir = dirname(path2);
84
96
  this.makeDir(dir);
85
- this.readDir(dir)?.push(path);
97
+ this.readDir(dir)?.push(path2);
86
98
  }
87
- this.files.set(path, file);
99
+ this.files.set(path2, file);
88
100
  }
89
101
  /**
90
102
  * Delete files at specified path.
@@ -92,12 +104,12 @@ var FileSystem = class {
92
104
  * @param path - the target path.
93
105
  * @param [recursive=false] - if set to `true`, it will also delete directories.
94
106
  */
95
- delete(path, recursive = false) {
96
- if (this.files.delete(path)) return true;
107
+ delete(path2, recursive = false) {
108
+ if (this.files.delete(path2)) return true;
97
109
  if (recursive) {
98
- const folder = this.folders.get(path);
110
+ const folder = this.folders.get(path2);
99
111
  if (!folder) return false;
100
- this.folders.delete(path);
112
+ this.folders.delete(path2);
101
113
  for (const child of folder) {
102
114
  this.delete(child);
103
115
  }
@@ -108,8 +120,8 @@ var FileSystem = class {
108
120
  getFiles() {
109
121
  return Array.from(this.files.keys());
110
122
  }
111
- makeDir(path) {
112
- const segments = splitPath(path);
123
+ makeDir(path2) {
124
+ const segments = splitPath(path2);
113
125
  for (let i = 0; i < segments.length; i++) {
114
126
  const segment = segments.slice(0, i + 1).join("/");
115
127
  if (this.folders.has(segment)) continue;
@@ -124,28 +136,28 @@ function isLocaleValid(locale) {
124
136
  return locale.length > 0 && !/\d+/.test(locale);
125
137
  }
126
138
  var parsers = {
127
- dir(path) {
128
- const [locale, ...segs] = path.split("/");
139
+ dir(path2) {
140
+ const [locale, ...segs] = path2.split("/");
129
141
  if (locale && segs.length > 0 && isLocaleValid(locale))
130
142
  return [segs.join("/"), locale];
131
- return [path];
143
+ return [path2];
132
144
  },
133
- dot(path) {
134
- const dir = dirname(path);
135
- const base = basename(path);
145
+ dot(path2) {
146
+ const dir = dirname(path2);
147
+ const base = basename(path2);
136
148
  const parts = base.split(".");
137
- if (parts.length < 3) return [path];
149
+ if (parts.length < 3) return [path2];
138
150
  const [locale] = parts.splice(parts.length - 2, 1);
139
- if (!isLocaleValid(locale)) return [path];
151
+ if (!isLocaleValid(locale)) return [path2];
140
152
  return [joinPath(dir, parts.join(".")), locale];
141
153
  },
142
- none(path) {
143
- return [path];
154
+ none(path2) {
155
+ return [path2];
144
156
  }
145
157
  };
146
158
  function buildContentStorage(loaderConfig, defaultLanguage) {
147
159
  const {
148
- source,
160
+ source: source2,
149
161
  plugins = [],
150
162
  i18n = {
151
163
  defaultLanguage,
@@ -156,7 +168,7 @@ function buildContentStorage(loaderConfig, defaultLanguage) {
156
168
  const parser = parsers[i18n.parser ?? "dot"];
157
169
  const storages = {};
158
170
  const normalized = /* @__PURE__ */ new Map();
159
- for (const inputFile of source.files) {
171
+ for (const inputFile of source2.files) {
160
172
  let file;
161
173
  if (inputFile.type === "page") {
162
174
  file = {
@@ -209,8 +221,8 @@ function buildContentStorage(loaderConfig, defaultLanguage) {
209
221
  for (const lang of i18n.languages) scan(lang);
210
222
  return storages;
211
223
  }
212
- function normalizePath(path) {
213
- const segments = splitPath(slash(path));
224
+ function normalizePath(path2) {
225
+ const segments = splitPath(slash(path2));
214
226
  if (segments[0] === "." || segments[0] === "..")
215
227
  throw new Error("It must not start with './' or '../'");
216
228
  return segments.join("/");
@@ -298,15 +310,15 @@ function createPageTreeBuilder(loaderConfig) {
298
310
  };
299
311
  }
300
312
  function createFlattenPathResolver(storage) {
301
- const map2 = /* @__PURE__ */ new Map();
313
+ const map = /* @__PURE__ */ new Map();
302
314
  const files = storage.getFiles();
303
315
  for (const file of files) {
304
316
  const content = storage.read(file);
305
317
  const flattenPath = file.substring(0, file.length - extname(file).length);
306
- map2.set(flattenPath + "." + content.format, file);
318
+ map.set(flattenPath + "." + content.format, file);
307
319
  }
308
320
  return (name, format) => {
309
- return map2.get(name + "." + format) ?? name;
321
+ return map.get(name + "." + format) ?? name;
310
322
  };
311
323
  }
312
324
  function createPageTreeBuilderUtils(ctx) {
@@ -322,15 +334,15 @@ function createPageTreeBuilderUtils(ctx) {
322
334
  const sortedPaths = paths.sort(
323
335
  (a, b) => a.localeCompare(b) * (reversed ? -1 : 1)
324
336
  );
325
- for (const path of sortedPaths) {
326
- const fileNode = this.file(path);
337
+ for (const path2 of sortedPaths) {
338
+ const fileNode = this.file(path2);
327
339
  if (fileNode) {
328
- if (basename(path, extname(path)) === "index")
340
+ if (basename(path2, extname(path2)) === "index")
329
341
  items.unshift(fileNode);
330
342
  else items.push(fileNode);
331
343
  continue;
332
344
  }
333
- const dirNode = this.folder(path, false);
345
+ const dirNode = this.folder(path2, false);
334
346
  if (dirNode) folders.push(dirNode);
335
347
  }
336
348
  items.push(...folders);
@@ -377,16 +389,16 @@ function createPageTreeBuilderUtils(ctx) {
377
389
  } else if (isExtract) {
378
390
  filename = item.slice(extractPrefix.length);
379
391
  }
380
- const path = resolveFlattenPath(joinPath(folderPath, filename), "page");
392
+ const path2 = resolveFlattenPath(joinPath(folderPath, filename), "page");
381
393
  if (isExcept) {
382
- visitedPaths.add(path);
394
+ visitedPaths.add(path2);
383
395
  return [];
384
396
  }
385
- const dirNode = this.folder(path, false);
397
+ const dirNode = this.folder(path2, false);
386
398
  if (dirNode) {
387
399
  return isExtract ? dirNode.children : [dirNode];
388
400
  }
389
- const fileNode = this.file(path);
401
+ const fileNode = this.file(path2);
390
402
  return fileNode ? [fileNode] : [];
391
403
  },
392
404
  folder(folderPath, isGlobalRoot) {
@@ -453,26 +465,26 @@ function createPageTreeBuilderUtils(ctx) {
453
465
  }
454
466
  return node;
455
467
  },
456
- file(path) {
468
+ file(path2) {
457
469
  const { options, getUrl, storage, locale, transformers } = ctx;
458
- const page = storage.read(path);
470
+ const page = storage.read(path2);
459
471
  if (page?.format !== "page") return;
460
472
  const { title, description, icon } = page.data;
461
473
  let item = {
462
- $id: nextNodeId(path),
474
+ $id: nextNodeId(path2),
463
475
  type: "page",
464
- name: title ?? pathToName(basename(path, extname(path))),
476
+ name: title ?? pathToName(basename(path2, extname(path2))),
465
477
  description,
466
478
  icon,
467
479
  url: getUrl(page.slugs, locale),
468
480
  $ref: !options.noRef ? {
469
- file: path
481
+ file: path2
470
482
  } : void 0
471
483
  };
472
- visitedPaths.add(path);
484
+ visitedPaths.add(path2);
473
485
  for (const transformer of transformers) {
474
486
  if (!transformer.file) continue;
475
- item = transformer.file.call(ctx, item, path);
487
+ item = transformer.file.call(ctx, item, path2);
476
488
  }
477
489
  return item;
478
490
  },
@@ -531,22 +543,22 @@ function slugsPlugin(slugsFn) {
531
543
  const indexFiles = /* @__PURE__ */ new Set();
532
544
  const taken = /* @__PURE__ */ new Set();
533
545
  const autoIndex = slugsFn === void 0;
534
- for (const path of storage.getFiles()) {
535
- const file = storage.read(path);
546
+ for (const path2 of storage.getFiles()) {
547
+ const file = storage.read(path2);
536
548
  if (!file || file.format !== "page" || file.slugs) continue;
537
- if (isIndex(path) && autoIndex) {
538
- indexFiles.add(path);
549
+ if (isIndex(path2) && autoIndex) {
550
+ indexFiles.add(path2);
539
551
  continue;
540
552
  }
541
- file.slugs = slugsFn ? slugsFn({ path }) : getSlugs(path);
553
+ file.slugs = slugsFn ? slugsFn({ path: path2 }) : getSlugs(path2);
542
554
  const key = file.slugs.join("/");
543
555
  if (taken.has(key)) throw new Error("Duplicated slugs");
544
556
  taken.add(key);
545
557
  }
546
- for (const path of indexFiles) {
547
- const file = storage.read(path);
558
+ for (const path2 of indexFiles) {
559
+ const file = storage.read(path2);
548
560
  if (file?.format !== "page") continue;
549
- file.slugs = getSlugs(path);
561
+ file.slugs = getSlugs(path2);
550
562
  if (taken.has(file.slugs.join("/"))) file.slugs.push("index");
551
563
  }
552
564
  }
@@ -569,6 +581,7 @@ function getSlugs(file) {
569
581
  }
570
582
 
571
583
  // src/source/loader.ts
584
+ import path from "path";
572
585
  function indexPages(storages, { url }) {
573
586
  const result = {
574
587
  // (locale.slugs -> page)
@@ -581,9 +594,9 @@ function indexPages(storages, { url }) {
581
594
  for (const [lang, storage] of Object.entries(storages)) {
582
595
  for (const filePath of storage.getFiles()) {
583
596
  const item = storage.read(filePath);
584
- const path = `${lang}.${filePath}`;
597
+ const path2 = `${lang}.${filePath}`;
585
598
  if (item.format === "meta") {
586
- result.pathToMeta.set(path, {
599
+ result.pathToMeta.set(path2, {
587
600
  path: item.path,
588
601
  absolutePath: item.absolutePath,
589
602
  data: item.data
@@ -598,7 +611,7 @@ function indexPages(storages, { url }) {
598
611
  data: item.data,
599
612
  locale: lang
600
613
  };
601
- result.pathToPage.set(path, page);
614
+ result.pathToPage.set(path2, page);
602
615
  result.pages.set(`${lang}.${page.slugs.join("/")}`, page);
603
616
  }
604
617
  }
@@ -647,9 +660,9 @@ function loader(...args) {
647
660
  getPageByHref(href, { dir = "", language = defaultLanguage } = {}) {
648
661
  const [value, hash] = href.split("#", 2);
649
662
  let target;
650
- if (value.startsWith(".") && (value.endsWith(".md") || value.endsWith(".mdx"))) {
651
- const path = joinPath(dir, value);
652
- target = walker.pathToPage.get(`${language}.${path}`);
663
+ if (value.startsWith("./")) {
664
+ const path2 = joinPath(dir, value);
665
+ target = walker.pathToPage.get(`${language}.${path2}`);
653
666
  } else {
654
667
  target = this.getPages(language).find((item) => item.url === value);
655
668
  }
@@ -659,6 +672,18 @@ function loader(...args) {
659
672
  hash
660
673
  };
661
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
+ },
662
687
  getPages(language) {
663
688
  const pages = [];
664
689
  for (const [key, value] of walker.pages.entries()) {
@@ -733,11 +758,11 @@ function loader(...args) {
733
758
  }
734
759
  };
735
760
  }
736
- function resolveConfig(source, { slugs, icon, plugins = [], baseUrl, url, ...base }) {
761
+ function resolveConfig(source2, { slugs, icon, plugins = [], baseUrl, url, ...base }) {
737
762
  let config = {
738
763
  ...base,
739
764
  url: url ? (...args) => normalizeUrl(url(...args)) : createGetUrl(baseUrl, base.i18n),
740
- source,
765
+ source: source2,
741
766
  plugins: buildPlugins([
742
767
  slugsPlugin(slugs),
743
768
  icon && iconPlugin(icon),
@@ -758,6 +783,7 @@ export {
758
783
  createGetUrl,
759
784
  getSlugs,
760
785
  loader,
761
- map,
762
- multiple
786
+ multiple,
787
+ source,
788
+ update
763
789
  };
@@ -1,4 +1,4 @@
1
- import { L as LoaderPlugin } from '../../loader-qkSHi822.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';
@@ -0,0 +1,6 @@
1
+ import { Pluggable } from 'unified';
2
+
3
+ type Thenable<T> = T | PromiseLike<T>;
4
+ type ResolvePlugins = Thenable<Pluggable>[] | ((v: Pluggable[]) => Thenable<Pluggable>[]);
5
+
6
+ export type { ResolvePlugins as R };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "16.2.4",
3
+ "version": "16.3.0",
4
4
  "description": "The React.js library for building a documentation website",
5
5
  "keywords": [
6
6
  "Fumadocs",
@@ -111,8 +111,8 @@
111
111
  "dependencies": {
112
112
  "@formatjs/intl-localematcher": "^0.6.2",
113
113
  "@orama/orama": "^3.1.16",
114
- "@shikijs/rehype": "^3.19.0",
115
- "@shikijs/transformers": "^3.19.0",
114
+ "@shikijs/rehype": "^3.20.0",
115
+ "@shikijs/transformers": "^3.20.0",
116
116
  "estree-util-value-to-estree": "^3.5.0",
117
117
  "github-slugger": "^2.0.0",
118
118
  "hast-util-to-estree": "^3.1.3",
@@ -125,14 +125,14 @@
125
125
  "remark-gfm": "^4.0.1",
126
126
  "remark-rehype": "^11.1.2",
127
127
  "scroll-into-view-if-needed": "^3.1.0",
128
- "shiki": "^3.19.0",
128
+ "shiki": "^3.20.0",
129
129
  "unist-util-visit": "^5.0.0"
130
130
  },
131
131
  "devDependencies": {
132
132
  "@mdx-js/mdx": "^3.1.1",
133
133
  "@mixedbread/sdk": "^0.46.0",
134
- "@orama/core": "^1.2.13",
135
- "@tanstack/react-router": "1.140.0",
134
+ "@orama/core": "^1.2.14",
135
+ "@tanstack/react-router": "1.136.18",
136
136
  "@types/estree-jsx": "^1.0.5",
137
137
  "@types/hast": "^3.0.4",
138
138
  "@types/mdast": "^4.0.4",
@@ -141,10 +141,10 @@
141
141
  "@types/react": "^19.2.7",
142
142
  "@types/react-dom": "^19.2.3",
143
143
  "algoliasearch": "5.46.0",
144
- "lucide-react": "^0.556.0",
144
+ "lucide-react": "^0.561.0",
145
145
  "mdast-util-mdx-jsx": "^3.2.0",
146
146
  "mdast-util-mdxjs-esm": "^2.0.1",
147
- "next": "16.0.8",
147
+ "next": "16.0.10",
148
148
  "react-router": "^7.10.1",
149
149
  "remark-directive": "^4.0.0",
150
150
  "remark-mdx": "^3.1.1",
@@ -152,10 +152,10 @@
152
152
  "typescript": "^5.9.3",
153
153
  "unified": "^11.0.5",
154
154
  "vfile": "^6.0.3",
155
- "waku": "^0.27.3",
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",