refactor: improve internal typing (#6507)

* refactor: improve internal typing

* fix

* fix test
This commit is contained in:
Joshua Chen 2022-01-29 22:58:40 +08:00 committed by GitHub
parent 58e07a6796
commit 2553f1fb5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 165 additions and 132 deletions

View file

@ -249,7 +249,7 @@ describe('simple website', () => {
.spyOn(cliDocs, 'cliDocsVersionCommand') .spyOn(cliDocs, 'cliDocsVersionCommand')
.mockImplementation(); .mockImplementation();
const cli = new commander.Command(); const cli = new commander.Command();
// @ts-expect-error: TODO annoying type incompatibility // @ts-expect-error: in actual usage, we pass the static commander instead of the new command
plugin.extendCli!(cli); plugin.extendCli!(cli);
cli.parse(['node', 'test', 'docs:version', '1.0.0']); cli.parse(['node', 'test', 'docs:version', '1.0.0']);
expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledTimes(1);
@ -373,7 +373,7 @@ describe('versioned website', () => {
.spyOn(cliDocs, 'cliDocsVersionCommand') .spyOn(cliDocs, 'cliDocsVersionCommand')
.mockImplementation(); .mockImplementation();
const cli = new commander.Command(); const cli = new commander.Command();
// @ts-expect-error: TODO annoying type incompatibility // @ts-expect-error: in actual usage, we pass the static commander instead of the new command
plugin.extendCli!(cli); plugin.extendCli!(cli);
cli.parse(['node', 'test', 'docs:version', '2.0.0']); cli.parse(['node', 'test', 'docs:version', '2.0.0']);
expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledTimes(1);
@ -522,7 +522,7 @@ describe('versioned website (community)', () => {
.spyOn(cliDocs, 'cliDocsVersionCommand') .spyOn(cliDocs, 'cliDocsVersionCommand')
.mockImplementation(); .mockImplementation();
const cli = new commander.Command(); const cli = new commander.Command();
// @ts-expect-error: TODO annoying type incompatibility // @ts-expect-error: in actual usage, we pass the static commander instead of the new command
plugin.extendCli!(cli); plugin.extendCli!(cli);
cli.parse(['node', 'test', `docs:version:${pluginId}`, '2.0.0']); cli.parse(['node', 'test', `docs:version:${pluginId}`, '2.0.0']);
expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledTimes(1);

View file

@ -29,6 +29,6 @@ export function useDynamicCallback<T extends (...args: never[]) => unknown>(
ref.current = callback; ref.current = callback;
}, [callback]); }, [callback]);
// @ts-expect-error: TODO, not sure how to fix this TS error // @ts-expect-error: TS is right that this callback may be a supertype of T, but good enough for our use
return useCallback<T>((...args) => ref.current(...args), []); return useCallback<T>((...args) => ref.current(...args), []);
} }

View file

@ -0,0 +1,10 @@
/**
* 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.
*/
declare module '@docsearch/react/modal';
declare module '@docsearch/react/style';

View file

@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import React, {useState, useRef, useCallback, useMemo} from 'react'; import React, {useState, useRef, useCallback, useMemo} from 'react';
import {createPortal} from 'react-dom'; import {createPortal} from 'react-dom';
@ -120,9 +119,7 @@ function DocSearch({
} }
return Promise.all([ return Promise.all([
// @ts-ignore
import('@docsearch/react/modal'), import('@docsearch/react/modal'),
// @ts-ignore
import('@docsearch/react/style'), import('@docsearch/react/style'),
import('./styles.css'), import('./styles.css'),
]).then(([{DocSearchModal: Modal}]) => { ]).then(([{DocSearchModal: Modal}]) => {
@ -271,8 +268,7 @@ function DocSearch({
function SearchBar(): JSX.Element { function SearchBar(): JSX.Element {
const {siteConfig} = useDocusaurusContext(); const {siteConfig} = useDocusaurusContext();
// @ts-ignore return <DocSearch {...(siteConfig.themeConfig.algolia as DocSearchProps)} />;
return <DocSearch {...siteConfig.themeConfig.algolia} />;
} }
export default SearchBar; export default SearchBar;

View file

@ -6,7 +6,6 @@
*/ */
/* eslint-disable jsx-a11y/no-autofocus */ /* eslint-disable jsx-a11y/no-autofocus */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import React, {useEffect, useState, useReducer, useRef} from 'react'; import React, {useEffect, useState, useReducer, useRef} from 'react';
@ -29,6 +28,7 @@ import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
import Layout from '@theme/Layout'; import Layout from '@theme/Layout';
import Translate, {translate} from '@docusaurus/Translate'; import Translate, {translate} from '@docusaurus/Translate';
import styles from './styles.module.css'; import styles from './styles.module.css';
import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
// Very simple pluralization: probably good enough for now // Very simple pluralization: probably good enough for now
function useDocumentsFoundPlural() { function useDocumentsFoundPlural() {
@ -151,14 +151,12 @@ type ResultDispatcher =
function SearchPage(): JSX.Element { function SearchPage(): JSX.Element {
const { const {
siteConfig: { siteConfig: {themeConfig},
themeConfig: {
// @ts-ignore
algolia: {appId, apiKey, indexName, externalUrlRegex},
},
},
i18n: {currentLocale}, i18n: {currentLocale},
} = useDocusaurusContext(); } = useDocusaurusContext();
const {
algolia: {appId, apiKey, indexName, externalUrlRegex},
} = themeConfig as ThemeConfig;
const documentsFoundPlural = useDocumentsFoundPlural(); const documentsFoundPlural = useDocumentsFoundPlural();
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers(); const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();

View file

@ -6,7 +6,7 @@
*/ */
import type {RuleSetRule, Configuration} from 'webpack'; import type {RuleSetRule, Configuration} from 'webpack';
import type {Command} from 'commander'; import type {CommanderStatic} from 'commander';
import type {ParsedUrlQueryInput} from 'querystring'; import type {ParsedUrlQueryInput} from 'querystring';
import type Joi from 'joi'; import type Joi from 'joi';
import type {Overwrite, DeepPartial} from 'utility-types'; import type {Overwrite, DeepPartial} from 'utility-types';
@ -259,7 +259,6 @@ export interface Plugin<Content = unknown> {
}) => Promise<void>; }) => Promise<void>;
routesLoaded?: (routes: RouteConfig[]) => void; // TODO remove soon, deprecated (alpha-60) routesLoaded?: (routes: RouteConfig[]) => void; // TODO remove soon, deprecated (alpha-60)
postBuild?: (props: Props & {content: Content}) => Promise<void>; postBuild?: (props: Props & {content: Content}) => Promise<void>;
postStart?: (props: Props) => void;
// 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?: ( configureWebpack?: (
config: Configuration, config: Configuration,
@ -272,7 +271,7 @@ export interface Plugin<Content = unknown> {
getTypeScriptThemePath?: () => string; getTypeScriptThemePath?: () => string;
getPathsToWatch?: () => string[]; getPathsToWatch?: () => string[];
getClientModules?: () => string[]; getClientModules?: () => string[];
extendCli?: (cli: Command) => void; extendCli?: (cli: CommanderStatic) => void;
injectHtmlTags?: ({content}: {content: Content}) => { injectHtmlTags?: ({content}: {content: Content}) => {
headTags?: HtmlTags; headTags?: HtmlTags;
preBodyTags?: HtmlTags; preBodyTags?: HtmlTags;

View file

@ -28,8 +28,7 @@ export function normalizeUrl(rawUrls: string[]): string {
const replacement = urls[0].match(/^file:\/\/\//) ? '$1:///' : '$1://'; const replacement = urls[0].match(/^file:\/\/\//) ? '$1:///' : '$1://';
urls[0] = urls[0].replace(/^([^/:]+):\/*/, replacement); urls[0] = urls[0].replace(/^([^/:]+):\/*/, replacement);
// eslint-disable-next-line for (let i = 0; i < urls.length; i += 1) {
for (let i = 0; i < urls.length; i++) {
let component = urls[i]; let component = urls[i];
if (typeof component !== 'string') { if (typeof component !== 'string') {
@ -40,7 +39,7 @@ export function normalizeUrl(rawUrls: string[]): string {
if (i === urls.length - 1 && hasEndingSlash) { if (i === urls.length - 1 && hasEndingSlash) {
resultArray.push('/'); resultArray.push('/');
} }
// eslint-disable-next-line // eslint-disable-next-line no-continue
continue; continue;
} }

View file

@ -20,16 +20,20 @@ const {
engines: {node: requiredVersion}, engines: {node: requiredVersion},
} = require('../package.json'); } = require('../package.json');
// Notify user if @docusaurus packages is outdated // eslint-disable-next-line import/no-dynamic-require
// const sitePkg = require(path.resolve(process.cwd(), 'package.json'));
// Note: this is a 2-step process to avoid delaying cli usage by awaiting a response:
// - 1st run: trigger background job to check releases + store result /**
// - 2nd run: display potential update to users * Notify user if `@docusaurus` packages are outdated
// *
// Note: even if the * Note: this is a 2-step process to avoid delaying cli usage by awaiting a
// * response:
// cache data is stored in ~/.config/configstore/update-notifier-@docusaurus * - 1st run: trigger background job to check releases + store result
// * - 2nd run: display potential update to users
*
* cache data is stored in `~/.config/configstore/update-notifier-@docusaurus`
*/
function beforeCli() {
const notifier = updateNotifier({ const notifier = updateNotifier({
pkg: { pkg: {
name, name,
@ -47,6 +51,7 @@ const notifier = updateNotifier({
try { try {
if ( if (
notifier.config && notifier.config &&
// @ts-expect-error: this is an internal API
!notifier.disabled && !notifier.disabled &&
Date.now() - notifier.config.get('lastUpdateCheck') < 50 Date.now() - notifier.config.get('lastUpdateCheck') < 50
) { ) {
@ -58,8 +63,11 @@ try {
logger.error(e); logger.error(e);
} }
// We don't want to display update message for canary releases /**
// See https://github.com/facebook/docusaurus/issues/5378 * We don't want to display update message for canary releases.
* See https://github.com/facebook/docusaurus/issues/5378
* @param {import('update-notifier').UpdateInfo} update
*/
function ignoreUpdate(update) { function ignoreUpdate(update) {
const isCanaryRelease = const isCanaryRelease =
update && update.current && update.current.startsWith('0.0.0'); update && update.current && update.current.startsWith('0.0.0');
@ -71,17 +79,15 @@ if (
notifier.update && notifier.update &&
semver.lt(notifier.update.current, notifier.update.latest) semver.lt(notifier.update.current, notifier.update.latest)
) { ) {
// Because notifier clears cached data after reading it, leading to notifier not consistently displaying the update // Because notifier clears cached data after reading it, leading to notifier
// not consistently displaying the update.
// See https://github.com/yeoman/update-notifier/issues/209 // See https://github.com/yeoman/update-notifier/issues/209
notifier.config.set('update', notifier.update); notifier.config.set('update', notifier.update);
if (ignoreUpdate(notifier.update)) { if (ignoreUpdate(notifier.update)) {
// @ts-expect-error: it works
return; return;
} }
// eslint-disable-next-line import/no-dynamic-require, global-require
const sitePkg = require(path.resolve(process.cwd(), 'package.json'));
const siteDocusaurusPackagesForUpdate = Object.keys({ const siteDocusaurusPackagesForUpdate = Object.keys({
...sitePkg.dependencies, ...sitePkg.dependencies,
...sitePkg.devDependencies, ...sitePkg.devDependencies,
@ -122,3 +128,6 @@ if (!semver.satisfies(process.version, requiredVersion)) {
logger.info`You are using Node.js number=${process.version}, Requirement: Node.js number=${requiredVersion}.`; logger.info`You are using Node.js number=${process.version}, Requirement: Node.js number=${requiredVersion}.`;
process.exit(1); process.exit(1);
} }
}
module.exports = beforeCli;

View file

@ -23,7 +23,9 @@ const {
writeHeadingIds, writeHeadingIds,
} = require('../lib'); } = require('../lib');
require('./beforeCli'); const beforeCli = require('./beforeCli');
beforeCli();
const resolveDir = (dir = '.') => fs.realpathSync(dir); const resolveDir = (dir = '.') => fs.realpathSync(dir);
@ -239,7 +241,6 @@ function isInternalCommand(command) {
async function run() { async function run() {
if (!isInternalCommand(process.argv.slice(2)[0])) { if (!isInternalCommand(process.argv.slice(2)[0])) {
// @ts-expect-error: Hmmm
await externalCommand(cli, resolveDir('.')); await externalCommand(cli, resolveDir('.'));
} }

View file

@ -116,6 +116,7 @@
"@types/react-router-config": "^5.0.1", "@types/react-router-config": "^5.0.1",
"@types/rtl-detect": "^1.0.0", "@types/rtl-detect": "^1.0.0",
"@types/serve-handler": "^6.1.1", "@types/serve-handler": "^6.1.1",
"@types/update-notifier": "^5.1.0",
"@types/wait-on": "^5.2.0", "@types/wait-on": "^5.2.0",
"@types/webpack-bundle-analyzer": "^4.4.1", "@types/webpack-bundle-analyzer": "^4.4.1",
"react-test-renderer": "^17.0.2", "react-test-renderer": "^17.0.2",

View file

@ -47,11 +47,10 @@ function ComponentCreator(
Object.keys(flatChunkNames).forEach((key) => { Object.keys(flatChunkNames).forEach((key) => {
const chunkRegistry = registry[flatChunkNames[key]]; const chunkRegistry = registry[flatChunkNames[key]];
if (chunkRegistry) { if (chunkRegistry) {
/* eslint-disable prefer-destructuring */ // eslint-disable-next-line prefer-destructuring
optsLoader[key] = chunkRegistry[0]; optsLoader[key] = chunkRegistry[0];
optsModules.push(chunkRegistry[1]); optsModules.push(chunkRegistry[1]);
optsWebpack.push(chunkRegistry[2]); optsWebpack.push(chunkRegistry[2]);
/* eslint-enable prefer-destructuring */
} }
}); });

View file

@ -5,12 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import type {Command} from 'commander'; import type {CommanderStatic} from 'commander';
import {loadContext, loadPluginConfigs} from '../server'; import {loadContext, loadPluginConfigs} from '../server';
import initPlugins from '../server/plugins/init'; import initPlugins from '../server/plugins/init';
export default async function externalCommand( export default async function externalCommand(
cli: Command, cli: CommanderStatic,
siteDir: string, siteDir: string,
): Promise<void> { ): Promise<void> {
const context = await loadContext(siteDir); const context = await loadContext(siteDir);

View file

@ -121,24 +121,13 @@ Running the command will copy the relevant theme files to your site folder. You
| `--danger` | Allow swizzling of unstable components | | `--danger` | Allow swizzling of unstable components |
| `--typescript` | Swizzle TypeScript components | | `--typescript` | Swizzle TypeScript components |
An example to use `--danger` flag let's consider the below code:
```bash npm2yarn
npm run swizzle @docusaurus/theme-classic Logo -- --danger
```
:::caution :::caution
Unstable Components: components that have a higher risk of breaking changes due to internal refactorings. Unstable Components: components that have a higher risk of breaking changes due to internal refactorings.
::: :::
To unswizzle a component, simply delete the files of the swizzled component. To learn more about swizzling, see the [swizzling guide](./advanced/swizzling.md).
<!--
TODO a separate section for swizzle tutorial.
To learn more about swizzling, check [here](#).
-->
### `docusaurus deploy [siteDir]` {#docusaurus-deploy-sitedir} ### `docusaurus deploy [siteDir]` {#docusaurus-deploy-sitedir}

View file

@ -3686,6 +3686,11 @@
dependencies: dependencies:
"@types/color-convert" "*" "@types/color-convert" "*"
"@types/configstore@*":
version "5.0.1"
resolved "https://registry.yarnpkg.com/@types/configstore/-/configstore-5.0.1.tgz#7be34d28ce29a408c98e717ada0488664eaf6173"
integrity sha512-c/QCznvk7bLKGhHETj29rqKufui3jaAxjBhK4R2zUrMG5UG0qTwfWYxBoUbH8JCyDjdCWMIxPJ7/Fdz1UcAnWg==
"@types/connect-history-api-fallback@*", "@types/connect-history-api-fallback@^1.3.5": "@types/connect-history-api-fallback@*", "@types/connect-history-api-fallback@^1.3.5":
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
@ -4283,6 +4288,14 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
"@types/update-notifier@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/update-notifier/-/update-notifier-5.1.0.tgz#52ed6a2e9851fd6f1c88e93c85e8a0e1d5500fda"
integrity sha512-aGY5pH1Q/DcToKXl4MCj1c0uDUB+zSVFDRCI7Q7js5sguzBTqJV/5kJA2awofbtWYF3xnon1TYdZYnFditRPtQ==
dependencies:
"@types/configstore" "*"
boxen "^4.2.0"
"@types/wait-on@^5.2.0": "@types/wait-on@^5.2.0":
version "5.3.1" version "5.3.1"
resolved "https://registry.yarnpkg.com/@types/wait-on/-/wait-on-5.3.1.tgz#bc5520d1d8b90b9caab1bef23315685ded73320d" resolved "https://registry.yarnpkg.com/@types/wait-on/-/wait-on-5.3.1.tgz#bc5520d1d8b90b9caab1bef23315685ded73320d"
@ -5572,6 +5585,20 @@ boolbase@^1.0.0, boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
boxen@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==
dependencies:
ansi-align "^3.0.0"
camelcase "^5.3.1"
chalk "^3.0.0"
cli-boxes "^2.2.0"
string-width "^4.1.0"
term-size "^2.1.0"
type-fest "^0.8.1"
widest-line "^3.1.0"
boxen@^5.0.0, boxen@^5.0.1: boxen@^5.0.0, boxen@^5.0.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
@ -6163,7 +6190,7 @@ clear-module@^4.1.2:
parent-module "^2.0.0" parent-module "^2.0.0"
resolve-from "^5.0.0" resolve-from "^5.0.0"
cli-boxes@^2.2.1: cli-boxes@^2.2.0, cli-boxes@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
@ -17901,6 +17928,11 @@ tempy@^1.0.0:
type-fest "^0.16.0" type-fest "^0.16.0"
unique-string "^2.0.0" unique-string "^2.0.0"
term-size@^2.1.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==
terminal-link@^2.0.0, terminal-link@^2.1.1: terminal-link@^2.0.0, terminal-link@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"