fix(v2): relax URI validation (#3227)

* relax URI validation

* add regex

* add test

* fix linting error

* fix formatting

* use URL rather than regex
This commit is contained in:
Anshul Goyal 2020-08-08 01:41:19 +05:30 committed by GitHub
parent fe281a8ebe
commit 181a6174c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 44 additions and 7 deletions

View file

@ -10,6 +10,7 @@ import {
RemarkPluginsSchema, RemarkPluginsSchema,
RehypePluginsSchema, RehypePluginsSchema,
AdmonitionsSchema, AdmonitionsSchema,
URISchema,
} from '@docusaurus/utils-validation'; } from '@docusaurus/utils-validation';
export const DEFAULT_OPTIONS = { export const DEFAULT_OPTIONS = {
@ -55,7 +56,7 @@ export const PluginOptionSchema = Joi.object({
remarkPlugins: RemarkPluginsSchema.default(DEFAULT_OPTIONS.remarkPlugins), remarkPlugins: RemarkPluginsSchema.default(DEFAULT_OPTIONS.remarkPlugins),
rehypePlugins: RehypePluginsSchema.default(DEFAULT_OPTIONS.rehypePlugins), rehypePlugins: RehypePluginsSchema.default(DEFAULT_OPTIONS.rehypePlugins),
admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions), admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
editUrl: Joi.string().uri(), editUrl: URISchema,
truncateMarker: Joi.object().default(DEFAULT_OPTIONS.truncateMarker), truncateMarker: Joi.object().default(DEFAULT_OPTIONS.truncateMarker),
beforeDefaultRemarkPlugins: Joi.array() beforeDefaultRemarkPlugins: Joi.array()
.items( .items(

View file

@ -10,6 +10,7 @@ import {
RemarkPluginsSchema, RemarkPluginsSchema,
RehypePluginsSchema, RehypePluginsSchema,
AdmonitionsSchema, AdmonitionsSchema,
URISchema,
} from '@docusaurus/utils-validation'; } from '@docusaurus/utils-validation';
export const DEFAULT_OPTIONS: PluginOptions = { export const DEFAULT_OPTIONS: PluginOptions = {
@ -31,7 +32,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
export const PluginOptionSchema = Joi.object({ export const PluginOptionSchema = Joi.object({
path: Joi.string().default(DEFAULT_OPTIONS.path), path: Joi.string().default(DEFAULT_OPTIONS.path),
editUrl: Joi.string().uri(), editUrl: URISchema,
routeBasePath: Joi.string().allow('').default(DEFAULT_OPTIONS.routeBasePath), routeBasePath: Joi.string().allow('').default(DEFAULT_OPTIONS.routeBasePath),
homePageId: Joi.string().optional(), homePageId: Joi.string().optional(),
include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include), include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include),

View file

@ -26,7 +26,8 @@
"prismjs": "^1.20.0", "prismjs": "^1.20.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",
"react-toggle": "^4.1.1" "react-toggle": "^4.1.1",
"@docusaurus/utils-validation": "^2.0.0-alpha.61"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "^2.0.0-alpha.61", "@docusaurus/module-type-aliases": "^2.0.0-alpha.61",

View file

@ -6,6 +6,7 @@
*/ */
const Joi = require('@hapi/joi'); const Joi = require('@hapi/joi');
const {URISchema} = require('@docusaurus/utils-validation');
const DEFAULT_COLOR_MODE_CONFIG = { const DEFAULT_COLOR_MODE_CONFIG = {
defaultMode: 'light', defaultMode: 'light',
@ -28,7 +29,7 @@ const NavbarItemPosition = Joi.string().equal('left', 'right').default('left');
const DefaultNavbarItemSchema = Joi.object({ const DefaultNavbarItemSchema = Joi.object({
items: Joi.array().optional().items(Joi.link('...')), items: Joi.array().optional().items(Joi.link('...')),
to: Joi.string(), to: Joi.string(),
href: Joi.string().uri(), href: URISchema,
label: Joi.string(), label: Joi.string(),
position: NavbarItemPosition, position: NavbarItemPosition,
activeBasePath: Joi.string(), activeBasePath: Joi.string(),
@ -140,7 +141,7 @@ const ColorModeSchema = Joi.object({
const FooterLinkItemSchema = Joi.object({ const FooterLinkItemSchema = Joi.object({
to: Joi.string(), to: Joi.string(),
href: Joi.string().uri(), href: URISchema,
html: Joi.string(), html: Joi.string(),
label: Joi.string(), label: Joi.string(),
}) })

View file

@ -59,3 +59,5 @@ exports[`validation schemas RemarkPluginsSchema: for value=3 1`] = `"\\"value\\"
exports[`validation schemas RemarkPluginsSchema: for value=false 1`] = `"\\"value\\" must be an array"`; exports[`validation schemas RemarkPluginsSchema: for value=false 1`] = `"\\"value\\" must be an array"`;
exports[`validation schemas RemarkPluginsSchema: for value=null 1`] = `"\\"value\\" must be an array"`; exports[`validation schemas RemarkPluginsSchema: for value=null 1`] = `"\\"value\\" must be an array"`;
exports[`validation schemas URISchema: for value="invalidURL" 1`] = `"\\"value\\" does not match any of the allowed types"`;

View file

@ -12,6 +12,7 @@ import {
RehypePluginsSchema, RehypePluginsSchema,
RemarkPluginsSchema, RemarkPluginsSchema,
PluginIdSchema, PluginIdSchema,
URISchema,
} from '../validationSchemas'; } from '../validationSchemas';
function createTestHelpers({ function createTestHelpers({
@ -106,4 +107,16 @@ describe('validation schemas', () => {
test('RehypePluginsSchema', () => { test('RehypePluginsSchema', () => {
testMarkdownPluginSchemas(RehypePluginsSchema); testMarkdownPluginSchemas(RehypePluginsSchema);
}); });
test('URISchema', () => {
const validURL = 'https://docusaurus.io';
const doubleHash = 'https://docusaurus.io#github#/:';
const invalidURL = 'invalidURL';
const urlFromIssue = 'https://riot.im/app/#/room/#ligo-public:matrix.org';
const {testFail, testOK} = createTestHelpers({schema: URISchema});
testOK(validURL);
testOK(doubleHash);
testFail(invalidURL);
testOK(urlFromIssue);
});
}); });

View file

@ -25,3 +25,19 @@ export const RemarkPluginsSchema = MarkdownPluginsSchema;
export const RehypePluginsSchema = MarkdownPluginsSchema; export const RehypePluginsSchema = MarkdownPluginsSchema;
export const AdmonitionsSchema = Joi.object().default({}); export const AdmonitionsSchema = Joi.object().default({});
export const URISchema = Joi.alternatives(
Joi.string().uri(),
Joi.custom((val, helpers) => {
try {
const url = new URL(val);
if (url) {
return val;
} else {
return helpers.error('any.invalid');
}
} catch {
return helpers.error('any.invalid');
}
}),
);

View file

@ -107,7 +107,8 @@
"webpack-bundle-analyzer": "^3.6.1", "webpack-bundle-analyzer": "^3.6.1",
"webpack-dev-server": "^3.11.0", "webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2", "webpack-merge": "^4.2.2",
"webpackbar": "^4.0.0" "webpackbar": "^4.0.0",
"@docusaurus/utils-validation": "^2.0.0-alpha.61"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^16.8.4", "react": "^16.8.4",

View file

@ -11,6 +11,7 @@ import Joi from '@hapi/joi';
import { import {
logValidationBugReportHint, logValidationBugReportHint,
isValidationDisabledEscapeHatch, isValidationDisabledEscapeHatch,
URISchema,
} from '@docusaurus/utils-validation'; } from '@docusaurus/utils-validation';
export const DEFAULT_CONFIG: Pick< export const DEFAULT_CONFIG: Pick<
@ -55,7 +56,7 @@ const ConfigSchema = Joi.object({
.message('{{#label}} must be a string with a trailing `/`'), .message('{{#label}} must be a string with a trailing `/`'),
favicon: Joi.string().required(), favicon: Joi.string().required(),
title: Joi.string().required(), title: Joi.string().required(),
url: Joi.string().uri().required(), url: URISchema.required(),
onBrokenLinks: Joi.string() onBrokenLinks: Joi.string()
.equal('ignore', 'log', 'warn', 'error', 'throw') .equal('ignore', 'log', 'warn', 'error', 'throw')
.default(DEFAULT_CONFIG.onBrokenLinks), .default(DEFAULT_CONFIG.onBrokenLinks),