refactor: reduce number of leaked anys (#7465)

This commit is contained in:
Joshua Chen 2022-05-23 00:30:32 +08:00 committed by GitHub
parent 6e62bba30f
commit 89b0fff128
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 121 additions and 89 deletions

View file

@ -28,7 +28,11 @@ type PackageJsonFile = {
async function getPackagesJsonFiles(): Promise<PackageJsonFile[]> { async function getPackagesJsonFiles(): Promise<PackageJsonFile[]> {
const files = await Globby('packages/*/package.json'); const files = await Globby('packages/*/package.json');
return Promise.all( return Promise.all(
files.map((file) => fs.readJSON(file).then((content) => ({file, content}))), files.map((file) =>
fs
.readJSON(file)
.then((content: PackageJsonFile['content']) => ({file, content})),
),
); );
} }

View file

@ -22,7 +22,11 @@ type TsconfigFile = {
async function getTsconfigFiles(): Promise<TsconfigFile[]> { async function getTsconfigFiles(): Promise<TsconfigFile[]> {
const files = await Globby('packages/*/tsconfig.*'); const files = await Globby('packages/*/tsconfig.*');
return Promise.all( return Promise.all(
files.map((file) => fs.readJSON(file).then((content) => ({file, content}))), files.map((file) =>
fs
.readJSON(file)
.then((content: TsconfigFile['content']) => ({file, content})),
),
); );
} }

View file

@ -65,7 +65,7 @@ async function askForPackageManagerChoice(): Promise<PackageManager> {
.map((p) => ({title: p, value: p})); .map((p) => ({title: p, value: p}));
return ( return (
await prompts( (await prompts(
{ {
type: 'select', type: 'select',
name: 'packageManager', name: 'packageManager',
@ -77,7 +77,7 @@ async function askForPackageManagerChoice(): Promise<PackageManager> {
logger.info`Falling back to name=${defaultPackageManager}`; logger.info`Falling back to name=${defaultPackageManager}`;
}, },
}, },
) )) as {packageManager: PackageManager}
).packageManager; ).packageManager;
} }
@ -203,7 +203,7 @@ async function getGitCommand(gitStrategy: GitStrategy): Promise<string> {
case 'copy': case 'copy':
return 'git clone --recursive --depth 1'; return 'git clone --recursive --depth 1';
case 'custom': { case 'custom': {
const {command} = await prompts( const {command} = (await prompts(
{ {
type: 'text', type: 'text',
name: 'command', name: 'command',
@ -215,7 +215,7 @@ async function getGitCommand(gitStrategy: GitStrategy): Promise<string> {
logger.info`Falling back to code=${'git clone'}`; logger.info`Falling back to code=${'git clone'}`;
}, },
}, },
); )) as {command: string};
return command ?? 'git clone'; return command ?? 'git clone';
} }
case 'deep': case 'deep':
@ -245,7 +245,7 @@ async function getSiteName(
} }
return reqName; return reqName;
} }
const {siteName} = await prompts( const {siteName} = (await prompts(
{ {
type: 'text', type: 'text',
name: 'siteName', name: 'siteName',
@ -259,7 +259,7 @@ async function getSiteName(
process.exit(1); process.exit(1);
}, },
}, },
); )) as {siteName: string};
return siteName; return siteName;
} }
@ -324,7 +324,7 @@ async function getSource(
const template = cliOptions.gitStrategy const template = cliOptions.gitStrategy
? 'Git repository' ? 'Git repository'
: ( : (
await prompts( (await prompts(
{ {
type: 'select', type: 'select',
name: 'template', name: 'template',
@ -337,10 +337,10 @@ async function getSource(
process.exit(1); process.exit(1);
}, },
}, },
) )) as {template: Template | 'Git repository' | 'Local template'}
).template; ).template;
if (template === 'Git repository') { if (template === 'Git repository') {
const {gitRepoUrl} = await prompts( const {gitRepoUrl} = (await prompts(
{ {
type: 'text', type: 'text',
name: 'gitRepoUrl', name: 'gitRepoUrl',
@ -359,7 +359,7 @@ async function getSource(
process.exit(1); process.exit(1);
}, },
}, },
); )) as {gitRepoUrl: string};
let strategy = cliOptions.gitStrategy; let strategy = cliOptions.gitStrategy;
if (!strategy) { if (!strategy) {
({strategy} = await prompts( ({strategy} = await prompts(
@ -393,7 +393,7 @@ async function getSource(
strategy: strategy ?? 'deep', strategy: strategy ?? 'deep',
}; };
} else if (template === 'Local template') { } else if (template === 'Local template') {
const {templateDir} = await prompts( const {templateDir} = (await prompts(
{ {
type: 'text', type: 'text',
name: 'templateDir', name: 'templateDir',
@ -418,7 +418,7 @@ async function getSource(
process.exit(1); process.exit(1);
}, },
}, },
); )) as {templateDir: string};
return { return {
type: 'local', type: 'local',
path: templateDir, path: templateDir,
@ -442,7 +442,7 @@ async function getSource(
} }
async function updatePkg(pkgPath: string, obj: {[key: string]: unknown}) { async function updatePkg(pkgPath: string, obj: {[key: string]: unknown}) {
const pkg = await fs.readJSON(pkgPath); const pkg = (await fs.readJSON(pkgPath)) as {[key: string]: unknown};
const newPkg = Object.assign(pkg, obj); const newPkg = Object.assign(pkg, obj);
await fs.outputFile(pkgPath, `${JSON.stringify(newPkg, null, 2)}\n`); await fs.outputFile(pkgPath, `${JSON.stringify(newPkg, null, 2)}\n`);

View file

@ -92,8 +92,12 @@ async function readMetadataPath(metadataPath: string) {
* *
* `{image: "./myImage.png"}` => `{image: require("./myImage.png")}` * `{image: "./myImage.png"}` => `{image: require("./myImage.png")}`
*/ */
function createAssetsExportCode(assets: {[key: string]: unknown}) { function createAssetsExportCode(assets: unknown) {
if (Object.keys(assets).length === 0) { if (
typeof assets !== 'object' ||
!assets ||
Object.keys(assets).length === 0
) {
return 'undefined'; return 'undefined';
} }
@ -101,7 +105,7 @@ function createAssetsExportCode(assets: {[key: string]: unknown}) {
function createAssetValueCode(assetValue: unknown): string | undefined { function createAssetValueCode(assetValue: unknown): string | undefined {
if (Array.isArray(assetValue)) { if (Array.isArray(assetValue)) {
const arrayItemCodes = assetValue.map( const arrayItemCodes = assetValue.map(
(item) => createAssetValueCode(item) ?? 'undefined', (item: unknown) => createAssetValueCode(item) ?? 'undefined',
); );
return `[${arrayItemCodes.join(', ')}]`; return `[${arrayItemCodes.join(', ')}]`;
} }
@ -119,7 +123,7 @@ function createAssetsExportCode(assets: {[key: string]: unknown}) {
const assetEntries = Object.entries(assets); const assetEntries = Object.entries(assets);
const codeLines = assetEntries const codeLines = assetEntries
.map(([key, value]) => { .map(([key, value]: [string, unknown]) => {
const assetRequireCode = createAssetValueCode(value); const assetRequireCode = createAssetValueCode(value);
return assetRequireCode ? `"${key}": ${assetRequireCode},` : undefined; return assetRequireCode ? `"${key}": ${assetRequireCode},` : undefined;
}) })
@ -227,7 +231,7 @@ ${JSON.stringify(frontMatter, null, 2)}`;
: undefined; : undefined;
const metadata = metadataJsonString const metadata = metadataJsonString
? JSON.parse(metadataJsonString) ? (JSON.parse(metadataJsonString) as {[key: string]: unknown})
: undefined; : undefined;
const assets = const assets =

View file

@ -13,13 +13,14 @@ import removePosition from 'unist-util-remove-position';
import toString from 'mdast-util-to-string'; import toString from 'mdast-util-to-string';
import visit from 'unist-util-visit'; import visit from 'unist-util-visit';
import slug from '../index'; import slug from '../index';
import type {Plugin} from 'unified';
function process(doc, plugins = []) { function process(doc: string, plugins: Plugin[] = []) {
const processor = remark().use({plugins: [...plugins, slug]}); const processor = remark().use({plugins: [...plugins, slug]});
return removePosition(processor.runSync(processor.parse(doc)), true); return removePosition(processor.runSync(processor.parse(doc)), true);
} }
function heading(label, id) { function heading(label: string, id: string) {
return u( return u(
'heading', 'heading',
{depth: 2, data: {id, hProperties: {id}}}, {depth: 2, data: {id, hProperties: {id}}},

View file

@ -35,9 +35,11 @@ declare module '@generated/registry' {
declare module '@generated/routes' { declare module '@generated/routes' {
import type {RouteConfig as RRRouteConfig} from 'react-router-config'; import type {RouteConfig as RRRouteConfig} from 'react-router-config';
import type Loadable from 'react-loadable';
type RouteConfig = RRRouteConfig & { type RouteConfig = RRRouteConfig & {
path: string; path: string;
component: ReturnType<typeof Loadable>;
}; };
const routes: RouteConfig[]; const routes: RouteConfig[];
export default routes; export default routes;

View file

@ -13,7 +13,11 @@ import {
URISchema, URISchema,
} from '@docusaurus/utils-validation'; } from '@docusaurus/utils-validation';
import {GlobExcludeDefault} from '@docusaurus/utils'; import {GlobExcludeDefault} from '@docusaurus/utils';
import type {PluginOptions, Options} from '@docusaurus/plugin-content-blog'; import type {
PluginOptions,
Options,
FeedType,
} from '@docusaurus/plugin-content-blog';
import type {OptionValidationContext} from '@docusaurus/types'; import type {OptionValidationContext} from '@docusaurus/types';
export const DEFAULT_OPTIONS: PluginOptions = { export const DEFAULT_OPTIONS: PluginOptions = {
@ -101,7 +105,7 @@ const PluginOptionSchema = Joi.object<PluginOptions>({
Joi.alternatives().conditional( Joi.alternatives().conditional(
Joi.string().equal('all', 'rss', 'atom', 'json'), Joi.string().equal('all', 'rss', 'atom', 'json'),
{ {
then: Joi.custom((val) => then: Joi.custom((val: FeedType | 'all') =>
val === 'all' ? ['rss', 'atom', 'json'] : [val], val === 'all' ? ['rss', 'atom', 'json'] : [val],
), ),
}, },

View file

@ -53,7 +53,7 @@ async function createVersionedSidebarFile({
// Tests depend on non-default export for mocking. // Tests depend on non-default export for mocking.
export async function cliDocsVersionCommand( export async function cliDocsVersionCommand(
version: string, version: unknown,
{id: pluginId, path: docsPath, sidebarPath}: PluginOptions, {id: pluginId, path: docsPath, sidebarPath}: PluginOptions,
{siteDir, i18n}: LoadContext, {siteDir, i18n}: LoadContext,
): Promise<void> { ): Promise<void> {
@ -70,7 +70,7 @@ export async function cliDocsVersionCommand(
} }
// Load existing versions. // Load existing versions.
let versions = []; let versions: string[] = [];
const versionsJSONFile = getVersionsFilePath(siteDir, pluginId); const versionsJSONFile = getVersionsFilePath(siteDir, pluginId);
if (await fs.pathExists(versionsJSONFile)) { if (await fs.pathExists(versionsJSONFile)) {
versions = await fs.readJSON(versionsJSONFile); versions = await fs.readJSON(versionsJSONFile);

View file

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

View file

@ -98,7 +98,7 @@ const OptionsSchema = Joi.object<PluginOptions>({
Joi.function(), Joi.function(),
// Convert boolean values to functions // Convert boolean values to functions
Joi.alternatives().conditional(Joi.boolean(), { Joi.alternatives().conditional(Joi.boolean(), {
then: Joi.custom((val) => then: Joi.custom((val: boolean) =>
val ? DefaultNumberPrefixParser : DisabledNumberPrefixParser, val ? DefaultNumberPrefixParser : DisabledNumberPrefixParser,
), ),
}), }),

View file

@ -95,7 +95,7 @@ async function readVersionsFile(
): Promise<string[] | null> { ): Promise<string[] | null> {
const versionsFilePath = getVersionsFilePath(siteDir, pluginId); const versionsFilePath = getVersionsFilePath(siteDir, pluginId);
if (await fs.pathExists(versionsFilePath)) { if (await fs.pathExists(versionsFilePath)) {
const content = await fs.readJSON(versionsFilePath); const content: unknown = await fs.readJSON(versionsFilePath);
validateVersionNames(content); validateVersionNames(content);
return content; return content;
} }

View file

@ -19,8 +19,9 @@ function BrowserOnlyReactJson(props: ReactJsonViewProps) {
return ( return (
<BrowserOnly> <BrowserOnly>
{() => { {() => {
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires const {default: ReactJson} =
const ReactJson = require('react-json-view').default; // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
require('react-json-view') as typeof import('react-json-view');
return <ReactJson {...props} />; return <ReactJson {...props} />;
}} }}
</BrowserOnly> </BrowserOnly>

View file

@ -320,6 +320,6 @@ if (typeof window !== 'undefined') {
addLegacyAppInstalledEventsListeners(); addLegacyAppInstalledEventsListeners();
// Then try to register the SW using lazy/dynamic imports // Then try to register the SW using lazy/dynamic imports
registerSW().catch((e) => console.error('registerSW failed', e)); registerSW().catch((e: unknown) => console.error('registerSW failed', e));
} }
} }

View file

@ -35,7 +35,7 @@ export default async function createSitemap(
} }
// https://github.com/staylor/react-helmet-async/pull/167 // https://github.com/staylor/react-helmet-async/pull/167
const meta = head[route]?.meta.toComponent() as unknown as const meta = head[route]?.meta.toComponent() as unknown as
| ReactElement[] | ReactElement<{name?: string; content?: string}>[]
| undefined; | undefined;
return !meta?.some( return !meta?.some(
(tag) => tag.props.name === 'robots' && tag.props.content === 'noindex', (tag) => tag.props.name === 'robots' && tag.props.content === 'noindex',

View file

@ -25,8 +25,10 @@ import styles from './styles.module.css';
// A very rough duck type, but good enough to guard against mistakes while // A very rough duck type, but good enough to guard against mistakes while
// allowing customization // allowing customization
function isTabItem(comp: ReactElement): comp is ReactElement<TabItemProps> { function isTabItem(
return typeof comp.props.value !== 'undefined'; comp: ReactElement<object>,
): comp is ReactElement<TabItemProps> {
return 'value' in comp.props;
} }
function TabsComponent(props: Props): JSX.Element { function TabsComponent(props: Props): JSX.Element {

View file

@ -196,9 +196,7 @@ function CollapsibleBase({
className, className,
disableSSRStyle, disableSSRStyle,
}: CollapsibleBaseProps) { }: CollapsibleBaseProps) {
// any because TS is a pain for HTML element refs, see https://twitter.com/sebastienlorber/status/1412784677795110914 const collapsibleRef = useRef<HTMLElement>(null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const collapsibleRef = useRef<any>(null);
useCollapseAnimation({collapsibleRef, collapsed, animation}); useCollapseAnimation({collapsibleRef, collapsed, animation});
@ -206,7 +204,7 @@ function CollapsibleBase({
<As <As
// @ts-expect-error: the "too complicated type" is produced from // @ts-expect-error: the "too complicated type" is produced from
// "CollapsibleElementType" being a huge union // "CollapsibleElementType" being a huge union
ref={collapsibleRef} ref={collapsibleRef as RefObject<never>} // Refs are contravariant, which is not expressible in TS
style={disableSSRStyle ? undefined : getSSRStyle(collapsed)} style={disableSSRStyle ? undefined : getSSRStyle(collapsed)}
onTransitionEnd={(e: React.TransitionEvent) => { onTransitionEnd={(e: React.TransitionEvent) => {
if (e.propertyName !== 'height') { if (e.propertyName !== 'height') {

View file

@ -318,7 +318,7 @@ export function useDocRouteMetadata({
} }
// For now, the sidebarName is added as route config: not ideal! // For now, the sidebarName is added as route config: not ideal!
const sidebarName = currentDocRoute.sidebar; const sidebarName = currentDocRoute.sidebar as string;
const sidebarItems = sidebarName const sidebarItems = sidebarName
? versionMetadata.docsSidebars[sidebarName] ? versionMetadata.docsSidebars[sidebarName]

View file

@ -23,7 +23,7 @@ import type {TranslationFileContent} from '@docusaurus/types';
async function getPackageCodePath(packageName: string) { async function getPackageCodePath(packageName: string) {
const packagePath = path.join(__dirname, '../..', packageName); const packagePath = path.join(__dirname, '../..', packageName);
const packageJsonPath = path.join(packagePath, 'package.json'); const packageJsonPath = path.join(packagePath, 'package.json');
const {main} = await fs.readJSON(packageJsonPath); const {main} = (await fs.readJSON(packageJsonPath)) as {main: string};
const packageSrcPath = path.join(packagePath, path.dirname(main)); const packageSrcPath = path.join(packagePath, path.dirname(main));
return packageSrcPath; return packageSrcPath;
} }

View file

@ -11,7 +11,7 @@ const JoiFrontMatterString: Joi.Extension = {
type: 'string', type: 'string',
base: Joi.string(), base: Joi.string(),
// Fix Yaml that tries to auto-convert many things to string out of the box // Fix Yaml that tries to auto-convert many things to string out of the box
prepare: (value) => { prepare: (value: unknown) => {
if (typeof value === 'number' || value instanceof Date) { if (typeof value === 'number' || value instanceof Date) {
return {value: value.toString()}; return {value: value.toString()};
} }

View file

@ -40,10 +40,10 @@ export const URISchema = Joi.alternatives(
Joi.string().uri({allowRelative: true}), Joi.string().uri({allowRelative: true}),
// This custom validation logic is required notably because Joi does not // This custom validation logic is required notably because Joi does not
// accept paths like /a/b/c ... // accept paths like /a/b/c ...
Joi.custom((val, helpers) => { Joi.custom((val: unknown, helpers) => {
try { try {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new URL(val); new URL(String(val));
return val; return val;
} catch { } catch {
return helpers.error('any.invalid'); return helpers.error('any.invalid');
@ -55,7 +55,7 @@ export const URISchema = Joi.alternatives(
}); });
export const PathnameSchema = Joi.string() export const PathnameSchema = Joi.string()
.custom((val) => { .custom((val: string) => {
if (!isValidPathname(val)) { if (!isValidPathname(val)) {
throw new Error(); throw new Error();
} }

View file

@ -17,8 +17,9 @@ export const NODE_MINOR_VERSION = parseInt(
); );
/** Docusaurus core version. */ /** Docusaurus core version. */
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires export const DOCUSAURUS_VERSION =
export const DOCUSAURUS_VERSION = require('../package.json').version; // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
(require('../package.json') as {version: string}).version;
/** /**
* Can be overridden with cli option `--out-dir`. Code should generally use * Can be overridden with cli option `--out-dir`. Code should generally use

View file

@ -280,7 +280,10 @@ This can happen if you use special characters in front matter values (try using
} }
function unwrapMarkdownLinks(line: string): string { function unwrapMarkdownLinks(line: string): string {
return line.replace(/\[(?<alt>[^\]]+)\]\([^)]+\)/g, (match, p1) => p1); return line.replace(
/\[(?<alt>[^\]]+)\]\([^)]+\)/g,
(match, p1: string) => p1,
);
} }
function addHeadingId( function addHeadingId(

View file

@ -53,7 +53,8 @@ function getTransformOptions(isServer: boolean): TransformOptions {
// better to explicitly specify the version so that it can reuse the // better to explicitly specify the version so that it can reuse the
// helper better. See https://github.com/babel/babel/issues/10261 // helper better. See https://github.com/babel/babel/issues/10261
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
version: require('@babel/runtime/package.json').version, version: (require('@babel/runtime/package.json') as {version: string})
.version,
regenerator: true, regenerator: true,
useESModules: true, useESModules: true,
// Undocumented option that lets us encapsulate our runtime, ensuring // Undocumented option that lets us encapsulate our runtime, ensuring

View file

@ -70,7 +70,7 @@ class PendingNavigation extends React.Component<Props, State> {
this.routeUpdateCleanupCb?.(); this.routeUpdateCleanupCb?.();
this.setState({nextRouteHasLoaded: true}); this.setState({nextRouteHasLoaded: true});
}) })
.catch((e) => console.warn(e)); .catch((e: unknown) => console.warn(e));
return false; return false;
} }

View file

@ -19,8 +19,5 @@ import {matchRoutes} from 'react-router-config';
export default function preload(pathname: string): Promise<void[]> { export default function preload(pathname: string): Promise<void[]> {
const matches = matchRoutes(routes, pathname); const matches = matchRoutes(routes, pathname);
return Promise.all( return Promise.all(matches.map((match) => match.route.component.preload?.()));
// @ts-expect-error: ComponentCreator injected this method.
matches.map((match) => match.route.component?.preload?.()),
);
} }

View file

@ -37,7 +37,7 @@ export default function Loading({
maxWidth: '50%', maxWidth: '50%',
width: '100%', width: '100%',
}}> }}>
<p>{error.message}</p> <p>{String(error)}</p>
<div> <div>
<button type="button" onClick={retry}> <button type="button" onClick={retry}>
Retry Retry

View file

@ -78,7 +78,7 @@ export async function start(
logger.success`Docusaurus website is running at url=${newOpenUrl}.`; logger.success`Docusaurus website is running at url=${newOpenUrl}.`;
} }
}) })
.catch((err) => { .catch((err: Error) => {
logger.error(err.stack); logger.error(err.stack);
}); });
}, 500); }, 500);

View file

@ -14,14 +14,14 @@ import type {SwizzleAction, SwizzleComponentConfig} from '@docusaurus/types';
const ExitTitle = logger.yellow('[Exit]'); const ExitTitle = logger.yellow('[Exit]');
export async function askThemeName(themeNames: string[]): Promise<string> { export async function askThemeName(themeNames: string[]): Promise<string> {
const {themeName} = await prompts({ const {themeName} = (await prompts({
type: 'select', type: 'select',
name: 'themeName', name: 'themeName',
message: 'Select a theme to swizzle:', message: 'Select a theme to swizzle:',
choices: themeNames choices: themeNames
.map((theme) => ({title: theme, value: theme})) .map((theme) => ({title: theme, value: theme}))
.concat({title: ExitTitle, value: '[Exit]'}), .concat({title: ExitTitle, value: '[Exit]'}),
}); })) as {themeName?: string};
if (!themeName || themeName === '[Exit]') { if (!themeName || themeName === '[Exit]') {
process.exit(0); process.exit(0);
} }
@ -41,7 +41,7 @@ export async function askComponentName(
})}`; })}`;
} }
const {componentName} = await prompts({ const {componentName} = (await prompts({
type: 'autocomplete', type: 'autocomplete',
name: 'componentName', name: 'componentName',
message: ` message: `
@ -58,12 +58,12 @@ ${PartiallySafeHint} = not safe for all swizzle actions
value: compName, value: compName,
})) }))
.concat({title: ExitTitle, value: '[Exit]'}), .concat({title: ExitTitle, value: '[Exit]'}),
async suggest(input, choices) { async suggest(input: string, choices) {
return choices.filter((choice) => return choices.filter((choice) =>
choice.title.toLowerCase().includes(input.toLowerCase()), choice.title.toLowerCase().includes(input.toLowerCase()),
); );
}, },
}); })) as {componentName?: string};
logger.newLine(); logger.newLine();
if (!componentName || componentName === '[Exit]') { if (!componentName || componentName === '[Exit]') {
@ -74,7 +74,7 @@ ${PartiallySafeHint} = not safe for all swizzle actions
} }
export async function askSwizzleDangerousComponent(): Promise<boolean> { export async function askSwizzleDangerousComponent(): Promise<boolean> {
const {switchToDanger} = await prompts({ const {switchToDanger} = (await prompts({
type: 'select', type: 'select',
name: 'switchToDanger', name: 'switchToDanger',
message: `Do you really want to swizzle this unsafe internal component?`, message: `Do you really want to swizzle this unsafe internal component?`,
@ -86,7 +86,7 @@ export async function askSwizzleDangerousComponent(): Promise<boolean> {
}, },
{title: ExitTitle, value: '[Exit]'}, {title: ExitTitle, value: '[Exit]'},
], ],
}); })) as {switchToDanger?: boolean | '[Exit]'};
if (typeof switchToDanger === 'undefined' || switchToDanger === '[Exit]') { if (typeof switchToDanger === 'undefined' || switchToDanger === '[Exit]') {
return process.exit(0); return process.exit(0);
@ -98,7 +98,7 @@ export async function askSwizzleDangerousComponent(): Promise<boolean> {
export async function askSwizzleAction( export async function askSwizzleAction(
componentConfig: SwizzleComponentConfig, componentConfig: SwizzleComponentConfig,
): Promise<SwizzleAction> { ): Promise<SwizzleAction> {
const {action} = await prompts({ const {action} = (await prompts({
type: 'select', type: 'select',
name: 'action', name: 'action',
message: `Which swizzle action do you want to do?`, message: `Which swizzle action do you want to do?`,
@ -117,7 +117,7 @@ export async function askSwizzleAction(
}, },
{title: ExitTitle, value: '[Exit]'}, {title: ExitTitle, value: '[Exit]'},
], ],
}); })) as {action?: SwizzleAction | '[Exit]'};
if (typeof action === 'undefined' || action === '[Exit]') { if (typeof action === 'undefined' || action === '[Exit]') {
return process.exit(0); return process.exit(0);

View file

@ -30,7 +30,7 @@ export async function loadSiteConfig({
const importedConfig = importFresh(siteConfigPath); const importedConfig = importFresh(siteConfigPath);
const loadedConfig = const loadedConfig: unknown =
typeof importedConfig === 'function' typeof importedConfig === 'function'
? await importedConfig() ? await importedConfig()
: await importedConfig; : await importedConfig;

View file

@ -144,9 +144,9 @@ const I18N_CONFIG_SCHEMA = Joi.object<I18nConfig>({
.optional() .optional()
.default(DEFAULT_I18N_CONFIG); .default(DEFAULT_I18N_CONFIG);
const SiteUrlSchema = URISchema.required().custom((value, helpers) => { const SiteUrlSchema = URISchema.required().custom((value: unknown, helpers) => {
try { try {
const {pathname} = new URL(value); const {pathname} = new URL(String(value));
if (pathname !== '/') { if (pathname !== '/') {
helpers.warn('docusaurus.configValidationWarning', { helpers.warn('docusaurus.configValidationWarning', {
warningMessage: `the url is not supposed to contain a sub-path like '${pathname}', please use the baseUrl field for sub-paths`, warningMessage: `the url is not supposed to contain a sub-path like '${pathname}', please use the baseUrl field for sub-paths`,
@ -157,7 +157,7 @@ const SiteUrlSchema = URISchema.required().custom((value, helpers) => {
}, 'siteUrlCustomValidation'); }, 'siteUrlCustomValidation');
// TODO move to @docusaurus/utils-validation // TODO move to @docusaurus/utils-validation
export const ConfigSchema = Joi.object({ export const ConfigSchema = Joi.object<DocusaurusConfig>({
baseUrl: Joi.string() baseUrl: Joi.string()
.required() .required()
.regex(/\/$/m) .regex(/\/$/m)
@ -237,9 +237,7 @@ export const ConfigSchema = Joi.object({
}); });
// TODO move to @docusaurus/utils-validation // TODO move to @docusaurus/utils-validation
export function validateConfig( export function validateConfig(config: unknown): DocusaurusConfig {
config: Partial<DocusaurusConfig>,
): DocusaurusConfig {
const {error, warning, value} = ConfigSchema.validate(config, { const {error, warning, value} = ConfigSchema.validate(config, {
abortEarly: false, abortEarly: false,
}); });

View file

@ -70,7 +70,7 @@ async function choosePort(
} }
clearConsole(); clearConsole();
const existingProcess = getProcessForPort(defaultPort); const existingProcess = getProcessForPort(defaultPort);
const {shouldChangePort} = await prompts({ const {shouldChangePort} = (await prompts({
type: 'confirm', type: 'confirm',
name: 'shouldChangePort', name: 'shouldChangePort',
message: logger.yellow(`${logger.bold('[WARNING]')} ${message}${ message: logger.yellow(`${logger.bold('[WARNING]')} ${message}${
@ -79,7 +79,7 @@ async function choosePort(
Would you like to run the app on another port instead?`), Would you like to run the app on another port instead?`),
initial: true, initial: true,
}); })) as {shouldChangePort: boolean};
return shouldChangePort ? port : null; return shouldChangePort ? port : null;
} catch (err) { } catch (err) {
logger.error`Could not find an open port at ${host}.`; logger.error`Could not find an open port at ${host}.`;

View file

@ -20,7 +20,7 @@ async function getPackageJsonVersion(
): Promise<string | undefined> { ): Promise<string | undefined> {
if (await fs.pathExists(packageJsonPath)) { if (await fs.pathExists(packageJsonPath)) {
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
return require(packageJsonPath).version; return (require(packageJsonPath) as {version?: string}).version;
} }
return undefined; return undefined;
} }
@ -29,7 +29,7 @@ async function getPackageJsonName(
packageJsonPath: string, packageJsonPath: string,
): Promise<string | undefined> { ): Promise<string | undefined> {
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
return require(packageJsonPath).name; return (require(packageJsonPath) as {name?: string}).name;
} }
export async function getPluginVersion( export async function getPluginVersion(

View file

@ -58,7 +58,7 @@ async function readTranslationFileContent(
): Promise<TranslationFileContent | undefined> { ): Promise<TranslationFileContent | undefined> {
if (await fs.pathExists(filePath)) { if (await fs.pathExists(filePath)) {
try { try {
const content = await fs.readJSON(filePath); const content: unknown = await fs.readJSON(filePath);
ensureTranslationFileContent(content); ensureTranslationFileContent(content);
return content; return content;
} catch (err) { } catch (err) {

View file

@ -347,10 +347,12 @@ ${sourceWarningPart(path.node)}`,
firstArgEvaluated.confident && firstArgEvaluated.confident &&
typeof firstArgEvaluated.value === 'object' typeof firstArgEvaluated.value === 'object'
) { ) {
const {message, id, description} = firstArgEvaluated.value; const {message, id, description} = firstArgEvaluated.value as {
translations[id ?? message] = { [propName: string]: unknown;
message: message ?? id, };
...(description && {description}), translations[String(id ?? message)] = {
message: String(message ?? id),
...(Boolean(description) && {description: String(description)}),
}; };
} else { } else {
warnings.push( warnings.push(

View file

@ -27,6 +27,7 @@
"node": ">=14" "node": ">=14"
}, },
"devDependencies": { "devDependencies": {
"@types/file-loader": "^5.0.1",
"@types/sharp": "^0.30.2" "@types/sharp": "^0.30.2"
} }
} }

View file

@ -38,7 +38,7 @@ export default async function lqipLoader(
} else { } else {
if (!contentIsFileExport) { if (!contentIsFileExport) {
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
const fileLoader = require('file-loader'); const fileLoader = require('file-loader') as typeof import('file-loader');
content = fileLoader.call(this, contentBuffer); content = fileLoader.call(this, contentBuffer);
} }
source = content.match( source = content.match(

View file

@ -9,8 +9,8 @@ import path from 'path';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import sharp from 'sharp'; import sharp from 'sharp';
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
const {version} = require('../package.json'); const {version} = require('../package.json') as {version: string};
const ERROR_EXT = `Error: Input file is missing or uses unsupported image format, lqip v${version}`; const ERROR_EXT = `Error: Input file is missing or uses unsupported image format, lqip v${version}`;

View file

@ -27,11 +27,13 @@ export function VersionsProvider({
useEffect(() => { useEffect(() => {
fetch('https://registry.npmjs.org/@docusaurus/core') fetch('https://registry.npmjs.org/@docusaurus/core')
.then((res) => res.json()) .then((res) => res.json())
.then((data) => { .then(
const name = Object.keys(data.versions).at(-1)!; (data: {versions: string[]; time: {[versionName: string]: string}}) => {
const time = data.time[name]; const name = Object.keys(data.versions).at(-1)!;
setCanaryVersion({name, time}); const time = data.time[name];
}); setCanaryVersion({name, time});
},
);
}, []); }, []);
return <Context.Provider value={canaryVersion}>{children}</Context.Provider>; return <Context.Provider value={canaryVersion}>{children}</Context.Provider>;
} }

View file

@ -3308,6 +3308,13 @@
"@types/qs" "*" "@types/qs" "*"
"@types/serve-static" "*" "@types/serve-static" "*"
"@types/file-loader@^5.0.1":
version "5.0.1"
resolved "https://registry.yarnpkg.com/@types/file-loader/-/file-loader-5.0.1.tgz#300b7c729e4f0c523783b865b287e3459135bf22"
integrity sha512-FHPPuRb/Ts/25qvNU/mQGwRZUp793nBxYqXd/KwApykxATagqrO4+2EEcGDm/DuXyV/EkOa04umS1DQ8tQSomg==
dependencies:
"@types/webpack" "^4"
"@types/fs-extra@^9.0.13": "@types/fs-extra@^9.0.13":
version "9.0.13" version "9.0.13"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45"