From 3573b5e4a90c5185dec569dd3cccfd8a1e05a6ab Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Wed, 2 Feb 2022 21:45:00 +0800 Subject: [PATCH] fix(content-docs): render category with no subitems as a normal link (#6495) --- .../src/sidebars/__tests__/processor.test.ts | 70 ++++++++++++++++++- .../src/sidebars/processor.ts | 28 ++++++++ .../src/theme/DocSidebarItem/index.tsx | 3 - .../tests/category-links/no-subdoc/index.md | 3 + website/_dogfooding/docs-tests-sidebars.js | 8 ++- .../docs/guides/docs/sidebar/autogenerated.md | 13 ++++ 6 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 website/_dogfooding/_docs tests/tests/category-links/no-subdoc/index.md diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts index 46a016245b..31ea227594 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts @@ -209,6 +209,12 @@ describe('processSidebars', () => { // typing error needing refactor permalink: undefined, }, + items: [ + { + type: 'doc', + id: 'foo', + }, + ], }, ]; @@ -232,11 +238,73 @@ describe('processSidebars', () => { slug: 'generated-cat-index-slug', permalink: '/docs/1.0.0/generated-cat-index-slug', }, - items: [], + items: [ + { + type: 'doc', + id: 'foo', + }, + ], collapsible: true, collapsed: true, }, ], } as Sidebars); }); + + test('transforms category without subitems', async () => { + const sidebarSlice: SidebarItem[] = [ + { + type: 'category', + label: 'Category', + link: { + type: 'generated-index', + permalink: 'generated/permalink', + }, + items: [], + }, + { + type: 'category', + label: 'Category 2', + link: { + type: 'doc', + id: 'doc ID', + }, + items: [], + }, + ]; + + const processedSidebar = await testProcessSidebars( + {sidebar: sidebarSlice}, + {}, + ); + + expect(processedSidebar).toEqual({ + sidebar: [ + { + type: 'link', + label: 'Category', + href: 'generated/permalink', + }, + { + type: 'doc', + label: 'Category 2', + id: 'doc ID', + }, + ], + } as Sidebars); + + await expect(async () => { + await testProcessSidebars({ + sidebar: [ + { + type: 'category', + label: 'Bad category', + items: [], + }, + ], + }); + }).rejects.toThrowErrorMatchingInlineSnapshot( + `"Sidebar category Bad category has neither any subitem nor a link. This makes this item not able to link to anything."`, + ); + }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts index 9336a1a049..f6596d1c09 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts @@ -117,6 +117,34 @@ async function processSidebar( item: NormalizedSidebarItem, ): Promise { if (item.type === 'category') { + // If the current category doesn't have subitems, we render a normal doc link instead. + if (item.items.length === 0) { + if (!item.link) { + throw new Error( + `Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`, + ); + } + switch (item.link.type) { + case 'doc': + return [ + { + type: 'doc', + label: item.label, + id: item.link.id, + }, + ]; + case 'generated-index': + return [ + { + type: 'link', + label: item.label, + href: item.link.permalink, + }, + ]; + default: + throw new Error('Unexpected sidebar category link type'); + } + } return [await processCategoryItem(item)]; } if (item.type === 'autogenerated') { diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx index 28e03c1648..543d526319 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx @@ -39,9 +39,6 @@ export default function DocSidebarItem({ }: Props): JSX.Element | null { switch (item.type) { case 'category': - if (item.items.length === 0) { - return null; - } return ; case 'link': default: diff --git a/website/_dogfooding/_docs tests/tests/category-links/no-subdoc/index.md b/website/_dogfooding/_docs tests/tests/category-links/no-subdoc/index.md new file mode 100644 index 0000000000..1f02e8af26 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/category-links/no-subdoc/index.md @@ -0,0 +1,3 @@ +# No sub-docs + +The only doc of this category is the index page. It should show up as a regular doc link. diff --git a/website/_dogfooding/docs-tests-sidebars.js b/website/_dogfooding/docs-tests-sidebars.js index 7e8a83ea49..8be3194694 100644 --- a/website/_dogfooding/docs-tests-sidebars.js +++ b/website/_dogfooding/docs-tests-sidebars.js @@ -82,7 +82,13 @@ function generateHugeSidebarItems() { function generateRecursive(maxLevel, currentLevel = 0) { if (currentLevel === maxLevel) { - return []; + return [ + { + type: 'link', + href: '/', + label: `Link (level ${currentLevel + 1})`, + }, + ]; } const linkItems = [...Array(linksCount).keys()].map((index) => ({ diff --git a/website/docs/guides/docs/sidebar/autogenerated.md b/website/docs/guides/docs/sidebar/autogenerated.md index 8445482203..5b28a541c8 100644 --- a/website/docs/guides/docs/sidebar/autogenerated.md +++ b/website/docs/guides/docs/sidebar/autogenerated.md @@ -194,6 +194,19 @@ Naming your introductory document `README.md` makes it show up when browsing the ::: +:::tip + +If a folder only has one index page, it will be turned into a link instead of a category. This is useful for **asset collocation**: + +``` +some-doc +├── index.md +├── img1.png +└── img2.png +``` + +::: +
Customizing category index matching