Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v2): add option validation for remaining official plugins #2970

Merged
merged 41 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
1b49445
feat(v2): add option validation lifecycle method
teikjun Jun 17, 2020
f28eb1d
chore(v2): add dependencies
teikjun Jun 17, 2020
032de42
chore(v2): add yup dependency
teikjun Jun 17, 2020
43132fb
feat(v2): add option validation for plugin-content-docs
teikjun Jun 17, 2020
09a80cd
chore(v2): add facebook copyright
teikjun Jun 17, 2020
c4035b3
refactor(v2): remove unused variable
teikjun Jun 17, 2020
c9921e9
chore(v2): add dependencies
teikjun Jun 17, 2020
ab9200d
chore(v2): add copyright
teikjun Jun 17, 2020
890d092
fix(v2): use strict for option validation
teikjun Jun 17, 2020
9cb9901
feat(v2): add option validation for plugin-content-pages
teikjun Jun 17, 2020
da49235
feat(v2): add schema for plugin-google-analytics and plugin-google-gtag
teikjun Jun 17, 2020
b77572f
feat(v2): add option validation for plugin-sitemap
teikjun Jun 17, 2020
877bff0
chore(v2): add dependency for yup
teikjun Jun 17, 2020
a34eb1d
fix(v2): remove strict to allow normalization
teikjun Jun 18, 2020
e2a98cc
refactor(v2): refactor validate method
teikjun Jun 18, 2020
73d9c79
feat(v2): modify existing tests
teikjun Jun 18, 2020
13fdc69
feat(v2): add tests for plugin normalization
teikjun Jun 18, 2020
dc82ecb
style(v2): use a more descriptive filename for schema
teikjun Jun 18, 2020
e43887c
feat(v2): add normalization tests
teikjun Jun 18, 2020
8ec540b
feat(v2): add more tests for option validation
teikjun Jun 18, 2020
a85fe6b
refactor(v2): remove unused code
teikjun Jun 19, 2020
9f56d1b
refactor(v2): remove unused code
teikjun Jun 21, 2020
ca3a74d
refactor(v2): refactor methods and types
teikjun Jun 21, 2020
4be0982
feat(v2): replace Yup with Joi
teikjun Jun 21, 2020
f218b55
fix(v2): fix plugin-content-docs schema
teikjun Jun 21, 2020
c17eeb9
feat(v2): modify tests for plugin-content-docs
teikjun Jun 21, 2020
8b5bd35
fix(v2): fix a typo
teikjun Jun 21, 2020
67e8f5d
refactor(v2): improve tests and refactor code
teikjun Jun 21, 2020
080136a
feat(v2): support both commonjs and ES modules
teikjun Jun 25, 2020
45b8f95
refactor(v2): refactor validateOption method
teikjun Jun 25, 2020
6c79e8a
chore(v2): resolve merge conflicts
teikjun Jun 25, 2020
4ecc355
style(v2): fix eslint errors and typo in types
teikjun Jun 25, 2020
4735b65
chore(v2): remove unused yup dependency
teikjun Jun 25, 2020
9e6c00f
style(v2): standardize naming across official plugins
teikjun Jun 25, 2020
dae6733
chore(v2): merge branch 'master' into teikjun/validation
teikjun Jun 25, 2020
6d69363
chore(v2): update test snapshots
teikjun Jun 25, 2020
084f1f6
chore(v2): remove obsolete snapshots
teikjun Jun 25, 2020
28c2c9b
chore(v2): fix a typo and check test
teikjun Jun 25, 2020
63ca9a4
chore(v2): resolve merge conflict
teikjun Jun 25, 2020
3db66a3
feat(v2): add validation for new field
teikjun Jun 25, 2020
d89d118
feat(v2): add test for new field
teikjun Jun 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions packages/docusaurus-plugin-client-redirects/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
"eta": "^1.1.1",
"fs-extra": "^8.1.0",
"globby": "^10.0.1",
"lodash": "^4.17.15",
"yup": "^0.29.0"
"lodash": "^4.17.15"
},
"peerDependencies": {
"@docusaurus/core": "^2.0.0",
Expand All @@ -30,8 +29,5 @@
},
"engines": {
"node": ">=10.9.0"
},
"devDependencies": {
"@types/yup": "^0.29.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import fs from 'fs-extra';
import path from 'path';
import pluginContentBlog from '../index';
import {DocusaurusConfig, LoadContext} from '@docusaurus/types';
import {PluginOptionSchema} from '../validation';
import {PluginOptionSchema} from '../pluginOptionSchema';

function validateAndNormalize(schema, options) {
const {value, error} = schema.validate(options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/

import {PluginOptionSchema, DefaultOptions} from '../validation';
import {PluginOptionSchema, DEFAULT_OPTIONS} from '../pluginOptionSchema';

test('normalize options', () => {
const {value} = PluginOptionSchema.validate({});
expect(value).toEqual(DefaultOptions);
expect(value).toEqual(DEFAULT_OPTIONS);
});

test('validate options', () => {
Expand All @@ -20,7 +20,7 @@ test('validate options', () => {
routeBasePath: 'not_blog',
});
expect(value).toEqual({
...DefaultOptions,
...DEFAULT_OPTIONS,
postsPerPage: 5,
include: ['api/*', 'docs/*'],
routeBasePath: 'not_blog',
Expand Down Expand Up @@ -54,7 +54,7 @@ test('convert all feed type to array with other feed type', () => {
feedOptions: {type: 'all'},
});
expect(value).toEqual({
...DefaultOptions,
...DEFAULT_OPTIONS,
feedOptions: {type: ['rss', 'atom']},
});
});
2 changes: 1 addition & 1 deletion packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
BlogPaginated,
BlogPost,
} from './types';
import {PluginOptionSchema} from './validation';
import {PluginOptionSchema} from './pluginOptionSchema';
import {
LoadContext,
PluginContentLoadedActions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import * as Joi from '@hapi/joi';

export const DefaultOptions = {
export const DEFAULT_OPTIONS = {
feedOptions: {},
beforeDefaultRehypePlugins: [],
beforeDefaultRemarkPlugins: [],
Expand All @@ -27,22 +27,22 @@ export const DefaultOptions = {
};

export const PluginOptionSchema = Joi.object({
path: Joi.string().default(DefaultOptions.path),
routeBasePath: Joi.string().default(DefaultOptions.routeBasePath),
include: Joi.array().items(Joi.string()).default(DefaultOptions.include),
path: Joi.string().default(DEFAULT_OPTIONS.path),
routeBasePath: Joi.string().default(DEFAULT_OPTIONS.routeBasePath),
include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include),
postsPerPage: Joi.number()
.integer()
.min(1)
.default(DefaultOptions.postsPerPage),
blogListComponent: Joi.string().default(DefaultOptions.blogListComponent),
blogPostComponent: Joi.string().default(DefaultOptions.blogPostComponent),
.default(DEFAULT_OPTIONS.postsPerPage),
blogListComponent: Joi.string().default(DEFAULT_OPTIONS.blogListComponent),
blogPostComponent: Joi.string().default(DEFAULT_OPTIONS.blogPostComponent),
blogTagsListComponent: Joi.string().default(
DefaultOptions.blogTagsListComponent,
DEFAULT_OPTIONS.blogTagsListComponent,
),
blogTagsPostsComponent: Joi.string().default(
DefaultOptions.blogTagsPostsComponent,
DEFAULT_OPTIONS.blogTagsPostsComponent,
),
showReadingTime: Joi.bool().default(DefaultOptions.showReadingTime),
showReadingTime: Joi.bool().default(DEFAULT_OPTIONS.showReadingTime),
remarkPlugins: Joi.array()
.items(
Joi.alternatives().try(
Expand All @@ -52,19 +52,19 @@ export const PluginOptionSchema = Joi.object({
.length(2),
),
)
.default(DefaultOptions.remarkPlugins),
.default(DEFAULT_OPTIONS.remarkPlugins),
rehypePlugins: Joi.array()
.items(Joi.string())
.default(DefaultOptions.rehypePlugins),
.default(DEFAULT_OPTIONS.rehypePlugins),
editUrl: Joi.string().uri(),
truncateMarker: Joi.object().default(DefaultOptions.truncateMarker),
admonitions: Joi.object().default(DefaultOptions.admonitions),
truncateMarker: Joi.object().default(DEFAULT_OPTIONS.truncateMarker),
admonitions: Joi.object().default(DEFAULT_OPTIONS.admonitions),
beforeDefaultRemarkPlugins: Joi.array()
.items(Joi.object())
.default(DefaultOptions.beforeDefaultRemarkPlugins),
.default(DEFAULT_OPTIONS.beforeDefaultRemarkPlugins),
beforeDefaultRehypePlugins: Joi.array()
.items(Joi.object())
.default(DefaultOptions.beforeDefaultRehypePlugins),
.default(DEFAULT_OPTIONS.beforeDefaultRehypePlugins),
feedOptions: Joi.object({
type: Joi.alternatives().conditional(
Joi.string().equal('all', 'rss', 'atom'),
Expand All @@ -76,5 +76,5 @@ export const PluginOptionSchema = Joi.object({
description: Joi.string(),
copyright: Joi.string(),
language: Joi.string(),
}).default(DefaultOptions.feedOptions),
}).default(DEFAULT_OPTIONS.feedOptions),
});
4 changes: 3 additions & 1 deletion packages/docusaurus-plugin-content-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"license": "MIT",
"devDependencies": {
"commander": "^5.0.0",
"picomatch": "^2.1.1"
"picomatch": "^2.1.1",
"@types/hapi__joi": "^17.1.2"
},
"dependencies": {
"@docusaurus/mdx-loader": "^2.0.0-alpha.58",
Expand All @@ -22,6 +23,7 @@
"execa": "^3.4.0",
"fs-extra": "^8.1.0",
"globby": "^10.0.1",
"@hapi/joi": "17.1.1",
"import-fresh": "^3.2.1",
"loader-utils": "^1.2.3",
"lodash.flatmap": "^4.5.0",
Expand Down
45 changes: 30 additions & 15 deletions packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import commander from 'commander';
import fs from 'fs-extra';
import pluginContentDocs from '../index';
import loadEnv from '../env';
import normalizePluginOptions from './pluginOptionSchema.test';
import {loadContext} from '@docusaurus/core/src/server/index';
import {applyConfigureWebpack} from '@docusaurus/core/src/webpack/utils';
import {RouteConfig} from '@docusaurus/types';
Expand Down Expand Up @@ -42,9 +43,12 @@ test('site with wrong sidebar file', async () => {
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
const context = loadContext(siteDir);
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
const plugin = pluginContentDocs(context, {
sidebarPath,
});
const plugin = pluginContentDocs(
context,
normalizePluginOptions({
sidebarPath,
}),
);
await expect(plugin.loadContent()).rejects.toThrowErrorMatchingSnapshot();
});

Expand All @@ -54,7 +58,7 @@ describe('empty/no docs website', () => {

test('no files in docs folder', async () => {
await fs.ensureDir(path.join(siteDir, 'docs'));
const plugin = pluginContentDocs(context, {});
const plugin = pluginContentDocs(context, normalizePluginOptions({}));
const content = await plugin.loadContent();
const {docsMetadata, docsSidebars} = content;
expect(docsMetadata).toMatchInlineSnapshot(`Object {}`);
Expand All @@ -73,7 +77,12 @@ describe('empty/no docs website', () => {
});

test('docs folder does not exist', async () => {
const plugin = pluginContentDocs(context, {path: '/path/does/not/exist/'});
const plugin = pluginContentDocs(
context,
normalizePluginOptions({
path: '/path/does/not/exist/',
}),
);
const content = await plugin.loadContent();
expect(content).toBeNull();
});
Expand All @@ -84,11 +93,14 @@ describe('simple website', () => {
const context = loadContext(siteDir);
const sidebarPath = path.join(siteDir, 'sidebars.json');
const pluginPath = 'docs';
const plugin = pluginContentDocs(context, {
path: pluginPath,
sidebarPath,
homePageId: 'hello',
});
const plugin = pluginContentDocs(
context,
normalizePluginOptions({
path: pluginPath,
sidebarPath,
homePageId: 'hello',
}),
);
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);

test('extendCli - docsVersion', () => {
Expand Down Expand Up @@ -215,11 +227,14 @@ describe('versioned website', () => {
const context = loadContext(siteDir);
const sidebarPath = path.join(siteDir, 'sidebars.json');
const routeBasePath = 'docs';
const plugin = pluginContentDocs(context, {
routeBasePath,
sidebarPath,
homePageId: 'hello',
});
const plugin = pluginContentDocs(
context,
normalizePluginOptions({
routeBasePath,
sidebarPath,
homePageId: 'hello',
}),
);
const env = loadEnv(siteDir);
const {docsDir: versionedDir} = env.versioning;
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* 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 {PluginOptionSchema, DEFAULT_OPTIONS} from '../pluginOptionSchema';

export default function normalizePluginOptions(options) {
const {value, error} = PluginOptionSchema.validate(options, {
slorber marked this conversation as resolved.
Show resolved Hide resolved
convert: false,
});
if (error) {
throw error;
} else {
return value;
}
}

describe('normalizeDocsPluginOptions', () => {
test('should return default options for undefined user options', async () => {
const {value} = await PluginOptionSchema.validate({});
expect(value).toEqual(DEFAULT_OPTIONS);
});

test('should accept correctly defined user options', async () => {
const userOptions = {
path: 'my-docs', // Path to data on filesystem, relative to site dir.
routeBasePath: 'my-docs', // URL Route.
homePageId: 'home', // Document id for docs home page.
include: ['**/*.{md,mdx}'], // Extensions to include.
sidebarPath: 'my-sidebar', // Path to sidebar configuration for showing a list of markdown pages.
docLayoutComponent: '@theme/DocPage',
docItemComponent: '@theme/DocItem',
remarkPlugins: [],
rehypePlugins: [],
showLastUpdateTime: true,
showLastUpdateAuthor: true,
admonitions: {},
excludeNextVersionDocs: true,
};

const {value} = await PluginOptionSchema.validate(userOptions);
expect(value).toEqual(userOptions);
});

test('should reject bad path inputs', () => {
expect(() => {
normalizePluginOptions({
path: 2,
});
}).toThrowErrorMatchingInlineSnapshot(`"\\"path\\" must be a string"`);
});

test('should reject bad include inputs', () => {
expect(() => {
normalizePluginOptions({
include: '**/*.{md,mdx}',
});
}).toThrowErrorMatchingInlineSnapshot(`"\\"include\\" must be an array"`);
});

test('should reject bad showLastUpdateTime inputs', () => {
expect(() => {
normalizePluginOptions({
showLastUpdateTime: 'true',
});
}).toThrowErrorMatchingInlineSnapshot(
`"\\"showLastUpdateTime\\" must be a boolean"`,
);
});

test('should reject bad remarkPlugins input', () => {
expect(() => {
normalizePluginOptions({
remarkPlugins: 'remark-math',
});
}).toThrowErrorMatchingInlineSnapshot(
`"\\"remarkPlugins\\" must be an array"`,
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('loadSidebars', () => {
expect(result).toMatchSnapshot();
});

test('sidebars shortand and longform lead to exact same sidebar', async () => {
test('sidebars shorthand and longform lead to exact same sidebar', async () => {
const sidebarPath1 = path.join(fixtureDir, 'sidebars-category.js');
const sidebarPath2 = path.join(
fixtureDir,
Expand Down
Loading