mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 23:57:22 +02:00
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:
parent
95f911efef
commit
cfae5d0933
105 changed files with 3904 additions and 816 deletions
|
@ -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),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue