Core: fix loader().getNodePage() returning undefined for other locales

This commit is contained in:
Fuma Nama
2025-04-08 18:13:10 +08:00
parent 9ff6dd84f6
commit b07e98c7ff
6 changed files with 61 additions and 25 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-core': patch
---
fix `loader().getNodePage()` returning undefined for other locales
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-ui': patch
---
Deprecate `DocsCategory`, see https://fumadocs.vercel.app/docs/ui/markdown#further-reading-section
@@ -26,8 +26,6 @@ export const source = loader({
});
```
> The output page tree strictly follows [Page Conventions](/docs/headless/page-conventions).
### Base URL
The loader generates a URL for each page, you can override the default base URL.
+6
View File
@@ -11,6 +11,9 @@ export type Node = Item | Separator | Folder;
export interface Item {
$id?: string;
/**
* @internal
*/
$ref?: {
file: string;
};
@@ -34,6 +37,9 @@ export interface Separator {
export interface Folder {
$id?: string;
/**
* @internal
*/
$ref?: {
metaFile?: string;
};
+33 -21
View File
@@ -118,10 +118,12 @@ export interface LoaderOutput<Config extends LoaderConfig> {
getNodePage: (
node: PageTree.Item,
language?: string,
) => Page<Config['source']['pageData']> | undefined;
getNodeMeta: (
node: PageTree.Folder,
language?: string,
) => Meta<Config['source']['metaData']> | undefined;
/**
@@ -144,32 +146,33 @@ function indexPages(
// (locale.slugs -> page)
pages: Map<string, Page>;
pathToFile: Map<string, Page | Meta>;
getResultFromFile: (file: MetaFile | PageFile) => Page | Meta | undefined;
} {
const defaultLanguage = i18n?.defaultLanguage ?? '';
const map = new Map<string, Page>();
const pathToFile = new Map<string, Page | Meta>();
const fileMapped = new WeakMap<object, Page | Meta>();
for (const item of storages[defaultLanguage].list()) {
if (item.format === 'meta')
pathToFile.set(item.file.path, fileToMeta(item));
if (item.format === 'meta') {
fileMapped.set(item, fileToMeta(item));
}
if (item.format === 'page') {
const page = fileToPage(item, getUrl, defaultLanguage);
pathToFile.set(item.file.path, page);
fileMapped.set(item, page);
map.set(`${defaultLanguage}.${page.slugs.join('/')}`, page);
if (!i18n) continue;
const path = joinPath(item.file.dirname, item.file.name);
for (const lang of i18n.languages) {
if (lang === defaultLanguage) continue;
const localizedItem = storages[lang].read(path, 'page');
const localizedPage = fileToPage(localizedItem ?? item, getUrl, lang);
const localizedPage = fileToPage(
storages[lang].read(path, 'page') ?? item,
getUrl,
lang,
);
if (localizedItem) {
fileMapped.set(localizedItem, localizedPage);
}
map.set(`${lang}.${localizedPage.slugs.join('/')}`, localizedPage);
}
}
@@ -177,7 +180,9 @@ function indexPages(
return {
pages: map,
pathToFile,
getResultFromFile(file) {
return fileMapped.get(file);
},
};
}
@@ -332,10 +337,23 @@ function createOutput(options: LoaderOptions): LoaderOutput<LoaderConfig> {
getPage(slugs = [], language = options.i18n?.defaultLanguage ?? '') {
return walker.pages.get(`${language}.${slugs.join('/')}`);
},
getNodeMeta(node) {
if (!node.$ref?.metaFile) return;
getNodeMeta(node, language = options.i18n?.defaultLanguage ?? '') {
const ref = node.$ref?.metaFile;
if (!ref) return;
return walker.pathToFile.get(node.$ref.metaFile) as Meta;
const file = storages[language]
.list()
.find((v) => v.format === 'meta' && v.file.path === ref);
if (file) return walker.getResultFromFile(file) as Meta;
},
getNodePage(node, language = options.i18n?.defaultLanguage ?? '') {
const ref = node.$ref?.file;
if (!ref) return;
const file = storages[language]
.list()
.find((v) => v.format === 'page' && v.file.path === ref);
if (file) return walker.getResultFromFile(file) as Page;
},
getPageTree(locale) {
if (options.i18n) {
@@ -346,12 +364,6 @@ function createOutput(options: LoaderOptions): LoaderOutput<LoaderConfig> {
return this.pageTree;
},
getNodePage(node) {
const ref = node.$ref?.file ?? node.$id;
if (!ref) return;
return walker.pathToFile.get(ref) as Page;
},
// @ts-expect-error -- ignore this
generateParams(slug, lang) {
if (options.i18n) {
+12 -2
View File
@@ -285,6 +285,18 @@ test('Internationalized Routing', () => {
},
}),
);
expect(
result.getNodePage(
result.pageTree['en'].children[0] as PageTree.Item,
'cn',
),
).toEqual(
expect.objectContaining({
data: {
title: 'Hello Chinese',
},
}),
);
expect(removeUndefined(result.pageTree['en'], true), 'Page Tree')
.toMatchInlineSnapshot(`
@@ -444,8 +456,6 @@ test('Internationalized Routing', () => {
},
]
`);
expect(result.getPage(['test'])?.url).toBe('/en/test');
expect(result.getPage(['test'], 'cn')?.url).toBe('/cn/test');
});
test('Internationalized Routing: Hide Prefix', () => {