refactor: ensure all types are using index signature instead of Record (#6995)

* refactor: ensure all types are using index signature instead of Record

* kick CI
This commit is contained in:
Joshua Chen 2022-03-25 18:06:30 +08:00 committed by GitHub
parent e8800b9d49
commit 87592bca03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 339 additions and 307 deletions

View file

@ -269,6 +269,10 @@ module.exports = {
ERROR,
{'ts-expect-error': 'allow-with-description'},
],
'@typescript-eslint/consistent-indexed-object-style': [
WARNING,
'index-signature',
],
'@typescript-eslint/consistent-type-imports': [
WARNING,
{disallowTypeAnnotations: false},

View file

@ -26,9 +26,11 @@ const PlaygroundDocumentationUrl = 'https://docusaurus.io/docs/playground';
export type PlaygroundName = keyof typeof PlaygroundConfigs;
function isValidPlaygroundName(
playgroundName: string,
playgroundName: string | undefined,
): playgroundName is PlaygroundName {
return Object.keys(PlaygroundConfigs).includes(playgroundName);
return (
!!playgroundName && Object.keys(PlaygroundConfigs).includes(playgroundName)
);
}
export function createPlaygroundDocumentationResponse(): HandlerResponse {
@ -54,10 +56,10 @@ export function createPlaygroundResponse(
}
// Inspired by https://stackoverflow.com/a/3409200/82609
function parseCookieString(cookieString: string): Record<string, string> {
const result: Record<string, string> = {};
function parseCookieString(cookieString: string): {[key: string]: string} {
const result: {[key: string]: string} = {};
cookieString.split(';').forEach((cookie) => {
const [name, value] = cookie.split('=');
const [name, value] = cookie.split('=') as [string, string];
result[name.trim()] = decodeURI(value);
});
return result;
@ -66,7 +68,7 @@ function parseCookieString(cookieString: string): Record<string, string> {
export function readPlaygroundName(
event: HandlerEvent,
): PlaygroundName | undefined {
const parsedCookie: Record<string, string> = event.headers.cookie
const parsedCookie: {[key: string]: string} = event.headers.cookie
? parseCookieString(event.headers.cookie)
: {};
const playgroundName: string | undefined = parsedCookie[CookieName];

View file

@ -31,7 +31,7 @@ export function print(
});
return serialize(error);
} else if (val && typeof val === 'object') {
const normalizedValue = _.cloneDeep(val) as Record<string, unknown>;
const normalizedValue = _.cloneDeep(val) as {[key: string]: unknown};
Object.keys(normalizedValue).forEach((key) => {
normalizedValue[key] = normalizePaths(normalizedValue[key]);
@ -46,7 +46,7 @@ export function test(val: unknown): boolean {
(typeof val === 'object' &&
val &&
Object.keys(val).some((key) =>
shouldUpdate((val as Record<string, unknown>)[key]),
shouldUpdate((val as {[key: string]: unknown})[key]),
)) ||
// val.message is non-enumerable in an error
(val instanceof Error && shouldUpdate(val.message)) ||

View file

@ -102,7 +102,7 @@ function isValidGitRepoUrl(gitRepoUrl: string) {
return ['https://', 'git@'].some((item) => gitRepoUrl.startsWith(item));
}
async function updatePkg(pkgPath: string, obj: Record<string, unknown>) {
async function updatePkg(pkgPath: string, obj: {[key: string]: unknown}) {
const content = await fs.readFile(pkgPath, 'utf-8');
const pkg = JSON.parse(content);
const newPkg = Object.assign(pkg, obj);

View file

@ -43,9 +43,9 @@ type Options = RemarkAndRehypePluginOptions & {
removeContentTitle?: boolean;
metadataPath?: string | ((filePath: string) => string);
createAssets?: (metadata: {
frontMatter: Record<string, unknown>;
metadata: Record<string, unknown>;
}) => Record<string, unknown>;
frontMatter: {[key: string]: unknown};
metadata: {[key: string]: unknown};
}) => {[key: string]: unknown};
filepath: string;
};
@ -72,7 +72,7 @@ async function readMetadataPath(metadataPath: string) {
*
* `{image: "./myImage.png"}` => `{image: require("./myImage.png")}`
*/
function createAssetsExportCode(assets: Record<string, unknown>) {
function createAssetsExportCode(assets: {[key: string]: unknown}) {
if (Object.keys(assets).length === 0) {
return 'undefined';
}

View file

@ -9,7 +9,7 @@ import type {Plugin} from 'unified';
export type RemarkOrRehypePlugin =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[Plugin<any[]>, Record<string, unknown>] | Plugin<any[]>;
[Plugin<any[]>, any] | Plugin<any[]>;
export type RemarkAndRehypePluginOptions = {
remarkPlugins: RemarkOrRehypePlugin[];
rehypePlugins: RemarkOrRehypePlugin[];

View file

@ -67,7 +67,7 @@ ${
type MigrationContext = {
siteDir: string;
newDir: string;
deps: Record<string, string>;
deps: {[key: string]: string};
shouldMigrateMdFiles: boolean;
shouldMigratePages: boolean;
v1Config: VersionOneConfig;
@ -83,7 +83,7 @@ export async function migrateDocusaurusProject(
async function createMigrationContext(): Promise<MigrationContext> {
const v1Config = importFresh(`${siteDir}/siteConfig`) as VersionOneConfig;
logger.info('Starting migration from v1 to v2...');
const deps: Record<string, string> = {
const deps = {
'@docusaurus/core': DOCUSAURUS_VERSION,
'@docusaurus/preset-classic': DOCUSAURUS_VERSION,
clsx: '^1.1.1',
@ -206,7 +206,7 @@ export function createConfigFile({
'v1Config' | 'siteDir' | 'newDir'
>): VersionTwoConfig {
const siteConfig = v1Config;
const customConfigFields: Record<string, unknown> = {};
const customConfigFields: {[key: string]: unknown} = {};
// add fields that are unknown to v2 to customConfigFields
Object.keys(siteConfig).forEach((key) => {
const knownFields = [
@ -564,7 +564,7 @@ async function migrateVersionedSidebar(
};
});
return acc;
}, {} as Record<string, Array<string | Record<string, unknown>>>);
}, {} as {[key: string]: Array<string | {[key: string]: unknown}>});
return topLevel;
},
{},
@ -702,9 +702,9 @@ async function migrateLatestDocs(context: MigrationContext) {
async function migratePackageFile(context: MigrationContext): Promise<void> {
const {deps, siteDir, newDir} = context;
const packageFile = importFresh(`${siteDir}/package.json`) as {
scripts?: Record<string, string>;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
scripts?: {[key: string]: string};
dependencies?: {[key: string]: string};
devDependencies?: {[key: string]: string};
[otherKey: string]: unknown;
};
packageFile.scripts = {

View file

@ -33,8 +33,8 @@ export type SidebarEntry =
export type SidebarEntries = {
[key: string]:
| Record<string, unknown>
| Array<Record<string, unknown> | string>;
| {[key: string]: unknown}
| Array<{[key: string]: unknown} | string>;
};
export interface VersionTwoConfig {
@ -58,7 +58,7 @@ export interface VersionTwoConfig {
logo?: {
src?: string;
};
items: Array<Record<string, unknown> | null>;
items: Array<{[key: string]: unknown} | null>;
};
image?: string;
footer: {
@ -74,7 +74,7 @@ export interface VersionTwoConfig {
src?: string;
};
};
algolia?: Record<string, unknown>;
algolia?: {[key: string]: unknown};
};
customFields: {
[key: string]: unknown;
@ -111,16 +111,16 @@ export type VersionOneConfig = {
copyright?: string;
editUrl?: string;
customDocsPath?: string;
users?: Array<Record<string, unknown>>;
users?: Array<{[key: string]: unknown}>;
disableHeaderTitle?: string;
disableTitleTagline?: string;
separateCss?: Array<Record<string, unknown>>;
separateCss?: Array<{[key: string]: unknown}>;
footerIcon?: string;
translationRecruitingLink?: string;
algolia?: Record<string, unknown>;
algolia?: {[key: string]: unknown};
gaTrackingId?: string;
gaGtag?: boolean;
highlight?: Record<string, unknown>;
highlight?: {[key: string]: unknown};
markdownPlugins?: Array<() => void>;
scripts?: Array<{src: string; [key: string]: unknown} | string>;
stylesheets?: Array<{href: string; [key: string]: unknown} | string>;
@ -133,5 +133,5 @@ export type VersionOneConfig = {
ogImage?: string;
cleanUrl?: boolean;
scrollToTop?: boolean;
scrollToTopOptions?: Record<string, unknown>;
scrollToTopOptions?: {[key: string]: unknown};
};

View file

@ -44,13 +44,14 @@ declare module '@generated/routes' {
declare module '@generated/routesChunkNames' {
import type {RouteChunksTree} from '@docusaurus/types';
const routesChunkNames: Record<string, RouteChunksTree>;
const routesChunkNames: {[route: string]: RouteChunksTree};
export = routesChunkNames;
}
declare module '@generated/globalData' {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const globalData: Record<string, any>;
import type {GlobalData} from '@docusaurus/types';
const globalData: GlobalData;
export = globalData;
}
@ -59,20 +60,19 @@ declare module '@generated/i18n' {
defaultLocale: string;
locales: [string, ...string[]];
currentLocale: string;
localeConfigs: Record<
string,
{
localeConfigs: {
[localeName: string]: {
label: string;
direction: string;
htmlLang: string;
}
>;
};
};
};
export = i18n;
}
declare module '@generated/codeTranslations' {
const codeTranslations: Record<string, string>;
const codeTranslations: {[msgId: string]: string};
export = codeTranslations;
}
@ -172,10 +172,9 @@ declare module '@docusaurus/Interpolate' {
? Key | ExtractInterpolatePlaceholders<Rest>
: never;
export type InterpolateValues<
Str extends string,
Value extends ReactNode,
> = Record<ExtractInterpolatePlaceholders<Str>, Value>;
export type InterpolateValues<Str extends string, Value extends ReactNode> = {
[key in ExtractInterpolatePlaceholders<Str>]: Value;
};
// If all the values are plain strings, interpolate returns a simple string
export function interpolate<Str extends string>(
@ -320,17 +319,18 @@ declare module '@docusaurus/renderRoutes' {
}
declare module '@docusaurus/useGlobalData' {
export function useAllPluginInstancesData<T = unknown>(
pluginName: string,
): Record<string, T>;
import type {GlobalData} from '@docusaurus/types';
export function usePluginData<T = unknown>(
export function useAllPluginInstancesData(
pluginName: string,
): GlobalData[string];
export function usePluginData(
pluginName: string,
pluginId?: string,
): T;
): GlobalData[string][string];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function useGlobalData(): Record<string, any>;
export default function useGlobalData(): GlobalData;
}
declare module '*.svg' {

View file

@ -13,7 +13,7 @@ const getCompiledRedirectPageTemplate = _.memoize(() =>
eta.compile(redirectPageTemplate.trim()),
);
function renderRedirectPageTemplate(data: Record<string, unknown>) {
function renderRedirectPageTemplate(data: {toUrl: string}) {
const compiled = getCompiledRedirectPageTemplate();
return compiled(data, eta.defaultConfig);
}

View file

@ -15,11 +15,11 @@ function testField(params: {
fieldName: keyof BlogPostFrontMatter;
validFrontMatters: BlogPostFrontMatter[];
convertibleFrontMatter?: [
ConvertibleFrontMatter: Record<string, unknown>,
ConvertibleFrontMatter: {[key: string]: unknown},
ConvertedFrontMatter: BlogPostFrontMatter,
][];
invalidFrontMatters?: [
InvalidFrontMatter: Record<string, unknown>,
InvalidFrontMatter: {[key: string]: unknown},
ErrorMessage: string,
][];
}) {

View file

@ -15,7 +15,7 @@ import type {
BlogPostFrontMatterAuthors,
} from '@docusaurus/plugin-content-blog';
export type AuthorsMap = Record<string, Author>;
export type AuthorsMap = {[authorKey: string]: Author};
const AuthorsMapSchema = Joi.object<AuthorsMap>()
.pattern(

View file

@ -43,9 +43,9 @@ export function truncate(fileString: string, truncateMarker: RegExp): string {
return fileString.split(truncateMarker, 1).shift()!;
}
export function getSourceToPermalink(
blogPosts: BlogPost[],
): Record<string, string> {
export function getSourceToPermalink(blogPosts: BlogPost[]): {
[aliasedPath: string]: string;
} {
return Object.fromEntries(
blogPosts.map(({metadata: {source, permalink}}) => [source, permalink]),
);

View file

@ -6,7 +6,7 @@
*/
declare module 'remark-admonitions' {
type Options = Record<string, unknown>;
type Options = {[key: string]: unknown};
const plugin: (options?: Options) => void;
export = plugin;

View file

@ -74,8 +74,8 @@ const BlogFrontMatterSchema = Joi.object<BlogPostFrontMatter>({
'{#label} blog frontMatter field is deprecated. Please use {#alternative} instead.',
});
export function validateBlogPostFrontMatter(
frontMatter: Record<string, unknown>,
): BlogPostFrontMatter {
export function validateBlogPostFrontMatter(frontMatter: {
[key: string]: unknown;
}): BlogPostFrontMatter {
return validateFrontMatter(frontMatter, BlogFrontMatterSchema);
}

View file

@ -205,7 +205,7 @@ export default async function pluginContentBlog(
blogTagsListPath,
} = blogContents;
const blogItemsToMetadata: Record<string, BlogPostMetadata> = {};
const blogItemsToMetadata: {[postId: string]: BlogPostMetadata} = {};
const sidebarBlogPosts =
options.blogSidebarCount === 'ALL'
@ -316,7 +316,7 @@ export default async function pluginContentBlog(
return;
}
const tagsModule: Record<string, TagModule> = Object.fromEntries(
const tagsModule: {[tagName: string]: TagModule} = Object.fromEntries(
Object.entries(blogTags).map(([, tag]) => {
const tagModule: TagModule = {
allTagsPath: blogTagsListPath,

View file

@ -232,7 +232,7 @@ declare module '@docusaurus/plugin-content-blog' {
/**
* Front matter, as-is.
*/
readonly frontMatter: BlogPostFrontMatter & Record<string, unknown>;
readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown};
/**
* Tags, normalized.
*/
@ -301,7 +301,7 @@ declare module '@docusaurus/plugin-content-blog' {
/** Markdown content. */
content: string;
/** Front matter. */
frontMatter?: BlogPostFrontMatter & Record<string, unknown>;
frontMatter?: BlogPostFrontMatter & {[key: string]: unknown};
/** Options accepted by ngryman/reading-time. */
options?: ReadingTimeOptions;
}) => number;
@ -402,7 +402,7 @@ declare module '@docusaurus/plugin-content-blog' {
* unlocalized file. Ignored when `editUrl` is a function.
*/
editLocalizedFiles?: boolean;
admonitions: Record<string, unknown>;
admonitions: {[key: string]: unknown};
/** Path to the authors map file, relative to the blog content directory. */
authorsMapPath: string;
/** A callback to customize the reading time number displayed. */
@ -545,7 +545,7 @@ declare module '@theme/BlogTagsListPage' {
/** Blog sidebar. */
readonly sidebar: BlogSidebar;
/** A map from tag names to the full tag module. */
readonly tags: Readonly<Record<string, TagModule>>;
readonly tags: Readonly<{[tagName: string]: TagModule}>;
}
export default function BlogTagsListPage(props: Props): JSX.Element;

View file

@ -50,6 +50,6 @@ export type BlogMarkdownLoaderOptions = {
siteDir: string;
contentPaths: BlogContentPaths;
truncateMarker: RegExp;
sourceToPermalink: Record<string, string>;
sourceToPermalink: {[aliasedPath: string]: string};
onBrokenMarkdownLink: (brokenMarkdownLink: BlogBrokenMarkdownLink) => void;
};

View file

@ -1535,10 +1535,6 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle
"type": "autogenerated",
},
"numberPrefixParser": [Function],
"options": {
"sidebarCollapsed": true,
"sidebarCollapsible": true,
},
"version": {
"contentPath": "docs",
"versionName": "current",

View file

@ -43,7 +43,7 @@ const createFakeDocFile = ({
markdown = 'some markdown content',
}: {
source: string;
frontMatter?: Record<string, string>;
frontMatter?: {[key: string]: string};
markdown?: string;
}): DocFile => {
const content = `---

View file

@ -13,11 +13,11 @@ function testField(params: {
prefix: string;
validFrontMatters: DocFrontMatter[];
convertibleFrontMatter?: [
ConvertibleFrontMatter: Record<string, unknown>,
ConvertibleFrontMatter: {[key: string]: unknown},
ConvertedFrontMatter: DocFrontMatter,
][];
invalidFrontMatters?: [
InvalidFrontMatter: Record<string, unknown>,
InvalidFrontMatter: {[key: string]: unknown},
ErrorMessage: string,
][];
}) {

View file

@ -52,7 +52,7 @@ Available ids are:\n- ${version.docs.map((d) => d.unversionedId).join('\n- ')}`,
const createFakeActions = (contentDir: string) => {
const routeConfigs: RouteConfig[] = [];
const dataContainer: Record<string, unknown> = {};
const dataContainer: {[key: string]: unknown} = {};
const globalDataContainer: {pluginName?: {pluginId: unknown}} = {};
const actions = {

View file

@ -17,7 +17,7 @@ function getCategoryGeneratedIndexMetadata({
}: {
category: SidebarItemCategoryWithGeneratedIndex;
sidebarsUtils: SidebarsUtils;
docsById: Record<string, DocMetadataBase>;
docsById: {[docId: string]: DocMetadataBase};
}): CategoryGeneratedIndexMetadata {
const {sidebarName, previous, next} =
sidebarsUtils.getCategoryGeneratedIndexNavigation(category.link.permalink);

View file

@ -21,7 +21,7 @@ import _ from 'lodash';
describe('docsClientUtils', () => {
it('getActivePlugin', () => {
const data: Record<string, GlobalPluginData> = {
const data: {[key: string]: GlobalPluginData} = {
pluginIosId: {
path: '/ios',
versions: [],

View file

@ -23,11 +23,11 @@ import type {
// ie the docs of that plugin are currently browsed
// it is useful to support multiple docs plugin instances
export function getActivePlugin(
allPluginDatas: Record<string, GlobalPluginData>,
allPluginData: {[pluginId: string]: GlobalPluginData},
pathname: string,
options: GetActivePluginOptions = {},
): ActivePlugin | undefined {
const activeEntry = Object.entries(allPluginDatas)
const activeEntry = Object.entries(allPluginData)
// Route sorting: '/android/foo' should match '/android' instead of '/'
.sort((a, b) => b[1].path.localeCompare(a[1].path))
.find(
@ -46,7 +46,7 @@ export function getActivePlugin(
if (!activePlugin && options.failfast) {
throw new Error(
`Can't find active docs plugin for "${pathname}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(
allPluginDatas,
allPluginData,
)
.map((plugin) => plugin.path)
.join(', ')}`,

View file

@ -31,7 +31,7 @@ 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
export const useAllDocsData = (): Record<string, GlobalPluginData> =>
export const useAllDocsData = (): {[pluginId: string]: GlobalPluginData} =>
useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject;
export const useDocsData = (pluginId: string | undefined): GlobalPluginData =>

View file

@ -6,7 +6,7 @@
*/
declare module 'remark-admonitions' {
type Options = Record<string, unknown>;
type Options = {[key: string]: unknown};
const plugin: (options?: Options) => void;
export = plugin;

View file

@ -424,7 +424,7 @@ export function getDocIds(doc: DocMetadataBase): [string, string] {
// to "id")
export function createDocsByIdIndex<
Doc extends {id: string; unversionedId: string},
>(docs: Doc[]): Record<string, Doc> {
>(docs: Doc[]): {[docId: string]: Doc} {
return Object.fromEntries(
docs.flatMap((doc) => [
[doc.unversionedId, doc],

View file

@ -41,8 +41,8 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
...FrontMatterTOCHeadingLevels,
}).unknown();
export function validateDocFrontMatter(
frontMatter: Record<string, unknown>,
): DocFrontMatter {
export function validateDocFrontMatter(frontMatter: {
[key: string]: unknown;
}): DocFrontMatter {
return validateFrontMatter(frontMatter, DocFrontMatterSchema);
}

View file

@ -40,7 +40,7 @@ function toGlobalDataGeneratedIndex(
function toGlobalSidebars(
sidebars: Sidebars,
version: LoadedVersion,
): Record<string, GlobalSidebar> {
): {[sidebarId: string]: GlobalSidebar} {
const {getFirstLink} = createSidebarsUtils(sidebars);
return _.mapValues(sidebars, (sidebar, sidebarId) => {
const firstLink = getFirstLink(sidebarId);

View file

@ -56,7 +56,6 @@ import type {
PropTagsListPage,
PluginOptions,
} from '@docusaurus/plugin-content-docs';
import type {GlobalPluginData} from '@docusaurus/plugin-content-docs/client';
import {createSidebarsUtils} from './sidebars/utils';
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
@ -293,7 +292,7 @@ export default async function pluginContentDocs(
// TODO tags should be a sub route of the version route
await Promise.all(loadedVersions.map(createVersionTagsRoutes));
setGlobalData<GlobalPluginData>({
setGlobalData({
path: normalizeUrl([baseUrl, options.routeBasePath]),
versions: loadedVersions.map(toGlobalDataVersion),
breadcrumbs,

View file

@ -68,7 +68,7 @@ declare module '@docusaurus/plugin-content-docs' {
};
export type VersionsOptions = {
lastVersion?: string;
versions: Record<string, VersionOptions>;
versions: {[versionName: string]: VersionOptions};
onlyIncludeVersions?: string[];
};
export type SidebarOptions = {
@ -89,7 +89,7 @@ declare module '@docusaurus/plugin-content-docs' {
docTagDocListComponent: string;
docTagsListComponent: string;
docCategoryGeneratedIndexComponent: string;
admonitions: Record<string, unknown>;
admonitions: {[key: string]: unknown};
disableVersioning: boolean;
includeCurrentVersion: boolean;
sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption;
@ -282,7 +282,7 @@ declare module '@docusaurus/plugin-content-docs/client' {
export type ActiveDocContext = {
activeVersion?: GlobalVersion;
activeDoc?: GlobalDoc;
alternateDocVersions: Record<string, GlobalDoc>;
alternateDocVersions: {[versionName: string]: GlobalDoc};
};
export type GlobalDoc = {
id: string;
@ -297,7 +297,7 @@ declare module '@docusaurus/plugin-content-docs/client' {
path: string;
mainDocId: string; // home doc (if docs homepage configured), or first doc
docs: GlobalDoc[];
sidebars?: Record<string, GlobalSidebar>;
sidebars?: {[sidebarId: string]: GlobalSidebar};
};
export type GlobalSidebarLink = {
@ -322,7 +322,7 @@ declare module '@docusaurus/plugin-content-docs/client' {
};
export type GetActivePluginOptions = {failfast?: boolean}; // use fail-fast option if you know for sure one plugin instance is active
export const useAllDocsData: () => Record<string, GlobalPluginData>;
export const useAllDocsData: () => {[pluginId: string]: GlobalPluginData};
export const useDocsData: (pluginId?: string) => GlobalPluginData;
export const useActivePlugin: (
options?: GetActivePluginOptions,

View file

@ -57,7 +57,7 @@ describe('processSidebars', () => {
async function testProcessSidebars(
unprocessedSidebars: NormalizedSidebars,
categoriesMetadata: Record<string, CategoryMetadataFile> = {},
categoriesMetadata: {[filePath: string]: CategoryMetadataFile} = {},
paramsOverrides: Partial<SidebarProcessorParams> = {},
) {
return processSidebars(unprocessedSidebars, categoriesMetadata, {
@ -142,7 +142,6 @@ describe('processSidebars', () => {
},
numberPrefixParser: DefaultNumberPrefixParser,
isCategoryIndex,
options: params.sidebarOptions,
});
expect(StaticSidebarItemsGenerator).toHaveBeenCalledWith({
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
@ -154,7 +153,6 @@ describe('processSidebars', () => {
},
numberPrefixParser: DefaultNumberPrefixParser,
isCategoryIndex,
options: params.sidebarOptions,
});
expect(StaticSidebarItemsGenerator).toHaveBeenCalledWith({
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
@ -166,7 +164,6 @@ describe('processSidebars', () => {
},
numberPrefixParser: DefaultNumberPrefixParser,
isCategoryIndex,
options: params.sidebarOptions,
});
expect(processedSidebar).toEqual({

View file

@ -680,7 +680,7 @@ describe('toNavigationLink', () => {
return {...data, frontMatter: {}} as DocMetadataBase;
}
const docsById: Record<string, DocMetadataBase> = {
const docsById: {[docId: string]: DocMetadataBase} = {
doc1: testDoc({
title: 'Doc 1',
permalink: '/doc1',

View file

@ -48,16 +48,10 @@ function toSidebarItemsGeneratorVersion(
// post-processing checks
async function processSidebar(
unprocessedSidebar: NormalizedSidebar,
categoriesMetadata: Record<string, CategoryMetadataFile>,
categoriesMetadata: {[filePath: string]: CategoryMetadataFile},
params: SidebarProcessorParams,
): Promise<ProcessedSidebar> {
const {
sidebarItemsGenerator,
numberPrefixParser,
docs,
version,
sidebarOptions,
} = params;
const {sidebarItemsGenerator, numberPrefixParser, docs, version} = params;
// Just a minor lazy transformation optimization
const getSidebarItemsGeneratorDocsAndVersion = _.memoize(() => ({
@ -74,7 +68,6 @@ async function processSidebar(
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
isCategoryIndex,
...getSidebarItemsGeneratorDocsAndVersion(),
options: sidebarOptions,
categoriesMetadata,
});
// Process again... weird but sidebar item generated might generate some
@ -113,7 +106,7 @@ async function processSidebar(
export async function processSidebars(
unprocessedSidebars: NormalizedSidebars,
categoriesMetadata: Record<string, CategoryMetadataFile>,
categoriesMetadata: {[filePath: string]: CategoryMetadataFile},
params: SidebarProcessorParams,
): Promise<ProcessedSidebars> {
const processedSidebars = await combinePromises(

View file

@ -15,11 +15,11 @@ import type {
import type {Slugger} from '@docusaurus/utils';
// Makes all properties visible when hovering over the type
type Expand<T extends Record<string, unknown>> = {[P in keyof T]: T[P]};
type Expand<T extends {[x: string]: unknown}> = {[P in keyof T]: T[P]};
export type SidebarItemBase = {
className?: string;
customProps?: Record<string, unknown>;
customProps?: {[key: string]: unknown};
};
export type SidebarItemDoc = SidebarItemBase & {
@ -216,7 +216,7 @@ export type CategoryMetadataFile = {
collapsible?: boolean;
className?: string;
link?: SidebarItemCategoryLinkConfig | null;
customProps?: Record<string, unknown>;
customProps?: {[key: string]: unknown};
// TODO should we allow "items" here? how would this work? would an
// "autogenerated" type be allowed?
@ -247,8 +247,7 @@ export type SidebarItemsGeneratorArgs = {
docs: SidebarItemsGeneratorDoc[];
numberPrefixParser: NumberPrefixParser;
isCategoryIndex: CategoryIndexMatcher;
categoriesMetadata: Record<string, CategoryMetadataFile>;
options: SidebarOptions;
categoriesMetadata: {[filePath: string]: CategoryMetadataFile};
};
export type SidebarItemsGenerator = (
generatorArgs: SidebarItemsGeneratorArgs,

View file

@ -107,15 +107,15 @@ export function collectSidebarNavigation(
});
}
export function collectSidebarsDocIds(
sidebars: Sidebars,
): Record<string, string[]> {
export function collectSidebarsDocIds(sidebars: Sidebars): {
[sidebarId: string]: string[];
} {
return _.mapValues(sidebars, collectSidebarDocIds);
}
export function collectSidebarsNavigations(
sidebars: Sidebars,
): Record<string, SidebarNavigationItem[]> {
export function collectSidebarsNavigations(sidebars: Sidebars): {
[sidebarId: string]: SidebarNavigationItem[];
} {
return _.mapValues(sidebars, collectSidebarNavigation);
}
@ -360,7 +360,7 @@ export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink {
export function toNavigationLink(
navigationItem: SidebarNavigationItem | undefined,
docsById: Record<string, DocMetadataBase>,
docsById: {[docId: string]: DocMetadataBase},
): DocNavLink | undefined {
function getDocById(docId: string) {
const doc = docsById[docId];

View file

@ -149,9 +149,9 @@ function validateSidebarItem(
}
}
export function validateSidebars(
sidebars: Record<string, unknown>,
): asserts sidebars is NormalizedSidebars {
export function validateSidebars(sidebars: {
[sidebarId: string]: unknown;
}): asserts sidebars is NormalizedSidebars {
Object.values(sidebars as NormalizedSidebars).forEach((sidebar) => {
sidebar.forEach(validateSidebarItem);
});

View file

@ -269,7 +269,7 @@ function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles {
}
function translateVersion(
version: LoadedVersion,
translationFiles: Record<string, TranslationFile>,
translationFiles: {[fileName: string]: TranslationFile},
): LoadedVersion {
const versionTranslations =
translationFiles[getVersionFileName(version.versionName)]!.content;
@ -289,7 +289,7 @@ function getVersionsTranslationFiles(
}
function translateVersions(
versions: LoadedVersion[],
translationFiles: Record<string, TranslationFile>,
translationFiles: {[fileName: string]: TranslationFile},
): LoadedVersion[] {
return versions.map((version) => translateVersion(version, translationFiles));
}
@ -303,7 +303,7 @@ export function translateLoadedContent(
loadedContent: LoadedContent,
translationFiles: TranslationFile[],
): LoadedContent {
const translationFilesMap: Record<string, TranslationFile> = _.keyBy(
const translationFilesMap: {[fileName: string]: TranslationFile} = _.keyBy(
translationFiles,
(f) => f.path,
);

View file

@ -59,7 +59,7 @@ export type DocFrontMatter = {
sidebar_label?: string;
sidebar_position?: number;
sidebar_class_name?: string;
sidebar_custom_props?: Record<string, unknown>;
sidebar_custom_props?: {[key: string]: unknown};
displayed_sidebar?: string | null;
pagination_label?: string;
custom_edit_url?: string | null;
@ -83,7 +83,7 @@ export type DocMetadataBase = LastUpdateData & {
sidebarPosition?: number;
editUrl?: string | null;
tags: Tag[];
frontMatter: DocFrontMatter & Record<string, unknown>;
frontMatter: DocFrontMatter & {[key: string]: unknown};
};
export type DocNavLink = {

View file

@ -6,7 +6,7 @@
*/
declare module 'remark-admonitions' {
type Options = Record<string, unknown>;
type Options = {[key: string]: unknown};
const plugin: (options?: Options) => void;
export = plugin;

View file

@ -20,8 +20,8 @@ const PageFrontMatterSchema = Joi.object<FrontMatter>({
...FrontMatterTOCHeadingLevels,
});
export function validatePageFrontMatter(
frontMatter: Record<string, unknown>,
): FrontMatter {
export function validatePageFrontMatter(frontMatter: {
[key: string]: unknown;
}): FrontMatter {
return validateFrontMatter(frontMatter, PageFrontMatterSchema);
}

View file

@ -15,7 +15,7 @@ declare module '@docusaurus/plugin-content-pages' {
include: string[];
exclude: string[];
mdxPageComponent: string;
admonitions: Record<string, unknown>;
admonitions: {[key: string]: unknown};
};
export type Options = Partial<PluginOptions>;
@ -39,7 +39,7 @@ declare module '@docusaurus/plugin-content-pages' {
type: 'mdx';
permalink: string;
source: string;
frontMatter: FrontMatter & Record<string, unknown>;
frontMatter: FrontMatter & {[key: string]: unknown};
title?: string;
description?: string;
};

View file

@ -31,7 +31,7 @@ function PluginContent({
pluginContent,
}: {
pluginName: string;
pluginContent: Record<string, unknown>;
pluginContent: {[pluginId: string]: unknown};
}) {
return (
<section style={{marginBottom: 60}}>

View file

@ -14,7 +14,7 @@ export default (function gtagModule() {
return null;
}
const {trackingID} = globalData['docusaurus-plugin-google-gtag']
const {trackingID} = globalData['docusaurus-plugin-google-gtag']!
.default as PluginOptions;
return {

View file

@ -68,7 +68,7 @@ declare module '@endiliey/react-ideal-image' {
* from material design, Implemented as React components with the SVG
* element. You can customize icons
*/
icons?: Partial<Record<IconKey, ComponentType>>;
icons?: Partial<{[icon in IconKey]: ComponentType}>;
/**
* This prop takes one of the 2 options, xhr and image.
* Read more about it:
@ -102,7 +102,7 @@ declare module '@endiliey/react-ideal-image' {
* inline styles, but it is also possible to use CSS modules and override
* all styles.
*/
theme?: Partial<Record<ThemeKey, string | CSSProperties>>;
theme?: Partial<{[key in ThemeKey]: string | CSSProperties}>;
/**
* Tells how much to wait in milliseconds until consider the download to be
* slow.

View file

@ -0,0 +1,11 @@
```bash npm2yarn
npm install --global docusaurus
```
```bash npm2yarn
npm install --save docusaurus-plugin-name
```
```bash npm2yarn
npm run build
```

View file

@ -48,6 +48,21 @@ import TabItem from '@theme/TabItem';
"
`;
exports[`npm2yarn plugin does not work when language is not set 1`] = `
"\`\`\`npm2yarn
npm install --save docusaurus-plugin-name
\`\`\`
\`\`\`bash
npm install --save docusaurus-plugin-name
\`\`\`
\`\`\`shell
npm install --save docusaurus-plugin-name
\`\`\`
"
`;
exports[`npm2yarn plugin works on installation file 1`] = `
"import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
@ -98,17 +113,29 @@ yarn add docusaurus-plugin-name
"
`;
exports[`npm2yarn plugin works when language is not set 1`] = `
"\`\`\`npm2yarn
npm install --save docusaurus-plugin-name
\`\`\`
exports[`npm2yarn plugin works with sync option 1`] = `
"import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## Installing a plugin
A plugin is usually a npm package, so you install them like other npm packages using npm.
<Tabs groupId=\\"npm2yarn\\">
<TabItem value=\\"npm\\">
\`\`\`bash
npm install --save docusaurus-plugin-name
\`\`\`
\`\`\`shell
npm install --save docusaurus-plugin-name
</TabItem>
<TabItem value=\\"yarn\\" label=\\"Yarn\\">
\`\`\`bash
yarn add docusaurus-plugin-name
\`\`\`
</TabItem>
</Tabs>
"
`;

View file

@ -16,10 +16,7 @@ import mdx from 'remark-mdx';
const processFixture = async (name: string, options?: {sync?: boolean}) => {
const filePath = path.join(__dirname, '__fixtures__', `${name}.md`);
const file = await vfile.read(filePath);
const result = await remark()
.use(mdx)
.use(npm2yarn, {...options, filePath})
.process(file);
const result = await remark().use(mdx).use(npm2yarn, options).process(file);
return result.toString();
};
@ -37,7 +34,13 @@ describe('npm2yarn plugin', () => {
expect(result).toMatchSnapshot();
});
it('works when language is not set', async () => {
it('works with sync option', async () => {
const result = await processFixture('plugin', {sync: true});
expect(result).toMatchSnapshot();
});
it('does not work when language is not set', async () => {
const result = await processFixture('syntax-not-properly-set');
expect(result).toMatchSnapshot();

View file

@ -12,14 +12,14 @@ import {normalizeThemeConfig} from '@docusaurus/utils-validation';
import theme from 'prism-react-renderer/themes/github';
import darkTheme from 'prism-react-renderer/themes/dracula';
function testValidateThemeConfig(partialThemeConfig: Record<string, unknown>) {
function testValidateThemeConfig(partialThemeConfig: {[key: string]: unknown}) {
return normalizeThemeConfig(ThemeConfigSchema, {
...DEFAULT_CONFIG,
...partialThemeConfig,
});
}
function testOk(partialThemeConfig: Record<string, unknown>) {
function testOk(partialThemeConfig: {[key: string]: unknown}) {
expect(
testValidateThemeConfig({...DEFAULT_CONFIG, ...partialThemeConfig}),
).toEqual({

View file

@ -507,7 +507,7 @@ declare module '@theme/MDXComponents' {
readonly h4: (props: ComponentProps<'h4'>) => JSX.Element;
readonly h5: (props: ComponentProps<'h5'>) => JSX.Element;
readonly h6: (props: ComponentProps<'h6'>) => JSX.Element;
} & Record<string, ComponentType<unknown>>;
} & {[tagName: string]: ComponentType<unknown>};
const MDXComponents: MDXComponentsObject;
export default MDXComponents;
@ -768,7 +768,7 @@ declare module '@theme/TabItem' {
readonly label?: string;
readonly hidden?: boolean;
readonly className?: string;
readonly attributes?: Record<string, unknown>;
readonly attributes?: {[key: string]: unknown};
}
export default function TabItem(props: Props): JSX.Element;
@ -786,7 +786,7 @@ declare module '@theme/Tabs' {
readonly values?: readonly {
value: string;
label?: string;
attributes?: Record<string, unknown>;
attributes?: {[key: string]: unknown};
}[];
readonly groupId?: string;
readonly className?: string;

View file

@ -70,10 +70,9 @@ function UnmaintainedVersionLabel({
);
}
const BannerLabelComponents: Record<
VersionBanner,
ComponentType<BannerLabelComponentProps>
> = {
const BannerLabelComponents: {
[banner in VersionBanner]: ComponentType<BannerLabelComponentProps>;
} = {
unreleased: UnreleasedVersionLabel,
unmaintained: UnmaintainedVersionLabel,
};

View file

@ -7,8 +7,9 @@
import React, {isValidElement} from 'react';
import CodeBlock from '@theme/CodeBlock';
import type {Props} from '@theme/MDXComponents/Pre';
export default function MDXPre(props: any) {
export default function MDXPre(props: Props): JSX.Element {
return (
<CodeBlock
// If this pre is created by a ``` fenced codeblock, unwrap the children

View file

@ -14,12 +14,11 @@ import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem
import SearchNavbarItem from '@theme/NavbarItem/SearchNavbarItem';
import type {Types, Props} from '@theme/NavbarItem';
const NavbarItemComponents: Record<
Exclude<Types, undefined>,
const NavbarItemComponents: {
// Not really worth typing, as we pass all props down immediately
// eslint-disable-next-line @typescript-eslint/no-explicit-any
() => (props: any) => JSX.Element
> = {
[type in Exclude<Types, undefined>]: () => (props: any) => JSX.Element;
} = {
default: () => DefaultNavbarItem,
localeDropdown: () => LocaleDropdownNavbarItem,
search: () => SearchNavbarItem,

View file

@ -184,7 +184,7 @@ export function translateThemeConfig({
themeConfig: ThemeConfig;
translationFiles: TranslationFile[];
}): ThemeConfig {
const translationFilesMap: Record<string, TranslationFile> = _.keyBy(
const translationFilesMap: {[fileName: string]: TranslationFile} = _.keyBy(
translationFiles,
(f) => f.path,
);

View file

@ -84,7 +84,7 @@ function readStorageState({
}: {
pluginIds: string[];
versionPersistence: DocsVersionPersistence;
allDocsData: Record<string, GlobalPluginData>;
allDocsData: {[pluginId: string]: GlobalPluginData};
}): DocsPreferredVersionState {
/**
* The storage value we read might be stale, and belong to a version that does
@ -227,10 +227,9 @@ export function useDocsPreferredVersion(
return {preferredVersion, savePreferredVersionName};
}
export function useDocsPreferredVersionByPluginId(): Record<
string,
GlobalVersion | null
> {
export function useDocsPreferredVersionByPluginId(): {
[pluginId: string]: GlobalVersion | null;
} {
const allDocsData = useAllDocsData();
const [state] = useDocsPreferredVersionContext();

View file

@ -37,7 +37,7 @@ function useContextValue(): ContextValue {
useEffect(() => {
try {
const localStorageChoices: Record<string, string> = {};
const localStorageChoices: {[groupId: string]: string} = {};
listStorageKeys().forEach((storageKey) => {
if (storageKey.startsWith(TAB_CHOICE_PREFIX)) {
const groupId = storageKey.substring(TAB_CHOICE_PREFIX.length);

View file

@ -33,11 +33,11 @@ function getTagLetter(tag: string): string {
export function listTagsByLetters(
tags: readonly TagsListItem[],
): TagLetterEntry[] {
const groups: Record<string, TagsListItem[]> = {};
const groups: {[initial: string]: TagsListItem[]} = {};
Object.values(tags).forEach((tag) => {
const letter = getTagLetter(tag.name);
groups[letter] ??= [];
groups[letter]!.push(tag);
const initial = getTagLetter(tag.name);
groups[initial] ??= [];
groups[initial]!.push(tag);
});
return (

View file

@ -17,7 +17,7 @@ export type NavbarItem = {
items?: NavbarItem[];
label?: string;
position?: 'left' | 'right';
} & Record<string, unknown>;
} & {[key: string]: unknown};
export type NavbarLogo = {
src: string;
@ -65,7 +65,7 @@ export type FooterLinkItem = {
href?: string;
html?: string;
prependBaseUrlToHref?: string;
} & Record<string, unknown>;
} & {[key: string]: unknown};
export type FooterLogo = {
alt?: string;
@ -119,7 +119,7 @@ export type ThemeConfig = {
hideableSidebar: boolean;
autoCollapseSidebarCategories: boolean;
image?: string;
metadata: Array<Record<string, string>>;
metadata: Array<{[key: string]: string}>;
sidebarCollapsible: boolean;
tableOfContents: TableOfContents;
};

View file

@ -8,8 +8,8 @@
import type {Joi} from '@docusaurus/utils-validation';
import {validateThemeConfig, DEFAULT_CONFIG} from '../validateThemeConfig';
function testValidateThemeConfig(themeConfig: Record<string, unknown>) {
function validate(schema: Joi.Schema, cfg: Record<string, unknown>) {
function testValidateThemeConfig(themeConfig: {[key: string]: unknown}) {
function validate(schema: Joi.Schema, cfg: {[key: string]: unknown}) {
const {value, error} = schema.validate(cfg, {
convert: false,
});

View file

@ -15,7 +15,7 @@ declare module '@docusaurus/theme-search-algolia' {
appId: string;
apiKey: string;
indexName: string;
searchParameters: Record<string, unknown>;
searchParameters: {[key: string]: unknown};
searchPagePath: string | false | null;
};
};

View file

@ -54,15 +54,16 @@ function useDocsSearchVersionsHelpers() {
// State of the version select menus / algolia facet filters
// docsPluginId -> versionName map
const [searchVersions, setSearchVersions] = useState<Record<string, string>>(
() =>
Object.entries(allDocsData).reduce(
(acc, [pluginId, pluginData]) => ({
...acc,
[pluginId]: pluginData.versions[0]!.name,
}),
{},
),
const [searchVersions, setSearchVersions] = useState<{
[pluginId: string]: string;
}>(() =>
Object.entries(allDocsData).reduce(
(acc, [pluginId, pluginData]) => ({
...acc,
[pluginId]: pluginData.versions[0]!.name,
}),
{},
),
);
// Set the value of a single select menu

View file

@ -26,7 +26,7 @@ describe('theme translations', () => {
(await fs.readJSON(
path.join(baseMessagesDirPath, baseMessagesFile),
'utf-8',
)) as Record<string, string>,
)) as {[key: string]: string},
),
),
).then((translations) =>

View file

@ -39,7 +39,7 @@ export async function readDefaultCodeTranslationMessages({
dirPath?: string;
locale: string;
name: string;
}): Promise<Record<string, string>> {
}): Promise<{[msgId: string]: string}> {
const localesToTry = codeTranslationLocalesToTry(locale);
// Return the content of the first file that match

View file

@ -91,7 +91,7 @@ export type Config = Overwrite<
* package.json.
* - `type: 'synthetic'`, docusaurus generated internal plugin.
*/
export type DocusaurusPluginVersionInformation =
export type PluginVersionInformation =
| {
readonly type: 'package';
readonly name?: string;
@ -104,7 +104,7 @@ export type DocusaurusPluginVersionInformation =
export interface DocusaurusSiteMetadata {
readonly docusaurusVersion: string;
readonly siteVersion?: string;
readonly pluginVersions: Record<string, DocusaurusPluginVersionInformation>;
readonly pluginVersions: {[pluginName: string]: PluginVersionInformation};
}
// Inspired by Chrome JSON, because it's a widely supported i18n format
@ -114,7 +114,7 @@ export interface DocusaurusSiteMetadata {
// https://docs.transifex.com/formats/chrome-json
// https://help.phrase.com/help/chrome-json-messages
export type TranslationMessage = {message: string; description?: string};
export type TranslationFileContent = Record<string, TranslationMessage>;
export type TranslationFileContent = {[key: string]: TranslationMessage};
export type TranslationFile = {path: string; content: TranslationFileContent};
export type TranslationFiles = TranslationFile[];
@ -127,22 +127,24 @@ export type I18nLocaleConfig = {
export type I18nConfig = {
defaultLocale: string;
locales: [string, ...string[]];
localeConfigs: Record<string, Partial<I18nLocaleConfig>>;
localeConfigs: {[locale: string]: Partial<I18nLocaleConfig>};
};
export type I18n = {
defaultLocale: string;
locales: [string, ...string[]];
currentLocale: string;
localeConfigs: Record<string, I18nLocaleConfig>;
localeConfigs: {[locale: string]: I18nLocaleConfig};
};
export type GlobalData = {[pluginName: string]: {[pluginId: string]: unknown}};
export interface DocusaurusContext {
siteConfig: DocusaurusConfig;
siteMetadata: DocusaurusSiteMetadata;
globalData: Record<string, unknown>;
globalData: GlobalData;
i18n: I18n;
codeTranslations: Record<string, string>;
codeTranslations: {[msgId: string]: string};
// Don't put mutable values here, to avoid triggering re-renders
// We could reconsider that choice if context selectors are implemented
@ -162,7 +164,7 @@ export type ImportedPresetModule = PresetModule & {
default?: PresetModule;
};
export type PresetConfig = string | [string, Record<string, unknown>];
export type PresetConfig = string | [string, {[key: string]: unknown}];
export type HostPortCLIOptions = {
host?: string;
@ -207,7 +209,7 @@ export interface LoadContext {
baseUrl: string; // TODO to remove: useless, there's already siteConfig.baseUrl!
i18n: I18n;
ssrTemplate: string;
codeTranslations: Record<string, string>;
codeTranslations: {[msgId: string]: string};
}
export interface InjectedHtmlTags {
@ -228,7 +230,7 @@ export interface Props extends LoadContext, InjectedHtmlTags {
export interface PluginContentLoadedActions {
addRoute: (config: RouteConfig) => void;
createData: (name: string, data: string) => Promise<string>;
setGlobalData: <T = unknown>(data: T) => void;
setGlobalData: (data: unknown) => void;
}
export type AllContent = {
@ -238,7 +240,7 @@ export type AllContent = {
};
// TODO improve type (not exposed by postcss-loader)
export type PostCssOptions = Record<string, unknown> & {plugins: unknown[]};
export type PostCssOptions = {[key: string]: unknown} & {plugins: unknown[]};
export interface Plugin<Content = unknown> {
name: string;
@ -290,7 +292,7 @@ export interface Plugin<Content = unknown> {
export type InitializedPlugin<Content = unknown> = Plugin<Content> & {
readonly options: Required<PluginOptions>;
readonly version: DocusaurusPluginVersionInformation;
readonly version: PluginVersionInformation;
/**
* The absolute path to the folder containing the entry point file.
*/
@ -305,12 +307,12 @@ export type SwizzleAction = 'eject' | 'wrap';
export type SwizzleActionStatus = 'safe' | 'unsafe' | 'forbidden';
export type SwizzleComponentConfig = {
actions: Record<SwizzleAction, SwizzleActionStatus>;
actions: {[action in SwizzleAction]: SwizzleActionStatus};
description?: string;
};
export type SwizzleConfig = {
components: Record<string, SwizzleComponentConfig>;
components: {[componentName: string]: SwizzleComponentConfig};
// Other settings could be added here,
// For example: the ability to declare the config as exhaustive
// so that we can emit errors
@ -332,13 +334,12 @@ export type ImportedPluginModule = PluginModule & {
};
export type ConfigureWebpackFn = Plugin<unknown>['configureWebpack'];
export type ConfigureWebpackFnMergeStrategy = Record<
string,
CustomizeRuleString
>;
export type ConfigureWebpackFnMergeStrategy = {
[key: string]: CustomizeRuleString;
};
export type ConfigurePostCssFn = Plugin<unknown>['configurePostCss'];
export type PluginOptions = {id?: string} & Record<string, unknown>;
export type PluginOptions = {id?: string} & {[key: string]: unknown};
export type PluginConfig =
| string
@ -416,7 +417,7 @@ export interface ConfigureWebpackUtils {
) => RuleSetRule[];
getJSLoader: (options: {
isServer: boolean;
babelOptions?: Record<string, unknown>;
babelOptions?: {[key: string]: unknown};
}) => RuleSetRule;
}
@ -425,7 +426,7 @@ interface HtmlTagObject {
* Attributes of the html tag
* E.g. `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}`
*/
attributes?: Partial<Record<string, string | boolean>>;
attributes?: Partial<{[key: string]: string | boolean}>;
/**
* The tag name e.g. `div`, `script`, `link`, `meta`
*/

View file

@ -77,7 +77,7 @@ export function normalizeThemeConfig<T>(
* Validate front matter with better error message
*/
export function validateFrontMatter<T>(
frontMatter: Record<string, unknown>,
frontMatter: {[key: string]: unknown},
schema: Joi.ObjectSchema<T>,
): T {
const {value, error, warning} = schema.validate(frontMatter, {

View file

@ -12,7 +12,7 @@ import fs from 'fs-extra';
describe('genChunkName', () => {
it('works', () => {
const firstAssert: Record<string, string> = {
const firstAssert: {[key: string]: string} = {
'/docs/adding-blog': 'docs-adding-blog-062',
'/docs/versioning': 'docs-versioning-8a8',
'/': 'index',
@ -34,7 +34,7 @@ describe('genChunkName', () => {
});
it('emits different chunk names for different paths even with same preferred name', () => {
const secondAssert: Record<string, string> = {
const secondAssert: {[key: string]: string} = {
'/blog/1': 'blog-85-f-089',
'/blog/2': 'blog-353-489',
};
@ -44,7 +44,7 @@ describe('genChunkName', () => {
});
it('only generates short unique IDs', () => {
const thirdAssert: Record<string, string> = {
const thirdAssert: {[key: string]: string} = {
a: '0cc175b9',
b: '92eb5ffe',
c: '4a8a08f0',

View file

@ -9,7 +9,7 @@ import {simpleHash, docuHash} from '../hashUtils';
describe('hashUtils', () => {
it('simpleHash', () => {
const asserts: Record<string, string> = {
const asserts: {[key: string]: string} = {
'': 'd41',
'/foo-bar': '096',
'/foo/bar': '1df',
@ -30,7 +30,7 @@ describe('hashUtils', () => {
describe('docuHash', () => {
it('docuHash works', () => {
const asserts: Record<string, string> = {
const asserts: {[key: string]: string} = {
'': '-d41',
'/': 'index',
'/foo-bar': 'foo-bar-096',

View file

@ -45,15 +45,15 @@ describe('mapAsyncSequential', () => {
}
it('maps sequentially', async () => {
const itemToTimeout: Record<string, number> = {
const itemToTimeout: {[key: string]: number} = {
'1': 200,
'2': 600,
'3': 400,
};
const items = Object.keys(itemToTimeout);
const itemMapStartsAt: Record<string, number> = {};
const itemMapEndsAt: Record<string, number> = {};
const itemMapStartsAt: {[key: string]: number} = {};
const itemMapEndsAt: {[key: string]: number} = {};
const timeBefore = Date.now();
await expect(

View file

@ -131,7 +131,7 @@ describe('toMessageRelativeFilePath', () => {
describe('escapePath', () => {
it('works', () => {
const asserts: Record<string, string> = {
const asserts: {[key: string]: string} = {
'c:/aaaa\\bbbb': 'c:/aaaa\\\\bbbb',
'c:\\aaaa\\bbbb\\★': 'c:\\\\aaaa\\\\bbbb\\\\★',
'\\\\?\\c:\\aaaa\\bbbb': '\\\\\\\\?\\\\c:\\\\aaaa\\\\bbbb',
@ -148,7 +148,7 @@ describe('escapePath', () => {
describe('posixPath', () => {
it('works', () => {
const asserts: Record<string, string> = {
const asserts: {[key: string]: string} = {
'c:/aaaa\\bbbb': 'c:/aaaa/bbbb',
'c:\\aaaa\\bbbb\\★': 'c:\\aaaa\\bbbb\\★',
'\\\\?\\c:\\aaaa\\bbbb': '\\\\?\\c:\\aaaa\\bbbb',
@ -165,7 +165,7 @@ describe('posixPath', () => {
describe('aliasedSitePath', () => {
it('works', () => {
const asserts: Record<string, string> = {
const asserts: {[key: string]: string} = {
'user/website/docs/asd.md': '@site/docs/asd.md',
'user/website/versioned_docs/foo/bar.md':
'@site/versioned_docs/foo/bar.md',

View file

@ -170,7 +170,7 @@ describe('getEditUrl', () => {
describe('fileToPath', () => {
it('works', () => {
const asserts: Record<string, string> = {
const asserts: {[key: string]: string} = {
'index.md': '/',
'hello/index.md': '/hello/',
'foo.md': '/foo',

View file

@ -69,7 +69,7 @@ export function replaceMarkdownLinks<T extends ContentPaths>({
/**
* A map from source paths to their URLs. Source paths are `@site` aliased.
*/
sourceToPermalink: Record<string, string>;
sourceToPermalink: {[aliasedPath: string]: string};
}): {
/**
* The content with all Markdown file references replaced with their URLs.

View file

@ -143,7 +143,7 @@ export function createExcerpt(fileString: string): string | undefined {
*/
export function parseFrontMatter(markdownFileContent: string): {
/** Front matter as parsed by gray-matter. */
frontMatter: Record<string, unknown>;
frontMatter: {[key: string]: unknown};
/** The remaining content, trimmed. */
content: string;
} {
@ -244,7 +244,7 @@ export function parseMarkdownString(
options?: ParseMarkdownContentTitleOptions,
): {
/** @see {@link parseFrontMatter} */
frontMatter: Record<string, unknown>;
frontMatter: {[key: string]: unknown};
/** @see {@link parseMarkdownContentTitle} */
contentTitle: string | undefined;
/** @see {@link createExcerpt} */

View file

@ -18,12 +18,12 @@ import prompts from 'prompts';
const isInteractive = process.stdout.isTTY;
const execOptions: Record<string, unknown> = {
encoding: 'utf8',
const execOptions = {
encoding: 'utf8' as const,
stdio: [
'pipe', // stdin (default)
'pipe', // stdout (default)
'ignore', // stderr
'pipe' as const, // stdin (default)
'pipe' as const, // stdout (default)
'ignore' as const, // stderr
],
};
@ -37,19 +37,18 @@ function clearConsole(): void {
// Gets process id of what is on port
function getProcessIdOnPort(port: number): string {
return execSync(`lsof -i:${port} -P -t -sTCP:LISTEN`, execOptions)
.toString()
.split('\n')[0]!
.trim();
}
// Gets process command
function getProcessCommand(processId: string): string {
const command: Buffer = execSync(
const command = execSync(
`ps -o command -p ${processId} | sed -n 2p`,
execOptions,
);
return command.toString().replace(/\n$/, '');
return command.replace(/\n$/, '');
}
// Gets directory of a process from its process id
@ -57,9 +56,7 @@ function getDirectoryOfProcessById(processId: string): string {
return execSync(
`lsof -p ${processId} | awk '$4=="cwd" {for (i=9; i<=NF; i++) printf "%s ", $i}'`,
execOptions,
)
.toString()
.trim();
).trim();
}
// Gets process on port

View file

@ -12,8 +12,8 @@ import prefetchHelper from './prefetch';
import preloadHelper from './preload';
import flat from './flat';
const fetched: Record<string, boolean> = {};
const loaded: Record<string, boolean> = {};
const fetched: {[key: string]: boolean} = {};
const loaded: {[key: string]: boolean} = {};
declare global {
// eslint-disable-next-line camelcase, no-underscore-dangle

View file

@ -13,8 +13,6 @@ import registry from '@generated/registry';
import flat from '../flat';
import {RouteContextProvider} from '../routeContext';
type OptsLoader = Record<string, typeof registry[keyof typeof registry][0]>;
export default function ComponentCreator(
path: string,
hash: string,
@ -40,7 +38,8 @@ export default function ComponentCreator(
const chunkNames = routesChunkNames[chunkNamesKey]!;
const optsModules: string[] = [];
const optsWebpack: string[] = [];
const optsLoader: OptsLoader = {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const optsLoader: {[key: string]: () => Promise<any>} = {};
/* Prepare opts data that react-loadable needs
https://github.com/jamiebuilds/react-loadable#declaring-which-modules-are-being-loaded

View file

@ -7,8 +7,9 @@
import useDocusaurusContext from './useDocusaurusContext';
import {DEFAULT_PLUGIN_ID} from './constants';
import type {GlobalData} from '@docusaurus/types';
export default function useGlobalData(): Record<string, unknown> {
export default function useGlobalData(): GlobalData {
const {globalData} = useDocusaurusContext();
if (!globalData) {
throw new Error('Docusaurus global data not found.');
@ -16,9 +17,9 @@ export default function useGlobalData(): Record<string, unknown> {
return globalData;
}
export function useAllPluginInstancesData<T = unknown>(
export function useAllPluginInstancesData(
pluginName: string,
): Record<string, T> {
): GlobalData[string] {
const globalData = useGlobalData();
const pluginGlobalData = globalData[pluginName];
if (!pluginGlobalData) {
@ -26,13 +27,13 @@ export function useAllPluginInstancesData<T = unknown>(
`Docusaurus plugin global data not found for "${pluginName}" plugin.`,
);
}
return pluginGlobalData as Record<string, T>;
return pluginGlobalData;
}
export function usePluginData<T = unknown>(
export function usePluginData(
pluginName: string,
pluginId: string = DEFAULT_PLUGIN_ID,
): T {
): GlobalData[string][string] {
const pluginGlobalData = useAllPluginInstancesData(pluginName);
const pluginInstanceGlobalData = pluginGlobalData[pluginId];
if (!pluginInstanceGlobalData) {
@ -40,5 +41,5 @@ export function usePluginData<T = unknown>(
`Docusaurus plugin global data not found for "${pluginName}" plugin with id "${pluginId}".`,
);
}
return pluginInstanceGlobalData as T;
return pluginInstanceGlobalData;
}

View file

@ -10,9 +10,11 @@ import type {RouteChunksTree} from '@docusaurus/types';
const isTree = (x: string | RouteChunksTree): x is RouteChunksTree =>
typeof x === 'object' && !!x && Object.keys(x).length > 0;
export default function flat(target: RouteChunksTree): Record<string, string> {
export default function flat(target: RouteChunksTree): {
[keyPath: string]: string;
} {
const delimiter = '.';
const output: Record<string, string> = {};
const output: {[keyPath: string]: string} = {};
function step(object: RouteChunksTree, prefix?: string | number) {
Object.entries(object).forEach(([key, value]) => {

View file

@ -8,7 +8,7 @@
import type {Location} from 'history';
// Memoize previously normalized pathnames.
const pathnames: Record<string, string> = {};
const pathnames: {[rawPathname: string]: string} = {};
export default function normalizeLocation<T extends Location>(location: T): T {
if (pathnames[location.pathname]) {

View file

@ -65,7 +65,7 @@ const supportedPrefetchStrategy = support('prefetch')
? linkPrefetchStrategy
: xhrPrefetchStrategy;
const preFetched: Record<string, boolean> = {};
const preFetched: {[url: string]: boolean} = {};
export default function prefetch(url: string): Promise<void> {
return new Promise((resolve) => {

View file

@ -146,7 +146,7 @@ async function buildLocale({
},
);
const allCollectedLinks: Record<string, string[]> = {};
const allCollectedLinks: {[location: string]: string[]} = {};
let serverConfig: Configuration = await createServerConfig({
props,

View file

@ -29,10 +29,9 @@ export function actionStatusLabel(status: SwizzleActionStatus): string {
return _.capitalize(status);
}
const SwizzleActionStatusColors: Record<
SwizzleActionStatus,
(str: string) => string
> = {
const SwizzleActionStatusColors: {
[status in SwizzleActionStatus]: (str: string) => string;
} = {
safe: logger.green,
unsafe: logger.yellow,
forbidden: logger.red,

View file

@ -17,8 +17,8 @@ declare module 'react-loadable-ssr-addon-v5-slorber' {
export type Manifest = {
entrypoints: string[];
origins: Record<string, number[]>;
assets: Array<Record<string, Asset[]>>;
origins: {[key: string]: number[]};
assets: Array<{[key: string]: Asset[]}>;
};
export function getBundles(
@ -36,7 +36,7 @@ declare module 'react-loadable-ssr-addon-v5-slorber' {
declare module '@slorber/static-site-generator-webpack-plugin' {
export type Locals = {
routesLocation: Record<string, string>;
routesLocation: {[filePath: string]: string};
generatedFilesDir: string;
headTags: string;
preBodyTags: string;
@ -53,7 +53,7 @@ declare module '@slorber/static-site-generator-webpack-plugin' {
locals: Locals;
paths: string[];
preferFoldersOutput?: boolean;
globals: Record<string, unknown>;
globals: {[key: string]: unknown};
});
}

View file

@ -75,9 +75,9 @@ function getAllBrokenLinks({
allCollectedLinks,
routes,
}: {
allCollectedLinks: Record<string, string[]>;
allCollectedLinks: {[location: string]: string[]};
routes: RouteConfig[];
}): Record<string, BrokenLink[]> {
}): {[location: string]: BrokenLink[]} {
const filteredRoutes = filterIntermediateRoutes(routes);
const allBrokenLinks = _.mapValues(allCollectedLinks, (pageLinks, pagePath) =>
@ -88,9 +88,9 @@ function getAllBrokenLinks({
return _.pickBy(allBrokenLinks, (brokenLinks) => brokenLinks.length > 0);
}
function getBrokenLinksErrorMessage(
allBrokenLinks: Record<string, BrokenLink[]>,
): string | undefined {
function getBrokenLinksErrorMessage(allBrokenLinks: {
[location: string]: BrokenLink[];
}): string | undefined {
if (Object.keys(allBrokenLinks).length === 0) {
return undefined;
}
@ -177,8 +177,8 @@ async function filterExistingFileLinks({
}: {
baseUrl: string;
outDir: string;
allCollectedLinks: Record<string, string[]>;
}): Promise<Record<string, string[]>> {
allCollectedLinks: {[location: string]: string[]};
}): Promise<{[location: string]: string[]}> {
async function linkFileExists(link: string) {
// /baseUrl/javadoc/ -> /outDir/javadoc
const baseFilePath = onlyPathname(
@ -222,7 +222,7 @@ export async function handleBrokenLinks({
baseUrl,
outDir,
}: {
allCollectedLinks: Record<string, string[]>;
allCollectedLinks: {[location: string]: string[]};
onBrokenLinks: ReportingSeverity;
routes: RouteConfig[];
baseUrl: string;

View file

@ -404,7 +404,7 @@ ${Object.entries(registry)
JSON.stringify(i18n, null, 2),
);
const codeTranslationsWithFallbacks: Record<string, string> = {
const codeTranslationsWithFallbacks: {[msgId: string]: string} = {
...(await getPluginsDefaultCodeTranslationMessages(plugins)),
...codeTranslations,
};

View file

@ -14,6 +14,7 @@ import type {
PluginContentLoadedActions,
RouteConfig,
AllContent,
GlobalData,
TranslationFiles,
ThemeConfig,
LoadedPlugin,
@ -75,7 +76,7 @@ export async function loadPlugins({
}): Promise<{
plugins: LoadedPlugin[];
pluginsRouteConfigs: RouteConfig[];
globalData: unknown;
globalData: GlobalData;
themeConfigTranslated: ThemeConfig;
}> {
// 1. Plugin Lifecycle - Initialization/Constructor.
@ -135,7 +136,7 @@ export async function loadPlugins({
// 3. Plugin Lifecycle - contentLoaded.
const pluginsRouteConfigs: RouteConfig[] = [];
const globalData: Record<string, Record<string, unknown>> = {};
const globalData: GlobalData = {};
await Promise.all(
contentLoadedTranslatedPlugins.map(

View file

@ -9,7 +9,7 @@ import {createRequire} from 'module';
import path from 'path';
import importFresh from 'import-fresh';
import type {
DocusaurusPluginVersionInformation,
PluginVersionInformation,
ImportedPluginModule,
LoadContext,
PluginModule,
@ -151,7 +151,7 @@ export default async function initPlugins({
async function doGetPluginVersion(
normalizedPluginConfig: NormalizedPluginConfig,
): Promise<DocusaurusPluginVersionInformation> {
): Promise<PluginVersionInformation> {
// get plugin version
if (normalizedPluginConfig.pluginModule?.path) {
const pluginPath = pluginRequire.resolve(
@ -198,8 +198,9 @@ export default async function initPlugins({
async function initializePlugin(
normalizedPluginConfig: NormalizedPluginConfig,
): Promise<InitializedPlugin> {
const pluginVersion: DocusaurusPluginVersionInformation =
await doGetPluginVersion(normalizedPluginConfig);
const pluginVersion: PluginVersionInformation = await doGetPluginVersion(
normalizedPluginConfig,
);
const pluginOptions = doValidatePluginOptions(normalizedPluginConfig);
// Side-effect: merge the normalized theme config in the original one

View file

@ -103,8 +103,8 @@ function isModule(value: unknown): value is Module {
if (
typeof value === 'object' &&
// eslint-disable-next-line no-underscore-dangle
(value as Record<string, unknown>)?.__import &&
(value as Record<string, unknown>)?.path
(value as {[key: string]: unknown})?.__import &&
(value as {[key: string]: unknown})?.path
) {
return true;
}

View file

@ -265,7 +265,7 @@ export async function localizePluginTranslationFile({
export async function getPluginsDefaultCodeTranslationMessages(
plugins: InitializedPlugin[],
): Promise<Record<string, string>> {
): Promise<{[msgId: string]: string}> {
const pluginsMessages = await Promise.all(
plugins.map((plugin) => plugin.getDefaultCodeTranslationMessages?.() ?? {}),
);
@ -280,9 +280,9 @@ export function applyDefaultCodeTranslations({
extractedCodeTranslations,
defaultCodeMessages,
}: {
extractedCodeTranslations: Record<string, TranslationMessage>;
defaultCodeMessages: Record<string, string>;
}): Record<string, TranslationMessage> {
extractedCodeTranslations: {[msgId: string]: TranslationMessage};
defaultCodeMessages: {[msgId: string]: string};
}): {[msgId: string]: TranslationMessage} {
const unusedDefaultCodeMessages = _.difference(
Object.keys(defaultCodeMessages),
Object.keys(extractedCodeTranslations),

View file

@ -130,7 +130,7 @@ function logSourceCodeFileTranslationsWarnings(
type SourceCodeFileTranslations = {
sourceCodeFilePath: string;
translations: Record<string, TranslationMessage>;
translations: {[msgId: string]: TranslationMessage};
warnings: string[];
};
@ -189,7 +189,7 @@ function extractSourceCodeAstTranslations(
Full code: ${generate(node).code}`;
}
const translations: Record<string, TranslationMessage> = {};
const translations: {[msgId: string]: TranslationMessage} = {};
const warnings: string[] = [];
let translateComponentName: string | undefined;
let translateFunctionName: string | undefined;

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import type {DocusaurusPluginVersionInformation} from '@docusaurus/types';
import type {PluginVersionInformation} from '@docusaurus/types';
import fs from 'fs-extra';
import path from 'path';
@ -29,7 +29,7 @@ async function getPackageJsonName(
export async function getPluginVersion(
pluginPath: string,
siteDir: string,
): Promise<DocusaurusPluginVersionInformation> {
): Promise<PluginVersionInformation> {
let potentialPluginPackageJsonDirectory = path.dirname(pluginPath);
while (potentialPluginPackageJsonDirectory !== '/') {
const packageJsonPath = path.join(

View file

@ -44,11 +44,13 @@ export function excludeJS(modulePath: string): boolean {
);
}
export async function getDocusaurusAliases(): Promise<Record<string, string>> {
export async function getDocusaurusAliases(): Promise<{
[aliasName: string]: string;
}> {
const dirPath = path.resolve(__dirname, '../client/exports');
const extensions = ['.js', '.ts', '.tsx'];
const aliases: Record<string, string> = {};
const aliases: {[key: string]: string} = {};
(await fs.readdir(dirPath))
.filter((fileName) => extensions.includes(path.extname(fileName)))

View file

@ -37,7 +37,7 @@ export default async function createServerConfig({
} = props;
const config = await createBaseConfig(props, true);
const routesLocation: Record<string, string> = {};
const routesLocation: {[filePath: string]: string} = {};
// Array of paths to be rendered. Relative to output directory
const ssgPaths = routesPaths.map((str) => {
const ssgPath =

View file

@ -14,7 +14,7 @@ const {version} = require('../package.json');
const ERROR_EXT = `Error: Input file is missing or uses unsupported image format, lqip v${version}`;
const SUPPORTED_MIMES: Record<string, string> = {
const SUPPORTED_MIMES: {[ext: string]: string} = {
jpeg: 'image/jpeg',
jpg: 'image/jpeg',
png: 'image/png',

View file

@ -335,7 +335,7 @@ You can even omit the children prop and specify a translation string in your `co
React hook to access Docusaurus Context. The context contains the `siteConfig` object from [docusaurus.config.js](api/docusaurus.config.js.md) and some additional site metadata.
```ts
type DocusaurusPluginVersionInformation =
type PluginVersionInformation =
| {readonly type: 'package'; readonly version?: string}
| {readonly type: 'project'}
| {readonly type: 'local'}
@ -344,7 +344,7 @@ type DocusaurusPluginVersionInformation =
interface DocusaurusSiteMetadata {
readonly docusaurusVersion: string;
readonly siteVersion?: string;
readonly pluginVersions: Record<string, DocusaurusPluginVersionInformation>;
readonly pluginVersions: Record<string, PluginVersionInformation>;
}
interface I18nLocaleConfig {

View file

@ -74,7 +74,7 @@ export type User = {
// Available tags to assign to your site
// Please choose all tags that you think might apply.
// We'll remove inappropriate tags, but it's less likely that we add tags.
export const Tags: Record<TagType, Tag> = {
export const Tags: {[type in TagType]: Tag} = {
// DO NOT USE THIS TAG: we choose sites to add to favorites
favorite: {
label: 'Favorite',

View file

@ -19,15 +19,14 @@ export type ColorState = {
shades: Shades;
};
export type Shades = Record<
string,
{
export type Shades = {
[cssVar: string]: {
adjustment: number;
adjustmentInput: string;
displayOrder: number;
codeOrder: number;
}
>;
};
};
export const COLOR_SHADES: Shades = {
'--ifm-color-primary': {
adjustment: 0,

View file

@ -335,7 +335,7 @@ You can even omit the children prop and specify a translation string in your `co
React hook to access Docusaurus Context. The context contains the `siteConfig` object from [docusaurus.config.js](api/docusaurus.config.js.md) and some additional site metadata.
```ts
type DocusaurusPluginVersionInformation =
type PluginVersionInformation =
| {readonly type: 'package'; readonly version?: string}
| {readonly type: 'project'}
| {readonly type: 'local'}
@ -344,7 +344,7 @@ type DocusaurusPluginVersionInformation =
interface DocusaurusSiteMetadata {
readonly docusaurusVersion: string;
readonly siteVersion?: string;
readonly pluginVersions: Record<string, DocusaurusPluginVersionInformation>;
readonly pluginVersions: Record<string, PluginVersionInformation>;
}
interface I18nLocaleConfig {

View file

@ -335,7 +335,7 @@ You can even omit the children prop and specify a translation string in your `co
React hook to access Docusaurus Context. The context contains the `siteConfig` object from [docusaurus.config.js](api/docusaurus.config.js.md) and some additional site metadata.
```ts
type DocusaurusPluginVersionInformation =
type PluginVersionInformation =
| {readonly type: 'package'; readonly version?: string}
| {readonly type: 'project'}
| {readonly type: 'local'}
@ -344,7 +344,7 @@ type DocusaurusPluginVersionInformation =
interface DocusaurusSiteMetadata {
readonly docusaurusVersion: string;
readonly siteVersion?: string;
readonly pluginVersions: Record<string, DocusaurusPluginVersionInformation>;
readonly pluginVersions: Record<string, PluginVersionInformation>;
}
interface I18nLocaleConfig {