Core: Support folder group on Page Tree Builder

This commit is contained in:
fuma-nama
2024-07-17 19:01:58 +08:00
parent c22371a7b2
commit 2ffd5ea287
21 changed files with 84 additions and 29 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-core': patch
---
Support folder group on Page Tree Builder
+1 -7
View File
@@ -37,10 +37,4 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
apps/docs/content/docs/ui/museum/events.mdx
apps/docs/content/docs/ui/museum/operations.mdx
apps/docs/content/docs/ui/museum/tickets.mdx
apps/docs/content/docs/ui/typescript.mdx
next-env.d.ts
+5 -1
View File
@@ -1 +1,5 @@
out
out
content/docs/ui/museum/events.mdx
content/docs/ui/museum/operations.mdx
content/docs/ui/museum/tickets.mdx
content/docs/ui/(integrations)/typescript.mdx
+1 -3
View File
@@ -14,8 +14,6 @@ interface Param {
slug: string[];
}
export const dynamicParams = false;
export default function Page({
params,
}: {
@@ -64,7 +62,6 @@ export default function Page({
</p>
<DocsBody>
{preview && preview in Preview ? Preview[preview] : null}
{page.data.index ? <Category page={page} /> : null}
<page.data.exports.default
components={{
HeadlessOnly:
@@ -77,6 +74,7 @@ export default function Page({
: () => undefined,
}}
/>
{page.data.index ? <Category page={page} /> : null}
</DocsBody>
</DocsPage>
);
@@ -0,0 +1,8 @@
---
title: Blocks
description: Introduction to blocks
index: true
---
Blocks are essential elements of docs, including layouts and navigation elements.
They provide basic functionalities to browse the docs, you can see their usage and customisable options.
@@ -0,0 +1,5 @@
---
title: Components
description: Additional components to improve your docs
index: true
---
+1 -1
View File
@@ -100,7 +100,7 @@ Some common questions you may encounter.
they are customisable with exposed props like `style` and `className`.
Blocks are essential elements of docs, providing navigation and basic functionality.
We provided many options to customise them, see the **Blocks** section of the docs.
We provided many options to customise them, see [Blocks](/docs/ui/blocks).
Although the docs didn't explicitly mention, you can always style the elements with CSS selectors.
+1 -1
View File
@@ -72,7 +72,7 @@ see [MDX Syntax](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) to learn more.
### Cards
A [`Card`](/docs/ui/components/mdx/card) component is included by default. Similar to links, but you can display more information (e.g. icons).
A [`Card`](/docs/ui/mdx/card) component is included by default. Similar to links, but you can display more information (e.g. icons).
```mdx
<Cards>
@@ -1,11 +1,12 @@
---
title: MDX
description: Default MDX Components
index: true
---
## Usage
The default components include Card, Code Blocks and Headings.
The default MDX components include Card, Code Blocks and Headings.
```ts
import defaultComponents from 'fumadocs-ui/mdx';
+6 -10
View File
@@ -10,17 +10,13 @@
"markdown",
"page-conventions",
"navigation",
"---Components---",
"...components",
"---Blocks---",
"...blocks",
"---Integrations---",
"math",
"typescript",
"twoslash",
"openapi",
"museum",
"---References---",
"components",
"mdx",
"blocks",
"(integrations)",
"---Others---",
"museum",
"[Vercel](https://vercel.com)"
]
}
+1
View File
@@ -25,6 +25,7 @@ const config = {
ignoreDuringBuilds: true,
},
images: {
unoptimized: true,
remotePatterns: [
{
protocol: 'https',
+2 -1
View File
@@ -141,7 +141,8 @@ export function createGetUrl(baseUrl: string): UrlFn {
export function getSlugs(info: FileInfo): string[] {
const result = [...info.dirname.split('/'), info.name].filter(
(v) => v.length > 0,
// filter empty folder names and file groups like (group_name)
(v) => v.length > 0 && !/^\(.+\)$/.test(v),
);
return result[result.length - 1] === 'index' ? result.slice(0, -1) : result;
+19 -3
View File
@@ -56,6 +56,7 @@ export interface PageTreeBuilder {
) => Record<string, PageTree.Root>;
}
const group = /^\((?<name>.+)\)$/;
const link = /^\[(?<text>.+)]\((?<url>.+)\)$/;
const separator = /^---(?<name>.*?)---$/;
const rest = '...';
@@ -204,7 +205,7 @@ function buildFolderNode(
const node: PageTree.Folder = {
type: 'folder',
name: metadata?.title ?? index?.name ?? pathToName(folder.file.name),
name: metadata?.title ?? index?.name ?? pathToName(folder.file.name, true),
icon: ctx.options.resolveIcon?.(metadata?.icon),
root: metadata?.root,
defaultOpen: metadata?.defaultOpen,
@@ -282,8 +283,23 @@ function findLocalizedFile(
return ctx.storage.read(`${path}.${ctx.lang}`, format);
}
function pathToName(path: string): string {
return path.slice(0, 1).toUpperCase() + path.slice(1);
/**
* Get item name from file name
*
* @param name - file name
* @param resolveGroup - resolve folder groups like (group_name)
*/
function pathToName(name: string, resolveGroup = false): string {
const resolved = resolveGroup ? (group.exec(name)?.[1] ?? name) : name;
const result = [];
for (const c of resolved) {
if (result.length === 0) result.push(c.toLocaleUpperCase());
else if (c === '-') result.push(' ');
else result.push(c);
}
return result.join('');
}
function removeUndefined<T extends object>(value: T): T {
+27 -1
View File
@@ -8,6 +8,10 @@ test('Get Slugs', () => {
'to',
'file',
]);
expect(getSlugs(parseFilePath('path/(group)/file'))).toStrictEqual([
'path',
'file',
]);
expect(getSlugs(parseFilePath(''))).toStrictEqual([]);
});
@@ -96,6 +100,13 @@ test('Page Tree: Nested Directories', async () => {
title: 'Nested Page',
},
},
{
type: 'page',
path: '/(nested)/hello.mdx',
data: {
title: 'Route Group Page',
},
},
],
},
});
@@ -103,6 +114,17 @@ test('Page Tree: Nested Directories', async () => {
expect(result.pageTree, 'Page Tree').toMatchInlineSnapshot(`
{
"children": [
{
"children": [
{
"name": "Route Group Page",
"type": "page",
"url": "/hello",
},
],
"name": "Nested",
"type": "folder",
},
{
"name": "Hello",
"type": "page",
@@ -129,8 +151,12 @@ test('Page Tree: Nested Directories', async () => {
"name": "",
}
`);
expect(result.getPages().length).toBe(3);
expect(result.getPages().length).toBe(4);
// page in folder
expect(result.getPage(['nested', 'test'])).toBeDefined();
// page in folder group
expect(result.getPage(['hello'])).toBeDefined();
});
test('Page Tree: Internationalized Routing', () => {