refactor: remove unnecessary default values normalized during validation (#6864)

* refactor: remove unnecessary default values normalized during validation

* more
This commit is contained in:
Joshua Chen 2022-03-07 19:23:30 +08:00 committed by GitHub
parent 7fc134ba0e
commit 8e934450d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 146 additions and 138 deletions

View file

@ -114,7 +114,7 @@ export default async function mdxLoader(
): Promise<void> {
const callback = this.async();
const filePath = this.resourcePath;
const reqOptions = this.getOptions() || {};
const reqOptions = this.getOptions() ?? {};
const {frontMatter, content: contentWithTitle} = parseFrontMatter(fileString);
@ -127,7 +127,7 @@ export default async function mdxLoader(
const options: Options = {
...reqOptions,
remarkPlugins: [
...(reqOptions.beforeDefaultRemarkPlugins || []),
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
...DEFAULT_OPTIONS.remarkPlugins,
[
transformImage,
@ -143,12 +143,12 @@ export default async function mdxLoader(
siteDir: reqOptions.siteDir,
},
],
...(reqOptions.remarkPlugins || []),
...(reqOptions.remarkPlugins ?? []),
],
rehypePlugins: [
...(reqOptions.beforeDefaultRehypePlugins || []),
...(reqOptions.beforeDefaultRehypePlugins ?? []),
...DEFAULT_OPTIONS.rehypePlugins,
...(reqOptions.rehypePlugins || []),
...(reqOptions.rehypePlugins ?? []),
],
filepath: filePath,
};

View file

@ -166,9 +166,7 @@ function createCreateRedirectsOptionRedirects(
createRedirects: PluginOptions['createRedirects'],
): RedirectMetadata[] {
function createPathRedirects(path: string): RedirectMetadata[] {
const fromsMixed: string | string[] = createRedirects
? createRedirects(path) || []
: [];
const fromsMixed: string | string[] = createRedirects?.(path) ?? [];
const froms: string[] =
typeof fromsMixed === 'string' ? [fromsMixed] : fromsMixed;

View file

@ -546,13 +546,11 @@ export default async function pluginContentBlog(
const headTags: HtmlTags = [];
feedTypes.forEach((feedType) => {
const feedConfig = feedsConfig[feedType] || {};
if (!feedsConfig) {
return;
}
const {type, path: feedConfigPath, title: feedConfigTitle} = feedConfig;
const {
type,
path: feedConfigPath,
title: feedConfigTitle,
} = feedsConfig[feedType];
headTags.push({
tagName: 'link',

View file

@ -537,7 +537,7 @@ export function filterVersions(
): string[] {
if (options.onlyIncludeVersions) {
return versionNamesUnfiltered.filter((name) =>
(options.onlyIncludeVersions || []).includes(name),
options.onlyIncludeVersions!.includes(name),
);
}
return versionNamesUnfiltered;

View file

@ -47,7 +47,7 @@ export default async function pluginContentPages(
): Promise<Plugin<LoadedContent | null>> {
if (options.admonitions) {
options.remarkPlugins = options.remarkPlugins.concat([
[admonitions, options.admonitions || {}],
[admonitions, options.admonitions],
]);
}
const {
@ -77,7 +77,7 @@ export default async function pluginContentPages(
name: 'docusaurus-plugin-content-pages',
getPathsToWatch() {
const {include = []} = options;
const {include} = options;
return getContentPathList(contentPaths).flatMap((contentPath) =>
include.map((pattern) => `${contentPath}/${pattern}`),
);

View file

@ -191,7 +191,7 @@ export default function pluginPWA(
'**/*.{woff,woff2,eot,ttf,otf}',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
...(injectManifest.globPatterns || []),
...(injectManifest.globPatterns ?? []),
],
// those attributes are not overrideable
swDest,

View file

@ -97,16 +97,15 @@ export default function docusaurusThemeClassic(
options: Options,
): Plugin<void> {
const {
siteConfig: {themeConfig: roughlyTypedThemeConfig},
i18n: {currentLocale, localeConfigs},
} = context;
const themeConfig = (roughlyTypedThemeConfig || {}) as ThemeConfig;
const themeConfig = context.siteConfig.themeConfig as ThemeConfig;
const {
announcementBar,
colorMode,
prism: {additionalLanguages = []} = {},
prism: {additionalLanguages},
} = themeConfig;
const {customCss} = options || {};
const {customCss} = options ?? {};
const {direction} = localeConfigs[currentLocale]!;
return {

View file

@ -50,14 +50,11 @@ function YearsSection({years}: {years: YearProp[]}) {
}
function listPostsByYears(blogPosts: readonly ArchiveBlogPost[]): YearProp[] {
const postsByYear: Map<string, ArchiveBlogPost[]> = blogPosts.reduceRight(
(posts, post) => {
const year = post.metadata.date.split('-')[0];
const yearPosts = posts.get(year) || [];
return posts.set(year, [post, ...yearPosts]);
},
new Map(),
);
const postsByYear = blogPosts.reduceRight((posts, post) => {
const year = post.metadata.date.split('-')[0]!;
const yearPosts = posts.get(year) ?? [];
return posts.set(year, [post, ...yearPosts]);
}, new Map<string, ArchiveBlogPost[]>());
return Array.from(postsByYear, ([year, posts]) => ({
year,

View file

@ -15,10 +15,10 @@ import {
type MultiColumnFooter,
type SimpleFooter,
} from '@docusaurus/theme-common';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useBaseUrl, {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
import isInternalUrl from '@docusaurus/isInternalUrl';
import styles from './styles.module.css';
import ThemedImage, {type Props as ThemedImageProps} from '@theme/ThemedImage';
import ThemedImage from '@theme/ThemedImage';
import IconExternalLink from '@theme/IconExternalLink';
function FooterLink({
@ -54,21 +54,35 @@ function FooterLink({
);
}
function FooterLogo({
sources,
alt,
width,
height,
}: Pick<ThemedImageProps, 'sources' | 'alt' | 'width' | 'height'>) {
return (
function FooterLogo({logo}: {logo: SimpleFooter['logo']}) {
const {withBaseUrl} = useBaseUrlUtils();
if (!logo?.src) {
return null;
}
const sources = {
light: withBaseUrl(logo.src),
dark: withBaseUrl(logo.srcDark ?? logo.src),
};
const image = (
<ThemedImage
className="footer__logo"
alt={alt}
alt={logo.alt}
sources={sources}
width={width}
height={height}
width={logo.width}
height={logo.height}
/>
);
return (
<div className="margin-bottom--sm">
{logo.href ? (
<Link href={logo.href} className={styles.footerLogoLink}>
{image}
</Link>
) : (
image
)}
</div>
);
}
function MultiColumnLinks({links}: {links: MultiColumnFooter['links']}) {
@ -136,16 +150,10 @@ function isMultiColumnFooterLinks(
function Footer(): JSX.Element | null {
const {footer} = useThemeConfig();
const {copyright, links = [], logo = {}} = footer || {};
const sources = {
light: useBaseUrl(logo.src),
dark: useBaseUrl(logo.srcDark || logo.src),
};
if (!footer) {
return null;
}
const {copyright, links, logo} = footer;
return (
<footer
@ -166,28 +174,8 @@ function Footer(): JSX.Element | null {
))}
{(logo || copyright) && (
<div className="footer__bottom text--center">
{logo && (logo.src || logo.srcDark) && (
<div className="margin-bottom--sm">
{logo.href ? (
<Link href={logo.href} className={styles.footerLogoLink}>
<FooterLogo
alt={logo.alt}
sources={sources}
width={logo.width}
height={logo.height}
/>
</Link>
) : (
<FooterLogo
alt={logo.alt}
sources={sources}
width={logo.width}
height={logo.height}
/>
)}
</div>
)}
{copyright ? (
<FooterLogo logo={logo} />
{copyright && (
<div
className="footer__copyright"
// Developer provided the HTML, so assume it's safe.
@ -196,7 +184,7 @@ function Footer(): JSX.Element | null {
__html: copyright,
}}
/>
) : null}
)}
</div>
)}
</div>

View file

@ -17,7 +17,7 @@ import styles from './styles.module.css';
export default function ThemedImage(props: Props): JSX.Element {
const isBrowser = useIsBrowser();
const {isDarkTheme} = useColorMode();
const {sources, className, alt = '', ...propsRest} = props;
const {sources, className, alt, ...propsRest} = props;
type SourceName = keyof Props['sources'];

View file

@ -304,7 +304,7 @@ export const ThemeConfigSchema = Joi.object({
style: Joi.string().equal('dark', 'light').default('light'),
logo: Joi.object({
alt: Joi.string().allow(''),
src: Joi.string(),
src: Joi.string().required(),
srcDark: Joi.string(),
// TODO infer this from reading the image
width: Joi.alternatives().try(Joi.string(), Joi.number()),

View file

@ -56,7 +56,7 @@ export type PrismConfig = {
theme?: PrismTheme;
darkTheme?: PrismTheme;
defaultLanguage?: string;
additionalLanguages?: string[];
additionalLanguages: string[];
};
export type FooterLinkItem = {
@ -71,7 +71,7 @@ export type FooterBase = {
style: 'light' | 'dark';
logo?: {
alt?: string;
src?: string;
src: string;
srcDark?: string;
width?: string | number;
height?: string | number;

View file

@ -40,24 +40,24 @@ export interface DocusaurusConfig {
deploymentBranch?: string;
githubHost?: string;
githubPort?: string;
plugins?: PluginConfig[];
themes?: PluginConfig[];
presets?: PresetConfig[];
plugins: PluginConfig[];
themes: PluginConfig[];
presets: PresetConfig[];
themeConfig: ThemeConfig;
customFields?: {
[key: string]: unknown;
};
scripts?: (
scripts: (
| string
| {
src: string;
[key: string]: unknown;
}
)[];
clientModules?: string[];
clientModules: string[];
ssrTemplate?: string;
staticDirectories: string[];
stylesheets?: (
stylesheets: (
| string
| {
href: string;

View file

@ -30,5 +30,5 @@ Current type: ${isValidElement(children) ? 'React element' : typeof children}`);
return <>{children()}</>;
}
return fallback || null;
return fallback ?? null;
}

View file

@ -179,7 +179,7 @@ function Link(
{...props}
onMouseEnter={onMouseEnter}
innerRef={handleRef}
to={targetLink || ''}
to={targetLink}
// avoid "React does not recognize the `activeClassName` prop on a DOM
// element"
{...(isNavLink && {isActive, activeClassName})}

View file

@ -116,14 +116,14 @@ async function doRender(locals: Locals & {path: string}) {
// manifest information.
const modulesToBeLoaded = [...manifest.entrypoints, ...Array.from(modules)];
const bundles = getBundles(manifest, modulesToBeLoaded);
const stylesheets = (bundles.css || []).map((b) => b.file);
const scripts = (bundles.js || []).map((b) => b.file);
const stylesheets = (bundles.css ?? []).map((b) => b.file);
const scripts = (bundles.js ?? []).map((b) => b.file);
const renderedHtml = renderSSRTemplate(ssrTemplate, {
appHtml,
baseUrl,
htmlAttributes: htmlAttributes || '',
bodyAttributes: bodyAttributes || '',
htmlAttributes,
bodyAttributes,
headTags,
preBodyTags,
postBodyTags,

View file

@ -12,7 +12,7 @@ import {DEFAULT_PORT} from '@docusaurus/utils';
export function getCLIOptionHost(
hostOption: HostPortCLIOptions['host'],
): string {
return hostOption || 'localhost';
return hostOption ?? 'localhost';
}
export async function getCLIOptionPort(

View file

@ -75,7 +75,7 @@ export default async function start(
logger.error(err.stack);
});
}, 500);
const {siteConfig, plugins = []} = props;
const {siteConfig, plugins} = props;
const normalizeToSiteDir = (filepath: string) => {
if (filepath && path.isAbsolute(filepath)) {
@ -84,12 +84,9 @@ export default async function start(
return posixPath(filepath);
};
const pluginPaths = ([] as string[])
.concat(
...plugins
.map((plugin) => plugin.getPathsToWatch?.() ?? [])
.filter(Boolean),
)
const pluginPaths = plugins
.flatMap((plugin) => plugin.getPathsToWatch?.() ?? [])
.filter(Boolean)
.map(normalizeToSiteDir);
const pathsToWatch = [

View file

@ -15,6 +15,7 @@ exports[`loadConfig website with valid async config 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"clientModules": Array [],
"customFields": Object {},
"i18n": Object {
"defaultLocale": "en",
@ -31,9 +32,11 @@ Object {
"plugins": Array [],
"presets": Array [],
"projectName": "hello",
"scripts": Array [],
"staticDirectories": Array [
"static",
],
"stylesheets": Array [],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
@ -47,6 +50,7 @@ exports[`loadConfig website with valid async config creator function 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"clientModules": Array [],
"customFields": Object {},
"i18n": Object {
"defaultLocale": "en",
@ -63,9 +67,11 @@ Object {
"plugins": Array [],
"presets": Array [],
"projectName": "hello",
"scripts": Array [],
"staticDirectories": Array [
"static",
],
"stylesheets": Array [],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
@ -79,6 +85,7 @@ exports[`loadConfig website with valid config creator function 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"clientModules": Array [],
"customFields": Object {},
"i18n": Object {
"defaultLocale": "en",
@ -95,9 +102,11 @@ Object {
"plugins": Array [],
"presets": Array [],
"projectName": "hello",
"scripts": Array [],
"staticDirectories": Array [
"static",
],
"stylesheets": Array [],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
@ -111,6 +120,7 @@ exports[`loadConfig website with valid siteConfig 1`] = `
Object {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"clientModules": Array [],
"customFields": Object {},
"favicon": "img/docusaurus.ico",
"i18n": Object {
@ -136,9 +146,11 @@ Object {
],
"presets": Array [],
"projectName": "hello",
"scripts": Array [],
"staticDirectories": Array [
"static",
],
"stylesheets": Array [],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],

View file

@ -26,6 +26,9 @@ export const DEFAULT_CONFIG: Pick<
| 'plugins'
| 'themes'
| 'presets'
| 'stylesheets'
| 'scripts'
| 'clientModules'
| 'customFields'
| 'themeConfig'
| 'titleDelimiter'
@ -41,6 +44,9 @@ export const DEFAULT_CONFIG: Pick<
plugins: [],
themes: [],
presets: [],
stylesheets: [],
scripts: [],
clientModules: [],
customFields: {},
themeConfig: {},
titleDelimiter: '|',
@ -170,25 +176,31 @@ export const ConfigSchema = Joi.object({
themes: Joi.array().items(ThemeSchema).default(DEFAULT_CONFIG.themes),
presets: Joi.array().items(PresetSchema).default(DEFAULT_CONFIG.presets),
themeConfig: Joi.object().unknown().default(DEFAULT_CONFIG.themeConfig),
scripts: Joi.array().items(
Joi.string(),
Joi.object({
src: Joi.string().required(),
async: Joi.bool(),
defer: Joi.bool(),
})
// See https://github.com/facebook/docusaurus/issues/3378
.unknown(),
),
scripts: Joi.array()
.items(
Joi.string(),
Joi.object({
src: Joi.string().required(),
async: Joi.bool(),
defer: Joi.bool(),
})
// See https://github.com/facebook/docusaurus/issues/3378
.unknown(),
)
.default(DEFAULT_CONFIG.scripts),
ssrTemplate: Joi.string(),
stylesheets: Joi.array().items(
Joi.string(),
Joi.object({
href: Joi.string().required(),
type: Joi.string(),
}).unknown(),
),
clientModules: Joi.array().items(Joi.string()),
stylesheets: Joi.array()
.items(
Joi.string(),
Joi.object({
href: Joi.string().required(),
type: Joi.string(),
}).unknown(),
)
.default(DEFAULT_CONFIG.stylesheets),
clientModules: Joi.array()
.items(Joi.string())
.default(DEFAULT_CONFIG.clientModules),
tagline: Joi.string().allow('').default(DEFAULT_CONFIG.tagline),
titleDelimiter: Joi.string().default('|'),
noIndex: Joi.bool().default(false),

View file

@ -33,7 +33,7 @@ export default function htmlTagObjectToString(tagDefinition: unknown): string {
);
}
const isVoidTag = voidHtmlTags.indexOf(tagDefinition.tagName) !== -1;
const tagAttributes = tagDefinition.attributes || {};
const tagAttributes = tagDefinition.attributes ?? {};
const attributes = Object.keys(tagAttributes)
.filter((attributeName) => tagAttributes[attributeName] !== false)
.map((attributeName) => {

View file

@ -28,7 +28,7 @@ export function loadHtmlTags(plugins: LoadedPlugin[]): InjectedHtmlTags {
return acc;
}
const {headTags, preBodyTags, postBodyTags} =
plugin.injectHtmlTags({content: plugin.content}) || {};
plugin.injectHtmlTags({content: plugin.content}) ?? {};
return {
headTags: headTags
? `${acc.headTags}\n${createHtmlTagsString(headTags)}`

View file

@ -160,10 +160,10 @@ export async function loadPluginConfigs(
presetThemes = presetThemes.map((theme) =>
normalizeShorthand(theme, 'theme'),
);
const standalonePlugins = (siteConfig.plugins || []).map((plugin) =>
const standalonePlugins = siteConfig.plugins.map((plugin) =>
normalizeShorthand(plugin, 'plugin'),
);
const standaloneThemes = (siteConfig.themes || []).map((theme) =>
const standaloneThemes = siteConfig.themes.map((theme) =>
normalizeShorthand(theme, 'theme'),
);
return [
@ -184,9 +184,9 @@ function createBootstrapPlugin({
siteConfig: DocusaurusConfig;
}): LoadedPlugin {
const {
stylesheets = [],
scripts = [],
clientModules: siteConfigClientModules = [],
stylesheets,
scripts,
clientModules: siteConfigClientModules,
} = siteConfig;
return {
name: 'docusaurus-bootstrap-plugin',
@ -314,6 +314,7 @@ export async function load(
generatedFilesDir,
'DONT-EDIT-THIS-FOLDER',
`This folder stores temp files that Docusaurus' client bundler accesses.
DO NOT hand-modify files in this folder because they will be overwritten in the
next build. You can clear all build artifacts (including this folder) with the
\`docusaurus clear\` command.
@ -326,11 +327,12 @@ next build. You can clear all build artifacts (including this folder) with the
generatedFilesDir,
DEFAULT_CONFIG_FILE_NAME,
`/*
AUTOGENERATED - DON'T EDIT
Your edits in this file will be overwritten in the next build!
Modify the docusaurus.config.js file at your site's root instead.
*/
export default ${JSON.stringify(siteConfig, null, 2)};`,
* AUTOGENERATED - DON'T EDIT
* Your edits in this file will be overwritten in the next build!
* Modify the docusaurus.config.js file at your site's root instead.
*/
export default ${JSON.stringify(siteConfig, null, 2)};
`,
);
plugins.push(createBootstrapPlugin({siteConfig}));
@ -341,11 +343,14 @@ export default ${JSON.stringify(siteConfig, null, 2)};`,
const genClientModules = generate(
generatedFilesDir,
'client-modules.js',
`export default [\n${clientModules
// import() is async so we use require() because client modules can have
// CSS and the order matters for loading CSS.
.map((module) => ` require('${escapePath(module)}'),`)
.join('\n')}\n];\n`,
`export default [
${clientModules
// import() is async so we use require() because client modules can have
// CSS and the order matters for loading CSS.
.map((module) => ` require('${escapePath(module)}'),`)
.join('\n')}
];
`,
);
// Load extra head & body html tags.
@ -367,7 +372,8 @@ ${Object.entries(registry)
chunk.modulePath,
)}', require.resolveWeak('${escapePath(chunk.modulePath)}')],`,
)
.join('\n')}};\n`,
.join('\n')}};
`,
);
const genRoutesChunkNames = generate(

View file

@ -14,7 +14,9 @@ describe('loadPresets', () => {
test('no presets', async () => {
const context = {
siteConfigPath: __dirname,
siteConfig: {},
siteConfig: {
presets: [],
},
} as LoadContext;
const presets = await loadPresets(context);
expect(presets).toMatchInlineSnapshot(`

View file

@ -10,7 +10,6 @@ import importFresh from 'import-fresh';
import type {
LoadContext,
PluginConfig,
PresetConfig,
ImportedPresetModule,
} from '@docusaurus/types';
import {resolveModuleName} from '../moduleShorthand';
@ -23,7 +22,7 @@ export default async function loadPresets(context: LoadContext): Promise<{
// siteDir's package.json declares the dependency on these presets.
const presetRequire = createRequire(context.siteConfigPath);
const presets: PresetConfig[] = context.siteConfig.presets || [];
const {presets} = context.siteConfig;
const unflatPlugins: PluginConfig[][] = [];
const unflatThemes: PluginConfig[][] = [];

View file

@ -176,7 +176,7 @@ export default class CleanWebpackPlugin {
stats.toJson({
all: false,
assets: true,
}).assets || [];
}).assets ?? [];
const assets = statsAssets.map((asset: {name: string}) => asset.name);
/**

View file

@ -23,7 +23,7 @@ export default async function lqipLoader(
const callback = this.async();
const imgPath = this.resourcePath;
const config = this.getOptions() || {};
const config = this.getOptions() ?? {};
config.base64 = 'base64' in config ? config.base64 : true;
// color palette generation is set to false by default
// since it is little bit slower than base64 generation