fumadocs-core 16.8.12 → 16.9.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.
@@ -1,2 +1,2 @@
1
- import { n as defineI18n, t as I18nConfig } from "../index-BreFfl9v.js";
2
- export { I18nConfig, defineI18n };
1
+ import { a as TranslationPreset, c as TranslationsAPIExtension, d as renderTranslation, i as TranslationObject, l as defineI18n, n as I18nConfig, o as TranslationValue, r as SingularTranslationsAPI, s as TranslationsAPI, t as I18nAPI, u as defineTranslations } from "../index-YTOeewZk.js";
2
+ export { I18nAPI, I18nConfig, SingularTranslationsAPI, TranslationObject, TranslationPreset, TranslationValue, TranslationsAPI, TranslationsAPIExtension, defineI18n, defineTranslations, renderTranslation };
@@ -1,6 +1,59 @@
1
1
  //#region src/i18n/index.ts
2
2
  function defineI18n(config) {
3
- return config;
3
+ return {
4
+ ...config,
5
+ translations() {
6
+ const translations = {};
7
+ for (const lang of config.languages) translations[lang] = {};
8
+ return {
9
+ config,
10
+ $inferLanguages: void 0,
11
+ $inferNamespaces: void 0,
12
+ get(lang) {
13
+ return translations[lang];
14
+ },
15
+ preset(lang, preset) {
16
+ const t = translations[lang];
17
+ for (const [namespace, obj] of Object.entries(preset.value)) if (t[namespace]) Object.assign(t[namespace], obj);
18
+ return this;
19
+ },
20
+ add(namespace, overrides) {
21
+ for (const [lang, values] of Object.entries(overrides)) Object.assign(translations[lang][namespace], values);
22
+ return this;
23
+ },
24
+ extend({ namespace, defaultValue }) {
25
+ for (const lang of config.languages) translations[lang][namespace] = { ...defaultValue };
26
+ return this;
27
+ }
28
+ };
29
+ }
30
+ };
31
+ }
32
+ /** create translations API without i18n */
33
+ function defineTranslations() {
34
+ const translations = {};
35
+ return {
36
+ $inferNamespaces: void 0,
37
+ get() {
38
+ return translations;
39
+ },
40
+ preset(preset) {
41
+ for (const [namespace, obj] of Object.entries(preset.value)) if (translations[namespace]) Object.assign(translations[namespace], obj);
42
+ return this;
43
+ },
44
+ add(namespace, overrides) {
45
+ Object.assign(translations[namespace], overrides);
46
+ return this;
47
+ },
48
+ extend({ namespace, defaultValue }) {
49
+ translations[namespace] = { ...defaultValue };
50
+ return this;
51
+ }
52
+ };
53
+ }
54
+ function renderTranslation(label, params) {
55
+ if (params) for (const k in params) label = label.replaceAll(`{${k}}`, params[k]);
56
+ return label;
4
57
  }
5
58
  //#endregion
6
- export { defineI18n };
59
+ export { defineI18n, defineTranslations, renderTranslation };
@@ -1,4 +1,4 @@
1
- import { t as I18nConfig } from "../index-BreFfl9v.js";
1
+ import { n as I18nConfig } from "../index-YTOeewZk.js";
2
2
  import { NextProxy } from "next/server.js";
3
3
  import { NextURL } from "next/dist/server/web/next-url.js";
4
4
 
@@ -1,7 +1,7 @@
1
1
  import { a as Separator, i as Root, n as Item, r as Node, t as Folder } from "./definitions-Cob-Q8-8.js";
2
2
  import { t as Awaitable } from "./types-DpbpliNk.js";
3
3
  import { i as StructuredData } from "./remark-structure-C2-K9_ko.js";
4
- import { t as I18nConfig } from "./index-BreFfl9v.js";
4
+ import { n as I18nConfig } from "./index-YTOeewZk.js";
5
5
  import { n as SerializedPageTree } from "./index-D2f_P1Zo.js";
6
6
  import { ReactNode } from "react";
7
7
 
@@ -55,15 +55,13 @@ interface ContentStoragePageFile<Type extends string | undefined = string | unde
55
55
  //#endregion
56
56
  //#region src/source/page-tree/builder.d.ts
57
57
  interface PageTreeBuilderContext<S extends ContentStorage = ContentStorage> {
58
- idPrefix: string;
59
- noRef: boolean;
60
58
  transformers: PageTreeTransformer<S>[];
61
59
  builder: PageTreeBuilder;
62
60
  storage: S;
63
- getUrl: ResolvedLoaderConfig['url'];
64
61
  storages?: Record<string, S>;
65
62
  locale?: string;
66
63
  custom?: Record<string, unknown>;
64
+ options: PageTreeOptions<S>;
67
65
  }
68
66
  interface PageTreeTransformer<S extends ContentStorage = ContentStorage> {
69
67
  file?: (this: PageTreeBuilderContext<S>, node: Item, filePath?: string) => Item;
@@ -93,35 +91,15 @@ interface PageTreeOptions<S extends ContentStorage = ContentStorage> {
93
91
  transformers?: PageTreeTransformer<S>[];
94
92
  /** custom context */
95
93
  context?: Record<string, unknown>;
94
+ /** customize the default sorting behaviour (`localeCompare`) */
95
+ sort?: {
96
+ /** @default 'path' */by?: 'name' | 'path';
97
+ locales?: Intl.LocalesArgument;
98
+ options?: Intl.CollatorOptions;
99
+ };
96
100
  }
97
- declare class PageTreeBuilder {
98
- private readonly flattenPathToFullPath;
99
- private readonly transformers;
100
- /** virtual file path -> output page tree node (if cached) */
101
- private readonly pathToNode;
102
- /** unfinished nodes */
103
- private readonly unfinished;
104
- private readonly ownerMap;
105
- private _nextId;
106
- /** passed as additional information to transformers */
107
- private readonly ctx;
108
- private readonly storage;
109
- constructor(input: ContentStorage | [locale: string, storages: Record<string, ContentStorage>], options: PageTreeOptions);
101
+ interface PageTreeBuilder {
110
102
  resolveFlattenPath(name: string, format: string): string;
111
- /**
112
- * try to register as the owner of `node`.
113
- *
114
- * when a node is referenced by multiple folders, this determines which folder they should belong to.
115
- *
116
- * @returns whether the owner owns the node.
117
- */
118
- private own;
119
- private transferOwner;
120
- private generateId;
121
- buildPaths(paths: string[], filter?: (file: string) => boolean, reversed?: boolean): Node[];
122
- private resolveFolderItem;
123
- folder(folderPath: string): Folder | undefined;
124
- file(path: string): Item | undefined;
125
103
  root(id?: string, path?: string): Root;
126
104
  }
127
105
  //#endregion
@@ -0,0 +1,85 @@
1
+ //#region src/i18n/index.d.ts
2
+ interface I18nConfig<Languages extends string = string> {
3
+ /**
4
+ * Supported locale codes.
5
+ *
6
+ * A page tree will be built for each language.
7
+ */
8
+ languages: Languages[];
9
+ /**
10
+ * Default locale if not specified
11
+ */
12
+ defaultLanguage: NoInfer<Languages>;
13
+ /**
14
+ * Don't show the locale prefix on URL.
15
+ *
16
+ * - `always`: Always hide the prefix
17
+ * - `default-locale`: Only hide the default locale
18
+ * - `never`: Never hide the prefix
19
+ *
20
+ * This API uses `NextResponse.rewrite`.
21
+ *
22
+ * @defaultValue 'never'
23
+ */
24
+ hideLocale?: 'always' | 'default-locale' | 'never';
25
+ /**
26
+ * Used by `loader()`, specify the way to parse i18n file structure.
27
+ *
28
+ * @defaultValue 'dot'
29
+ */
30
+ parser?: 'dot' | 'dir' | 'none';
31
+ /**
32
+ * the fallback language when the page has no translations available for a given locale.
33
+ *
34
+ * Default to `defaultLanguage`, no fallback when set to `null`.
35
+ */
36
+ fallbackLanguage?: NoInfer<Languages> | null;
37
+ }
38
+ interface I18nAPI<Languages extends string = string> extends I18nConfig<Languages> {
39
+ translations: () => TranslationsAPI<Languages, Record<never, TranslationObject>>;
40
+ }
41
+ declare function defineI18n<const Languages extends string>(config: I18nConfig<Languages>): I18nAPI<Languages>;
42
+ type TranslationObject = Record<string, TranslationValue>;
43
+ type TranslationValue<Params extends string = string> = string & {
44
+ _params?: Params;
45
+ };
46
+ type TranslationPreset<Namespaces extends Record<string, TranslationObject> = Record<string, TranslationObject>> = {
47
+ name: string;
48
+ value: Partial<Namespaces>;
49
+ };
50
+ interface TranslationsAPIExtension<Namespace extends string = string, Obj extends TranslationObject = TranslationObject> {
51
+ namespace: Namespace;
52
+ defaultValue: Obj;
53
+ }
54
+ interface TranslationsAPI<Languages extends string = string, Namespaces extends Record<string, TranslationObject> = Record<string, TranslationObject>> {
55
+ /** for type inference only, always `undefined` in runtime */
56
+ $inferLanguages: Languages;
57
+ /** for type inference only, always `undefined` in runtime */
58
+ $inferNamespaces: Namespaces;
59
+ config: I18nConfig<Languages>;
60
+ get: {
61
+ (lang: Languages): Namespaces;
62
+ (lang: string): Namespaces | undefined;
63
+ };
64
+ extend: <N extends string, Obj extends TranslationObject>(extension: TranslationsAPIExtension<N, Obj>) => TranslationsAPI<Languages, Namespaces & { [K in N]: Obj }>;
65
+ /** add translations */
66
+ add: <N extends keyof Namespaces>(namespace: N, overrides: { [Lang in Languages]?: Partial<Namespaces[N]> }) => TranslationsAPI<Languages, Namespaces>;
67
+ /** add language pack, you should call `extend()` first before adding a language preset */
68
+ preset: (lang: Languages, preset: TranslationPreset<Namespaces>) => TranslationsAPI<Languages, Namespaces>;
69
+ }
70
+ interface SingularTranslationsAPI<Namespaces extends Record<string, TranslationObject> = Record<string, TranslationObject>> {
71
+ /** for type inference only, always `undefined` in runtime */
72
+ $inferNamespaces: Namespaces;
73
+ get: () => Namespaces;
74
+ extend: <N extends string, Obj extends TranslationObject>(extension: TranslationsAPIExtension<N, Obj>) => SingularTranslationsAPI<Namespaces & { [K in N]: Obj }>;
75
+ /** add translations */
76
+ add: <N extends keyof Namespaces>(namespace: N, overrides: Partial<Namespaces[N]>) => SingularTranslationsAPI<Namespaces>;
77
+ /** add language pack, you should call `extend()` first before adding a language preset */
78
+ preset: (preset: TranslationPreset<Namespaces>) => SingularTranslationsAPI<Namespaces>;
79
+ }
80
+ /** create translations API without i18n */
81
+ declare function defineTranslations(): SingularTranslationsAPI<Record<never, TranslationObject>>;
82
+ declare function renderTranslation(v: TranslationValue<never>): string;
83
+ declare function renderTranslation<Params extends string>(v: TranslationValue<Params>, params: Record<Params, string>): string;
84
+ //#endregion
85
+ export { TranslationPreset as a, TranslationsAPIExtension as c, renderTranslation as d, TranslationObject as i, defineI18n as l, I18nConfig as n, TranslationValue as o, SingularTranslationsAPI as r, TranslationsAPI as s, I18nAPI as t, defineTranslations as u };
@@ -232,11 +232,9 @@ function transformerFallback() {
232
232
  if (addedFiles.has(file)) continue;
233
233
  isolatedStorage.write(file, this.storage.read(file));
234
234
  }
235
- root.fallback = new PageTreeBuilder(isolatedStorage, {
236
- idPrefix: this.idPrefix ? `fallback:${this.idPrefix}` : "fallback",
237
- url: this.getUrl,
238
- noRef: this.noRef,
239
- transformers: this.transformers,
235
+ root.fallback = createPageTreeBuilder(isolatedStorage, {
236
+ ...this.options,
237
+ idPrefix: this.options.idPrefix ? `fallback:${this.options.idPrefix}` : "fallback",
240
238
  generateFallback: false,
241
239
  context: {
242
240
  ...this.custom,
@@ -267,40 +265,50 @@ const rest = "...";
267
265
  const restReversed = "z...a";
268
266
  const extractPrefix = "...";
269
267
  const excludePrefix = "!";
270
- var PageTreeBuilder = class {
271
- constructor(input, options) {
272
- this.flattenPathToFullPath = /* @__PURE__ */ new Map();
273
- this.transformers = [];
274
- this.pathToNode = /* @__PURE__ */ new Map();
275
- this.unfinished = /* @__PURE__ */ new WeakSet();
276
- this.ownerMap = /* @__PURE__ */ new Map();
277
- this._nextId = 0;
278
- const { transformers, url, context, generateFallback = true, idPrefix = "", noRef = false } = options;
279
- if (transformers) this.transformers.push(...transformers);
280
- if (generateFallback) this.transformers.push(transformerFallback());
281
- this.ctx = {
282
- builder: this,
283
- idPrefix,
284
- getUrl: url,
285
- storage: void 0,
286
- noRef,
287
- transformers: this.transformers,
288
- custom: context
268
+ const SymbolUnfinished = Symbol("unfinished");
269
+ const SymbolName = Symbol("name");
270
+ const SymbolOwner = Symbol("owner");
271
+ function createPageTreeBuilder(input, options) {
272
+ const flattenPathToFullPath = /* @__PURE__ */ new Map();
273
+ const transformers = [];
274
+ /** virtual file path -> output page tree node (if cached) */
275
+ const pathToNode = /* @__PURE__ */ new Map();
276
+ let _nextId = 0;
277
+ const { noRef = false, idPrefix, url: getUrl, generateFallback = true, sort: { by: sortBy = "path", locales: sortLocales, options: sortOptions } = {} } = options;
278
+ /** passed as additional information to transformers */
279
+ let ctx;
280
+ if (options.transformers) transformers.push(...options.transformers);
281
+ if (generateFallback) transformers.push(transformerFallback());
282
+ if (Array.isArray(input)) {
283
+ const [locale, storages] = input;
284
+ ctx = {
285
+ get builder() {
286
+ return builder;
287
+ },
288
+ storage: storages[locale],
289
+ storages,
290
+ locale,
291
+ transformers,
292
+ custom: options.context,
293
+ options
289
294
  };
290
- if (Array.isArray(input)) {
291
- const [locale, storages] = input;
292
- this.ctx.storage = this.storage = storages[locale];
293
- this.ctx.locale = locale;
294
- this.ctx.storages = storages;
295
- } else this.ctx.storage = this.storage = input;
296
- for (const file of this.storage.getFiles()) {
297
- const content = this.storage.read(file);
298
- const flattenPath = file.substring(0, file.length - extname(file).length);
299
- this.flattenPathToFullPath.set(flattenPath + "." + content.format, file);
300
- }
295
+ } else ctx = {
296
+ get builder() {
297
+ return builder;
298
+ },
299
+ storage: input,
300
+ transformers,
301
+ custom: options.context,
302
+ options
303
+ };
304
+ const { storage, locale } = ctx;
305
+ for (const file of storage.getFiles()) {
306
+ const content = storage.read(file);
307
+ const flattenPath = file.substring(0, file.length - extname(file).length);
308
+ flattenPathToFullPath.set(flattenPath + "." + content.format, file);
301
309
  }
302
- resolveFlattenPath(name, format) {
303
- return this.flattenPathToFullPath.get(name + "." + format) ?? name;
310
+ function resolveFlattenPath(name, format) {
311
+ return flattenPathToFullPath.get(name + "." + format) ?? name;
304
312
  }
305
313
  /**
306
314
  * try to register as the owner of `node`.
@@ -309,14 +317,14 @@ var PageTreeBuilder = class {
309
317
  *
310
318
  * @returns whether the owner owns the node.
311
319
  */
312
- own(ownerPath, node, priority) {
313
- if (this.unfinished.has(node)) return false;
314
- const existing = this.ownerMap.get(node);
320
+ function own(ownerPath, node, priority) {
321
+ if (node[SymbolUnfinished]) return false;
322
+ const existing = node[SymbolOwner];
315
323
  if (!existing) {
316
- this.ownerMap.set(node, {
324
+ node[SymbolOwner] = {
317
325
  owner: ownerPath,
318
326
  priority
319
- });
327
+ };
320
328
  return true;
321
329
  }
322
330
  if (existing.owner === ownerPath) {
@@ -324,7 +332,7 @@ var PageTreeBuilder = class {
324
332
  return true;
325
333
  }
326
334
  if (existing.priority >= priority) return false;
327
- const folder = this.pathToNode.get(existing.owner);
335
+ const folder = pathToNode.get(existing.owner);
328
336
  if (folder && folder.type === "folder") if (folder.index === node) delete folder.index;
329
337
  else {
330
338
  const idx = folder.children.indexOf(node);
@@ -334,35 +342,43 @@ var PageTreeBuilder = class {
334
342
  existing.priority = priority;
335
343
  return true;
336
344
  }
337
- transferOwner(ownerPath, node) {
338
- const existing = this.ownerMap.get(node);
345
+ function transferOwner(ownerPath, node) {
346
+ const existing = node[SymbolOwner];
339
347
  if (existing) existing.owner = ownerPath;
340
348
  }
341
- generateId(localId = `_${this._nextId++}`) {
349
+ function generateId(localId = `_${_nextId++}`) {
342
350
  let id = localId;
343
- if (this.ctx.locale) id = `${this.ctx.locale}:${id}`;
344
- if (this.ctx.idPrefix) id = `${this.ctx.idPrefix}:${id}`;
351
+ if (locale) id = `${locale}:${id}`;
352
+ if (idPrefix) id = `${idPrefix}:${id}`;
345
353
  return id;
346
354
  }
347
- buildPaths(paths, filter, reversed = false) {
348
- const items = [];
349
- const folders = [];
350
- const sortedPaths = paths.sort((a, b) => reversed ? b.localeCompare(a) : a.localeCompare(b));
351
- for (const path of sortedPaths) {
355
+ function buildPaths(paths, filter, reversed = false) {
356
+ const nodeToPath = /* @__PURE__ */ new Map();
357
+ let indexNode;
358
+ for (const path of paths) {
352
359
  if (filter && !filter(path)) continue;
353
- const fileNode = this.file(path);
360
+ const fileNode = buildFile(path);
354
361
  if (fileNode) {
355
- if (basename(path, extname(path)) === "index") items.unshift(fileNode);
356
- else items.push(fileNode);
362
+ nodeToPath.set(fileNode, path);
363
+ if (!indexNode && basename(path, extname(path)) === "index") indexNode = fileNode;
357
364
  continue;
358
365
  }
359
- const dirNode = this.folder(path);
360
- if (dirNode) folders.push(dirNode);
366
+ const dirNode = buildFolder(path);
367
+ if (dirNode) nodeToPath.set(dirNode, path);
361
368
  }
362
- items.push(...folders);
363
- return items;
369
+ const factor = reversed ? -1 : 1;
370
+ const useName = sortBy === "name";
371
+ return Array.from(nodeToPath.keys()).sort((a, b) => {
372
+ if (a === indexNode) return -100;
373
+ if (b === indexNode) return 100;
374
+ const aT = useName && a[SymbolName] || nodeToPath.get(a);
375
+ const bT = useName && b[SymbolName] || nodeToPath.get(b);
376
+ const aK = a.type === "folder" ? 10 : 0;
377
+ const bK = b.type === "folder" ? 10 : 0;
378
+ return factor * (aT.localeCompare(bT, sortLocales, sortOptions) + (aK - bK));
379
+ });
364
380
  }
365
- resolveFolderItem(folderPath, item, outputArray, excludedPaths) {
381
+ function resolveFolderItem(folderPath, item, outputArray, excludedPaths) {
366
382
  if (item === rest || item === restReversed) {
367
383
  outputArray.push(item);
368
384
  return;
@@ -370,14 +386,14 @@ var PageTreeBuilder = class {
370
386
  let match = separator.exec(item);
371
387
  if (match?.groups) {
372
388
  let node = {
373
- $id: this.generateId(),
389
+ $id: generateId(),
374
390
  type: "separator",
375
391
  icon: match.groups.icon,
376
392
  name: match.groups.name
377
393
  };
378
- for (const transformer of this.transformers) {
394
+ for (const transformer of transformers) {
379
395
  if (!transformer.separator) continue;
380
- node = transformer.separator.call(this.ctx, node);
396
+ node = transformer.separator.call(ctx, node);
381
397
  }
382
398
  outputArray.push(node);
383
399
  return;
@@ -386,16 +402,16 @@ var PageTreeBuilder = class {
386
402
  if (match?.groups) {
387
403
  const { icon, url, name, external } = match.groups;
388
404
  let node = {
389
- $id: this.generateId(),
405
+ $id: generateId(),
390
406
  type: "page",
391
407
  icon,
392
408
  name,
393
409
  url
394
410
  };
395
411
  if (external) node.external = true;
396
- for (const transformer of this.transformers) {
412
+ for (const transformer of transformers) {
397
413
  if (!transformer.file) continue;
398
- node = transformer.file.call(this.ctx, node);
414
+ node = transformer.file.call(ctx, node);
399
415
  }
400
416
  outputArray.push(node);
401
417
  return;
@@ -403,42 +419,42 @@ var PageTreeBuilder = class {
403
419
  if (item.startsWith(excludePrefix)) {
404
420
  const path = joinPath(folderPath, item.slice(1));
405
421
  excludedPaths.add(path);
406
- excludedPaths.add(this.resolveFlattenPath(path, "page"));
422
+ excludedPaths.add(resolveFlattenPath(path, "page"));
407
423
  return;
408
424
  }
409
425
  if (item.startsWith(extractPrefix)) {
410
426
  const path = joinPath(folderPath, item.slice(3));
411
- const node = this.folder(path);
427
+ const node = buildFolder(path);
412
428
  if (!node) return;
413
429
  const children = node.index ? [node.index, ...node.children] : node.children;
414
- if (this.own(folderPath, node, 2)) {
430
+ if (own(folderPath, node, 2)) {
415
431
  for (const child of children) {
416
- this.transferOwner(folderPath, child);
432
+ transferOwner(folderPath, child);
417
433
  outputArray.push(child);
418
434
  }
419
435
  excludedPaths.add(path);
420
- } else for (const child of children) if (this.own(folderPath, child, 2)) outputArray.push(child);
436
+ } else for (const child of children) if (own(folderPath, child, 2)) outputArray.push(child);
421
437
  return;
422
438
  }
423
439
  let path = joinPath(folderPath, item);
424
- let node = this.folder(path);
440
+ let node = buildFolder(path);
425
441
  if (!node) {
426
- path = this.resolveFlattenPath(path, "page");
427
- node = this.file(path);
442
+ path = resolveFlattenPath(path, "page");
443
+ node = buildFile(path);
428
444
  }
429
- if (!node || !this.own(folderPath, node, 2)) return;
445
+ if (!node || !own(folderPath, node, 2)) return;
430
446
  outputArray.push(node);
431
447
  excludedPaths.add(path);
432
448
  }
433
- folder(folderPath) {
434
- const cached = this.pathToNode.get(folderPath);
449
+ function buildFolder(folderPath) {
450
+ const cached = pathToNode.get(folderPath);
435
451
  if (cached) return cached;
436
- const files = this.storage.readDir(folderPath);
452
+ const files = storage.readDir(folderPath);
437
453
  if (!files) return;
438
454
  const isGlobalRoot = folderPath === "";
439
- const metaPath = this.resolveFlattenPath(joinPath(folderPath, "meta"), "meta");
440
- const indexPath = this.resolveFlattenPath(joinPath(folderPath, "index"), "page");
441
- let meta = this.storage.read(metaPath);
455
+ const metaPath = resolveFlattenPath(joinPath(folderPath, "meta"), "meta");
456
+ const indexPath = resolveFlattenPath(joinPath(folderPath, "index"), "page");
457
+ let meta = storage.read(metaPath);
442
458
  if (meta && meta.format !== "meta") meta = void 0;
443
459
  const metadata = meta?.data ?? {};
444
460
  let node = {
@@ -449,19 +465,19 @@ var PageTreeBuilder = class {
449
465
  description: metadata.description,
450
466
  collapsible: metadata.collapsible,
451
467
  children: [],
452
- $id: this.generateId(folderPath),
453
- $ref: !this.ctx.noRef && meta ? metaPath : void 0
468
+ $id: generateId(folderPath),
469
+ $ref: !noRef && meta ? metaPath : void 0,
470
+ [SymbolUnfinished]: true
454
471
  };
455
- this.pathToNode.set(folderPath, node);
456
- this.unfinished.add(node);
472
+ pathToNode.set(folderPath, node);
457
473
  if (!(metadata.root ?? isGlobalRoot)) {
458
- const file = this.file(indexPath);
459
- if (file && this.own(folderPath, file, 0)) node.index = file;
474
+ const fileNode = buildFile(indexPath);
475
+ if (fileNode && own(folderPath, fileNode, 0)) node.index = fileNode;
460
476
  }
461
477
  if (metadata.pages) {
462
478
  const outputArray = [];
463
479
  const excludedPaths = /* @__PURE__ */ new Set();
464
- for (const item of metadata.pages) this.resolveFolderItem(folderPath, item, outputArray, excludedPaths);
480
+ for (const item of metadata.pages) resolveFolderItem(folderPath, item, outputArray, excludedPaths);
465
481
  if (excludedPaths.has(indexPath)) delete node.index;
466
482
  else if (node.index) excludedPaths.add(indexPath);
467
483
  for (const item of outputArray) {
@@ -469,63 +485,73 @@ var PageTreeBuilder = class {
469
485
  node.children.push(item);
470
486
  continue;
471
487
  }
472
- const resolvedItem = this.buildPaths(files, (file) => !excludedPaths.has(file), item === restReversed);
473
- for (const child of resolvedItem) if (this.own(folderPath, child, 0)) node.children.push(child);
488
+ const resolvedItem = buildPaths(files, (file) => !excludedPaths.has(file), item === restReversed);
489
+ for (const child of resolvedItem) if (own(folderPath, child, 0)) node.children.push(child);
474
490
  }
475
- } else for (const item of this.buildPaths(files, node.index ? (file) => file !== indexPath : void 0)) if (this.own(folderPath, item, 0)) node.children.push(item);
491
+ } else for (const item of buildPaths(files, node.index ? (file) => file !== indexPath : void 0)) if (own(folderPath, item, 0)) node.children.push(item);
476
492
  node.icon = metadata.icon ?? node.index?.icon;
477
493
  node.name = metadata.title ?? node.index?.name;
478
- this.unfinished.delete(node);
494
+ node[SymbolName] = metadata.title ?? node.index?.[SymbolName];
479
495
  if (!node.name) {
480
496
  const folderName = basename(folderPath);
481
497
  node.name = pathToName(group.exec(folderName)?.[1] ?? folderName);
482
498
  }
483
- for (const transformer of this.transformers) {
499
+ for (const transformer of transformers) {
484
500
  if (!transformer.folder) continue;
485
- node = transformer.folder.call(this.ctx, node, folderPath, meta ? metaPath : void 0);
501
+ node = transformer.folder.call(ctx, node, folderPath, meta ? metaPath : void 0);
486
502
  }
487
- this.pathToNode.set(folderPath, node);
503
+ pathToNode.set(folderPath, node);
504
+ delete node[SymbolUnfinished];
488
505
  return node;
489
506
  }
490
- file(path) {
491
- const cached = this.pathToNode.get(path);
507
+ function buildFile(path) {
508
+ const cached = pathToNode.get(path);
492
509
  if (cached) return cached;
493
- const page = this.storage.read(path);
510
+ const page = storage.read(path);
494
511
  if (!page || page.format !== "page") return;
495
512
  const { title, description, icon } = page.data;
496
513
  let item = {
497
- $id: this.generateId(path),
514
+ $id: generateId(path),
498
515
  type: "page",
499
516
  name: title ?? pathToName(basename(path, extname(path))),
500
517
  description,
501
518
  icon,
502
- url: this.ctx.getUrl(page.slugs, this.ctx.locale),
503
- $ref: !this.ctx.noRef ? path : void 0
519
+ url: getUrl(page.slugs, ctx.locale),
520
+ $ref: !noRef ? path : void 0,
521
+ [SymbolName]: title
504
522
  };
505
- for (const transformer of this.transformers) {
523
+ for (const transformer of transformers) {
506
524
  if (!transformer.file) continue;
507
- item = transformer.file.call(this.ctx, item, path);
525
+ item = transformer.file.call(ctx, item, path);
508
526
  }
509
- this.pathToNode.set(path, item);
527
+ pathToNode.set(path, item);
510
528
  return item;
511
529
  }
512
- root(id = "root", path = "") {
513
- const folder = this.folder(path);
514
- let root = {
515
- type: "root",
516
- $ref: folder?.$ref,
517
- $id: this.generateId(id),
518
- name: folder?.name || "Docs",
519
- description: folder?.description,
520
- children: folder ? folder.children : []
521
- };
522
- for (const transformer of this.transformers) {
523
- if (!transformer.root) continue;
524
- root = transformer.root.call(this.ctx, root);
530
+ const builder = {
531
+ resolveFlattenPath,
532
+ root(id = "root", path = "") {
533
+ const node = buildFolder(path);
534
+ let root = {
535
+ type: "root",
536
+ $ref: node?.$ref,
537
+ $id: generateId(id),
538
+ name: node?.name || "Docs",
539
+ description: node?.description,
540
+ children: node ? node.children : []
541
+ };
542
+ for (const transformer of transformers) {
543
+ if (!transformer.root) continue;
544
+ root = transformer.root.call(ctx, root);
545
+ }
546
+ for (const node of pathToNode.values()) {
547
+ delete node[SymbolName];
548
+ delete node[SymbolOwner];
549
+ }
550
+ return root;
525
551
  }
526
- return root;
527
- }
528
- };
552
+ };
553
+ return builder;
554
+ }
529
555
  /**
530
556
  * Get item name from file name
531
557
  *
@@ -623,10 +649,10 @@ function loader(...args) {
623
649
  ...pageTreeConfig,
624
650
  transformers
625
651
  };
626
- if (storage instanceof FileSystem) return pageTrees = new PageTreeBuilder(storage, options).root();
652
+ if (storage instanceof FileSystem) return pageTrees = createPageTreeBuilder(storage, options).root();
627
653
  else {
628
654
  const out = {};
629
- for (const locale in storage) out[locale] = new PageTreeBuilder([locale, storage], options).root();
655
+ for (const locale in storage) out[locale] = createPageTreeBuilder([locale, storage], options).root();
630
656
  return pageTrees = out;
631
657
  }
632
658
  }
@@ -1,7 +1,7 @@
1
1
  import { t as Awaitable } from "../types-DpbpliNk.js";
2
- import { t as I18nConfig } from "../index-BreFfl9v.js";
3
- import { m as SharedIndex, n as SearchAPI, t as QueryOptions } from "../server-CQJ8bzkB.js";
4
- import { C as LoaderConfig, T as LoaderOutput } from "../index-VMicRewG2.js";
2
+ import { n as I18nConfig } from "../index-YTOeewZk.js";
3
+ import { m as SharedIndex, n as SearchAPI, t as QueryOptions } from "../server-BmBBtKX6.js";
4
+ import { C as LoaderConfig, T as LoaderOutput } from "../index-CKvjS08M2.js";
5
5
  import { DocumentData, DocumentOptions } from "flexsearch";
6
6
 
7
7
  //#region src/search/server/build-doc.d.ts
@@ -1,5 +1,5 @@
1
1
  import { r as SortedResult } from "../index-Bcms_L7o.js";
2
- import { n as SearchAPI } from "../server-CQJ8bzkB.js";
2
+ import { n as SearchAPI } from "../server-BmBBtKX6.js";
3
3
  import Mixedbread from "@mixedbread/sdk";
4
4
  import { StoreSearchResponse } from "@mixedbread/sdk/resources/stores";
5
5
 
@@ -1,2 +1,2 @@
1
- import { a as AdvancedOptions, c as SimpleOptions, d as createSearchAPI, f as initAdvancedSearch, i as AdvancedIndex, l as createFromSource, n as SearchAPI, o as ExportedData, p as initSimpleSearch, r as SearchServer, s as Index, t as QueryOptions, u as createI18nSearchAPI } from "../server-CQJ8bzkB.js";
1
+ import { a as AdvancedOptions, c as SimpleOptions, d as createSearchAPI, f as initAdvancedSearch, i as AdvancedIndex, l as createFromSource, n as SearchAPI, o as ExportedData, p as initSimpleSearch, r as SearchServer, s as Index, t as QueryOptions, u as createI18nSearchAPI } from "../server-BmBBtKX6.js";
2
2
  export { AdvancedIndex, AdvancedOptions, ExportedData, Index, QueryOptions, SearchAPI, SearchServer, SimpleOptions, createFromSource, createI18nSearchAPI, createSearchAPI, initAdvancedSearch, initSimpleSearch };
@@ -1,8 +1,8 @@
1
1
  import { t as Awaitable } from "./types-DpbpliNk.js";
2
2
  import { i as StructuredData } from "./remark-structure-C2-K9_ko.js";
3
- import { t as I18nConfig } from "./index-BreFfl9v.js";
3
+ import { n as I18nConfig } from "./index-YTOeewZk.js";
4
4
  import { r as SortedResult } from "./index-Bcms_L7o.js";
5
- import { C as LoaderConfig, T as LoaderOutput } from "./index-VMicRewG2.js";
5
+ import { C as LoaderConfig, T as LoaderOutput } from "./index-CKvjS08M2.js";
6
6
  import { Language, Orama, RawData, SearchParams, TypedDocument, create } from "@orama/orama";
7
7
 
8
8
  //#region src/search/orama/create-db.d.ts
@@ -1,2 +1,2 @@
1
- import { b as dynamicLoader, v as DynamicLoader, y as DynamicLoaderConfig } from "../index-VMicRewG2.js";
1
+ import { b as dynamicLoader, v as DynamicLoader, y as DynamicLoaderConfig } from "../index-CKvjS08M2.js";
2
2
  export { DynamicLoader, DynamicLoaderConfig, dynamicLoader };
@@ -1,4 +1,4 @@
1
- import { i as isStaticSource, n as loader, r as isDynamicSource } from "../loader-Bs2iumYD.js";
1
+ import { i as isStaticSource, n as loader, r as isDynamicSource } from "../loader-DWaWaGZg.js";
2
2
  import { cache } from "react";
3
3
  //#region src/source/dynamic.ts
4
4
  function dynamicLoader(input, options) {
@@ -1,2 +1,2 @@
1
- import { A as ResolvedLoaderConfig, B as PageTreeTransformer, C as LoaderConfig, D as LoaderPluginOption, E as LoaderPlugin, H as ContentStorageMetaFile, L as PageTreeBuilder, M as loader, O as Meta, P as getSlugs, R as PageTreeBuilderContext, S as InferPageType, T as LoaderOutput, U as ContentStoragePageFile, V as ContentStorage, W as FileSystem, _ as update, a as MetaData, c as SourceConfig, d as VirtualFile, f as _SourceUpdate_, g as source, h as multiple, i as DynamicSource, j as createGetUrl, k as Page, l as SourceUnion, m as isStaticSource, n as llms, o as PageData, p as isDynamicSource, r as path_d_exports, s as Source, t as LLMsConfig, u as StaticSource, w as LoaderOptions, x as InferMetaType, z as PageTreeOptions } from "../index-VMicRewG2.js";
1
+ import { A as ResolvedLoaderConfig, B as PageTreeTransformer, C as LoaderConfig, D as LoaderPluginOption, E as LoaderPlugin, H as ContentStorageMetaFile, L as PageTreeBuilder, M as loader, O as Meta, P as getSlugs, R as PageTreeBuilderContext, S as InferPageType, T as LoaderOutput, U as ContentStoragePageFile, V as ContentStorage, W as FileSystem, _ as update, a as MetaData, c as SourceConfig, d as VirtualFile, f as _SourceUpdate_, g as source, h as multiple, i as DynamicSource, j as createGetUrl, k as Page, l as SourceUnion, m as isStaticSource, n as llms, o as PageData, p as isDynamicSource, r as path_d_exports, s as Source, t as LLMsConfig, u as StaticSource, w as LoaderOptions, x as InferMetaType, z as PageTreeOptions } from "../index-CKvjS08M2.js";
2
2
  export { ContentStorage, ContentStorageMetaFile, ContentStoragePageFile, DynamicSource, FileSystem, InferMetaType, InferPageType, LLMsConfig, LoaderConfig, LoaderOptions, LoaderOutput, LoaderPlugin, LoaderPluginOption, Meta, MetaData, Page, PageData, PageTreeBuilder, PageTreeBuilderContext, PageTreeOptions, PageTreeTransformer, path_d_exports as PathUtils, ResolvedLoaderConfig, Source, SourceConfig, SourceUnion, StaticSource, VirtualFile, _SourceUpdate_, createGetUrl, getSlugs, isDynamicSource, isStaticSource, llms, loader, multiple, source, update };
@@ -1,5 +1,5 @@
1
1
  import { o as path_exports } from "../path-CPgAF5cw.js";
2
- import { a as multiple, c as FileSystem, i as isStaticSource, n as loader, o as source, r as isDynamicSource, s as update, t as createGetUrl } from "../loader-Bs2iumYD.js";
2
+ import { a as multiple, c as FileSystem, i as isStaticSource, n as loader, o as source, r as isDynamicSource, s as update, t as createGetUrl } from "../loader-DWaWaGZg.js";
3
3
  import { getSlugs } from "./plugins/slugs.js";
4
4
  import { llms } from "./llms.js";
5
5
  export { FileSystem, path_exports as PathUtils, createGetUrl, getSlugs, isDynamicSource, isStaticSource, llms, loader, multiple, source, update };
@@ -1,2 +1,2 @@
1
- import { n as llms, t as LLMsConfig } from "../index-VMicRewG2.js";
1
+ import { n as llms, t as LLMsConfig } from "../index-CKvjS08M2.js";
2
2
  export { LLMsConfig, llms };
@@ -1,4 +1,4 @@
1
- import { E as LoaderPlugin } from "../../index-VMicRewG2.js";
1
+ import { E as LoaderPlugin } from "../../index-CKvjS08M2.js";
2
2
  import { icons } from "lucide-react";
3
3
 
4
4
  //#region src/source/plugins/lucide-icons.d.ts
@@ -1,2 +1,2 @@
1
- import { F as slugsFromData, I as slugsPlugin, N as SlugFn, P as getSlugs } from "../../index-VMicRewG2.js";
1
+ import { F as slugsFromData, I as slugsPlugin, N as SlugFn, P as getSlugs } from "../../index-CKvjS08M2.js";
2
2
  export { SlugFn, getSlugs, slugsFromData, slugsPlugin };
@@ -1,5 +1,5 @@
1
1
  import { a as Separator$1, n as Item$1, t as Folder$1 } from "../../definitions-Cob-Q8-8.js";
2
- import { E as LoaderPlugin } from "../../index-VMicRewG2.js";
2
+ import { E as LoaderPlugin } from "../../index-CKvjS08M2.js";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/source/plugins/status-badges.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "16.8.12",
3
+ "version": "16.9.0",
4
4
  "description": "The React.js library for building a documentation website",
5
5
  "keywords": [
6
6
  "Docs",
@@ -1,40 +0,0 @@
1
- //#region src/i18n/index.d.ts
2
- interface I18nConfig<Languages extends string = string> {
3
- /**
4
- * Supported locale codes.
5
- *
6
- * A page tree will be built for each language.
7
- */
8
- languages: Languages[];
9
- /**
10
- * Default locale if not specified
11
- */
12
- defaultLanguage: Languages;
13
- /**
14
- * Don't show the locale prefix on URL.
15
- *
16
- * - `always`: Always hide the prefix
17
- * - `default-locale`: Only hide the default locale
18
- * - `never`: Never hide the prefix
19
- *
20
- * This API uses `NextResponse.rewrite`.
21
- *
22
- * @defaultValue 'never'
23
- */
24
- hideLocale?: 'always' | 'default-locale' | 'never';
25
- /**
26
- * Used by `loader()`, specify the way to parse i18n file structure.
27
- *
28
- * @defaultValue 'dot'
29
- */
30
- parser?: 'dot' | 'dir' | 'none';
31
- /**
32
- * the fallback language when the page has no translations available for a given locale.
33
- *
34
- * Default to `defaultLanguage`, no fallback when set to `null`.
35
- */
36
- fallbackLanguage?: Languages | null;
37
- }
38
- declare function defineI18n<Languages extends string>(config: I18nConfig<Languages>): I18nConfig<Languages>;
39
- //#endregion
40
- export { defineI18n as n, I18nConfig as t };