mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-12 08:37:25 +02:00
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:
parent
d6bdf7e804
commit
e3fd3e74ce
23 changed files with 750 additions and 615 deletions
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue