refactor(content-docs): clean up sidebars logic; validate generator returns (#6596)

* refactor(content-docs): clean up sidebars logic; validate generator returns

* remove another TODO

* fix types

* refactors

* refactor...
This commit is contained in:
Joshua Chen 2022-02-04 09:46:25 +08:00 committed by GitHub
parent d6bdf7e804
commit e3fd3e74ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 750 additions and 615 deletions

View file

@ -8,7 +8,6 @@
import {Joi, URISchema} from '@docusaurus/utils-validation';
import type {
SidebarItemConfig,
SidebarCategoriesShorthand,
SidebarItemBase,
SidebarItemAutogenerated,
SidebarItemDoc,
@ -16,12 +15,13 @@ import type {
SidebarItemLink,
SidebarItemCategoryConfig,
SidebarItemCategoryLink,
SidebarsConfig,
SidebarItemCategoryLinkDoc,
SidebarItemCategoryLinkGeneratedIndex,
NormalizedSidebars,
NormalizedSidebarItem,
NormalizedSidebarItemCategory,
CategoryMetadataFile,
} from './types';
import {isCategoriesShorthand} from './utils';
// NOTE: we don't add any default values during validation on purpose!
// Config types are exposed to users for typechecking and we use the same type
@ -52,7 +52,7 @@ const sidebarItemDocSchema = sidebarItemBaseSchema.append<SidebarItemDoc>({
const sidebarItemHtmlSchema = sidebarItemBaseSchema.append<SidebarItemHtml>({
type: 'html',
value: Joi.string().required(),
defaultStyle: Joi.boolean().default(false),
defaultStyle: Joi.boolean(),
});
const sidebarItemLinkSchema = sidebarItemBaseSchema.append<SidebarItemLink>({
@ -88,14 +88,13 @@ const sidebarItemCategoryLinkSchema = Joi.object<SidebarItemCategoryLink>()
}),
},
{
is: Joi.string().required(),
is: Joi.required(),
then: Joi.forbidden().messages({
'any.unknown': 'Unknown sidebar category link type "{.type}".',
}),
},
],
})
.id('sidebarCategoryLinkSchema');
});
const sidebarItemCategorySchema =
sidebarItemBaseSchema.append<SidebarItemCategoryConfig>({
@ -103,10 +102,11 @@ const sidebarItemCategorySchema =
label: Joi.string()
.required()
.messages({'any.unknown': '"label" must be a string'}),
// TODO: Joi doesn't allow mutual recursion. See https://github.com/sideway/joi/issues/2611
items: Joi.array()
.required()
.messages({'any.unknown': '"items" must be an array'}), // .items(Joi.link('#sidebarItemSchema')),
.messages({'any.unknown': '"items" must be an array'}),
// TODO: Joi doesn't allow mutual recursion. See https://github.com/sideway/joi/issues/2611
// .items(Joi.link('#sidebarItemSchema')),
link: sidebarItemCategoryLinkSchema,
collapsed: Joi.boolean().messages({
'any.unknown': '"collapsed" must be a boolean',
@ -116,56 +116,44 @@ const sidebarItemCategorySchema =
}),
});
const sidebarItemSchema: Joi.Schema<SidebarItemConfig> = Joi.object()
.when('.type', {
switch: [
{is: 'link', then: sidebarItemLinkSchema},
{
is: Joi.string().valid('doc', 'ref').required(),
then: sidebarItemDocSchema,
},
{is: 'html', then: sidebarItemHtmlSchema},
{is: 'autogenerated', then: sidebarItemAutogeneratedSchema},
{is: 'category', then: sidebarItemCategorySchema},
{
is: Joi.any().required(),
then: Joi.forbidden().messages({
'any.unknown': 'Unknown sidebar item type "{.type}".',
}),
},
],
})
.id('sidebarItemSchema');
const sidebarItemSchema = Joi.object<SidebarItemConfig>().when('.type', {
switch: [
{is: 'link', then: sidebarItemLinkSchema},
{
is: Joi.string().valid('doc', 'ref').required(),
then: sidebarItemDocSchema,
},
{is: 'html', then: sidebarItemHtmlSchema},
{is: 'autogenerated', then: sidebarItemAutogeneratedSchema},
{is: 'category', then: sidebarItemCategorySchema},
{
is: Joi.any().required(),
then: Joi.forbidden().messages({
'any.unknown': 'Unknown sidebar item type "{.type}".',
}),
},
],
});
// .id('sidebarItemSchema');
function validateSidebarItem(item: unknown): asserts item is SidebarItemConfig {
if (typeof item === 'string') {
return;
}
function validateSidebarItem(
item: unknown,
): asserts item is NormalizedSidebarItem {
// TODO: remove once with proper Joi support
// Because we can't use Joi to validate nested items (see above), we do it
// manually
if (isCategoriesShorthand(item as SidebarItemConfig)) {
Object.values(item as SidebarCategoriesShorthand).forEach((category) =>
category.forEach(validateSidebarItem),
);
} else {
Joi.assert(item, sidebarItemSchema);
Joi.assert(item, sidebarItemSchema);
if ((item as SidebarItemCategoryConfig).type === 'category') {
(item as SidebarItemCategoryConfig).items.forEach(validateSidebarItem);
}
if ((item as NormalizedSidebarItemCategory).type === 'category') {
(item as NormalizedSidebarItemCategory).items.forEach(validateSidebarItem);
}
}
export function validateSidebars(
sidebars: unknown,
): asserts sidebars is SidebarsConfig {
Object.values(sidebars as SidebarsConfig).forEach((sidebar) => {
if (Array.isArray(sidebar)) {
sidebar.forEach(validateSidebarItem);
} else {
validateSidebarItem(sidebar);
}
sidebars: Record<string, unknown>,
): asserts sidebars is NormalizedSidebars {
Object.values(sidebars as NormalizedSidebars).forEach((sidebar) => {
sidebar.forEach(validateSidebarItem);
});
}