diff --git a/.eslintrc.js b/.eslintrc.js index 28a000035f..ec890ace34 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -22,15 +22,14 @@ module.exports = { allowImportExportEverywhere: true, }, globals: { - testStylelintRule: true, + JSX: true, }, extends: [ 'eslint:recommended', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', 'plugin:jest/recommended', 'airbnb', + 'plugin:@typescript-eslint/recommended', 'prettier', ], settings: { @@ -41,111 +40,37 @@ module.exports = { }, }, reportUnusedDisableDirectives: true, - plugins: ['react-hooks', 'header', 'jest'], + plugins: ['react-hooks', 'header', 'jest', '@typescript-eslint'], rules: { - 'react-hooks/rules-of-hooks': ERROR, - 'react-hooks/exhaustive-deps': ERROR, - 'class-methods-use-this': OFF, // It's a way of allowing private variables. - 'func-names': OFF, - // Ignore certain webpack alias because it can't be resolved - 'import/no-unresolved': [ - ERROR, - { - ignore: ['^@theme', '^@docusaurus', '^@generated', '^@site'], - }, - ], - 'import/extensions': OFF, - 'no-restricted-exports': OFF, - 'header/header': [ - ERROR, - 'block', - [ - '*', - ' * 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.', - ' ', - ], - ], - 'jsx-a11y/click-events-have-key-events': WARNING, - 'jsx-a11y/no-noninteractive-element-interactions': WARNING, - 'jsx-a11y/html-has-lang': OFF, - 'no-console': OFF, - 'no-else-return': OFF, - 'no-param-reassign': [WARNING, {props: false}], - 'no-underscore-dangle': OFF, - curly: [WARNING, 'all'], - 'react/jsx-filename-extension': OFF, - 'react/no-array-index-key': OFF, // Sometimes its ok, e.g. non-changing data. - 'react/prop-types': OFF, - 'react/destructuring-assignment': OFF, // Too many lines. - 'react/prefer-stateless-function': WARNING, - 'react/jsx-props-no-spreading': OFF, - 'react/require-default-props': [ERROR, {ignoreFunctionalComponents: true}], - 'react/function-component-definition': [ - WARNING, - { - namedComponents: 'function-declaration', - unnamedComponents: 'arrow-function', - }, - ], - 'react/no-unstable-nested-components': [WARNING, {allowAsProps: true}], - '@typescript-eslint/no-inferrable-types': OFF, - '@typescript-eslint/consistent-type-imports': [ - WARNING, - {disallowTypeAnnotations: false}, - ], - 'import/order': OFF, - 'import/prefer-default-export': OFF, - 'lines-between-class-members': OFF, - 'no-lonely-if': WARNING, - 'no-use-before-define': OFF, - '@typescript-eslint/no-use-before-define': [ - ERROR, - {functions: false, classes: false, variables: true}, - ], - 'no-unused-vars': OFF, - 'no-nested-ternary': WARNING, - '@typescript-eslint/no-empty-function': OFF, - '@typescript-eslint/no-non-null-assertion': OFF, - '@typescript-eslint/no-unused-vars': [ - ERROR, - {argsIgnorePattern: '^_', ignoreRestSiblings: true}, - ], - '@typescript-eslint/explicit-module-boundary-types': WARNING, - '@typescript-eslint/ban-ts-comment': [ - ERROR, - {'ts-expect-error': 'allow-with-description'}, - ], - 'import/no-extraneous-dependencies': ERROR, - 'no-useless-escape': WARNING, - 'prefer-template': WARNING, - 'no-template-curly-in-string': WARNING, 'array-callback-return': WARNING, camelcase: WARNING, - 'no-restricted-syntax': WARNING, - 'no-unused-expressions': [WARNING, {allowTaggedTemplates: true}], + 'class-methods-use-this': OFF, // It's a way of allowing private variables. + curly: [WARNING, 'all'], 'global-require': WARNING, - 'prefer-destructuring': WARNING, - yoda: WARNING, - 'no-await-in-loop': OFF, - 'no-control-regex': WARNING, - 'no-empty': [WARNING, {allowEmptyCatch: true}], - 'no-prototype-builtins': WARNING, - 'no-case-declarations': WARNING, - 'no-undef': OFF, - 'no-shadow': OFF, - '@typescript-eslint/no-shadow': ERROR, - 'no-redeclare': OFF, - '@typescript-eslint/no-redeclare': ERROR, - '@typescript-eslint/no-empty-interface': [ - ERROR, + 'lines-between-class-members': OFF, + 'max-len': [ + WARNING, { - allowSingleExtends: true, + code: Infinity, // Code width is already enforced by Prettier + tabWidth: 2, + comments: 80, + ignoreUrls: true, + ignorePattern: '(eslint-disable|@)', }, ], - '@typescript-eslint/method-signature-style': ERROR, + 'no-await-in-loop': OFF, + 'no-case-declarations': WARNING, + 'no-console': OFF, + 'no-control-regex': WARNING, + 'no-else-return': [WARNING, {allowElseIf: true}], + 'no-empty': [WARNING, {allowEmptyCatch: true}], + 'no-lonely-if': WARNING, + 'no-nested-ternary': WARNING, + 'no-param-reassign': [WARNING, {props: false}], + 'no-prototype-builtins': WARNING, + 'no-restricted-exports': OFF, + 'no-useless-escape': WARNING, + 'no-template-curly-in-string': WARNING, 'no-restricted-imports': [ ERROR, { @@ -153,7 +78,9 @@ module.exports = { { name: 'lodash', importNames: [ - // 'compact', // TODO: TS doesn't make Boolean a narrowing function yet, so filter(Boolean) is problematic type-wise + // TODO: TS doesn't make Boolean a narrowing function yet, + // so filter(Boolean) is problematic type-wise + // 'compact', 'filter', 'flatten', 'flatMap', @@ -170,16 +97,104 @@ module.exports = { ], }, ], + 'no-restricted-syntax': WARNING, + 'no-unused-expressions': [WARNING, {allowTaggedTemplates: true}], + 'prefer-destructuring': WARNING, + 'prefer-template': WARNING, + yoda: WARNING, + + 'header/header': [ + ERROR, + 'block', + [ + '*', + ' * 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.', + ' ', + ], + ], + + 'import/extensions': OFF, + // Ignore certain webpack aliases because they can't be resolved + 'import/no-unresolved': [ + ERROR, + { + ignore: ['^@theme', '^@docusaurus', '^@generated', '^@site'], + }, + ], + 'import/order': OFF, + 'import/prefer-default-export': OFF, + 'jest/prefer-expect-resolves': WARNING, 'jest/expect-expect': OFF, 'jest/valid-title': OFF, + + 'jsx-a11y/click-events-have-key-events': WARNING, + 'jsx-a11y/no-noninteractive-element-interactions': WARNING, + 'jsx-a11y/html-has-lang': OFF, + + 'react-hooks/rules-of-hooks': ERROR, + 'react-hooks/exhaustive-deps': ERROR, + + // Sometimes we do need the props as a whole, e.g. when spreading + 'react/destructuring-assignment': OFF, + 'react/function-component-definition': [ + WARNING, + { + namedComponents: 'function-declaration', + unnamedComponents: 'arrow-function', + }, + ], + 'react/jsx-filename-extension': OFF, + 'react/jsx-props-no-spreading': OFF, + 'react/no-array-index-key': OFF, // We build a static site, and nearly all components don't change. + 'react/no-unstable-nested-components': [WARNING, {allowAsProps: true}], + 'react/prefer-stateless-function': WARNING, + 'react/prop-types': OFF, + 'react/require-default-props': [ERROR, {ignoreFunctionalComponents: true}], + + '@typescript-eslint/ban-ts-comment': [ + ERROR, + {'ts-expect-error': 'allow-with-description'}, + ], + '@typescript-eslint/consistent-type-imports': [ + WARNING, + {disallowTypeAnnotations: false}, + ], + '@typescript-eslint/explicit-module-boundary-types': WARNING, + '@typescript-eslint/method-signature-style': ERROR, + '@typescript-eslint/no-empty-function': OFF, + '@typescript-eslint/no-empty-interface': [ + ERROR, + { + allowSingleExtends: true, + }, + ], + '@typescript-eslint/no-inferrable-types': OFF, + 'no-use-before-define': OFF, + '@typescript-eslint/no-use-before-define': [ + ERROR, + {functions: false, classes: false, variables: true}, + ], + '@typescript-eslint/no-non-null-assertion': OFF, + 'no-redeclare': OFF, + '@typescript-eslint/no-redeclare': ERROR, + 'no-shadow': OFF, + '@typescript-eslint/no-shadow': ERROR, + 'no-unused-vars': OFF, + '@typescript-eslint/no-unused-vars': [ + ERROR, + {argsIgnorePattern: '^_', ignoreRestSiblings: true}, + ], }, overrides: [ { files: [ - 'packages/docusaurus-theme-*/src/theme/**/*.js', - 'packages/docusaurus-theme-*/src/theme/**/*.ts', - 'packages/docusaurus-theme-*/src/theme/**/*.tsx', + 'packages/docusaurus-*/src/theme/**/*.js', + 'packages/docusaurus-*/src/theme/**/*.ts', + 'packages/docusaurus-*/src/theme/**/*.tsx', ], rules: { 'import/no-named-export': ERROR, @@ -206,6 +221,7 @@ module.exports = { { files: ['*.ts', '*.tsx'], rules: { + 'no-undef': OFF, 'import/no-import-module-exports': OFF, }, }, diff --git a/__tests__/validate-package-json.test.ts b/__tests__/validate-package-json.test.ts index ad2d67f1eb..5b6dffdef9 100644 --- a/__tests__/validate-package-json.test.ts +++ b/__tests__/validate-package-json.test.ts @@ -62,9 +62,11 @@ describe('packages', () => { .filter((packageJsonFile) => packageJsonFile.content.name.startsWith('@')) .forEach((packageJsonFile) => { if (packageJsonFile) { - // Unfortunately jest custom message do not exist in loops, so using an exception instead to show failing package file + // Unfortunately jest custom message do not exist in loops, + // so using an exception instead to show failing package file // (see https://github.com/facebook/jest/issues/3293) - // expect(packageJsonFile.content.publishConfig?.access).toEqual('public'); + // expect(packageJsonFile.content.publishConfig?.access) + // .toEqual('public'); if (packageJsonFile.content.publishConfig?.access !== 'public') { throw new Error( `Package ${packageJsonFile.file} does not have publishConfig.access: 'public'`, diff --git a/admin/new.docusaurus.io/functionUtils/playgroundUtils.ts b/admin/new.docusaurus.io/functionUtils/playgroundUtils.ts index 1fd7b75073..b8a7f84ca9 100644 --- a/admin/new.docusaurus.io/functionUtils/playgroundUtils.ts +++ b/admin/new.docusaurus.io/functionUtils/playgroundUtils.ts @@ -10,7 +10,9 @@ import type {HandlerEvent, HandlerResponse} from '@netlify/functions'; const CookieName = 'DocusaurusPlaygroundName'; const PlaygroundConfigs = { - // codesandbox: 'https://codesandbox.io/s/docusaurus', // Do not use this one, see https://github.com/codesandbox/codesandbox-client/issues/5683#issuecomment-1023252459 + // Do not use this one, see + // https://github.com/codesandbox/codesandbox-client/issues/5683#issuecomment-1023252459 + // codesandbox: 'https://codesandbox.io/s/docusaurus', codesandbox: 'https://codesandbox.io/s/github/facebook/docusaurus/tree/main/examples/classic', @@ -69,14 +71,11 @@ export function readPlaygroundName( : {}; const playgroundName: string | undefined = parsedCookie[CookieName]; - if (playgroundName) { - if (isValidPlaygroundName(playgroundName)) { - return playgroundName; - } else { - console.error( - `playgroundName found in cookie was invalid: ${playgroundName}`, - ); - } + if (!isValidPlaygroundName(playgroundName)) { + console.error( + `playgroundName found in cookie was invalid: ${playgroundName}`, + ); + return undefined; } - return undefined; + return playgroundName; } diff --git a/admin/new.docusaurus.io/functions/codesandbox.ts b/admin/new.docusaurus.io/functions/codesandbox.ts index fa57531f88..9cb6c9b41e 100644 --- a/admin/new.docusaurus.io/functions/codesandbox.ts +++ b/admin/new.docusaurus.io/functions/codesandbox.ts @@ -9,6 +9,6 @@ import type {Handler} from '@netlify/functions'; import {createPlaygroundResponse} from '../functionUtils/playgroundUtils'; -export const handler: Handler = async function (_event, _context) { +export const handler: Handler = async function handler(_event, _context) { return createPlaygroundResponse('codesandbox'); }; diff --git a/admin/new.docusaurus.io/functions/stackblitz.ts b/admin/new.docusaurus.io/functions/stackblitz.ts index cc80bf7915..28bf7bb11f 100644 --- a/admin/new.docusaurus.io/functions/stackblitz.ts +++ b/admin/new.docusaurus.io/functions/stackblitz.ts @@ -9,6 +9,6 @@ import type {Handler} from '@netlify/functions'; import {createPlaygroundResponse} from '../functionUtils/playgroundUtils'; -export const handler: Handler = async function (_event, _context) { +export const handler: Handler = async function handler(_event, _context) { return createPlaygroundResponse('stackblitz'); }; diff --git a/admin/scripts/generateExamples.mjs b/admin/scripts/generateExamples.mjs index eabdb6b880..54e3e92c19 100644 --- a/admin/scripts/generateExamples.mjs +++ b/admin/scripts/generateExamples.mjs @@ -26,16 +26,16 @@ async function generateTemplateExample(template) { `generating ${template} template for codesandbox in the examples folder...`, ); - // run the docusaurus script to bootstrap the template in the examples folder + // run the docusaurus script to create the template in the examples folder const command = template.endsWith('-typescript') ? template.replace('-typescript', ' -- --typescript') : template; shell.exec( // /!\ we use the published init script on purpose, - // because using the local init script is too early and could generate upcoming/unavailable config options - // remember CodeSandbox templates will use the published version, not the repo version + // because using the local init script is too early and could generate + // upcoming/unavailable config options. Remember CodeSandbox templates + // will use the published version, not the repo version `npm init docusaurus@latest examples/${template} ${command}`, - // `node ./packages/docusaurus-init/bin/index.js init examples/${template} ${template}`, ); // read the content of the package.json @@ -49,10 +49,10 @@ async function generateTemplateExample(template) { // these example projects are not meant to be published to npm templatePackageJson.private = true; - // make sure package.json name is not "examples-classic" - // the package.json name appear in CodeSandbox UI so let's display a good name! - // unfortunately we can't use uppercase or spaces - // see also https://github.com/codesandbox/codesandbox-client/pull/5136#issuecomment-763521662 + // Make sure package.json name is not "examples-classic". The package.json + // name appears in CodeSandbox UI so let's display a good name! + // Unfortunately we can't use uppercase or spaces... See also + // https://github.com/codesandbox/codesandbox-client/pull/5136#issuecomment-763521662 templatePackageJson.name = template === 'classic' ? 'docusaurus' : `docusaurus-${template}`; templatePackageJson.description = @@ -98,12 +98,13 @@ async function generateTemplateExample(template) { } } -/* -Starters are repositories/branches that only contains a newly initialized Docusaurus site -Those are useful for users to inspect (may be more convenient than "examples/classic) -Also some tools like Netlify deploy button currently require using the main branch of a dedicated repo -See https://github.com/jamstack/jamstack.org/pull/609 -Button visible here: https://jamstack.org/generators/ +/** + * Starters are repositories/branches that only contains a newly initialized + * Docusaurus site. Those are useful for users to inspect (may be more + * convenient than "examples/classic) Also some tools like Netlify deploy button + * currently require using the main branch of a dedicated repo. + * See https://github.com/jamstack/jamstack.org/pull/609 + * Button visible here: https://jamstack.org/generators/ */ function updateStarters() { function forcePushGitSubtree({subfolder, remote, remoteBranch}) { diff --git a/admin/scripts/image-resize.mjs b/admin/scripts/image-resize.mjs index 2b221835be..e8b8718e1d 100644 --- a/admin/scripts/image-resize.mjs +++ b/admin/scripts/image-resize.mjs @@ -39,7 +39,8 @@ await Promise.all( }), ); -// You should also run optimizt `find website/src/data/showcase -type f -name '*.png'`. -// This is not included here because @funboxteam/optimizt doesn't seem to play well with M1 -// so I had to run this in a Rosetta terminal. +// You should also run +// optimizt `find website/src/data/showcase -type f -name '*.png'`. +// This is not included here because @funboxteam/optimizt doesn't seem to play +// well with M1 so I had to run this in a Rosetta terminal. // TODO integrate this as part of the script diff --git a/jest.config.mjs b/jest.config.mjs index 343d5b7ded..9bd06327ae 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -40,7 +40,7 @@ export default { '@docusaurus/core/lib/client/exports/$1', // Maybe point to a fixture? '@generated/.*': '/jest/emptyModule.js', - // TODO maybe use "projects" + multiple configs if we plan to add tests to another theme? + // TODO use "projects" + multiple configs if we work on another theme? '@theme/(.*)': '@docusaurus/theme-classic/src/theme/$1', '@site/(.*)': 'website/$1', diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts index 7e39145926..979516ee8a 100755 --- a/packages/create-docusaurus/src/index.ts +++ b/packages/create-docusaurus/src/index.ts @@ -81,7 +81,8 @@ async function copyTemplate( ) { await fs.copy(path.resolve(templatesDir, 'shared'), dest); - // TypeScript variants will copy duplicate resources like CSS & config from base template + // TypeScript variants will copy duplicate resources like CSS & config from + // base template const tsBaseTemplate = getTypeScriptBaseTemplate(template); if (tsBaseTemplate) { const tsBaseTemplatePath = path.resolve(templatesDir, tsBaseTemplate); @@ -94,7 +95,8 @@ async function copyTemplate( } await fs.copy(path.resolve(templatesDir, template), dest, { - // Symlinks don't exist in published NPM packages anymore, so this is only to prevent errors during local testing + // Symlinks don't exist in published NPM packages anymore, so this is only + // to prevent errors during local testing filter: (filePath) => !fs.lstatSync(filePath).isSymbolicLink(), }); } @@ -278,7 +280,8 @@ export default async function init( shell.exec(useYarn ? 'yarn' : 'npm install --color always', { env: { ...process.env, - // Force coloring the output, since the command is invoked by shelljs, which is not the interactive shell + // Force coloring the output, since the command is invoked by shelljs, + // which is not the interactive shell ...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}), }, }).code !== 0 diff --git a/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/index.js b/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/index.js index fe19a8fe3c..51eb53b353 100644 --- a/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/index.js +++ b/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/index.js @@ -6,12 +6,17 @@ */ /** - * This PostCSS plugin will remove duplicate/same custom properties (which are actually overridden ones) **only** from `:root` selector. + * This PostCSS plugin will remove duplicate/same custom properties (which are + * actually overridden ones) **only** from `:root` selector. * - * Depending on the presence of an `!important` rule in value of custom property, the following actions will happens: + * Depending on the presence of an `!important` rule in value of custom + * property, the following actions will happen: * - * - If the same custom properties do **not** have an `!important` rule, then all of them will be removed except for the last one (which will actually be applied). - * - If the same custom properties have at least one `!important` rule, then only those properties that do not have this rule will be removed. + * - If the same custom properties do **not** have an `!important` rule, then + * all of them will be removed except for the last one (which will actually be + * applied). + * - If the same custom properties have at least one `!important` rule, then + * only those properties that do not have this rule will be removed. * @returns {import('postcss').Plugin} */ module.exports = function creator() { diff --git a/packages/docusaurus-logger/src/index.ts b/packages/docusaurus-logger/src/index.ts index 5684cec8fe..e8c9ed8a25 100644 --- a/packages/docusaurus-logger/src/index.ts +++ b/packages/docusaurus-logger/src/index.ts @@ -23,7 +23,7 @@ function interpolate( values.forEach((value, idx) => { const flag = msgs[idx].match(/[a-z]+=$/); res += msgs[idx].replace(/[a-z]+=$/, ''); - const format = (function () { + const format = (() => { if (!flag) { return (a: string | number) => a; } diff --git a/packages/docusaurus-mdx-loader/src/index.ts b/packages/docusaurus-mdx-loader/src/index.ts index 4871e1bc0a..c3e15c338d 100644 --- a/packages/docusaurus-mdx-loader/src/index.ts +++ b/packages/docusaurus-mdx-loader/src/index.ts @@ -49,9 +49,12 @@ type Options = RemarkAndRehypePluginOptions & { filepath: string; }; -// When this throws, it generally means that there's no metadata file associated with this MDX document -// It can happen when using MDX partials (usually starting with _) -// That's why it's important to provide the "isMDXPartial" function in config +/** + * When this throws, it generally means that there's no metadata file associated + * with this MDX document. It can happen when using MDX partials (usually + * starting with _). That's why it's important to provide the `isMDXPartial` + * function in config + */ async function readMetadataPath(metadataPath: string) { try { return await readFile(metadataPath, 'utf8'); @@ -62,11 +65,14 @@ async function readMetadataPath(metadataPath: string) { } } -// Converts assets an object with Webpack require calls code -// This is useful for mdx files to reference co-located assets using relative paths -// Those assets should enter the Webpack assets pipeline and be hashed -// For now, we only handle that for images and paths starting with ./ -// {image: "./myImage.png"} => {image: require("./myImage.png")} +/** + * Converts assets an object with Webpack require calls code. + * This is useful for mdx files to reference co-located assets using relative + * paths. Those assets should enter the Webpack assets pipeline and be hashed. + * For now, we only handle that for images and paths starting with `./`: + * + * `{image: "./myImage.png"}` => `{image: require("./myImage.png")}` + */ function createAssetsExportCode(assets: Record) { if (Object.keys(assets).length === 0) { return 'undefined'; @@ -148,7 +154,7 @@ export default async function mdxLoader( filepath: filePath, }; - let result; + let result: string; try { result = await mdx(content, options); } catch (err) { @@ -156,7 +162,7 @@ export default async function mdxLoader( } // MDX partials are MDX files starting with _ or in a folder starting with _ - // Partial are not expected to have an associated metadata file or front matter + // Partial are not expected to have associated metadata files or front matter const isMDXPartial = options.isMDXPartial && options.isMDXPartial(filePath); if (isMDXPartial && hasFrontMatter) { const errorMessage = `Docusaurus MDX partial files should not contain FrontMatter. @@ -168,9 +174,8 @@ ${JSON.stringify(frontMatter, null, 2)}`; const shouldError = process.env.NODE_ENV === 'test' || process.env.CI; if (shouldError) { return callback(new Error(errorMessage)); - } else { - logger.warn(errorMessage); } + logger.warn(errorMessage); } } diff --git a/packages/docusaurus-mdx-loader/src/remark/headings/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/headings/__tests__/index.test.ts index a317cf4001..ee10568ba8 100644 --- a/packages/docusaurus-mdx-loader/src/remark/headings/__tests__/index.test.ts +++ b/packages/docusaurus-mdx-loader/src/remark/headings/__tests__/index.test.ts @@ -57,7 +57,7 @@ describe('headings plugin', () => { test('should not overwrite `data` on headings', () => { const result = process('# Normal\n', [ - function () { + () => { function transform(tree) { tree.children[0].data = {foo: 'bar'}; } @@ -80,7 +80,7 @@ describe('headings plugin', () => { test('should not overwrite `data.hProperties` on headings', () => { const result = process('# Normal\n', [ - function () { + () => { function transform(tree) { tree.children[0].data = {hProperties: {className: ['foo']}}; } @@ -110,7 +110,7 @@ describe('headings plugin', () => { '## Something also', ].join('\n\n'), [ - function () { + () => { function transform(tree) { tree.children[1].data = {hProperties: {id: 'here'}}; tree.children[3].data = {hProperties: {id: 'something'}}; diff --git a/packages/docusaurus-mdx-loader/src/remark/headings/index.ts b/packages/docusaurus-mdx-loader/src/remark/headings/index.ts index 62b87054a7..0036b1b969 100644 --- a/packages/docusaurus-mdx-loader/src/remark/headings/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/headings/index.ts @@ -44,7 +44,8 @@ function headings(): Transformer { if (parsedHeading.id) { // When there's an id, it is always in the last child node - // Sometimes heading is in multiple "parts" (** syntax creates a child node): + // Sometimes heading is in multiple "parts" (** syntax creates a child + // node): // ## part1 *part2* part3 {#id} const lastNode = headingNode.children[ headingNode.children.length - 1 diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/search.ts b/packages/docusaurus-mdx-loader/src/remark/toc/search.ts index 4c87132c1e..ea8fc8b704 100644 --- a/packages/docusaurus-mdx-loader/src/remark/toc/search.ts +++ b/packages/docusaurus-mdx-loader/src/remark/toc/search.ts @@ -46,9 +46,9 @@ export default function search(node: Node): TOCItem[] { }); }); - // Keep track of which previous index would be the current heading's direct parent. - // Each entry is the last index of the `headings` array at heading level . - // We will modify these indices as we iterate through all headings. + // Keep track of which previous index would be the current heading's direct + // parent. Each entry is the last index of the `headings` array at heading + // level . We will modify these indices as we iterate through all headings. // e.g. if an ### H3 was last seen at index 2, then prevIndexForLevel[3] === 2 // indices 0 and 1 will remain unused. const prevIndexForLevel = Array(7).fill(-1); diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts index 7644080ae4..97e9e841e5 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts @@ -116,14 +116,10 @@ async function getImageAbsolutePath( } return imageFilePath; } - // We try to convert image urls without protocol to images with require calls - // going through webpack ensures that image assets exist at build time - else { - // relative paths are resolved against the source file's folder - const imageFilePath = path.join(path.dirname(filePath), imagePath); - await ensureImageFileExist(imageFilePath, filePath); - return imageFilePath; - } + // relative paths are resolved against the source file's folder + const imageFilePath = path.join(path.dirname(filePath), imagePath); + await ensureImageFileExist(imageFilePath, filePath); + return imageFilePath; } async function processImageNode(node: Image, context: Context) { @@ -137,16 +133,16 @@ async function processImageNode(node: Image, context: Context) { const parsedUrl = url.parse(node.url); if (parsedUrl.protocol || !parsedUrl.pathname) { - // pathname:// is an escape hatch, - // in case user does not want his images to be converted to require calls going through webpack loader - // we don't have to document this for now, - // it's mostly to make next release less risky (2.0.0-alpha.59) + // pathname:// is an escape hatch, in case user does not want her images to + // be converted to require calls going through webpack loader if (parsedUrl.protocol === 'pathname:') { node.url = node.url.replace('pathname://', ''); } return; } + // We try to convert image urls without protocol to images with require calls + // going through webpack ensures that image assets exist at build time const imagePath = await getImageAbsolutePath(parsedUrl.pathname, context); await toImageRequireNode(node, imagePath, context.filePath); } diff --git a/packages/docusaurus-mdx-loader/src/remark/unwrapMdxCodeBlocks/index.ts b/packages/docusaurus-mdx-loader/src/remark/unwrapMdxCodeBlocks/index.ts index 101f2552e6..2c9558642b 100644 --- a/packages/docusaurus-mdx-loader/src/remark/unwrapMdxCodeBlocks/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/unwrapMdxCodeBlocks/index.ts @@ -10,9 +10,10 @@ import type {Transformer, Processor} from 'unified'; import type {Code, Parent} from 'mdast'; // This plugin is mostly to help integrating Docusaurus with translation systems -// that do not support well MDX embedded JSX syntax (like Crowdin) -// We wrap the JSX syntax in code blocks so that translation tools don't mess-up with the markup -// But the JSX inside such code blocks should still be evaluated as JSX +// that do not support well MDX embedded JSX syntax (like Crowdin). +// We wrap the JSX syntax in code blocks so that translation tools don't mess up +// with the markup, but the JSX inside such code blocks should still be +// evaluated as JSX // See https://github.com/facebook/docusaurus/pull/4278 function plugin(this: Processor): Transformer { const transformer: Transformer = (root) => { diff --git a/packages/docusaurus-migrate/src/index.ts b/packages/docusaurus-migrate/src/index.ts index d6e45d0ffb..7fd20bf54f 100644 --- a/packages/docusaurus-migrate/src/index.ts +++ b/packages/docusaurus-migrate/src/index.ts @@ -61,7 +61,8 @@ function sanitizedFileContent( return sanitizedData; } -// TODO refactor this new type should be used everywhere instead of passing many params to each method +// TODO refactor this new type should be used everywhere instead of passing many +// params to each method type MigrationContext = { siteDir: string; newDir: string; diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index ed9a3e4a5f..1ca6d07c00 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -179,13 +179,13 @@ declare module '@docusaurus/Interpolate' { Value extends ReactNode, > = Record, Value>; - // TS function overload: if all the values are plain strings, then interpolate returns a simple string + // If all the values are plain strings, interpolate returns a simple string export function interpolate( text: Str, values?: InterpolateValues, ): string; - // If values contain any ReactNode, then the return is a ReactNode + // If values contain any ReactNode, the return is a ReactNode export function interpolate( text: Str, values?: InterpolateValues, diff --git a/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts b/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts index f01181d97a..8dfb206a4d 100644 --- a/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts +++ b/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts @@ -114,7 +114,9 @@ describe('toRedirectFilesMetadata', () => { ); expect(redirectFiles.map((f) => f.fileAbsolutePath)).toEqual([ - // path.join(pluginContext.outDir, '/abc.html/index.html'), // Can't be used because /abc.html already exists, and file/folder can't share same name on Unix! + // Can't be used because /abc.html already exists, and file/folder can't + // share same name on Unix! + // path.join(pluginContext.outDir, '/abc.html/index.html'), path.join(pluginContext.outDir, '/abc.html.html'), // Weird but on purpose! path.join(pluginContext.outDir, '/def/index.html'), path.join(pluginContext.outDir, '/xyz/index.html'), diff --git a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts index 6c53e817d8..e746242cb8 100644 --- a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts @@ -39,9 +39,12 @@ export default function collectRedirects( } // If users wants to redirect to=/abc and they enable trailingSlash=true then -// => we don't want to reject the to=/abc (as only /abc/ is an existing/valid path now) -// => we want to redirect to=/abc/ without the user having to change all its redirect plugin options -// It should be easy to toggle siteConfig.trailingSlash option without having to change other configs +// => we don't want to reject the to=/abc (as only /abc/ is an existing/valid +// path now) +// => we want to redirect to=/abc/ without the user having to change all its +// redirect plugin options +// It should be easy to toggle siteConfig.trailingSlash option without having to +// change other configs function applyRedirectsTrailingSlash( redirects: RedirectMetadata[], params: ApplyTrailingSlashParams, diff --git a/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts index 0ef5660602..a72452a752 100644 --- a/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts @@ -81,19 +81,12 @@ export function createFromExtensionsRedirects( if (path === '' || path === '/' || alreadyEndsWithAnExtension(path)) { return []; } - - // /path => /path.html - // /path/ => /path.html/ - function getFrom(ext: string) { - if (path.endsWith('/')) { - return addTrailingSlash(`${removeTrailingSlash(path)}.${ext}`); - } else { - return `${path}.${ext}`; - } - } - return extensions.map((ext) => ({ - from: getFrom(ext), + // /path => /path.html + // /path/ => /path.html/ + from: path.endsWith('/') + ? addTrailingSlash(`${removeTrailingSlash(path)}.${ext}`) + : `${path}.${ext}`, to: path, })); }; diff --git a/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts b/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts index 8dcb5a14a7..8343cdd794 100644 --- a/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts +++ b/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts @@ -25,7 +25,8 @@ export function createToUrl(baseUrl: string, to: string): string { } // Create redirect file path -// Make sure this path has lower precedence over the original file path when served by host providers! +// Make sure this path has lower precedence over the original file path when +// served by host providers! // Otherwise it can produce infinite redirect loops! // // See https://github.com/facebook/docusaurus/issues/5055 @@ -39,17 +40,19 @@ function getRedirectFilePath( const filePath = path.dirname(fromPath); // Edge case for https://github.com/facebook/docusaurus/pull/5102 // If the redirect source path is /xyz, with file /xyz.html - // We can't write the redirect file at /xyz.html/index.html because for Unix FS, a file/folder can't have the same name "xyz.html" - // The only possible solution for a redirect file is thus /xyz.html.html (I know, looks suspicious) + // We can't write the redirect file at /xyz.html/index.html because for Unix + // FS, a file/folder can't have the same name "xyz.html" + // The only possible solution for a redirect file is thus /xyz.html.html (I + // know, looks suspicious) if (trailingSlash === false && fileName.endsWith('.html')) { return path.join(filePath, `${fileName}.html`); } - // If the target path is /xyz, with file /xyz/index.html, we don't want the redirect file to be /xyz.html - // otherwise it would be picked in priority and the redirect file would redirect to itself - // We prefer the redirect file to be /xyz.html/index.html, served with lower priority for most static hosting tools - else { - return path.join(filePath, `${fileName}/index.html`); - } + // If the target path is /xyz, with file /xyz/index.html, we don't want the + // redirect file to be /xyz.html, otherwise it would be picked in priority and + // the redirect file would redirect to itself. We prefer the redirect file to + // be /xyz.html/index.html, served with lower priority for most static hosting + // tools + return path.join(filePath, `${fileName}/index.html`); } export function toRedirectFilesMetadata( diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 85c01c4a55..e69ec0c849 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -83,9 +83,9 @@ function normalizeFrontMatterAuthors( authorInput: string | BlogPostFrontMatterAuthor, ): BlogPostFrontMatterAuthor { if (typeof authorInput === 'string') { - // Technically, we could allow users to provide an author's name here - // IMHO it's better to only support keys here - // Reason: a typo in a key would fallback to becoming a name and may end-up un-noticed + // Technically, we could allow users to provide an author's name here, but + // we only support keys, otherwise, a typo in a key would fallback to + // becoming a name and may end up unnoticed return {key: authorInput}; } return authorInput; @@ -137,7 +137,8 @@ export function getBlogPostAuthors(params: AuthorsParam): Author[] { const authors = getFrontMatterAuthors(params); if (authorLegacy) { - // Technically, we could allow mixing legacy/authors front matter, but do we really want to? + // Technically, we could allow mixing legacy/authors front matter, but do we + // really want to? if (authors.length > 0) { throw new Error( `To declare blog post authors, use the 'authors' front matter in priority. diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index ddda9dc016..34d315127c 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -82,11 +82,10 @@ export function parseBlogFileName( const slugDate = dateString.replace(/-/g, '/'); const slug = `/${slugDate}/${folder}${text}`; return {date, text, slug}; - } else { - const text = blogSourceRelative.replace(/(\/index)?\.mdx?$/, ''); - const slug = `/${text}`; - return {date: undefined, text, slug}; } + const text = blogSourceRelative.replace(/(\/index)?\.mdx?$/, ''); + const slug = `/${text}`; + return {date: undefined, text, slug}; } function formatBlogPostDate(locale: string, date: Date): string { diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 14729a2fad..750d0489ec 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -322,7 +322,8 @@ export default async function pluginContentBlog( modules: { sidebar: aliasedSource(sidebarProp), items: items.map((postID) => - // To tell routes.js this is an import and not a nested object to recurse. + // To tell routes.js this is an import and not a nested object + // to recurse. ({ content: { __import: true, @@ -485,7 +486,8 @@ export default async function pluginContentBlog( // Blog posts title are rendered separately removeContentTitle: true, - // Assets allow to convert some relative images paths to require() calls + // Assets allow to convert some relative images paths to + // require() calls createAssets: ({ frontMatter, metadata, diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index ceca2f46d0..5ea80609e1 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -95,7 +95,8 @@ Entries created: }, expectSnapshot: () => { - // Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering + // Sort the route config like in src/server/plugins/index.ts for + // consistent snapshot ordering sortConfig(routeConfigs); expect(routeConfigs).not.toEqual([]); expect(routeConfigs).toMatchSnapshot('route config'); @@ -249,7 +250,8 @@ describe('simple website', () => { .spyOn(cliDocs, 'cliDocsVersionCommand') .mockImplementation(); const cli = new commander.Command(); - // @ts-expect-error: in actual usage, we pass the static commander instead of the new command + // @ts-expect-error: in actual usage, we pass the static commander instead + // of the new command plugin.extendCli!(cli); cli.parse(['node', 'test', 'docs:version', '1.0.0']); expect(mock).toHaveBeenCalledTimes(1); @@ -373,7 +375,8 @@ describe('versioned website', () => { .spyOn(cliDocs, 'cliDocsVersionCommand') .mockImplementation(); const cli = new commander.Command(); - // @ts-expect-error: in actual usage, we pass the static commander instead of the new command + // @ts-expect-error: in actual usage, we pass the static commander instead + // of the new command plugin.extendCli!(cli); cli.parse(['node', 'test', 'docs:version', '2.0.0']); expect(mock).toHaveBeenCalledTimes(1); @@ -522,7 +525,8 @@ describe('versioned website (community)', () => { .spyOn(cliDocs, 'cliDocsVersionCommand') .mockImplementation(); const cli = new commander.Command(); - // @ts-expect-error: in actual usage, we pass the static commander instead of the new command + // @ts-expect-error: in actual usage, we pass the static commander instead + // of the new command plugin.extendCli!(cli); cli.parse(['node', 'test', `docs:version:${pluginId}`, '2.0.0']); expect(mock).toHaveBeenCalledTimes(1); @@ -726,7 +730,8 @@ describe('site with partial autogenerated sidebars', () => { const {content} = await loadSite(); const version = content.loadedVersions[0]; - // Only looking at the docs of the autogen sidebar, others metadata should not be affected + // Only looking at the docs of the autogen sidebar, others metadata should + // not be affected expect(getDocById(version, 'API/api-end')).toMatchSnapshot(); expect(getDocById(version, 'API/api-overview')).toMatchSnapshot(); @@ -803,7 +808,8 @@ describe('site with custom sidebar items generator', () => { const generatorArg: SidebarItemsGeneratorOptionArgs = customSidebarItemsGeneratorMock.mock.calls[0][0]; - // Make test pass even if docs are in different order and paths are absolutes + // Make test pass even if docs are in different order and paths are + // absolutes function makeDeterministic( arg: SidebarItemsGeneratorOptionArgs, ): SidebarItemsGeneratorOptionArgs { diff --git a/packages/docusaurus-plugin-content-docs/src/cli.ts b/packages/docusaurus-plugin-content-docs/src/cli.ts index 76045beef0..83b5649c2d 100644 --- a/packages/docusaurus-plugin-content-docs/src/cli.ts +++ b/packages/docusaurus-plugin-content-docs/src/cli.ts @@ -32,10 +32,12 @@ function createVersionedSidebarFile({ version: string; }) { // Load current sidebar and create a new versioned sidebars file (if needed). - // Note: we don't need the sidebars file to be normalized: it's ok to let plugin option changes to impact older, versioned sidebars + // Note: we don't need the sidebars file to be normalized: it's ok to let + // plugin option changes to impact older, versioned sidebars const sidebars = loadSidebarsFile(sidebarPath); - // Do not create a useless versioned sidebars file if sidebars file is empty or sidebars are disabled/false) + // Do not create a useless versioned sidebars file if sidebars file is empty + // or sidebars are disabled/false) const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0; if (shouldCreateVersionedSidebarFile) { diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index 3af5af23ae..ad40156a7e 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -28,7 +28,7 @@ export function getActivePlugin( options: GetActivePluginOptions = {}, ): ActivePlugin | undefined { const activeEntry = Object.entries(allPluginDatas) - // A quick route sorting: '/android/foo' should match '/android' instead of '/' + // Route sorting: '/android/foo' should match '/android' instead of '/' .sort((a, b) => b[1].path.localeCompare(a[1].path)) .find( ([, pluginData]) => @@ -67,7 +67,7 @@ export const getActiveVersion = ( ): GlobalVersion | undefined => { const lastVersion = getLatestVersion(data); // Last version is a route like /docs/*, - // we need to try to match it last or it would match /docs/version-1.0/* as well + // we need to match it last or it would match /docs/version-1.0/* as well const orderedVersionsMetadata = [ ...data.versions.filter((version) => version !== lastVersion), lastVersion, diff --git a/packages/docusaurus-plugin-content-docs/src/client/globalDataHooks.ts b/packages/docusaurus-plugin-content-docs/src/client/globalDataHooks.ts index 96a14ce909..bd225ce6cd 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/globalDataHooks.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/globalDataHooks.ts @@ -27,12 +27,13 @@ import type { GetActivePluginOptions, } from '@docusaurus/plugin-content-docs/client'; -// Important to use a constant object to avoid React useEffect executions etc..., +// Important to use a constant object to avoid React useEffect executions etc. // see https://github.com/facebook/docusaurus/issues/5089 const StableEmptyObject = {}; -// Not using useAllPluginInstancesData() because in blog-only mode, docs hooks are still used by the theme -// We need a fail-safe fallback when the docs plugin is not in use +// Not using useAllPluginInstancesData() because in blog-only mode, docs hooks +// are still used by the theme. We need a fail-safe fallback when the docs +// plugin is not in use export const useAllDocsData = (): Record => // useAllPluginInstancesData('docusaurus-plugin-content-docs'); useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject; diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index 9002479b9a..79f692b169 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -139,7 +139,8 @@ function doProcessDocMetadata({ const { custom_edit_url: customEditURL, - // Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default, + // Strip number prefixes by default + // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) // but allow to disable this behavior with front matter parse_number_prefixes: parseNumberPrefixes = true, } = frontMatter; @@ -164,7 +165,8 @@ function doProcessDocMetadata({ throw new Error(`Document id "${baseID}" cannot include slash.`); } - // For autogenerated sidebars, sidebar position can come from filename number prefix or front matter + // For autogenerated sidebars, sidebar position can come from filename number + // prefix or front matter const sidebarPosition: number | undefined = frontMatter.sidebar_position ?? numberPrefix; @@ -205,8 +207,9 @@ function doProcessDocMetadata({ numberPrefixParser: options.numberPrefixParser, }); - // Note: the title is used by default for page title, sidebar label, pagination buttons... - // frontMatter.title should be used in priority over contentTitle (because it can contain markdown/JSX syntax) + // Note: the title is used by default for page title, sidebar label, + // pagination buttons... frontMatter.title should be used in priority over + // contentTitle (because it can contain markdown/JSX syntax) const title: string = frontMatter.title ?? contentTitle ?? baseID; const description: string = frontMatter.description ?? excerpt ?? ''; @@ -233,9 +236,8 @@ function doProcessDocMetadata({ ? versionMetadata.versionEditUrlLocalized : versionMetadata.versionEditUrl; return getEditUrl(relativeFilePath, baseVersionEditUrl); - } else { - return undefined; } + return undefined; } // Assign all of object properties during instantiation (if possible) for @@ -361,9 +363,8 @@ export function getMainDocId({ doc.id === firstDocIdOfFirstSidebar || doc.unversionedId === firstDocIdOfFirstSidebar, )!; - } else { - return docs[0]; } + return docs[0]; } return getMainDoc().unversionedId; @@ -407,7 +408,8 @@ export function toCategoryIndexMatcherParam({ } /** - * guides/sidebar/autogenerated.md -> 'autogenerated', '.md', ['sidebar', 'guides'] + * `guides/sidebar/autogenerated.md` -> + * `'autogenerated', '.md', ['sidebar', 'guides']` */ export function splitPath(str: string): { /** @@ -428,15 +430,17 @@ export function splitPath(str: string): { } // Return both doc ids -// TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids -// ("id" should be removed & "versionedId" should be renamed to "id") +// TODO legacy retro-compatibility due to old versioned sidebars using +// versioned doc ids ("id" should be removed & "versionedId" should be renamed +// to "id") export function getDocIds(doc: DocMetadataBase): [string, string] { return [doc.unversionedId, doc.id]; } // docs are indexed by both versioned and unversioned ids at the same time -// TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids -// ("id" should be removed & "versionedId" should be renamed to "id") +// TODO legacy retro-compatibility due to old versioned sidebars using +// versioned doc ids ("id" should be removed & "versionedId" should be renamed +// to "id") export function createDocsByIdIndex< Doc extends {id: string; unversionedId: string}, >(docs: Doc[]): Record { diff --git a/packages/docusaurus-plugin-content-docs/src/numberPrefix.ts b/packages/docusaurus-plugin-content-docs/src/numberPrefix.ts index 85933aa94c..100b377830 100644 --- a/packages/docusaurus-plugin-content-docs/src/numberPrefix.ts +++ b/packages/docusaurus-plugin-content-docs/src/numberPrefix.ts @@ -8,15 +8,16 @@ import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs'; // Best-effort to avoid parsing some patterns as number prefix -const IgnoredPrefixPatterns = (function () { +const IgnoredPrefixPatterns = (() => { // ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640 const DateLikePrefixRegex = /^((\d{2}|\d{4})[-_.]\d{2}([-_.](\d{2}|\d{4}))?)(.*)$/; // ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653 - // note: we could try to parse float numbers in filenames but that is probably not worth it - // as a version such as "8.0" can be interpreted as both a version and a float - // User can configure his own NumberPrefixParser if he wants 8.0 to be interpreted as a float + // note: we could try to parse float numbers in filenames but that is + // probably not worth it as a version such as "8.0" can be interpreted as both + // a version and a float. User can configure her own NumberPrefixParser if + // she wants 8.0 to be interpreted as a float const VersionLikePrefixRegex = /^(\d+[-_.]\d+)(.*)$/; return new RegExp( diff --git a/packages/docusaurus-plugin-content-docs/src/options.ts b/packages/docusaurus-plugin-content-docs/src/options.ts index f7b2f7ed47..7c79e5ac02 100644 --- a/packages/docusaurus-plugin-content-docs/src/options.ts +++ b/packages/docusaurus-plugin-content-docs/src/options.ts @@ -148,8 +148,9 @@ export function validateOptions({ let options = userOptions; if (options.sidebarCollapsible === false) { - // When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't want to have the inconsistency warning - // We let options.sidebarCollapsible become the default value for options.sidebarCollapsed + // When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't + // want to have the inconsistency warning. We let options.sidebarCollapsible + // become the default value for options.sidebarCollapsed if (typeof options.sidebarCollapsed === 'undefined') { options = { ...options, diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index 59f54a69c7..75acc8b501 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -45,7 +45,8 @@ declare module '@docusaurus/plugin-content-docs' { sidebarPath?: string | false | undefined; }; - // TODO support custom version banner? {type: "error", content: "html content"} + // TODO support custom version banner? + // {type: "error", content: "html content"} export type VersionBanner = 'unreleased' | 'unmaintained'; export type VersionOptions = { path?: string; diff --git a/packages/docusaurus-plugin-content-docs/src/routes.ts b/packages/docusaurus-plugin-content-docs/src/routes.ts index a853901df4..e86b42f571 100644 --- a/packages/docusaurus-plugin-content-docs/src/routes.ts +++ b/packages/docusaurus-plugin-content-docs/src/routes.ts @@ -73,7 +73,8 @@ export async function createCategoryGeneratedIndexRoutes({ modules: { categoryGeneratedIndex: aliasedSource(propData), }, - // Same as doc, this sidebar route attribute permits to associate this subpage to the given sidebar + // Same as doc, this sidebar route attribute permits to associate this + // subpage to the given sidebar ...(sidebar && {sidebar}), }; } @@ -109,7 +110,8 @@ export async function createDocRoutes({ content: metadataItem.source, }, // Because the parent (DocPage) comp need to access it easily - // This permits to render the sidebar once without unmount/remount when navigating (and preserve sidebar state) + // This permits to render the sidebar once without unmount/remount when + // navigating (and preserve sidebar state) ...(metadataItem.sidebar && { sidebar: metadataItem.sidebar, }), diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts index 3341d8c399..46a016245b 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts @@ -205,7 +205,8 @@ describe('processSidebars', () => { link: { type: 'generated-index', slug: 'generated-cat-index-slug', - // @ts-expect-error: TODO undefined should be allowed here, typing error needing refactor + // @ts-expect-error: TODO undefined should be allowed here, + // typing error needing refactor permalink: undefined, }, }, diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts index 6199d2e483..455acd55fa 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts @@ -47,7 +47,8 @@ export type CategoryMetadataFile = { className?: string; link?: SidebarItemCategoryLinkConfig | null; - // TODO should we allow "items" here? how would this work? would an "autogenerated" type be allowed? + // TODO should we allow "items" here? how would this work? would an + // "autogenerated" type be allowed? // This mkdocs plugin do something like that: https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin/ // cf comment: https://github.com/facebook/docusaurus/issues/3464#issuecomment-784765199 }; @@ -56,16 +57,20 @@ type WithPosition = T & {position?: number}; /** * A representation of the fs structure. For each object entry: - * If it's a folder, the key is the directory name, and value is the directory content; - * If it's a doc file, the key is the doc id prefixed with '$doc$/', and value is null + * If it's a folder, the key is the directory name, and value is the directory + * content; If it's a doc file, the key is the doc id prefixed with '$doc$/', + * and value is null */ type Dir = { [item: string]: Dir | null; }; -// TODO I now believe we should read all the category metadata files ahead of time: we may need this metadata to customize docs metadata -// Example use-case being able to disable number prefix parsing at the folder level, or customize the default route path segment for an intermediate directory... -// TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may want to read the metadata as yaml on it +// TODO I now believe we should read all the category metadata files ahead of +// time: we may need this metadata to customize docs metadata +// Example use-case being able to disable number prefix parsing at the folder +// level, or customize the default base slug for an intermediate directory +// TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may +// want to read the metadata as yaml on it // see https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449 async function readCategoryMetadataFile( categoryDirPath: string, @@ -142,7 +147,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ * Step 2. Turn the linear file list into a tree structure. */ function treeify(docs: SidebarItemsGeneratorDoc[]): Dir { - // Get the category breadcrumb of a doc (relative to the dir of the autogenerated sidebar item) + // Get the category breadcrumb of a doc (relative to the dir of the + // autogenerated sidebar item) // autogenDir=a/b and docDir=a/b/c/d => returns [c, d] // autogenDir=a/b and docDir=a/b => returns [] // TODO: try to use path.relative() @@ -169,7 +175,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ } /** - * Step 3. Recursively transform the tree-like file structure to sidebar items. + * Step 3. Recursively transform the tree-like structure to sidebar items. * (From a record to an array of items, akin to normalizing shorthand) */ function generateSidebar(fsModel: Dir): Promise[]> { @@ -182,7 +188,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ type: 'doc', id, position, - // We don't want these fields to magically appear in the generated sidebar + // We don't want these fields to magically appear in the generated + // sidebar ...(label !== undefined && {label}), ...(className !== undefined && {className}), }; @@ -225,13 +232,12 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ if (link !== undefined) { if (link && link.type === 'doc') { return findDocByLocalId(link.id)?.id || getDoc(link.id).id; - } else { - // We don't continue for other link types on purpose! - // IE if user decide to use type "generated-index", we should not pick a README.md file as the linked doc - return undefined; } + // If a link is explicitly specified, we won't apply conventions + return undefined; } - // Apply default convention to pick index.md, README.md or .md as the category doc + // Apply default convention to pick index.md, README.md or + // .md as the category doc return findConventionalCategoryDocLink()?.id; } @@ -279,10 +285,11 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ } /** - * Step 4. Recursively sort the categories/docs + remove the "position" attribute from final output. - * Note: the "position" is only used to sort "inside" a sidebar slice. It is not - * used to sort across multiple consecutive sidebar slices (ie a whole Category - * composed of multiple autogenerated items) + * Step 4. Recursively sort the categories/docs + remove the "position" + * attribute from final output. Note: the "position" is only used to sort + * "inside" a sidebar slice. It is not used to sort across multiple + * consecutive sidebar slices (i.e. a whole category composed of multiple + * autogenerated items) */ function sortItems(sidebarItems: WithPosition[]): SidebarItem[] { const processedSidebarItems = sidebarItems.map((item) => { @@ -298,7 +305,6 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ return sortedSidebarItems.map(({position, ...item}) => item); } // TODO: the whole code is designed for pipeline operator - // return getAutogenDocs() |> treeify |> await generateSidebar(^) |> sortItems; const docs = getAutogenDocs(); const fsModel = treeify(docs); const sidebarWithPosition = await generateSidebar(fsModel); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts index 0ef94ba25f..9336a1a049 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts @@ -60,7 +60,8 @@ function toSidebarItemsGeneratorVersion( return pick(version, ['versionName', 'contentPath']); } -// Handle the generation of autogenerated sidebar items and other post-processing checks +// Handle the generation of autogenerated sidebar items and other +// post-processing checks async function processSidebar( unprocessedSidebar: NormalizedSidebar, params: SidebarProcessorParams, @@ -91,7 +92,8 @@ async function processSidebar( async function processAutoGeneratedItem( item: SidebarItemAutogenerated, ): Promise { - // TODO the returned type can't be trusted in practice (generator can be user-provided) + // TODO the returned type can't be trusted in practice (generator can be + // user-provided) const generatedItems = await sidebarItemsGenerator({ item, numberPrefixParser, @@ -106,7 +108,8 @@ async function processSidebar( normalizeItem(generatedItem, {...params, ...sidebarOptions}), ); - // Process again... weird but sidebar item generated might generate some auto-generated items? + // Process again... weird but sidebar item generated might generate some + // auto-generated items? return processItems(generatedItemsNormalized); } diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts index 56a4be084a..331887d122 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts @@ -205,7 +205,8 @@ export type SidebarItemsGenerator = ( Promise; // Promise; -// Also inject the default generator to conveniently wrap/enhance/sort the default sidebar gen logic +// Also inject the default generator to conveniently wrap/enhance/sort the +// default sidebar gen logic // see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320 export type SidebarItemsGeneratorOptionArgs = { defaultSidebarItemsGenerator: SidebarItemsGenerator; diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts index 80bc2a3fd3..7b2e902fad 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts @@ -16,7 +16,6 @@ import type { SidebarCategoriesShorthand, SidebarItemConfig, SidebarItemCategoryWithGeneratedIndex, - SidebarItemCategoryWithLink, SidebarNavigationItem, } from './types'; @@ -46,8 +45,11 @@ export function transformSidebarItems( return sidebar.map(transformRecursive); } -// Flatten sidebar items into a single flat array (containing categories/docs on the same level) -// /!\ order matters (useful for next/prev nav), top categories appear before their child elements +/** + * Flatten sidebar items into a single flat array (containing categories/docs on + * the same level). Order matters (useful for next/prev nav), top categories + * appear before their child elements + */ function flattenSidebarItems(items: SidebarItem[]): SidebarItem[] { function flattenRecursive(item: SidebarItem): SidebarItem[] { return item.type === 'category' @@ -196,34 +198,33 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils { sidebarName = getSidebarNameByDocId(docId); } - if (sidebarName) { - if (!sidebarNameToNavigationItems[sidebarName]) { - throw new Error( - `Doc with ID ${docId} wants to display sidebar ${sidebarName} but a sidebar with this name doesn't exist`, - ); - } - const navigationItems = sidebarNameToNavigationItems[sidebarName]; - const currentItemIndex = navigationItems.findIndex((item) => { - if (item.type === 'doc') { - return item.id === docId; - } - if (item.type === 'category' && item.link.type === 'doc') { - return item.link.id === docId; - } - return false; - }); - if (currentItemIndex === -1) { - return {sidebarName, next: undefined, previous: undefined}; - } - - const {previous, next} = getElementsAround( - navigationItems, - currentItemIndex, - ); - return {sidebarName, previous, next}; - } else { + if (!sidebarName) { return emptySidebarNavigation(); } + if (!sidebarNameToNavigationItems[sidebarName]) { + throw new Error( + `Doc with ID ${docId} wants to display sidebar ${sidebarName} but a sidebar with this name doesn't exist`, + ); + } + const navigationItems = sidebarNameToNavigationItems[sidebarName]; + const currentItemIndex = navigationItems.findIndex((item) => { + if (item.type === 'doc') { + return item.id === docId; + } + if (item.type === 'category' && item.link.type === 'doc') { + return item.link.id === docId; + } + return false; + }); + if (currentItemIndex === -1) { + return {sidebarName, next: undefined, previous: undefined}; + } + + const {previous, next} = getElementsAround( + navigationItems, + currentItemIndex, + ); + return {sidebarName, previous, next}; } function getCategoryGeneratedIndexList(): SidebarItemCategoryWithGeneratedIndex[] { @@ -237,8 +238,10 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils { }); } - // We identity the category generated index by its permalink (should be unique) - // More reliable than using object identity + /** + * We identity the category generated index by its permalink (should be + * unique). More reliable than using object identity + */ function getCategoryGeneratedIndexNavigation( categoryGeneratedIndexPermalink: string, ): SidebarNavigation { @@ -257,19 +260,18 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils { navigationItems.find(isCurrentCategoryGeneratedIndexItem), )?.[0]; - if (sidebarName) { - const navigationItems = sidebarNameToNavigationItems[sidebarName]; - const currentItemIndex = navigationItems.findIndex( - isCurrentCategoryGeneratedIndexItem, - ); - const {previous, next} = getElementsAround( - navigationItems, - currentItemIndex, - ); - return {sidebarName, previous, next}; - } else { + if (!sidebarName) { return emptySidebarNavigation(); } + const navigationItems = sidebarNameToNavigationItems[sidebarName]; + const currentItemIndex = navigationItems.findIndex( + isCurrentCategoryGeneratedIndexItem, + ); + const {previous, next} = getElementsAround( + navigationItems, + currentItemIndex, + ); + return {sidebarName, previous, next}; } function checkSidebarsDocIds(validDocIds: string[], sidebarFilePath: string) { @@ -322,11 +324,10 @@ Available document ids are: slug: item.link.slug, label: item.label, }; - } else { - const firstSubItem = getFirstLink(item.items); - if (firstSubItem) { - return firstSubItem; - } + } + const firstSubItem = getFirstLink(item.items); + if (firstSubItem) { + return firstSubItem; } } } @@ -371,18 +372,6 @@ export function toNavigationLink( return doc; } - function handleCategory(category: SidebarItemCategoryWithLink): DocNavLink { - if (category.link.type === 'doc') { - return toDocNavigationLink(getDocById(category.link.id)); - } else if (category.link.type === 'generated-index') { - return { - title: category.label, - permalink: category.link.permalink, - }; - } else { - throw new Error('unexpected category link type'); - } - } if (!navigationItem) { return undefined; } @@ -390,8 +379,15 @@ export function toNavigationLink( if (navigationItem.type === 'doc') { return toDocNavigationLink(getDocById(navigationItem.id)); } else if (navigationItem.type === 'category') { - return handleCategory(navigationItem); - } else { - throw new Error('unexpected navigation item'); + if (navigationItem.link.type === 'doc') { + return toDocNavigationLink(getDocById(navigationItem.link.id)); + } else if (navigationItem.link.type === 'generated-index') { + return { + title: navigationItem.label, + permalink: navigationItem.link.permalink, + }; + } + throw new Error('unexpected category link type'); } + throw new Error('unexpected navigation item'); } diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts index 3535d0cb3d..9b6845a877 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts @@ -23,7 +23,8 @@ import {isCategoriesShorthand} from './utils'; import type {CategoryMetadataFile} from './generator'; // NOTE: we don't add any default values during validation on purpose! -// Config types are exposed to users for typechecking and we use the same type in normalization +// Config types are exposed to users for typechecking and we use the same type +// in normalization const sidebarItemBaseSchema = Joi.object({ className: Joi.string(), @@ -71,7 +72,8 @@ const sidebarItemCategoryLinkSchema = Joi.object() then: Joi.object({ type: 'generated-index', slug: Joi.string().optional(), - // permalink: Joi.string().optional(), // No, this one is not in the user config, only in the normalized version + // This one is not in the user config, only in the normalized version + // permalink: Joi.string().optional(), title: Joi.string().optional(), description: Joi.string().optional(), image: Joi.string().optional(), @@ -132,7 +134,8 @@ function validateSidebarItem(item: unknown): asserts item is SidebarItemConfig { return; } // TODO: remove once with proper Joi support - // Because we can't use Joi to validate nested items (see above), we do it manually + // Because we can't use Joi to validate nested items (see above), we do it + // manually if (isCategoriesShorthand(item as SidebarItemConfig)) { Object.values(item as SidebarCategoriesShorthand).forEach((category) => category.forEach(validateSidebarItem), diff --git a/packages/docusaurus-plugin-content-docs/src/slug.ts b/packages/docusaurus-plugin-content-docs/src/slug.ts index e5168563c2..14c99925dc 100644 --- a/packages/docusaurus-plugin-content-docs/src/slug.ts +++ b/packages/docusaurus-plugin-content-docs/src/slug.ts @@ -48,17 +48,16 @@ export default function getSlug({ function computeSlug(): string { if (frontMatterSlug?.startsWith('/')) { return frontMatterSlug; - } else { - const dirNameSlug = getDirNameSlug(); - if ( - !frontMatterSlug && - isCategoryIndex(toCategoryIndexMatcherParam({source, sourceDirName})) - ) { - return dirNameSlug; - } - const baseSlug = frontMatterSlug || baseID; - return resolvePathname(baseSlug, getDirNameSlug()); } + const dirNameSlug = getDirNameSlug(); + if ( + !frontMatterSlug && + isCategoryIndex(toCategoryIndexMatcherParam({source, sourceDirName})) + ) { + return dirNameSlug; + } + const baseSlug = frontMatterSlug || baseID; + return resolvePathname(baseSlug, getDirNameSlug()); } function ensureValidSlug(slug: string): string { diff --git a/packages/docusaurus-plugin-content-docs/src/translations.ts b/packages/docusaurus-plugin-content-docs/src/translations.ts index 772c350ab3..d1d24172b7 100644 --- a/packages/docusaurus-plugin-content-docs/src/translations.ts +++ b/packages/docusaurus-plugin-content-docs/src/translations.ts @@ -31,11 +31,10 @@ import {CURRENT_VERSION_NAME} from './constants'; function getVersionFileName(versionName: string): string { if (versionName === CURRENT_VERSION_NAME) { return versionName; - } else { - // I don't like this "version-" prefix, - // but it's for consistency with site/versioned_docs - return `version-${versionName}`; } + // I don't like this "version-" prefix, + // but it's for consistency with site/versioned_docs + return `version-${versionName}`; } // TODO legacy, the sidebar name is like "version-2.0.0-alpha.66/docs" @@ -68,7 +67,8 @@ function getDocTranslations(doc: DocMetadata): TranslationFileContent { ? { [`${doc.unversionedId}.sidebar_label`]: { message: doc.sidebar_label, - description: `The sidebar label for doc with id=${doc.unversionedId}`, + description: + `The sidebar label for doc with id=${doc.unversionedId}`, }, } : undefined), @@ -253,7 +253,8 @@ function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles { const sidebarsTranslations: TranslationFileContent = getSidebarsTranslations(version); - // const docsTranslations: TranslationFileContent = getDocsTranslations(version); + // const docsTranslations: TranslationFileContent = + // getDocsTranslations(version); return [ { diff --git a/packages/docusaurus-plugin-content-docs/src/versions.ts b/packages/docusaurus-plugin-content-docs/src/versions.ts index 7934a4e0b7..fc76c649a2 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions.ts @@ -33,11 +33,9 @@ import {resolveSidebarPathOption} from './sidebars'; // retro-compatibility: no prefix for the default plugin id function addPluginIdPrefix(fileOrDir: string, pluginId: string): string { - if (pluginId === DEFAULT_PLUGIN_ID) { - return fileOrDir; - } else { - return `${pluginId}_${fileOrDir}`; - } + return pluginId === DEFAULT_PLUGIN_ID + ? fileOrDir + : `${pluginId}_${fileOrDir}`; } export function getVersionedDocsDirPath( @@ -96,9 +94,8 @@ async function readVersionsFile( const content = JSON.parse(await fs.readFile(versionsFilePath, 'utf8')); ensureValidVersionArray(content); return content; - } else { - return null; } + return null; } async function readVersionNames( @@ -274,15 +271,13 @@ function getDefaultVersionBanner({ return null; } // Upcoming versions: unreleased banner - else if ( + if ( versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName) ) { return 'unreleased'; } // Older versions: display unmaintained banner - else { - return 'unmaintained'; - } + return 'unmaintained'; } function getVersionBanner({ @@ -443,8 +438,9 @@ function checkVersionMetadataPaths({ ); } - // If the current version defines a path to a sidebar file that does not exist, we throw! - // Note: for versioned sidebars, the file may not exist (as we prefer to not create it rather than to create an empty file) + // If the current version defines a path to a sidebar file that does not + // exist, we throw! Note: for versioned sidebars, the file may not exist (as + // we prefer to not create it rather than to create an empty file) // See https://github.com/facebook/docusaurus/issues/3366 // See https://github.com/facebook/docusaurus/pull/4775 if ( @@ -469,11 +465,10 @@ Please set the docs "sidebarPath" field in your config file to: function getDefaultLastVersionName(versionNames: string[]) { if (versionNames.length === 1) { return versionNames[0]; - } else { - return versionNames.filter( - (versionName) => versionName !== CURRENT_VERSION_NAME, - )[0]; } + return versionNames.filter( + (versionName) => versionName !== CURRENT_VERSION_NAME, + )[0]; } function checkVersionsOptions( @@ -544,9 +539,8 @@ function filterVersions( return versionNamesUnfiltered.filter((name) => (options.onlyIncludeVersions || []).includes(name), ); - } else { - return versionNamesUnfiltered; } + return versionNamesUnfiltered; } export async function readVersionsMetadata({ diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index c553d08444..b5cee171af 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -112,29 +112,28 @@ export default async function pluginContentPages( options.routeBasePath, encodePath(fileToPath(relativeSource)), ]); - if (isMarkdownSource(relativeSource)) { - const content = await fs.readFile(source, 'utf-8'); - const { - frontMatter: unsafeFrontMatter, - contentTitle, - excerpt, - } = parseMarkdownString(content); - const frontMatter = validatePageFrontMatter(unsafeFrontMatter); - return { - type: 'mdx', - permalink, - source: aliasedSourcePath, - title: frontMatter.title ?? contentTitle, - description: frontMatter.description ?? excerpt, - frontMatter, - }; - } else { + if (!isMarkdownSource(relativeSource)) { return { type: 'jsx', permalink, source: aliasedSourcePath, }; } + const content = await fs.readFile(source, 'utf-8'); + const { + frontMatter: unsafeFrontMatter, + contentTitle, + excerpt, + } = parseMarkdownString(content); + const frontMatter = validatePageFrontMatter(unsafeFrontMatter); + return { + type: 'mdx', + permalink, + source: aliasedSourcePath, + title: frontMatter.title ?? contentTitle, + description: frontMatter.description ?? excerpt, + frontMatter, + }; } return Promise.all(pagesFiles.map(toMetadata)); diff --git a/packages/docusaurus-plugin-debug/src/plugin-debug.d.ts b/packages/docusaurus-plugin-debug/src/plugin-debug.d.ts index 890a2b38a8..93b666dd4f 100644 --- a/packages/docusaurus-plugin-debug/src/plugin-debug.d.ts +++ b/packages/docusaurus-plugin-debug/src/plugin-debug.d.ts @@ -33,6 +33,8 @@ declare module '@theme/DebugJsonView' { } declare module '@theme/DebugLayout' { + import type {ReactNode} from 'react'; + export default function DebugLayout(props: { children: ReactNode; }): JSX.Element; diff --git a/packages/docusaurus-plugin-google-analytics/src/analytics.ts b/packages/docusaurus-plugin-google-analytics/src/analytics.ts index ae5c6532fe..e0196d77fb 100644 --- a/packages/docusaurus-plugin-google-analytics/src/analytics.ts +++ b/packages/docusaurus-plugin-google-analytics/src/analytics.ts @@ -7,7 +7,7 @@ import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; -export default (function () { +export default (function analyticsModule() { if (!ExecutionEnvironment.canUseDOM) { return null; } diff --git a/packages/docusaurus-plugin-google-gtag/src/gtag.ts b/packages/docusaurus-plugin-google-gtag/src/gtag.ts index 4e07afe4d8..9cf397488f 100644 --- a/packages/docusaurus-plugin-google-gtag/src/gtag.ts +++ b/packages/docusaurus-plugin-google-gtag/src/gtag.ts @@ -9,7 +9,7 @@ import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; import globalData from '@generated/globalData'; import type {PluginOptions} from '@docusaurus/plugin-google-gtag'; -export default (function () { +export default (function gtagModule() { if (!ExecutionEnvironment.canUseDOM) { return null; } @@ -19,7 +19,8 @@ export default (function () { return { onRouteUpdate({location}: {location: Location}) { - // Always refer to the variable on window in-case it gets overridden elsewhere. + // Always refer to the variable on window in case it gets overridden + // elsewhere. window.gtag('config', trackingID, { page_path: location.pathname, page_title: document.title, diff --git a/packages/docusaurus-plugin-google-gtag/src/index.ts b/packages/docusaurus-plugin-google-gtag/src/index.ts index 5dacf0a1c3..ad66bca069 100644 --- a/packages/docusaurus-plugin-google-gtag/src/index.ts +++ b/packages/docusaurus-plugin-google-gtag/src/index.ts @@ -40,7 +40,8 @@ export default function pluginGoogleGtag( return {}; } return { - // Gtag includes GA by default, so we also preconnect to google-analytics. + // Gtag includes GA by default, so we also preconnect to + // google-analytics. headTags: [ { tagName: 'link', diff --git a/packages/docusaurus-plugin-ideal-image/src/deps.d.ts b/packages/docusaurus-plugin-ideal-image/src/deps.d.ts index b77a092e37..2adc3d7281 100644 --- a/packages/docusaurus-plugin-ideal-image/src/deps.d.ts +++ b/packages/docusaurus-plugin-ideal-image/src/deps.d.ts @@ -9,9 +9,12 @@ /** * @see https://github.com/endiliey/react-ideal-image/blob/master/index.d.ts - * Note: the original type definition is WRONG. getIcon & getMessage receive full state object. + * Note: the original type definition is WRONG. getIcon & getMessage receive + * full state object. */ declare module '@endiliey/react-ideal-image' { + import type {ComponentProps, ComponentType, CSSProperties} from 'react'; + export type LoadingState = 'initial' | 'loading' | 'loaded' | 'error'; export type State = { @@ -39,19 +42,21 @@ declare module '@endiliey/react-ideal-image' { type ThemeKey = 'placeholder' | 'img' | 'icon' | 'noscript'; - export interface ImageProps { + export interface ImageProps extends ComponentProps<'img'> { /** - * This function decides what icon to show based on the current state of the component. + * This function decides what icon to show based on the current state of the + * component. */ getIcon?: (state: State) => IconKey; /** - * This function decides what message to show based on the icon (returned from getIcon prop) and - * the current state of the component. + * This function decides what message to show based on the icon (returned + * from `getIcon` prop) and the current state of the component. */ - getMessage?: (icon: IconKey, state: State) => string; + getMessage?: (icon: IconKey, state: State) => string | null; /** - * This function is called as soon as the component enters the viewport and is used to generate urls - * based on width and format if props.srcSet doesn't provide src field. + * This function is called as soon as the component enters the viewport and + * is used to generate urls based on width and format if `props.srcSet` + * doesn't provide `src` field. */ getUrl?: (srcType: SrcType) => string; /** @@ -59,10 +64,11 @@ declare module '@endiliey/react-ideal-image' { */ height: number; /** - * This provides a map of the icons. By default, the component uses icons from material design, - * implemented as React components with the SVG element. You can customize icons + * This provides a map of the icons. By default, the component uses icons + * from material design, Implemented as React components with the SVG + * element. You can customize icons */ - icons: Partial>; + icons?: Partial>; /** * This prop takes one of the 2 options, xhr and image. * Read more about it: @@ -74,9 +80,10 @@ declare module '@endiliey/react-ideal-image' { */ placeholder: {color: string} | {lqip: string}; /** - * This function decides if image should be downloaded automatically. The default function - * returns false for a 2g network, for a 3g network it decides based on props.threshold - * and for a 4g network it returns true by default. + * This function decides if image should be downloaded automatically. The + * default function returns false for a 2g network, for a 3g network it + * decides based on `props.threshold` and for a 4g network it returns true + * by default. */ shouldAutoDownload?: (options: { connection?: 'slow-2g' | '2g' | '3g' | '4g'; @@ -85,18 +92,20 @@ declare module '@endiliey/react-ideal-image' { possiblySlowNetwork?: boolean; }) => boolean; /** - * This provides an array of sources of different format and size of the image. - * Read more about it: + * This provides an array of sources of different format and size of the + * image. Read more about it: * https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#srcset */ srcSet: SrcType[]; /** - * This provides a theme to the component. By default, the component uses inline styles, - * but it is also possible to use CSS modules and override all styles. + * This provides a theme to the component. By default, the component uses + * inline styles, but it is also possible to use CSS modules and override + * all styles. */ theme?: Partial>; /** - * Tells how much to wait in milliseconds until consider the download to be slow. + * Tells how much to wait in milliseconds until consider the download to be + * slow. */ threshold?: number; /** @@ -105,8 +114,6 @@ declare module '@endiliey/react-ideal-image' { width: number; } - type IdealImageComponent = ComponentClass; - - declare const IdealImage: IdealImageComponent; + declare const IdealImage: (props: ImageProps) => JSX.Element; export default IdealImage; } diff --git a/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts b/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts index b992324e6d..c576246ebb 100644 --- a/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts +++ b/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts @@ -12,15 +12,21 @@ declare module '@docusaurus/plugin-ideal-image' { */ name?: string; /** - * Specify all widths you want to use; if a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up). You may also declare a default sizes array in the loader options in your webpack.config.js. + * Specify all widths you want to use; if a specified size exceeds the + * original image's width, the latter will be used (i.e. images won't be + * scaled up). You may also declare a default sizes array in the loader + * options in your webpack.config.js. */ sizes?: number[]; /** - * Specify one width you want to use; if the specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up) + * Specify one width you want to use; if the specified size exceeds the + * original image's width, the latter will be used (i.e. images won't be + * scaled up) */ size?: number; /** - * As an alternative to manually specifying sizes, you can specify min, max and steps, and the sizes will be generated for you. + * As an alternative to manually specifying sizes, you can specify min, max + * and steps, and the sizes will be generated for you. */ min?: number; /** diff --git a/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage/index.tsx b/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage/index.tsx index 60d4e323f9..9e8fe9b1cd 100644 --- a/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage/index.tsx +++ b/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage/index.tsx @@ -68,13 +68,12 @@ const getMessage = (icon: IconKey, state: State) => { message: '404. Image not found', description: 'When the image is not found', }); - } else { - return translate({ - id: 'theme.IdealImageMessage.error', - message: 'Error. Click to reload', - description: 'When the image fails to load for unknown error', - }); } + return translate({ + id: 'theme.IdealImageMessage.error', + message: 'Error. Click to reload', + description: 'When the image fails to load for unknown error', + }); } default: throw new Error(`Wrong icon: ${icon}`); diff --git a/packages/docusaurus-plugin-pwa/src/index.ts b/packages/docusaurus-plugin-pwa/src/index.ts index 64ee7bc02d..a03a1cfdb2 100644 --- a/packages/docusaurus-plugin-pwa/src/index.ts +++ b/packages/docusaurus-plugin-pwa/src/index.ts @@ -46,7 +46,7 @@ function getSWBabelLoader() { }; } -export default function ( +export default function pluginPWA( context: LoadContext, options: PluginOptions, ): Plugin { diff --git a/packages/docusaurus-plugin-pwa/src/registerSw.js b/packages/docusaurus-plugin-pwa/src/registerSw.js index d46bf6cdcc..ec507d7a12 100644 --- a/packages/docusaurus-plugin-pwa/src/registerSw.js +++ b/packages/docusaurus-plugin-pwa/src/registerSw.js @@ -219,8 +219,8 @@ async function registerSW() { } } -// TODO these events still works in chrome but have been removed from the spec in 2019! -// See https://github.com/w3c/manifest/pull/836 +// TODO these events still works in chrome but have been removed from the spec +// in 2019! See https://github.com/w3c/manifest/pull/836 function addLegacyAppInstalledEventsListeners() { if (typeof window !== 'undefined') { if (debug) { @@ -248,7 +248,8 @@ function addLegacyAppInstalledEventsListeners() { await clearRegistrations(); }); - // TODO this event still works in chrome but has been removed from the spec in 2019!!! + // TODO this event still works in chrome but has been removed from the spec + // in 2019!!! window.addEventListener('beforeinstallprompt', async (event) => { if (debug) { console.log( @@ -256,7 +257,8 @@ function addLegacyAppInstalledEventsListeners() { event, ); } - // TODO instead of default browser install UI, show custom docusaurus prompt? + // TODO instead of default browser install UI, show custom docusaurus + // prompt? // event.preventDefault(); if (debug) { console.log( @@ -273,7 +275,7 @@ function addLegacyAppInstalledEventsListeners() { } // After uninstalling the app, if the user doesn't clear all data, then // the previous service worker will continue serving cached files. We - // need to clear registrations and reload, otherwise the popup will show. + // need to clear registrations and reload, otherwise the popup shows. await clearRegistrations(); } }); diff --git a/packages/docusaurus-plugin-pwa/src/sw.js b/packages/docusaurus-plugin-pwa/src/sw.js index 4834f2bcf0..155228cb38 100644 --- a/packages/docusaurus-plugin-pwa/src/sw.js +++ b/packages/docusaurus-plugin-pwa/src/sw.js @@ -18,10 +18,10 @@ function parseSwParams() { return params; } -// doc advise against dynamic imports in SW +// doc advises against dynamic imports in SW // https://developers.google.com/web/tools/workbox/guides/using-bundlers#code_splitting_and_dynamic_imports // https://twitter.com/sebastienlorber/status/1280155204575518720 -// but I think it's working fine as it's inlined by webpack, need to double check? +// but looks it's working fine as it's inlined by webpack, need to double check async function runSWCustomCode(params) { if (process.env.PWA_SW_CUSTOM) { const customSW = await import(process.env.PWA_SW_CUSTOM); @@ -70,6 +70,7 @@ function getPossibleURLs(url) { (async () => { const params = parseSwParams(); + // eslint-disable-next-line no-underscore-dangle const precacheManifest = self.__WB_MANIFEST; const controller = new PrecacheController({ fallbackToNetwork: true, // safer to turn this true? diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts index ef1c4c84b8..c8459f70c1 100644 --- a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts +++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts @@ -6,7 +6,7 @@ */ import remark from 'remark'; -// import from the transpiled lib because Babel can't transpile `export =` syntax +// import from the transpiled lib because Babel can't transpile `export =` // TODO change to `../index` after migrating to ESM import npm2yarn from '../../lib/index'; import vfile from 'to-vfile'; diff --git a/packages/docusaurus-theme-classic/src/index.ts b/packages/docusaurus-theme-classic/src/index.ts index a902c96f2c..8434e3b0ff 100644 --- a/packages/docusaurus-theme-classic/src/index.ts +++ b/packages/docusaurus-theme-classic/src/index.ts @@ -23,7 +23,7 @@ const ContextReplacementPlugin: typeof webpack.ContextReplacementPlugin = requireFromDocusaurusCore('webpack/lib/ContextReplacementPlugin'); // Need to be inlined to prevent dark mode FOUC -// Make sure that the 'storageKey' is the same as the one in `/theme/hooks/useTheme.js` +// Make sure the key is the same as the one in `/theme/hooks/useTheme.js` const ThemeStorageKey = 'theme'; const noFlashColorMode = ({ defaultMode, @@ -64,15 +64,17 @@ const noFlashColorMode = ({ } })();`; -// Duplicated constant. Unfortunately we can't import it from theme-common, as we need to support older nodejs versions without ESM support +// Duplicated constant. Unfortunately we can't import it from theme-common, as +// we need to support older nodejs versions without ESM support // TODO: import from theme-common once we only support Node.js with ESM support // + move all those announcementBar stuff there too export const AnnouncementBarDismissStorageKey = 'docusaurus.announcement.dismiss'; const AnnouncementBarDismissDataAttribute = 'data-announcement-bar-initially-dismissed'; -// We always render the announcement bar html on the server, to prevent layout shifts on React hydration -// The theme can use CSS + the data attribute to hide the announcement bar asap (before React hydration) +// We always render the announcement bar html on the server, to prevent layout +// shifts on React hydration. The theme can use CSS + the data attribute to hide +// the announcement bar asap (before React hydration) const AnnouncementBarInlineJavaScript = ` (function() { function isDismissed() { diff --git a/packages/docusaurus-theme-classic/src/theme/BackToTopButton/index.tsx b/packages/docusaurus-theme-classic/src/theme/BackToTopButton/index.tsx index 1b88c9ed62..2a36a576b5 100644 --- a/packages/docusaurus-theme-classic/src/theme/BackToTopButton/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BackToTopButton/index.tsx @@ -22,7 +22,9 @@ const threshold = 300; // TODO proper detection is currently unreliable! // see https://github.com/wessberg/scroll-behavior-polyfill/issues/16 const SupportsNativeSmoothScrolling = false; -// const SupportsNativeSmoothScrolling = ExecutionEnvironment.canUseDOM && 'scrollBehavior' in document.documentElement.style; +// const SupportsNativeSmoothScrolling = +// ExecutionEnvironment.canUseDOM && +// 'scrollBehavior' in document.documentElement.style; type CancelScrollTop = () => void; @@ -44,13 +46,14 @@ function smoothScrollTopPolyfill(): CancelScrollTop { } rafRecursion(); - // Break the recursion - // Prevents the user from "fighting" against that recursion producing a weird UX + // Break the recursion. Prevents the user from "fighting" against that + // recursion producing a weird UX return () => raf && cancelAnimationFrame(raf); } type UseSmoothScrollTopReturn = { - // We use a cancel function because the non-native smooth scroll-top implementation must be interrupted if user scroll down + // We use a cancel function because the non-native smooth scroll-top + // implementation must be interrupted if user scroll down smoothScrollTop: () => void; cancelScrollToTop: CancelScrollTop; }; diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx index ed6c43828d..aebe83109c 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx @@ -21,27 +21,24 @@ function BlogPostAuthor({author}: Props): JSX.Element { )} - { - // Note: only legacy author front matter allow empty name (not frontMatter.authors) - name && ( - ); } diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx index 4972a2d327..b6e00506be 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx @@ -53,8 +53,9 @@ function BlogPostPage(props: Props): JSX.Element { ) : undefined }> tags in markdown map to CodeBlocks and they may contain JSX children. - // When the children is not a simple string, we just return a styled block without actually highlighting. + // When the children is not a simple string, we just return a styled block + // without actually highlighting. if (React.Children.toArray(children).some((el) => isValidElement(el))) { return ( {/* - Title can be declared inside md content or declared through front matter and added manually - To make both cases consistent, the added title is added under the same div.markdown block + Title can be declared inside md content or declared through + front matter and added manually. To make both cases consistent, + the added title is added under the same div.markdown block See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120 */} {shouldAddTitle && ( diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx index 27648505a9..69c804414a 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx @@ -168,7 +168,7 @@ function DocPage(props: Props): JSX.Element { return ( <> - {/* TODO we should add a core addRoute({htmlClassName}) generic plugin option */} + {/* TODO we should add a core addRoute({htmlClassName}) action */} diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx index 7614930599..1af6915821 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx @@ -48,7 +48,8 @@ export default function DocSidebarItem({ } } -// If we navigate to a category and it becomes active, it should automatically expand itself +// If we navigate to a category and it becomes active, it should automatically +// expand itself function useAutoExpandActiveCategory({ isActive, collapsed, @@ -67,11 +68,14 @@ function useAutoExpandActiveCategory({ }, [isActive, wasActive, collapsed, setCollapsed]); } -// When a collapsible category has no link, we still link it to its first child during SSR as a temporary fallback -// This allows to be able to navigate inside the category even when JS fails to load, is delayed or simply disabled -// React hydration becomes an optional progressive enhancement -// see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188 -// see https://github.com/facebook/docusaurus/issues/3030 +/** + * When a collapsible category has no link, we still link it to its first child + * during SSR as a temporary fallback. This allows to be able to navigate inside + * the category even when JS fails to load, is delayed or simply disabled + * React hydration becomes an optional progressive enhancement + * see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188 + * see https://github.com/facebook/docusaurus/issues/3030 + */ function useCategoryHrefWithSSRFallback( item: PropSidebarItemCategory, ): string | undefined { diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/index.tsx b/packages/docusaurus-theme-classic/src/theme/MDXComponents/index.tsx index 17c34a9b06..ac22afa7e0 100644 --- a/packages/docusaurus-theme-classic/src/theme/MDXComponents/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/MDXComponents/index.tsx @@ -19,8 +19,8 @@ import type {MDXComponentsObject} from '@theme/MDXComponents'; import './styles.css'; -// MDX elements are wrapped through the MDX pragma -// In some cases (notably usage with Head/Helmet) we need to unwrap those elements. +// MDX elements are wrapped through the MDX pragma. In some cases (notably usage +// with Head/Helmet) we need to unwrap those elements. function unwrapMDXElement(element: ReactElement) { if (element?.props?.mdxType && element?.props?.originalType) { const {mdxType, originalType, ...newProps} = element.props; @@ -55,7 +55,8 @@ const MDXComponents: MDXComponentsObject = { ), details: (props): JSX.Element => { const items = React.Children.toArray(props.children) as ReactElement[]; - // Split summary item from the rest to pass it as a separate prop to the Details theme component + // Split summary item from the rest to pass it as a separate prop to the + // Details theme component const summary: ReactElement> = items.find( (item) => item?.props?.mdxType === 'summary', )!; diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx index 3349f81cc1..2cf1747835 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx @@ -78,8 +78,8 @@ export default function DocsVersionDropdownNavbarItem({ ? undefined : getVersionMainDoc(dropdownVersion).path; - // We don't want to render a version dropdown with 0 or 1 item - // If we build the site with a single docs version (onlyIncludeVersions: ['1.0.0']) + // We don't want to render a version dropdown with 0 or 1 item. If we build + // the site with a single docs version (onlyIncludeVersions: ['1.0.0']), // We'd rather render a button instead of a dropdown if (items.length <= 1) { return ( diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx index da7606057f..33985d537e 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx @@ -25,8 +25,8 @@ const NavbarItemComponents: Record< search: () => SearchNavbarItem, dropdown: () => DropdownNavbarItem, - // Need to lazy load these items as we don't know for sure the docs plugin is loaded - // See https://github.com/facebook/docusaurus/issues/3360 + // Need to lazy load these items as we don't know for sure the docs plugin is + // loaded. See https://github.com/facebook/docusaurus/issues/3360 /* eslint-disable @typescript-eslint/no-var-requires, global-require */ docsVersion: () => require('@theme/NavbarItem/DocsVersionNavbarItem').default, docsVersionDropdown: () => diff --git a/packages/docusaurus-theme-classic/src/theme/SearchBar.tsx b/packages/docusaurus-theme-classic/src/theme/SearchBar.tsx index 2c59cbfea8..7508f67db9 100644 --- a/packages/docusaurus-theme-classic/src/theme/SearchBar.tsx +++ b/packages/docusaurus-theme-classic/src/theme/SearchBar.tsx @@ -6,7 +6,7 @@ */ // By default, the classic theme does not provide any SearchBar implementation -// If you swizzled this file, it is your responsibility to provide an implementation +// If you swizzled this, it is your responsibility to provide an implementation // Tip: swizzle the SearchBar from the Algolia theme for inspiration: // npm run swizzle @docusaurus/theme-search-algolia SearchBar export {default} from '@docusaurus/Noop'; diff --git a/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx b/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx index efc6beebc5..288bd88142 100644 --- a/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx @@ -12,7 +12,7 @@ import TOCItems from '@theme/TOCItems'; import styles from './styles.module.css'; // Using a custom className -// This prevents TOC highlighting to highlight TOCInline/TOCCollapsible by mistake +// This prevents TOCInline/TOCCollapsible getting highlighted by mistake const LINK_CLASS_NAME = 'table-of-contents__link toc-highlight'; const LINK_ACTIVE_CLASS_NAME = 'table-of-contents__link--active'; diff --git a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx index 9fe416477d..2e77c4c562 100644 --- a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx @@ -55,7 +55,7 @@ function TabsComponent(props: Props): JSX.Element { }); const values = valuesProp ?? - // We only pick keys that we recognize. MDX would inject some keys by default + // Only pick keys that we recognize. MDX would inject some keys by default children.map(({props: {value, label, attributes}}) => ({ value, label, diff --git a/packages/docusaurus-theme-classic/src/translations.ts b/packages/docusaurus-theme-classic/src/translations.ts index 190a8188c7..0ee15d9def 100644 --- a/packages/docusaurus-theme-classic/src/translations.ts +++ b/packages/docusaurus-theme-classic/src/translations.ts @@ -171,7 +171,7 @@ export function translateThemeConfig({ themeConfig, translationFiles, }: { - // Why partial? To make TS correctly figure out the contravariance in parameter. + // To make TS correctly figure out the contravariance in parameter. // In practice it's always normalized themeConfig: ThemeConfig; translationFiles: TranslationFile[]; diff --git a/packages/docusaurus-theme-classic/src/validateThemeConfig.ts b/packages/docusaurus-theme-classic/src/validateThemeConfig.ts index 9fe30dee7f..756366d976 100644 --- a/packages/docusaurus-theme-classic/src/validateThemeConfig.ts +++ b/packages/docusaurus-theme-classic/src/validateThemeConfig.ts @@ -54,8 +54,8 @@ const NavbarItemBaseSchema = Joi.object({ label: Joi.string(), className: Joi.string(), }) - // We allow any unknown attributes on the links - // (users may need additional attributes like target, aria-role, data-customAttribute...) + // We allow any unknown attributes on the links (users may need additional + // attributes like target, aria-role, data-customAttribute...) .unknown(); const DefaultNavbarItemSchema = NavbarItemBaseSchema.append({ @@ -251,8 +251,8 @@ const FooterLinkItemSchema = Joi.object({ .with('to', 'label') .with('href', 'label') .nand('html', 'label') - // We allow any unknown attributes on the links - // (users may need additional attributes like target, aria-role, data-customAttribute...) + // We allow any unknown attributes on the links (users may need additional + // attributes like target, aria-role, data-customAttribute...) .unknown(); const CustomCssSchema = Joi.alternatives() diff --git a/packages/docusaurus-theme-common/src/components/Collapsible/index.tsx b/packages/docusaurus-theme-common/src/components/Collapsible/index.tsx index 57dff7b2f1..f1af0aa293 100644 --- a/packages/docusaurus-theme-common/src/components/Collapsible/index.tsx +++ b/packages/docusaurus-theme-common/src/components/Collapsible/index.tsx @@ -67,7 +67,8 @@ function applyCollapsedStyle(el: HTMLElement, collapsed: boolean) { } /* -Lex111: Dynamic transition duration is used in Material design, this technique is good for a large number of items. +Lex111: Dynamic transition duration is used in Material design, this technique +is good for a large number of items. https://material.io/archive/guidelines/motion/duration-easing.html#duration-easing-dynamic-durations https://github.com/mui-org/material-ui/blob/e724d98eba018e55e1a684236a2037e24bcf050c/packages/material-ui/src/styles/createTransitions.js#L40-L43 */ @@ -151,7 +152,8 @@ type CollapsibleElementType = React.ElementType< Pick, 'className' | 'onTransitionEnd' | 'style'> >; -// Prevent hydration layout shift before animations are handled imperatively with JS +// Prevent hydration layout shift before animations are handled imperatively +// with JS function getSSRStyle(collapsed: boolean) { if (ExecutionEnvironment.canUseDOM) { return undefined; @@ -167,8 +169,9 @@ type CollapsibleBaseProps = { onCollapseTransitionEnd?: (collapsed: boolean) => void; className?: string; - // This is mostly useful for details/summary component where ssrStyle is not needed (as details are hidden natively) - // and can mess-up with the default native behavior of the browser when JS fails to load or is disabled + // This is mostly useful for details/summary component where ssrStyle is not + // needed (as details are hidden natively) and can mess up with the default + // native behavior of the browser when JS fails to load or is disabled disableSSRStyle?: boolean; }; @@ -189,7 +192,8 @@ function CollapsibleBase({ return ( { @@ -215,7 +219,7 @@ function CollapsibleLazy({collapsed, ...props}: CollapsibleBaseProps) { } }, [collapsed]); - // lazyCollapsed updated in effect so that the first expansion transition can work + // lazyCollapsed updated in effect so that first expansion transition can work const [lazyCollapsed, setLazyCollapsed] = useState(collapsed); useLayoutEffect(() => { if (mounted) { @@ -229,9 +233,10 @@ function CollapsibleLazy({collapsed, ...props}: CollapsibleBaseProps) { } type CollapsibleProps = CollapsibleBaseProps & { - // Lazy allows to delay the rendering when collapsed => it will render children only after hydration, on first expansion - // Required prop: it forces to think if content should be server-rendered or not! - // This has perf impact on the SSR output and html file sizes + // Lazy allows to delay the rendering when collapsed => it will render + // children only after hydration, on first expansion + // Required prop: it forces to think if content should be server-rendered + // or not! This has perf impact on the SSR output and html file sizes // See https://github.com/facebook/docusaurus/issues/4753 lazy: boolean; }; diff --git a/packages/docusaurus-theme-common/src/components/Details/index.tsx b/packages/docusaurus-theme-common/src/components/Details/index.tsx index f4c8fa42b3..724a2c92dd 100644 --- a/packages/docusaurus-theme-common/src/components/Details/index.tsx +++ b/packages/docusaurus-theme-common/src/components/Details/index.tsx @@ -41,7 +41,7 @@ function Details({summary, children, ...props}: DetailsProps): JSX.Element { const {collapsed, setCollapsed} = useCollapsible({ initialState: !props.open, }); - // We use a separate prop because it must be set only after animation completes + // Use a separate prop because it must be set only after animation completes // Otherwise close anim won't work const [open, setOpen] = useState(props.open); diff --git a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts index 0b6e944392..1106e11e8f 100644 --- a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts +++ b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts @@ -15,7 +15,8 @@ const windowSizes = { // This "ssr" value is very important to handle hydration FOUC / layout shifts // You have to handle server-rendering explicitly on the call-site - // On the server, you may need to render BOTH the mobile/desktop elements (and hide one of them with mediaquery) + // On the server, you may need to render BOTH the mobile/desktop elements (and + // hide one of them with mediaquery) // We don't return "undefined" on purpose, to make it more explicit ssr: 'ssr', } as const; @@ -33,7 +34,8 @@ function getWindowSize() { : windowSizes.mobile; } -// Simulate the SSR window size in dev, so that potential hydration FOUC/layout shift problems can be seen in dev too! +// Simulate the SSR window size in dev, so that potential hydration FOUC/layout +// shift problems can be seen in dev too! const DevSimulateSSR = process.env.NODE_ENV === 'development' && true; // This hook returns an enum value on purpose! diff --git a/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts b/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts index b221801ada..fea5ac7d4e 100644 --- a/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts +++ b/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts @@ -7,7 +7,8 @@ // These class names are used to style page layouts in Docusaurus // Those are meant to be targeted by user-provided custom CSS selectors -// /!\ Please do not modify the classnames! This is a breaking change, and annoying for users! +// Please do not modify the classnames! This is a breaking change, and annoying +// for users! export const ThemeClassNames = { page: { blogListPage: 'blog-list-page', diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/tocUtils.test.ts b/packages/docusaurus-theme-common/src/utils/__tests__/tocUtils.test.ts index 4792d9a4ac..806f726fdd 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/tocUtils.test.ts +++ b/packages/docusaurus-theme-common/src/utils/__tests__/tocUtils.test.ts @@ -112,8 +112,9 @@ describe('filterTOC', () => { ]); }); - // It's not 100% clear exactly how the TOC should behave under weird heading levels provided by the user - // Adding a test so that behavior stays the same over time + // It's not 100% clear exactly how the TOC should behave under weird heading + // levels provided by the user. Adding a test so that behavior stays the same + // over time test('filter invalid heading levels (but possible) TOC', () => { const toc: TOCItem[] = [ { diff --git a/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx b/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx index d79cc59940..edc98ca1b3 100644 --- a/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx +++ b/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx @@ -76,10 +76,9 @@ function readStorageState({ ); if (versionExists) { return {preferredVersionName: preferredVersionNameUnsafe}; - } else { - DocsPreferredVersionStorage.clear(pluginId, versionPersistence); - return {preferredVersionName: null}; } + DocsPreferredVersionStorage.clear(pluginId, versionPersistence); + return {preferredVersionName: null}; } const initialState: DocsPreferredVersionState = {}; @@ -144,9 +143,8 @@ export function DocsPreferredVersionContextProvider({ {children} ); - } else { - return children; } + return children; } function DocsPreferredVersionContextProviderUnsafe({ diff --git a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx index daf9226b79..676ccee827 100644 --- a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx @@ -20,7 +20,7 @@ import {useLocation} from '@docusaurus/router'; // TODO not ideal, see also "useDocs" export const isDocsPluginEnabled: boolean = !!useAllDocsData; -// Using a Symbol because null is a valid context value (a doc can have no sidebar) +// Using a Symbol because null is a valid context value (a doc with no sidebar) // Inspired by https://github.com/jamiebuilds/unstated-next/blob/master/src/unstated-next.tsx const EmptyContextValue: unique symbol = Symbol('EmptyContext'); @@ -101,11 +101,10 @@ export function findSidebarCategory( if (item.type === 'category') { if (predicate(item)) { return item; - } else { - const subItem = findSidebarCategory(item.items, predicate); - if (subItem) { - return subItem; - } + } + const subItem = findSidebarCategory(item.items, predicate); + if (subItem) { + return subItem; } } } diff --git a/packages/docusaurus-theme-common/src/utils/historyUtils.ts b/packages/docusaurus-theme-common/src/utils/historyUtils.ts index 8243fd4199..6af29066ac 100644 --- a/packages/docusaurus-theme-common/src/utils/historyUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/historyUtils.ts @@ -11,9 +11,10 @@ import type {Location, Action} from '@docusaurus/history'; type HistoryBlockHandler = (location: Location, action: Action) => void | false; -/* -Permits to register a handler that will be called on history actions (pop,push,replace) -If the handler returns false, the navigation transition will be blocked/cancelled +/** + * Permits to register a handler that will be called on history actions (pop, + * push, replace) If the handler returns false, the navigation transition will + * be blocked/cancelled */ export function useHistoryActionHandler(handler: HistoryBlockHandler): void { const {block} = useHistory(); @@ -32,11 +33,11 @@ export function useHistoryActionHandler(handler: HistoryBlockHandler): void { ); } -/* -Permits to register a handler that will be called on history pop navigation (backward/forward) -If the handler returns false, the backward/forward transition will be blocked - -Unfortunately there's no good way to detect the "direction" (backward/forward) of the POP event. +/** + * Permits to register a handler that will be called on history pop navigation + * (backward/forward) If the handler returns false, the backward/forward + * transition will be blocked. Unfortunately there's no good way to detect the + * "direction" (backward/forward) of the POP event. */ export function useHistoryPopHandler(handler: HistoryBlockHandler): void { useHistoryActionHandler((location, action) => { diff --git a/packages/docusaurus-theme-common/src/utils/jsUtils.ts b/packages/docusaurus-theme-common/src/utils/jsUtils.ts index bcd41b3dc4..5a4c43aca9 100644 --- a/packages/docusaurus-theme-common/src/utils/jsUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/jsUtils.ts @@ -10,8 +10,11 @@ /** * Gets the duplicate values in an array. * @param arr The array. - * @param comparator Compares two values and returns `true` if they are equal (duplicated). - * @returns Value of the elements `v` that have a preceding element `u` where `comparator(u, v) === true`. Values within the returned array are not guaranteed to be unique. + * @param comparator Compares two values and returns `true` if they are equal + * (duplicated). + * @returns Value of the elements `v` that have a preceding element `u` where + * `comparator(u, v) === true`. Values within the returned array are not + * guaranteed to be unique. */ export function duplicates( arr: readonly T[], diff --git a/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx b/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx index cae6047260..74bead0bd0 100644 --- a/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx +++ b/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx @@ -16,12 +16,13 @@ import React, { } from 'react'; /* -The idea behind all this is that a specific component must be able to fill a placeholder in the generic layout -The doc page should be able to fill the secondary menu of the main mobile navbar. -This permits to reduce coupling between the main layout and the specific page. +The idea behind all this is that a specific component must be able to fill a +placeholder in the generic layout. The doc page should be able to fill the +secondary menu of the main mobile navbar. This permits to reduce coupling +between the main layout and the specific page. -This kind of feature is often called portal/teleport/gateway... various unmaintained React libs exist -Most up-to-date one: https://github.com/gregberge/react-teleporter +This kind of feature is often called portal/teleport/gateway... various +unmaintained React libs exist. Most up-to-date one: https://github.com/gregberge/react-teleporter Not sure any of those is safe regarding concurrent mode. */ diff --git a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx index 624b9c31de..e934235c69 100644 --- a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx @@ -7,19 +7,27 @@ import {useCallback, useEffect, useLayoutEffect, useRef} from 'react'; -// This hook is like useLayoutEffect, but without the SSR warning -// It seems hacky but it's used in many React libs (Redux, Formik...) -// Also mentioned here: https://github.com/facebook/react/issues/16956 -// It is useful when you need to update a ref as soon as possible after a React render (before useEffect) +/** + * This hook is like useLayoutEffect, but without the SSR warning + * It seems hacky but it's used in many React libs (Redux, Formik...) + * Also mentioned here: https://github.com/facebook/react/issues/16956 + * It is useful when you need to update a ref as soon as possible after a React + * render (before `useEffect`) + */ export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; -// Permits to transform an unstable callback (like an arrow function provided as props) -// to a "stable" callback that is safe to use in a useEffect dependency array -// Useful to avoid React stale closure problems + avoid useless effect re-executions -// -// Workaround until the React team recommends a good solution, see https://github.com/facebook/react/issues/16956 -// This generally works has some potential drawbacks, such as https://github.com/facebook/react/issues/16956#issuecomment-536636418 +/** + * Permits to transform an unstable callback (like an arrow function provided as + * props) to a "stable" callback that is safe to use in a useEffect dependency + * array. Useful to avoid React stale closure problems + avoid useless effect + * re-executions + * + * Workaround until the React team recommends a good solution, see + * https://github.com/facebook/react/issues/16956 + * This generally works but has some potential drawbacks, such as + * https://github.com/facebook/react/issues/16956#issuecomment-536636418 + */ export function useDynamicCallback unknown>( callback: T, ): T { @@ -29,6 +37,7 @@ export function useDynamicCallback unknown>( ref.current = callback; }, [callback]); - // @ts-expect-error: TS is right that this callback may be a supertype of T, but good enough for our use + // @ts-expect-error: TS is right that this callback may be a supertype of T, + // but good enough for our use return useCallback((...args) => ref.current(...args), []); } diff --git a/packages/docusaurus-theme-common/src/utils/regexpUtils.ts b/packages/docusaurus-theme-common/src/utils/regexpUtils.ts index bcb7bb4c88..36d8b8e8de 100644 --- a/packages/docusaurus-theme-common/src/utils/regexpUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/regexpUtils.ts @@ -6,7 +6,7 @@ */ /** - * Utility to convert an optional string into a Regex case insensitive and global + * Converts an optional string into a Regex case insensitive and global */ export function isRegexpStringMatch( regexAsString?: string, diff --git a/packages/docusaurus-theme-common/src/utils/storageUtils.ts b/packages/docusaurus-theme-common/src/utils/storageUtils.ts index 76e4c38fb0..6e5b49f3dd 100644 --- a/packages/docusaurus-theme-common/src/utils/storageUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/storageUtils.ts @@ -11,8 +11,8 @@ export type StorageType = typeof StorageTypes[number]; const DefaultStorageType: StorageType = 'localStorage'; -// Will return null browser storage is unavailable (like running Docusaurus in iframe) -// See https://github.com/facebook/docusaurus/pull/4501 +// Will return null browser storage is unavailable (like running Docusaurus in +// iframe) See https://github.com/facebook/docusaurus/pull/4501 function getBrowserStorage( storageType: StorageType = DefaultStorageType, ): Storage | null { @@ -23,13 +23,12 @@ function getBrowserStorage( } if (storageType === 'none') { return null; - } else { - try { - return window[storageType]; - } catch (e) { - logOnceBrowserStorageNotAvailableWarning(e as Error); - return null; - } + } + try { + return window[storageType]; + } catch (e) { + logOnceBrowserStorageNotAvailableWarning(e as Error); + return null; } } @@ -79,10 +78,10 @@ Please only call storage APIs in effects and event handlers.`); /** * Creates an object for accessing a particular key in localStorage. - * The API is fail-safe, and usage of browser storage should be considered unreliable - * Local storage might simply be unavailable (iframe + browser security) or operations might fail individually - * Please assume that using this API can be a NO-OP - * See also https://github.com/facebook/docusaurus/issues/6036 + * The API is fail-safe, and usage of browser storage should be considered + * unreliable. Local storage might simply be unavailable (iframe + browser + * security) or operations might fail individually. Please assume that using + * this API can be a NO-OP. See also https://github.com/facebook/docusaurus/issues/6036 */ export const createStorageSlot = ( key: string, diff --git a/packages/docusaurus-theme-common/src/utils/tocUtils.ts b/packages/docusaurus-theme-common/src/utils/tocUtils.ts index 3797cded4b..0e88c9fb4f 100644 --- a/packages/docusaurus-theme-common/src/utils/tocUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/tocUtils.ts @@ -36,9 +36,8 @@ export function filterTOC({ children: filteredChildren, }, ]; - } else { - return filteredChildren; } + return filteredChildren; }); } diff --git a/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts b/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts index bff300a634..29ce6f14fe 100644 --- a/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts @@ -39,14 +39,15 @@ export function useAlternatePageUtils(): { : `${baseUrlUnlocalized}${locale}/`; } - // TODO support correct alternate url when localized site is deployed on another domain + // TODO support correct alternate url when localized site is deployed on + // another domain function createUrl({ locale, fullyQualified, }: { locale: string; - // For hreflang SEO headers, we need it to be fully qualified (full protocol/domain/path...) - // For locale dropdown, using a path is good enough + // For hreflang SEO headers, we need it to be fully qualified (full + // protocol/domain/path...) or locale dropdown, using a path is good enough fullyQualified: boolean; }) { return `${fullyQualified ? url : ''}${getLocalizedBaseUrl( diff --git a/packages/docusaurus-theme-common/src/utils/useContextualSearchFilters.ts b/packages/docusaurus-theme-common/src/utils/useContextualSearchFilters.ts index 6df9198a35..d47cf84956 100644 --- a/packages/docusaurus-theme-common/src/utils/useContextualSearchFilters.ts +++ b/packages/docusaurus-theme-common/src/utils/useContextualSearchFilters.ts @@ -18,8 +18,8 @@ export type useContextualSearchFiltersReturns = { tags: string[]; }; -// We may want to support multiple search engines, don't couple that to Algolia/DocSearch -// Maybe users will want to use its own search engine solution +// We may want to support multiple search engines, don't couple that to +// Algolia/DocSearch. Maybe users want to use their own search engine solution export function useContextualSearchFilters(): useContextualSearchFiltersReturns { const {i18n} = useDocusaurusContext(); const allDocsData = useAllDocsData(); diff --git a/packages/docusaurus-theme-common/src/utils/usePluralForm.ts b/packages/docusaurus-theme-common/src/utils/usePluralForm.ts index 77a87d88ae..d0654e973c 100644 --- a/packages/docusaurus-theme-common/src/utils/usePluralForm.ts +++ b/packages/docusaurus-theme-common/src/utils/usePluralForm.ts @@ -49,23 +49,29 @@ function createLocalePluralForms(locale: string): LocalePluralForms { }; } -// Poor man's PluralSelector implementation, using an english fallback. -// We want a lightweight, future-proof and good-enough solution. -// We don't want a perfect and heavy solution. -// -// Docusaurus classic theme has only 2 deeply nested labels requiring complex plural rules -// We don't want to use Intl + PluralRules polyfills + full ICU syntax (react-intl) just for that. -// -// Notes: -// - 2021: 92+% Browsers support Intl.PluralRules, and support will increase in the future -// - NodeJS >= 13 has full ICU support by default -// - In case of "mismatch" between SSR and Browser ICU support, React keeps working! +/** + * Poor man's PluralSelector implementation, using an english fallback. We want + * a lightweight, future-proof and good-enough solution. We don't want a perfect + * and heavy solution. + * + * Docusaurus classic theme has only 2 deeply nested labels requiring complex + * plural rules. We don't want to use Intl + PluralRules polyfills + full ICU + * syntax (react-intl) just for that. + * + * Notes: + * - 2021: 92+% Browsers support Intl.PluralRules, and support will increase in + * the future + * - NodeJS >= 13 has full ICU support by default + * - In case of "mismatch" between SSR and Browser ICU support, React keeps + * working! + */ function useLocalePluralForms(): LocalePluralForms { const { i18n: {currentLocale}, } = useDocusaurusContext(); return useMemo(() => { - // @ts-expect-error checking Intl.PluralRules in case browser doesn't have it (e.g Safari 12-) + // @ts-expect-error checking Intl.PluralRules in case browser doesn't + // have it (e.g Safari 12-) if (Intl.PluralRules) { try { return createLocalePluralForms(currentLocale); @@ -94,17 +100,17 @@ function selectPluralMessage( if (parts.length === 1) { return parts[0]; - } else { - if (parts.length > localePluralForms.pluralForms.length) { - console.error( - `For locale=${localePluralForms.locale}, a maximum of ${localePluralForms.pluralForms.length} plural forms are expected (${localePluralForms.pluralForms}), but the message contains ${parts.length} plural forms: ${pluralMessages} `, - ); - } - const pluralForm = localePluralForms.select(count); - const pluralFormIndex = localePluralForms.pluralForms.indexOf(pluralForm); - // In case of not enough plural form messages, we take the last one (other) instead of returning undefined - return parts[Math.min(pluralFormIndex, parts.length - 1)]; } + if (parts.length > localePluralForms.pluralForms.length) { + console.error( + `For locale=${localePluralForms.locale}, a maximum of ${localePluralForms.pluralForms.length} plural forms are expected (${localePluralForms.pluralForms}), but the message contains ${parts.length} plural forms: ${pluralMessages} `, + ); + } + const pluralForm = localePluralForms.select(count); + const pluralFormIndex = localePluralForms.pluralForms.indexOf(pluralForm); + // In case of not enough plural form messages, we take the last one (other) + // instead of returning undefined + return parts[Math.min(pluralFormIndex, parts.length - 1)]; } export function usePluralForm(): { diff --git a/packages/docusaurus-theme-common/src/utils/useTOCHighlight.ts b/packages/docusaurus-theme-common/src/utils/useTOCHighlight.ts index fa5d54ba4c..8872439871 100644 --- a/packages/docusaurus-theme-common/src/utils/useTOCHighlight.ts +++ b/packages/docusaurus-theme-common/src/utils/useTOCHighlight.ts @@ -13,7 +13,8 @@ TODO make the hardcoded theme-classic classnames configurable (or add them to ThemeClassNames?) */ -// 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 +// 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 function getVisibleBoundingClientRect(element: HTMLElement): DOMRect { const rect = element.getBoundingClientRect(); const hasNoHeight = rect.top === rect.bottom; @@ -23,8 +24,10 @@ function getVisibleBoundingClientRect(element: HTMLElement): DOMRect { return rect; } -// Considering we divide viewport into 2 zones of each 50vh -// This returns true if an element is in the first zone (ie, appear in viewport, near the top) +/** + * Considering we divide viewport into 2 zones of each 50vh, this returns true + * if an element is in the first zone (ie, appear in viewport, near the top) + */ function isInViewportTopHalf(boundingRect: DOMRect) { return boundingRect.top > 0 && boundingRect.bottom < window.innerHeight / 2; } @@ -54,9 +57,10 @@ function getActiveAnchor( anchorTopOffset: number; }, ): Element | null { - // Naming is hard - // The "nextVisibleAnchor" is the first anchor that appear under the viewport top boundary - // Note: it does not mean this anchor is visible yet, but if user continues scrolling down, it will be the first to become visible + // Naming is hard: The "nextVisibleAnchor" is the first anchor that appear + // under the viewport top boundary. It does not mean this anchor is visible + // yet, but if user continues scrolling down, it will be the first to become + // visible const nextVisibleAnchor = anchors.find((anchor) => { const boundingRect = getVisibleBoundingClientRect(anchor); return boundingRect.top >= anchorTopOffset; @@ -64,23 +68,22 @@ function getActiveAnchor( if (nextVisibleAnchor) { const boundingRect = getVisibleBoundingClientRect(nextVisibleAnchor); - // If anchor is in the top half of the viewport: it is the one we consider "active" - // (unless it's too close to the top and and soon to be scrolled outside viewport) + // If anchor is in the top half of the viewport: it is the one we consider + // "active" (unless it's too close to the top and and soon to be scrolled + // outside viewport) if (isInViewportTopHalf(boundingRect)) { return nextVisibleAnchor; } - // If anchor is in the bottom half of the viewport, or under the viewport, we consider the active anchor is the previous one - // This is because the main text appearing in the user screen mostly belong to the previous anchor - else { - // Returns null for the first anchor, see https://github.com/facebook/docusaurus/issues/5318 - return anchors[anchors.indexOf(nextVisibleAnchor) - 1] ?? null; - } + // If anchor is in the bottom half of the viewport, or under the viewport, + // we consider the active anchor is the previous one. This is because the + // main text appearing in the user screen mostly belong to the previous + // anchor. Returns null for the first anchor, see + // https://github.com/facebook/docusaurus/issues/5318 + return anchors[anchors.indexOf(nextVisibleAnchor) - 1] ?? null; } // no anchor under viewport top? (ie we are at the bottom of the page) // => highlight the last anchor found - else { - return anchors[anchors.length - 1]; - } + return anchors[anchors.length - 1]; } function getLinkAnchorValue(link: HTMLAnchorElement): string { diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx index cddbbe9cf1..22623cbded 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx @@ -168,7 +168,8 @@ function DocSearch({ const transformItems = useRef( (items) => items.map((item) => { - // If Algolia contains a external domain, we should navigate without relative URL + // If Algolia contains a external domain, we should navigate without + // relative URL if (isRegexpStringMatch(externalUrlRegex, item.url)) { return item; } diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchMetadata/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchMetadata/index.tsx index de0b99a2f4..2ca2a7c275 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchMetadata/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchMetadata/index.tsx @@ -12,8 +12,8 @@ import type {Props} from '@theme/SearchMetadata'; // Override default/agnostic SearchMetadata to use Algolia-specific metadata function SearchMetadata({locale, version, tag}: Props): JSX.Element { - // Seems safe to consider here the locale is the language, - // as the existing docsearch:language filter is afaik a regular string-based filter + // Seems safe to consider here the locale is the language, as the existing + // docsearch:language filter is afaik a regular string-based filter const language = locale; return ( diff --git a/packages/docusaurus-theme-search-algolia/src/types.d.ts b/packages/docusaurus-theme-search-algolia/src/types.d.ts index 945c78410a..04ccef3c44 100644 --- a/packages/docusaurus-theme-search-algolia/src/types.d.ts +++ b/packages/docusaurus-theme-search-algolia/src/types.d.ts @@ -8,7 +8,3 @@ /// /// /// - -export type FacetFilters = Required< - Required['searchParameters'] ->['facetFilters']; diff --git a/packages/docusaurus-theme-translations/src/__tests__/index.test.ts b/packages/docusaurus-theme-translations/src/__tests__/index.test.ts index b6e82aeb49..3607e0fda0 100644 --- a/packages/docusaurus-theme-translations/src/__tests__/index.test.ts +++ b/packages/docusaurus-theme-translations/src/__tests__/index.test.ts @@ -20,8 +20,8 @@ describe('codeTranslationLocalesToTry', () => { 'fr-Latn', ]); expect(codeTranslationLocalesToTry('fr-FR')).toEqual(['fr-FR', 'fr']); - // Note: "pt" is expanded into "pt-BR", not "pt-PT", as "pt-BR" is more widely used! - // See https://github.com/facebook/docusaurus/pull/4536#issuecomment-810088783 + // Note: "pt" is expanded into "pt-BR", not "pt-PT", as "pt-BR" is more + // widely used! See https://github.com/facebook/docusaurus/pull/4536#issuecomment-810088783 expect(codeTranslationLocalesToTry('pt')).toEqual([ 'pt', 'pt-BR', diff --git a/packages/docusaurus-theme-translations/src/index.ts b/packages/docusaurus-theme-translations/src/index.ts index 24c7559c75..178c93ca1a 100644 --- a/packages/docusaurus-theme-translations/src/index.ts +++ b/packages/docusaurus-theme-translations/src/index.ts @@ -15,8 +15,8 @@ function getDefaultLocalesDirPath(): string { // Return an ordered list of locales we should try export function codeTranslationLocalesToTry(locale: string): string[] { const intlLocale = new Intl.Locale(locale); - // if locale is just a simple language like "pt", we want to fallback to pt-BR (not pt-PT!) - // see https://github.com/facebook/docusaurus/pull/4536#issuecomment-810088783 + // if locale is just a simple language like "pt", we want to fallback to pt-BR + // (not pt-PT!) See https://github.com/facebook/docusaurus/pull/4536#issuecomment-810088783 if (intlLocale.language === locale) { const maximizedLocale = intlLocale.maximize(); // pt-Latn-BR` // ["pt","pt-BR"]; ["zh", "zh-Hans"] @@ -27,9 +27,7 @@ export function codeTranslationLocalesToTry(locale: string): string[] { ]; } // if locale is like "pt-BR", we want to fallback to "pt" - else { - return [locale, intlLocale.language!]; - } + return [locale, intlLocale.language!]; } // Useful to implement getDefaultCodeTranslationMessages() in themes diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index bcbdb8042d..3b590b879c 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -12,8 +12,8 @@ import type Joi from 'joi'; import type {Overwrite, DeepPartial} from 'utility-types'; // Convert webpack-merge webpack-merge enum to union type -// For type retro-compatible webpack-merge upgrade: we used string literals before) -// see https://github.com/survivejs/webpack-merge/issues/179 +// For type retro-compatible webpack-merge upgrade: we used string literals +// before) See https://github.com/survivejs/webpack-merge/issues/179 type MergeStrategy = 'match' | 'merge' | 'append' | 'prepend' | 'replace'; export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'error' | 'throw'; @@ -30,7 +30,8 @@ export interface DocusaurusConfig { tagline: string; title: string; url: string; - // trailingSlash undefined = legacy retrocompatible behavior => /file => /file/index.html + // trailingSlash undefined = legacy retrocompatible behavior + // /file => /file/index.html trailingSlash: boolean | undefined; i18n: I18nConfig; onBrokenLinks: ReportingSeverity; @@ -73,8 +74,8 @@ export interface DocusaurusConfig { } // Docusaurus config, as provided by the user (partial/unnormalized) -// This type is used to provide type-safety / IDE auto-complete on the config file -// See https://docusaurus.io/docs/typescript-support +// This type is used to provide type-safety / IDE auto-complete on the config +// file. See https://docusaurus.io/docs/typescript-support export type Config = Overwrite< Partial, { @@ -88,7 +89,8 @@ export type Config = Overwrite< /** * - `type: 'package'`, plugin is in a different package. * - `type: 'project'`, plugin is in the same docusaurus project. - * - `type: 'local'`, none of plugin's ancestor directory contains any package.json. + * - `type: 'local'`, none of the plugin's ancestor directories contains a + * package.json. * - `type: 'synthetic'`, docusaurus generated internal plugin. */ export type DocusaurusPluginVersionInformation = @@ -259,7 +261,8 @@ export interface Plugin { }) => Promise; routesLoaded?: (routes: RouteConfig[]) => void; // TODO remove soon, deprecated (alpha-60) postBuild?: (props: Props & {content: Content}) => Promise; - // TODO refactor the configureWebpack API surface: use an object instead of multiple params (requires breaking change) + // TODO refactor the configureWebpack API surface: use an object instead of + // multiple params (requires breaking change) configureWebpack?: ( config: Configuration, isServer: boolean, diff --git a/packages/docusaurus-utils-common/src/applyTrailingSlash.ts b/packages/docusaurus-utils-common/src/applyTrailingSlash.ts index 50bf598a73..ee7e38f743 100644 --- a/packages/docusaurus-utils-common/src/applyTrailingSlash.ts +++ b/packages/docusaurus-utils-common/src/applyTrailingSlash.ts @@ -45,8 +45,8 @@ export default function applyTrailingSlash( // Never transform '/' to '' // Never remove the baseUrl trailing slash! - // If baseUrl = /myBase/, we want to emit /myBase/index.html and not /myBase.html ! - // See https://github.com/facebook/docusaurus/issues/5077 + // If baseUrl = /myBase/, we want to emit /myBase/index.html and not + // /myBase.html! See https://github.com/facebook/docusaurus/issues/5077 const shouldNotApply = pathname === '/' || pathname === baseUrl; const newPathname = shouldNotApply diff --git a/packages/docusaurus-utils-validation/src/JoiFrontMatter.ts b/packages/docusaurus-utils-validation/src/JoiFrontMatter.ts index 6fa679b62b..0205e9fdbe 100644 --- a/packages/docusaurus-utils-validation/src/JoiFrontMatter.ts +++ b/packages/docusaurus-utils-validation/src/JoiFrontMatter.ts @@ -7,11 +7,6 @@ import Joi from './Joi'; -// Enhance the default Joi.string() type so that it can convert number to strings -// If user use front matter "tag: 2021", we shouldn't need to ask the user to write "tag: '2021'" -// Also yaml tries to convert patterns like "2019-01-01" to dates automatically -// see https://github.com/facebook/docusaurus/issues/4642 -// see https://github.com/sideway/joi/issues/1442#issuecomment-823997884 const JoiFrontMatterString: Joi.Extension = { type: 'string', base: Joi.string(), @@ -23,4 +18,12 @@ const JoiFrontMatterString: Joi.Extension = { return {value}; }, }; +/** + * Enhance the default Joi.string() type so that it can convert number to + * strings. If user use front matter "tag: 2021", we shouldn't need to ask her + * to write "tag: '2021'". Also yaml tries to convert patterns like "2019-01-01" + * to dates automatically. + * @see https://github.com/facebook/docusaurus/issues/4642 + * @see https://github.com/sideway/joi/issues/1442#issuecomment-823997884 + */ export const JoiFrontMatter: typeof Joi = Joi.extend(JoiFrontMatterString); diff --git a/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts b/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts index 7987f5b946..29f00f7f13 100644 --- a/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts +++ b/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts @@ -43,13 +43,9 @@ function testMarkdownPluginSchemas(schema: Joi.Schema) { }); testOK(undefined); - testOK([function () {}]); - testOK([[function () {}, {attr: 'val'}]]); - testOK([ - [function () {}, {attr: 'val'}], - function () {}, - [function () {}, {attr: 'val'}], - ]); + testOK([() => {}]); + testOK([[() => {}, {attr: 'val'}]]); + testOK([[() => {}, {attr: 'val'}], () => {}, [() => {}, {attr: 'val'}]]); testFail(null); testFail(false); @@ -58,8 +54,8 @@ function testMarkdownPluginSchemas(schema: Joi.Schema) { testFail([false]); testFail([3]); testFail([[]]); - testFail([[function () {}, undefined]]); - testFail([[function () {}, true]]); + testFail([[() => {}, undefined]]); + testFail([[() => {}, true]]); } describe('validation schemas', () => { diff --git a/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts b/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts index 4d06e1014f..8da4c3d1ed 100644 --- a/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts +++ b/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts @@ -48,7 +48,8 @@ describe('validateFrontMatter', () => { }); // Fix Yaml trying to convert strings to numbers automatically - // We only want to deal with a single type in the final front matter (not string | number) + // We only want to deal with a single type in the final front matter + // (not string | number) test('should convert number values to string when string schema', () => { const schema = Joi.object<{test: string}>({ test: JoiFrontMatter.string(), @@ -60,7 +61,8 @@ describe('validateFrontMatter', () => { }); // Helps to fix Yaml trying to convert strings to dates automatically - // We only want to deal with a single type in the final front matter (not string | Date) + // We only want to deal with a single type in the final front matter + // (not string | Date) test('should convert date values when string schema', () => { const schema = Joi.object<{test: string}>({ test: JoiFrontMatter.string(), diff --git a/packages/docusaurus-utils-validation/src/validationSchemas.ts b/packages/docusaurus-utils-validation/src/validationSchemas.ts index e87d7c2a8c..23e50d44c1 100644 --- a/packages/docusaurus-utils-validation/src/validationSchemas.ts +++ b/packages/docusaurus-utils-validation/src/validationSchemas.ts @@ -31,7 +31,8 @@ export const AdmonitionsSchema = Joi.object().default({}); // Joi is such a pain, good luck to annoying trying to improve this export const URISchema = Joi.alternatives( Joi.string().uri({allowRelative: true}), - // This custom validation logic is required notably because Joi does not accept paths like /a/b/c ... + // This custom validation logic is required notably because Joi does not + // accept paths like /a/b/c ... Joi.custom((val, helpers) => { try { // eslint-disable-next-line no-new diff --git a/packages/docusaurus-utils-validation/src/validationUtils.ts b/packages/docusaurus-utils-validation/src/validationUtils.ts index b524a96717..afc6c2c219 100644 --- a/packages/docusaurus-utils-validation/src/validationUtils.ts +++ b/packages/docusaurus-utils-validation/src/validationUtils.ts @@ -58,12 +58,11 @@ export function normalizePluginOptions( if (isValidationDisabledEscapeHatch) { logger.error(error); return options as T; - } else { - throw error; } + throw error; } - return value!; // TODO remove ! this in TS 4.6, see https://twitter.com/sebastienlorber/status/1481950042277793793 + return value!; // TODO remove this ! in TS 4.6, see https://twitter.com/sebastienlorber/status/1481950042277793793 } export function normalizeThemeConfig( @@ -86,11 +85,10 @@ export function normalizeThemeConfig( if (isValidationDisabledEscapeHatch) { logger.error(error); return themeConfig as T; - } else { - throw error; } + throw error; } - return value!; // TODO remove ! this in TS 4.6, see https://twitter.com/sebastienlorber/status/1481950042277793793 + return value!; // TODO remove this ! in TS 4.6 } export function validateFrontMatter( @@ -120,5 +118,5 @@ ${errorDetails.map(({message}) => message)} throw error; } - return value!; // TODO remove ! this in TS 4.6, see https://twitter.com/sebastienlorber/status/1481950042277793793 + return value!; // TODO remove this ! in TS 4.6 } diff --git a/packages/docusaurus-utils/src/__tests__/index.test.ts b/packages/docusaurus-utils/src/__tests__/index.test.ts index 10699adc70..098d6c0cf2 100644 --- a/packages/docusaurus-utils/src/__tests__/index.test.ts +++ b/packages/docusaurus-utils/src/__tests__/index.test.ts @@ -75,7 +75,8 @@ describe('load utils', () => { genChunkName('path/is/similar', 'newPrefix'), ); - // Even with same preferred name, still different chunk name for different path + // Even with same preferred name, still different chunk name for + // different path const secondAssert: Record = { '/blog/1': 'blog-85-f-089', '/blog/2': 'blog-353-489', diff --git a/packages/docusaurus-utils/src/__tests__/markdownParser.test.ts b/packages/docusaurus-utils/src/__tests__/markdownParser.test.ts index 92acd07e70..6b8579f8e4 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownParser.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownParser.test.ts @@ -37,7 +37,8 @@ describe('createExcerpt', () => { Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis. `), ).toEqual( - // h1 title is skipped on purpose, because we don't want the page to have SEO metadata title === description + // h1 title is skipped on purpose, because we don't want the page to have + // SEO metadata title === description 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.', ); }); @@ -54,7 +55,8 @@ describe('createExcerpt', () => { Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis. `), ).toEqual( - // h1 title is skipped on purpose, because we don't want the page to have SEO metadata title === description + // h1 title is skipped on purpose, because we don't want the page to have + // SEO metadata title === description 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.', ); }); diff --git a/packages/docusaurus-utils/src/__tests__/pathUtils.test.ts b/packages/docusaurus-utils/src/__tests__/pathUtils.test.ts index 988af6dd81..0c3666d137 100644 --- a/packages/docusaurus-utils/src/__tests__/pathUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/pathUtils.test.ts @@ -70,7 +70,8 @@ describe('shortName', () => { 字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字: { apfs: '字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字', - // This is pretty bad (a character clipped in half), but I doubt if it ever happens + // This is pretty bad (a character clipped in half), but I doubt if it + // ever happens xfs: '字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字字�', }, }; diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index 4769a5f4cd..4e3b3538f3 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -200,7 +200,8 @@ export function getPluginI18nPath({ return path.join( siteDir, 'i18n', - // namespace first by locale: convenient to work in a single folder for a translator + // namespace first by locale: convenient to work in a single folder for a + // translator locale, // Make it convenient to use for single-instance // ie: return "docs", not "docs-default" nor "docs/default" @@ -212,7 +213,8 @@ export function getPluginI18nPath({ /** * @param permalink The URL that the HTML file corresponds to, without base URL * @param outDir Full path to the output directory - * @param trailingSlash The site config option. If provided, only one path will be read. + * @param trailingSlash The site config option. If provided, only one path will + * be read. * @returns This returns a buffer, which you have to decode string yourself if * needed. (Not always necessary since the output isn't for human consumption * anyways, and most HTML manipulation libs accept buffers) @@ -231,18 +233,17 @@ export async function readOutputHTMLFile( return fs.readFile(withTrailingSlashPath); } else if (trailingSlash === false) { return fs.readFile(withoutTrailingSlashPath); - } else { - const HTMLPath = await findAsyncSequential( - [withTrailingSlashPath, withoutTrailingSlashPath], - fs.pathExists, - ); - if (!HTMLPath) { - throw new Error( - `Expected output HTML file to be found at ${withTrailingSlashPath}`, - ); - } - return fs.readFile(HTMLPath); } + const HTMLPath = await findAsyncSequential( + [withTrailingSlashPath, withoutTrailingSlashPath], + fs.pathExists, + ); + if (!HTMLPath) { + throw new Error( + `Expected output HTML file to be found at ${withTrailingSlashPath}`, + ); + } + return fs.readFile(HTMLPath); } export async function mapAsyncSequential( diff --git a/packages/docusaurus-utils/src/markdownLinks.ts b/packages/docusaurus-utils/src/markdownLinks.ts index 5491e971fd..bf3d5cbf4e 100644 --- a/packages/docusaurus-utils/src/markdownLinks.ts +++ b/packages/docusaurus-utils/src/markdownLinks.ts @@ -51,7 +51,8 @@ export function replaceMarkdownLinks({ if (!fencedBlock) { fencedBlock = true; [lastCodeFence] = line.trim().match(/^`+/)!; - // If we are in a ````-fenced block, all ``` would be plain text instead of fences + // If we are in a ````-fenced block, all ``` would be plain text instead + // of fences } else if (line.trim().match(/^`+/)![0].length >= lastCodeFence.length) { fencedBlock = false; } @@ -62,7 +63,8 @@ export function replaceMarkdownLinks({ let modifiedLine = line; // Replace inline-style links or reference-style links e.g: - // This is [Document 1](doc1.md) -> we replace this doc1.md with correct link + // This is [Document 1](doc1.md) -> we replace this doc1.md with correct + // ink // [doc1]: doc1.md -> we replace this doc1.md with correct link const mdRegex = /(?:(?:\]\()|(?:\]:\s?))(?!https?:\/\/|@site\/)([^'")\]\s>]+\.mdx?)/g; @@ -86,7 +88,8 @@ export function replaceMarkdownLinks({ : undefined; if (permalink) { - // MDX won't be happy if the permalink contains a space, we need to convert it to %20 + // MDX won't be happy if the permalink contains a space, we need to + // convert it to %20 const encodedPermalink = permalink .split('/') .map((part) => part.replace(/\s/g, '%20')) diff --git a/packages/docusaurus-utils/src/markdownParser.ts b/packages/docusaurus-utils/src/markdownParser.ts index 83da2fd414..5f25fd9415 100644 --- a/packages/docusaurus-utils/src/markdownParser.ts +++ b/packages/docusaurus-utils/src/markdownParser.ts @@ -21,9 +21,8 @@ export function parseMarkdownHeadingId(heading: string): { text: matches[1], id: matches[2], }; - } else { - return {text: heading, id: undefined}; } + return {text: heading, id: undefined}; } // Hacky way of stripping out import statements from the excerpt @@ -56,7 +55,8 @@ export function createExcerpt(fileString: string): string | undefined { if (!inCode) { inCode = true; [lastCodeFence] = fileLine.trim().match(/^`+/)!; - // If we are in a ````-fenced block, all ``` would be plain text instead of fences + // If we are in a ````-fenced block, all ``` would be plain text instead + // of fences } else if ( fileLine.trim().match(/^`+/)![0].length >= lastCodeFence.length ) { @@ -113,9 +113,11 @@ export function parseFrontMatter(markdownFileContent: string): { }; } -// Try to convert markdown heading as text -// Does not need to be perfect, it is only used as a fallback when frontMatter.title is not provided -// For now, we just unwrap possible inline code blocks (# `config.js`) +/** + * Try to convert markdown heading to text. Does not need to be perfect, it is + * only used as a fallback when frontMatter.title is not provided. For now, we + * just unwrap possible inline code blocks (# `config.js`) + */ function toTextContentTitle(contentTitle: string): string { if (contentTitle.startsWith('`') && contentTitle.endsWith('`')) { return contentTitle.substring(1, contentTitle.length - 1); @@ -152,15 +154,14 @@ export function parseMarkdownContentTitle( if (!pattern || !title) { return {content, contentTitle: undefined}; - } else { - const newContent = removeContentTitleOption - ? content.replace(pattern, '') - : content; - return { - content: newContent.trim(), - contentTitle: toTextContentTitle(title.trim()).trim(), - }; } + const newContent = removeContentTitleOption + ? content.replace(pattern, '') + : content; + return { + content: newContent.trim(), + contentTitle: toTextContentTitle(title.trim()).trim(), + }; } type ParsedMarkdown = { diff --git a/packages/docusaurus-utils/src/pathUtils.ts b/packages/docusaurus-utils/src/pathUtils.ts index 680af93c04..384b73a2be 100644 --- a/packages/docusaurus-utils/src/pathUtils.ts +++ b/packages/docusaurus-utils/src/pathUtils.ts @@ -9,7 +9,8 @@ import path from 'path'; -// MacOS (APFS) and Windows (NTFS) filename length limit = 255 chars, Others = 255 bytes +// MacOS (APFS) and Windows (NTFS) filename length limit = 255 chars, +// Others = 255 bytes const MAX_PATH_SEGMENT_CHARS = 255; const MAX_PATH_SEGMENT_BYTES = 255; // Space for appending things to the string like file extensions and so on @@ -19,7 +20,7 @@ const isMacOs = () => process.platform === 'darwin'; const isWindows = () => process.platform === 'win32'; export const isNameTooLong = (str: string): boolean => - // This is actually not entirely correct: we can't assume FS from OS. But good enough? + // Not entirely correct: we can't assume FS from OS. But good enough? isMacOs() || isWindows() ? str.length + SPACE_FOR_APPENDING > MAX_PATH_SEGMENT_CHARS // MacOS (APFS) and Windows (NTFS) filename length limit (255 chars) : Buffer.from(str).length + SPACE_FOR_APPENDING > MAX_PATH_SEGMENT_BYTES; // Other (255 bytes) @@ -56,7 +57,8 @@ export const shortName = (str: string): string => { export function posixPath(str: string): string { const isExtendedLengthPath = /^\\\\\?\\/.test(str); - // Forward slashes are only valid Windows paths when they don't contain non-ascii characters. + // Forward slashes are only valid Windows paths when they don't contain non- + // ascii characters. // eslint-disable-next-line no-control-regex const hasNonAscii = /[^\u0000-\u0080]+/.test(str); @@ -66,13 +68,18 @@ export function posixPath(str: string): string { return str.replace(/\\/g, '/'); } -// When you want to display a path in a message/warning/error, -// it's more convenient to: -// - make it relative to cwd() -// - convert to posix (ie not using windows \ path separator) -// This way, Jest tests can run more reliably on any computer/CI -// on both Unix/Windows -// For Windows users this is not perfect (as they see / instead of \) but it's probably good enough +/** + * When you want to display a path in a message/warning/error, it's more + * convenient to: + * + * - make it relative to `cwd()` + * - convert to posix (ie not using windows \ path separator) + * + * This way, Jest tests can run more reliably on any computer/CI on both + * Unix/Windows + * For Windows users this is not perfect (as they see / instead of \) but it's + * probably good enough + */ export function toMessageRelativeFilePath(filePath: string): string { return posixPath(path.relative(process.cwd(), filePath)); } @@ -92,7 +99,8 @@ export function aliasedSitePath(filePath: string, siteDir: string): string { /** * When you have a path like C:\X\Y * It is not safe to use directly when generating code - * For example, this would fail due to unescaped \: `` + * For example, this would fail due to unescaped \: + * `` * But this would work: `` * * posixPath can't be used in all cases, because forward slashes are only valid diff --git a/packages/docusaurus-utils/src/tags.ts b/packages/docusaurus-utils/src/tags.ts index 92f85b8941..64940aef26 100644 --- a/packages/docusaurus-utils/src/tags.ts +++ b/packages/docusaurus-utils/src/tags.ts @@ -28,9 +28,9 @@ export function normalizeFrontMatterTag( // TODO maybe make ensure the permalink is valid url path? function normalizeTagPermalink(permalink: string): string { - // note: we always apply tagsPath on purpose - // for versioned docs, v1/doc.md and v2/doc.md tags with custom permalinks don't lead to the same created page - // tagsPath is different for each doc version + // note: we always apply tagsPath on purpose. For versioned docs, v1/doc.md + // and v2/doc.md tags with custom permalinks don't lead to the same created + // page. tagsPath is different for each doc version return normalizeUrl([tagsPath, permalink]); } @@ -61,11 +61,14 @@ export type TaggedItemGroup = { items: Item[]; }; -// Permits to group docs/blogPosts by tag (provided by FrontMatter) -// Note: groups are indexed by permalink, because routes must be unique in the end -// Labels may vary on 2 md files but they are normalized. -// Docs with label='some label' and label='some-label' should end-up in the same group/page in the end -// We can't create 2 routes /some-label because one would override the other +/** + * Permits to group docs/blogPosts by tag (provided by front matter) + * Note: groups are indexed by permalink, because routes must be unique in the + * end. Labels may vary on 2 md files but they are normalized. Docs with + * label='some label' and label='some-label' should end-up in the same + * group/page in the end. We can't create 2 routes /some-label because one would + * override the other + */ export function groupTaggedItems( items: Item[], getItemTags: (item: Item) => Tag[], @@ -74,7 +77,8 @@ export function groupTaggedItems( function handleItemTag(item: Item, tag: Tag) { // Init missing tag groups - // TODO: it's not really clear what should be the behavior if 2 items have the same tag but the permalink is different for each + // TODO: it's not really clear what should be the behavior if 2 items have + // the same tag but the permalink is different for each // For now, the first tag found wins result[tag.permalink] = result[tag.permalink] ?? { tag, diff --git a/packages/docusaurus-utils/src/urlUtils.ts b/packages/docusaurus-utils/src/urlUtils.ts index 1c02abb774..dacbd1f186 100644 --- a/packages/docusaurus-utils/src/urlUtils.ts +++ b/packages/docusaurus-utils/src/urlUtils.ts @@ -16,7 +16,8 @@ export function normalizeUrl(rawUrls: string[]): string { if (urls[0].match(/^[^/:]+:\/*$/) && urls.length > 1) { const first = urls.shift(); if (first!.startsWith('file:') && urls[0].startsWith('/')) { - // Force a double slash here, else we lose the information that the next segment is an absolute path + // Force a double slash here, else we lose the information that the next + // segment is an absolute path urls[0] = `${first}//${urls[0]}`; } else { urls[0] = first + urls[0]; @@ -48,14 +49,15 @@ export function normalizeUrl(rawUrls: string[]): string { // Removing the starting slashes for each component but the first. component = component.replace( /^[/]+/, - // Special case where the first element of rawUrls is empty ["", "/hello"] => /hello + // Special case where the first element of rawUrls is empty + // ["", "/hello"] => /hello component[0] === '/' && !hasStartingSlash ? '/' : '', ); } hasEndingSlash = component[component.length - 1] === '/'; - // Removing the ending slashes for each component but the last. - // For the last component we will combine multiple slashes to a single one. + // Removing the ending slashes for each component but the last. For the + // last component we will combine multiple slashes to a single one. component = component.replace(/[/]+$/, i < urls.length - 1 ? '' : '/'); } diff --git a/packages/docusaurus-utils/src/webpackUtils.ts b/packages/docusaurus-utils/src/webpackUtils.ts index ea07e96681..499365c400 100644 --- a/packages/docusaurus-utils/src/webpackUtils.ts +++ b/packages/docusaurus-utils/src/webpackUtils.ts @@ -33,7 +33,8 @@ type FileLoaderUtils = { // Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447 export function getFileLoaderUtils(): FileLoaderUtils { - // files/images < urlLoaderLimit will be inlined as base64 strings directly in the html + // files/images < urlLoaderLimit will be inlined as base64 strings directly in + // the html const urlLoaderLimit = WEBPACK_URL_LOADER_LIMIT; // defines the path/pattern of the assets handled by webpack @@ -56,7 +57,7 @@ export function getFileLoaderUtils(): FileLoaderUtils { }, }), - // TODO find a better solution to avoid conflicts with the ideal-image plugin + // TODO avoid conflicts with the ideal-image plugin // TODO this may require a little breaking change for ideal-image users? // Maybe with the ideal image plugin, all md images should be "ideal"? // This is used to force url-loader+file-loader on markdown images diff --git a/packages/docusaurus/src/babel/preset.ts b/packages/docusaurus/src/babel/preset.ts index cb0579aa19..8b8290413f 100644 --- a/packages/docusaurus/src/babel/preset.ts +++ b/packages/docusaurus/src/babel/preset.ts @@ -13,7 +13,8 @@ function getTransformOptions(isServer: boolean): TransformOptions { require.resolve(`@babel/runtime/package.json`), ); return { - // All optional newlines and whitespace will be omitted when generating code in compact mode + // All optional newlines and whitespace will be omitted when generating code + // in compact mode compact: true, presets: [ isServer @@ -48,9 +49,9 @@ function getTransformOptions(isServer: boolean): TransformOptions { { corejs: false, helpers: true, - // By default, it assumes @babel/runtime@7.0.0. Since we use >7.0.0, better to - // explicitly specify the version so that it can reuse the helper better - // See https://github.com/babel/babel/issues/10261 + // By default, it assumes @babel/runtime@7.0.0. Since we use >7.0.0, + // better to explicitly specify the version so that it can reuse the + // helper better. See https://github.com/babel/babel/issues/10261 // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require version: require('@babel/runtime/package.json').version, regenerator: true, diff --git a/packages/docusaurus/src/client/PendingNavigation.tsx b/packages/docusaurus/src/client/PendingNavigation.tsx index c2c39de31c..aab379992d 100644 --- a/packages/docusaurus/src/client/PendingNavigation.tsx +++ b/packages/docusaurus/src/client/PendingNavigation.tsx @@ -49,8 +49,8 @@ class PendingNavigation extends React.Component { const routeDidChange = nextProps.location !== this.props.location; const {routes, delay} = this.props; - // If `routeDidChange` is true, means the router is trying to navigate to a new - // route. We will preload the new route. + // If `routeDidChange` is true, means the router is trying to navigate to a + // new route. We will preload the new route. if (routeDidChange) { const nextLocation = normalizeLocation(nextProps.location); this.startProgressBar(delay); @@ -99,14 +99,14 @@ class PendingNavigation extends React.Component { return true; } - clearProgressBarTimeout() { + private clearProgressBarTimeout() { if (this.progressBarTimeout) { clearTimeout(this.progressBarTimeout); this.progressBarTimeout = null; } } - startProgressBar(delay: number) { + private startProgressBar(delay: number) { this.clearProgressBarTimeout(); this.progressBarTimeout = setTimeout(() => { clientLifecyclesDispatcher.onRouteUpdateDelayed({ @@ -116,7 +116,7 @@ class PendingNavigation extends React.Component { }, delay); } - stopProgressBar() { + private stopProgressBar() { this.clearProgressBarTimeout(); nprogress.done(); } diff --git a/packages/docusaurus/src/client/baseUrlIssueBanner/BaseUrlIssueBanner.tsx b/packages/docusaurus/src/client/baseUrlIssueBanner/BaseUrlIssueBanner.tsx index eb4194843a..59f693931a 100644 --- a/packages/docusaurus/src/client/baseUrlIssueBanner/BaseUrlIssueBanner.tsx +++ b/packages/docusaurus/src/client/baseUrlIssueBanner/BaseUrlIssueBanner.tsx @@ -101,11 +101,14 @@ function BaseUrlIssueBannerEnabled() { ); } -// We want to help the users with a bad baseUrl configuration (very common error) -// Help message is inlined, and hidden if JS or CSS is able to load -// 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 +/** + * We want to help the users with a bad baseUrl configuration (very common + * error) Help message is inlined, and hidden if JS or CSS is able to load + * 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(): JSX.Element | null { const { siteConfig: {baseUrl, baseUrlIssueBanner}, diff --git a/packages/docusaurus/src/client/clientEntry.tsx b/packages/docusaurus/src/client/clientEntry.tsx index 4742ee8105..6a4185d8ac 100644 --- a/packages/docusaurus/src/client/clientEntry.tsx +++ b/packages/docusaurus/src/client/clientEntry.tsx @@ -21,12 +21,14 @@ declare global { } } -// Client-side render (e.g: running in browser) to become single-page application (SPA). +// Client-side render (e.g: running in browser) to become single-page +// application (SPA). if (ExecutionEnvironment.canUseDOM) { window.docusaurus = docusaurus; - // For production, attempt to hydrate existing markup for performant first-load experience. + // For production, attempt to hydrate existing markup for performant + // first-load experience. // For development, there is no existing markup so we had to render it. - // Note that we also preload async component to avoid first-load loading screen. + // We also preload async component to avoid first-load loading screen. const renderMethod = process.env.NODE_ENV === 'production' ? hydrate : render; preload(routes, window.location.pathname).then(() => { renderMethod( diff --git a/packages/docusaurus/src/client/docusaurus.ts b/packages/docusaurus/src/client/docusaurus.ts index 8849cedd22..92de4721d4 100644 --- a/packages/docusaurus/src/client/docusaurus.ts +++ b/packages/docusaurus/src/client/docusaurus.ts @@ -16,7 +16,7 @@ const fetched: Record = {}; const loaded: Record = {}; declare global { - // eslint-disable-next-line camelcase + // eslint-disable-next-line camelcase, no-underscore-dangle const __webpack_require__: {gca: (name: string) => string}; interface Navigator { connection: {effectiveType: string; saveData: boolean}; @@ -66,12 +66,14 @@ const docusaurus = { // Prefetch all webpack chunk assets file needed. chunkNamesNeeded.forEach((chunkName) => { - // "__webpack_require__.gca" is a custom function provided by ChunkAssetPlugin. - // Pass it the chunkName or chunkId you want to load and it will return the URL for that chunk. + // "__webpack_require__.gca" is a custom function provided by + // ChunkAssetPlugin. Pass it the chunkName or chunkId you want to load and + // it will return the URL for that chunk. // eslint-disable-next-line camelcase const chunkAsset = __webpack_require__.gca(chunkName); - // In some cases, webpack might decide to optimize further & hence the chunk assets are merged to another chunk/previous chunk. + // In some cases, webpack might decide to optimize further & hence the + // chunk assets are merged to another chunk/previous chunk. // Hence, we can safely filter it out/don't need to load it. if (chunkAsset && !/undefined/.test(chunkAsset)) { prefetchHelper(chunkAsset); diff --git a/packages/docusaurus/src/client/exports/ComponentCreator.tsx b/packages/docusaurus/src/client/exports/ComponentCreator.tsx index 3b66b9bcc4..dd8eafdefb 100644 --- a/packages/docusaurus/src/client/exports/ComponentCreator.tsx +++ b/packages/docusaurus/src/client/exports/ComponentCreator.tsx @@ -41,7 +41,10 @@ function ComponentCreator( content.foo: () => import('./doc1.md'), } - optsModules: ['./Pages.js', './doc1.md'] - - optsWebpack: [require.resolveWeak('./Pages.js'), require.resolveWeak('./doc1.md')] + - optsWebpack: [ + require.resolveWeak('./Pages.js'), + require.resolveWeak('./doc1.md'), + ] */ const flatChunkNames = flat(chunkNames); Object.keys(flatChunkNames).forEach((key) => { diff --git a/packages/docusaurus/src/client/exports/Interpolate.tsx b/packages/docusaurus/src/client/exports/Interpolate.tsx index 5b608470d6..323369b3ba 100644 --- a/packages/docusaurus/src/client/exports/Interpolate.tsx +++ b/packages/docusaurus/src/client/exports/Interpolate.tsx @@ -21,7 +21,7 @@ More details here: https://github.com/facebook/docusaurus/pull/4295 const ValueRegexp = /{\w+}/g; const ValueFoundMarker = '{}'; // does not care much -// TS function overload: if all the values are plain strings, then interpolate returns a simple string +// If all the values are plain strings, then interpolate returns a simple string export function interpolate( text: Str, values?: InterpolateValues, @@ -55,9 +55,8 @@ export function interpolate( String(value); elements.push(element); return ValueFoundMarker; - } else { - return match; // no match? add warning? } + return match; // no match? add warning? }); // No interpolation to be done: just return the text @@ -65,7 +64,7 @@ export function interpolate( return text; } // Basic string interpolation: returns interpolated string - else if (elements.every((el) => typeof el === 'string')) { + if (elements.every((el) => typeof el === 'string')) { return processedText .split(ValueFoundMarker) .reduce( @@ -75,18 +74,16 @@ export function interpolate( ); } // JSX interpolation: returns ReactNode - else { - return processedText.split(ValueFoundMarker).reduce( - (array, value, index) => [ - ...array, - - {value} - {elements[index]} - , - ], - [], - ); - } + return processedText.split(ValueFoundMarker).reduce( + (array, value, index) => [ + ...array, + + {value} + {elements[index]} + , + ], + [], + ); } export default function Interpolate({ diff --git a/packages/docusaurus/src/client/exports/Link.tsx b/packages/docusaurus/src/client/exports/Link.tsx index f652e11e27..c0fc6e1b34 100644 --- a/packages/docusaurus/src/client/exports/Link.tsx +++ b/packages/docusaurus/src/client/exports/Link.tsx @@ -95,7 +95,7 @@ function Link({ ioRef.current = new window.IntersectionObserver((entries) => { entries.forEach((entry) => { if (el === entry.target) { - // If element is in viewport, stop listening/observing and run callback. + // If element is in viewport, stop observing and run callback. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API if (entry.isIntersecting || entry.intersectionRatio > 0) { ioRef.current!.unobserve(el); @@ -112,7 +112,7 @@ function Link({ const handleRef = (ref: HTMLAnchorElement | null) => { if (IOSupported && ref && isInternal) { - // If IO supported and element reference found, setup Observer functionality. + // If IO supported and element reference found, set up Observer. handleIntersection(ref, () => { if (targetLink != null) { window.docusaurus.prefetch(targetLink); @@ -165,7 +165,8 @@ function Link({ onMouseEnter={onMouseEnter} innerRef={handleRef} to={targetLink || ''} - // avoid "React does not recognize the `activeClassName` prop on a DOM element" + // avoid "React does not recognize the `activeClassName` prop on a DOM + // element" {...(isNavLink && {isActive, activeClassName})} /> ); diff --git a/packages/docusaurus/src/client/exports/Translate.tsx b/packages/docusaurus/src/client/exports/Translate.tsx index d6acd3fc64..4c059d8055 100644 --- a/packages/docusaurus/src/client/exports/Translate.tsx +++ b/packages/docusaurus/src/client/exports/Translate.tsx @@ -40,7 +40,8 @@ export function translate( } // Maybe we'll want to improve this component with additional features -// Like toggling a translation mode that adds a little translation button near the text? +// Like toggling a translation mode that adds a little translation button near +// the text? export default function Translate({ children, id, diff --git a/packages/docusaurus/src/client/exports/browserContext.tsx b/packages/docusaurus/src/client/exports/browserContext.tsx index 56e5e47872..d18cd22ec1 100644 --- a/packages/docusaurus/src/client/exports/browserContext.tsx +++ b/packages/docusaurus/src/client/exports/browserContext.tsx @@ -13,7 +13,8 @@ import React, {type ReactNode, useEffect, useState} from 'react'; // isBrowser is set to true only after a successful hydration // Note, isBrowser is not part of useDocusaurusContext() for perf reasons -// Using useDocusaurusContext() (much more common need) should not trigger re-rendering after a successful hydration +// Using useDocusaurusContext() (much more common need) should not trigger +// re-rendering after a successful hydration export const Context = React.createContext(false); diff --git a/packages/docusaurus/src/client/preload.ts b/packages/docusaurus/src/client/preload.ts index 8163807724..b81d54e62d 100644 --- a/packages/docusaurus/src/client/preload.ts +++ b/packages/docusaurus/src/client/preload.ts @@ -9,7 +9,8 @@ import {matchRoutes, type RouteConfig} from 'react-router-config'; /** * Helper function to make sure all async components for that particular route - * is preloaded before rendering. This is especially useful to avoid loading screens. + * is preloaded before rendering. This is especially useful to avoid loading + * screens. * * @param routes react-router-config * @param pathname the route pathname, example: /docs/installation diff --git a/packages/docusaurus/src/client/serverEntry.tsx b/packages/docusaurus/src/client/serverEntry.tsx index b6349f49fc..f4c1642bc6 100644 --- a/packages/docusaurus/src/client/serverEntry.tsx +++ b/packages/docusaurus/src/client/serverEntry.tsx @@ -66,7 +66,7 @@ It might also require to wrap your client code in code=${'useEffect'} hook and/o } } -// Renderer for static-site-generator-webpack-plugin (async rendering via promises). +// Renderer for static-site-generator-webpack-plugin (async rendering). async function doRender(locals: Locals & {path: string}) { const { routesLocation, diff --git a/packages/docusaurus/src/client/theme-fallback/Error/index.tsx b/packages/docusaurus/src/client/theme-fallback/Error/index.tsx index 4d6f35a6bc..9adbca8c25 100644 --- a/packages/docusaurus/src/client/theme-fallback/Error/index.tsx +++ b/packages/docusaurus/src/client/theme-fallback/Error/index.tsx @@ -32,11 +32,13 @@ function ErrorDisplay({error, tryAgain}: Props): JSX.Element { } function Error({error, tryAgain}: Props): JSX.Element { - // We wrap the error in its own error boundary because the layout can actually throw too... - // Only the ErrorDisplay component is simple enough to be considered safe to never throw + // We wrap the error in its own error boundary because the layout can actually + // throw too... Only the ErrorDisplay component is simple enough to be + // considered safe to never throw return ( }> diff --git a/packages/docusaurus/src/commands/build.ts b/packages/docusaurus/src/commands/build.ts index 2f7d64c7d7..916515f8b0 100644 --- a/packages/docusaurus/src/commands/build.ts +++ b/packages/docusaurus/src/commands/build.ts @@ -72,25 +72,24 @@ export default async function build( }); if (cliOptions.locale) { return tryToBuildLocale({locale: cliOptions.locale, isLastLocale: true}); - } else { - if (i18n.locales.length > 1) { - logger.info`Website will be built for all these locales: ${i18n.locales}`; - } - - // We need the default locale to always be the 1st in the list - // If we build it last, it would "erase" the localized sites built in sub-folders - const orderedLocales: string[] = [ - i18n.defaultLocale, - ...i18n.locales.filter((locale) => locale !== i18n.defaultLocale), - ]; - - const results = await mapAsyncSequential(orderedLocales, (locale) => { - const isLastLocale = - orderedLocales.indexOf(locale) === orderedLocales.length - 1; - return tryToBuildLocale({locale, isLastLocale}); - }); - return results[0]; } + if (i18n.locales.length > 1) { + logger.info`Website will be built for all these locales: ${i18n.locales}`; + } + + // We need the default locale to always be the 1st in the list. If we build it + // last, it would "erase" the localized sites built in sub-folders + const orderedLocales: string[] = [ + i18n.defaultLocale, + ...i18n.locales.filter((locale) => locale !== i18n.defaultLocale), + ]; + + const results = await mapAsyncSequential(orderedLocales, (locale) => { + const isLastLocale = + orderedLocales.indexOf(locale) === orderedLocales.length - 1; + return tryToBuildLocale({locale, isLastLocale}); + }); + return results[0]; } async function buildLocale({ @@ -136,7 +135,8 @@ async function buildLocale({ plugins: [ // Remove/clean build folders before building bundles. new CleanWebpackPlugin({verbose: false}), - // Visualize size of webpack output files with an interactive zoomable tree map. + // Visualize size of webpack output files with an interactive zoomable + // tree map. cliOptions.bundleAnalyzer && new BundleAnalyzerPlugin(), // Generate client manifests file that will be used for server bundle. new ReactLoadableSSRAddon({ @@ -220,7 +220,6 @@ async function buildLocale({ if (!plugin.postBuild) { return; } - // The plugin may reference `this`. We manually bind it again to prevent any bugs. await plugin.postBuild({...props, content: plugin.content}); }), ); diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 7916961bd8..43c42f7aa8 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -148,8 +148,8 @@ This behavior can have SEO impacts and create relative link issues. shell.exit(0); } - // github.io indicates organization repos that deploy via default branch. All others use gh-pages. - // Organization deploys looks like: + // github.io indicates organization repos that deploy via default branch. + // All others use gh-pages. Organization deploys looks like: // - Git repo: https://github.com//.github.io // - Site url: https://.github.io const isGitHubPagesOrganizationDeploy = projectName.includes('.github.io'); @@ -269,7 +269,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); }; if (!cliOptions.skipBuild) { - // Build static html files, then push to deploymentBranch branch of specified repo. + // Build site, then push to deploymentBranch branch of specified repo. try { await runDeploy(await build(siteDir, cliOptions, false)); } catch (buildError) { diff --git a/packages/docusaurus/src/commands/serve.ts b/packages/docusaurus/src/commands/serve.ts index bf578a2908..42c1c27f43 100644 --- a/packages/docusaurus/src/commands/serve.ts +++ b/packages/docusaurus/src/commands/serve.ts @@ -59,8 +59,8 @@ export default async function serve( return; } - // Remove baseUrl before calling serveHandler - // Reason: /baseUrl/ should serve /build/index.html, not /build/baseUrl/index.html (does not exist) + // Remove baseUrl before calling serveHandler, because /baseUrl/ should + // serve /build/index.html, not /build/baseUrl/index.html (does not exist) req.url = req.url?.replace(baseUrl, '/'); serveHandler(req, res, { diff --git a/packages/docusaurus/src/commands/swizzle.ts b/packages/docusaurus/src/commands/swizzle.ts index b76979d3ff..b6f96133d5 100644 --- a/packages/docusaurus/src/commands/swizzle.ts +++ b/packages/docusaurus/src/commands/swizzle.ts @@ -240,7 +240,8 @@ export default async function swizzle( let score = formattedComponentName.length; components.forEach((component) => { if (component.toLowerCase() === formattedComponentName.toLowerCase()) { - // may be components with same lowercase key, try to match closest component + // may be components with same lowercase key, try to match closest + // component const currentScore = leven(formattedComponentName, component); if (currentScore < score) { score = currentScore; @@ -259,7 +260,8 @@ export default async function swizzle( let fromPath = path.join(themePath, mostSuitableComponent); let toPath = path.resolve(siteDir, THEME_PATH, mostSuitableComponent); // Handle single TypeScript/JavaScript file only. - // E.g: if does not exist, we try to swizzle .(ts|tsx|js) instead + // E.g: if does not exist, we try to swizzle + // .(ts|tsx|js) instead if (!fs.existsSync(fromPath)) { if (fs.existsSync(`${fromPath}.ts`)) { [fromPath, toPath] = [`${fromPath}.ts`, `${toPath}.ts`]; diff --git a/packages/docusaurus/src/commands/writeHeadingIds.ts b/packages/docusaurus/src/commands/writeHeadingIds.ts index 55d8b12d12..1a0978a740 100644 --- a/packages/docusaurus/src/commands/writeHeadingIds.ts +++ b/packages/docusaurus/src/commands/writeHeadingIds.ts @@ -73,9 +73,8 @@ function transformMarkdownLine( // Ignore h1 headings on purpose, as we don't create anchor links for those if (line.startsWith('##')) { return transformMarkdownHeadingLine(line, slugger, options); - } else { - return line; } + return line; } function transformMarkdownLines(lines: string[], options?: Options): string[] { @@ -86,12 +85,11 @@ function transformMarkdownLines(lines: string[], options?: Options): string[] { if (line.startsWith('```')) { inCode = !inCode; return line; - } else { - if (inCode) { - return line; - } - return transformMarkdownLine(line, slugger, options); } + if (inCode) { + return line; + } + return transformMarkdownLine(line, slugger, options); }); } @@ -118,9 +116,12 @@ async function transformMarkdownFile( return undefined; } -// We only handle the "paths to watch" because these are the paths where the markdown files are -// Also we don't want to transform the site md docs that do not belong to a content plugin -// For example ./README.md should not be transformed +/** + * We only handle the "paths to watch" because these are the paths where the + * markdown files are. Also we don't want to transform the site md docs that do + * not belong to a content plugin. For example ./README.md should not be + * transformed + */ async function getPathsToWatch(siteDir: string): Promise { const context = await loadContext(siteDir); const pluginConfigs = loadPluginConfigs(context); diff --git a/packages/docusaurus/src/commands/writeTranslations.ts b/packages/docusaurus/src/commands/writeTranslations.ts index bae83028e5..b13eeb273b 100644 --- a/packages/docusaurus/src/commands/writeTranslations.ts +++ b/packages/docusaurus/src/commands/writeTranslations.ts @@ -23,10 +23,13 @@ import { } from '../server/translations/translationsExtractor'; import {getCustomBabelConfigFilePath, getBabelOptions} from '../webpack/utils'; -// This is a hack, so that @docusaurus/theme-common translations are extracted! -// A theme doesn't have a way to express that one of its dependency (like @docusaurus/theme-common) also has translations to extract -// Instead of introducing a new lifecycle (like plugin.getThemeTranslationPaths() ?) -// We just make an exception and assume that Docusaurus user is using an official theme +/** + * This is a hack, so that @docusaurus/theme-common translations are extracted! + * A theme doesn't have a way to express that one of its dependency (like + * @docusaurus/theme-common) also has translations to extract. + * Instead of introducing a new lifecycle (like `getThemeTranslationPaths()`?) + * We just make an exception and assume that user is using an official theme + */ async function getExtraSourceCodeFilePaths(): Promise { try { const themeCommonSourceDir = path.dirname( diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index f9dedbab8a..24a483de30 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -168,10 +168,13 @@ describe('normalizeConfig', () => { ['this/should/work', {too: 'yes'}], ], ], - ['should accept function for plugin', [function (_context, _options) {}]], + [ + 'should accept function for plugin', + [function plugin(_context, _options) {}], + ], [ 'should accept [function, object] for plugin', - [[function (_context, _options) {}, {it: 'should work'}]], + [[(_context, _options) => {}, {it: 'should work'}]], ], ])(`%s for the input of: %p`, (_message, plugins) => { expect(() => { @@ -206,10 +209,13 @@ describe('normalizeConfig', () => { ['this/should/work', {too: 'yes'}], ], ], - ['should accept function for theme', [function (_context, _options) {}]], + [ + 'should accept function for theme', + [function theme(_context, _options) {}], + ], [ 'should accept [function, object] for theme', - [[function (_context, _options) {}, {it: 'should work'}]], + [[function theme(_context, _options) {}, {it: 'should work'}]], ], ])(`%s for the input of: %p`, (_message, themes) => { expect(() => { diff --git a/packages/docusaurus/src/server/brokenLinks.ts b/packages/docusaurus/src/server/brokenLinks.ts index 1e3ca6dc4d..907b4762a2 100644 --- a/packages/docusaurus/src/server/brokenLinks.ts +++ b/packages/docusaurus/src/server/brokenLinks.ts @@ -64,10 +64,12 @@ function getPageBrokenLinks({ return pageLinks.map(resolveLink).filter((l) => isBrokenLink(l.resolvedLink)); } -// The route defs can be recursive, and have a parent match-all route -// We don't want to match broken links like /docs/brokenLink against /docs/* -// For this reason, we only consider the "final routes", that do not have subroutes -// We also need to remove the match all 404 route +/** + * The route defs can be recursive, and have a parent match-all route. We don't + * want to match broken links like /docs/brokenLink against /docs/*. For this + * reason, we only consider the "final routes", that do not have subroutes. + * We also need to remove the match all 404 route + */ function filterIntermediateRoutes(routesInput: RouteConfig[]): RouteConfig[] { const routesWithout404 = routesInput.filter((route) => route.path !== '*'); return getAllFinalRoutes(routesWithout404); @@ -113,9 +115,11 @@ export function getBrokenLinksErrorMessage( .join('\n -> linking to ')}`; } - // If there's a broken link appearing very often, it is probably a broken link on the layout! - // Add an additional message in such case to help user figure this out. - // see https://github.com/facebook/docusaurus/issues/3567#issuecomment-706973805 + /** + * If there's a broken link appearing very often, it is probably a broken link + * on the layout. Add an additional message in such case to help user figure + * this out. See https://github.com/facebook/docusaurus/issues/3567#issuecomment-706973805 + */ function getLayoutBrokenLinksHelpMessage() { const flatList = Object.entries(allBrokenLinks).flatMap( ([pagePage, brokenLinks]) => @@ -215,8 +219,9 @@ export async function handleBrokenLinks({ return; } - // If we link to a file like /myFile.zip, and the file actually exist for the file system - // it is not a broken link, it may simply be a link to an existing static file... + // If we link to a file like /myFile.zip, and the file actually exist for the + // file system. It is not a broken link, it may simply be a link to an + // existing static file... const allCollectedLinksFiltered = await filterExistingFileLinks({ allCollectedLinks, baseUrl, diff --git a/packages/docusaurus/src/server/duplicateRoutes.ts b/packages/docusaurus/src/server/duplicateRoutes.ts index 42ae393066..25916d6291 100644 --- a/packages/docusaurus/src/server/duplicateRoutes.ts +++ b/packages/docusaurus/src/server/duplicateRoutes.ts @@ -19,10 +19,9 @@ export function getAllDuplicateRoutes( return allRoutes.filter((route) => { if (Object.prototype.hasOwnProperty.call(seenRoutes, route)) { return true; - } else { - seenRoutes[route] = true; - return false; } + seenRoutes[route] = true; + return false; }); } diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index 6a847d6e9b..1885b3f47f 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -91,20 +91,17 @@ export function localizePath({ i18n.currentLocale !== i18n.defaultLocale : options.localizePath; - if (shouldLocalizePath) { - // FS paths need special care, for Windows support - if (pathType === 'fs') { - return path.join(originalPath, path.sep, i18n.currentLocale, path.sep); - } - // Url paths - else if (pathType === 'url') { - return normalizeUrl([originalPath, '/', i18n.currentLocale, '/']); - } - // should never happen - else { - throw new Error(`Unhandled path type "${pathType}".`); - } - } else { + if (!shouldLocalizePath) { return originalPath; } + // FS paths need special care, for Windows support + if (pathType === 'fs') { + return path.join(originalPath, path.sep, i18n.currentLocale, path.sep); + } + // Url paths + if (pathType === 'url') { + return normalizeUrl([originalPath, '/', i18n.currentLocale, '/']); + } + // should never happen + throw new Error(`Unhandled path type "${pathType}".`); } diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index cdf1045672..aa8f18b97d 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -221,10 +221,12 @@ function createBootstrapPlugin({ }; } -// Configure Webpack fallback mdx loader for md/mdx files out of content-plugin folders -// Adds a "fallback" mdx loader for mdx files that are not processed by content plugins -// This allows to do things such as importing repo/README.md as a partial from another doc -// Not ideal solution though, but good enough for now +/** + * Configure Webpack fallback mdx loader for md/mdx files out of content-plugin + * folders. Adds a "fallback" mdx loader for mdx files that are not processed by + * content plugins. This allows to do things such as importing repo/README.md as + * a partial from another doc. Not ideal solution, but good enough for now + */ function createMDXFallbackPlugin({ siteDir, siteConfig, @@ -238,9 +240,9 @@ function createMDXFallbackPlugin({ options: {}, version: {type: 'synthetic'}, configureWebpack(config, isServer, {getJSLoader}) { - // We need the mdx fallback loader to exclude files that were already processed by content plugins mdx loaders - // This works, but a bit hacky... - // Not sure there's a way to handle that differently in webpack :s + // We need the mdx fallback loader to exclude files that were already + // processed by content plugins mdx loaders. This works, but a bit + // hacky... Not sure there's a way to handle that differently in webpack function getMDXFallbackExcludedPaths(): string[] { const rules: RuleSetRule[] = config?.module?.rules as RuleSetRule[]; return rules.flatMap((rule) => { diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index e3f85404af..fc3f354b11 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -84,9 +84,9 @@ export async function loadPlugins({ }); // 2. Plugin Lifecycle - loadContent. - // Currently plugins run lifecycle methods in parallel and are not order-dependent. - // We could change this in future if there are plugins which need to - // run in certain order or depend on others for data. + // Currently plugins run lifecycle methods in parallel and are not + // order-dependent. We could change this in future if there are plugins which + // need to run in certain order or depend on others for data. const loadedPlugins: LoadedPlugin[] = await Promise.all( plugins.map(async (plugin) => { const content = plugin.loadContent ? await plugin.loadContent() : null; @@ -199,9 +199,9 @@ export async function loadPlugins({ ); // 4. Plugin Lifecycle - routesLoaded. - // Currently plugins run lifecycle methods in parallel and are not order-dependent. - // We could change this in future if there are plugins which need to - // run in certain order or depend on others for data. + // Currently plugins run lifecycle methods in parallel and are not + // order-dependent. We could change this in future if there are plugins which + // need to run in certain order or depend on others for data. await Promise.all( contentLoadedTranslatedPlugins.map(async (plugin) => { if (!plugin.routesLoaded) { diff --git a/packages/docusaurus/src/server/plugins/init.ts b/packages/docusaurus/src/server/plugins/init.ts index 8f5ee1a41c..a1de61e82b 100644 --- a/packages/docusaurus/src/server/plugins/init.ts +++ b/packages/docusaurus/src/server/plugins/init.ts @@ -105,9 +105,8 @@ function getOptionValidationFunction( normalizedPluginConfig.pluginModule.module?.default?.validateOptions ?? normalizedPluginConfig.pluginModule.module?.validateOptions ); - } else { - return normalizedPluginConfig.plugin.validateOptions; } + return normalizedPluginConfig.plugin.validateOptions; } function getThemeValidationFunction( @@ -119,9 +118,8 @@ function getThemeValidationFunction( normalizedPluginConfig.pluginModule.module.default?.validateThemeConfig ?? normalizedPluginConfig.pluginModule.module.validateThemeConfig ); - } else { - return normalizedPluginConfig.plugin.validateThemeConfig; } + return normalizedPluginConfig.plugin.validateThemeConfig; } export default async function initPlugins({ @@ -131,8 +129,8 @@ export default async function initPlugins({ pluginConfigs: PluginConfig[]; context: LoadContext; }): Promise { - // We need to resolve plugins from the perspective of the siteDir, since the siteDir's package.json - // declares the dependency on these plugins. + // We need to resolve plugins from the perspective of the siteDir, since the + // siteDir's package.json declares the dependency on these plugins. const pluginRequire = createRequire(context.siteConfigPath); function doGetPluginVersion( @@ -144,9 +142,8 @@ export default async function initPlugins({ normalizedPluginConfig.pluginModule?.path, ); return getPluginVersion(pluginPath, context.siteDir); - } else { - return {type: 'local'}; } + return {type: 'local'}; } function doValidateThemeConfig( @@ -160,9 +157,8 @@ export default async function initPlugins({ validate: normalizeThemeConfig, themeConfig: context.siteConfig.themeConfig, }); - } else { - return context.siteConfig.themeConfig; } + return context.siteConfig.themeConfig; } function doValidatePluginOptions( @@ -174,14 +170,13 @@ export default async function initPlugins({ validate: normalizePluginOptions, options: normalizedPluginConfig.options, }); - } else { - // Important to ensure all plugins have an id - // as we don't go through the Joi schema that adds it - return { - ...normalizedPluginConfig.options, - id: normalizedPluginConfig.options.id ?? DEFAULT_PLUGIN_ID, - }; } + // Important to ensure all plugins have an id + // as we don't go through the Joi schema that adds it + return { + ...normalizedPluginConfig.options, + id: normalizedPluginConfig.options.id ?? DEFAULT_PLUGIN_ID, + }; } async function initializePlugin( diff --git a/packages/docusaurus/src/server/presets/index.ts b/packages/docusaurus/src/server/presets/index.ts index 01263685a0..f04917968c 100644 --- a/packages/docusaurus/src/server/presets/index.ts +++ b/packages/docusaurus/src/server/presets/index.ts @@ -19,8 +19,8 @@ export default function loadPresets(context: LoadContext): { plugins: PluginConfig[]; themes: PluginConfig[]; } { - // We need to resolve presets from the perspective of the siteDir, since the siteDir's package.json - // declares the dependency on these presets. + // We need to resolve presets from the perspective of the siteDir, since the + // siteDir's package.json declares the dependency on these presets. const presetRequire = createRequire(context.siteConfigPath); const presets: PresetConfig[] = context.siteConfig.presets || []; @@ -28,7 +28,7 @@ export default function loadPresets(context: LoadContext): { const unflatThemes: PluginConfig[][] = []; presets.forEach((presetItem) => { - let presetModuleImport; + let presetModuleImport: string; let presetOptions = {}; if (typeof presetItem === 'string') { presetModuleImport = presetItem; diff --git a/packages/docusaurus/src/server/routes.ts b/packages/docusaurus/src/server/routes.ts index 03dde9e974..f18c6c1128 100644 --- a/packages/docusaurus/src/server/routes.ts +++ b/packages/docusaurus/src/server/routes.ts @@ -147,7 +147,8 @@ export default async function loadRoutes( // Collect all page paths for injecting it later in the plugin lifecycle // This is useful for plugins like sitemaps, redirects etc... - // If a route has subroutes, it is not necessarily a valid page path (more likely to be a wrapper) + // If a route has subroutes, it is not necessarily a valid page path (more + // likely to be a wrapper) if (!subroutes) { routesPaths.push(routePath); } diff --git a/packages/docusaurus/src/server/themes/index.ts b/packages/docusaurus/src/server/themes/index.ts index 387e3792cc..cb973e0e2a 100644 --- a/packages/docusaurus/src/server/themes/index.ts +++ b/packages/docusaurus/src/server/themes/index.ts @@ -21,8 +21,9 @@ export function loadThemeAliases( themePaths.forEach((themePath) => { const themeAliases = themeAlias(themePath, true); Object.keys(themeAliases).forEach((aliasKey) => { - // If this alias shadows a previous one, use @theme-init to preserve the initial one. - // @theme-init is only applied once: to the initial theme that provided this component + // If this alias shadows a previous one, use @theme-init to preserve the + // initial one. @theme-init is only applied once: to the initial theme + // that provided this component if (aliasKey in aliases) { const componentName = aliasKey.substring(aliasKey.indexOf('/') + 1); const initAlias = `@theme-init/${componentName}`; diff --git a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts index acb1be2fe8..916b4bb5e2 100644 --- a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts +++ b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts @@ -459,8 +459,9 @@ describe('localizePluginTranslationFile', () => { expect(localizedTranslationFile).toEqual({ path: translationFile.path, content: { - // We only append/override localized messages, but never delete the data of the unlocalized translation file - // This ensures that all required keys are present when trying to read the translations files + // We only append/override localized messages, but never delete the data + // of the unlocalized translation file. This ensures that all required + // keys are present when trying to read the translations files key1: {message: 'key1 message'}, key2: {message: 'key2 message localized'}, key3: {message: 'key3 message'}, diff --git a/packages/docusaurus/src/server/translations/translations.ts b/packages/docusaurus/src/server/translations/translations.ts index f06c55cb6e..66f5179a89 100644 --- a/packages/docusaurus/src/server/translations/translations.ts +++ b/packages/docusaurus/src/server/translations/translations.ts @@ -86,7 +86,7 @@ function mergeTranslationFileContent({ Object.entries(newContentTransformed).forEach( ([key, {message, description}]) => { result[key] = { - // If the messages already exist, we don't override them (unless requested) + // If messages already exist, we don't override them (unless requested) message: options.override ? message : existingContent[key]?.message ?? message, @@ -252,9 +252,8 @@ export async function localizePluginTranslationFile({ ...localizedContent, }, }; - } else { - return translationFile; } + return translationFile; } export async function getPluginsDefaultCodeTranslationMessages( diff --git a/packages/docusaurus/src/server/translations/translationsExtractor.ts b/packages/docusaurus/src/server/translations/translationsExtractor.ts index ec808f79b9..6b7f7403cb 100644 --- a/packages/docusaurus/src/server/translations/translationsExtractor.ts +++ b/packages/docusaurus/src/server/translations/translationsExtractor.ts @@ -45,8 +45,9 @@ function getSiteSourceCodeFilePaths(siteDir: string): string[] { function getPluginSourceCodeFilePaths(plugin: InitializedPlugin): string[] { // The getPathsToWatch() generally returns the js/jsx/ts/tsx/md/mdx file paths - // We can use this method as well to know which folders we should try to extract translations from - // Hacky/implicit, but do we want to introduce a new lifecycle method just for that??? + // We can use this method as well to know which folders we should try to + // extract translations from. Hacky/implicit, but do we want to introduce a + // new lifecycle method just for that??? const codePaths: string[] = plugin.getPathsToWatch?.() ?? []; // We also include theme code @@ -72,8 +73,9 @@ async function getSourceCodeFilePaths( const sitePaths = getSiteSourceCodeFilePaths(siteDir); // The getPathsToWatch() generally returns the js/jsx/ts/tsx/md/mdx file paths - // We can use this method as well to know which folders we should try to extract translations from - // Hacky/implicit, but do we want to introduce a new lifecycle method for that??? + // We can use this method as well to know which folders we should try to + // extract translations from. Hacky/implicit, but do we want to introduce a + // new lifecycle method for that??? const pluginsPaths = plugins.flatMap(getPluginSourceCodeFilePaths); const allPaths = [...sitePaths, ...pluginsPaths]; @@ -87,7 +89,8 @@ export async function extractSiteSourceCodeTranslations( babelOptions: TransformOptions, extraSourceCodeFilePaths: string[] = [], ): Promise { - // Should we warn here if the same translation "key" is found in multiple source code files? + // Should we warn here if the same translation "key" is found in multiple + // source code files? function toTranslationFileContent( sourceCodeFileTranslations: SourceCodeFileTranslations[], ): TranslationFileContent { @@ -152,8 +155,9 @@ export async function extractSourceCodeFileTranslations( const ast = parse(code, { ...babelOptions, ast: true, - // filename is important, because babel does not process the same files according to their js/ts extensions - // see see https://twitter.com/NicoloRibaudo/status/1321130735605002243 + // filename is important, because babel does not process the same files + // according to their js/ts extensions. + // See https://twitter.com/NicoloRibaudo/status/1321130735605002243 filename: sourceCodeFilePath, }) as Node; @@ -260,14 +264,13 @@ Full code: ${generate(node).code}`; typeof attributeValueEvaluated.value === 'string' ) { return attributeValueEvaluated.value; - } else { - warnings.push( - ` prop=${propName} should be a statically evaluable object. + } + warnings.push( + ` prop=${propName} should be a statically evaluable object. Example: Message Dynamically constructed values are not allowed, because they prevent translations to be extracted. ${sourceWarningPart(path.node)}`, - ); - } + ); } return undefined; @@ -275,7 +278,7 @@ ${sourceWarningPart(path.node)}`, const id = evaluateJSXProp('id'); const description = evaluateJSXProp('description'); - let message; + let message: string; const childrenPath = path.get('children'); // Handle empty content @@ -286,7 +289,7 @@ Example: ${sourceWarningPart(path.node)}`); } else { translations[id] = { - message: message ?? id, + message: id, ...(description && {description}), }; } @@ -296,8 +299,9 @@ ${sourceWarningPart(path.node)}`); // Handle single non-empty content const singleChildren = childrenPath - // Remove empty/useless text nodes that might be around our translation! - // Makes the translation system more reliable to JSX formatting issues + // Remove empty/useless text nodes that might be around our + // translation! Makes the translation system more reliable to JSX + // formatting issues .filter( (children) => !( @@ -340,7 +344,7 @@ ${sourceWarningPart(path.node)}`, if (args.length === 1 || args.length === 2) { const firstArgPath = args[0]; - // evaluation allows translate("x" + "y"); to be considered as translate("xy"); + // translate("x" + "y"); => translate("xy"); const firstArgEvaluated = firstArgPath.evaluate(); if ( diff --git a/packages/docusaurus/src/server/versions/index.ts b/packages/docusaurus/src/server/versions/index.ts index bf499d569c..3df9f84923 100644 --- a/packages/docusaurus/src/server/versions/index.ts +++ b/packages/docusaurus/src/server/versions/index.ts @@ -43,7 +43,8 @@ export function getPluginVersion( ); if (existsSync(packageJsonPath) && lstatSync(packageJsonPath).isFile()) { if (potentialPluginPackageJsonDirectory === siteDir) { - // If the plugin belongs to the same docusaurus project, we classify it as local plugin. + // If the plugin belongs to the same docusaurus project, we classify it + // as local plugin. return {type: 'project'}; } return { @@ -56,6 +57,7 @@ export function getPluginVersion( potentialPluginPackageJsonDirectory, ); } - // In rare cases where a plugin is a path where no parent directory contains package.json, we can only classify it as local. + // In the case where a plugin is a path where no parent directory contains + // package.json (e.g. inline plugin), we can only classify it as local. return {type: 'local'}; } diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index 79fd9237d3..11db878c16 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -104,16 +104,19 @@ export function createBaseConfig( // When version string changes, cache is evicted version: [ siteMetadata.docusaurusVersion, - // Webpack does not evict the cache correctly on alias/swizzle change, so we force eviction. + // Webpack does not evict the cache correctly on alias/swizzle change, + // so we force eviction. // See https://github.com/webpack/webpack/issues/13627 md5Hash(JSON.stringify(themeAliases)), ].join('-'), - // When one of those modules/dependencies change (including transitive deps), cache is invalidated + // When one of those modules/dependencies change (including transitive + // deps), cache is invalidated buildDependencies: { config: [ __filename, path.join(__dirname, isServer ? 'server.js' : 'client.js'), - // Docusaurus config changes can affect MDX/JSX compilation, so we'd rather evict the cache. + // Docusaurus config changes can affect MDX/JSX compilation, so we'd + // rather evict the cache. // See https://github.com/questdb/questdb.io/issues/493 siteConfigPath, ], @@ -158,10 +161,11 @@ export function createBaseConfig( ...getDocusaurusAliases(), ...themeAliases, }, - // This allows you to set a fallback for where Webpack should look for modules. - // We want `@docusaurus/core` own dependencies/`node_modules` to "win" if there is conflict - // Example: if there is core-js@3 in user's own node_modules, but core depends on - // core-js@2, we should use core-js@2. + // This allows you to set a fallback for where Webpack should look for + // modules. We want `@docusaurus/core` own dependencies/`node_modules` to + // "win" if there is conflict. Example: if there is core-js@3 in user's + // own node_modules, but core depends on core-js@2, we should use + // core-js@2. modules: [ path.resolve(__dirname, '..', '..', 'node_modules'), 'node_modules', @@ -173,7 +177,8 @@ export function createBaseConfig( }, optimization: { removeAvailableModules: false, - // Only minimize client bundle in production because server bundle is only used for static site generation + // Only minimize client bundle in production because server bundle is only + // used for static site generation minimize: minimizeEnabled, minimizer: minimizeEnabled ? getMinimizer(useSimpleCssMinifier) @@ -181,7 +186,9 @@ export function createBaseConfig( splitChunks: isServer ? false : { - // Since the chunk name includes all origin chunk names it's recommended for production builds with long term caching to NOT include [name] in the filenames + // Since the chunk name includes all origin chunk names it's + // recommended for production builds with long term caching to NOT + // include [name] in the filenames name: false, cacheGroups: { // disable the built-in cacheGroups @@ -255,8 +262,9 @@ export function createBaseConfig( chunkFilename: isProd ? 'assets/css/[name].[contenthash:8].css' : '[name].css', - // remove css order warnings if css imports are not sorted alphabetically - // see https://github.com/webpack-contrib/mini-css-extract-plugin/pull/422 for more reasoning + // remove css order warnings if css imports are not sorted + // alphabetically. See https://github.com/webpack-contrib/mini-css-extract-plugin/pull/422 + // for more reasoning ignoreOrder: true, }), ], diff --git a/packages/docusaurus/src/webpack/client.ts b/packages/docusaurus/src/webpack/client.ts index a22ecbdfb4..0942e0c078 100644 --- a/packages/docusaurus/src/webpack/client.ts +++ b/packages/docusaurus/src/webpack/client.ts @@ -23,7 +23,9 @@ export default function createClientConfig( const config = createBaseConfig(props, false, minify); const clientConfig = merge(config, { - // target: 'browserslist', // useless, disabled on purpose (errors on existing sites with no browserslist cfg) + // useless, disabled on purpose (errors on existing sites with no + // browserslist config) + // target: 'browserslist', entry: path.resolve(__dirname, '../client/clientEntry.js'), optimization: { // Keep the runtime chunk separated to enable long term caching @@ -39,7 +41,8 @@ export default function createClientConfig( ], }); - // When building include the plugin to force terminate building if errors happened in the client bundle. + // When building, include the plugin to force terminate building if errors + // happened in the client bundle. if (isBuilding) { clientConfig.plugins?.push({ apply: (compiler) => { diff --git a/packages/docusaurus/src/webpack/plugins/ChunkAssetPlugin.ts b/packages/docusaurus/src/webpack/plugins/ChunkAssetPlugin.ts index 6db248532b..6f364b8560 100644 --- a/packages/docusaurus/src/webpack/plugins/ChunkAssetPlugin.ts +++ b/packages/docusaurus/src/webpack/plugins/ChunkAssetPlugin.ts @@ -9,16 +9,20 @@ import {Template, type Compiler} from 'webpack'; const pluginName = 'chunk-asset-plugin'; +/** + * We modify webpack runtime to add an extra function called + * "__webpack_require__.gca" that will allow us to get the corresponding chunk + * asset for a webpack chunk. Pass it the chunkName or chunkId you want to load. + * For example: if you have a chunk named "my-chunk-name" that will map to + * "/publicPath/0a84b5e7.c8e35c7a.js" as its corresponding output path + * __webpack_require__.gca("my-chunk-name") will return + * "/publicPath/0a84b5e7.c8e35c7a.js" + * + * "gca" stands for "get chunk asset" + */ class ChunkAssetPlugin { apply(compiler: Compiler): void { compiler.hooks.thisCompilation.tap(pluginName, ({mainTemplate}) => { - /* We modify webpack runtime to add an extra function called "__webpack_require__.gca" - that will allow us to get the corresponding chunk asset for a webpack chunk. - Pass it the chunkName or chunkId you want to load. - For example: if you have a chunk named "my-chunk-name" that will map to "/publicPath/0a84b5e7.c8e35c7a.js" as its corresponding output path - __webpack_require__.gca("my-chunk-name") will return "/publicPath/0a84b5e7.c8e35c7a.js" - "gca" stands for "get chunk asset" - */ mainTemplate.hooks.requireExtensions.tap(pluginName, (source, chunk) => { const chunkIdToName = chunk.getChunkMaps(false).name; const chunkNameToId = Object.create(null); @@ -31,10 +35,13 @@ class ChunkAssetPlugin { buf.push( // If chunkName is passed, we convert it to chunk asset url // .p => public path url ("/" or "/baseUrl/") - // .u(chunkId) => chunk asset url ("assets/js/x63b64xd.contentHash.js") - // not sure where this is documented, but this link was helpful: https://programmer.help/blogs/5d68849083e1a.html + // .u(chunkId) => + // chunk asset url ("assets/js/x63b64xd.contentHash.js") + // not sure where this is documented, but this link was helpful: + // https://programmer.help/blogs/5d68849083e1a.html // - // Note: __webpack_require__.gca() is called in docusaurus.ts for prefetching + // Note: __webpack_require__.gca() is called in docusaurus.ts for + // prefetching // Note: we previously used jsonpScriptSrc (Webpack 4) `__webpack_require__.gca = function(chunkId) { chunkId = ${JSON.stringify( chunkNameToId, diff --git a/packages/docusaurus/src/webpack/plugins/CleanWebpackPlugin.ts b/packages/docusaurus/src/webpack/plugins/CleanWebpackPlugin.ts index 1818d843ef..9e61761971 100644 --- a/packages/docusaurus/src/webpack/plugins/CleanWebpackPlugin.ts +++ b/packages/docusaurus/src/webpack/plugins/CleanWebpackPlugin.ts @@ -14,8 +14,8 @@ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -144,7 +144,8 @@ class CleanWebpackPlugin { * * Only happens once. * - * Warning: It is recommended to initially clean your build directory outside of webpack to minimize unexpected behavior. + * Warning: It is recommended to initially clean your build directory outside + * of webpack to minimize unexpected behavior. */ handleInitial(): void { if (this.initialClean) { diff --git a/packages/docusaurus/src/webpack/server.ts b/packages/docusaurus/src/webpack/server.ts index 56b8b43ff2..85aa0a6722 100644 --- a/packages/docusaurus/src/webpack/server.ts +++ b/packages/docusaurus/src/webpack/server.ts @@ -79,9 +79,10 @@ export default function createServerConfig({ paths: ssgPaths, preferFoldersOutput: trailingSlash, - // When using "new URL('file.js', import.meta.url)", Webpack will emit __filename, and this plugin will throw - // not sure the __filename value has any importance for this plugin, just using an empty string to avoid the error - // See https://github.com/facebook/docusaurus/issues/4922 + // When using "new URL('file.js', import.meta.url)", Webpack will emit + // __filename, and this plugin will throw. not sure the __filename value + // has any importance for this plugin, just using an empty string to + // avoid the error. See https://github.com/facebook/docusaurus/issues/4922 globals: {__filename: ''}, }), diff --git a/packages/docusaurus/src/webpack/utils.ts b/packages/docusaurus/src/webpack/utils.ts index 91f6327b02..acc265eb35 100644 --- a/packages/docusaurus/src/webpack/utils.ts +++ b/packages/docusaurus/src/webpack/utils.ts @@ -126,16 +126,13 @@ export function getBabelOptions({ configFile: babelOptions, caller: {name: isServer ? 'server' : 'client'}, }; - } else { - return Object.assign( - babelOptions ?? {presets: [require.resolve('../babel/preset')]}, - { - babelrc: false, - configFile: false, - caller: {name: isServer ? 'server' : 'client'}, - }, - ); } + return { + ...(babelOptions ?? {presets: [require.resolve('../babel/preset')]}), + babelrc: false, + configFile: false, + caller: {name: isServer ? 'server' : 'client'}, + }; } // Name is generic on purpose @@ -405,8 +402,8 @@ export function getMinimizer( output: { ecma: 5, comments: false, - // Turned on because emoji and regex is not minified properly using default - // https://github.com/facebook/create-react-app/issues/2488 + // Turned on because emoji and regex is not minified properly using + // default. See https://github.com/facebook/create-react-app/issues/2488 ascii_only: true, }, }, diff --git a/packages/stylelint-copyright/__tests__/index.test.js b/packages/stylelint-copyright/__tests__/index.test.js index 4ba7008506..18c02f7039 100644 --- a/packages/stylelint-copyright/__tests__/index.test.js +++ b/packages/stylelint-copyright/__tests__/index.test.js @@ -13,6 +13,7 @@ const rule = require('..'); const {ruleName, messages} = rule; function getOutputCss(output) { + // eslint-disable-next-line no-underscore-dangle const result = output.results[0]._postcssResult; return result.root.toString(result.opts.syntax); } diff --git a/website/delayCrowdin.mjs b/website/delayCrowdin.mjs index 31063fc49f..d212e0e7c9 100644 --- a/website/delayCrowdin.mjs +++ b/website/delayCrowdin.mjs @@ -8,8 +8,8 @@ /* We delay a bit the i18n staging deployment Because sometimes, prod + i18n-staging call this script at the exact same time -And then both try to dl the translations at the same time, and then we have a 409 error -This delay makes sure prod starts to dl the translations in priority +And then both try to dl the translations at the same time, and then we have a +409 error. This delay makes sure prod starts to dl the translations in priority Used in conjunction with waitForCrowdin.js (which is not enough) */ diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 7fc0bad551..f4642c8dee 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -500,7 +500,8 @@ const config = { }, { title: 'Legal', - // Please do not remove the privacy and terms, it's a legal requirement. + // Please don't remove the privacy and terms, it's a legal + // requirement. items: [ { label: 'Privacy', diff --git a/website/src/components/ColorGenerator/index.tsx b/website/src/components/ColorGenerator/index.tsx index b2edfb1d44..2514b45f14 100644 --- a/website/src/components/ColorGenerator/index.tsx +++ b/website/src/components/ColorGenerator/index.tsx @@ -123,7 +123,8 @@ function ColorGenerator(): JSX.Element { diff --git a/website/src/data/__tests__/user.test.ts b/website/src/data/__tests__/user.test.ts index 170985edcf..f6e80becea 100644 --- a/website/src/data/__tests__/user.test.ts +++ b/website/src/data/__tests__/user.test.ts @@ -25,7 +25,8 @@ declare global { expect.extend({ toHaveGoodDimensions({width, height}: {width: number; height: number}) { - // Put this one first because aspect ratio is harder to fix than resizing (need to take another screenshot) + // Put this one first because aspect ratio is harder to fix than resizing + // (need to take another screenshot) if (width / height < 0.5) { return { pass: false, diff --git a/website/src/data/users.tsx b/website/src/data/users.tsx index f800a34e78..8362d20197 100644 --- a/website/src/data/users.tsx +++ b/website/src/data/users.tsx @@ -13,15 +13,16 @@ import {sortBy} from '@site/src/utils/jsUtils'; * ADD YOUR SITE TO THE DOCUSAURUS SHOWCASE: * * Requirements for adding your site to our showcase: - * - It is a production-ready site with real content and decent customizations (different from the init templates) + * - It is a production-ready site with real content and decent customizations + * (different from the init templates) * - It is NOT a work-in-progress with empty pages - * - It has a stable domain name (a Netlify/Vercel deploy preview is not allowed) + * - It has a stable domain (a Netlify/Vercel deploy preview is not allowed) * * Instructions: * - Add your site in the json array below * - Add a local image preview (decent screenshot of your Docusaurus site) * - Use relevant tags to qualify your site (read the tag descriptions below) - * - The image MUST be added to the GitHub repository, and use `require("image")` + * - The image MUST be added to the GitHub repository, and use `require("img")` * - The image has to have minimum width 640 and an aspect of no wider than 2:1 * - Open a PR and check for reported CI errors * @@ -115,7 +116,7 @@ export const Tags: Record = { color: '#fe6829', }, - // Large Docusaurus sites, with a lot of content (> 200 pages, excluding versions) + // Large sites, with a lot of content (> 200 pages, excluding versions) large: { label: 'Large', description: @@ -1658,7 +1659,7 @@ const Users: User[] = [ preview: require('./showcase/verida-developers.png'), website: 'https://developers.verida.io/', source: 'https://github.com/verida/documentation', - tags: ['opensource', 'product'], + tags: ['opensource', 'product'], }, { title: 'Vue NodeGui', diff --git a/website/src/pages/showcase/index.tsx b/website/src/pages/showcase/index.tsx index dcc74aac53..5ff3e7cc2d 100644 --- a/website/src/pages/showcase/index.tsx +++ b/website/src/pages/showcase/index.tsx @@ -93,9 +93,8 @@ function filterUsers( } if (operator === 'AND') { return selectedTags.every((tag) => user.tags.includes(tag)); - } else { - return selectedTags.some((tag) => user.tags.includes(tag)); } + return selectedTags.some((tag) => user.tags.includes(tag)); }); } @@ -105,7 +104,8 @@ function useFilteredUsers() { // On SSR / first mount (hydration) no tag is selected const [selectedTags, setSelectedTags] = useState([]); const [searchName, setSearchName] = useState(null); - // Sync tags from QS to state (delayed on purpose to avoid SSR/Client hydration mismatch) + // Sync tags from QS to state (delayed on purpose to avoid SSR/Client + // hydration mismatch) useEffect(() => { setSelectedTags(readSearchTags(location.search)); setOperator(readOperator(location.search)); diff --git a/website/src/plugins/changelog/index.js b/website/src/plugins/changelog/index.js index c8e5cfdf2b..9559cc5fae 100644 --- a/website/src/plugins/changelog/index.js +++ b/website/src/plugins/changelog/index.js @@ -17,7 +17,9 @@ const syncAvatars = require('./syncAvatars'); * the reverse. Therefore, our publish time has a "fake hour" to order them. */ const publishTimes = new Set(); -/** @type {Record} */ +/** + * @type {Record} + */ const authorsMap = {}; /** diff --git a/website/src/plugins/changelog/syncAvatars.js b/website/src/plugins/changelog/syncAvatars.js index bbcf3d5e59..dc94ac1c91 100644 --- a/website/src/plugins/changelog/syncAvatars.js +++ b/website/src/plugins/changelog/syncAvatars.js @@ -14,12 +14,14 @@ const fs = require('fs-extra'); // TODO not sure how the syncing should be done at all... for now it always // pretends the limit is reached. We should only fetch a portion of the avatars -// at a time. But seems avatars.githubusercontent.com API doesn't like HTTP requests? +// at a time. But seems avatars.githubusercontent.com API doesn't like HTTP +// requests? /** * @param {string} username * @param {Record} lastUpdateCache * @param {Record} authorsMap - * @returns true if saved successfully (including not found); false if limited reached + * @returns true if saved successfully (including not found); false if limit + * reached */ // eslint-disable-next-line @typescript-eslint/no-unused-vars async function fetchImage(username, lastUpdateCache, authorsMap) { diff --git a/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx b/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx index c5f10ab95a..65a365e006 100644 --- a/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx +++ b/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx @@ -22,7 +22,8 @@ function ChangelogAuthor({author}: Props): JSX.Element { src={imageURL} alt={name} onError={(e) => { - // Image returns 404 if the user's handle changes. We display a fallback instead. + // Image returns 404 if the user's handle changes. We display a + // fallback instead. e.currentTarget.src = 'data:image/svg+xml,'; }} diff --git a/website/src/plugins/changelog/theme/ChangelogPage/index.tsx b/website/src/plugins/changelog/theme/ChangelogPage/index.tsx index aebe4eed29..7abc98c809 100644 --- a/website/src/plugins/changelog/theme/ChangelogPage/index.tsx +++ b/website/src/plugins/changelog/theme/ChangelogPage/index.tsx @@ -16,7 +16,8 @@ import TOC from '@theme/TOC'; import Link from '@docusaurus/Link'; // This page doesn't change anything. It's just swapping BlogPostItem with our -// own ChangelogItem. We don't want to apply the swizzled item to the actual blog. +// own ChangelogItem. We don't want to apply the swizzled item to the actual +// blog. function BlogPostPage(props: Props): JSX.Element { const {content: BlogPostContents, sidebar} = props; const {assets, metadata} = BlogPostContents; diff --git a/website/src/remark/configTabs.mjs b/website/src/remark/configTabs.mjs index 6e5962af27..ec4e8de8ce 100644 --- a/website/src/remark/configTabs.mjs +++ b/website/src/remark/configTabs.mjs @@ -8,7 +8,8 @@ import visit from 'unist-util-visit'; /** - * Turns a "```js config-tabs" code block into a "plugin options" and a "preset options" tab + * Turns a "```js config-tabs" code block into a "plugin options" and a "preset + * options" tab */ export default function plugin() { const transformer = (root) => { @@ -71,7 +72,8 @@ export default function plugin() { { type: 'link', title: null, - // TODO make this version-aware; maybe we need a useVersionedLink() hook + // TODO make this version-aware; maybe we need a + // useVersionedLink() hook url: '/docs/using-plugins#docusauruspreset-classic', children: [ { diff --git a/website/src/utils/jsUtils.ts b/website/src/utils/jsUtils.ts index c699dceca8..c389b4e397 100644 --- a/website/src/utils/jsUtils.ts +++ b/website/src/utils/jsUtils.ts @@ -27,9 +27,8 @@ export function toggleListItem(list: T[], item: T): T[] { const itemIndex = list.indexOf(item); if (itemIndex === -1) { return list.concat(item); - } else { - const newList = [...list]; - newList.splice(itemIndex, 1); - return newList; } + const newList = [...list]; + newList.splice(itemIndex, 1); + return newList; } diff --git a/website/testCSSOrder.mjs b/website/testCSSOrder.mjs index 49df2a327d..3b2b6eaf2f 100644 --- a/website/testCSSOrder.mjs +++ b/website/testCSSOrder.mjs @@ -20,8 +20,8 @@ See also - https://github.com/facebook/docusaurus/issues/3678 - https://github.com/facebook/docusaurus/pull/5987 -TODO we should probably add a real e2e test in core instead of using our own website? -Current solution looks good-enough for now +TODO we should probably add a real e2e test in core instead of using our own +website? Current solution looks good-enough for now */ diff --git a/website/waitForCrowdin.mjs b/website/waitForCrowdin.mjs index e9bd89811b..577abf38cc 100644 --- a/website/waitForCrowdin.mjs +++ b/website/waitForCrowdin.mjs @@ -8,14 +8,16 @@ import {Translations} from '@crowdin/crowdin-api-client'; /* -Crowdin does not support concurrent "project builds" (downloads of translations). -The Crowdin CLI fails with error 409, and it leads to failures on Netlify. +Crowdin does not support concurrent "project builds" (downloads of +translations). The Crowdin CLI fails with error 409, and it leads to failures on +Netlify. On Docusaurus, when we commit on main, we have 2 Netlify deployments triggered: - prod - i18n-staging (work-in-progress locales) -This script helps the 2 deployments to not download translations concurrently from Crowdin. +This script helps the 2 deployments to not download translations concurrently +from Crowdin. */ const pollInterval = 5000;