Core: Apply hideLocale to Source getPage APIs

This commit is contained in:
fuma-nama
2024-09-19 18:04:30 +08:00
parent 61a3d14322
commit 8ef00dc6b8
8 changed files with 55 additions and 48 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@fumadocs/content-collections': patch
---
Improve types
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-core': patch
---
Apply `hideLocale` to Source `getPage` APIs
@@ -19,7 +19,6 @@ import {
type StructuredData,
} from 'fumadocs-core/mdx-plugins';
import type { z as Zod } from 'zod';
import { type TableOfContents } from 'fumadocs-core/server';
import {
resolvePlugin,
resolvePlugins,
@@ -42,6 +41,9 @@ export interface TransformOptions
rehypeCodeOptions?: RehypeCodeOptions | boolean;
}
/**
* The default TOC types support `ReactNode`, which isn't serializable
*/
export type SerializableTOC = {
title: string;
url: string;
@@ -72,7 +74,7 @@ export async function transformMDX<D extends BaseDoc>(
): Promise<
D & {
body: string;
toc: InterfaceToObject<TableOfContents>;
toc: SerializableTOC;
/**
* `StructuredData` for search indexes
*/
+1 -7
View File
@@ -25,19 +25,13 @@ export interface Separator {
}
export interface Folder {
/**
* Optional id to be attached to folders
*
* @deprecated use `$ref`
*/
id?: string;
$ref?: {
metaFile?: string;
};
type: 'folder';
name: ReactNode;
description?: ReactNode;
root?: boolean;
defaultOpen?: boolean;
index?: Item;
+35 -26
View File
@@ -169,10 +169,22 @@ function indexPages(
};
}
export function createGetUrl(baseUrl: string): UrlFn {
export function createGetUrl(baseUrl: string, i18n?: I18nConfig): UrlFn {
return (slugs, locale) => {
const paths = locale
? [locale, ...baseUrl.split('/'), ...slugs]
const hideLocale = i18n?.hideLocale ?? 'never';
let urlLocale: string | undefined;
if (hideLocale === 'never') {
urlLocale = locale;
} else if (
hideLocale === 'default-locale' &&
locale !== i18n?.defaultLanguage
) {
urlLocale = locale;
}
const paths = urlLocale
? [urlLocale, ...baseUrl.split('/'), ...slugs]
: [...baseUrl.split('/'), ...slugs];
return `/${paths.filter((v) => v.length > 0).join('/')}`;
@@ -201,47 +213,44 @@ export function loader<Options extends LoaderOptions>(
return createOutput(options) as ReturnType<typeof loader<Options>>;
}
function createOutput({
source,
icon: resolveIcon,
rootDir = '',
transformers,
baseUrl = '/',
slugs: slugsFn = getSlugs,
url: getUrl = createGetUrl(baseUrl),
pageTree: pageTreeOptions = {},
i18n,
}: LoaderOptions): LoaderOutput<LoaderConfig> {
function createOutput(options: LoaderOptions): LoaderOutput<LoaderConfig> {
const {
source,
rootDir = '',
baseUrl = '/',
slugs: slugsFn = getSlugs,
url: getUrl = createGetUrl(baseUrl, options.i18n),
} = options;
const storage = loadFiles(
typeof source.files === 'function' ? source.files(rootDir) : source.files,
{
transformers,
transformers: options.transformers,
rootDir,
getSlugs: slugsFn,
},
);
const walker = indexPages(storage, getUrl, i18n?.languages);
const walker = indexPages(storage, getUrl, options.i18n?.languages);
const builder = createPageTreeBuilder();
const pageTree =
i18n === undefined
options.i18n === undefined
? builder.build({
storage,
resolveIcon,
resolveIcon: options.icon,
getUrl,
...pageTreeOptions,
...options.pageTree,
})
: builder.buildI18n({
storage,
resolveIcon,
resolveIcon: options.icon,
getUrl,
i18n,
...pageTreeOptions,
i18n: options.i18n,
...options.pageTree,
});
return {
_i18n: i18n,
_i18n: options.i18n,
pageTree: pageTree as LoaderOutput<LoaderConfig>['pageTree'],
getPages(language = i18n?.defaultLanguage ?? '') {
getPages(language = options.i18n?.defaultLanguage ?? '') {
return Array.from(walker.i18n.get(language)?.values() ?? []);
},
getLanguages() {
@@ -258,7 +267,7 @@ function createOutput({
return list;
},
getPage(slugs = [], language = i18n?.defaultLanguage ?? '') {
getPage(slugs = [], language = options.i18n?.defaultLanguage ?? '') {
return walker.i18n.get(language)?.get(slugs.join('/'));
},
getNodeMeta(node) {
@@ -273,7 +282,7 @@ function createOutput({
},
// @ts-expect-error -- ignore this
generateParams(slug, lang) {
if (i18n) {
if (options.i18n) {
return this.getLanguages().flatMap((entry) =>
entry.pages.map((page) => ({
[slug ?? 'slug']: page.slugs,
+2 -12
View File
@@ -209,6 +209,7 @@ function buildFolderNode(
icon: ctx.options.resolveIcon?.(metadata?.icon) ?? index?.icon,
root: metadata?.root,
defaultOpen: metadata?.defaultOpen,
description: metadata?.description,
index,
children,
$ref: !ctx.options.noRef
@@ -227,25 +228,14 @@ function buildFileNode(
file: PageFile,
ctx: PageTreeBuilderContext,
): PageTree.Item {
let urlLocale: string | undefined;
const localized =
findLocalizedFile(file.file.flattenedPath, 'page', ctx) ?? file;
const hideLocale = ctx.i18n?.hideLocale ?? 'never';
if (hideLocale === 'never') {
urlLocale = ctx.lang;
} else if (
hideLocale === 'default-locale' &&
ctx.lang !== ctx.i18n?.defaultLanguage
) {
urlLocale = ctx.lang;
}
const item: PageTree.Item = {
type: 'page',
name: localized.data.data.title,
icon: ctx.options.resolveIcon?.(localized.data.data.icon),
url: ctx.options.getUrl(localized.data.slugs, urlLocale),
url: ctx.options.getUrl(localized.data.slugs, ctx.lang),
$ref: !ctx.options.noRef
? {
file: localized.file.path,
+2
View File
@@ -6,6 +6,8 @@ export interface MetaData {
root?: boolean | undefined;
pages?: string[] | undefined;
defaultOpen?: boolean | undefined;
description?: string | undefined;
}
export interface PageData {
+1 -1
View File
@@ -403,6 +403,6 @@ test('Internationalized Routing: Hide Prefix', () => {
`);
expect(result.getPages().length).toBe(2);
expect(result.getPage(['test'])?.url).toBe('/en/test');
expect(result.getPage(['test'])?.url).toBe('/test');
expect(result.getPage(['test'], 'cn')?.url).toBe('/cn/test');
});