chore(v2): fix several lint warnings, add missing types, cleanup (#3844)

* fix several lint warnings, add missing types, cleanup

* fix EnumChangefreq issue

* better utilization of EnumChangefreq type

* update test snapshot
This commit is contained in:
Bartosz Kaszubowski 2020-11-30 16:42:58 +01:00 committed by GitHub
parent 139b668737
commit ad31facb32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 228 additions and 171 deletions

View file

@ -28,11 +28,13 @@ module.exports = postcss.plugin(
const sameProperties =
decl.parent.nodes.filter((n) => n.prop === decl.prop) || [];
const hasImportantProperties = sameProperties.some((p) =>
p.hasOwnProperty('important'),
Object.prototype.hasOwnProperty.call(p, 'important'),
);
const overriddenProperties = hasImportantProperties
? sameProperties.filter((p) => !p.hasOwnProperty('important'))
? sameProperties.filter(
(p) => !Object.prototype.hasOwnProperty.call(p, 'important'),
)
: sameProperties.slice(0, -1);
overriddenProperties.map((p) => p.remove());

View file

@ -18,21 +18,22 @@ const {
} = getFileLoaderUtils();
const createJSX = (node, pathUrl) => {
node.type = 'jsx';
node.value = `<img ${node.alt ? `alt={"${escapeHtml(node.alt)}"} ` : ''}${
const jsxNode = node;
jsxNode.type = 'jsx';
jsxNode.value = `<img ${node.alt ? `alt={"${escapeHtml(node.alt)}"} ` : ''}${
node.url
? `src={require("${inlineMarkdownImageFileLoader}${pathUrl}").default}`
: ''
}${node.title ? ` title="${escapeHtml(node.title)}"` : ''} />`;
if (node.url) {
delete node.url;
if (jsxNode.url) {
delete jsxNode.url;
}
if (node.alt) {
delete node.alt;
if (jsxNode.alt) {
delete jsxNode.alt;
}
if (node.title) {
delete node.title;
if (jsxNode.title) {
delete jsxNode.title;
}
};

View file

@ -1,7 +1,7 @@
{
"name": "@docusaurus/migrate",
"version": "2.0.0-alpha.69",
"description": "A cli tool to migrate between different version of docusuarus",
"description": "A cli tool to migrate between different version of Docusuarus",
"main": "lib/index.js",
"license": "MIT",
"engines": {
@ -43,6 +43,7 @@
"unist-util-visit": "^2.0.2"
},
"devDependencies": {
"@types/color": "^3.0.1",
"@types/jscodeshift": "^0.7.1"
}
}

View file

@ -12,10 +12,10 @@ import glob from 'glob';
import Color from 'color';
import {
VersionOneConfig,
VersionTwoConfig,
ClassicPresetEntries,
SidebarEntries,
VersionOneConfig,
VersionTwoConfig,
} from './types';
import extractMetadata, {shouldQuotifyFrontMatter} from './frontMatter';
import migratePage from './transform';
@ -229,9 +229,9 @@ export function createConfigFile({
const homePageId = siteConfig.headerLinks?.filter((value) => value.doc)[0]
.doc;
const customConfigFields: Record<string, any> = {};
const customConfigFields: Record<string, unknown> = {};
// add fields that are unknown to v2 to customConfigFields
Object.keys(siteConfig).forEach((key: any) => {
Object.keys(siteConfig).forEach((key) => {
const knownFields = [
'title',
'tagline',
@ -289,7 +289,7 @@ export function createConfigFile({
v2DocsPath = path.relative(newDir, absoluteDocsPath);
}
const result: VersionTwoConfig = {
return {
title: siteConfig.title ?? '',
tagline: siteConfig.tagline,
url: siteConfig.url ?? '',
@ -330,22 +330,24 @@ export function createConfigFile({
: undefined,
items: (siteConfig.headerLinks ?? [])
.map((link) => {
if (link.doc) {
const {doc, href, label, page} = link;
const position = 'left';
if (doc) {
return {
to: `docs/${link.doc === homePageId ? '' : link.doc}`,
label: link.label,
position: 'left',
to: `docs/${doc === homePageId ? '' : doc}`,
label,
position,
};
}
if (link.page) {
if (page) {
return {
to: `/${link.page}`,
label: link.label,
position: 'left',
to: `/${page}`,
label,
position,
};
}
if (link.href) {
return {href: link.href, label: link.label, position: 'left'};
if (href) {
return {href, label, position};
}
return null;
})
@ -379,7 +381,6 @@ export function createConfigFile({
: undefined,
},
};
return result;
}
function createClientRedirects(
@ -476,7 +477,7 @@ function handleVersioning(
const loadedVersions: Array<string> = JSON.parse(
String(fs.readFileSync(path.join(siteDir, 'versions.json'))),
);
fs.copyFile(
fs.copyFileSync(
path.join(siteDir, 'versions.json'),
path.join(newDir, 'versions.json'),
);
@ -732,11 +733,10 @@ function migrateLatestDocs(
classicPreset: ClassicPresetEntries,
): void {
if (fs.existsSync(path.join(siteDir, '..', 'docs'))) {
const docsPath = path.join(
classicPreset.docs.path = path.join(
path.relative(newDir, path.join(siteDir, '..')),
'docs',
);
classicPreset.docs.path = docsPath;
const files = walk(path.join(siteDir, '..', 'docs'));
files.forEach((file) => {
const content = String(fs.readFileSync(file));
@ -797,5 +797,5 @@ export async function migrateMDToMDX(
sanitizedFileContent(String(fs.readFileSync(file)), true),
);
});
console.log(`Succesfully migrated ${siteDir} to ${newDir}`);
console.log(`Successfully migrated ${siteDir} to ${newDir}`);
}

View file

@ -20,9 +20,7 @@ const tags = htmlTags.reduce((acc: {[key: string]: boolean}, tag) => {
}, {});
export default function sanitizeMD(code: string): string {
const markdownTree = unified()
.use(markdown as any)
.parse(code);
const markdownTree = unified().use(markdown).parse(code);
visit(markdownTree, 'code', (node) => {
node.value = `\n<!--${node.value}-->\n`;
});
@ -31,12 +29,10 @@ export default function sanitizeMD(code: string): string {
});
const markdownString = unified()
.use(remarkStringify as any, {fence: '`', fences: true})
.use(remarkStringify, {fence: '`', fences: true})
.stringify(markdownTree);
const htmlTree = unified()
.use(parse as any)
.parse(markdownString);
const htmlTree = unified().use(parse).parse(markdownString);
visit(htmlTree, 'element', (node) => {
if (!tags[node.tagName as string]) {
node.type = 'text';

View file

@ -5,7 +5,14 @@
* LICENSE file in the root directory of this source tree.
*/
import jscodeshift from 'jscodeshift';
import jscodeshift, {
ArrowFunctionExpression,
AssignmentExpression,
ASTPath,
Collection,
TemplateElement,
VariableDeclarator,
} from 'jscodeshift';
const empty = () =>
jscodeshift.arrowFunctionExpression(
@ -18,16 +25,14 @@ const empty = () =>
),
);
const property = (key: string, value: jscodeshift.ArrowFunctionExpression) =>
const property = (key: string, value: ArrowFunctionExpression) =>
jscodeshift.objectProperty(jscodeshift.identifier(key), value);
const processCallExpression = (
node: jscodeshift.ASTPath<jscodeshift.VariableDeclarator>,
) => {
const processCallExpression = (node: ASTPath<VariableDeclarator>) => {
const args = (node?.value?.init as any)?.arguments[0];
if (args.type === 'Literal') {
if (args.value.includes('../../core/CompLibrary')) {
const newDeclartor = jscodeshift.variableDeclarator(
const newDeclarator = jscodeshift.variableDeclarator(
node.value.id,
jscodeshift.objectExpression([
property('Container', empty()),
@ -35,32 +40,30 @@ const processCallExpression = (
property('MarkdownBlock', empty()),
]),
);
jscodeshift(node).replaceWith(newDeclartor);
jscodeshift(node).replaceWith(newDeclarator);
}
}
if (args.type === 'TemplateLiteral') {
if (
args.quasis
.map((element: jscodeshift.TemplateElement) => element.value.raw)
.map((element: TemplateElement) => element.value.raw)
.join('')
.match(/\/core\//)
) {
const newDeclartor = jscodeshift.variableDeclarator(
const newDeclarator = jscodeshift.variableDeclarator(
node.value.id,
empty(),
);
jscodeshift(node).replaceWith(newDeclartor);
jscodeshift(node).replaceWith(newDeclarator);
}
}
};
const processMemberExpression = (
node: jscodeshift.ASTPath<jscodeshift.VariableDeclarator>,
) => {
const processMemberExpression = (node: ASTPath<VariableDeclarator>) => {
const args = (node?.value?.init as any)?.object?.arguments[0];
if (args.type === 'Literal') {
if (args.value === '../../core/CompLibrary.js') {
const newDeclartor = jscodeshift.variableDeclarator(
const newDeclarator = jscodeshift.variableDeclarator(
node.value.id,
jscodeshift.objectExpression([
property('Container', empty()),
@ -68,27 +71,27 @@ const processMemberExpression = (
property('MarkdownBlock', empty()),
]),
);
jscodeshift(node).replaceWith(newDeclartor);
jscodeshift(node).replaceWith(newDeclarator);
} else if (args.value.match(/server/)) {
const newDeclartor = jscodeshift.variableDeclarator(
const newDeclarator = jscodeshift.variableDeclarator(
node.value.id,
empty(),
);
jscodeshift(node).replaceWith(newDeclartor);
jscodeshift(node).replaceWith(newDeclarator);
}
}
if (args.type === 'TemplateLiteral') {
if (
args.quasis
.map((ele: jscodeshift.TemplateElement) => ele.value.raw)
.map((ele: TemplateElement) => ele.value.raw)
.join('')
.match(/\/core\//)
) {
const newDeclartor = jscodeshift.variableDeclarator(
const newDeclarator = jscodeshift.variableDeclarator(
node.value.id,
empty(),
);
jscodeshift(node).replaceWith(newDeclartor);
jscodeshift(node).replaceWith(newDeclarator);
}
}
};
@ -113,7 +116,7 @@ export default function transformer(file: string): string {
}
root
.find(jscodeshift.AssignmentExpression, {
.find(AssignmentExpression, {
operator: '=',
left: {
type: 'MemberExpression',
@ -164,10 +167,10 @@ export default function transformer(file: string): string {
return root.toSource();
}
function getDefaultImportDeclarators(rootAst: jscodeshift.Collection) {
function getDefaultImportDeclarators(rootAst: Collection) {
// var ... = require('y')
return rootAst
.find(jscodeshift.VariableDeclarator, {
.find(VariableDeclarator, {
init: {
callee: {
name: 'require',
@ -179,9 +182,9 @@ function getDefaultImportDeclarators(rootAst: jscodeshift.Collection) {
});
}
function getNamedImportDeclarators(rootAst: jscodeshift.Collection) {
function getNamedImportDeclarators(rootAst: Collection) {
// var ... = require('y').x
return rootAst.find(jscodeshift.VariableDeclarator, {
return rootAst.find(VariableDeclarator, {
init: {
object: {
callee: {
@ -192,7 +195,7 @@ function getNamedImportDeclarators(rootAst: jscodeshift.Collection) {
});
}
function getImportDeclaratorPaths(variableDeclaration: jscodeshift.Collection) {
function getImportDeclaratorPaths(variableDeclaration: Collection) {
const defaultImports = getDefaultImportDeclarators(variableDeclaration);
const namedImports = getNamedImportDeclarators(variableDeclaration);

View file

@ -85,11 +85,11 @@ It is not possible to redirect the same pathname to multiple destinations:
}
},
);
redirects = uniqBy(redirects, (redirect) => redirect.from);
const collectedRedirects = uniqBy(redirects, (redirect) => redirect.from);
// We don't want to override an already existing route with a redirect file!
const redirectsOverridingExistingPath = redirects.filter((redirect) =>
pluginContext.relativeRoutesPaths.includes(redirect.from),
const redirectsOverridingExistingPath = collectedRedirects.filter(
(redirect) => pluginContext.relativeRoutesPaths.includes(redirect.from),
);
if (redirectsOverridingExistingPath.length > 0) {
console.error(
@ -100,11 +100,9 @@ It is not possible to redirect the same pathname to multiple destinations:
),
);
}
redirects = redirects.filter(
return collectedRedirects.filter(
(redirect) => !pluginContext.relativeRoutesPaths.includes(redirect.from),
);
return redirects;
}
// For each plugin config option, create the appropriate redirects

View file

@ -17,14 +17,14 @@ const getCompiledRedirectPageTemplate = memoize(() => {
return eta.compile(redirectPageTemplate.trim());
});
function renderRedirectPageTemplate(data: object) {
function renderRedirectPageTemplate(data: Record<string, unknown>) {
const compiled = getCompiledRedirectPageTemplate();
return compiled(data, eta.defaultConfig);
}
export default function createRedirectPageContent({
toUrl,
}: CreateRedirectPageOptions) {
}: CreateRedirectPageOptions): string {
return renderRedirectPageTemplate({
toUrl: encodeURI(toUrl),
});

View file

@ -272,6 +272,6 @@ export function linkify({
}
// Order matters: we look in priority in localized folder
export function getContentPathList(contentPaths: BlogContentPaths) {
export function getContentPathList(contentPaths: BlogContentPaths): string[] {
return [contentPaths.contentPathLocalized, contentPaths.contentPath];
}

View file

@ -38,9 +38,15 @@ export interface PluginOptions {
blogDescription: string;
blogSidebarCount: number | 'ALL';
blogSidebarTitle: string;
remarkPlugins: ([Function, object] | Function)[];
beforeDefaultRehypePlugins: ([Function, object] | Function)[];
beforeDefaultRemarkPlugins: ([Function, object] | Function)[];
remarkPlugins: ([Function, Record<string, unknown>] | Function)[];
beforeDefaultRehypePlugins: (
| [Function, Record<string, unknown>]
| Function
)[];
beforeDefaultRemarkPlugins: (
| [Function, Record<string, unknown>]
| Function
)[];
rehypePlugins: string[];
truncateMarker: RegExp;
showReadingTime: boolean;
@ -52,7 +58,7 @@ export interface PluginOptions {
language?: string;
};
editUrl?: string;
admonitions: any;
admonitions: Record<string, unknown>;
}
export interface BlogTags {

View file

@ -6,7 +6,7 @@
*/
declare module 'remark-admonitions' {
type Options = any;
type Options = Record<string, unknown>;
const plugin: (options?: Options) => void;
export = plugin;

View file

@ -9,21 +9,21 @@ import path from 'path';
import fs from 'fs-extra';
import {
aliasedSitePath,
normalizeUrl,
getEditUrl,
parseMarkdownString,
getFolderContainingFile,
normalizeUrl,
parseMarkdownString,
} from '@docusaurus/utils';
import {LoadContext} from '@docusaurus/types';
import {getFileLastUpdate} from './lastUpdate';
import {
DocFile,
DocMetadataBase,
LastUpdateData,
MetadataOptions,
VersionMetadata,
DocFile,
PluginOptions,
VersionMetadata,
} from './types';
import getSlug from './slug';
import {CURRENT_VERSION_NAME} from './constants';
@ -173,7 +173,7 @@ export function processDocMetadata({
// NodeJS optimization.
// Adding properties to object after instantiation will cause hidden
// class transitions.
const metadata: DocMetadataBase = {
return {
unversionedId,
id,
isDocsHomePage,
@ -188,6 +188,4 @@ export function processDocMetadata({
lastUpdatedAt: lastUpdate.lastUpdatedAt,
sidebar_label,
};
return metadata;
}

View file

@ -268,7 +268,9 @@ export function collectSidebarsDocIds(
});
}
export function createSidebarsUtils(sidebars: Sidebars) {
export function createSidebarsUtils(
sidebars: Sidebars,
): Record<string, Function> {
const sidebarNameToDocIds = collectSidebarsDocIds(sidebars);
function getFirstDocIdOfFirstSidebar(): string | undefined {

View file

@ -21,7 +21,7 @@ export default function getSlug({
frontmatterSlug?: string;
dirName: string;
}): string {
const baseSlug: string = frontmatterSlug || baseID;
const baseSlug = frontmatterSlug || baseID;
let slug: string;
if (baseSlug.startsWith('/')) {
slug = baseSlug;

View file

@ -59,11 +59,17 @@ export type PluginOptions = MetadataOptions &
include: string[];
docLayoutComponent: string;
docItemComponent: string;
remarkPlugins: ([Function, object] | Function)[];
remarkPlugins: ([Function, Record<string, unknown>] | Function)[];
rehypePlugins: string[];
beforeDefaultRemarkPlugins: ([Function, object] | Function)[];
beforeDefaultRehypePlugins: ([Function, object] | Function)[];
admonitions: any;
beforeDefaultRemarkPlugins: (
| [Function, Record<string, unknown>]
| Function
)[];
beforeDefaultRehypePlugins: (
| [Function, Record<string, unknown>]
| Function
)[];
admonitions: Record<string, unknown>;
disableVersioning: boolean;
excludeNextVersionDocs?: boolean;
includeCurrentVersion: boolean;

View file

@ -6,7 +6,7 @@
*/
declare module 'remark-admonitions' {
type Options = any;
type Options = Record<string, unknown>;
const plugin: (options?: Options) => void;
export = plugin;

View file

@ -42,7 +42,7 @@ import {
} from './types';
import {flatten} from 'lodash';
export function getContentPathList(contentPaths: PagesContentPaths) {
export function getContentPathList(contentPaths: PagesContentPaths): string[] {
return [contentPaths.contentPathLocalized, contentPaths.contentPath];
}

View file

@ -12,11 +12,17 @@ export interface PluginOptions {
include: string[];
exclude: string[];
mdxPageComponent: string;
remarkPlugins: ([Function, object] | Function)[];
remarkPlugins: ([Function, Record<string, unknown>] | Function)[];
rehypePlugins: string[];
beforeDefaultRemarkPlugins: ([Function, object] | Function)[];
beforeDefaultRehypePlugins: ([Function, object] | Function)[];
admonitions: any;
beforeDefaultRemarkPlugins: (
| [Function, Record<string, unknown>]
| Function
)[];
beforeDefaultRehypePlugins: (
| [Function, Record<string, unknown>]
| Function
)[];
admonitions: Record<string, unknown>;
}
export type JSXPageMetadata = {

View file

@ -6,7 +6,7 @@
*/
declare module 'remark-admonitions' {
type Options = any;
type Options = Record<string, unknown>;
const plugin: (options?: Options) => void;
export = plugin;

View file

@ -59,7 +59,7 @@ describe('normalizeSitemapPluginOptions', () => {
changefreq: 'annually',
});
}).toThrowErrorMatchingInlineSnapshot(
`"\\"changefreq\\" must be one of [always, hourly, daily, weekly, monthly, yearly, never]"`,
`"\\"changefreq\\" must be one of [daily, monthly, always, hourly, weekly, yearly, never]"`,
);
});
});

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import sitemap, {SitemapItemOptions} from 'sitemap';
import sitemap, {Sitemap, SitemapItemOptions} from 'sitemap';
import {PluginOptions} from './types';
import {DocusaurusConfig} from '@docusaurus/types';
@ -13,28 +13,26 @@ export default function createSitemap(
siteConfig: DocusaurusConfig,
routesPaths: string[],
options: PluginOptions,
): sitemap.Sitemap {
): Sitemap {
const {url: hostname} = siteConfig;
if (!hostname) {
throw new Error('url in docusaurus.config.js cannot be empty/undefined');
}
const {cacheTime, changefreq, priority, trailingSlash} = options;
const urls = routesPaths
.filter((route: string) => !route.endsWith('404.html'))
.filter((route) => !route.endsWith('404.html'))
.map(
(routesPath) =>
({
url: `${routesPath}${
options.trailingSlash && routesPath !== '/' ? '/' : ''
}`,
changefreq: options.changefreq,
priority: options.priority,
} as SitemapItemOptions),
(routesPath): SitemapItemOptions => ({
url: `${routesPath}${trailingSlash && routesPath !== '/' ? '/' : ''}`,
changefreq,
priority,
}),
);
return sitemap.createSitemap({
hostname,
cacheTime: options.cacheTime,
cacheTime,
urls,
});
}

View file

@ -5,11 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/
import * as Joi from 'joi';
import {EnumChangefreq} from 'sitemap';
import {PluginOptions} from './types';
export const DEFAULT_OPTIONS: Required<PluginOptions> = {
cacheTime: 600 * 1000, // 600 sec - cache purge period.
changefreq: 'weekly',
changefreq: EnumChangefreq.WEEKLY,
priority: 0.5,
trailingSlash: false,
};
@ -17,7 +18,7 @@ export const DEFAULT_OPTIONS: Required<PluginOptions> = {
export const PluginOptionSchema = Joi.object({
cacheTime: Joi.number().positive().default(DEFAULT_OPTIONS.cacheTime),
changefreq: Joi.string()
.valid('always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never')
.valid(...Object.values(EnumChangefreq))
.default(DEFAULT_OPTIONS.changefreq),
priority: Joi.number().min(0).max(1).default(DEFAULT_OPTIONS.priority),
trailingSlash: Joi.bool().default(false),

View file

@ -4,10 +4,11 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {EnumChangefreq} from 'sitemap';
export interface PluginOptions {
cacheTime?: number;
changefreq?: string;
changefreq?: EnumChangefreq;
priority?: number;
trailingSlash?: boolean;
}

View file

@ -151,7 +151,7 @@ const swizzleAllowedComponents = [
'prism-include-languages',
];
export function getSwizzleComponentList() {
export function getSwizzleComponentList(): string[] {
return swizzleAllowedComponents;
}

View file

@ -11,7 +11,7 @@ import Link from '@docusaurus/Link';
import type {Props} from '@theme/BlogSidebar';
import styles from './styles.module.css';
export default function BlogSidebar({sidebar}: Props) {
export default function BlogSidebar({sidebar}: Props): JSX.Element | null {
if (sidebar.items.length === 0) {
return null;
}

View file

@ -113,9 +113,7 @@ export default ({
const prismTheme = usePrismTheme();
// In case interleaved Markdown (e.g. when using CodeBlock as standalone component).
if (Array.isArray(children)) {
children = children.join('');
}
const content = Array.isArray(children) ? children.join('') : children;
if (metastring && highlightLinesRangeRegex.test(metastring)) {
// Tested above
@ -133,6 +131,7 @@ export default ({
let language =
languageClassName &&
// Force Prism's language union type to `any` because it does not contain all available languages
// eslint-disable-next-line @typescript-eslint/no-explicit-any
((languageClassName.replace(/language-/, '') as Language) as any);
if (!language && prism.defaultLanguage) {
@ -140,12 +139,12 @@ export default ({
}
// only declaration OR directive highlight can be used for a block
let code = children.replace(/\n$/, '');
let code = content.replace(/\n$/, '');
if (highlightLines.length === 0 && language !== undefined) {
let range = '';
const directiveRegex = highlightDirectiveRegex(language);
// go through line by line
const lines = children.replace(/\n$/, '').split('\n');
const lines = content.replace(/\n$/, '').split('\n');
let blockStart;
// loop through lines
for (let index = 0; index < lines.length; ) {

View file

@ -28,7 +28,15 @@ function DocItem(props: Props): JSX.Element {
const {siteConfig} = useDocusaurusContext();
const {url: siteUrl} = siteConfig;
const {content: DocContent} = props;
const {metadata} = DocContent;
const {
metadata,
frontMatter: {
image: metaImage,
keywords,
hide_title: hideTitle,
hide_table_of_contents: hideTableOfContents,
},
} = DocContent;
const {
description,
title,
@ -37,14 +45,6 @@ function DocItem(props: Props): JSX.Element {
lastUpdatedAt,
lastUpdatedBy,
} = metadata;
const {
frontMatter: {
image: metaImage,
keywords,
hide_title: hideTitle,
hide_table_of_contents: hideTableOfContents,
},
} = DocContent;
const {pluginId} = useActivePlugin({failfast: true});
const versions = useVersions(pluginId);

View file

@ -9,8 +9,9 @@ import React from 'react';
import ThemeProvider from '@theme/ThemeProvider';
import UserPreferencesProvider from '@theme/UserPreferencesProvider';
import {DocsPreferredVersionContextProvider} from '@docusaurus/theme-common';
import {Props} from '@theme/LayoutProviders';
export default function LayoutProviders({children}) {
export default function LayoutProviders({children}: Props): JSX.Element {
return (
<ThemeProvider>
<UserPreferencesProvider>

View file

@ -22,7 +22,7 @@ export default function SearchMetadatas({
locale,
version,
tag,
}: SearchTagMetaProps) {
}: SearchTagMetaProps): JSX.Element {
return (
<Head>
{locale && <meta name="docusaurus_locale" content={`${locale}`} />}

View file

@ -440,6 +440,15 @@ declare module '@theme/UserPreferencesProvider' {
export default UserPreferencesProvider;
}
declare module '@theme/LayoutProviders' {
import type {ReactNode} from 'react';
export type Props = {readonly children: ReactNode};
const LayoutProviders: (props: Props) => JSX.Element;
export default LayoutProviders;
}
declare module '@theme/ThemeContext' {
import type {Context} from 'react';
import type {ThemeContextProps} from '@theme/hooks/useThemeContext';

View file

@ -9,7 +9,7 @@
export const isSamePath = (
path1: string | undefined,
path2: string | undefined,
) => {
): boolean => {
const normalize = (pathname: string | undefined) => {
return !pathname || pathname?.endsWith('/') ? pathname : `${pathname}/`;
};

View file

@ -7,6 +7,9 @@
export const DEFAULT_SEARCH_TAG = 'default';
export function docVersionSearchTag(pluginId: string, versionName: string) {
export function docVersionSearchTag(
pluginId: string,
versionName: string,
): string {
return `docs-${pluginId}-${versionName}`;
}

View file

@ -336,7 +336,10 @@ export interface ThemeConfigValidationContext<T, E extends Error = Error> {
// TODO we should use a Joi type here
export interface ValidationSchema<T> {
validate(options: Partial<T>, opt: object): ValidationResult<T>;
validate(
options: Partial<T>,
opt: Record<string, unknown>,
): ValidationResult<T>;
unknown(): ValidationSchema<T>;
append(data: any): ValidationSchema<T>;
}

View file

@ -19,7 +19,7 @@ function createTestHelpers({
schema,
defaultValue,
}: {
schema: Joi.SchemaLike;
schema: Joi.Schema;
defaultValue?: unknown;
}) {
function testOK(value: unknown) {
@ -36,7 +36,7 @@ function createTestHelpers({
return {testOK, testFail};
}
function testMarkdownPluginSchemas(schema: Joi.SchemaLike) {
function testMarkdownPluginSchemas(schema: Joi.Schema) {
const {testOK, testFail} = createTestHelpers({
schema,
defaultValue: [],

View file

@ -25,7 +25,7 @@ if (isValidationDisabledEscapeHatch) {
);
}
export const logValidationBugReportHint = () => {
export const logValidationBugReportHint = (): void => {
console.log(
`\n${chalk.red('A validation error occured.')}${chalk.cyanBright(
'\nThe validation system was added recently to Docusaurus as an attempt to avoid user configuration errors.' +

View file

@ -266,7 +266,7 @@ export function parseMarkdownString(markdownString: string): ParsedMarkdown {
return {frontMatter, content, excerpt};
} catch (e) {
throw new Error(`Error while parsing markdown front matter.
This can happen if you use special characteres like : in frontmatter values (try using "" around that value)
This can happen if you use special characters like : in frontmatter values (try using "" around that value)
${e.message}`);
}
}
@ -394,7 +394,7 @@ export function isValidPathname(str: string): boolean {
}
// resolve pathname and fail fast if resolution fails
export function resolvePathname(to: string, from?: string) {
export function resolvePathname(to: string, from?: string): string {
return resolvePathnameUnsafe(to, from);
}
export function addLeadingSlash(str: string): string {
@ -456,7 +456,7 @@ export function getPluginI18nPath({
pluginName: string;
pluginId?: string | undefined;
subPaths?: string[];
}) {
}): string {
return path.join(
siteDir,
'i18n',

View file

@ -33,6 +33,7 @@
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-alpha.69",
"@types/detect-port": "^1.3.0",
"@types/nprogress": "^0.2.0",
"tmp-promise": "^3.0.2"
},
"dependencies": {

View file

@ -18,7 +18,7 @@ import inquirer from 'inquirer';
const isInteractive = process.stdout.isTTY;
const execOptions: object = {
const execOptions: Record<string, unknown> = {
encoding: 'utf8',
stdio: [
'pipe', // stdin (default)
@ -43,15 +43,13 @@ function getProcessIdOnPort(port: number): string {
}
// Gets process command
function getProcessCommand(processId: string): Promise<string | null> | string {
let command: Buffer | string = execSync(
function getProcessCommand(processId: string): string {
const command: Buffer = execSync(
`ps -o command -p ${processId} | sed -n 2p`,
execOptions,
);
command = command.toString().replace(/\n$/, '');
return command;
return command.toString().replace(/\n$/, '');
}
// Gets directory of a process from its process id
@ -103,7 +101,7 @@ export default async function choosePort(
if (isInteractive) {
clearConsole();
const existingProcess = getProcessForPort(defaultPort);
const question: any = {
const question: Record<string, unknown> = {
type: 'confirm',
name: 'shouldChangePort',
message: `${chalk.yellow(

View file

@ -35,7 +35,7 @@ const Context = createContext<LinksCollector>({
},
});
export const useLinksCollector = () => {
export const useLinksCollector = (): LinksCollector => {
return useContext(Context);
};
@ -45,6 +45,6 @@ export const ProvideLinksCollector = ({
}: {
children: ReactNode;
linksCollector: LinksCollector;
}) => {
}): JSX.Element => {
return <Context.Provider value={linksCollector}>{children}</Context.Provider>;
};

View file

@ -7,6 +7,7 @@
import React from 'react';
import {Route, withRouter} from 'react-router-dom';
import {RouteConfig} from 'react-router-config';
import nprogress from 'nprogress';
import clientLifecyclesDispatcher from './client-lifecycles-dispatcher';
@ -18,7 +19,7 @@ import './nprogress.css';
nprogress.configure({showSpinner: false});
interface Props {
routes: any[];
routes: RouteConfig[];
delay: number;
location: any;
}
@ -104,7 +105,7 @@ class PendingNavigation extends React.Component<Props, State> {
}
}
startProgressBar(delay) {
startProgressBar(delay: number) {
this.clearProgressBarTimeout();
this.progressBarTimeout = setTimeout(() => {
clientLifecyclesDispatcher.onRouteUpdateDelayed({

View file

@ -18,7 +18,7 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
// Note: it might create false positives (ie network failures): not a big deal
// Note: we only inline this for the homepage to avoid polluting all the site's pages
// See https://github.com/facebook/docusaurus/pull/3621
export default function BaseUrlIssueBanner() {
export default function BaseUrlIssueBanner(): JSX.Element | null {
const {
siteConfig: {baseUrl, baseUrlIssueBanner},
} = useDocusaurusContext();

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
export function hasProtocol(url: string) {
export function hasProtocol(url: string): boolean {
return /^(\w*:|\/\/)/.test(url) === true;
}

View file

@ -202,7 +202,7 @@ export async function handleBrokenLinks({
routes: RouteConfig[];
baseUrl: string;
outDir: string;
}) {
}): Promise<void> {
if (onBrokenLinks === 'ignore') {
return;
}

View file

@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {RouteConfig, ReportingSeverity} from '@docusaurus/types';
import {ReportingSeverity, RouteConfig} from '@docusaurus/types';
import {reportMessage} from '@docusaurus/utils';
import {getAllFinalRoutes} from './utils';
@ -15,15 +15,14 @@ export function getAllDuplicateRoutes(
(routeConfig) => routeConfig.path,
);
const seenRoutes: Record<string, any> = {};
const duplicateRoutes: string[] = allRoutes.filter(function (route) {
if (seenRoutes.hasOwnProperty(route)) {
return allRoutes.filter((route) => {
if (Object.prototype.hasOwnProperty.call(seenRoutes, route)) {
return true;
} else {
seenRoutes[route] = true;
return false;
}
});
return duplicateRoutes;
}
export function getDuplicateRoutesMessage(

View file

@ -9,11 +9,11 @@ import Module from 'module';
import {join} from 'path';
import importFresh from 'import-fresh';
import {
DocusaurusPluginVersionInformation,
LoadContext,
Plugin,
PluginOptions,
PluginConfig,
DocusaurusPluginVersionInformation,
PluginOptions,
} from '@docusaurus/types';
import {CONFIG_FILE_NAME, DEFAULT_PLUGIN_ID} from '../../constants';
import {getPluginVersion} from '../versions';
@ -74,11 +74,10 @@ export default function initPlugins({
pluginModule.default?.validateOptions ?? pluginModule.validateOptions;
if (validateOptions) {
const normalizedOptions = validateOptions({
pluginOptions = validateOptions({
validate: normalizePluginOptions,
options: pluginOptions,
});
pluginOptions = normalizedOptions;
} else {
// Important to ensure all plugins have an id
// as we don't go through the Joi schema that adds it

View file

@ -9,9 +9,9 @@ import {groupBy} from 'lodash';
import {InitPlugin} from './init';
import {DEFAULT_PLUGIN_ID} from '../../constants';
// It is forbidden to have 2 plugins of the same name sharind the same id
// It is forbidden to have 2 plugins of the same name sharing the same id
// this is required to support multi-instance plugins without conflict
export function ensureUniquePluginInstanceIds(plugins: InitPlugin[]) {
export function ensureUniquePluginInstanceIds(plugins: InitPlugin[]): void {
const pluginsByName = groupBy(plugins, (p) => p.name);
Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => {
const pluginInstancesById = groupBy(

View file

@ -36,11 +36,11 @@ export function excludeJS(modulePath: string): boolean {
);
}
export function getDocusaurusAliases() {
export function getDocusaurusAliases(): Record<string, string> {
const dirPath = path.resolve(__dirname, '../client/exports');
const extensions = ['.js', '.ts', '.tsx'];
const aliases: Record<string, string> = {};
const aliases = {};
fs.readdirSync(dirPath)
.filter((fileName) => extensions.includes(path.extname(fileName)))

View file

@ -8,7 +8,13 @@
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import env from 'std-env';
import merge from 'webpack-merge';
import webpack, {Configuration, Loader, RuleSetRule, Stats} from 'webpack';
import webpack, {
Configuration,
Loader,
Plugin,
RuleSetRule,
Stats,
} from 'webpack';
import fs from 'fs-extra';
import TerserPlugin from 'terser-webpack-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
@ -228,7 +234,7 @@ export function compile(config: Configuration[]): Promise<void> {
type AssetFolder = 'images' | 'files' | 'medias';
// Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
export function getFileLoaderUtils() {
export function getFileLoaderUtils(): Record<string, any> {
// files/images < 10kb will be inlined as base64 strings directly in the html
const urlLoaderLimit = 10000;
@ -375,7 +381,7 @@ function getTerserParallel() {
return terserParallel;
}
export function getMinimizer(useSimpleCssMinifier = false) {
export function getMinimizer(useSimpleCssMinifier = false): Plugin[] {
const minimizer = [
new TerserPlugin({
cache: true,

View file

@ -3197,11 +3197,25 @@
dependencies:
"@types/node" "*"
"@types/color-name@^1.1.1":
"@types/color-convert@*":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-1.9.0.tgz#bfa8203e41e7c65471e9841d7e306a7cd8b5172d"
integrity sha512-OKGEfULrvSL2VRbkl/gnjjgbbF7ycIlpSsX7Nkab4MOWi5XxmgBYvuiQ7lcCFY5cPDz7MUNaKgxte2VRmtr4Fg==
dependencies:
"@types/color-name" "*"
"@types/color-name@*", "@types/color-name@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
"@types/color@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/color/-/color-3.0.1.tgz#2900490ed04da8116c5058cd5dba3572d5a25071"
integrity sha512-oeUWVaAwI+xINDUx+3F2vJkl/vVB03VChFF/Gl3iQCdbcakjuoJyMOba+3BXRtnBhxZ7uBYqQBi9EpLnvSoztA==
dependencies:
"@types/color-convert" "*"
"@types/connect-history-api-fallback@*":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.3.tgz#4772b79b8b53185f0f4c9deab09236baf76ee3b4"
@ -3537,6 +3551,11 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
"@types/nprogress@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@types/nprogress/-/nprogress-0.2.0.tgz#86c593682d4199212a0509cc3c4d562bbbd6e45f"
integrity sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"