mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
chore(v2): Fix more eslint errors (#2976)
This commit is contained in:
parent
3611c96f90
commit
6e43c9bd34
81 changed files with 375 additions and 237 deletions
14
.eslintrc.js
14
.eslintrc.js
|
@ -85,27 +85,23 @@ module.exports = {
|
|||
],
|
||||
'no-unused-vars': OFF,
|
||||
'@typescript-eslint/no-unused-vars': [ERROR, {argsIgnorePattern: '^_'}],
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
ERROR,
|
||||
{'ts-expect-error': 'allow-with-description'},
|
||||
],
|
||||
|
||||
// TODO re-enable some these as errors
|
||||
// context: https://github.com/facebook/docusaurus/pull/2949
|
||||
'@typescript-eslint/ban-ts-comment': WARNING,
|
||||
'@typescript-eslint/ban-types': WARNING,
|
||||
'import/prefer-default-export': WARNING,
|
||||
'import/no-extraneous-dependencies': WARNING,
|
||||
'no-useless-escape': WARNING,
|
||||
'prefer-template': WARNING,
|
||||
'no-shadow': WARNING,
|
||||
'no-param-reassign': WARNING,
|
||||
'no-else-return': WARNING,
|
||||
'no-template-curly-in-string': WARNING,
|
||||
'array-callback-return': WARNING,
|
||||
camelcase: WARNING,
|
||||
'no-nested-ternary': WARNING,
|
||||
'object-shorthand': WARNING,
|
||||
'no-restricted-syntax': WARNING,
|
||||
'no-unused-expressions': WARNING,
|
||||
'consistent-return': WARNING,
|
||||
'no-useless-return': WARNING,
|
||||
'@typescript-eslint/no-empty-function': WARNING,
|
||||
'global-require': WARNING,
|
||||
'prefer-destructuring': WARNING,
|
||||
|
@ -114,8 +110,6 @@ module.exports = {
|
|||
'no-empty': WARNING,
|
||||
'no-prototype-builtins': WARNING,
|
||||
'no-case-declarations': WARNING,
|
||||
'default-case': WARNING,
|
||||
'dot-notation': WARNING,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
|
|
11
package.json
11
package.json
|
@ -37,8 +37,6 @@
|
|||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "^3.3.0",
|
||||
"@typescript-eslint/parser": "^3.3.0",
|
||||
"@types/express": "^4.17.2",
|
||||
"@types/fs-extra": "^8.0.1",
|
||||
"@types/inquirer": "^6.5.0",
|
||||
|
@ -54,13 +52,18 @@
|
|||
"@types/lodash.pick": "^4.4.6",
|
||||
"@types/lodash.pickby": "^4.6.6",
|
||||
"@types/node": "^13.11.0",
|
||||
"@types/react": "^16.9.13",
|
||||
"@types/react": "^16.9.38",
|
||||
"@types/react-dev-utils": "^9.0.1",
|
||||
"@types/react-helmet": "^6.0.0",
|
||||
"@types/react-loadable": "^5.5.3",
|
||||
"@types/react-router-config": "^5.0.1",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/shelljs": "^0.8.6",
|
||||
"@types/webpack": "^4.41.0",
|
||||
"@types/webpack-dev-server": "^3.9.0",
|
||||
"@types/webpack-merge": "^4.1.5",
|
||||
"@typescript-eslint/eslint-plugin": "^3.3.0",
|
||||
"@typescript-eslint/parser": "^3.3.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"concurrently": "^5.2.0",
|
||||
"enzyme": "^3.10.0",
|
||||
|
@ -85,7 +88,7 @@
|
|||
"rimraf": "^3.0.2",
|
||||
"serve": "^11.3.2",
|
||||
"stylelint": "^13.2.1",
|
||||
"typescript": "^3.7.2"
|
||||
"typescript": "^3.9.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"stylelint-copyright": "^2.0.0"
|
||||
|
|
|
@ -11,7 +11,7 @@ const chalk = require('chalk');
|
|||
const semver = require('semver');
|
||||
const path = require('path');
|
||||
const program = require('commander');
|
||||
const {init} = require('../lib');
|
||||
const {default: init} = require('../lib');
|
||||
const requiredVersion = require('../package.json').engines.node;
|
||||
|
||||
if (!semver.satisfies(process.version, requiredVersion)) {
|
||||
|
|
|
@ -26,7 +26,10 @@ function isValidGitRepoUrl(gitRepoUrl: string): boolean {
|
|||
return ['https://', 'git@'].some((item) => gitRepoUrl.startsWith(item));
|
||||
}
|
||||
|
||||
async function updatePkg(pkgPath: string, obj: any): Promise<void> {
|
||||
async function updatePkg(
|
||||
pkgPath: string,
|
||||
obj: Record<string, unknown>,
|
||||
): Promise<void> {
|
||||
const content = await fs.readFile(pkgPath, 'utf-8');
|
||||
const pkg = JSON.parse(content);
|
||||
const newPkg = Object.assign(pkg, obj);
|
||||
|
@ -34,7 +37,7 @@ async function updatePkg(pkgPath: string, obj: any): Promise<void> {
|
|||
await fs.outputFile(pkgPath, JSON.stringify(newPkg, null, 2));
|
||||
}
|
||||
|
||||
export async function init(
|
||||
export default async function init(
|
||||
rootDir: string,
|
||||
siteName?: string,
|
||||
reqTemplate?: string,
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
"dependencies": {
|
||||
"@docusaurus/types": "^2.0.0-alpha.58",
|
||||
"@docusaurus/utils": "^2.0.0-alpha.58",
|
||||
"chalk": "^3.0.0",
|
||||
"eta": "^1.1.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"globby": "^10.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"yup": "^0.29.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
|
@ -208,7 +208,7 @@ describe('collectRedirects', () => {
|
|||
{
|
||||
createRedirects: (routePath) => {
|
||||
if (routePath === '/') {
|
||||
return [[`/fromPath`]] as any;
|
||||
return ([[`/fromPath`]] as unknown) as string;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
|
|
@ -49,7 +49,7 @@ describe('normalizePluginOptions', () => {
|
|||
test('should reject bad fromExtensions user inputs', () => {
|
||||
expect(() =>
|
||||
normalizePluginOptions({
|
||||
fromExtensions: [null, undefined, 123, true] as any,
|
||||
fromExtensions: ([null, undefined, 123, true] as unknown) as string[],
|
||||
}),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ describe('normalizePluginOptions', () => {
|
|||
test('should reject bad toExtensions user inputs', () => {
|
||||
expect(() =>
|
||||
normalizePluginOptions({
|
||||
toExtensions: [null, undefined, 123, true] as any,
|
||||
toExtensions: ([null, undefined, 123, true] as unknown) as string[],
|
||||
}),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
@ -65,7 +65,10 @@ describe('normalizePluginOptions', () => {
|
|||
test('should reject bad createRedirects user inputs', () => {
|
||||
expect(() =>
|
||||
normalizePluginOptions({
|
||||
createRedirects: ['bad', 'value'] as any,
|
||||
createRedirects: ([
|
||||
'bad',
|
||||
'value',
|
||||
] as unknown) as CreateRedirectsFnOption,
|
||||
}),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
|
|
@ -36,6 +36,7 @@ function validateCollectedRedirects(
|
|||
.map((redirect) => {
|
||||
try {
|
||||
validateRedirect(redirect);
|
||||
return undefined;
|
||||
} catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
|
@ -132,12 +133,11 @@ function createRedirectsOptionRedirects(
|
|||
function optionToRedirects(option: RedirectOption): RedirectMetadata[] {
|
||||
if (typeof option.from === 'string') {
|
||||
return [{from: option.from, to: option.to}];
|
||||
} else {
|
||||
return option.from.map((from) => ({
|
||||
from,
|
||||
to: option.to,
|
||||
}));
|
||||
}
|
||||
return option.from.map((from) => ({
|
||||
from,
|
||||
to: option.to,
|
||||
}));
|
||||
}
|
||||
|
||||
return flatten(redirectsOption.map(optionToRedirects));
|
||||
|
|
|
@ -12,6 +12,8 @@ import {RedirectMetadata} from './types';
|
|||
export const PathnameValidator = Yup.string().test({
|
||||
name: 'isValidPathname',
|
||||
message:
|
||||
// Yup requires this format.
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'${path} is not a valid pathname. Pathname should start with / and not contain any domain or query string',
|
||||
test: isValidPathname,
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('blogFeed', () => {
|
|||
routeBasePath: 'blog',
|
||||
include: ['*.md', '*.mdx'],
|
||||
feedOptions: {
|
||||
type: feedType as any,
|
||||
type: feedType,
|
||||
copyright: 'Copyright',
|
||||
},
|
||||
} as PluginOptions,
|
||||
|
@ -62,7 +62,7 @@ describe('blogFeed', () => {
|
|||
routeBasePath: 'blog',
|
||||
include: ['*r*.md', '*.mdx'], // skip no-date.md - it won't play nice with snapshots
|
||||
feedOptions: {
|
||||
type: feedType as any,
|
||||
type: feedType,
|
||||
copyright: 'Copyright',
|
||||
},
|
||||
} as PluginOptions,
|
||||
|
|
|
@ -72,10 +72,10 @@ export async function generateBlogFeed(
|
|||
blogPosts.forEach((post) => {
|
||||
const {
|
||||
id,
|
||||
metadata: {title, permalink, date, description},
|
||||
metadata: {title: metadataTitle, permalink, date, description},
|
||||
} = post;
|
||||
feed.addItem({
|
||||
title,
|
||||
title: metadataTitle,
|
||||
id,
|
||||
link: normalizeUrl([siteUrl, permalink]),
|
||||
date,
|
||||
|
|
|
@ -205,9 +205,8 @@ export default function pluginContentBlog(
|
|||
label: tag,
|
||||
permalink,
|
||||
};
|
||||
} else {
|
||||
return tag;
|
||||
}
|
||||
return tag;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -244,7 +243,7 @@ export default function pluginContentBlog(
|
|||
`~blog/${path.relative(dataDir, source)}`;
|
||||
const {addRoute, createData} = actions;
|
||||
const {
|
||||
blogPosts,
|
||||
blogPosts: loadedBlogPosts,
|
||||
blogListPaginated,
|
||||
blogTags,
|
||||
blogTagsListPath,
|
||||
|
@ -254,7 +253,7 @@ export default function pluginContentBlog(
|
|||
|
||||
// Create routes for blog entries.
|
||||
await Promise.all(
|
||||
blogPosts.map(async (blogPost) => {
|
||||
loadedBlogPosts.map(async (blogPost) => {
|
||||
const {id, metadata} = blogPost;
|
||||
await createData(
|
||||
// Note that this created data path must be in sync with
|
||||
|
@ -292,12 +291,11 @@ export default function pluginContentBlog(
|
|||
exact: true,
|
||||
modules: {
|
||||
items: items.map((postID) => {
|
||||
const metadata = blogItemsToMetadata[postID];
|
||||
// To tell routes.js this is an import and not a nested object to recurse.
|
||||
return {
|
||||
content: {
|
||||
__import: true,
|
||||
path: metadata.source,
|
||||
path: blogItemsToMetadata[postID].source,
|
||||
query: {
|
||||
truncated: true,
|
||||
},
|
||||
|
@ -481,22 +479,26 @@ export default function pluginContentBlog(
|
|||
};
|
||||
const headTags: HtmlTags = [];
|
||||
|
||||
feedTypes.map((feedType) => {
|
||||
feedTypes.forEach((feedType) => {
|
||||
const feedConfig = feedsConfig[feedType] || {};
|
||||
|
||||
if (!feedsConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {type, path, title} = feedConfig;
|
||||
const {type, path: feedConfigPath, title: feedConfigTitle} = feedConfig;
|
||||
|
||||
headTags.push({
|
||||
tagName: 'link',
|
||||
attributes: {
|
||||
rel: 'alternate',
|
||||
type,
|
||||
href: normalizeUrl([baseUrl, options.routeBasePath, path]),
|
||||
title,
|
||||
href: normalizeUrl([
|
||||
baseUrl,
|
||||
options.routeBasePath,
|
||||
feedConfigPath,
|
||||
]),
|
||||
title: feedConfigTitle,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -170,7 +170,8 @@ describe('simple site', () => {
|
|||
});
|
||||
|
||||
// unrelated frontmatter is not part of metadata
|
||||
expect(data['unrelated_frontmatter']).toBeUndefined();
|
||||
// @ts-expect-error: It doesn't exist, so the test will show it's undefined.
|
||||
expect(data.unrelated_frontmatter).toBeUndefined();
|
||||
});
|
||||
|
||||
test('docs with last update time and author', async () => {
|
||||
|
|
|
@ -14,15 +14,15 @@ import {
|
|||
VERSIONED_SIDEBARS_DIR,
|
||||
} from './constants';
|
||||
|
||||
export function getVersionedDocsDir(siteDir: string) {
|
||||
export function getVersionedDocsDir(siteDir: string): string {
|
||||
return path.join(siteDir, VERSIONED_DOCS_DIR);
|
||||
}
|
||||
|
||||
export function getVersionedSidebarsDir(siteDir: string) {
|
||||
export function getVersionedSidebarsDir(siteDir: string): string {
|
||||
return path.join(siteDir, VERSIONED_SIDEBARS_DIR);
|
||||
}
|
||||
|
||||
export function getVersionsJSONFile(siteDir: string) {
|
||||
export function getVersionsJSONFile(siteDir: string): string {
|
||||
return path.join(siteDir, VERSIONS_JSON_FILE);
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ export default function (siteDir: string): Env {
|
|||
fs.readFileSync(versionsJSONFile, 'utf8'),
|
||||
);
|
||||
if (parsedVersions && parsedVersions.length > 0) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
versioning.latestVersion = parsedVersions[0];
|
||||
versioning.enabled = true;
|
||||
versioning.versions = parsedVersions;
|
||||
|
|
|
@ -378,9 +378,7 @@ Available document ids=
|
|||
}),
|
||||
);
|
||||
|
||||
return routes.sort((a, b) =>
|
||||
a.path > b.path ? 1 : b.path > a.path ? -1 : 0,
|
||||
);
|
||||
return routes.sort((a, b) => a.path.localeCompare(b.path));
|
||||
};
|
||||
|
||||
// This is the base route of the document root (for a doc given version)
|
||||
|
@ -400,10 +398,10 @@ Available document ids=
|
|||
// Important: the layout component should not end with /,
|
||||
// as it conflicts with the home doc
|
||||
// Workaround fix for https://github.com/facebook/docusaurus/issues/2917
|
||||
const path = docsBaseRoute === '/' ? '' : docsBaseRoute;
|
||||
const docsPath = docsBaseRoute === '/' ? '' : docsBaseRoute;
|
||||
|
||||
addRoute({
|
||||
path,
|
||||
path: docsPath,
|
||||
exact: false, // allow matching /docs/* as well
|
||||
component: docLayoutComponent, // main docs component (DocPage)
|
||||
routes, // subroute for each doc
|
||||
|
@ -466,7 +464,7 @@ Available document ids=
|
|||
const routes = await genRoutes(Object.values(content.docsMetadata));
|
||||
const docsBaseMetadata = createDocsBaseMetadata();
|
||||
const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath]);
|
||||
return addBaseRoute(docsBaseRoute, docsBaseMetadata, routes);
|
||||
await addBaseRoute(docsBaseRoute, docsBaseMetadata, routes);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -41,13 +41,12 @@ function inferVersion(
|
|||
.replace(/^version-/, '');
|
||||
if (inferredVersion && versioning.versions.includes(inferredVersion)) {
|
||||
return inferredVersion;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Can't infer version from folder=${dirName}
|
||||
}
|
||||
throw new Error(
|
||||
`Can't infer version from folder=${dirName}
|
||||
Expected versions:
|
||||
- ${versioning.versions.join('- ')}`,
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return 'next';
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ export default function createOrder(allSidebars: Sidebar = {}): Order {
|
|||
case 'doc':
|
||||
ids.push(item.id);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -45,8 +45,12 @@ function normalizeCategoryShorthand(
|
|||
/**
|
||||
* Check that item contains only allowed keys.
|
||||
*/
|
||||
function assertItem(item: Object, keys: string[]): void {
|
||||
function assertItem<K extends string>(
|
||||
item: any,
|
||||
keys: K[],
|
||||
): asserts item is Record<K, any> {
|
||||
const unknownKeys = Object.keys(item).filter(
|
||||
// @ts-expect-error: key is always string
|
||||
(key) => !keys.includes(key) && key !== 'type',
|
||||
);
|
||||
|
||||
|
@ -59,7 +63,9 @@ function assertItem(item: Object, keys: string[]): void {
|
|||
}
|
||||
}
|
||||
|
||||
function assertIsCategory(item: any): asserts item is SidebarItemCategoryRaw {
|
||||
function assertIsCategory(
|
||||
item: unknown,
|
||||
): asserts item is SidebarItemCategoryRaw {
|
||||
assertItem(item, ['items', 'label', 'collapsed']);
|
||||
if (typeof item.label !== 'string') {
|
||||
throw new Error(
|
||||
|
@ -79,7 +85,7 @@ function assertIsCategory(item: any): asserts item is SidebarItemCategoryRaw {
|
|||
}
|
||||
}
|
||||
|
||||
function assertIsDoc(item: any): asserts item is SidebarItemDoc {
|
||||
function assertIsDoc(item: unknown): asserts item is SidebarItemDoc {
|
||||
assertItem(item, ['id']);
|
||||
if (typeof item.id !== 'string') {
|
||||
throw new Error(
|
||||
|
@ -88,7 +94,7 @@ function assertIsDoc(item: any): asserts item is SidebarItemDoc {
|
|||
}
|
||||
}
|
||||
|
||||
function assertIsLink(item: any): asserts item is SidebarItemLink {
|
||||
function assertIsLink(item: unknown): asserts item is SidebarItemLink {
|
||||
assertItem(item, ['href', 'label']);
|
||||
if (typeof item.href !== 'string') {
|
||||
throw new Error(
|
||||
|
@ -175,7 +181,7 @@ export default function loadSidebars(sidebarPaths?: string[]): Sidebar {
|
|||
return {} as Sidebar;
|
||||
}
|
||||
|
||||
sidebarPaths.map((sidebarPath) => {
|
||||
sidebarPaths.forEach((sidebarPath) => {
|
||||
if (sidebarPath && fs.existsSync(sidebarPath)) {
|
||||
const sidebar = importFresh(sidebarPath) as SidebarRaw;
|
||||
Object.assign(allSidebars, sidebar);
|
||||
|
|
|
@ -5,13 +5,20 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
let versions: string[] = [];
|
||||
let versions: string[];
|
||||
|
||||
try {
|
||||
// eslint-disable-next-line global-require
|
||||
versions = require('@site/versions.json');
|
||||
} catch (e) {}
|
||||
} catch {
|
||||
versions = [];
|
||||
}
|
||||
|
||||
function useVersioning() {
|
||||
function useVersioning(): {
|
||||
versioningEnabled: boolean;
|
||||
versions: string[];
|
||||
latestVersion: string;
|
||||
} {
|
||||
return {
|
||||
versioningEnabled: versions.length > 0,
|
||||
versions,
|
||||
|
|
|
@ -65,7 +65,7 @@ export type SidebarItemRaw =
|
|||
| SidebarItemCategoryRaw
|
||||
| {
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export interface SidebarCategoryShorthandRaw {
|
||||
|
|
|
@ -15,6 +15,8 @@ import path from 'path';
|
|||
import {Sidebar, PathOptions, SidebarItem} from './types';
|
||||
import loadSidebars from './sidebars';
|
||||
|
||||
// Tests depend on non-default export for mocking.
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function docsVersion(
|
||||
version: string | null | undefined,
|
||||
siteDir: string,
|
||||
|
|
|
@ -4,13 +4,16 @@
|
|||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import {LoadContext} from '@docusaurus/types';
|
||||
import {LoadContext, Plugin} from '@docusaurus/types';
|
||||
import {PluginOptions} from './types';
|
||||
import {Configuration} from 'webpack';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
export default function (_context: LoadContext, options: PluginOptions) {
|
||||
export default function (
|
||||
_context: LoadContext,
|
||||
options: PluginOptions,
|
||||
): Plugin<void> {
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
return {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@docusaurus/types": "^2.0.0-alpha.58",
|
||||
"fs-extra": "^8.1.0",
|
||||
"sitemap": "^3.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
|
@ -28,7 +28,7 @@ describe('createSitemap', () => {
|
|||
|
||||
test('empty site', () => {
|
||||
expect(() => {
|
||||
createSitemap({} as DocusaurusConfig, [], {} as any);
|
||||
createSitemap({} as DocusaurusConfig, [], {});
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
`"url in docusaurus.config.js cannot be empty/undefined"`,
|
||||
);
|
||||
|
|
|
@ -13,7 +13,7 @@ export default function createSitemap(
|
|||
siteConfig: DocusaurusConfig,
|
||||
routesPaths: string[],
|
||||
options: PluginOptions,
|
||||
) {
|
||||
): sitemap.Sitemap {
|
||||
const {url: hostname} = siteConfig;
|
||||
if (!hostname) {
|
||||
throw new Error('url in docusaurus.config.js cannot be empty/undefined');
|
||||
|
|
|
@ -11,7 +11,7 @@ import {PluginOptions} from './types';
|
|||
import createSitemap from './createSitemap';
|
||||
import {LoadContext, Props, Plugin} from '@docusaurus/types';
|
||||
|
||||
const DEFAULT_OPTIONS: PluginOptions = {
|
||||
const DEFAULT_OPTIONS: Required<PluginOptions> = {
|
||||
cacheTime: 600 * 1000, // 600 sec - cache purge period.
|
||||
changefreq: 'weekly',
|
||||
priority: 0.5,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
export interface PluginOptions {
|
||||
cacheTime: number;
|
||||
changefreq: string;
|
||||
priority: number;
|
||||
cacheTime?: number;
|
||||
changefreq?: string;
|
||||
priority?: number;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ function Footer() {
|
|||
<li
|
||||
key={key}
|
||||
className="mb-2"
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: item.html,
|
||||
}}
|
||||
|
|
|
@ -32,6 +32,8 @@ function AnnouncementBar() {
|
|||
role="banner">
|
||||
<div
|
||||
className={styles.announcementBarContent}
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{__html: content}}
|
||||
/>
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ function Headings({headings, isChild}) {
|
|||
<a
|
||||
href={`#${heading.id}`}
|
||||
className={LINK_CLASS_NAME}
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{__html: heading.value}}
|
||||
/>
|
||||
<Headings isChild headings={heading.children} />
|
||||
|
|
|
@ -74,6 +74,8 @@ function Footer() {
|
|||
<li
|
||||
key={key}
|
||||
className="footer__item"
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: item.html,
|
||||
}}
|
||||
|
@ -109,6 +111,8 @@ function Footer() {
|
|||
)}
|
||||
|
||||
<div
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: copyright,
|
||||
}}
|
||||
|
|
|
@ -323,6 +323,8 @@ function Search() {
|
|||
{breadcrumbs.length > 0 && (
|
||||
<span
|
||||
className={styles.searchResultItemPath}
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: breadcrumbs.join(' › '),
|
||||
}}
|
||||
|
@ -332,6 +334,8 @@ function Search() {
|
|||
{summary && (
|
||||
<p
|
||||
className={styles.searchResultItemSummary}
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{__html: summary}}
|
||||
/>
|
||||
)}
|
||||
|
|
32
packages/docusaurus-types/src/index.d.ts
vendored
32
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -22,23 +22,23 @@ export interface DocusaurusConfig {
|
|||
themes?: PluginConfig[];
|
||||
presets?: PresetConfig[];
|
||||
themeConfig?: {
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
customFields?: {
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
scripts?: (
|
||||
| string
|
||||
| {
|
||||
src: string;
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
)[];
|
||||
stylesheets?: (
|
||||
| string
|
||||
| {
|
||||
href: string;
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
)[];
|
||||
}
|
||||
|
@ -53,7 +53,10 @@ export interface Preset {
|
|||
themes?: PluginConfig[];
|
||||
}
|
||||
|
||||
export type PresetConfig = [string, Object] | [string] | string;
|
||||
export type PresetConfig =
|
||||
| [string, Record<string, unknown>]
|
||||
| [string]
|
||||
| string;
|
||||
|
||||
export interface StartCLIOptions {
|
||||
port: string;
|
||||
|
@ -88,7 +91,7 @@ export type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[];
|
|||
|
||||
export interface Props extends LoadContext, InjectedHtmlTags {
|
||||
routesPaths: string[];
|
||||
plugins: Plugin<any>[];
|
||||
plugins: Plugin<unknown>[];
|
||||
}
|
||||
|
||||
export interface PluginContentLoadedActions {
|
||||
|
@ -125,7 +128,10 @@ export interface Plugin<T> {
|
|||
};
|
||||
}
|
||||
|
||||
export type PluginConfig = [string, Object] | [string] | string;
|
||||
export type PluginConfig =
|
||||
| [string, Record<string, unknown>]
|
||||
| [string]
|
||||
| string;
|
||||
|
||||
export interface ChunkRegistry {
|
||||
loader: string;
|
||||
|
@ -165,11 +171,17 @@ export interface ConfigureWebpackUtils {
|
|||
getStyleLoaders: (
|
||||
isServer: boolean,
|
||||
cssOptions: {
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
},
|
||||
) => Loader[];
|
||||
getCacheLoader: (isServer: boolean, cacheOptions?: {}) => Loader | null;
|
||||
getBabelLoader: (isServer: boolean, babelOptions?: {}) => Loader;
|
||||
getCacheLoader: (
|
||||
isServer: boolean,
|
||||
cacheOptions?: Record<string, unknown>,
|
||||
) => Loader | null;
|
||||
getBabelLoader: (
|
||||
isServer: boolean,
|
||||
babelOptions?: Record<string, unknown>,
|
||||
) => Loader;
|
||||
}
|
||||
|
||||
interface HtmlTagObject {
|
||||
|
|
|
@ -160,6 +160,8 @@ export function genChunkName(
|
|||
return chunkName;
|
||||
}
|
||||
|
||||
// Too dynamic
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
||||
export function idx(target: any, keyPaths?: string | (string | number)[]): any {
|
||||
return (
|
||||
target &&
|
||||
|
@ -231,13 +233,15 @@ export function createExcerpt(fileString: string): string | undefined {
|
|||
|
||||
type ParsedMarkdown = {
|
||||
frontMatter: {
|
||||
// Returned by gray-matter
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
};
|
||||
content: string;
|
||||
excerpt: string | undefined;
|
||||
};
|
||||
export function parseMarkdownString(markdownString: string): ParsedMarkdown {
|
||||
const options: {} = {
|
||||
const options: Record<string, unknown> = {
|
||||
excerpt: (file: matter.GrayMatterFile<string>): void => {
|
||||
// Hacky way of stripping out import statements from the excerpt
|
||||
// TODO: Find a better way to do so, possibly by compiling the Markdown content,
|
||||
|
|
|
@ -50,7 +50,7 @@ function getTransformOptions(isServer: boolean): TransformOptions {
|
|||
// By default, it assumes @babel/runtime@7.0.0. Since we use >7.0.0, better to
|
||||
// explicitly specify the version so that it can reuse the helper better
|
||||
// See https://github.com/babel/babel/issues/10261
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
||||
version: require('@babel/runtime/package.json').version,
|
||||
regenerator: true,
|
||||
useESModules: true,
|
||||
|
|
|
@ -28,7 +28,7 @@ interface State {
|
|||
|
||||
class PendingNavigation extends React.Component<Props, State> {
|
||||
previousLocation: any;
|
||||
progressBarTimeout: any;
|
||||
progressBarTimeout: NodeJS.Timeout | null;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
@ -43,7 +43,7 @@ class PendingNavigation extends React.Component<Props, State> {
|
|||
|
||||
// Intercept location update and still show current route until next route
|
||||
// is done loading.
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
shouldComponentUpdate(nextProps: Props, nextState: State) {
|
||||
const routeDidChange = nextProps.location !== this.props.location;
|
||||
const {routes, delay = 1000} = this.props;
|
||||
|
||||
|
|
|
@ -5,9 +5,20 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// too dynamic
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import clientModules from '@generated/client-modules';
|
||||
|
||||
function dispatchLifecycleAction(lifecycleAction, ...args) {
|
||||
interface Dispatchers {
|
||||
onRouteUpdate: (...args: any) => void;
|
||||
onRouteUpdateDelayed: (...args: any) => void;
|
||||
}
|
||||
|
||||
function dispatchLifecycleAction(
|
||||
lifecycleAction: keyof Dispatchers,
|
||||
...args: any[]
|
||||
) {
|
||||
clientModules.forEach((clientModule) => {
|
||||
const mod = clientModule.__esModule ? clientModule.default : clientModule;
|
||||
if (mod && mod[lifecycleAction]) {
|
||||
|
@ -16,26 +27,13 @@ function dispatchLifecycleAction(lifecycleAction, ...args) {
|
|||
});
|
||||
}
|
||||
|
||||
interface Dispatchers {
|
||||
onRouteUpdate: Function;
|
||||
onRouteUpdateDelayed: Function;
|
||||
}
|
||||
const clientLifecyclesDispatchers: Dispatchers = {
|
||||
onRouteUpdate(...args) {
|
||||
dispatchLifecycleAction('onRouteUpdate', ...args);
|
||||
},
|
||||
onRouteUpdateDelayed(...args) {
|
||||
dispatchLifecycleAction('onRouteUpdateDelayed', ...args);
|
||||
},
|
||||
};
|
||||
|
||||
function createLifecyclesDispatcher(): Dispatchers {
|
||||
// TODO: Not sure whether it's better to declare an explicit object
|
||||
// with all the lifecycles. It's better for typing but quite verbose.
|
||||
// On the other hand, there's some runtime cost generating this object
|
||||
// on initial load.
|
||||
return ['onRouteUpdate', 'onRouteUpdateDelayed'].reduce(
|
||||
(lifecycles, lifecycleAction) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
lifecycles[lifecycleAction] = function (...args) {
|
||||
dispatchLifecycleAction(lifecycleAction, ...args);
|
||||
};
|
||||
return lifecycles;
|
||||
},
|
||||
{},
|
||||
) as Dispatchers;
|
||||
}
|
||||
|
||||
export default createLifecyclesDispatcher();
|
||||
export default clientLifecyclesDispatchers;
|
||||
|
|
|
@ -17,7 +17,7 @@ import docusaurus from './docusaurus';
|
|||
|
||||
declare global {
|
||||
interface NodeModule {
|
||||
hot?: any;
|
||||
hot?: {accept: () => void};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ const fetched = {};
|
|||
const loaded = {};
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line camelcase
|
||||
const __webpack_require__: any;
|
||||
// eslint-disable-next-line camelcase, @typescript-eslint/no-explicit-any
|
||||
const __webpack_require__: {gca: (name: string) => string};
|
||||
interface Navigator {
|
||||
connection: any;
|
||||
}
|
||||
|
@ -35,13 +35,14 @@ const isSlowConnection = () => {
|
|||
return false;
|
||||
};
|
||||
|
||||
const canPrefetch = (routePath) =>
|
||||
const canPrefetch = (routePath: string) =>
|
||||
!isSlowConnection() && !loaded[routePath] && !fetched[routePath];
|
||||
|
||||
const canPreload = (routePath) => !isSlowConnection() && !loaded[routePath];
|
||||
const canPreload = (routePath: string) =>
|
||||
!isSlowConnection() && !loaded[routePath];
|
||||
|
||||
const docusaurus = {
|
||||
prefetch: (routePath) => {
|
||||
prefetch: (routePath: string): boolean => {
|
||||
if (!canPrefetch(routePath)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -50,13 +51,13 @@ const docusaurus = {
|
|||
|
||||
// Find all webpack chunk names needed.
|
||||
const matches = matchRoutes(routes, routePath);
|
||||
const chunkNamesNeeded = matches.reduce((arr, match) => {
|
||||
const chunk = routesChunkNames[match.route.path];
|
||||
const chunkNamesNeeded = matches.reduce((arr: string[], match) => {
|
||||
const chunk = routesChunkNames[match.route.path as string];
|
||||
if (!chunk) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
const chunkNames = Object.values(flat(chunk));
|
||||
const chunkNames = Object.values(flat(chunk)) as string[];
|
||||
return arr.concat(chunkNames);
|
||||
}, []);
|
||||
|
||||
|
@ -77,7 +78,7 @@ const docusaurus = {
|
|||
return true;
|
||||
},
|
||||
|
||||
preload: (routePath) => {
|
||||
preload: (routePath: string): boolean => {
|
||||
if (!canPreload(routePath)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,15 @@
|
|||
import React from 'react';
|
||||
import ExecutionEnvironment from './ExecutionEnvironment';
|
||||
|
||||
function BrowserOnly({children, fallback}) {
|
||||
function BrowserOnly({
|
||||
children,
|
||||
fallback,
|
||||
}: {
|
||||
children?: () => JSX.Element;
|
||||
fallback?: JSX.Element;
|
||||
}): JSX.Element | undefined {
|
||||
if (!ExecutionEnvironment.canUseDOM || children == null) {
|
||||
return fallback || null;
|
||||
return fallback || undefined;
|
||||
}
|
||||
|
||||
return <>{children()}</>;
|
||||
|
|
|
@ -12,7 +12,7 @@ import routesChunkNames from '@generated/routesChunkNames';
|
|||
import registry from '@generated/registry';
|
||||
import flat from '../flat';
|
||||
|
||||
function ComponentCreator(path: string) {
|
||||
function ComponentCreator(path: string): ReturnType<typeof Loadable> {
|
||||
// 404 page
|
||||
if (path === '*') {
|
||||
return Loadable({
|
||||
|
|
|
@ -15,7 +15,8 @@ const ExecutionEnvironment = {
|
|||
canUseDOM,
|
||||
|
||||
canUseEventListeners:
|
||||
// @ts-ignore
|
||||
// @ts-expect-error: window.attachEvent is IE specific.
|
||||
// See https://github.com/Microsoft/TypeScript/issues/3953#issuecomment-123396830
|
||||
canUseDOM && !!(window.addEventListener || window.attachEvent),
|
||||
|
||||
canUseIntersectionObserver: canUseDOM && 'IntersectionObserver' in window,
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {Helmet} from 'react-helmet';
|
||||
import {Helmet, HelmetProps} from 'react-helmet';
|
||||
|
||||
function Head(props): JSX.Element {
|
||||
function Head(props: HelmetProps): JSX.Element {
|
||||
return <Helmet {...props} />;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useEffect, useRef} from 'react';
|
||||
import React, {ReactNode, useEffect, useRef} from 'react';
|
||||
|
||||
import {NavLink, Link as RRLink} from 'react-router-dom';
|
||||
import isInternalUrl from './isInternalUrl';
|
||||
|
@ -21,6 +21,7 @@ interface Props {
|
|||
readonly isNavLink?: boolean;
|
||||
readonly to?: string;
|
||||
readonly href: string;
|
||||
readonly children?: ReactNode;
|
||||
}
|
||||
|
||||
function Link({isNavLink, ...props}: Props): JSX.Element {
|
||||
|
@ -85,6 +86,7 @@ function Link({isNavLink, ...props}: Props): JSX.Element {
|
|||
return !targetLink || !isInternal || targetLink.startsWith('#') ? (
|
||||
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
||||
<a
|
||||
// @ts-expect-error: href specified twice needed to pass children and other user specified props
|
||||
href={targetLink}
|
||||
{...(!isInternal && {target: '_blank', rel: 'noopener noreferrer'})}
|
||||
{...props}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
function flat(target) {
|
||||
// Too dynamic
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function flat(target: unknown): any {
|
||||
const delimiter = '.';
|
||||
const output = {};
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Memoize previously normalized pathnames.
|
||||
const pathnames = {};
|
||||
type Location = {pathname: string};
|
||||
|
||||
function normalizeLocation(location) {
|
||||
// Memoize previously normalized pathnames.
|
||||
const pathnames: Record<string, string> = {};
|
||||
|
||||
function normalizeLocation<T extends Location>(location: T): T {
|
||||
if (pathnames[location.pathname]) {
|
||||
return {
|
||||
...location,
|
||||
|
|
|
@ -5,24 +5,29 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {matchRoutes} from 'react-router-config';
|
||||
import {matchRoutes, RouteConfig} from 'react-router-config';
|
||||
|
||||
/**
|
||||
* Helper function to make sure all async components for that particular route
|
||||
* is preloaded before rendering. This is especially useful to avoid loading screens.
|
||||
*
|
||||
* @param {Array<RouteConfig>} routes react-router-config
|
||||
* @param {string} pathname the route pathname, example: /docs/installation
|
||||
* @returns {Promise} Promise object represents whether pathname has been preloaded
|
||||
* @param routes react-router-config
|
||||
* @param pathname the route pathname, example: /docs/installation
|
||||
* @returns Promise object represents whether pathname has been preloaded
|
||||
*/
|
||||
export default function preload(routes, pathname: string) {
|
||||
export default function preload(
|
||||
routes: RouteConfig[],
|
||||
pathname: string,
|
||||
): Promise<void[]> {
|
||||
const matches = matchRoutes(routes, pathname);
|
||||
|
||||
return Promise.all(
|
||||
matches.map((match) => {
|
||||
const {component} = match.route;
|
||||
|
||||
// @ts-expect-error: ComponentCreator injected this method.
|
||||
if (component && component.preload) {
|
||||
// @ts-expect-error: checked above.
|
||||
return component.preload();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@ import merge from 'webpack-merge';
|
|||
import {STATIC_DIR_NAME} from '../constants';
|
||||
import {load} from '../server';
|
||||
import {BuildCLIOptions, Props} from '@docusaurus/types';
|
||||
import {createClientConfig} from '../webpack/client';
|
||||
import {createServerConfig} from '../webpack/server';
|
||||
import createClientConfig from '../webpack/client';
|
||||
import createServerConfig from '../webpack/server';
|
||||
import {applyConfigureWebpack} from '../webpack/utils';
|
||||
import CleanWebpackPlugin from '../webpack/plugins/CleanWebpackPlugin';
|
||||
|
||||
function compile(config: Configuration[]): Promise<any> {
|
||||
function compile(config: Configuration[]): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const compiler = webpack(config);
|
||||
compiler.run((err, stats) => {
|
||||
|
@ -55,7 +55,7 @@ function compile(config: Configuration[]): Promise<any> {
|
|||
});
|
||||
}
|
||||
|
||||
export async function build(
|
||||
export default async function build(
|
||||
siteDir: string,
|
||||
cliOptions: Partial<BuildCLIOptions> = {},
|
||||
forceTerminate: boolean = true,
|
||||
|
|
|
@ -10,11 +10,11 @@ import path from 'path';
|
|||
import shell from 'shelljs';
|
||||
import {CONFIG_FILE_NAME, GENERATED_FILES_DIR_NAME} from '../constants';
|
||||
import {loadContext} from '../server';
|
||||
import {loadConfig} from '../server/config';
|
||||
import {build} from './build';
|
||||
import loadConfig from '../server/config';
|
||||
import build from './build';
|
||||
import {BuildCLIOptions} from '@docusaurus/types';
|
||||
|
||||
export async function deploy(
|
||||
export default async function deploy(
|
||||
siteDir: string,
|
||||
cliOptions: Partial<BuildCLIOptions> = {},
|
||||
): Promise<void> {
|
||||
|
@ -98,7 +98,7 @@ export async function deploy(
|
|||
// out to deployment branch.
|
||||
const currentCommit = shell.exec('git rev-parse HEAD').stdout.trim();
|
||||
|
||||
const runDeploy = (outDir) => {
|
||||
const runDeploy = (outputDirectory) => {
|
||||
if (shell.cd(tempDir).code !== 0) {
|
||||
throw new Error(
|
||||
`Temp dir ${GENERATED_FILES_DIR_NAME} does not exists. Run build website first.`,
|
||||
|
@ -141,7 +141,7 @@ export async function deploy(
|
|||
|
||||
shell.cd('../..');
|
||||
|
||||
const fromPath = outDir;
|
||||
const fromPath = outputDirectory;
|
||||
const toPath = path.join(
|
||||
GENERATED_FILES_DIR_NAME,
|
||||
`${projectName}-${deploymentBranch}`,
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
|
||||
import {CommanderStatic} from 'commander';
|
||||
import {loadContext, loadPluginConfigs} from '../server';
|
||||
import {initPlugins} from '../server/plugins/init';
|
||||
import initPlugins from '../server/plugins/init';
|
||||
|
||||
export function externalCommand(cli: CommanderStatic, siteDir: string): void {
|
||||
export default function externalCommand(
|
||||
cli: CommanderStatic,
|
||||
siteDir: string,
|
||||
): void {
|
||||
const context = loadContext(siteDir);
|
||||
const pluginConfigs = loadPluginConfigs(context);
|
||||
const plugins = initPlugins({pluginConfigs, context});
|
||||
|
|
|
@ -23,7 +23,7 @@ import HotModuleReplacementPlugin from 'webpack/lib/HotModuleReplacementPlugin';
|
|||
import {load} from '../server';
|
||||
import {StartCLIOptions} from '@docusaurus/types';
|
||||
import {CONFIG_FILE_NAME, STATIC_DIR_NAME, DEFAULT_PORT} from '../constants';
|
||||
import {createClientConfig} from '../webpack/client';
|
||||
import createClientConfig from '../webpack/client';
|
||||
import {applyConfigureWebpack} from '../webpack/utils';
|
||||
|
||||
function getHost(reqHost: string | undefined): string {
|
||||
|
@ -36,7 +36,7 @@ async function getPort(reqPort: string | undefined): Promise<number> {
|
|||
return port;
|
||||
}
|
||||
|
||||
export async function start(
|
||||
export default async function start(
|
||||
siteDir: string,
|
||||
cliOptions: Partial<StartCLIOptions> = {},
|
||||
): Promise<void> {
|
||||
|
@ -65,9 +65,7 @@ export async function start(
|
|||
const pluginPaths: string[] = ([] as string[])
|
||||
.concat(
|
||||
...plugins
|
||||
.map<any>(
|
||||
(plugin) => plugin.getPathsToWatch && plugin.getPathsToWatch(),
|
||||
)
|
||||
.map((plugin) => plugin.getPathsToWatch?.() ?? [])
|
||||
.filter(Boolean),
|
||||
)
|
||||
.map(normalizeToSiteDir);
|
||||
|
@ -172,7 +170,9 @@ export async function start(
|
|||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
cliOptions.open && openBrowser(openUrl);
|
||||
if (cliOptions.open) {
|
||||
openBrowser(openUrl);
|
||||
}
|
||||
});
|
||||
['SIGINT', 'SIGTERM'].forEach((sig) => {
|
||||
process.on(sig as NodeJS.Signals, () => {
|
||||
|
|
|
@ -9,19 +9,22 @@ import chalk = require('chalk');
|
|||
import fs from 'fs-extra';
|
||||
import importFresh from 'import-fresh';
|
||||
import path from 'path';
|
||||
import {Plugin, LoadContext} from '@docusaurus/types';
|
||||
|
||||
import {THEME_PATH} from '../constants';
|
||||
import {loadContext} from '../server';
|
||||
|
||||
export async function swizzle(
|
||||
export default async function swizzle(
|
||||
siteDir: string,
|
||||
themeName: string,
|
||||
componentName?: string,
|
||||
): Promise<void> {
|
||||
const plugin: any = importFresh(themeName);
|
||||
const plugin = importFresh(themeName) as (
|
||||
context: LoadContext,
|
||||
) => Plugin<unknown>;
|
||||
const context = loadContext(siteDir);
|
||||
const pluginInstance = plugin(context);
|
||||
let fromPath = pluginInstance.getThemePath();
|
||||
let fromPath = pluginInstance.getThemePath?.();
|
||||
|
||||
if (fromPath) {
|
||||
let toPath = path.resolve(siteDir, THEME_PATH);
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export {build} from './commands/build';
|
||||
export {start} from './commands/start';
|
||||
export {swizzle} from './commands/swizzle';
|
||||
export {deploy} from './commands/deploy';
|
||||
export {externalCommand} from './commands/external';
|
||||
export {default as build} from './commands/build';
|
||||
export {default as start} from './commands/start';
|
||||
export {default as swizzle} from './commands/swizzle';
|
||||
export {default as deploy} from './commands/deploy';
|
||||
export {default as externalCommand} from './commands/external';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import path from 'path';
|
||||
import {loadConfig} from '../config';
|
||||
import loadConfig from '../config';
|
||||
|
||||
describe('loadConfig', () => {
|
||||
test('website with valid siteConfig', async () => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {loadRoutes} from '../routes';
|
||||
import loadRoutes from '../routes';
|
||||
import {RouteConfig} from '@docusaurus/types';
|
||||
|
||||
describe('loadRoutes', () => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {loadClientModules} from '../index';
|
||||
import loadClientModules from '../index';
|
||||
|
||||
import pluginEmpty from './__fixtures__/plugin-empty';
|
||||
import pluginFooBar from './__fixtures__/plugin-foo-bar';
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
import {Plugin} from '@docusaurus/types';
|
||||
|
||||
export function loadClientModules(plugins: Plugin<unknown>[]): string[] {
|
||||
export default function loadClientModules(
|
||||
plugins: Plugin<unknown>[],
|
||||
): string[] {
|
||||
return ([] as string[]).concat(
|
||||
...plugins
|
||||
.map<any>(
|
||||
(plugin) => plugin.getClientModules && plugin.getClientModules(),
|
||||
)
|
||||
.map((plugin) => plugin.getClientModules?.() ?? [])
|
||||
.filter(Boolean),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ function formatFields(fields: string[]): string {
|
|||
return fields.map((field) => `'${field}'`).join(', ');
|
||||
}
|
||||
|
||||
export function loadConfig(siteDir: string): DocusaurusConfig {
|
||||
export default function loadConfig(siteDir: string): DocusaurusConfig {
|
||||
const configPath = path.resolve(siteDir, CONFIG_FILE_NAME);
|
||||
|
||||
if (!fs.existsSync(configPath)) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {htmlTagObjectToString} from '../htmlTags';
|
||||
import htmlTagObjectToString from '../htmlTags';
|
||||
|
||||
describe('htmlTagObjectToString', () => {
|
||||
test('simple html tag', () => {
|
||||
|
|
|
@ -10,10 +10,11 @@ import {HtmlTagObject} from '@docusaurus/types';
|
|||
import htmlTags from 'html-tags';
|
||||
import voidHtmlTags from 'html-tags/void';
|
||||
|
||||
function assertIsHtmlTagObject(val: any): asserts val is HtmlTagObject {
|
||||
function assertIsHtmlTagObject(val: unknown): asserts val is HtmlTagObject {
|
||||
if (!isPlainObject(val)) {
|
||||
throw new Error(`"${val}" is not a valid HTML tag object`);
|
||||
}
|
||||
// @ts-expect-error: If tagName doesn't exist, it will throw.
|
||||
if (typeof val.tagName !== 'string') {
|
||||
throw new Error(
|
||||
`${JSON.stringify(
|
||||
|
@ -23,7 +24,7 @@ function assertIsHtmlTagObject(val: any): asserts val is HtmlTagObject {
|
|||
}
|
||||
}
|
||||
|
||||
export function htmlTagObjectToString(tagDefinition: unknown): string {
|
||||
export default function htmlTagObjectToString(tagDefinition: unknown): string {
|
||||
assertIsHtmlTagObject(tagDefinition);
|
||||
if (htmlTags.indexOf(tagDefinition.tagName) === -1) {
|
||||
throw new Error(
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {htmlTagObjectToString} from './htmlTags';
|
||||
import htmlTagObjectToString from './htmlTags';
|
||||
import {
|
||||
Plugin,
|
||||
InjectedHtmlTags,
|
||||
|
@ -21,7 +21,7 @@ export function createHtmlTagsString(tags: HtmlTags): string {
|
|||
return Array.isArray(tags) ? tags.map(toString).join('\n') : toString(tags);
|
||||
}
|
||||
|
||||
export function loadHtmlTags(plugins: Plugin<any>[]): InjectedHtmlTags {
|
||||
export function loadHtmlTags(plugins: Plugin<unknown>[]): InjectedHtmlTags {
|
||||
const htmlTags = plugins.reduce(
|
||||
(acc, plugin) => {
|
||||
if (!plugin.injectHtmlTags) {
|
||||
|
|
|
@ -13,12 +13,12 @@ import {
|
|||
GENERATED_FILES_DIR_NAME,
|
||||
THEME_PATH,
|
||||
} from '../constants';
|
||||
import {loadClientModules} from './client-modules';
|
||||
import {loadConfig} from './config';
|
||||
import loadClientModules from './client-modules';
|
||||
import loadConfig from './config';
|
||||
import {loadPlugins} from './plugins';
|
||||
import {loadPresets} from './presets';
|
||||
import {loadRoutes} from './routes';
|
||||
import {loadThemeAlias} from './themes';
|
||||
import loadPresets from './presets';
|
||||
import loadRoutes from './routes';
|
||||
import loadThemeAlias from './themes';
|
||||
import {
|
||||
DocusaurusConfig,
|
||||
LoadContext,
|
||||
|
@ -84,11 +84,9 @@ export async function load(
|
|||
|
||||
// Themes.
|
||||
const fallbackTheme = path.resolve(__dirname, '../client/theme-fallback');
|
||||
const pluginThemes = ([] as string[]).concat(
|
||||
...plugins
|
||||
.map<any>((plugin) => plugin.getThemePath && plugin.getThemePath())
|
||||
.filter(Boolean),
|
||||
);
|
||||
const pluginThemes: string[] = plugins
|
||||
.map((plugin) => plugin.getThemePath && plugin.getThemePath())
|
||||
.filter((x): x is string => Boolean(x));
|
||||
const userTheme = path.resolve(siteDir, THEME_PATH);
|
||||
const alias = loadThemeAlias([fallbackTheme, ...pluginThemes], [userTheme]);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {load} from './index';
|
|||
import {Props} from '@docusaurus/types';
|
||||
|
||||
// Helper methods to setup dummy/fake projects.
|
||||
export const loadSetup = async (name: string): Promise<Props> => {
|
||||
const loadSetup = async (name: string): Promise<Props> => {
|
||||
const fixtures = path.join(__dirname, '__tests__', '__fixtures__');
|
||||
const simpleSite = path.join(fixtures, 'simple-site');
|
||||
const customSite = path.join(fixtures, 'custom-site');
|
||||
|
@ -23,3 +23,5 @@ export const loadSetup = async (name: string): Promise<Props> => {
|
|||
return load(simpleSite);
|
||||
}
|
||||
};
|
||||
|
||||
export default loadSetup;
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
PluginContentLoadedActions,
|
||||
RouteConfig,
|
||||
} from '@docusaurus/types';
|
||||
import {initPlugins} from './init';
|
||||
import initPlugins from './init';
|
||||
|
||||
export function sortConfig(routeConfigs: RouteConfig[]): void {
|
||||
// Sort the route config. This ensures that route with nested
|
||||
|
@ -31,20 +31,18 @@ export function sortConfig(routeConfigs: RouteConfig[]): void {
|
|||
if (a.priority || b.priority) {
|
||||
const priorityA = a.priority || 0;
|
||||
const priorityB = b.priority || 0;
|
||||
const score = priorityA > priorityB ? -1 : priorityB > priorityA ? 1 : 0;
|
||||
const score = priorityB - priorityA;
|
||||
|
||||
if (score !== 0) {
|
||||
return score;
|
||||
}
|
||||
}
|
||||
|
||||
return a.path > b.path ? 1 : b.path > a.path ? -1 : 0;
|
||||
return a.path.localeCompare(b.path);
|
||||
});
|
||||
|
||||
routeConfigs.forEach((routeConfig) => {
|
||||
routeConfig.routes?.sort((a, b) => {
|
||||
return a.path > b.path ? 1 : b.path > a.path ? -1 : 0;
|
||||
});
|
||||
routeConfig.routes?.sort((a, b) => a.path.localeCompare(b.path));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@ import importFresh from 'import-fresh';
|
|||
import {LoadContext, Plugin, PluginConfig} from '@docusaurus/types';
|
||||
import {CONFIG_FILE_NAME} from '../../constants';
|
||||
|
||||
export function initPlugins({
|
||||
export default function initPlugins({
|
||||
pluginConfigs,
|
||||
context,
|
||||
}: {
|
||||
pluginConfigs: PluginConfig[];
|
||||
context: LoadContext;
|
||||
}): Plugin<any>[] {
|
||||
}): Plugin<unknown>[] {
|
||||
// We need to resolve plugins from the perspective of the siteDir, since the siteDir's package.json
|
||||
// declares the dependency on these plugins.
|
||||
// We need to fallback to createRequireFromPath since createRequire is only available in node v12.
|
||||
|
@ -25,7 +25,7 @@ export function initPlugins({
|
|||
const createRequire = Module.createRequire || Module.createRequireFromPath;
|
||||
const pluginRequire = createRequire(join(context.siteDir, CONFIG_FILE_NAME));
|
||||
|
||||
const plugins: Plugin<any>[] = pluginConfigs
|
||||
const plugins: Plugin<unknown>[] = pluginConfigs
|
||||
.map((pluginItem) => {
|
||||
let pluginModuleImport: string | undefined;
|
||||
let pluginOptions = {};
|
||||
|
@ -37,8 +37,7 @@ export function initPlugins({
|
|||
if (typeof pluginItem === 'string') {
|
||||
pluginModuleImport = pluginItem;
|
||||
} else if (Array.isArray(pluginItem)) {
|
||||
pluginModuleImport = pluginItem[0];
|
||||
pluginOptions = pluginItem[1] || {};
|
||||
[pluginModuleImport, pluginOptions = {}] = pluginItem;
|
||||
}
|
||||
|
||||
if (!pluginModuleImport) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import path from 'path';
|
||||
|
||||
import {loadPresets} from '../index';
|
||||
import loadPresets from '../index';
|
||||
import {LoadContext} from '@docusaurus/types';
|
||||
|
||||
describe('loadPresets', () => {
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
PresetConfig,
|
||||
} from '@docusaurus/types';
|
||||
|
||||
export function loadPresets(
|
||||
export default function loadPresets(
|
||||
context: LoadContext,
|
||||
): {
|
||||
plugins: PluginConfig[];
|
||||
|
|
|
@ -36,10 +36,21 @@ function getModulePath(target: Module): string {
|
|||
return `${target.path}${queryStr}`;
|
||||
}
|
||||
|
||||
export async function loadRoutes(
|
||||
type LoadedRoutes = {
|
||||
registry: {
|
||||
[chunkName: string]: ChunkRegistry;
|
||||
};
|
||||
routesConfig: string;
|
||||
routesChunkNames: {
|
||||
[routePath: string]: ChunkNames;
|
||||
};
|
||||
routesPaths: string[];
|
||||
};
|
||||
|
||||
export default async function loadRoutes(
|
||||
pluginsRouteConfigs: RouteConfig[],
|
||||
baseUrl: string,
|
||||
) {
|
||||
): Promise<LoadedRoutes> {
|
||||
const routesImports = [
|
||||
`import React from 'react';`,
|
||||
`import ComponentCreator from '@docusaurus/ComponentCreator';`,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import {themeAlias} from '../alias';
|
||||
import themeAlias from '../alias';
|
||||
|
||||
describe('themeAlias', () => {
|
||||
test('valid themePath 1 with components', () => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import path from 'path';
|
||||
import {loadThemeAlias} from '../index';
|
||||
import loadThemeAlias from '../index';
|
||||
|
||||
describe('loadThemeAlias', () => {
|
||||
test('next alias can override the previous alias', () => {
|
||||
|
|
|
@ -11,7 +11,7 @@ import path from 'path';
|
|||
import {fileToPath, posixPath, normalizeUrl} from '@docusaurus/utils';
|
||||
import {ThemeAlias} from '@docusaurus/types';
|
||||
|
||||
export function themeAlias(
|
||||
export default function themeAlias(
|
||||
themePath: string,
|
||||
addOriginalAlias: boolean = true,
|
||||
): ThemeAlias {
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
*/
|
||||
|
||||
import {ThemeAlias} from '@docusaurus/types';
|
||||
import {themeAlias} from './alias';
|
||||
import themeAlias from './alias';
|
||||
|
||||
export function loadThemeAlias(
|
||||
export default function loadThemeAlias(
|
||||
themePaths: string[],
|
||||
userThemePaths: string[] = [],
|
||||
): ThemeAlias {
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import {validate} from 'webpack';
|
||||
|
||||
import {createClientConfig} from '../client';
|
||||
import {loadSetup} from '../../server/loadSetup';
|
||||
import createClientConfig from '../client';
|
||||
import loadSetup from '../../server/loadSetup';
|
||||
|
||||
describe('webpack dev config', () => {
|
||||
test('simple', async () => {
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import {validate} from 'webpack';
|
||||
|
||||
import {createServerConfig} from '../server';
|
||||
import {loadSetup} from '../../server/loadSetup';
|
||||
import createServerConfig from '../server';
|
||||
import loadSetup from '../../server/loadSetup';
|
||||
|
||||
describe('webpack production config', () => {
|
||||
test('simple', async () => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {createBaseConfig} from './base';
|
|||
import ChunkAssetPlugin from './plugins/ChunkAssetPlugin';
|
||||
import LogPlugin from './plugins/LogPlugin';
|
||||
|
||||
export function createClientConfig(
|
||||
export default function createClientConfig(
|
||||
props: Props,
|
||||
minify: boolean = true,
|
||||
): Configuration {
|
||||
|
@ -46,7 +46,7 @@ export function createClientConfig(
|
|||
|
||||
// When building include the plugin to force terminate building if errors happened in the client bundle.
|
||||
if (isBuilding) {
|
||||
clientConfig.plugins!.push({
|
||||
clientConfig.plugins?.push({
|
||||
apply: (compiler) => {
|
||||
compiler.hooks.done.tap('client:done', (stats) => {
|
||||
if (stats.hasErrors()) {
|
||||
|
|
|
@ -33,6 +33,9 @@ import path from 'path';
|
|||
import {sync as delSync} from 'del';
|
||||
|
||||
export interface Options {
|
||||
/** @deprecated */
|
||||
allowExternal?: unknown;
|
||||
|
||||
/**
|
||||
* Simulate the removal of files
|
||||
*
|
||||
|
@ -110,7 +113,6 @@ class CleanWebpackPlugin {
|
|||
https://github.com/johnagan/clean-webpack-plugin#options-and-defaults-optional`);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (options.allowExternal) {
|
||||
throw new Error(
|
||||
'clean-webpack-plugin: `allowExternal` option no longer supported. Use `dangerouslyAllowCleanPatternsOutsideProject`',
|
||||
|
|
|
@ -15,7 +15,7 @@ import {createBaseConfig} from './base';
|
|||
import WaitPlugin from './plugins/WaitPlugin';
|
||||
import LogPlugin from './plugins/LogPlugin';
|
||||
|
||||
export function createServerConfig(
|
||||
export default function createServerConfig(
|
||||
props: Props,
|
||||
minify: boolean = true,
|
||||
): Configuration {
|
||||
|
|
|
@ -10,6 +10,7 @@ import env from 'std-env';
|
|||
import merge from 'webpack-merge';
|
||||
import {Configuration, Loader} from 'webpack';
|
||||
import {TransformOptions} from '@babel/core';
|
||||
import {ConfigureWebpackUtils} from '@docusaurus/types';
|
||||
|
||||
import {version as cacheLoaderVersion} from 'cache-loader/package.json';
|
||||
|
||||
|
@ -17,7 +18,7 @@ import {version as cacheLoaderVersion} from 'cache-loader/package.json';
|
|||
export function getStyleLoaders(
|
||||
isServer: boolean,
|
||||
cssOptions: {
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
} = {},
|
||||
): Loader[] {
|
||||
if (isServer) {
|
||||
|
@ -53,7 +54,7 @@ export function getStyleLoaders(
|
|||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
|
@ -69,7 +70,7 @@ export function getStyleLoaders(
|
|||
|
||||
export function getCacheLoader(
|
||||
isServer: boolean,
|
||||
cacheOptions?: {},
|
||||
cacheOptions?: {[key: string]: unknown},
|
||||
): Loader | null {
|
||||
if (env.ci || env.test) {
|
||||
return null;
|
||||
|
@ -113,13 +114,19 @@ export function getBabelLoader(
|
|||
|
||||
/**
|
||||
* Helper function to modify webpack config
|
||||
* @param {Object | Function} configureWebpack a webpack config or a function to modify config
|
||||
* @param {Object} config initial webpack config
|
||||
* @param {boolean} isServer indicates if this is a server webpack configuration
|
||||
* @returns {Object} final/ modified webpack config
|
||||
* @param configureWebpack a webpack config or a function to modify config
|
||||
* @param config initial webpack config
|
||||
* @param isServer indicates if this is a server webpack configuration
|
||||
* @returns final/ modified webpack config
|
||||
*/
|
||||
export function applyConfigureWebpack(
|
||||
configureWebpack: any,
|
||||
configureWebpack:
|
||||
| Configuration
|
||||
| ((
|
||||
config: Configuration,
|
||||
isServer: boolean,
|
||||
utils: ConfigureWebpackUtils,
|
||||
) => Configuration),
|
||||
config: Configuration,
|
||||
isServer: boolean,
|
||||
): Configuration {
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
|
||||
import path from 'path';
|
||||
import Vibrant from 'node-vibrant';
|
||||
import {Palette} from 'node-vibrant/lib/color';
|
||||
|
||||
// @ts-ignore
|
||||
import {toPalette, toBase64} from '../utils';
|
||||
// @ts-ignore
|
||||
import lqip from '../lqip';
|
||||
|
||||
describe('lqip-loader', () => {
|
||||
|
@ -24,8 +23,8 @@ describe('lqip-loader', () => {
|
|||
});
|
||||
|
||||
describe('toPalette', () => {
|
||||
let correctTestSwatch: object = {};
|
||||
let testSwatchWithNull: object = {};
|
||||
let correctTestSwatch: Palette = {};
|
||||
let testSwatchWithNull: Palette & {Vibrant?: null} = {};
|
||||
|
||||
beforeAll(() => {
|
||||
const imgPath = path.join(__dirname, '__fixtures__', 'endi.jpg');
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
const sortBy = require('lodash.sortby');
|
||||
|
||||
/**
|
||||
|
@ -12,7 +14,7 @@ const sortBy = require('lodash.sortby');
|
|||
* @description it returns a Base64 image string with required formatting
|
||||
* to work on the web (<img src=".." /> or in CSS url('..'))
|
||||
*
|
||||
* @param extMimeType: image mime type string
|
||||
* @param {string} extMimeType: image mime type string
|
||||
* @param data: base64 string
|
||||
* @returns {string}
|
||||
*/
|
||||
|
@ -25,10 +27,11 @@ const toBase64 = (extMimeType, data) => {
|
|||
* @description takes a color swatch object, converts it to an array & returns
|
||||
* only hex color
|
||||
*
|
||||
* @param swatch
|
||||
* @returns {{palette: Array}}
|
||||
* @param {import("node-vibrant/lib/color").Palette} swatch
|
||||
* @returns {string[]}
|
||||
*/
|
||||
const toPalette = (swatch) => {
|
||||
/** @type {Array<{popularity: number, hex: string}>} */
|
||||
let palette = Object.keys(swatch).reduce((result, key) => {
|
||||
if (swatch[key] !== null) {
|
||||
result.push({
|
||||
|
@ -39,8 +42,7 @@ const toPalette = (swatch) => {
|
|||
return result;
|
||||
}, []);
|
||||
palette = sortBy(palette, ['popularity']);
|
||||
palette = palette.map((color) => color.hex).reverse();
|
||||
return palette;
|
||||
return palette.map((color) => color.hex).reverse();
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
53
yarn.lock
53
yarn.lock
|
@ -2795,6 +2795,11 @@
|
|||
"@types/minimatch" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/history@*":
|
||||
version "4.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.6.tgz#ed8fc802c45b8e8f54419c2d054e55c9ea344356"
|
||||
integrity sha512-GRTZLeLJ8ia00ZH8mxMO8t0aC9M1N9bN461Z2eaRurJo6Fpa+utgCwLzI4jQHcrdzuzp5WPN9jRwpsCQ1VhJ5w==
|
||||
|
||||
"@types/html-minifier-terser@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.0.0.tgz#7532440c138605ced1b555935c3115ddd20e8bef"
|
||||
|
@ -3032,10 +3037,42 @@
|
|||
"@types/webpack" "*"
|
||||
"@types/webpack-dev-server" "*"
|
||||
|
||||
"@types/react@^16.9.13":
|
||||
version "16.9.32"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.32.tgz#f6368625b224604148d1ddf5920e4fefbd98d383"
|
||||
integrity sha512-fmejdp0CTH00mOJmxUPPbWCEBWPvRIL4m8r0qD+BSDUqmutPyGQCHifzMpMzdvZwROdEdL78IuZItntFWgPXHQ==
|
||||
"@types/react-helmet@^6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.0.0.tgz#5b74e44a12662ffb12d1c97ee702cf4e220958cf"
|
||||
integrity sha512-NBMPAxgjpaMooXa51cU1BTgrX6T+hQbMiLm77JhBbfOzPQea3RB5rNpPOD5xGWHIVpGXHd59cltEzIq0qglGcQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-loadable@^5.5.3":
|
||||
version "5.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-loadable/-/react-loadable-5.5.3.tgz#65d50a6f9f7ff62513010bd6a460ed60ba58ca7d"
|
||||
integrity sha512-BRzQhbMo5CjfxFU2tmmBNh16QqKUwNiaX0vflCwIVPVG8g/pCOyJ3rOdSPo4m+TPS7C9q/TupaqYXXTMtFoyng==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
"@types/webpack" "*"
|
||||
|
||||
"@types/react-router-config@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.1.tgz#54da8418190ee47484dee279975e2b8038fb8b5d"
|
||||
integrity sha512-D4srFL4XP21GjWWnM7mL8j+Nrrw13pc2TYr57WTHJxU9YTxnrXL7p1iqGtwecgwhyeXJSm4WrGwq0SOgSALVbA==
|
||||
dependencies:
|
||||
"@types/history" "*"
|
||||
"@types/react" "*"
|
||||
"@types/react-router" "*"
|
||||
|
||||
"@types/react-router@*":
|
||||
version "5.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.7.tgz#e9d12ed7dcfc79187e4d36667745b69a5aa11556"
|
||||
integrity sha512-2ouP76VQafKjtuc0ShpwUebhHwJo0G6rhahW9Pb8au3tQTjYXd2jta4wv6U2tGLR/I42yuG00+UXjNYY0dTzbg==
|
||||
dependencies:
|
||||
"@types/history" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16.9.38":
|
||||
version "16.9.38"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.38.tgz#868405dace93a4095d3e054f4c4a1de7a1ac0680"
|
||||
integrity sha512-pHAeZbjjNRa/hxyNuLrvbxhhnKyKNiLC6I5fRF2Zr/t/S6zS41MiyzH4+c+1I9vVfvuRt1VS2Lodjr4ZWnxrdA==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
@ -17815,10 +17852,10 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^3.7.2:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
||||
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
|
||||
typescript@^3.9.5:
|
||||
version "3.9.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36"
|
||||
integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==
|
||||
|
||||
ua-parser-js@^0.7.18:
|
||||
version "0.7.21"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue