fix(v2): fix too strict markdown frontmatter validation (#4654)

* start work

* use orta.vscode-jest

* node 14

* add some better  infra to validate markdown frontmatter

* better docs frontmatter validation

* fix Yaml / Joi validation issues

* fix Yaml / Joi validation issues

Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
John Reilly 2021-04-21 15:19:55 +01:00 committed by GitHub
parent c04e613ffe
commit e11597aba9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 238 additions and 21 deletions

View file

@ -0,0 +1,64 @@
/**
* 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 {JoiFrontMatter, validateFrontMatter} from '../validationUtils';
describe('validateFrontMatter', () => {
test('should accept good values', () => {
const schema = Joi.object<{test: string}>({
test: Joi.string(),
});
const frontMatter = {
test: 'hello',
};
expect(validateFrontMatter(frontMatter, schema)).toEqual(frontMatter);
});
test('should reject bad values', () => {
const consoleError = jest.spyOn(console, 'error').mockImplementation();
const schema = Joi.object<{test: string}>({
test: Joi.string(),
});
const frontMatter = {
test: true,
};
expect(() =>
validateFrontMatter(frontMatter, schema),
).toThrowErrorMatchingInlineSnapshot(`"\\"test\\" must be a string"`);
expect(consoleError).toHaveBeenCalledWith(
expect.stringContaining('FrontMatter contains invalid values: '),
);
});
// Fix Yaml trying to convert strings to numbers automatically
// We only want to deal with a single type in the final frontmatter (not string | number)
test('should convert number values to string when string schema', () => {
const schema = Joi.object<{test: string}>({
test: JoiFrontMatter.string(),
});
const frontMatter = {
test: 42,
};
expect(validateFrontMatter(frontMatter, schema)).toEqual({test: '42'});
});
// Helps to fix Yaml trying to convert strings to dates automatically
// We only want to deal with a single type in the final frontmatter (not string | Date)
test('should convert date values when string schema', () => {
const schema = Joi.object<{test: string}>({
test: JoiFrontMatter.string(),
});
const date = new Date();
const frontMatter = {
test: date,
};
expect(validateFrontMatter(frontMatter, schema)).toEqual({
test: date.toString(),
});
});
});

View file

@ -83,3 +83,44 @@ export function normalizeThemeConfig<T>(
}
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 {
try {
return JoiFrontMatter.attempt(frontMatter, schema, {
convert: true,
allowUnknown: true,
});
} catch (e) {
console.error(
chalk.red(
`FrontMatter contains invalid values: ${JSON.stringify(
frontMatter,
null,
2,
)}`,
),
);
throw e;
}
}