feat(content-docs): autogenerate category with linked doc metadata as fallback (#6859)

This commit is contained in:
Joshua Chen 2022-03-25 22:23:11 +08:00 committed by GitHub
parent f1bcdbff63
commit b5ceead3b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 62 additions and 23 deletions

View file

@ -1407,6 +1407,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 0, "sidebarPosition": 0,
"source": "@site/docs/3-API/01_Core APIs/0 --- Client API.md", "source": "@site/docs/3-API/01_Core APIs/0 --- Client API.md",
"sourceDirName": "3-API/01_Core APIs", "sourceDirName": "3-API/01_Core APIs",
"title": "Client API",
"unversionedId": "API/Core APIs/Client API", "unversionedId": "API/Core APIs/Client API",
}, },
{ {
@ -1415,6 +1416,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 1, "sidebarPosition": 1,
"source": "@site/docs/3-API/01_Core APIs/1 --- Server API.md", "source": "@site/docs/3-API/01_Core APIs/1 --- Server API.md",
"sourceDirName": "3-API/01_Core APIs", "sourceDirName": "3-API/01_Core APIs",
"title": "Server API",
"unversionedId": "API/Core APIs/Server API", "unversionedId": "API/Core APIs/Server API",
}, },
{ {
@ -1423,6 +1425,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 0, "sidebarPosition": 0,
"source": "@site/docs/3-API/02_Extension APIs/0. Plugin API.md", "source": "@site/docs/3-API/02_Extension APIs/0. Plugin API.md",
"sourceDirName": "3-API/02_Extension APIs", "sourceDirName": "3-API/02_Extension APIs",
"title": "Plugin API",
"unversionedId": "API/Extension APIs/Plugin API", "unversionedId": "API/Extension APIs/Plugin API",
}, },
{ {
@ -1431,6 +1434,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 1, "sidebarPosition": 1,
"source": "@site/docs/3-API/02_Extension APIs/1. Theme API.md", "source": "@site/docs/3-API/02_Extension APIs/1. Theme API.md",
"sourceDirName": "3-API/02_Extension APIs", "sourceDirName": "3-API/02_Extension APIs",
"title": "Theme API",
"unversionedId": "API/Extension APIs/Theme API", "unversionedId": "API/Extension APIs/Theme API",
}, },
{ {
@ -1439,6 +1443,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 3, "sidebarPosition": 3,
"source": "@site/docs/3-API/03_api-end.md", "source": "@site/docs/3-API/03_api-end.md",
"sourceDirName": "3-API", "sourceDirName": "3-API",
"title": "API End",
"unversionedId": "API/api-end", "unversionedId": "API/api-end",
}, },
{ {
@ -1447,6 +1452,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 0, "sidebarPosition": 0,
"source": "@site/docs/3-API/00_api-overview.md", "source": "@site/docs/3-API/00_api-overview.md",
"sourceDirName": "3-API", "sourceDirName": "3-API",
"title": "API Overview",
"unversionedId": "API/api-overview", "unversionedId": "API/api-overview",
}, },
{ {
@ -1458,6 +1464,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 1, "sidebarPosition": 1,
"source": "@site/docs/Guides/z-guide1.md", "source": "@site/docs/Guides/z-guide1.md",
"sourceDirName": "Guides", "sourceDirName": "Guides",
"title": "Guide 1",
"unversionedId": "Guides/guide1", "unversionedId": "Guides/guide1",
}, },
{ {
@ -1468,6 +1475,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 2, "sidebarPosition": 2,
"source": "@site/docs/Guides/02-guide2.md", "source": "@site/docs/Guides/02-guide2.md",
"sourceDirName": "Guides", "sourceDirName": "Guides",
"title": "Guide 2",
"unversionedId": "Guides/guide2", "unversionedId": "Guides/guide2",
}, },
{ {
@ -1479,6 +1487,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 2.5, "sidebarPosition": 2.5,
"source": "@site/docs/Guides/0-guide2.5.md", "source": "@site/docs/Guides/0-guide2.5.md",
"sourceDirName": "Guides", "sourceDirName": "Guides",
"title": "Guide 2.5",
"unversionedId": "Guides/guide2.5", "unversionedId": "Guides/guide2.5",
}, },
{ {
@ -1490,6 +1499,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 3, "sidebarPosition": 3,
"source": "@site/docs/Guides/guide3.md", "source": "@site/docs/Guides/guide3.md",
"sourceDirName": "Guides", "sourceDirName": "Guides",
"title": "Guide 3",
"unversionedId": "Guides/guide3", "unversionedId": "Guides/guide3",
}, },
{ {
@ -1500,6 +1510,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": undefined, "sidebarPosition": undefined,
"source": "@site/docs/Guides/a-guide4.md", "source": "@site/docs/Guides/a-guide4.md",
"sourceDirName": "Guides", "sourceDirName": "Guides",
"title": "Guide 4",
"unversionedId": "Guides/guide4", "unversionedId": "Guides/guide4",
}, },
{ {
@ -1510,6 +1521,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": undefined, "sidebarPosition": undefined,
"source": "@site/docs/Guides/b-guide5.md", "source": "@site/docs/Guides/b-guide5.md",
"sourceDirName": "Guides", "sourceDirName": "Guides",
"title": "Guide 5",
"unversionedId": "Guides/guide5", "unversionedId": "Guides/guide5",
}, },
{ {
@ -1518,6 +1530,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 0, "sidebarPosition": 0,
"source": "@site/docs/0-getting-started.md", "source": "@site/docs/0-getting-started.md",
"sourceDirName": ".", "sourceDirName": ".",
"title": "Getting Started",
"unversionedId": "getting-started", "unversionedId": "getting-started",
}, },
{ {
@ -1526,6 +1539,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"sidebarPosition": 1, "sidebarPosition": 1,
"source": "@site/docs/1-installation.md", "source": "@site/docs/1-installation.md",
"sourceDirName": ".", "sourceDirName": ".",
"title": "Installation",
"unversionedId": "installation", "unversionedId": "installation",
}, },
], ],

