refactor(v2): add typing for docs plugin (#1811)

* refactor(v2): add typing for docs plugin

* nits
This commit is contained in:
Endi 2019-10-07 18:28:33 +07:00 committed by GitHub
parent f671e6b437
commit 1591128cdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 304 additions and 131 deletions

View file

@ -14,3 +14,4 @@ packages/docusaurus-utils/lib/
packages/docusaurus/lib/ packages/docusaurus/lib/
packages/docusaurus-init/lib/ packages/docusaurus-init/lib/
packages/docusaurus-plugin-content-blog/lib/ packages/docusaurus-plugin-content-blog/lib/
packages/docusaurus-plugin-content-docs-legacy/lib/

1
.gitignore vendored
View file

@ -16,3 +16,4 @@ packages/docusaurus-utils/lib/
packages/docusaurus/lib/ packages/docusaurus/lib/
packages/docusaurus-init/lib/ packages/docusaurus-init/lib/
packages/docusaurus-plugin-content-blog/lib/ packages/docusaurus-plugin-content-blog/lib/
packages/docusaurus-plugin-content-docs-legacy/lib/

View file

@ -6,3 +6,4 @@ packages/docusaurus-utils/lib/
packages/docusaurus/lib/ packages/docusaurus/lib/
packages/docusaurus-init/lib/ packages/docusaurus-init/lib/
packages/docusaurus-plugin-content-blog/lib/ packages/docusaurus-plugin-content-blog/lib/
packages/docusaurus-plugin-content-docs-legacy/lib/

View file

@ -18,6 +18,7 @@ module.exports = {
'/packages/docusaurus/lib', '/packages/docusaurus/lib',
'/packages/docusaurus-utils/lib', '/packages/docusaurus-utils/lib',
'/packages/docusaurus-plugin-content-blog/lib', '/packages/docusaurus-plugin-content-blog/lib',
'/packages/docusaurus-plugin-content-docs-legacy/lib',
], ],
transform: { transform: {
'^.+\\.[jt]sx?$': 'babel-jest', '^.+\\.[jt]sx?$': 'babel-jest',

View file

@ -28,6 +28,7 @@
"@types/fs-extra": "8.0.0", "@types/fs-extra": "8.0.0",
"@types/inquirer": "^6.0.3", "@types/inquirer": "^6.0.3",
"@types/jest": "^24.0.15", "@types/jest": "^24.0.15",
"@types/loader-utils": "^1.1.3",
"@types/lodash": "^4.14.136", "@types/lodash": "^4.14.136",
"@types/lodash.kebabcase": "^4.1.6", "@types/lodash.kebabcase": "^4.1.6",
"@types/node": "^12.0.2", "@types/node": "^12.0.2",

View file

@ -2,17 +2,23 @@
"name": "@docusaurus/plugin-content-docs-legacy", "name": "@docusaurus/plugin-content-docs-legacy",
"version": "2.0.0-alpha.25", "version": "2.0.0-alpha.25",
"description": "Documentation plugin for legacy v1 Docusaurus docs", "description": "Documentation plugin for legacy v1 Docusaurus docs",
"main": "src/index.js", "main": "lib/index.js",
"scripts": {
"tsc": "tsc"
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"license": "MIT", "license": "MIT",
"devDependencies": {
"@docusaurus/types": "^2.0.0-alpha.25"
},
"dependencies": { "dependencies": {
"@docusaurus/mdx-loader": "^2.0.0-alpha.25", "@docusaurus/mdx-loader": "^2.0.0-alpha.25",
"@docusaurus/utils": "^2.0.0-alpha.25", "@docusaurus/utils": "^2.0.0-alpha.25",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"globby": "^10.0.1", "globby": "^10.0.1",
"import-fresh": "^3.0.0", "import-fresh": "^3.1.0",
"loader-utils": "^1.2.3" "loader-utils": "^1.2.3"
}, },
"peerDependencies": { "peerDependencies": {

View file

@ -7,6 +7,7 @@
import path from 'path'; import path from 'path';
import pluginContentDocs from '../index'; import pluginContentDocs from '../index';
import {LoadContext} from '@docusaurus/types';
describe('loadDocs', () => { describe('loadDocs', () => {
test('simple website', async () => { test('simple website', async () => {
@ -16,18 +17,16 @@ describe('loadDocs', () => {
baseUrl: '/', baseUrl: '/',
url: 'https://docusaurus.io', url: 'https://docusaurus.io',
}; };
const context = {
siteDir,
siteConfig,
} as LoadContext;
const sidebarPath = path.join(siteDir, 'sidebars.json'); const sidebarPath = path.join(siteDir, 'sidebars.json');
const pluginPath = 'docs'; const pluginPath = 'docs';
const plugin = pluginContentDocs( const plugin = pluginContentDocs(context, {
{ path: 'docs',
siteDir, sidebarPath,
siteConfig, });
},
{
path: 'docs',
sidebarPath,
},
);
const {docs: docsMetadata} = await plugin.loadContent(); const {docs: docsMetadata} = await plugin.loadContent();
expect(docsMetadata.hello).toEqual({ expect(docsMetadata.hello).toEqual({

View file

@ -5,38 +5,49 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
const globby = require('globby'); import globby from 'globby';
const fs = require('fs'); import fs from 'fs-extra';
const path = require('path'); import path from 'path';
const {idx, normalizeUrl, docuHash} = require('@docusaurus/utils'); import {idx, normalizeUrl, docuHash} from '@docusaurus/utils';
const createOrder = require('./order'); import createOrder from './order';
const loadSidebars = require('./sidebars'); import loadSidebars from './sidebars';
const processMetadata = require('./metadata'); import processMetadata from './metadata';
import {LoadContext, Plugin, DocusaurusConfig} from '@docusaurus/types';
import {
PluginOptions,
Sidebar,
Order,
Metadata,
DocsMetadata,
LoadedContent,
SourceToPermalink,
PermalinkToId,
} from './types';
import {Configuration} from 'webpack';
const DEFAULT_OPTIONS = { const DEFAULT_OPTIONS: PluginOptions = {
path: 'docs', // Path to data on filesystem, relative to site dir. path: 'docs', // Path to data on filesystem, relative to site dir.
routeBasePath: 'docs', // URL Route. routeBasePath: 'docs', // URL Route.
include: ['**/*.md', '**/*.mdx'], // Extensions to include. include: ['**/*.md', '**/*.mdx'], // Extensions to include.
// TODO: Change format to array.
sidebarPath: '', // Path to sidebar configuration for showing a list of markdown pages. sidebarPath: '', // Path to sidebar configuration for showing a list of markdown pages.
// TODO: Settle themeing.
docLayoutComponent: '@theme/DocLegacyPage', docLayoutComponent: '@theme/DocLegacyPage',
docItemComponent: '@theme/DocLegacyItem', docItemComponent: '@theme/DocLegacyItem',
remarkPlugins: [], remarkPlugins: [],
rehypePlugins: [], rehypePlugins: [],
}; };
module.exports = function(context, opts) { export default function pluginContentDocs(
context: LoadContext,
opts: Partial<PluginOptions>,
): Plugin<LoadedContent | null> {
const options = {...DEFAULT_OPTIONS, ...opts}; const options = {...DEFAULT_OPTIONS, ...opts};
const contentPath = path.resolve(context.siteDir, options.path); const contentPath = path.resolve(context.siteDir, options.path);
let globalContents = {}; let sourceToPermalink: SourceToPermalink = {};
return { return {
name: 'docusaurus-plugin-content-docs', name: 'docusaurus-plugin-content-docs',
contentPath,
getPathsToWatch() { getPathsToWatch() {
const {include = []} = options; const {include = []} = options;
const globPattern = include.map(pattern => `${contentPath}/${pattern}`); const globPattern = include.map(pattern => `${contentPath}/${pattern}`);
@ -53,13 +64,13 @@ module.exports = function(context, opts) {
return null; return null;
} }
const docsSidebars = loadSidebars(sidebarPath); const docsSidebars: Sidebar = loadSidebars(sidebarPath);
// Build the docs ordering such as next, previous, category and sidebar // Build the docs ordering such as next, previous, category and sidebar
const order = createOrder(docsSidebars); const order: Order = createOrder(docsSidebars);
// Prepare metadata container. // Prepare metadata container.
const docs = {}; const docs: DocsMetadata = {};
// Metadata for default docs files. // Metadata for default docs files.
const docsFiles = await globby(include, { const docsFiles = await globby(include, {
@ -67,7 +78,7 @@ module.exports = function(context, opts) {
}); });
await Promise.all( await Promise.all(
docsFiles.map(async source => { docsFiles.map(async source => {
const metadata = await processMetadata( const metadata: Metadata = await processMetadata(
source, source,
docsDir, docsDir,
order, order,
@ -93,22 +104,19 @@ module.exports = function(context, opts) {
} }
}); });
const sourceToPermalink = {}; const permalinkToId: PermalinkToId = {};
const permalinkToId = {};
Object.values(docs).forEach(({id, source, permalink}) => { Object.values(docs).forEach(({id, source, permalink}) => {
sourceToPermalink[source] = permalink; sourceToPermalink[source] = permalink;
permalinkToId[permalink] = id; permalinkToId[permalink] = id;
}); });
globalContents = { return {
docs, docs,
docsDir, docsDir,
docsSidebars, docsSidebars,
sourceToPermalink, sourceToPermalink,
permalinkToId, permalinkToId,
}; };
return globalContents;
}, },
async contentLoaded({content, actions}) { async contentLoaded({content, actions}) {
@ -138,7 +146,7 @@ module.exports = function(context, opts) {
); );
const docsBaseRoute = normalizeUrl([ const docsBaseRoute = normalizeUrl([
context.siteConfig.baseUrl, (context.siteConfig as DocusaurusConfig).baseUrl,
routeBasePath, routeBasePath,
]); ]);
const docsMetadataPath = await createData( const docsMetadataPath = await createData(
@ -156,7 +164,8 @@ module.exports = function(context, opts) {
}); });
}, },
configureWebpack(config, isServer, {getBabelLoader, getCacheLoader}) { configureWebpack(_, isServer, utils) {
const {getBabelLoader, getCacheLoader} = utils;
const {rehypePlugins, remarkPlugins} = options; const {rehypePlugins, remarkPlugins} = options;
return { return {
module: { module: {
@ -179,15 +188,15 @@ module.exports = function(context, opts) {
options: { options: {
siteConfig: context.siteConfig, siteConfig: context.siteConfig,
siteDir: context.siteDir, siteDir: context.siteDir,
docsDir: globalContents.docsDir, docsDir: contentPath,
sourceToPermalink: globalContents.sourceToPermalink, sourceToPermalink: sourceToPermalink,
}, },
}, },
].filter(Boolean), ].filter(Boolean),
}, },
], ],
}, },
}; } as Configuration;
}, },
}; };
}; }

View file

@ -5,11 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
const path = require('path'); import path from 'path';
const {getOptions} = require('loader-utils'); import {getOptions} from 'loader-utils';
const {resolve} = require('url'); import {resolve} from 'url';
import {loader} from 'webpack';
module.exports = async function(fileString) { export = function(fileString: string) {
const callback = this.async(); const callback = this.async();
const options = Object.assign({}, getOptions(this), { const options = Object.assign({}, getOptions(this), {
filepath: this.resourcePath, filepath: this.resourcePath,
@ -17,7 +18,7 @@ module.exports = async function(fileString) {
const {docsDir, siteDir, sourceToPermalink} = options; const {docsDir, siteDir, sourceToPermalink} = options;
// Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0 // Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0
let sourceDir; let sourceDir: string | undefined;
const thisSource = this.resourcePath; const thisSource = this.resourcePath;
if (thisSource.startsWith(docsDir)) { if (thisSource.startsWith(docsDir)) {
sourceDir = docsDir; sourceDir = docsDir;
@ -44,7 +45,7 @@ module.exports = async function(fileString) {
// Replace it to correct html link. // Replace it to correct html link.
const mdLink = mdMatch[1]; const mdLink = mdMatch[1];
const targetSource = `${sourceDir}/${mdLink}`; const targetSource = `${sourceDir}/${mdLink}`;
const aliasedSource = source => const aliasedSource = (source: string) =>
`@site/${path.relative(siteDir, source)}`; `@site/${path.relative(siteDir, source)}`;
const permalink = const permalink =
sourceToPermalink[aliasedSource(resolve(thisSource, mdLink))] || sourceToPermalink[aliasedSource(resolve(thisSource, mdLink))] ||
@ -59,5 +60,5 @@ module.exports = async function(fileString) {
content = lines.join('\n'); content = lines.join('\n');
} }
return callback(null, content); return callback && callback(null, content);
}; } as loader.Loader;

View file

@ -5,18 +5,20 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
const fs = require('fs-extra'); import fs from 'fs-extra';
const path = require('path'); import path from 'path';
const {parse, normalizeUrl} = require('@docusaurus/utils'); import {parse, normalizeUrl} from '@docusaurus/utils';
import {Order, MetadataRaw} from './types';
import {DocusaurusConfig} from '@docusaurus/types';
module.exports = async function processMetadata( export default async function processMetadata(
source, source: string,
docsDir, docsDir: string,
order, order: Order,
siteConfig, siteConfig: Partial<DocusaurusConfig>,
docsBasePath, docsBasePath: string,
siteDir, siteDir: string,
) { ): Promise<MetadataRaw> {
const filepath = path.join(docsDir, source); const filepath = path.join(docsDir, source);
const fileString = await fs.readFile(filepath, 'utf-8'); const fileString = await fs.readFile(filepath, 'utf-8');
@ -82,5 +84,5 @@ module.exports = async function processMetadata(
} }
} }
return metadata; return metadata as MetadataRaw;
}; }

View file

@ -5,24 +5,42 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {
Sidebar,
SidebarItem,
SidebarItemDoc,
SidebarItemCategory,
Order,
} from './types';
// Build the docs meta such as next, previous, category and sidebar. // Build the docs meta such as next, previous, category and sidebar.
module.exports = function createOrder(allSidebars = {}) { export default function createOrder(allSidebars: Sidebar = {}): Order {
const order = {}; const order: Order = {};
Object.keys(allSidebars).forEach(sidebarId => { Object.keys(allSidebars).forEach(sidebarId => {
const sidebar = allSidebars[sidebarId]; const sidebar = allSidebars[sidebarId];
const ids = []; const ids: string[] = [];
const categoryOrder = []; const categoryOrder: (string | undefined)[] = [];
const subCategoryOrder = []; const subCategoryOrder: (string | undefined)[] = [];
const indexItems = ({items, categoryLabel, subCategoryLabel}) => { const indexItems = ({
items,
categoryLabel,
subCategoryLabel,
}: {
items: SidebarItem[];
categoryLabel?: string;
subCategoryLabel?: string;
}) => {
items.forEach(item => { items.forEach(item => {
switch (item.type) { switch (item.type) {
case 'category': case 'category':
indexItems({ indexItems({
items: item.items, items: (item as SidebarItemCategory).items,
categoryLabel: categoryLabel || item.label, categoryLabel:
subCategoryLabel: categoryLabel && item.label, categoryLabel || (item as SidebarItemCategory).label,
subCategoryLabel:
categoryLabel && (item as SidebarItemCategory).label,
}); });
break; break;
case 'ref': case 'ref':
@ -30,7 +48,7 @@ module.exports = function createOrder(allSidebars = {}) {
// Refs and links should not be shown in navigation. // Refs and links should not be shown in navigation.
break; break;
case 'doc': case 'doc':
ids.push(item.id); ids.push((item as SidebarItemDoc).id);
categoryOrder.push(categoryLabel); categoryOrder.push(categoryLabel);
subCategoryOrder.push(subCategoryLabel); subCategoryOrder.push(subCategoryLabel);
break; break;
@ -69,4 +87,4 @@ module.exports = function createOrder(allSidebars = {}) {
}); });
return order; return order;
}; }

View file

@ -5,16 +5,20 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
const fs = require('fs'); import fs from 'fs';
const importFresh = require('import-fresh'); import importFresh from 'import-fresh';
import {
SidebarItemCategory,
Sidebar,
SidebarRaw,
SidebarItem,
SidebarItemCategoryRaw,
} from './types';
/** /**
* Check that item contains only allowed keys * Check that item contains only allowed keys
*
* @param {Object} item
* @param {Array<string>} keys
*/ */
function assertItem(item, keys) { function assertItem(item: Object, keys: string[]): void {
const unknownKeys = Object.keys(item).filter( const unknownKeys = Object.keys(item).filter(
key => !keys.includes(key) && key !== 'type', key => !keys.includes(key) && key !== 'type',
); );
@ -31,13 +35,11 @@ function assertItem(item, keys) {
/** /**
* Normalizes recursively category and all its children. Ensures, that at the end * Normalizes recursively category and all its children. Ensures, that at the end
* each item will be an object with the corresponding type * each item will be an object with the corresponding type
*
* @param {Array<Object>} category
* @param {number} [level=0]
*
* @return {Array<Object>}
*/ */
function normalizeCategory(category, level = 0) { function normalizeCategory(
category: SidebarItemCategoryRaw,
level = 0,
): SidebarItemCategory {
if (level === 2) { if (level === 2) {
throw new Error( throw new Error(
`Can not process ${ `Can not process ${
@ -54,33 +56,32 @@ function normalizeCategory(category, level = 0) {
); );
} }
const items = category.items.map(item => { const items: SidebarItem[] = category.items.map(item => {
if (typeof item === 'string') {
return {
type: 'doc',
id: item,
};
}
switch (item.type) { switch (item.type) {
case 'category': case 'category':
return normalizeCategory(item, level + 1); return normalizeCategory(item as SidebarItemCategoryRaw, level + 1);
case 'link': case 'link':
assertItem(item, ['href', 'label']); assertItem(item, ['href', 'label']);
break; break;
case 'ref': case 'ref':
assertItem(item, ['id', 'label']); assertItem(item, ['id']);
break; break;
default: default:
if (typeof item === 'string') {
return {
type: 'doc',
id: item,
};
}
if (item.type !== 'doc') { if (item.type !== 'doc') {
throw new Error(`Unknown sidebar item type: ${item.type}`); throw new Error(`Unknown sidebar item type: ${item.type}`);
} }
assertItem(item, ['id', 'label']); assertItem(item, ['id']);
break; break;
} }
return item; return item as SidebarItem;
}); });
return {...category, items}; return {...category, items};
@ -88,35 +89,36 @@ function normalizeCategory(category, level = 0) {
/** /**
* Converts sidebars object to mapping to arrays of sidebar item objects * Converts sidebars object to mapping to arrays of sidebar item objects
*
* @param {{[key: string]: Object}} sidebars
*
* @return {{[key: string]: Array<Object>}}
*/ */
function normalizeSidebar(sidebars) { function normalizeSidebar(sidebars: SidebarRaw): Sidebar {
return Object.entries(sidebars).reduce((acc, [sidebarId, sidebar]) => { return Object.entries(sidebars).reduce(
let normalizedSidebar = sidebar; (acc: Sidebar, [sidebarId, sidebar]) => {
let normalizedSidebar: SidebarItemCategoryRaw[];
if (!Array.isArray(sidebar)) { if (!Array.isArray(sidebar)) {
// convert sidebar to a more generic structure // convert sidebar to a more generic structure
normalizedSidebar = Object.entries(sidebar).map(([label, items]) => ({ normalizedSidebar = Object.entries(sidebar).map(([label, items]) => ({
type: 'category', type: 'category',
label, label,
items, items,
})); }));
} } else {
normalizedSidebar = sidebar;
}
acc[sidebarId] = normalizedSidebar.map(item => normalizeCategory(item)); acc[sidebarId] = normalizedSidebar.map(item => normalizeCategory(item));
return acc; return acc;
}, {}); },
{},
);
} }
module.exports = function loadSidebars(sidebarPath) { export default function loadSidebars(sidebarPath: string): Sidebar {
// We don't want sidebars to be cached because of hotreloading. // We don't want sidebars to be cached because of hotreloading.
let allSidebars = {}; let allSidebars: SidebarRaw = {};
if (sidebarPath && fs.existsSync(sidebarPath)) { if (sidebarPath && fs.existsSync(sidebarPath)) {
allSidebars = importFresh(sidebarPath); allSidebars = importFresh(sidebarPath) as SidebarRaw;
} }
return normalizeSidebar(allSidebars); return normalizeSidebar(allSidebars);
}; }

View file

@ -0,0 +1,105 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export interface PluginOptions {
path: string;
routeBasePath: string;
include: string[];
sidebarPath: string;
docLayoutComponent: string;
docItemComponent: string;
remarkPlugins: string[];
rehypePlugins: string[];
}
export type SidebarItemDoc = {
type: string;
id: string;
};
export interface SidebarItemLink {
type: string;
href: string;
label: string;
}
export interface SidebarItemCategory {
type: string;
label: string;
items: SidebarItem[];
}
export interface SidebarItemCategoryRaw {
type: string;
label: string;
items: SidebarItemRaw[];
}
export type SidebarItem =
| SidebarItemDoc
| SidebarItemLink
| SidebarItemCategory;
export type SidebarItemRaw =
| string
| SidebarItemDoc
| SidebarItemLink
| SidebarItemCategoryRaw;
// Sidebar given by user that is not normalized yet. e.g: sidebars.json
export interface SidebarRaw {
[sidebarId: string]: {
[sidebarCategory: string]: SidebarItemRaw[];
};
}
export interface Sidebar {
[sidebarId: string]: SidebarItemCategory[];
}
export interface OrderMetadata {
previous?: string;
next?: string;
sidebar?: string;
category?: string;
subCategory?: string;
}
export interface Order {
[id: string]: OrderMetadata;
}
export interface MetadataRaw extends OrderMetadata {
id: string;
title: string;
description: string;
source: string;
permalink: string;
}
export interface Metadata extends MetadataRaw {
previous_title?: string;
next_title?: string;
}
export interface DocsMetadata {
[id: string]: Metadata;
}
export interface SourceToPermalink {
[source: string]: string;
}
export interface PermalinkToId {
[permalink: string]: string;
}
export interface LoadedContent {
docs: DocsMetadata;
docsDir: string;
docsSidebars: Sidebar;
sourceToPermalink: SourceToPermalink;
permalinkToId: PermalinkToId;
}

View file

@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./lib/.tsbuildinfo",
"rootDir": "src",
"outDir": "lib",
}
}

View file

@ -57,7 +57,7 @@ export interface PluginContentLoadedActions {
export interface Plugin<T> { export interface Plugin<T> {
name: string; name: string;
loadContent?(): T; loadContent?(): Promise<T>;
contentLoaded?({ contentLoaded?({
content, content,
actions, actions,
@ -67,7 +67,11 @@ export interface Plugin<T> {
}): void; }): void;
postBuild?(props: Props): void; postBuild?(props: Props): void;
postStart?(props: Props): void; postStart?(props: Props): void;
configureWebpack?(config: Configuration, isServer: boolean): Configuration; configureWebpack?(
config: Configuration,
isServer: boolean,
utils: ConfigureWebpackUtils,
): Configuration;
getThemePath?(): string; getThemePath?(): string;
getPathsToWatch?(): string[]; getPathsToWatch?(): string[];
getClientModules?(): string[]; getClientModules?(): string[];

View file

@ -52,7 +52,7 @@
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"globby": "^10.0.1", "globby": "^10.0.1",
"html-webpack-plugin": "^4.0.0-beta.8", "html-webpack-plugin": "^4.0.0-beta.8",
"import-fresh": "^3.0.0", "import-fresh": "^3.1.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"mini-css-extract-plugin": "^0.8.0", "mini-css-extract-plugin": "^0.8.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",

View file

@ -17,7 +17,7 @@ export async function swizzle(
themeName: string, themeName: string,
componentName?: string, componentName?: string,
): Promise<void> { ): Promise<void> {
const plugin = importFresh(themeName); const plugin: any = importFresh(themeName);
const pluginInstance = plugin({siteDir}); const pluginInstance = plugin({siteDir});
let fromPath = pluginInstance.getThemePath(); let fromPath = pluginInstance.getThemePath();

View file

@ -51,7 +51,7 @@ export function loadConfig(siteDir: string): DocusaurusConfig {
if (!fs.existsSync(configPath)) { if (!fs.existsSync(configPath)) {
throw new Error(`${CONFIG_FILE_NAME} not found`); throw new Error(`${CONFIG_FILE_NAME} not found`);
} }
const loadedConfig = importFresh(configPath); const loadedConfig = importFresh(configPath) as Partial<DocusaurusConfig>;
const missingFields = REQUIRED_FIELDS.filter( const missingFields = REQUIRED_FIELDS.filter(
field => !_.has(loadedConfig, field), field => !_.has(loadedConfig, field),
); );
@ -64,7 +64,10 @@ export function loadConfig(siteDir: string): DocusaurusConfig {
} }
// Merge default config with loaded config. // Merge default config with loaded config.
const config: DocusaurusConfig = {...DEFAULT_CONFIG, ...loadedConfig}; const config: DocusaurusConfig = {
...DEFAULT_CONFIG,
...loadedConfig,
} as DocusaurusConfig;
// Don't allow unrecognized fields. // Don't allow unrecognized fields.
const allowedFields = [...REQUIRED_FIELDS, ...OPTIONAL_FIELDS]; const allowedFields = [...REQUIRED_FIELDS, ...OPTIONAL_FIELDS];

View file

@ -49,7 +49,7 @@ export async function loadPlugins({
} }
// module is any valid module identifier - npm package or locally-resolved path. // module is any valid module identifier - npm package or locally-resolved path.
const pluginModule = importFresh(pluginModuleImport); const pluginModule: any = importFresh(pluginModuleImport);
return (pluginModule.default || pluginModule)(context, pluginOptions); return (pluginModule.default || pluginModule)(context, pluginOptions);
}), }),
); );

View file

@ -32,9 +32,11 @@ export function loadPresets(
} else if (Array.isArray(presetItem)) { } else if (Array.isArray(presetItem)) {
presetModuleImport = presetItem[0]; presetModuleImport = presetItem[0];
presetOptions = presetItem[1] || {}; presetOptions = presetItem[1] || {};
} else {
throw new Error('Invalid presets format detected in config.');
} }
const presetModule = importFresh(presetModuleImport); const presetModule: any = importFresh(presetModuleImport);
const preset: Preset = (presetModule.default || presetModule)( const preset: Preset = (presetModule.default || presetModule)(
context, context,
presetOptions, presetOptions,

View file

@ -2494,6 +2494,14 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
"@types/loader-utils@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-1.1.3.tgz#82b9163f2ead596c68a8c03e450fbd6e089df401"
integrity sha512-euKGFr2oCB3ASBwG39CYJMR3N9T0nanVqXdiH7Zu/Nqddt6SmFRxytq/i2w9LQYNQekEtGBz+pE3qG6fQTNvRg==
dependencies:
"@types/node" "*"
"@types/webpack" "*"
"@types/lodash.kebabcase@^4.1.6": "@types/lodash.kebabcase@^4.1.6":
version "4.1.6" version "4.1.6"
resolved "https://registry.yarnpkg.com/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.6.tgz#07b07aeca6c0647836de46f87a3cdfff72166c8e" resolved "https://registry.yarnpkg.com/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.6.tgz#07b07aeca6c0647836de46f87a3cdfff72166c8e"
@ -8126,10 +8134,10 @@ import-fresh@^2.0.0:
caller-path "^2.0.0" caller-path "^2.0.0"
resolve-from "^3.0.0" resolve-from "^3.0.0"
import-fresh@^3.0.0: import-fresh@^3.1.0:
version "3.0.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118"
integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==
dependencies: dependencies:
parent-module "^1.0.0" parent-module "^1.0.0"
resolve-from "^4.0.0" resolve-from "^4.0.0"