refactor: remove sub-eslintrc, fix more lint errors (#7530)

This commit is contained in:
Joshua Chen 2022-05-30 14:49:51 +08:00 committed by GitHub
parent f443e992b9
commit 9023b7740c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 129 additions and 92 deletions

54
.eslintrc.js vendored
View file

@ -19,7 +19,8 @@ module.exports = {
}, },
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
allowImportExportEverywhere: true, // tsconfigRootDir: __dirname,
// project: ['./tsconfig.json', './website/tsconfig.json'],
}, },
globals: { globals: {
JSX: true, JSX: true,
@ -30,6 +31,8 @@ module.exports = {
'plugin:jest/recommended', 'plugin:jest/recommended',
'airbnb', 'airbnb',
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
// 'plugin:@typescript-eslint/strict',
'plugin:regexp/recommended', 'plugin:regexp/recommended',
'prettier', 'prettier',
'plugin:@docusaurus/all', 'plugin:@docusaurus/all',
@ -302,6 +305,9 @@ module.exports = {
'react/prop-types': OFF, 'react/prop-types': OFF,
'react/require-default-props': [ERROR, {ignoreFunctionalComponents: true}], 'react/require-default-props': [ERROR, {ignoreFunctionalComponents: true}],
'@typescript-eslint/consistent-type-definitions': OFF,
'@typescript-eslint/require-await': OFF,
'@typescript-eslint/ban-ts-comment': [ '@typescript-eslint/ban-ts-comment': [
ERROR, ERROR,
{'ts-expect-error': 'allow-with-description'}, {'ts-expect-error': 'allow-with-description'},
@ -363,20 +369,39 @@ module.exports = {
overrides: [ overrides: [
{ {
files: [ files: [
'packages/docusaurus-*/src/theme/**/*.js', 'packages/docusaurus-*/src/theme/**/*.{js,ts,tsx}',
'packages/docusaurus-*/src/theme/**/*.ts', 'packages/docusaurus/src/client/**/*.{js,ts,tsx}',
'packages/docusaurus-*/src/theme/**/*.tsx', ],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
// Prevent importing lodash in client bundle for bundle size
'lodash',
'lodash.**',
'lodash/**',
// Prevent importing server code in client bundle
'**/../babel/**',
'**/../server/**',
'**/../commands/**',
'**/../webpack/**',
],
},
],
},
},
{
files: [
'packages/docusaurus-*/src/theme/**/*.{js,ts,tsx}',
'packages/docusaurus/src/client/theme-fallback/**/*.{js,ts,tsx}',
], ],
rules: { rules: {
'import/no-named-export': ERROR, 'import/no-named-export': ERROR,
}, },
}, },
{ {
files: [ files: ['packages/create-docusaurus/templates/**/*.{js,ts,tsx}'],
'packages/create-docusaurus/templates/**/*.js',
'packages/create-docusaurus/templates/**/*.ts',
'packages/create-docusaurus/templates/**/*.tsx',
],
rules: { rules: {
'header/header': OFF, 'header/header': OFF,
'global-require': OFF, 'global-require': OFF,
@ -391,14 +416,14 @@ module.exports = {
}, },
}, },
{ {
files: ['*.ts', '*.tsx'], files: ['*.{ts,tsx}'],
rules: { rules: {
'no-undef': OFF, 'no-undef': OFF,
'import/no-import-module-exports': OFF, 'import/no-import-module-exports': OFF,
}, },
}, },
{ {
files: ['*.js', '*.mjs', '.cjs'], files: ['*.{js,mjs,cjs}'],
rules: { rules: {
// Make JS code directly runnable in Node. // Make JS code directly runnable in Node.
'@typescript-eslint/no-var-requires': OFF, '@typescript-eslint/no-var-requires': OFF,
@ -419,8 +444,7 @@ module.exports = {
// Internal files where extraneous deps don't matter much at long as // Internal files where extraneous deps don't matter much at long as
// they run // they run
files: [ files: [
'*.test.ts', '*.test.{js,ts,tsx}',
'*.test.tsx',
'admin/**', 'admin/**',
'jest/**', 'jest/**',
'website/**', 'website/**',
@ -431,5 +455,9 @@ module.exports = {
'import/no-extraneous-dependencies': OFF, 'import/no-extraneous-dependencies': OFF,
}, },
}, },
{
files: ['packages/eslint-plugin/**/*.{js,ts}'],
extends: ['plugin:eslint-plugin/recommended'],
},
], ],
}; };

View file

@ -47,12 +47,12 @@ program
\`custom\`: enter your custom git clone command. We will prompt you for it.`, \`custom\`: enter your custom git clone command. We will prompt you for it.`,
) )
.description('Initialize website.') .description('Initialize website.')
.action((siteName, template, rootDir, options) => { .action((siteName, template, rootDir, options) =>
// See https://github.com/facebook/docusaurus/pull/6860 // See https://github.com/facebook/docusaurus/pull/6860
import('../lib/index.js').then(({default: init}) => { import('../lib/index.js').then(({default: init}) =>
init(path.resolve(rootDir ?? '.'), siteName, template, options); init(path.resolve(rootDir ?? '.'), siteName, template, options),
}); ),
}); );
program.parse(process.argv); program.parse(process.argv);

View file

@ -128,11 +128,11 @@ function newLine(): void {
} }
const logger = { const logger = {
red: chalk.red, red: (msg: string | number): string => chalk.red(msg),
yellow: chalk.yellow, yellow: (msg: string | number): string => chalk.yellow(msg),
green: chalk.green, green: (msg: string | number): string => chalk.green(msg),
bold: chalk.bold, bold: (msg: string | number): string => chalk.bold(msg),
dim: chalk.dim, dim: (msg: string | number): string => chalk.dim(msg),
path, path,
url, url,
name, name,

View file

@ -0,0 +1,9 @@
foo
`bar`
```js
baz
```
export const toc = 1;

View file

@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`toc remark plugin does not overwrite TOC var if no TOC 1`] = `
"foo
\`bar\`
\`\`\`js
baz
\`\`\`
export const toc = 1;
"
`;
exports[`toc remark plugin escapes inline code 1`] = ` exports[`toc remark plugin escapes inline code 1`] = `
"export const toc = [ "export const toc = [
{ {

View file

@ -30,6 +30,14 @@ describe('toc remark plugin', () => {
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
}); });
// A very implicit API: we allow users to hand-write the toc variable. It will
// get overwritten in most cases, but until we find a better way, better keep
// supporting this
it('does not overwrite TOC var if no TOC', async () => {
const result = await processFixture('no-heading-with-toc-export');
expect(result).toMatchSnapshot();
});
it('works on non text phrasing content', async () => { it('works on non text phrasing content', async () => {
const result = await processFixture('non-text-content'); const result = await processFixture('non-text-content');
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();

View file

@ -89,8 +89,10 @@ export default function plugin(): Transformer {
const {children} = root as Parent<Literal>; const {children} = root as Parent<Literal>;
const targetIndex = getOrCreateExistingTargetIndex(children); const targetIndex = getOrCreateExistingTargetIndex(children);
children[targetIndex]!.value = `export const ${name} = ${stringifyObject( if (headings.length) {
headings, children[targetIndex]!.value = `export const ${name} = ${stringifyObject(
)};`; headings,
)};`;
}
}; };
} }

View file

@ -8,7 +8,7 @@
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import {Globby} from '@docusaurus/utils'; import {Globby, DOCUSAURUS_VERSION} from '@docusaurus/utils';
import importFresh from 'import-fresh'; import importFresh from 'import-fresh';
import Color from 'color'; import Color from 'color';
@ -23,9 +23,6 @@ import type {
VersionTwoConfig, VersionTwoConfig,
} from './types'; } from './types';
const DOCUSAURUS_VERSION = (importFresh('../package.json') as {version: string})
.version;
async function walk(dir: string): Promise<string[]> { async function walk(dir: string): Promise<string[]> {
const results: string[] = []; const results: string[] = [];
const list = await fs.readdir(dir); const list = await fs.readdir(dir);
@ -82,7 +79,8 @@ export async function migrateDocusaurusProject(
shouldMigratePages: boolean = false, shouldMigratePages: boolean = false,
): Promise<void> { ): Promise<void> {
async function createMigrationContext(): Promise<MigrationContext> { async function createMigrationContext(): Promise<MigrationContext> {
const v1Config = importFresh(`${siteDir}/siteConfig`) as VersionOneConfig; const v1Config = (await import(`${siteDir}/siteConfig`))
.default as VersionOneConfig;
logger.info('Starting migration from v1 to v2...'); logger.info('Starting migration from v1 to v2...');
const deps = { const deps = {
'@docusaurus/core': DOCUSAURUS_VERSION, '@docusaurus/core': DOCUSAURUS_VERSION,
@ -444,9 +442,9 @@ async function migrateBlogFiles(context: MigrationContext) {
async function handleVersioning(context: MigrationContext) { async function handleVersioning(context: MigrationContext) {
const {siteDir, newDir} = context; const {siteDir, newDir} = context;
if (await fs.pathExists(path.join(siteDir, 'versions.json'))) { if (await fs.pathExists(path.join(siteDir, 'versions.json'))) {
const loadedVersions: string[] = await fs.readJSON( const loadedVersions = (await fs.readJSON(
path.join(siteDir, 'versions.json'), path.join(siteDir, 'versions.json'),
); )) as string[];
await fs.copyFile( await fs.copyFile(
path.join(siteDir, 'versions.json'), path.join(siteDir, 'versions.json'),
path.join(newDir, 'versions.json'), path.join(newDir, 'versions.json'),
@ -488,7 +486,11 @@ async function migrateVersionedDocs(
path.join(newDir, 'versioned_docs', `version-${version}`), path.join(newDir, 'versioned_docs', `version-${version}`),
); );
await fs.copy( await fs.copy(
path.join(newDir, 'versioned_docs', `version-${versions[index - 1]}`), path.join(
newDir,
'versioned_docs',
`version-${versions[index - 1]!}`,
),
path.join(newDir, 'versioned_docs', `version-${version}`), path.join(newDir, 'versioned_docs', `version-${version}`),
); );
await fs.copy( await fs.copy(
@ -497,7 +499,11 @@ async function migrateVersionedDocs(
); );
} catch { } catch {
await fs.copy( await fs.copy(
path.join(newDir, 'versioned_docs', `version-${versions[index - 1]}`), path.join(
newDir,
'versioned_docs',
`version-${versions[index - 1]!}`,
),
path.join(newDir, 'versioned_docs', `version-${version}`), path.join(newDir, 'versioned_docs', `version-${version}`),
); );
} }
@ -543,7 +549,7 @@ async function migrateVersionedSidebar(
`version-${version}-sidebars.json`, `version-${version}-sidebars.json`,
); );
try { try {
sidebarEntries = await fs.readJSON(sidebarPath); sidebarEntries = (await fs.readJSON(sidebarPath)) as SidebarEntries;
} catch { } catch {
sidebars.push({version, entries: sidebars[i - 1]!.entries}); sidebars.push({version, entries: sidebars[i - 1]!.entries});
return; return;

View file

@ -100,9 +100,9 @@ export default async function pluginContentDocs(
.command(command) .command(command)
.arguments('<version>') .arguments('<version>')
.description(commandDescription) .description(commandDescription)
.action((version: unknown) => { .action((version: unknown) =>
cliDocsVersionCommand(version, options, context); cliDocsVersionCommand(version, options, context),
}); );
}, },
getTranslationFiles({content}) { getTranslationFiles({content}) {

View file

@ -21,7 +21,7 @@ const createContainer = () => {
}; };
export default async function renderReloadPopup(props: Props): Promise<void> { export default async function renderReloadPopup(props: Props): Promise<void> {
const container = getContainer() || createContainer(); const container = getContainer() ?? createContainer();
const ReloadPopup = (await import('@theme/PwaReloadPopup')).default; const ReloadPopup = (await import('@theme/PwaReloadPopup')).default;
ReactDOM.render(<ReloadPopup {...props} />, container); ReactDOM.render(<ReloadPopup {...props} />, container);
} }

View file

@ -23,6 +23,7 @@ describe('createSitemap', () => {
changefreq: EnumChangefreq.DAILY, changefreq: EnumChangefreq.DAILY,
priority: 0.7, priority: 0.7,
ignorePatterns: [], ignorePatterns: [],
filename: 'sitemap.xml',
}, },
); );
expect(sitemap).toContain( expect(sitemap).toContain(
@ -49,6 +50,7 @@ describe('createSitemap', () => {
changefreq: EnumChangefreq.DAILY, changefreq: EnumChangefreq.DAILY,
priority: 0.7, priority: 0.7,
ignorePatterns: [], ignorePatterns: [],
filename: 'sitemap.xml',
}, },
); );
expect(sitemap).not.toContain('404'); expect(sitemap).not.toContain('404');
@ -70,6 +72,7 @@ describe('createSitemap', () => {
// Deep ignore // Deep ignore
'/tags/**', '/tags/**',
], ],
filename: 'sitemap.xml',
}, },
); );
expect(sitemap).not.toContain('/search/</loc>'); expect(sitemap).not.toContain('/search/</loc>');
@ -89,6 +92,7 @@ describe('createSitemap', () => {
changefreq: EnumChangefreq.DAILY, changefreq: EnumChangefreq.DAILY,
priority: 0.7, priority: 0.7,
ignorePatterns: [], ignorePatterns: [],
filename: 'sitemap.xml',
}, },
); );
@ -110,6 +114,7 @@ describe('createSitemap', () => {
changefreq: EnumChangefreq.DAILY, changefreq: EnumChangefreq.DAILY,
priority: 0.7, priority: 0.7,
ignorePatterns: [], ignorePatterns: [],
filename: 'sitemap.xml',
}, },
); );
@ -131,6 +136,7 @@ describe('createSitemap', () => {
changefreq: EnumChangefreq.DAILY, changefreq: EnumChangefreq.DAILY,
priority: 0.7, priority: 0.7,
ignorePatterns: [], ignorePatterns: [],
filename: 'sitemap.xml',
}, },
); );

View file

@ -11,7 +11,7 @@ import CodeBlock from '@theme/CodeBlock';
import type {Props} from '@theme/MDXComponents/Code'; import type {Props} from '@theme/MDXComponents/Code';
export default function MDXCode(props: Props): JSX.Element { export default function MDXCode(props: Props): JSX.Element {
const inlineElements = [ const inlineElements: (string | undefined)[] = [
'a', 'a',
'b', 'b',
'big', 'big',
@ -26,7 +26,10 @@ export default function MDXCode(props: Props): JSX.Element {
const shouldBeInline = React.Children.toArray(props.children).every( const shouldBeInline = React.Children.toArray(props.children).every(
(el) => (el) =>
(typeof el === 'string' && !el.includes('\n')) || (typeof el === 'string' && !el.includes('\n')) ||
(isValidElement(el) && inlineElements.includes(el.props.mdxType)), (isValidElement(el) &&
inlineElements.includes(
(el.props as {mdxType: string} | null)?.mdxType,
)),
); );
return shouldBeInline ? ( return shouldBeInline ? (

View file

@ -15,7 +15,8 @@ export default function MDXDetails(props: Props): JSX.Element {
// Details theme component // Details theme component
const summary = items.find( const summary = items.find(
(item): item is ReactElement<ComponentProps<'summary'>> => (item): item is ReactElement<ComponentProps<'summary'>> =>
React.isValidElement(item) && item.props?.mdxType === 'summary', React.isValidElement(item) &&
(item.props as {mdxType: string} | null)?.mdxType === 'summary',
); );
const children = <>{items.filter((item) => item !== summary)}</>; const children = <>{items.filter((item) => item !== summary)}</>;

View file

@ -5,8 +5,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {type ReactElement, type ComponentProps} from 'react'; import React, {type ReactElement} from 'react';
import Head from '@docusaurus/Head'; import Head, {type Props as HeadProps} from '@docusaurus/Head';
import type {Props} from '@theme/MDXComponents/Head'; import type {Props} from '@theme/MDXComponents/Head';
// MDX elements are wrapped through the MDX pragma. In some cases (notably usage // MDX elements are wrapped through the MDX pragma. In some cases (notably usage
@ -25,7 +25,5 @@ export default function MDXHead(props: Props): JSX.Element {
const unwrappedChildren = React.Children.map(props.children, (child) => const unwrappedChildren = React.Children.map(props.children, (child) =>
React.isValidElement(child) ? unwrapMDXElement(child) : child, React.isValidElement(child) ? unwrapMDXElement(child) : child,
); );
return ( return <Head {...(props as HeadProps)}>{unwrappedChildren}</Head>;
<Head {...(props as ComponentProps<typeof Head>)}>{unwrappedChildren}</Head>
);
} }

View file

@ -14,7 +14,8 @@ export default function MDXPre(props: Props): JSX.Element {
<CodeBlock <CodeBlock
// If this pre is created by a ``` fenced codeblock, unwrap the children // If this pre is created by a ``` fenced codeblock, unwrap the children
{...(isValidElement(props.children) && {...(isValidElement(props.children) &&
props.children.props?.originalType === 'code' (props.children.props as {originalType: string} | null)?.originalType ===
'code'
? props.children.props ? props.children.props
: {...props})} : {...props})}
/> />

View file

@ -18,12 +18,12 @@ type HistoryBlockHandler = (location: Location, action: Action) => void | false;
* will be blocked/cancelled. * will be blocked/cancelled.
*/ */
function useHistoryActionHandler(handler: HistoryBlockHandler): void { function useHistoryActionHandler(handler: HistoryBlockHandler): void {
const {block} = useHistory(); const history = useHistory();
const stableHandler = useDynamicCallback(handler); const stableHandler = useDynamicCallback(handler);
useEffect( useEffect(
// See https://github.com/remix-run/history/blob/main/docs/blocking-transitions.md // See https://github.com/remix-run/history/blob/main/docs/blocking-transitions.md
() => block((location, action) => stableHandler(location, action)), () => history.block((location, action) => stableHandler(location, action)),
[block, stableHandler], [history, stableHandler],
); );
} }

View file

@ -1,27 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = {
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
// Prevent importing lodash in client bundle for bundle size
'lodash',
'lodash.**',
'lodash/**',
// Prevent importing server code in client bundle
'**/../babel/**',
'**/../server/**',
'**/../commands/**',
'**/../webpack/**',
],
},
],
},
};

View file

@ -18,6 +18,7 @@ type State = {
error: Error | null; error: Error | null;
}; };
// eslint-disable-next-line react/function-component-definition
const DefaultFallback: FallbackFunction = (params) => ( const DefaultFallback: FallbackFunction = (params) => (
<ThemeError {...params} /> <ThemeError {...params} />
); );

View file

@ -45,9 +45,7 @@ async function createTmpTranslationFile(
return { return {
siteDir, siteDir,
readFile() { readFile: () => fs.readJSON(filePath),
return fs.readJSON(filePath);
},
}; };
} }

View file

@ -1,10 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = {
extends: ['../../.eslintrc.js', 'plugin:eslint-plugin/recommended'],
};