View file

@ -116,7 +116,7 @@ exports[`DefaultSidebarItemsGenerator generates subfolder sidebar 1`] = `
"type": "doc", "type": "doc",
}, },
], ],
"label": "subsubsubfolder3 (_category_.json label)", "label": "Subsubsubfolder category label",
"link": { "link": {
"id": "doc1", "id": "doc1",
"type": "doc", "type": "doc",

View file

@ -234,7 +234,7 @@ describe('DefaultSidebarItemsGenerator', () => {
}, },
'subfolder/subsubfolder/subsubsubfolder3': { 'subfolder/subsubfolder/subsubsubfolder3': {
position: 1, position: 1,
label: 'subsubsubfolder3 (_category_.json label)', // This item's label is defined from the index doc instead
link: { link: {
type: 'doc', type: 'doc',
id: 'doc1', // This is a "fully-qualified" ID that can't be found locally id: 'doc1', // This is a "fully-qualified" ID that can't be found locally
@ -246,6 +246,7 @@ describe('DefaultSidebarItemsGenerator', () => {
id: 'doc1', id: 'doc1',
source: 'doc1.md', source: 'doc1.md',
sourceDirName: 'subfolder/subsubfolder', sourceDirName: 'subfolder/subsubfolder',
title: 'Subsubsubfolder category label',
sidebarPosition: undefined, sidebarPosition: undefined,
frontMatter: {}, frontMatter: {},
}, },

View file

@ -158,9 +158,6 @@ Available doc IDs:
): WithPosition<NormalizedSidebarItemCategory> { ): WithPosition<NormalizedSidebarItemCategory> {
const categoryMetadata = const categoryMetadata =
categoriesMetadata[posixPath(path.join(autogenDir, fullPath))]; categoriesMetadata[posixPath(path.join(autogenDir, fullPath))];
const className = categoryMetadata?.className;
const customProps = categoryMetadata?.customProps;
const {filename, numberPrefix} = numberPrefixParser(folderName);
const allItems = Object.entries(dir).map(([key, content]) => const allItems = Object.entries(dir).map(([key, content]) =>
dirToItem(content, key, `${fullPath}/${key}`), dirToItem(content, key, `${fullPath}/${key}`),
); );
@ -184,41 +181,65 @@ Available doc IDs:
}); });
} }
function getCategoryLinkedDocId(): string | undefined { // In addition to the ID, this function also retrieves metadata of the
const link = categoryMetadata?.link; // linked doc that could be used as fallback values for category metadata
if (link !== undefined) { function getCategoryLinkedDocMetadata():
if (link && link.type === 'doc') { | {
return findDocByLocalId(link.id)?.id || getDoc(link.id).id; id: string;
position?: number;
label?: string;
customProps?: {[key: string]: unknown};
className?: string;
} }
| undefined {
const link = categoryMetadata?.link;
if (link !== undefined && link?.type !== 'doc') {
// If a link is explicitly specified, we won't apply conventions // If a link is explicitly specified, we won't apply conventions
return undefined; return undefined;
} }
// Apply default convention to pick index.md, README.md or const id = link
// <categoryName>.md as the category doc ? findDocByLocalId(link.id)?.id ?? getDoc(link.id).id
return findConventionalCategoryDocLink()?.id; : findConventionalCategoryDocLink()?.id;
if (!id) {
return undefined;
}
const doc = getDoc(id);
return {
id,
position: doc.sidebarPosition,
label: doc.frontMatter.sidebar_label ?? doc.title,
customProps: doc.frontMatter.sidebar_custom_props,
className: doc.frontMatter.sidebar_class_name,
};
} }
const categoryLinkedDoc = getCategoryLinkedDocMetadata();
const categoryLinkedDocId = getCategoryLinkedDocId();
const link: SidebarItemCategoryLinkConfig | null | undefined = const link: SidebarItemCategoryLinkConfig | null | undefined =
categoryLinkedDocId categoryLinkedDoc
? { ? {
type: 'doc', type: 'doc',
id: categoryLinkedDocId, // We "remap" a potentially "local id" to a "qualified id" id: categoryLinkedDoc.id, // We "remap" a potentially "local id" to a "qualified id"
} }
: categoryMetadata?.link; : categoryMetadata?.link;
// If a doc is linked, remove it from the category subItems // If a doc is linked, remove it from the category subItems
const items = allItems.filter( const items = allItems.filter(
(item) => !(item.type === 'doc' && item.id === categoryLinkedDocId), (item) => !(item.type === 'doc' && item.id === categoryLinkedDoc?.id),
); );
const className =
categoryMetadata?.className ?? categoryLinkedDoc?.className;
const customProps =
categoryMetadata?.customProps ?? categoryLinkedDoc?.customProps;
const {filename, numberPrefix} = numberPrefixParser(folderName);
return { return {
type: 'category', type: 'category',
label: categoryMetadata?.label ?? filename, label: categoryMetadata?.label ?? categoryLinkedDoc?.label ?? filename,
collapsible: categoryMetadata?.collapsible, collapsible: categoryMetadata?.collapsible,
collapsed: categoryMetadata?.collapsed, collapsed: categoryMetadata?.collapsed,
position: categoryMetadata?.position ?? numberPrefix, position:
categoryMetadata?.position ??
categoryLinkedDoc?.position ??
numberPrefix,
source: folderName, source: folderName,
...(customProps !== undefined && {customProps}), ...(customProps !== undefined && {customProps}),
...(className !== undefined && {className}), ...(className !== undefined && {className}),

View file

@ -31,6 +31,7 @@ function toSidebarItemsGeneratorDoc(
return _.pick(doc, [ return _.pick(doc, [
'id', 'id',
'unversionedId', 'unversionedId',
'title',
'frontMatter', 'frontMatter',
'source', 'source',
'sourceDirName', 'sourceDirName',

View file

@ -231,6 +231,7 @@ export type SidebarItemsGeneratorDoc = Pick<
DocMetadataBase, DocMetadataBase,
| 'id' | 'id'
| 'unversionedId' | 'unversionedId'
| 'title'
| 'frontMatter' | 'frontMatter'
| 'source' | 'source'
| 'sourceDirName' | 'sourceDirName'

View file

@ -89,6 +89,7 @@ type SidebarGenerator = (generatorArgs: {
version: {contentPath: string; versionName: string}; // the current version version: {contentPath: string; versionName: string}; // the current version
docs: Array<{ docs: Array<{
id: string; id: string;
title: string;
frontMatter: DocFrontMatter & Record<string, unknown>; frontMatter: DocFrontMatter & Record<string, unknown>;
source: string; source: string;
sourceDirName: string; sourceDirName: string;

View file

@ -323,7 +323,7 @@ sidebar_class_name: green
This is the easy tutorial! This is the easy tutorial!
``` ```
**For categories**: add a `_category_.json` or `_category_.yml` file in the respective folder. You can specify any category metadata and also the `position` metadata. **For categories**: add a `_category_.json` or `_category_.yml` file in the respective folder. You can specify any category metadata and also the `position` metadata. `label`, `className`, `position`, and `customProps` will default to the respective values of the category's linked doc, if there is one.
<Tabs> <Tabs>
<TabItem value="JSON"> <TabItem value="JSON">