feat(content-docs): sidebar category linking to document or auto-generated index page (#5830)

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
Co-authored-by: Armano <armano2@users.noreply.github.com>
Co-authored-by: Alexey Pyltsyn <lex61rus@gmail.com>
This commit is contained in:
Sébastien Lorber 2021-12-03 14:44:59 +01:00 committed by GitHub
parent 95f911efef
commit cfae5d0933
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
105 changed files with 3904 additions and 816 deletions

View file

@ -21,18 +21,24 @@ import type {
SidebarItemsGeneratorOption,
SidebarItemsGeneratorDoc,
SidebarItemsGeneratorVersion,
NormalizedSidebarItemCategory,
SidebarItemCategory,
SidebarItemAutogenerated,
} from './types';
import {transformSidebarItems} from './utils';
import {DefaultSidebarItemsGenerator} from './generator';
import {mapValues, memoize, pick} from 'lodash';
import combinePromises from 'combine-promises';
import {normalizeItem} from './normalization';
import {Slugger} from '@docusaurus/utils';
export type SidebarProcessorProps = {
export type SidebarProcessorParams = {
sidebarItemsGenerator: SidebarItemsGeneratorOption;
numberPrefixParser: NumberPrefixParser;
docs: DocMetadataBase[];
version: VersionMetadata;
options: SidebarOptions;
categoryLabelSlugger: Slugger;
sidebarOptions: SidebarOptions;
};
function toSidebarItemsGeneratorDoc(
@ -40,6 +46,7 @@ function toSidebarItemsGeneratorDoc(
): SidebarItemsGeneratorDoc {
return pick(doc, [
'id',
'unversionedId',
'frontMatter',
'source',
'sourceDirName',
@ -56,48 +63,71 @@ function toSidebarItemsGeneratorVersion(
// Handle the generation of autogenerated sidebar items and other post-processing checks
async function processSidebar(
unprocessedSidebar: NormalizedSidebar,
{
params: SidebarProcessorParams,
): Promise<Sidebar> {
const {
sidebarItemsGenerator,
numberPrefixParser,
docs,
version,
options,
}: SidebarProcessorProps,
): Promise<Sidebar> {
sidebarOptions,
} = params;
// Just a minor lazy transformation optimization
const getSidebarItemsGeneratorDocsAndVersion = memoize(() => ({
docs: docs.map(toSidebarItemsGeneratorDoc),
version: toSidebarItemsGeneratorVersion(version),
}));
async function handleAutoGeneratedItems(
async function processCategoryItem(
item: NormalizedSidebarItemCategory,
): Promise<SidebarItemCategory> {
return {
...item,
items: (await Promise.all(item.items.map(processItem))).flat(),
};
}
async function processAutoGeneratedItem(
item: SidebarItemAutogenerated,
): Promise<SidebarItem[]> {
// TODO the returned type can't be trusted in practice (generator can be user-provided)
const generatedItems = await sidebarItemsGenerator({
item,
numberPrefixParser,
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
...getSidebarItemsGeneratorDocsAndVersion(),
options: sidebarOptions,
});
// TODO validate generated items: user can generate bad items
const generatedItemsNormalized = generatedItems.flatMap((generatedItem) =>
normalizeItem(generatedItem, {...params, ...sidebarOptions}),
);
// Process again... weird but sidebar item generated might generate some auto-generated items?
return processItems(generatedItemsNormalized);
}
async function processItem(
item: NormalizedSidebarItem,
): Promise<SidebarItem[]> {
if (item.type === 'category') {
return [
{
...item,
items: (
await Promise.all(item.items.map(handleAutoGeneratedItems))
).flat(),
},
];
return [await processCategoryItem(item)];
}
if (item.type === 'autogenerated') {
return sidebarItemsGenerator({
item,
numberPrefixParser,
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
...getSidebarItemsGeneratorDocsAndVersion(),
options,
});
return processAutoGeneratedItem(item);
}
return [item];
}
const processedSidebar = (
await Promise.all(unprocessedSidebar.map(handleAutoGeneratedItems))
).flat();
async function processItems(
items: NormalizedSidebarItem[],
): Promise<SidebarItem[]> {
return (await Promise.all(items.map(processItem))).flat();
}
const processedSidebar = await processItems(unprocessedSidebar);
const fixSidebarItemInconsistencies = (item: SidebarItem): SidebarItem => {
// A non-collapsible category can't be collapsed!
@ -114,11 +144,11 @@ async function processSidebar(
export async function processSidebars(
unprocessedSidebars: NormalizedSidebars,
props: SidebarProcessorProps,
params: SidebarProcessorParams,
): Promise<Sidebars> {
return combinePromises(
mapValues(unprocessedSidebars, (unprocessedSidebar) =>
processSidebar(unprocessedSidebar, props),
processSidebar(unprocessedSidebar, params),
),
);
}