chore: tighten ESLint config (#6931)

* chore: tighten ESLint config

* more refactor

* refactor push

* fix
This commit is contained in:
Joshua Chen 2022-03-17 17:59:41 +08:00 committed by GitHub
parent f70ddf7e69
commit cc0bceab9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 177 additions and 193 deletions

View file

@ -62,6 +62,7 @@ module.exports = {
'no-await-in-loop': OFF, 'no-await-in-loop': OFF,
'no-case-declarations': WARNING, 'no-case-declarations': WARNING,
'no-console': OFF, 'no-console': OFF,
'no-continue': OFF,
'no-control-regex': WARNING, 'no-control-regex': WARNING,
'no-else-return': [WARNING, {allowElseIf: true}], 'no-else-return': [WARNING, {allowElseIf: true}],
'no-empty': [WARNING, {allowEmptyCatch: true}], 'no-empty': [WARNING, {allowEmptyCatch: true}],
@ -275,6 +276,7 @@ module.exports = {
}, },
], ],
'@typescript-eslint/no-inferrable-types': OFF, '@typescript-eslint/no-inferrable-types': OFF,
'@typescript-eslint/no-namespace': [WARNING, {allowDeclarations: true}],
'no-use-before-define': OFF, 'no-use-before-define': OFF,
'@typescript-eslint/no-use-before-define': [ '@typescript-eslint/no-use-before-define': [
ERROR, ERROR,
@ -286,14 +288,11 @@ module.exports = {
'no-shadow': OFF, 'no-shadow': OFF,
'@typescript-eslint/no-shadow': ERROR, '@typescript-eslint/no-shadow': ERROR,
'no-unused-vars': OFF, 'no-unused-vars': OFF,
'@typescript-eslint/no-unused-vars': [ // We don't provide any escape hatches for this rule. Rest siblings and
ERROR, // function placeholder params are always ignored, and any other unused
{ // locals must be justified with a disable comment.
argsIgnorePattern: '^_', '@typescript-eslint/no-unused-vars': [ERROR, {ignoreRestSiblings: true}],
varsIgnorePattern: '^_', '@typescript-eslint/prefer-optional-chain': ERROR,
ignoreRestSiblings: true,
},
],
}, },
overrides: [ overrides: [
{ {
@ -340,7 +339,17 @@ module.exports = {
}, },
}, },
{ {
files: ['*.test.ts', '*.test.tsx'], // Internal files where extraneous deps don't matter much at long as
// they run
files: [
'*.test.ts',
'*.test.tsx',
'admin/**',
'jest/**',
'website/**',
'packages/docusaurus-theme-translations/update.mjs',
'packages/docusaurus-theme-translations/src/utils.ts',
],
rules: { rules: {
'import/no-extraneous-dependencies': OFF, 'import/no-extraneous-dependencies': OFF,
}, },

View file

@ -10,8 +10,19 @@ import fs from 'fs-extra';
type PackageJsonFile = { type PackageJsonFile = {
file: string; file: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any content: {
content: any; name?: string;
private?: boolean;
version?: string;
repository?: {
type?: string;
url?: string;
directory?: string;
};
publishConfig?: {
access?: string;
};
};
}; };
async function getPackagesJsonFiles(): Promise<PackageJsonFile[]> { async function getPackagesJsonFiles(): Promise<PackageJsonFile[]> {

View file

@ -9,6 +9,6 @@ import type {Handler} from '@netlify/functions';
import {createPlaygroundResponse} from '../functionUtils/playgroundUtils'; import {createPlaygroundResponse} from '../functionUtils/playgroundUtils';
export const handler: Handler = async function handler(_event, _context) { export const handler: Handler = async function handler() {
return createPlaygroundResponse('codesandbox'); return createPlaygroundResponse('codesandbox');
}; };

View file

@ -13,7 +13,7 @@ import {
createPlaygroundDocumentationResponse, createPlaygroundDocumentationResponse,
} from '../functionUtils/playgroundUtils'; } from '../functionUtils/playgroundUtils';
export const handler: Handler = async (event, _context) => { export const handler: Handler = async (event) => {
const playgroundName = readPlaygroundName(event); const playgroundName = readPlaygroundName(event);
return playgroundName return playgroundName
? createPlaygroundResponse(playgroundName) ? createPlaygroundResponse(playgroundName)

View file

@ -9,6 +9,6 @@ import type {Handler} from '@netlify/functions';
import {createPlaygroundResponse} from '../functionUtils/playgroundUtils'; import {createPlaygroundResponse} from '../functionUtils/playgroundUtils';
export const handler: Handler = async function handler(_event, _context) { export const handler: Handler = async function handler() {
return createPlaygroundResponse('stackblitz'); return createPlaygroundResponse('stackblitz');
}; };

View file

@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
/* eslint-disable import/no-extraneous-dependencies */
import fs from 'fs-extra'; import fs from 'fs-extra';
import shell from 'shelljs'; import shell from 'shelljs';

View file

@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
/* eslint-disable import/no-extraneous-dependencies */
import sharp from 'sharp'; import sharp from 'sharp';
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';

View file

@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
/* eslint-disable import/no-extraneous-dependencies */
// Forked from https://github.com/tribou/jest-serializer-path/blob/master/lib/index.js // Forked from https://github.com/tribou/jest-serializer-path/blob/master/lib/index.js
// Added some project-specific handlers // Added some project-specific handlers

View file

@ -162,7 +162,7 @@ export default async function mdxLoader(
// MDX partials are MDX files starting with _ or in a folder starting with _ // MDX partials are MDX files starting with _ or in a folder starting with _
// Partial are not expected to have associated metadata files or front matter // Partial are not expected to have associated metadata files or front matter
const isMDXPartial = options.isMDXPartial && options.isMDXPartial(filePath); const isMDXPartial = options.isMDXPartial?.(filePath);
if (isMDXPartial && hasFrontMatter) { if (isMDXPartial && hasFrontMatter) {
const errorMessage = `Docusaurus MDX partial files should not contain FrontMatter. const errorMessage = `Docusaurus MDX partial files should not contain FrontMatter.
Those partial files use the _ prefix as a convention by default, but this is configurable. Those partial files use the _ prefix as a convention by default, but this is configurable.

View file

@ -76,7 +76,7 @@ export default function plugin(options: PluginOptions = {}): Transformer {
return (root) => { return (root) => {
const headings: TOCItem[] = []; const headings: TOCItem[] = [];
visit(root, 'heading', (child: Heading, _index, parent) => { visit(root, 'heading', (child: Heading, index, parent) => {
const value = toString(child); const value = toString(child);
// depth:1 headings are titles and not included in the TOC // depth:1 headings are titles and not included in the TOC
@ -93,7 +93,7 @@ export default function plugin(options: PluginOptions = {}): Transformer {
const {children} = root as Parent<Literal>; const {children} = root as Parent<Literal>;
const targetIndex = getOrCreateExistingTargetIndex(children, name); const targetIndex = getOrCreateExistingTargetIndex(children, name);
if (headings && headings.length) { if (headings.length) {
children[targetIndex]!.value = `export const ${name} = ${stringifyObject( children[targetIndex]!.value = `export const ${name} = ${stringifyObject(
headings, headings,
)};`; )};`;

View file

@ -17,7 +17,7 @@ import type {Code, Parent} from 'mdast';
// See https://github.com/facebook/docusaurus/pull/4278 // See https://github.com/facebook/docusaurus/pull/4278
export default function plugin(this: Processor): Transformer { export default function plugin(this: Processor): Transformer {
return (root) => { return (root) => {
visit(root, 'code', (node: Code, _index, parent) => { visit(root, 'code', (node: Code, index, parent) => {
if (node.lang === 'mdx-code-block') { if (node.lang === 'mdx-code-block') {
const newChildren = (this.parse(node.value) as Parent).children; const newChildren = (this.parse(node.value) as Parent).children;

View file

@ -31,7 +31,7 @@ async function walk(dir: string): Promise<string[]> {
for (const file of list) { for (const file of list) {
const fullPath = `${dir}/${file}`; const fullPath = `${dir}/${file}`;
const stat = await fs.stat(fullPath); const stat = await fs.stat(fullPath);
if (stat && stat.isDirectory()) { if (stat.isDirectory()) {
results.push(...(await walk(fullPath))); results.push(...(await walk(fullPath)));
} else { } else {
results.push(fullPath); results.push(fullPath);

View file

@ -31,9 +31,7 @@ describe('normalizePluginOptions', () => {
}); });
it('overrides all default options with valid user options', () => { it('overrides all default options with valid user options', () => {
const createRedirects: Options['createRedirects'] = ( const createRedirects: Options['createRedirects'] = () => [];
_routePath: string,
) => [];
expect( expect(
testValidate({ testValidate({
fromExtensions: ['exe', 'zip'], fromExtensions: ['exe', 'zip'],

View file

@ -41,7 +41,7 @@ const UserOptionsSchema = Joi.object<PluginOptions>({
redirects: Joi.array() redirects: Joi.array()
.items(RedirectPluginOptionValidation) .items(RedirectPluginOptionValidation)
.default(DEFAULT_OPTIONS.redirects), .default(DEFAULT_OPTIONS.redirects),
createRedirects: Joi.function().arity(1), createRedirects: Joi.function().maxArity(1),
}).default(DEFAULT_OPTIONS); }).default(DEFAULT_OPTIONS);
export function validateOptions({ export function validateOptions({

View file

@ -45,7 +45,7 @@ async function generateBlogFeed({
const {url: siteUrl, baseUrl, title, favicon} = siteConfig; const {url: siteUrl, baseUrl, title, favicon} = siteConfig;
const blogBaseUrl = normalizeUrl([siteUrl, baseUrl, routeBasePath]); const blogBaseUrl = normalizeUrl([siteUrl, baseUrl, routeBasePath]);
const updated = blogPosts[0] && blogPosts[0].metadata.date; const updated = blogPosts[0]?.metadata.date;
const feed = new Feed({ const feed = new Feed({
id: blogBaseUrl, id: blogBaseUrl,

View file

@ -34,5 +34,5 @@ export default function markdownLoader(
finalContent = truncate(finalContent, markdownLoaderOptions.truncateMarker); finalContent = truncate(finalContent, markdownLoaderOptions.truncateMarker);
} }
return callback && callback(null, finalContent); return callback?.(null, finalContent);
} }

View file

@ -745,9 +745,7 @@ describe('site with custom sidebar items generator', () => {
} }
it('sidebarItemsGenerator is called with appropriate data', async () => { it('sidebarItemsGenerator is called with appropriate data', async () => {
const customSidebarItemsGeneratorMock = jest.fn( const customSidebarItemsGeneratorMock = jest.fn(async () => []);
async (_arg: SidebarItemsGeneratorOptionArgs) => [],
);
const {siteDir} = await loadSite(customSidebarItemsGeneratorMock); const {siteDir} = await loadSite(customSidebarItemsGeneratorMock);
const generatorArg: SidebarItemsGeneratorOptionArgs = const generatorArg: SidebarItemsGeneratorOptionArgs =

View file

@ -16,7 +16,5 @@ export default function markdownLoader(
const fileString = source; const fileString = source;
const callback = this.async(); const callback = this.async();
const options = this.getOptions(); const options = this.getOptions();
return ( return callback?.(null, linkify(fileString, this.resourcePath, options));
callback && callback(null, linkify(fileString, this.resourcePath, options))
);
} }

View file

@ -118,26 +118,24 @@ function getSidebarTranslationFileContent(
}, },
]); ]);
if (category.link) { if (category.link?.type === 'generated-index') {
if (category.link.type === 'generated-index') { if (category.link.title) {
if (category.link.title) { entries.push([
entries.push([ `sidebar.${sidebarName}.category.${category.label}.link.generated-index.title`,
`sidebar.${sidebarName}.category.${category.label}.link.generated-index.title`, {
{ message: category.link.title,
message: category.link.title, description: `The generated-index page title for category ${category.label} in sidebar ${sidebarName}`,
description: `The generated-index page title for category ${category.label} in sidebar ${sidebarName}`, },
}, ]);
]); }
} if (category.link.description) {
if (category.link.description) { entries.push([
entries.push([ `sidebar.${sidebarName}.category.${category.label}.link.generated-index.description`,
`sidebar.${sidebarName}.category.${category.label}.link.generated-index.description`, {
{ message: category.link.description,
message: category.link.description, description: `The generated-index page description for category ${category.label} in sidebar ${sidebarName}`,
description: `The generated-index page description for category ${category.label} in sidebar ${sidebarName}`, },
}, ]);
]);
}
} }
} }

View file

@ -18,5 +18,5 @@ export default function markdownLoader(
// TODO provide additional md processing here? like interlinking pages? // TODO provide additional md processing here? like interlinking pages?
// fileString = linkify(fileString) // fileString = linkify(fileString)
return callback && callback(null, fileString); return callback?.(null, fileString);
} }

View file

@ -39,9 +39,7 @@ function PluginContent({
<div> <div>
{Object.entries(pluginContent) {Object.entries(pluginContent)
// filter plugin instances with no content // filter plugin instances with no content
.filter( .filter(([, pluginInstanceContent]) => !!pluginInstanceContent)
([_pluginId, pluginInstanceContent]) => !!pluginInstanceContent,
)
.map(([pluginId, pluginInstanceContent]) => ( .map(([pluginId, pluginInstanceContent]) => (
<PluginInstanceContent <PluginInstanceContent
key={pluginId} key={pluginId}
@ -61,7 +59,7 @@ export default function DebugContent({allContent}: Props): JSX.Element {
<div> <div>
{Object.entries(allContent) {Object.entries(allContent)
// filter plugins with no content // filter plugins with no content
.filter(([_pluginName, pluginContent]) => .filter(([, pluginContent]) =>
Object.values(pluginContent).some( Object.values(pluginContent).some(
(instanceContent) => !!instanceContent, (instanceContent) => !!instanceContent,
), ),

View file

@ -79,7 +79,7 @@ function isStandaloneDisplayMode() {
const OfflineModeActivationStrategiesImplementations = { const OfflineModeActivationStrategiesImplementations = {
always: () => true, always: () => true,
mobile: () => window.innerWidth <= MAX_MOBILE_WIDTH, mobile: () => window.innerWidth <= MAX_MOBILE_WIDTH,
saveData: () => !!(navigator.connection && navigator.connection.saveData), saveData: () => !!navigator.connection?.saveData,
appInstalled: async () => { appInstalled: async () => {
const installedEventFired = await isAppInstalledEventFired(); const installedEventFired = await isAppInstalledEventFired();
const installedRelatedApps = await isAppInstalledRelatedApps(); const installedRelatedApps = await isAppInstalledRelatedApps();

View file

@ -137,7 +137,7 @@ function getPossibleURLs(url) {
}); });
} }
const type = event.data && event.data.type; const type = event.data?.type;
if (type === 'SKIP_WAITING') { if (type === 'SKIP_WAITING') {
self.skipWaiting(); self.skipWaiting();

View file

@ -833,11 +833,8 @@ declare module '@theme/IconExternalLink' {
} }
declare module '@theme/TagsListByLetter' { declare module '@theme/TagsListByLetter' {
export type TagsListItem = Readonly<{ import type {TagsListItem} from '@docusaurus/theme-common';
name: string;
permalink: string;
count: number;
}>;
export interface Props { export interface Props {
readonly tags: readonly TagsListItem[]; readonly tags: readonly TagsListItem[];
} }
@ -853,7 +850,7 @@ declare module '@theme/TagsListInline' {
} }
declare module '@theme/Tag' { declare module '@theme/Tag' {
import type {TagsListItem} from '@theme/TagsListByLetter'; import type {TagsListItem} from '@docusaurus/theme-common';
import type {Optional} from 'utility-types'; import type {Optional} from 'utility-types';
export interface Props extends Optional<TagsListItem, 'count'> {} export interface Props extends Optional<TagsListItem, 'count'> {}

View file

@ -234,9 +234,7 @@ function DocSidebarItemHtml({
)} )}
key={index} key={index}
// eslint-disable-next-line react/no-danger // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{__html: value}}
__html: value,
}}
/> />
); );
} }

View file

@ -14,9 +14,7 @@ export default function FooterCopyright({copyright}: Props): JSX.Element {
className="footer__copyright" className="footer__copyright"
// Developer provided the HTML, so assume it's safe. // Developer provided the HTML, so assume it's safe.
// eslint-disable-next-line react/no-danger // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{__html: copyright}}
__html: copyright,
}}
/> />
); );
} }

View file

@ -18,9 +18,7 @@ function ColumnLinkItem({item}: {item: ColumnItemType}) {
className="footer__item" className="footer__item"
// Developer provided the HTML, so assume it's safe. // Developer provided the HTML, so assume it's safe.
// eslint-disable-next-line react/no-danger // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{__html: item.html}}
__html: item.html,
}}
/> />
) : ( ) : (
<li key={item.href || item.to} className="footer__item"> <li key={item.href || item.to} className="footer__item">

View file

@ -19,9 +19,7 @@ function SimpleLinkItem({item}: {item: Props['links'][number]}) {
className="footer__link-item" className="footer__link-item"
// Developer provided the HTML, so assume it's safe. // Developer provided the HTML, so assume it's safe.
// eslint-disable-next-line react/no-danger // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{__html: item.html}}
__html: item.html,
}}
/> />
) : ( ) : (
<LinkItem item={item} /> <LinkItem item={item} />

View file

@ -41,7 +41,7 @@ function DefaultNavbarItemDesktop({
function DefaultNavbarItemMobile({ function DefaultNavbarItemMobile({
className, className,
isDropdownItem: _isDropdownItem, isDropdownItem,
...props ...props
}: DesktopOrMobileNavBarItemProps) { }: DesktopOrMobileNavBarItemProps) {
return ( return (
@ -53,7 +53,7 @@ function DefaultNavbarItemMobile({
export default function DefaultNavbarItem({ export default function DefaultNavbarItem({
mobile = false, mobile = false,
position: _position, // Need to destructure position from props so that it doesn't get passed on. position, // Need to destructure position from props so that it doesn't get passed on.
...props ...props
}: Props): JSX.Element { }: Props): JSX.Element {
const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop; const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;

View file

@ -124,7 +124,7 @@ function DropdownNavbarItemDesktop({
function DropdownNavbarItemMobile({ function DropdownNavbarItemMobile({
items, items,
className, className,
position: _position, // Need to destructure position from props so that it doesn't get passed on. position, // Need to destructure position from props so that it doesn't get passed on.
...props ...props
}: DesktopOrMobileNavBarItemProps) { }: DesktopOrMobileNavBarItemProps) {
const localPathname = useLocalPathname(); const localPathname = useLocalPathname();

View file

@ -5,26 +5,25 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
export {useThemeConfig} from './utils/useThemeConfig'; export {
useThemeConfig,
type ThemeConfig,
type UserThemeConfig,
type Navbar,
type NavbarItem,
type NavbarLogo,
type MultiColumnFooter,
type SimpleFooter,
type Footer,
type FooterLogo,
type FooterLinkItem,
type ColorModeConfig,
} from './utils/useThemeConfig';
export { export {
DocSidebarItemsExpandedStateProvider, DocSidebarItemsExpandedStateProvider,
useDocSidebarItemsExpandedState, useDocSidebarItemsExpandedState,
} from './utils/docSidebarItemsExpandedState'; } from './utils/docSidebarItemsExpandedState';
export type {
ThemeConfig,
UserThemeConfig,
Navbar,
NavbarItem,
NavbarLogo,
MultiColumnFooter,
SimpleFooter,
Footer,
FooterLogo,
FooterLinkItem,
ColorModeConfig,
} from './utils/useThemeConfig';
export {createStorageSlot, listStorageKeys} from './utils/storageUtils'; export {createStorageSlot, listStorageKeys} from './utils/storageUtils';
export {useAlternatePageUtils} from './utils/useAlternatePageUtils'; export {useAlternatePageUtils} from './utils/useAlternatePageUtils';
@ -63,14 +62,14 @@ export {useLocationChange} from './utils/useLocationChange';
export {usePrevious} from './utils/usePrevious'; export {usePrevious} from './utils/usePrevious';
export {useCollapsible, Collapsible} from './components/Collapsible'; export {
export type { useCollapsible,
UseCollapsibleConfig, Collapsible,
UseCollapsibleReturns, type UseCollapsibleConfig,
type UseCollapsibleReturns,
} from './components/Collapsible'; } from './components/Collapsible';
export {default as Details} from './components/Details'; export {default as Details, type DetailsProps} from './components/Details';
export type {DetailsProps} from './components/Details';
export { export {
MobileSecondaryMenuProvider, MobileSecondaryMenuProvider,
@ -97,13 +96,19 @@ export {
export {useLocalPathname} from './utils/useLocalPathname'; export {useLocalPathname} from './utils/useLocalPathname';
export {translateTagsPageTitle, listTagsByLetters} from './utils/tagsUtils'; export {
export type {TagLetterEntry} from './utils/tagsUtils'; translateTagsPageTitle,
listTagsByLetters,
type TagLetterEntry,
type TagsListItem,
} from './utils/tagsUtils';
export {useHistoryPopHandler} from './utils/historyUtils'; export {useHistoryPopHandler} from './utils/historyUtils';
export {default as useTOCHighlight} from './utils/useTOCHighlight'; export {
export type {TOCHighlightConfig} from './utils/useTOCHighlight'; default as useTOCHighlight,
type TOCHighlightConfig,
} from './utils/useTOCHighlight';
export { export {
useFilteredAndTreeifiedTOC, useFilteredAndTreeifiedTOC,

View file

@ -199,14 +199,12 @@ function getBreadcrumbs({
function extract(items: PropSidebar) { function extract(items: PropSidebar) {
for (const item of items) { for (const item of items) {
if ( if (
item.type === 'category' && (item.type === 'category' &&
(isSamePath(item.href, pathname) || extract(item.items)) (isSamePath(item.href, pathname) || extract(item.items))) ||
(item.type === 'link' && isSamePath(item.href, pathname))
) { ) {
breadcrumbs.push(item); breadcrumbs.push(item);
return true; return true;
} else if (item.type === 'link' && isSamePath(item.href, pathname)) {
breadcrumbs.push(item);
return true;
} }
} }

View file

@ -10,7 +10,7 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
export function useTitleFormatter(title?: string | undefined): string { export function useTitleFormatter(title?: string | undefined): string {
const {siteConfig} = useDocusaurusContext(); const {siteConfig} = useDocusaurusContext();
const {title: siteTitle, titleDelimiter} = siteConfig; const {title: siteTitle, titleDelimiter} = siteConfig;
return title && title.trim().length return title?.trim().length
? `${title.trim()} ${titleDelimiter} ${siteTitle}` ? `${title.trim()} ${titleDelimiter} ${siteTitle}`
: siteTitle; : siteTitle;
} }

View file

@ -14,7 +14,11 @@ export const translateTagsPageTitle = (): string =>
description: 'The title of the tag list page', description: 'The title of the tag list page',
}); });
type TagsListItem = Readonly<{name: string; permalink: string; count: number}>; // TODO remove duplicated type :s export type TagsListItem = Readonly<{
name: string;
permalink: string;
count: number;
}>;
export type TagLetterEntry = Readonly<{letter: string; tags: TagsListItem[]}>; export type TagLetterEntry = Readonly<{letter: string; tags: TagsListItem[]}>;

View file

@ -8,10 +8,8 @@
import {useEffect, useRef} from 'react'; import {useEffect, useRef} from 'react';
import {useThemeConfig} from './useThemeConfig'; import {useThemeConfig} from './useThemeConfig';
/* // TODO make the hardcoded theme-classic classnames configurable (or add them
TODO make the hardcoded theme-classic classnames configurable // to ThemeClassNames?)
(or add them to ThemeClassNames?)
*/
// If the anchor has no height and is just a "marker" in the dom; we'll use the // If the anchor has no height and is just a "marker" in the dom; we'll use the
// parent (normally the link text) rect boundaries instead // parent (normally the link text) rect boundaries instead

View file

@ -10,7 +10,6 @@
// update script has ts-check anyways) (b) the test coverage isn't destroyed by // update script has ts-check anyways) (b) the test coverage isn't destroyed by
// the untested update.mjs file (c) we can ergonomically import the util // the untested update.mjs file (c) we can ergonomically import the util
// functions in the Jest test without using `await import` // functions in the Jest test without using `await import`
/* eslint-disable import/no-extraneous-dependencies */
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';

View file

@ -6,7 +6,6 @@
*/ */
// @ts-check // @ts-check
/* eslint-disable import/no-extraneous-dependencies */
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import path from 'path'; import path from 'path';

View file

@ -49,7 +49,6 @@ export async function getDataFileData<T>(
const unsafeContent = Yaml.load(contentString); const unsafeContent = Yaml.load(contentString);
return validate(unsafeContent); return validate(unsafeContent);
} catch (err) { } catch (err) {
// TODO replace later by error cause, see https://v8.dev/features/error-cause
logger.error`The ${params.fileType} file at path=${filePath} looks invalid.`; logger.error`The ${params.fileType} file at path=${filePath} looks invalid.`;
throw err; throw err;
} }

View file

@ -38,7 +38,6 @@ export function createExcerpt(fileString: string): string | undefined {
let inCode = false; let inCode = false;
let lastCodeFence = ''; let lastCodeFence = '';
/* eslint-disable no-continue */
for (const fileLine of fileLines) { for (const fileLine of fileLines) {
// Skip empty line. // Skip empty line.
if (!fileLine.trim()) { if (!fileLine.trim()) {

View file

@ -50,7 +50,6 @@ export function normalizeUrl(rawUrls: string[]): string {
if (i === urls.length - 1 && hasEndingSlash) { if (i === urls.length - 1 && hasEndingSlash) {
resultArray.push('/'); resultArray.push('/');
} }
// eslint-disable-next-line no-continue
continue; continue;
} }

View file

@ -72,8 +72,7 @@ export default async function beforeCli() {
* @param {import('update-notifier').UpdateInfo} update * @param {import('update-notifier').UpdateInfo} update
*/ */
function ignoreUpdate(update) { function ignoreUpdate(update) {
const isCanaryRelease = const isCanaryRelease = update?.current?.startsWith('0.0.0');
update && update.current && update.current.startsWith('0.0.0');
return isCanaryRelease; return isCanaryRelease;
} }

View file

@ -52,8 +52,7 @@ export default function ComponentCreator(
if (chunkRegistry) { if (chunkRegistry) {
// eslint-disable-next-line prefer-destructuring // eslint-disable-next-line prefer-destructuring
optsLoader[key] = chunkRegistry[0]; optsLoader[key] = chunkRegistry[0];
optsModules.push(chunkRegistry[1]); optsModules.push(chunkRegistry[1], chunkRegistry[2]);
optsWebpack.push(chunkRegistry[2]);
} }
}); });
@ -75,7 +74,7 @@ export default function ComponentCreator(
const nonDefaultKeys = Object.keys(loaded[key]).filter( const nonDefaultKeys = Object.keys(loaded[key]).filter(
(k) => k !== 'default', (k) => k !== 'default',
); );
if (nonDefaultKeys && nonDefaultKeys.length) { if (nonDefaultKeys?.length) {
nonDefaultKeys.forEach((nonDefaultKey) => { nonDefaultKeys.forEach((nonDefaultKey) => {
val[keyPath[keyPath.length - 1]!][nonDefaultKey] = val[keyPath[keyPath.length - 1]!][nonDefaultKey] =
loaded[key][nonDefaultKey]; loaded[key][nonDefaultKey];

View file

@ -26,20 +26,20 @@ function statusTable(): string {
head: ['Status', 'CLI option', 'Description'], head: ['Status', 'CLI option', 'Description'],
}); });
table.push({ table.push(
[tableStatusLabel('safe')]: [ {
'', [tableStatusLabel('safe')]: [
` '',
`
This component is safe to swizzle and was designed for this purpose. This component is safe to swizzle and was designed for this purpose.
The swizzled component is retro-compatible with minor version upgrades. The swizzled component is retro-compatible with minor version upgrades.
`, `,
], ],
}); },
{
table.push({ [tableStatusLabel('unsafe')]: [
[tableStatusLabel('unsafe')]: [ logger.code('--danger'),
logger.code('--danger'), `
`
This component is unsafe to swizzle, but you can still do it! This component is unsafe to swizzle, but you can still do it!
Warning: we may release breaking changes within minor version upgrades. Warning: we may release breaking changes within minor version upgrades.
You will have to upgrade your component manually and maintain it over time. You will have to upgrade your component manually and maintain it over time.
@ -49,17 +49,17 @@ ${logger.green(
)}: your customization can't be done in a ${tableStatusLabel('safe')} way? )}: your customization can't be done in a ${tableStatusLabel('safe')} way?
Report it here: https://github.com/facebook/docusaurus/discussions/5468 Report it here: https://github.com/facebook/docusaurus/discussions/5468
`, `,
], ],
}); },
{
table.push({ [tableStatusLabel('forbidden')]: [
[tableStatusLabel('forbidden')]: [ '',
'', `
`
This component is not meant to be swizzled. This component is not meant to be swizzled.
`, `,
], ],
}); },
);
return table.toString(); return table.toString();
} }
@ -69,33 +69,34 @@ function actionsTable(): string {
head: ['Actions', 'CLI option', 'Description'], head: ['Actions', 'CLI option', 'Description'],
}); });
table.push({ table.push(
[logger.bold('Wrap')]: [ {
logger.code('--wrap'), [logger.bold('Wrap')]: [
` logger.code('--wrap'),
`
Creates a wrapper around the original theme component. Creates a wrapper around the original theme component.
Allows rendering other components before/after the original theme component. Allows rendering other components before/after the original theme component.
${logger.green('Tip')}: prefer ${logger.code( ${logger.green('Tip')}: prefer ${logger.code(
'--wrap', '--wrap',
)} whenever possible to reduce the amount of code to maintain. )} whenever possible to reduce the amount of code to maintain.
`, `,
], ],
}); },
{
table.push({ [logger.bold('Eject')]: [
[logger.bold('Eject')]: [ logger.code('--eject'),
logger.code('--eject'), `
`
Ejects the full source code of the original theme component. Ejects the full source code of the original theme component.
Allows overriding of the original component entirely with your own UI and logic. Allows overriding of the original component entirely with your own UI and logic.
${logger.green('Tip')}: ${logger.code( ${logger.green('Tip')}: ${logger.code(
'--eject', '--eject',
)} can be useful for completely redesigning a component. )} can be useful for completely redesigning a component.
`, `,
], ],
}); },
);
return table.toString(); return table.toString();
} }

View file

@ -168,13 +168,10 @@ describe('normalizeConfig', () => {
['this/should/work', {too: 'yes'}], ['this/should/work', {too: 'yes'}],
], ],
], ],
[ ['should accept function for plugin', [function plugin() {}]],
'should accept function for plugin',
[function plugin(_context, _options) {}],
],
[ [
'should accept [function, object] for plugin', 'should accept [function, object] for plugin',
[[(_context, _options) => {}, {it: 'should work'}]], [[() => {}, {it: 'should work'}]],
], ],
])(`%s for the input of: %p`, (_message, plugins) => { ])(`%s for the input of: %p`, (_message, plugins) => {
expect(() => { expect(() => {
@ -209,13 +206,10 @@ describe('normalizeConfig', () => {
['this/should/work', {too: 'yes'}], ['this/should/work', {too: 'yes'}],
], ],
], ],
[ ['should accept function for theme', [function theme() {}]],
'should accept function for theme',
[function theme(_context, _options) {}],
],
[ [
'should accept [function, object] for theme', 'should accept [function, object] for theme',
[[function theme(_context, _options) {}, {it: 'should work'}]], [[function theme() {}, {it: 'should work'}]],
], ],
])(`%s for the input of: %p`, (_message, themes) => { ])(`%s for the input of: %p`, (_message, themes) => {
expect(() => { expect(() => {

View file

@ -190,8 +190,10 @@ async function filterExistingFileLinks({
// -> /outDir/javadoc/index.html // -> /outDir/javadoc/index.html
const filePathsToTry: string[] = [baseFilePath]; const filePathsToTry: string[] = [baseFilePath];
if (!path.extname(baseFilePath)) { if (!path.extname(baseFilePath)) {
filePathsToTry.push(`${baseFilePath}.html`); filePathsToTry.push(
filePathsToTry.push(path.join(baseFilePath, 'index.html')); `${baseFilePath}.html`,
path.join(baseFilePath, 'index.html'),
);
} }
for (const file of filePathsToTry) { for (const file of filePathsToTry) {

View file

@ -277,7 +277,7 @@ function createMDXFallbackPlugin({
path.resolve(siteDir, dir), path.resolve(siteDir, dir),
), ),
siteDir, siteDir,
isMDXPartial: (_filename: string) => true, // External mdx files are always meant to be imported as partials isMDXPartial: () => true, // External mdx files are always meant to be imported as partials
isMDXPartialFrontMatterWarningDisabled: true, // External mdx files might have front matter, let's just disable the warning isMDXPartialFrontMatterWarningDisabled: true, // External mdx files might have front matter, let's just disable the warning
remarkPlugins: [admonitions], remarkPlugins: [admonitions],
}, },
@ -341,8 +341,10 @@ export default ${JSON.stringify(siteConfig, null, 2)};
`, `,
); );
plugins.push(createBootstrapPlugin({siteDir, siteConfig})); plugins.push(
plugins.push(createMDXFallbackPlugin({siteDir, siteConfig})); createBootstrapPlugin({siteDir, siteConfig}),
createMDXFallbackPlugin({siteDir, siteConfig}),
);
// Load client modules. // Load client modules.
const clientModules = loadClientModules(plugins); const clientModules = loadClientModules(plugins);

View file

@ -308,10 +308,9 @@ ${sourceWarningPart(path.node)}`);
), ),
) )
.pop(); .pop();
const isJSXText = singleChildren && singleChildren.isJSXText(); const isJSXText = singleChildren?.isJSXText();
const isJSXExpressionContainer = const isJSXExpressionContainer =
singleChildren && singleChildren?.isJSXExpressionContainer() &&
singleChildren.isJSXExpressionContainer() &&
(singleChildren.get('expression') as NodePath).evaluate().confident; (singleChildren.get('expression') as NodePath).evaluate().confident;
if (isJSXText || isJSXExpressionContainer) { if (isJSXText || isJSXExpressionContainer) {

View file

@ -23,7 +23,7 @@ function testStylelintRule(config, tests) {
const checkTestCaseContent = (testCase) => const checkTestCaseContent = (testCase) =>
testCase.description || testCase.code || 'no description'; testCase.description || testCase.code || 'no description';
if (tests.accept && tests.accept.length) { if (tests.accept?.length) {
describe('accept cases', () => { describe('accept cases', () => {
tests.accept.forEach((testCase) => { tests.accept.forEach((testCase) => {
it(`${checkTestCaseContent(testCase)}`, async () => { it(`${checkTestCaseContent(testCase)}`, async () => {
@ -46,7 +46,7 @@ function testStylelintRule(config, tests) {
}); });
} }
if (tests.reject && tests.reject.length) { if (tests.reject?.length) {
describe('reject cases', () => { describe('reject cases', () => {
tests.reject.forEach((testCase) => { tests.reject.forEach((testCase) => {
it(`${checkTestCaseContent(testCase)}`, async () => { it(`${checkTestCaseContent(testCase)}`, async () => {

View file

@ -120,7 +120,6 @@ for (const componentName of componentNames) {
logger.warn( logger.warn(
`${componentName} is marked as forbidden for action ${action} => skipping`, `${componentName} is marked as forbidden for action ${action} => skipping`,
); );
// eslint-disable-next-line no-continue
continue; continue;
} }

View file

@ -13,7 +13,6 @@ import path from 'path';
import imageSize from 'image-size'; import imageSize from 'image-size';
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace jest { namespace jest {
interface Matchers<R> { interface Matchers<R> {
toHaveGoodDimensions: () => R; toHaveGoodDimensions: () => R;

View file

@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
/* eslint-disable import/no-extraneous-dependencies */
const path = require('path'); const path = require('path');
const fs = require('fs-extra'); const fs = require('fs-extra');

View file

@ -7,7 +7,6 @@
import React from 'react'; import React from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
// eslint-disable-next-line import/no-extraneous-dependencies
import {MDXProvider} from '@mdx-js/react'; import {MDXProvider} from '@mdx-js/react';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';

View file

@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// eslint-disable-next-line import/no-extraneous-dependencies
import darkTheme from 'prism-react-renderer/themes/vsDark/index.cjs.js'; import darkTheme from 'prism-react-renderer/themes/vsDark/index.cjs.js';
export default { export default {

View file

@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// eslint-disable-next-line import/no-extraneous-dependencies
import lightTheme from 'prism-react-renderer/themes/github/index.cjs.js'; import lightTheme from 'prism-react-renderer/themes/github/index.cjs.js';
export default { export default {