fumadocs-core 15.2.5 → 15.2.7

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,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { R as Root, N as Node } from './page-tree-9q98UqWL.js';
2
+ import { R as Root, N as Node } from './page-tree-BG3wP0gU.js';
3
3
 
4
4
  interface BreadcrumbItem {
5
5
  name: ReactNode;
@@ -33,7 +33,7 @@ function remarkHeading({
33
33
  lastNode.value = lastNode.value.slice(0, match.index);
34
34
  }
35
35
  }
36
- let flattened;
36
+ let flattened = null;
37
37
  if (!id) {
38
38
  flattened ??= flattenNode(heading);
39
39
  id = defaultSlug ? defaultSlug(root, heading, flattened) : slugger.slug(flattened);
@@ -4,8 +4,9 @@ import { RehypeShikiOptions } from '@shikijs/rehype';
4
4
  import { Processor, Transformer } from 'unified';
5
5
  import { ShikiTransformer } from 'shiki';
6
6
  import { Root as Root$1 } from 'mdast';
7
- export { a as StructureOptions, S as StructuredData, r as remarkStructure, s as structure } from '../remark-structure-1kvQbrfH.js';
7
+ export { a as StructureOptions, S as StructuredData, r as remarkStructure, s as structure } from '../remark-structure-FIjTA11P.js';
8
8
  export { R as RemarkHeadingOptions, r as remarkHeading } from '../remark-heading-BPCoYwjn.js';
9
+ import 'mdast-util-mdx-jsx';
9
10
 
10
11
  interface CodeBlockIcon {
11
12
  viewBox: string;
@@ -113,4 +114,23 @@ declare function rehypeToc(this: Processor, { exportToc }?: RehypeTocOptions): T
113
114
 
114
115
  declare function remarkCodeTab(): Transformer<Root$1, Root$1>;
115
116
 
116
- export { type CodeBlockIcon, type RehypeCodeOptions, type RehypeTocOptions, type RemarkAdmonitionOptions, type RemarkImageOptions, rehypeCode, rehypeCodeDefaultOptions, rehypeToc, remarkAdmonition, remarkCodeTab, remarkImage, transformerIcon, transformerTab };
117
+ interface RemarkStepsOptions {
118
+ /**
119
+ * Class name for steps container
120
+ *
121
+ * @defaultValue fd-steps
122
+ */
123
+ steps?: string;
124
+ /**
125
+ * Class name for step container
126
+ *
127
+ * @defaultValue fd-step
128
+ */
129
+ step?: string;
130
+ }
131
+ /**
132
+ * Convert headings in the format of `1. Hello World` into steps.
133
+ */
134
+ declare function remarkSteps({ steps, step, }?: RemarkStepsOptions): Transformer<Root$1, Root$1>;
135
+
136
+ export { type CodeBlockIcon, type RehypeCodeOptions, type RehypeTocOptions, type RemarkAdmonitionOptions, type RemarkImageOptions, type RemarkStepsOptions, rehypeCode, rehypeCodeDefaultOptions, rehypeToc, remarkAdmonition, remarkCodeTab, remarkImage, remarkSteps, transformerIcon, transformerTab };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  flattenNode,
3
3
  remarkHeading
4
- } from "../chunk-IYQ35KI2.js";
4
+ } from "../chunk-Y2774T3B.js";
5
5
  import {
6
6
  joinPath,
7
7
  slash
@@ -185,10 +185,6 @@ var metaValues = [
185
185
  {
186
186
  name: "tab",
187
187
  regex: /tab="(?<value>[^"]+)"/
188
- },
189
- {
190
- name: "tab",
191
- regex: /tab/
192
188
  }
193
189
  ];
194
190
  var rehypeCodeDefaultOptions = {
@@ -281,7 +277,7 @@ function transformerTab() {
281
277
  data: {
282
278
  _codeblock: true
283
279
  },
284
- attributes: value !== "" ? [{ type: "mdxJsxAttribute", name: "value", value }] : [],
280
+ attributes: [{ type: "mdxJsxAttribute", name: "value", value }],
285
281
  children: root.children
286
282
  }
287
283
  ]
@@ -447,8 +443,23 @@ import remarkGfm from "remark-gfm";
447
443
  import { visit as visit2 } from "unist-util-visit";
