mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Core: extend page tree root scope
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-core': patch
|
||||
---
|
||||
|
||||
extend page tree root scope
|
||||
@@ -8,7 +8,14 @@ interface ID {
|
||||
}
|
||||
|
||||
export interface Root extends ID {
|
||||
/**
|
||||
* @internal meta file path
|
||||
*/
|
||||
$ref?: string;
|
||||
|
||||
type?: 'root';
|
||||
name: ReactNode;
|
||||
description?: ReactNode;
|
||||
children: Node[];
|
||||
/**
|
||||
* Another page tree that won't be displayed unless being opened.
|
||||
@@ -20,11 +27,9 @@ export type Node = Item | Separator | Folder;
|
||||
|
||||
export interface Item extends ID {
|
||||
/**
|
||||
* @internal
|
||||
* @internal page file path
|
||||
*/
|
||||
$ref?: {
|
||||
file: string;
|
||||
};
|
||||
$ref?: string;
|
||||
|
||||
type: 'page';
|
||||
name: ReactNode;
|
||||
@@ -48,11 +53,9 @@ export interface Separator extends ID {
|
||||
|
||||
export interface Folder extends ID {
|
||||
/**
|
||||
* @internal
|
||||
* @internal meta file path
|
||||
*/
|
||||
$ref?: {
|
||||
metaFile?: string;
|
||||
};
|
||||
$ref?: string;
|
||||
|
||||
type: 'folder';
|
||||
name: ReactNode;
|
||||
|
||||
@@ -60,7 +60,7 @@ export function getPageTreeRoots(
|
||||
return roots;
|
||||
});
|
||||
|
||||
if (!('type' in pageTree)) result.push(pageTree);
|
||||
if (!pageTree.type || pageTree.type === 'root') result.push(pageTree);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export function findParent(
|
||||
let result: PageTree.Root | PageTree.Folder | undefined;
|
||||
|
||||
visit(from, (node, parent) => {
|
||||
if ('type' in node && node.type === 'page' && node.url === url) {
|
||||
if (node.type === 'page' && node.url === url) {
|
||||
result = parent;
|
||||
return 'break';
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ export interface LoaderOutput<Config extends LoaderConfig> {
|
||||
) => Page<Config['source']['pageData']> | undefined;
|
||||
|
||||
getNodeMeta: (
|
||||
node: PageTree.Folder,
|
||||
node: PageTree.Folder | PageTree.Root,
|
||||
language?: string,
|
||||
) => Meta<Config['source']['metaData']> | undefined;
|
||||
|
||||
@@ -401,13 +401,13 @@ export function loader(
|
||||
return indexer.getPageBySlugs(slugs, language);
|
||||
},
|
||||
getNodeMeta(node, language = i18n?.defaultLanguage) {
|
||||
const ref = node.$ref?.metaFile;
|
||||
const ref = node.$ref;
|
||||
if (!ref) return;
|
||||
|
||||
return indexer.getMeta(ref, language);
|
||||
},
|
||||
getNodePage(node, language = i18n?.defaultLanguage) {
|
||||
const ref = node.$ref?.file;
|
||||
const ref = node.$ref;
|
||||
if (!ref) return;
|
||||
|
||||
return indexer.getPage(ref, language);
|
||||
|
||||
@@ -8,29 +8,38 @@ interface Context {
|
||||
export interface LLMsConfig {
|
||||
TAB?: string;
|
||||
renderName?: (item: PageTree.Node | PageTree.Root, ctx: Context) => string;
|
||||
renderDescription?: (item: PageTree.Item | PageTree.Folder, ctx: Context) => string;
|
||||
renderDescription?: (
|
||||
item: PageTree.Root | PageTree.Item | PageTree.Folder,
|
||||
ctx: Context,
|
||||
) => string;
|
||||
}
|
||||
|
||||
export function llms<C extends LoaderConfig>(loader: LoaderOutput<C>, config: LLMsConfig = {}) {
|
||||
const {
|
||||
TAB = ' ',
|
||||
renderName = (node, ctx): string => {
|
||||
if (typeof node.name === 'string') return node.name;
|
||||
if ('type' in node && node.type === 'page') {
|
||||
if (node.type === 'page') {
|
||||
const page = loader.getNodePage(node, ctx.lang);
|
||||
if (page) return page.data.title ?? '';
|
||||
} else if (node.type === 'separator') {
|
||||
return String(node.name);
|
||||
} else {
|
||||
const meta = loader.getNodeMeta(node, ctx.lang);
|
||||
if (meta) return meta?.data.title ?? '';
|
||||
}
|
||||
|
||||
return String(node.name);
|
||||
return typeof node.name === 'string' ? node.name : '';
|
||||
},
|
||||
renderDescription = (node, ctx): string => {
|
||||
if (typeof node.description === 'string') return node.description;
|
||||
if ('type' in node && node.type === 'page') {
|
||||
if (node.type === 'page') {
|
||||
const page = loader.getNodePage(node, ctx.lang);
|
||||
if (page) return page.data.description ?? '';
|
||||
} else {
|
||||
const meta = loader.getNodeMeta(node, ctx.lang);
|
||||
if (meta) return meta?.data.description ?? '';
|
||||
}
|
||||
|
||||
return String(node.description);
|
||||
return typeof node.description === 'string' ? node.description : '';
|
||||
},
|
||||
} = config;
|
||||
|
||||
@@ -44,6 +53,8 @@ export function llms<C extends LoaderConfig>(loader: LoaderOutput<C>, config: LL
|
||||
const out: string[] = [];
|
||||
const ctx: Context = { lang };
|
||||
out.push(`# ${renderName(pageTree, ctx)}`);
|
||||
const description = renderDescription(pageTree, ctx);
|
||||
if (description) out.push('', `> ${description}`);
|
||||
out.push('');
|
||||
|
||||
function item(name: string, description: string, indent: number) {
|
||||
|
||||
@@ -318,12 +318,7 @@ export class PageTreeBuilder {
|
||||
collapsible: metadata.collapsible,
|
||||
children: [],
|
||||
$id: this.generateId(folderPath),
|
||||
$ref:
|
||||
!this.ctx.noRef && meta
|
||||
? {
|
||||
metaFile: metaPath,
|
||||
}
|
||||
: undefined,
|
||||
$ref: !this.ctx.noRef && meta ? metaPath : undefined,
|
||||
};
|
||||
this.pathToNode.set(folderPath, node);
|
||||
this.unfinished.add(node);
|
||||
@@ -400,11 +395,7 @@ export class PageTreeBuilder {
|
||||
description,
|
||||
icon,
|
||||
url: this.ctx.getUrl(page.slugs, this.ctx.locale),
|
||||
$ref: !this.ctx.noRef
|
||||
? {
|
||||
file: path,
|
||||
}
|
||||
: undefined,
|
||||
$ref: !this.ctx.noRef ? path : undefined,
|
||||
};
|
||||
for (const transformer of this.transformers) {
|
||||
if (!transformer.file) continue;
|
||||
@@ -418,8 +409,11 @@ export class PageTreeBuilder {
|
||||
root(id = 'root', path = ''): PageTree.Root {
|
||||
const folder = this.folder(path);
|
||||
let root: PageTree.Root = {
|
||||
type: 'root',
|
||||
$ref: folder?.$ref,
|
||||
$id: this.generateId(id),
|
||||
name: folder?.name || 'Docs',
|
||||
description: folder?.description,
|
||||
children: folder ? folder.children : [],
|
||||
};
|
||||
|
||||
|
||||
@@ -21,4 +21,5 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
@@ -9,4 +9,5 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
@@ -29,4 +29,5 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs Chinese",
|
||||
"type": "root",
|
||||
},
|
||||
"en": {
|
||||
"$id": "en:root",
|
||||
@@ -48,5 +49,6 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs English",
|
||||
"type": "root",
|
||||
},
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs Chinese",
|
||||
"type": "root",
|
||||
},
|
||||
"en": {
|
||||
"$id": "en:root",
|
||||
@@ -48,5 +49,6 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs English",
|
||||
"type": "root",
|
||||
},
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs Chinese",
|
||||
"type": "root",
|
||||
},
|
||||
"en": {
|
||||
"$id": "en:root",
|
||||
@@ -48,5 +49,6 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs English",
|
||||
"type": "root",
|
||||
},
|
||||
}
|
||||
@@ -77,6 +77,8 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
},
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
@@ -47,4 +47,5 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
@@ -15,4 +15,5 @@
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
@@ -346,6 +346,7 @@ test('Loader: No duplicate pages when referencing subfolder items and folder', (
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
}
|
||||
`);
|
||||
});
|
||||
@@ -423,6 +424,7 @@ test('Loader: Serialize data', async () => {
|
||||
},
|
||||
],
|
||||
"name": "Docs",
|
||||
"type": "root",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
Reference in New Issue
Block a user