refactor(content-docs): read category metadata files before autogenerating (#6586)

* refactor(content-docs): read category metadata files before autogenerating

* fix tests

* fix Windows...

* warn user when behavior is undetermined

* oops

* fix typo
This commit is contained in:
Joshua Chen 2022-02-03 16:16:19 +08:00 committed by GitHub
parent b03431f139
commit 1ca07f8466
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 120 additions and 128 deletions

View file

@ -12,19 +12,11 @@ import type {
SidebarItemsGenerator,
SidebarItemsGeneratorDoc,
SidebarItemCategoryLink,
SidebarItemCategoryLinkConfig,
} from './types';
import {sortBy, last} from 'lodash';
import {
addTrailingSlash,
posixPath,
findAsyncSequential,
} from '@docusaurus/utils';
import {addTrailingSlash, posixPath} from '@docusaurus/utils';
import logger from '@docusaurus/logger';
import path from 'path';
import fs from 'fs-extra';
import Yaml from 'js-yaml';
import {validateCategoryMetadataFile} from './validation';
import {createDocsByIdIndex, toCategoryIndexMatcherParam} from '../docs';
const BreadcrumbSeparator = '/';
@ -39,20 +31,6 @@ function getLocalDocId(docId: string): string {
export const CategoryMetadataFilenameBase = '_category_';
export const CategoryMetadataFilenamePattern = '_category_.{json,yml,yaml}';
export type CategoryMetadataFile = {
label?: string;
position?: number;
collapsed?: boolean;
collapsible?: boolean;
className?: string;
link?: SidebarItemCategoryLinkConfig | null;
// TODO should we allow "items" here? how would this work? would an
// "autogenerated" type be allowed?
// This mkdocs plugin do something like that: https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin/
// cf comment: https://github.com/facebook/docusaurus/issues/3464#issuecomment-784765199
};
type WithPosition<T> = T & {position?: number};
/**
@ -65,37 +43,6 @@ type Dir = {
[item: string]: Dir | null;
};
// TODO I now believe we should read all the category metadata files ahead of
// time: we may need this metadata to customize docs metadata
// Example use-case being able to disable number prefix parsing at the folder
// level, or customize the default base slug for an intermediate directory
// TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may
// want to read the metadata as yaml on it
// see https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
async function readCategoryMetadataFile(
categoryDirPath: string,
): Promise<CategoryMetadataFile | null> {
async function tryReadFile(filePath: string): Promise<CategoryMetadataFile> {
const contentString = await fs.readFile(filePath, {encoding: 'utf8'});
const unsafeContent = Yaml.load(contentString);
try {
return validateCategoryMetadataFile(unsafeContent);
} catch (e) {
logger.error`The docs sidebar category metadata file path=${filePath} looks invalid!`;
throw e;
}
}
const filePath = await findAsyncSequential(
['.json', '.yml', '.yaml'].map((ext) =>
posixPath(
path.join(categoryDirPath, `${CategoryMetadataFilenameBase}${ext}`),
),
),
fs.pathExists,
);
return filePath ? tryReadFile(filePath) : null;
}
// Comment for this feature: https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
numberPrefixParser,
@ -103,7 +50,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
docs: allDocs,
options,
item: {dirName: autogenDir},
version,
categoriesMetadata,
}) => {
const docsById = createDocsByIdIndex(allDocs);
const findDoc = (docId: string): SidebarItemsGeneratorDoc | undefined =>
@ -199,8 +146,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
fullPath: string,
folderName: string,
): Promise<WithPosition<SidebarItemCategory>> {
const categoryPath = path.join(version.contentPath, autogenDir, fullPath);
const categoryMetadata = await readCategoryMetadataFile(categoryPath);
const categoryMetadata =
categoriesMetadata[posixPath(path.join(autogenDir, fullPath))];
const className = categoryMetadata?.className;
const {filename, numberPrefix} = numberPrefixParser(folderName);
const allItems = await Promise.all(