448
444
  var slugger = new Slugger();
449
445
  function remarkStructure({
450
- types = ["paragraph", "blockquote", "heading", "tableCell"]
446
+ types = [
447
+ "heading",
448
+ "paragraph",
449
+ "blockquote",
450
+ "tableCell",
451
+ "mdxJsxFlowElement"
452
+ ],
453
+ allowedMdxAttributes = () => true
451
454
  } = {}) {
455
+ if (Array.isArray(allowedMdxAttributes)) {
456
+ const arr = allowedMdxAttributes;
457
+ allowedMdxAttributes = (_node, attribute) => attribute.type === "mdxJsxAttribute" && arr.includes(attribute.name);
458
+ }
459
+ if (Array.isArray(types)) {
460
+ const arr = types;
461
+ types = (node) => arr.includes(node.type);
462
+ }
452
463
  return (node, file) => {
453
464
  slugger.reset();
454
465
  const data = { contents: [], headings: [] };
@@ -462,24 +473,25 @@ function remarkStructure({
462
473
  }
463
474
  visit2(node, (element) => {
464
475
  if (element.type === "root") return;
476
+ if (!types(element)) return;
465
477
  if (element.type === "heading") {
466
478
  element.data ||= {};
467
479
  element.data.hProperties ||= {};
468
480
  const properties = element.data.hProperties;
469
- const content = flattenNode(element).trim();
470
- const id = properties.id ?? slugger.slug(content);
481
+ const content2 = flattenNode(element).trim();
482
+ const id = properties.id ?? slugger.slug(content2);
471
483
  data.headings.push({
472
484
  id,
473
- content
485
+ content: content2
474
486
  });
475
487
  lastHeading = id;
476
488
  return "skip";
477
489
  }
478
490
  if (element.data?._string) {
479
- for (const content of element.data._string) {
491
+ for (const content2 of element.data._string) {
480
492
  data.contents.push({
481
493
  heading: lastHeading,
482
- content
494
+ content: content2
483
495
  });
484
496
  }
485
497
  return "skip";
@@ -493,6 +505,8 @@ function remarkStructure({
493
505
  ...element.attributes.flatMap((attribute) => {
494
506
  const valueStr = typeof attribute.value === "string" ? attribute.value : attribute.value?.value;
495
507
  if (!valueStr) return [];
508
+ if (allowedMdxAttributes && !allowedMdxAttributes(element, attribute))
509
+ return [];
496
510
  return {
497
511
  heading: lastHeading,
498
512
  content: attribute.type === "mdxJsxAttribute" ? `${attribute.name}: ${valueStr}` : valueStr
@@ -501,15 +515,13 @@ function remarkStructure({
501
515
  );
502
516
  return;
503
517
  }
504
- if (types.includes(element.type)) {
505
- const content = flattenNode(element).trim();
506
- if (content.length === 0) return;
507
- data.contents.push({
508
- heading: lastHeading,
509
- content
510
- });
511
- return "skip";
512
- }
518
+ const content = flattenNode(element).trim();
519
+ if (content.length === 0) return;
520
+ data.contents.push({
521
+ heading: lastHeading,
522
+ content
523
+ });
524
+ return "skip";
513
525
  });
514
526
  file.data.structuredData = data;
515
527
  };
@@ -787,32 +799,123 @@ function toTab(nodes) {
787
799
  function remarkCodeTab() {
788
800
  return (tree) => {
789
801
  visit5(tree, (node) => {
802
+ if (!("children" in node)) return;
790
803
  if (node.type === "mdxJsxFlowElement" && node.name === "Tabs") return;
791
- if ("children" in node) {
792
- let start = -1;
793
- let i = 0;
794
- while (i < node.children.length) {
795
- const child = node.children[i];
796
- const isSwitcher = child.type === "code" && child.meta && child.meta.match(TabRegex);
797
- if (isSwitcher && start === -1) {
798
- start = i;
799
- }
800
- const isLast = i === node.children.length - 1;
801
- if (start !== -1 && (isLast || !isSwitcher)) {
802
- const end = isSwitcher ? i + 1 : i;
803
- const targets = node.children.slice(start, end);
804
- node.children.splice(
805
- start,
806
- end - start,
807
- toTab(targets)
808
- );
809
- if (isLast) break;
810
- i = start;
811
- start = -1;
812
- }
813
- i++;
804
+ let start = -1;
805
+ let i = 0;
806
+ while (i < node.children.length) {
807
+ const child = node.children[i];
808
+ const isSwitcher = child.type === "code" && child.meta && child.meta.match(TabRegex);
809
+ if (isSwitcher && start === -1) {
810
+ start = i;
811
+ }
812
+ const isLast = i === node.children.length - 1;
813
+ if (start !== -1 && (isLast || !isSwitcher)) {
814
+ const end = isSwitcher ? i + 1 : i;
815
+ const targets = node.children.slice(start, end);
816
+ node.children.splice(
817
+ start,
818
+ end - start,
819
+ toTab(targets)
820
+ );
821
+ if (isLast) break;
822
+ i = start;
823
+ start = -1;
824
+ }
825
+ i++;
826
+ }
827
+ });
828
+ };
829
+ }
830
+
831
+ // src/mdx-plugins/remark-steps.ts
832
+ import { visit as visit6 } from "unist-util-visit";
833
+ var StepRegex = /^(\d+)\.\s(.+)$/;
834
+ function remarkSteps({
835
+ steps = "fd-steps",
836
+ step = "fd-step"
837
+ } = {}) {
838
+ function convertToSteps(nodes) {
839
+ const depth = nodes[0].depth;
840
+ const children = [];
841
+ for (const node of nodes) {
842
+ if (node.type === "heading" && node.depth === depth) {
843
+ children.push({
844
+ type: "mdxJsxFlowElement",
845
+ name: "div",
846
+ attributes: [
847
+ {
848
+ type: "mdxJsxAttribute",
849
+ name: "className",
850
+ value: step
851
+ }
852
+ ],
853
+ children: [node]
854
+ });
855
+ } else {
856
+ children[children.length - 1].children.push(node);
857
+ }
858
+ }
859
+ return {
860
+ type: "mdxJsxFlowElement",
861
+ name: "div",
862
+ attributes: [
863
+ {
864
+ type: "mdxJsxAttribute",
865
+ name: "className",
866
+ value: steps
867
+ }
868
+ ],
869
+ data: {
870
+ _fd_step: true
871
+ },
872
+ children
873
+ };
874
+ }
875
+ return (tree) => {
876
+ visit6(tree, (parent) => {
877
+ if (!("children" in parent) || parent.type === "heading") return;
878
+ if (parent.data && "_fd_step" in parent.data) return "skip";
879
+ let startIdx = -1;
880
+ let lastNumber = 0;
881
+ let i = 0;
882
+ const onEnd = () => {
883
+ if (startIdx === -1) return;
884
+ const item = {};
885
+ const nodes = parent.children.splice(
886
+ startIdx,
887
+ i - startIdx,
888
+ item
889
+ );
890
+ Object.assign(item, convertToSteps(nodes));
891
+ i = startIdx + 1;
892
+ startIdx = -1;
893
+ };
894
+ for (; i < parent.children.length; i++) {
895
+ const node = parent.children[i];
896
+ if (node.type !== "heading") continue;
897
+ if (startIdx !== -1) {
898
+ const startDepth = parent.children[startIdx].depth;
899
+ if (node.depth > startDepth) continue;
900
+ else if (node.depth < startDepth) onEnd();
901
+ }
902
+ const head = node.children.filter((c) => c.type === "text").at(0);
903
+ if (!head) {
904
+ onEnd();
905
+ continue;
906
+ }
907
+ const match = StepRegex.exec(head.value);
908
+ if (!match) {
909
+ onEnd();
910
+ continue;
814
911
  }
912
+ const num = Number(match[1]);
913
+ head.value = match[2];
914
+ if (startIdx !== -1 && num !== lastNumber + 1) onEnd();
915
+ if (startIdx === -1) startIdx = i;
916
+ lastNumber = num;
815
917
  }
918
+ onEnd();
816
919
  });
817
920
  };
818
921
  }
@@ -825,6 +928,7 @@ export {
825
928
  default2 as remarkGfm,
826
929
  remarkHeading,
827
930
  remarkImage,
931
+ remarkSteps,
828
932
  remarkStructure,
829
933
  structure,
830
934
  transformerIcon,
@@ -8,6 +8,9 @@ interface Root {
8
8
  type Node = Item | Separator | Folder;
9
9
  interface Item {
10
10
  $id?: string;
11
+ /**
12
+ * @internal
13
+ */
11
14
  $ref?: {
12
15
  file: string;
13
16
  };
@@ -26,6 +29,9 @@ interface Separator {
26
29
  }
27
30
  interface Folder {
28
31
  $id?: string;
32
+ /**
33
+ * @internal
34
+ */
29
35
  $ref?: {
30
36
  metaFile?: string;
31
37
  };
@@ -1,5 +1,6 @@
1
- import { Root } from 'mdast';
1
+ import { Nodes, Root } from 'mdast';
2
2
  import { Transformer, PluggableList } from 'unified';
3
+ import { MdxJsxAttribute, MdxJsxExpressionAttribute } from 'mdast-util-mdx-jsx';
3
4
 
4
5
  interface Heading {
5
6
  id: string;
@@ -20,9 +21,10 @@ interface StructureOptions {
20
21
  /**
21
22
  * Types to be scanned as content.
22
23
  *
23
- * @defaultValue ['paragraph', 'blockquote', 'tableCell']
24
+ * @defaultValue ['heading', 'paragraph', 'blockquote', 'tableCell', 'mdxJsxFlowElement']
24
25
  */
25
- types?: string[];
26
+ types?: string[] | ((node: Nodes) => boolean);
27
+ allowedMdxAttributes?: string[] | ((node: Nodes, attribute: MdxJsxAttribute | MdxJsxExpressionAttribute) => boolean);
26
28
  }
27
29
  declare module 'mdast' {
28
30
  interface Data {
@@ -37,7 +39,7 @@ declare module 'mdast' {
37
39
  /**
38
40
  * Attach structured data to VFile, you can access via `vfile.data.structuredData`.
39
41
  */
40
- declare function remarkStructure({ types, }?: StructureOptions): Transformer<Root, Root>;
42
+ declare function remarkStructure({ types, allowedMdxAttributes, }?: StructureOptions): Transformer<Root, Root>;
41
43
  /**
42
44
  * Extract data from markdown/mdx content
43
45
  */
@@ -1,7 +1,8 @@
1
1
  import { SearchClient, SearchIndex } from 'algoliasearch';
2
- import { S as StructuredData } from '../remark-structure-1kvQbrfH.js';
2
+ import { S as StructuredData } from '../remark-structure-FIjTA11P.js';
3
3
  import 'mdast';
4
4
  import 'unified';
5
+ import 'mdast-util-mdx-jsx';
5
6
 
6
7
  interface DocumentRecord {
7
8
  /**
@@ -2,10 +2,11 @@ import { S as SortedResult } from '../types-Ch8gnVgO.js';
2
2
  import { AnyOrama } from '@orama/orama';
3
3
  import { SearchOptions } from '@algolia/client-search';
4
4
  import { SearchIndex } from 'algoliasearch/lite';
5
- import '../remark-structure-1kvQbrfH.js';
5
+ import '../remark-structure-FIjTA11P.js';
6
6
  import { OramaClient, ClientSearchParams } from '@oramacloud/client';
7
7
  import 'mdast';
8
8
  import 'unified';
9
+ import 'mdast-util-mdx-jsx';
9
10
 
10
11
  interface FetchOptions {
11
12
  /**
@@ -1,8 +1,9 @@
1
1
  import { CloudManager } from '@oramacloud/client';
2
- import { S as StructuredData } from '../remark-structure-1kvQbrfH.js';
2
+ import { S as StructuredData } from '../remark-structure-FIjTA11P.js';
3
3
  import '../remark-heading-BPCoYwjn.js';
4
4
  import 'mdast';
5
5
  import 'unified';
6
+ import 'mdast-util-mdx-jsx';
6
7
 
7
8
  interface SyncOptions {
8
9
  /**
@@ -1,12 +1,13 @@
1
1
  import { TypedDocument, Orama, Language, RawData, create, SearchParams } from '@orama/orama';
2
- import { S as StructuredData } from '../remark-structure-1kvQbrfH.js';
2
+ import { S as StructuredData } from '../remark-structure-FIjTA11P.js';
3
3
  import { S as SortedResult } from '../types-Ch8gnVgO.js';
4
4
  import { I as I18nConfig } from '../config-inq6kP6y.js';
5
5
  import { LoaderOutput, LoaderConfig, InferPageType } from '../source/index.js';
6
6
  import 'mdast';
7
7
  import 'unified';
8
+ import 'mdast-util-mdx-jsx';
8
9
  import 'react';
9
- import '../page-tree-9q98UqWL.js';
10
+ import '../page-tree-BG3wP0gU.js';
10
11
 
11
12
  type AdvancedDocument = TypedDocument<Orama<typeof advancedSchema>>;
12
13
  declare const advancedSchema: {
@@ -1,6 +1,6 @@
1
1
  export { a as TOCItemType, T as TableOfContents, g as getTableOfContents } from '../get-toc-Cr2URuiP.js';
2
- import { N as Node, I as Item, R as Root, F as Folder } from '../page-tree-9q98UqWL.js';
3
- export { p as PageTree } from '../page-tree-9q98UqWL.js';
2
+ import { N as Node, I as Item, R as Root, F as Folder } from '../page-tree-BG3wP0gU.js';
3
+ export { p as PageTree } from '../page-tree-BG3wP0gU.js';
4
4
  export { S as SortedResult } from '../types-Ch8gnVgO.js';
5
5
  import { Metadata } from 'next';
6
6
  import { NextRequest } from 'next/server';
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  remarkHeading
3
- } from "../chunk-IYQ35KI2.js";
3
+ } from "../chunk-Y2774T3B.js";
4
4
  import "../chunk-MLKGABMK.js";
5
5
 
6
6
  // src/server/get-toc.ts
@@ -1,6 +1,6 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { I as I18nConfig } from '../config-inq6kP6y.js';
3
- import { R as Root, I as Item, F as Folder$1, S as Separator } from '../page-tree-9q98UqWL.js';
3
+ import { R as Root, I as Item, F as Folder$1, S as Separator } from '../page-tree-BG3wP0gU.js';
4
4
 
5
5
  interface FileInfo {
6
6
  /**
@@ -142,8 +142,8 @@ interface LoaderOutput<Config extends LoaderConfig> {
142
142
  * @param language - If empty, the default language will be used
143
143
  */
144
144
  getPage: (slugs: string[] | undefined, language?: string) => Page<Config['source']['pageData']> | undefined;
145
- getNodePage: (node: Item) => Page<Config['source']['pageData']> | undefined;
146
- getNodeMeta: (node: Folder$1) => Meta<Config['source']['metaData']> | undefined;
145
+ getNodePage: (node: Item, language?: string) => Page<Config['source']['pageData']> | undefined;
146
+ getNodeMeta: (node: Folder$1, language?: string) => Meta<Config['source']['metaData']> | undefined;
147
147
  /**
148
148
  * generate static params for Next.js SSG
149
149
  */
@@ -32,17 +32,12 @@ function buildAll(nodes, ctx, skipIndex) {
32
32
  const treeNode = buildFileNode(localized ?? node, ctx);
33
33
  if (node.file.name === "index") {
34
34
  if (!skipIndex) output.unshift(treeNode);
35
- continue;
35
+ } else {
36
+ output.push(treeNode);
36
37
  }
37
- output.push(treeNode);
38
38
  }
39
39
  if ("children" in node) {
40
- const folder = buildFolderNode(node, false, ctx);
41
- if (folder.children.length === 0 && folder.index) {
42
- output.push(folder.index);
43
- } else {
44
- folders.push(folder);
45
- }
40
+ folders.push(buildFolderNode(node, false, ctx));
46
41
  }
47
42
  }
48
43
  output.push(...folders);
@@ -94,19 +89,16 @@ function resolveFolderItem(folder, item, ctx, idx, addedNodePaths) {
94
89
  function buildFolderNode(folder, isGlobalRoot, ctx) {
95
90
  const metaPath = joinPath(folder.file.path, "meta");
96
91
  const meta = ctx.localeStorage?.read(metaPath, "meta") ?? ctx.storage.read(metaPath, "meta");
97
- const indexFile = ctx.storage.read(
98
- joinPath(folder.file.path, "index"),
99
- "page"
100
- );
101
- const metadata = meta?.data;
102
- const isRoot = metadata?.root ?? isGlobalRoot;
92
+ const indexPath = joinPath(folder.file.path, "index");
93
+ const indexFile = ctx.localeStorage?.read(indexPath, "page") ?? ctx.storage.read(indexPath, "page");
94
+ const isRoot = meta?.data.root ?? isGlobalRoot;
103
95
  const index = indexFile ? buildFileNode(indexFile, ctx) : void 0;
96
+ const addedNodePaths = /* @__PURE__ */ new Set();
104
97
  let children;
105
- if (!metadata?.pages) {
98
+ if (!meta?.data.pages) {
106
99
  children = buildAll(folder.children, ctx, !isRoot);
107
100
  } else {
108
- const addedNodePaths = /* @__PURE__ */ new Set();
109
- const resolved = metadata?.pages?.flatMap((item, i) => {
101
+ const resolved = meta.data.pages.flatMap((item, i) => {
110
102
  return resolveFolderItem(folder, item, ctx, i, addedNodePaths);
111
103
  });
112
104
  const restNodes = buildAll(
@@ -126,13 +118,13 @@ function buildFolderNode(folder, isGlobalRoot, ctx) {
126
118
  }
127
119
  const node = {
128
120
  type: "folder",
129
- name: metadata?.title ?? index?.name ?? // resolve folder groups like (group_name)
121
+ name: meta?.data.title ?? index?.name ?? // resolve folder groups like (group_name)
130
122
  pathToName(group.exec(folder.file.name)?.[1] ?? folder.file.name),
131
- icon: ctx.options.resolveIcon?.(metadata?.icon) ?? index?.icon,
132
- root: metadata?.root,
133
- defaultOpen: metadata?.defaultOpen,
134
- description: metadata?.description,
135
- index,
123
+ icon: ctx.options.resolveIcon?.(meta?.data.icon) ?? index?.icon,
124
+ root: meta?.data.root,
125
+ defaultOpen: meta?.data.defaultOpen,
126
+ description: meta?.data.description,
127
+ index: isRoot || indexFile && !addedNodePaths.has(indexFile.file.path) ? index : void 0,
136
128
  children,
137
129
  $id: folder.file.path,
138
130
  $ref: !ctx.options.noRef ? {
@@ -159,7 +151,7 @@ function build(ctx) {
159
151
  const root = ctx.storage.root();
160
152
  const folder = buildFolderNode(root, true, ctx);
161
153
  return {
162
- $id: "root",
154
+ $id: ctx.locale ? ctx.locale : "root",
163
155
  name: folder.name,
164
156
  children: folder.children
165
157
  };
@@ -360,30 +352,33 @@ function dotParser(path) {
360
352
  function indexPages(storages, getUrl, i18n) {
361
353
  const defaultLanguage = i18n?.defaultLanguage ?? "";
362
354
  const map = /* @__PURE__ */ new Map();
363
- const pathToFile = /* @__PURE__ */ new Map();
355
+ const fileMapped = /* @__PURE__ */ new WeakMap();
364
356
  for (const item of storages[defaultLanguage].list()) {
365
- if (item.format === "meta")
366
- pathToFile.set(item.file.path, fileToMeta(item));
357
+ if (item.format === "meta") {
358
+ fileMapped.set(item, fileToMeta(item));
359
+ }
367
360
  if (item.format === "page") {
368
361
  const page = fileToPage(item, getUrl, defaultLanguage);
369
- pathToFile.set(item.file.path, page);
362
+ fileMapped.set(item, page);
370
363
  map.set(`${defaultLanguage}.${page.slugs.join("/")}`, page);
371
364
  if (!i18n) continue;
372
365
  const path = joinPath(item.file.dirname, item.file.name);
373
366
  for (const lang of i18n.languages) {
374
367
  if (lang === defaultLanguage) continue;
375
- const localizedPage = fileToPage(
376
- storages[lang].read(path, "page") ?? item,
377
- getUrl,
378
- lang
379
- );
368
+ const localizedItem = storages[lang].read(path, "page");
369
+ const localizedPage = fileToPage(localizedItem ?? item, getUrl, lang);
370
+ if (localizedItem) {
371
+ fileMapped.set(localizedItem, localizedPage);
372
+ }
380
373
  map.set(`${lang}.${localizedPage.slugs.join("/")}`, localizedPage);
381
374
  }
382
375
  }
383
376
  }
384
377
  return {
385
378
  pages: map,
386
- pathToFile
379
+ getResultFromFile(file) {
380
+ return fileMapped.get(file);
381
+ }
387
382
  };
388
383
  }
389
384
  function createGetUrl(baseUrl, i18n) {
@@ -500,9 +495,17 @@ function createOutput(options) {
500
495
  getPage(slugs = [], language = options.i18n?.defaultLanguage ?? "") {
501
496
  return walker.pages.get(`${language}.${slugs.join("/")}`);
502
497
  },
503
- getNodeMeta(node) {
504
- if (!node.$ref?.metaFile) return;
505
- return walker.pathToFile.get(node.$ref.metaFile);
498
+ getNodeMeta(node, language = options.i18n?.defaultLanguage ?? "") {
499
+ const ref = node.$ref?.metaFile;
500
+ if (!ref) return;
501
+ const file = storages[language].list().find((v) => v.format === "meta" && v.file.path === ref);
502
+ if (file) return walker.getResultFromFile(file);
503
+ },
504
+ getNodePage(node, language = options.i18n?.defaultLanguage ?? "") {
505
+ const ref = node.$ref?.file;
506
+ if (!ref) return;
507
+ const file = storages[language].list().find((v) => v.format === "page" && v.file.path === ref);
508
+ if (file) return walker.getResultFromFile(file);
506
509
  },
507
510
  getPageTree(locale) {
508
511
  if (options.i18n) {
@@ -510,11 +513,6 @@ function createOutput(options) {
510
513
  }
511
514
  return this.pageTree;
512
515
  },
513
- getNodePage(node) {
514
- const ref = node.$ref?.file ?? node.$id;
515
- if (!ref) return;
516
- return walker.pathToFile.get(ref);
517
- },
518
516
  // @ts-expect-error -- ignore this
519
517
  generateParams(slug, lang) {
520
518
  if (options.i18n) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "15.2.5",
3
+ "version": "15.2.7",
4
4
  "description": "The library for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -79,8 +79,8 @@
79
79
  "dependencies": {
80
80
  "@formatjs/intl-localematcher": "^0.6.1",
81
81
  "@orama/orama": "^3.1.4",
82
- "@shikijs/rehype": "^3.2.1",
83
- "@shikijs/transformers": "^3.2.1",
82
+ "@shikijs/rehype": "^3.2.2",
83
+ "@shikijs/transformers": "^3.2.2",
84
84
  "github-slugger": "^2.0.0",
85
85
  "hast-util-to-estree": "^3.1.3",
86
86
  "hast-util-to-jsx-runtime": "^2.3.6",
@@ -90,25 +90,25 @@
90
90
  "remark": "^15.0.0",
91
91
  "remark-gfm": "^4.0.1",
92
92
  "scroll-into-view-if-needed": "^3.1.0",
93
- "shiki": "^3.2.1",
93
+ "shiki": "^3.2.2",
94
94
  "unist-util-visit": "^5.0.0"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@algolia/client-search": "4.24.0",
98
98
  "@mdx-js/mdx": "^3.1.0",
99
99
  "@oramacloud/client": "^2.1.4",
100
- "@tanstack/react-router": "^1.114.34",
100
+ "@tanstack/react-router": "^1.115.2",
101
101
  "@types/estree-jsx": "^1.0.5",
102
102
  "@types/hast": "^3.0.4",
103
103
  "@types/mdast": "^4.0.3",
104
104
  "@types/negotiator": "^0.6.3",
105
105
  "@types/node": "22.14.0",
106
106
  "@types/react": "^19.1.0",
107
- "@types/react-dom": "^19.1.1",
107
+ "@types/react-dom": "^19.1.2",
108
108
  "algoliasearch": "4.24.0",
109
109
  "mdast-util-mdx-jsx": "^3.2.0",
110
110
  "mdast-util-mdxjs-esm": "^2.0.1",
111
- "next": "^15.2.4",
111
+ "next": "^15.3.0",
112
112
  "react-router": "^7.5.0",
113
113
  "remark-mdx": "^3.1.0",
114
114
  "remark-rehype": "^11.1.2",