mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-12 08:37:25 +02:00
fix(core): normalize slashes for url/baseUrl instead of throwing (#8066)
This commit is contained in:
parent
73d0ede21a
commit
bcae7503ff
4 changed files with 73 additions and 16 deletions
|
@ -69,6 +69,9 @@ export const URISchema = Joi.alternatives(
|
|||
// This custom validation logic is required notably because Joi does not
|
||||
// accept paths like /a/b/c ...
|
||||
Joi.custom((val: unknown, helpers) => {
|
||||
if (typeof val !== 'string') {
|
||||
return helpers.error('any.invalid');
|
||||
}
|
||||
try {
|
||||
// eslint-disable-next-line no-new
|
||||
new URL(String(val));
|
||||
|
|
|
@ -138,11 +138,6 @@ exports[`normalizeConfig should throw error if themes is not array for the input
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`normalizeConfig throws error for baseUrl without trailing \`/\` 1`] = `
|
||||
""baseUrl" must be a string with a trailing slash.
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`normalizeConfig throws error for required fields 1`] = `
|
||||
""baseUrl" is required
|
||||
"title" is required
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {jest} from '@jest/globals';
|
||||
import {
|
||||
ConfigSchema,
|
||||
DEFAULT_CONFIG,
|
||||
|
@ -86,12 +87,68 @@ describe('normalizeConfig', () => {
|
|||
}).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
it('throws error for baseUrl without trailing `/`', () => {
|
||||
expect(() => {
|
||||
it('throws for non-string URLs', () => {
|
||||
expect(() =>
|
||||
normalizeConfig({
|
||||
// @ts-expect-error: test
|
||||
url: 1,
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(`
|
||||
""url" contains an invalid value
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('normalizes various URLs', () => {
|
||||
const consoleMock = jest
|
||||
.spyOn(console, 'warn')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
expect(
|
||||
normalizeConfig({
|
||||
url: 'https://mysite.com/',
|
||||
}).url,
|
||||
).toBe('https://mysite.com');
|
||||
expect(
|
||||
normalizeConfig({
|
||||
// This shouldn't happen
|
||||
url: 'https://mysite.com/foo/',
|
||||
}).url,
|
||||
).toBe('https://mysite.com/foo');
|
||||
|
||||
expect(consoleMock.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
`"[WARNING] Docusaurus config validation warning. Field "url": The url is not supposed to contain a sub-path like '/foo/'. Please use the baseUrl field for sub-paths."`,
|
||||
);
|
||||
});
|
||||
|
||||
it('throws for non-string base URLs', () => {
|
||||
expect(() =>
|
||||
normalizeConfig({
|
||||
// @ts-expect-error: test
|
||||
baseUrl: 1,
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(`
|
||||
""baseUrl" must be a string
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('normalizes various base URLs', () => {
|
||||
expect(
|
||||
normalizeConfig({
|
||||
baseUrl: 'noSlash',
|
||||
});
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
}).baseUrl,
|
||||
).toBe('/noSlash/');
|
||||
expect(
|
||||
normalizeConfig({
|
||||
baseUrl: '/noSlash',
|
||||
}).baseUrl,
|
||||
).toBe('/noSlash/');
|
||||
expect(
|
||||
normalizeConfig({
|
||||
baseUrl: 'noSlash/foo',
|
||||
}).baseUrl,
|
||||
).toBe('/noSlash/foo/');
|
||||
});
|
||||
|
||||
it.each([
|
||||
|
@ -342,7 +399,7 @@ describe('config warnings', () => {
|
|||
expect(warning).toBeDefined();
|
||||
expect(warning.details).toHaveLength(1);
|
||||
expect(warning.details[0]!.message).toMatchInlineSnapshot(
|
||||
`"Docusaurus config validation warning. Field "url": the url is not supposed to contain a sub-path like '/someSubpath', please use the baseUrl field for sub-paths"`,
|
||||
`"Docusaurus config validation warning. Field "url": The url is not supposed to contain a sub-path like '/someSubpath'. Please use the baseUrl field for sub-paths."`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
import {
|
||||
DEFAULT_STATIC_DIR_NAME,
|
||||
DEFAULT_I18N_DIR_NAME,
|
||||
addLeadingSlash,
|
||||
addTrailingSlash,
|
||||
removeTrailingSlash,
|
||||
} from '@docusaurus/utils';
|
||||
import {Joi, URISchema, printWarning} from '@docusaurus/utils-validation';
|
||||
import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
|
||||
|
@ -149,24 +152,23 @@ const I18N_CONFIG_SCHEMA = Joi.object<I18nConfig>({
|
|||
.optional()
|
||||
.default(DEFAULT_I18N_CONFIG);
|
||||
|
||||
const SiteUrlSchema = URISchema.required().custom((value: unknown, helpers) => {
|
||||
const SiteUrlSchema = URISchema.required().custom((value: string, helpers) => {
|
||||
try {
|
||||
const {pathname} = new URL(String(value));
|
||||
if (pathname !== '/') {
|
||||
helpers.warn('docusaurus.configValidationWarning', {
|
||||
warningMessage: `the url is not supposed to contain a sub-path like '${pathname}', please use the baseUrl field for sub-paths`,
|
||||
warningMessage: `The url is not supposed to contain a sub-path like '${pathname}'. Please use the baseUrl field for sub-paths.`,
|
||||
});
|
||||
}
|
||||
} catch {}
|
||||
return value;
|
||||
}, 'siteUrlCustomValidation');
|
||||
return removeTrailingSlash(value);
|
||||
});
|
||||
|
||||
// TODO move to @docusaurus/utils-validation
|
||||
export const ConfigSchema = Joi.object<DocusaurusConfig>({
|
||||
baseUrl: Joi.string()
|
||||
.required()
|
||||
.regex(/\/$/m)
|
||||
.message('{{#label}} must be a string with a trailing slash.'),
|
||||
.custom((value: string) => addLeadingSlash(addTrailingSlash(value))),
|
||||
baseUrlIssueBanner: Joi.boolean().default(DEFAULT_CONFIG.baseUrlIssueBanner),
|
||||
favicon: Joi.string().optional(),
|
||||
title: Joi.string().required(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue