fix(docusaurus-utils-validation): baseUrl + routeBasePath: allow empty string, normalized as "/" (#8258)

Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
fix https://github.com/facebook/docusaurus/issues/8254
This commit is contained in:
Dongjoon Lee 2022-12-09 00:54:32 +09:00 committed by GitHub
parent 85d0b5674f
commit e553ce7e59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 92 additions and 17 deletions

View file

@ -130,4 +130,12 @@ exports[`validation schemas remarkPluginsSchema: for value=false 1`] = `""value"
exports[`validation schemas remarkPluginsSchema: for value=null 1`] = `""value" must be an array"`;
exports[`validation schemas routeBasePathSchema: for value=[] 1`] = `""value" must be a string"`;
exports[`validation schemas routeBasePathSchema: for value={} 1`] = `""value" must be a string"`;
exports[`validation schemas routeBasePathSchema: for value=3 1`] = `""value" must be a string"`;
exports[`validation schemas routeBasePathSchema: for value=null 1`] = `""value" must be a string"`;
exports[`validation schemas uRISchema: for value="spaces are invalid in a URL" 1`] = `""value" does not look like a valid url (value='')"`;

View file

@ -14,6 +14,7 @@ import {
PluginIdSchema,
URISchema,
PathnameSchema,
RouteBasePathSchema,
ContentVisibilitySchema,
} from '../validationSchemas';
@ -24,8 +25,9 @@ function createTestHelpers({
schema: Joi.Schema;
defaultValue?: unknown;
}) {
function testOK(value: unknown) {
expect(Joi.attempt(value, schema)).toEqual(value ?? defaultValue);
function testOK(value: unknown, options?: {normalizedValue?: unknown}) {
const expectedValue = options?.normalizedValue ?? value ?? defaultValue;
expect(Joi.attempt(value, schema)).toEqual(expectedValue);
}
function testFail(value: unknown) {
@ -168,6 +170,29 @@ describe('validation schemas', () => {
testFail('https://github.com/foo');
});
it('routeBasePathSchema', () => {
const {testFail, testOK} = createTestHelpers({
schema: RouteBasePathSchema,
defaultValue: undefined,
});
testOK('', {normalizedValue: '/'});
testOK('/');
testOK('/foo', {normalizedValue: '/foo'});
testOK('foo', {normalizedValue: '/foo'});
testOK('blog', {normalizedValue: '/blog'});
testOK('blog/', {normalizedValue: '/blog/'});
testOK('prefix/blog', {normalizedValue: '/prefix/blog'});
testOK('prefix/blog/', {normalizedValue: '/prefix/blog/'});
testOK('/prefix/blog', {normalizedValue: '/prefix/blog'});
testOK(undefined);
testFail(3);
testFail([]);
testFail(null);
testFail({});
});
it('contentVisibilitySchema', () => {
const {testFail, testOK} = createTestHelpers({
schema: ContentVisibilitySchema,

View file

@ -20,6 +20,7 @@ export {
RemarkPluginsSchema,
RehypePluginsSchema,
AdmonitionsSchema,
RouteBasePathSchema,
URISchema,
PathnameSchema,
FrontMatterTagsSchema,

View file

@ -5,7 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/
import {isValidPathname, DEFAULT_PLUGIN_ID, type Tag} from '@docusaurus/utils';
import {
isValidPathname,
DEFAULT_PLUGIN_ID,
type Tag,
addLeadingSlash,
} from '@docusaurus/utils';
import Joi from './Joi';
import {JoiFrontMatter} from './JoiFrontMatter';
@ -96,6 +101,26 @@ export const PathnameSchema = Joi.string()
'{{#label}} is not a valid pathname. Pathname should start with slash and not contain any domain or query string.',
);
// Normalized schema for url path segments: baseUrl + routeBasePath...
// Note we only add a leading slash
// we don't always want to enforce a trailing slash on urls such as /docs
//
// Examples:
// '' => '/'
// 'docs' => '/docs'
// '/docs' => '/docs'
// 'docs/' => '/docs'
// 'prefix/docs' => '/prefix/docs'
// TODO tighter validation: not all strings are valid path segments
export const RouteBasePathSchema = Joi
// Weird Joi trick needed, otherwise value '' is not normalized...
.alternatives()
.try(Joi.string().required().allow(''))
.custom((value: string) =>
// /!\ do not add trailing slash here
addLeadingSlash(value),
);
const FrontMatterTagSchema = JoiFrontMatter.alternatives()
.try(
JoiFrontMatter.string().required(),