docusaurus/packages/docusaurus-utils-validation/src/validationUtils.ts
Joshua Chen 462b1cf2bc
style(v2): reduce number of ESLint warnings (#4993)
* Initial work

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* More fixes

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Update packages/docusaurus-theme-classic/src/theme/ThemedImage/index.tsx

Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>

* Update packages/docusaurus-theme-bootstrap/src/theme/ThemedImage/index.tsx

Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>

* Fix

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Replace versionPathPart with function

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Prefer non-null assertions

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Substitute for-of with forEach

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Fill `catch` block with placeholder comment

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Ignore local require

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Revert global require change

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Tighten eslint disable range

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Make eslint ignore examples and more tolerating to templates

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Use reduce to handle doc items sequentially

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

* Revert "Use reduce to handle doc items sequentially"

This reverts commit c7525d463b.

* Address change requests

Signed-off-by: Josh-Cena <sidachen2003@gmail.com>

Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
2021-06-24 18:12:48 +02:00

153 lines
4.5 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import Joi from './Joi';
import chalk from 'chalk';
import {PluginIdSchema} from './validationSchemas';
// TODO temporary escape hatch for alpha-60: to be removed soon
// Our validation schemas might be buggy at first
// will permit users to bypass validation until we fix all validation errors
// see for example: https://github.com/facebook/docusaurus/pull/3120
// Undocumented on purpose, as we don't want users to keep using it over time
// Maybe we'll make this escape hatch official some day, with a better api?
export const isValidationDisabledEscapeHatch =
process.env.DISABLE_DOCUSAURUS_VALIDATION === 'true';
if (isValidationDisabledEscapeHatch) {
console.error(
chalk.red(
'You should avoid using DISABLE_DOCUSAURUS_VALIDATION escape hatch, this will be removed.',
),
);
}
export const logValidationBugReportHint = (): void => {
console.log(
`\n${chalk.red('A validation error occurred.')}${chalk.cyanBright(
'\nThe validation system was added recently to Docusaurus as an attempt to avoid user configuration errors.' +
'\nWe may have made some mistakes.' +
'\nIf you think your configuration is valid and should keep working, please open a bug report.',
)}\n`,
);
};
export function printWarning(warning?: Joi.ValidationError): void {
if (warning) {
const warningMessages = warning.details
.map(({message}) => message)
.join('\n');
console.log(chalk.yellow(warningMessages));
}
}
export function normalizePluginOptions<T extends {id?: string}>(
schema: Joi.ObjectSchema<T>,
options: Partial<T>,
): T {
// All plugins can be provided an "id" option (multi-instance support)
// we add schema validation automatically
const finalSchema = schema.append({
id: PluginIdSchema,
});
const {error, warning, value} = finalSchema.validate(options, {
convert: false,
});
printWarning(warning);
if (error) {
logValidationBugReportHint();
if (isValidationDisabledEscapeHatch) {
console.error(error);
return options as T;
} else {
throw error;
}
}
return value;
}
export function normalizeThemeConfig<T>(
schema: Joi.ObjectSchema<T>,
themeConfig: Partial<T>,
): T {
// A theme should only validate his "slice" of the full themeConfig,
// not the whole object, so we allow unknown attributes
// otherwise one theme would fail validating the data of another theme
const finalSchema = schema.unknown();
const {error, warning, value} = finalSchema.validate(themeConfig, {
convert: false,
});
printWarning(warning);
if (error) {
logValidationBugReportHint();
if (isValidationDisabledEscapeHatch) {
console.error(error);
return themeConfig as T;
} else {
throw error;
}
}
return value;
}
// Enhance the default Joi.string() type so that it can convert number to strings
// If user use frontmatter "tag: 2021", we shouldn't need to ask the user to write "tag: '2021'"
// Also yaml tries to convert patterns like "2019-01-01" to dates automatically
// see https://github.com/facebook/docusaurus/issues/4642
// see https://github.com/sideway/joi/issues/1442#issuecomment-823997884
const JoiFrontMatterString: Joi.Extension = {
type: 'string',
base: Joi.string(),
// Fix Yaml that tries to auto-convert many things to string out of the box
prepare: (value) => {
if (typeof value === 'number' || value instanceof Date) {
return {value: value.toString()};
}
return {value};
},
};
export const JoiFrontMatter: typeof Joi = Joi.extend(JoiFrontMatterString);
export function validateFrontMatter<T>(
frontMatter: Record<string, unknown>,
schema: Joi.ObjectSchema<T>,
): T {
const {value, error, warning} = schema.validate(frontMatter, {
convert: true,
allowUnknown: true,
abortEarly: false,
});
printWarning(warning);
if (error) {
const frontMatterString = JSON.stringify(frontMatter, null, 2);
const errorDetails = error.details;
const invalidFields = errorDetails.map(({path}) => path).join(', ');
const errorMessages = errorDetails
.map(({message}) => ` - ${message}`)
.join('\n');
logValidationBugReportHint();
console.error(
chalk.red(
`The following frontmatter:\n${chalk.yellow(
frontMatterString,
)}\ncontains invalid values for field(s): ${invalidFields}.\n${errorMessages}\n`,
),
);
throw error;
}
return value;
}