diff --git a/.eslintrc.js b/.eslintrc.js index f1c1cf99b8..3a755c032e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -69,31 +69,44 @@ module.exports = { 'no-param-reassign': [WARNING, {props: false}], 'no-prototype-builtins': WARNING, 'no-restricted-exports': OFF, - 'no-restricted-imports': [ + 'no-restricted-properties': [ ERROR, - { - paths: [ - { - name: 'lodash', - importNames: [ - // TODO: TS doesn't make Boolean a narrowing function yet, - // so filter(Boolean) is problematic type-wise - // 'compact', - 'filter', - 'flatten', - 'flatMap', - 'map', - 'reduce', - 'take', - 'takeRight', - 'head', - 'tail', - 'initial', - ], - message: 'These APIs have their ES counterparts.', - }, - ], - }, + ...[ + // TODO: TS doesn't make Boolean a narrowing function yet, + // so filter(Boolean) is problematic type-wise + // ['compact', 'Array#filter(Boolean)'], + ['concat', 'Array#concat'], + ['drop', 'Array#slice(n)'], + ['dropRight', 'Array#slice(0, -n)'], + ['fill', 'Array#fill'], + ['filter', 'Array#filter'], + ['find', 'Array#find'], + ['findIndex', 'Array#findIndex'], + ['first', 'foo[0]'], + ['flatten', 'Array#flat'], + ['flattenDeep', 'Array#flat(Infinity)'], + ['flatMap', 'Array#flatMap'], + ['fromPairs', 'Object.fromEntries'], + ['head', 'foo[0]'], + ['indexOf', 'Array#indexOf'], + ['initial', 'Array#slice(0, -1)'], + ['join', 'Array#join'], + // Unfortunately there's no great alternative to _.last yet + // Candidates: foo.slice(-1)[0]; foo[foo.length - 1] + // Array#at is ES2022; could replace _.nth as well + // ['last'], + ['map', 'Array#map'], + ['reduce', 'Array#reduce'], + ['reverse', 'Array#reverse'], + ['slice', 'Array#slice'], + ['take', 'Array#slice(0, n)'], + ['takeRight', 'Array#slice(-n)'], + ['tail', 'Array#slice(1)'], + ].map(([property, alternative]) => ({ + object: '_', + property, + message: `Use ${alternative} instead.`, + })), ], 'no-restricted-syntax': [ WARNING, diff --git a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts index e746242cb8..de06a0b19e 100644 --- a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {uniqBy, difference, groupBy} from 'lodash'; +import _ from 'lodash'; import type { PluginOptions, RedirectOption, @@ -79,7 +79,7 @@ function validateCollectedRedirects( const allowedToPaths = pluginContext.relativeRoutesPaths; const toPaths = redirects.map((redirect) => redirect.to); - const illegalToPaths = difference(toPaths, allowedToPaths); + const illegalToPaths = _.difference(toPaths, allowedToPaths); if (illegalToPaths.length > 0) { throw new Error( `You are trying to create client-side redirections to paths that do not exist: @@ -98,7 +98,7 @@ function filterUnwantedRedirects( ): RedirectMetadata[] { // we don't want to create twice the same redirect // that would lead to writing twice the same html redirection file - Object.entries(groupBy(redirects, (redirect) => redirect.from)).forEach( + Object.entries(_.groupBy(redirects, (redirect) => redirect.from)).forEach( ([from, groupedFromRedirects]) => { if (groupedFromRedirects.length > 1) { logger.error`name=${'@docusaurus/plugin-client-redirects'}: multiple redirects are created with the same "from" pathname: path=${from} @@ -108,7 +108,7 @@ It is not possible to redirect the same pathname to multiple destinations: ${gro } }, ); - const collectedRedirects = uniqBy(redirects, (redirect) => redirect.from); + const collectedRedirects = _.uniqBy(redirects, (redirect) => redirect.from); // We don't want to override an already existing route with a redirect file! const redirectsOverridingExistingPath = collectedRedirects.filter( diff --git a/packages/docusaurus-plugin-client-redirects/src/createRedirectPageContent.ts b/packages/docusaurus-plugin-client-redirects/src/createRedirectPageContent.ts index f55a6e0e56..68d2c5a40d 100644 --- a/packages/docusaurus-plugin-client-redirects/src/createRedirectPageContent.ts +++ b/packages/docusaurus-plugin-client-redirects/src/createRedirectPageContent.ts @@ -7,13 +7,13 @@ import * as eta from 'eta'; import redirectPageTemplate from './templates/redirectPage.template.html'; -import {memoize} from 'lodash'; +import _ from 'lodash'; type CreateRedirectPageOptions = { toUrl: string; }; -const getCompiledRedirectPageTemplate = memoize(() => +const getCompiledRedirectPageTemplate = _.memoize(() => eta.compile(redirectPageTemplate.trim()), ); diff --git a/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts b/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts index 8343cdd794..c89c67f673 100644 --- a/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts +++ b/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts @@ -7,7 +7,7 @@ import fs from 'fs-extra'; import path from 'path'; -import {memoize} from 'lodash'; +import _ from 'lodash'; import type {PluginContext, RedirectMetadata} from './types'; import createRedirectPageContent from './createRedirectPageContent'; @@ -63,7 +63,7 @@ export function toRedirectFilesMetadata( // Perf: avoid rendering the template twice with the exact same "props" // We might create multiple redirect pages for the same destination url // note: the first fn arg is the cache key! - const createPageContentMemoized = memoize((toUrl: string) => + const createPageContentMemoized = _.memoize((toUrl: string) => createRedirectPageContent({toUrl}), ); diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 9c082b3e44..94898473e8 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -8,7 +8,7 @@ import fs from 'fs-extra'; import path from 'path'; import readingTime from 'reading-time'; -import {keyBy, mapValues} from 'lodash'; +import _ from 'lodash'; import type { BlogPost, BlogContentPaths, @@ -46,9 +46,8 @@ export function truncate(fileString: string, truncateMarker: RegExp): string { export function getSourceToPermalink( blogPosts: BlogPost[], ): Record { - return mapValues( - keyBy(blogPosts, (item) => item.metadata.source), - (v) => v.metadata.permalink, + return Object.fromEntries( + blogPosts.map(({metadata: {source, permalink}}) => [source, permalink]), ); } @@ -112,19 +111,16 @@ export function getBlogTags({ (blogPost) => blogPost.metadata.tags, ); - return mapValues(groups, (group) => { - const {tag, items: tagBlogPosts} = group; - return { - name: tag.label, - items: tagBlogPosts.map((item) => item.id), - permalink: tag.permalink, - pages: paginateBlogPosts({ - blogPosts: tagBlogPosts, - basePageUrl: group.tag.permalink, - ...params, - }), - }; - }); + return _.mapValues(groups, ({tag, items: tagBlogPosts}) => ({ + name: tag.label, + items: tagBlogPosts.map((item) => item.id), + permalink: tag.permalink, + pages: paginateBlogPosts({ + blogPosts: tagBlogPosts, + basePageUrl: tag.permalink, + ...params, + }), + })); } const DATE_FILENAME_REGEX = diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index 5ea80609e1..bcbaa522a8 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -8,7 +8,7 @@ import path from 'path'; import {isMatch} from 'picomatch'; import commander from 'commander'; -import {kebabCase, orderBy} from 'lodash'; +import _ from 'lodash'; import fs from 'fs-extra'; import pluginContentDocs from '../index'; @@ -89,7 +89,7 @@ Entries created: checkVersionMetadataPropCreated: (version: LoadedVersion) => { const versionMetadataProp = getCreatedDataByPrefix( - `version-${kebabCase(version.versionName)}-metadata-prop`, + `version-${_.kebabCase(version.versionName)}-metadata-prop`, ); expect(versionMetadataProp.docsSidebars).toEqual(toSidebarsProp(version)); }, @@ -815,7 +815,7 @@ describe('site with custom sidebar items generator', () => { ): SidebarItemsGeneratorOptionArgs { return { ...arg, - docs: orderBy(arg.docs, 'id'), + docs: _.orderBy(arg.docs, 'id'), version: { ...arg.version, contentPath: path.relative(siteDir, arg.version.contentPath), diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts index 0a414d4749..d807103078 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts @@ -17,7 +17,7 @@ import type { GlobalVersion, ActivePlugin, } from '@docusaurus/plugin-content-docs/client'; -import {shuffle} from 'lodash'; +import _ from 'lodash'; describe('docsClientUtils', () => { test('getActivePlugin', () => { @@ -227,7 +227,7 @@ describe('docsClientUtils', () => { }; // shuffle, because order shouldn't matter - const versions: GlobalVersion[] = shuffle([ + const versions: GlobalVersion[] = _.shuffle([ versionNext, version2, version1, @@ -356,7 +356,7 @@ describe('docsClientUtils', () => { }; // shuffle, because order shouldn't matter - const versions: GlobalVersion[] = shuffle([ + const versions: GlobalVersion[] = _.shuffle([ versionNext, version2, version1, diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index 79f692b169..4fd0d8a6e7 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -8,7 +8,6 @@ import path from 'path'; import fs from 'fs-extra'; import logger from '@docusaurus/logger'; -import {keyBy} from 'lodash'; import { aliasedSitePath, getEditUrl, @@ -444,8 +443,10 @@ export function getDocIds(doc: DocMetadataBase): [string, string] { export function createDocsByIdIndex< Doc extends {id: string; unversionedId: string}, >(docs: Doc[]): Record { - return { - ...keyBy(docs, (doc) => doc.unversionedId), - ...keyBy(docs, (doc) => doc.id), - }; + return Object.fromEntries( + docs.flatMap((doc) => [ + [doc.unversionedId, doc], + [doc.id, doc], + ]), + ); } diff --git a/packages/docusaurus-plugin-content-docs/src/globalData.ts b/packages/docusaurus-plugin-content-docs/src/globalData.ts index c97feb340c..9939fb7fca 100644 --- a/packages/docusaurus-plugin-content-docs/src/globalData.ts +++ b/packages/docusaurus-plugin-content-docs/src/globalData.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {mapValues} from 'lodash'; +import _ from 'lodash'; import {normalizeUrl} from '@docusaurus/utils'; import type {Sidebars} from './sidebars/types'; import {createSidebarsUtils} from './sidebars/utils'; @@ -43,7 +43,7 @@ export function toGlobalSidebars( version: LoadedVersion, ): Record { const {getFirstLink} = createSidebarsUtils(sidebars); - return mapValues(sidebars, (sidebar, sidebarId) => { + return _.mapValues(sidebars, (sidebar, sidebarId) => { const firstLink = getFirstLink(sidebarId); if (!firstLink) { return {}; diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 9aeac134bd..fa91c83c8e 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -42,7 +42,6 @@ import type { import type {RuleSetRule} from 'webpack'; import {cliDocsVersionCommand} from './cli'; import {VERSIONS_JSON_FILE} from './constants'; -import {keyBy, mapValues} from 'lodash'; import {toGlobalDataVersion} from './globalData'; import {toTagDocListProp} from './props'; import { @@ -311,9 +310,8 @@ export default async function pluginContentDocs( function getSourceToPermalink(): SourceToPermalink { const allDocs = content.loadedVersions.flatMap((v) => v.docs); - return mapValues( - keyBy(allDocs, (d) => d.source), - (d) => d.permalink, + return Object.fromEntries( + allDocs.map(({source, permalink}) => [source, permalink]), ); } diff --git a/packages/docusaurus-plugin-content-docs/src/props.ts b/packages/docusaurus-plugin-content-docs/src/props.ts index c65efa9e47..0a99bf8f5b 100644 --- a/packages/docusaurus-plugin-content-docs/src/props.ts +++ b/packages/docusaurus-plugin-content-docs/src/props.ts @@ -22,7 +22,7 @@ import type { PropTagDocListDoc, PropSidebarItemLink, } from '@docusaurus/plugin-content-docs'; -import {compact, keyBy, mapValues} from 'lodash'; +import _ from 'lodash'; import {createDocsByIdIndex} from './docs'; export function toSidebarsProp(loadedVersion: LoadedVersion): PropSidebars { @@ -93,18 +93,22 @@ Available document ids are: // Transform the sidebar so that all sidebar item will be in the // form of 'link' or 'category' only. // This is what will be passed as props to the UI component. - return mapValues(loadedVersion.sidebars, (items) => items.map(normalizeItem)); + return _.mapValues(loadedVersion.sidebars, (items) => + items.map(normalizeItem), + ); } function toVersionDocsProp(loadedVersion: LoadedVersion): PropVersionDocs { - return mapValues( - keyBy(loadedVersion.docs, (doc) => doc.unversionedId), - (doc) => ({ - id: doc.unversionedId, - title: doc.title, - description: doc.description, - sidebar: doc.sidebar, - }), + return Object.fromEntries( + loadedVersion.docs.map((doc) => [ + doc.unversionedId, + { + id: doc.unversionedId, + title: doc.title, + description: doc.description, + sidebar: doc.sidebar, + }, + ]), ); } @@ -135,7 +139,7 @@ export function toTagDocListProp({ docs: Pick[]; }): PropTagDocList { function toDocListProp(): PropTagDocListDoc[] { - const list = compact( + const list = _.compact( tag.docIds.map((id) => docs.find((doc) => doc.id === id)), ); // Sort docs by title diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts index 03239e3ec4..a0954cef8c 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts @@ -13,7 +13,7 @@ import type { NormalizedSidebarItem, SidebarItemCategoryLinkConfig, } from './types'; -import {sortBy, last} from 'lodash'; +import _ from 'lodash'; import {addTrailingSlash, posixPath} from '@docusaurus/utils'; import logger from '@docusaurus/logger'; import path from 'path'; @@ -25,7 +25,7 @@ const docIdPrefix = '$doc$/'; // Just an alias to the make code more explicit function getLocalDocId(docId: string): string { - return last(docId.split('/'))!; + return _.last(docId.split('/'))!; } export const CategoryMetadataFilenameBase = '_category_'; @@ -248,7 +248,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({ } return item; }); - const sortedSidebarItems = sortBy( + const sortedSidebarItems = _.sortBy( processedSidebarItems, (item) => item.position, ); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts index 2d095b2096..bdb65f73f7 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts @@ -17,7 +17,7 @@ import {Globby} from '@docusaurus/utils'; import logger from '@docusaurus/logger'; import type {PluginOptions} from '@docusaurus/plugin-content-docs'; import Yaml from 'js-yaml'; -import {groupBy, mapValues} from 'lodash'; +import _ from 'lodash'; import combinePromises from 'combine-promises'; export const DefaultSidebars: SidebarsConfig = { @@ -46,9 +46,9 @@ async function readCategoriesMetadata(contentPath: string) { const categoryFiles = await Globby('**/_category_.{json,yml,yaml}', { cwd: contentPath, }); - const categoryToFile = groupBy(categoryFiles, path.dirname); + const categoryToFile = _.groupBy(categoryFiles, path.dirname); return combinePromises( - mapValues(categoryToFile, async (files, folder) => { + _.mapValues(categoryToFile, async (files, folder) => { const [filePath] = files; if (files.length > 1) { logger.warn`There are more than one category metadata files for path=${folder}: ${files.join( diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/normalization.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/normalization.ts index 60c7b80405..1492ba0970 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/normalization.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/normalization.ts @@ -17,7 +17,7 @@ import type { NormalizedSidebarItemCategory, } from './types'; import {isCategoriesShorthand} from './utils'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; function normalizeCategoriesShorthand( sidebar: SidebarCategoriesShorthand, @@ -81,5 +81,5 @@ function normalizeSidebar(sidebar: SidebarConfig): NormalizedSidebar { export function normalizeSidebars( sidebars: SidebarsConfig, ): NormalizedSidebars { - return mapValues(sidebars, normalizeSidebar); + return _.mapValues(sidebars, normalizeSidebar); } diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts index 7a30354ebd..48dafff60c 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts @@ -15,7 +15,7 @@ import type { ProcessedSidebars, SidebarItemCategoryLink, } from './types'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; function normalizeCategoryLink( category: ProcessedSidebarItemCategory, @@ -88,7 +88,7 @@ export function postProcessSidebars( sidebars: ProcessedSidebars, params: SidebarProcessorParams, ): Sidebars { - return mapValues(sidebars, (sidebar) => + return _.mapValues(sidebars, (sidebar) => sidebar.map((item) => postProcessSidebarItem(item, params)), ); } diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts index f7432222e4..6f99428f6e 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts @@ -21,14 +21,14 @@ import type { } from './types'; import {DefaultSidebarItemsGenerator} from './generator'; import {validateSidebars} from './validation'; -import {mapValues, memoize, pick} from 'lodash'; +import _ from 'lodash'; import combinePromises from 'combine-promises'; import {isCategoryIndex} from '../docs'; function toSidebarItemsGeneratorDoc( doc: DocMetadataBase, ): SidebarItemsGeneratorDoc { - return pick(doc, [ + return _.pick(doc, [ 'id', 'unversionedId', 'frontMatter', @@ -41,7 +41,7 @@ function toSidebarItemsGeneratorDoc( function toSidebarItemsGeneratorVersion( version: VersionMetadata, ): SidebarItemsGeneratorVersion { - return pick(version, ['versionName', 'contentPath']); + return _.pick(version, ['versionName', 'contentPath']); } // Handle the generation of autogenerated sidebar items and other @@ -60,7 +60,7 @@ async function processSidebar( } = params; // Just a minor lazy transformation optimization - const getSidebarItemsGeneratorDocsAndVersion = memoize(() => ({ + const getSidebarItemsGeneratorDocsAndVersion = _.memoize(() => ({ docs: docs.map(toSidebarItemsGeneratorDoc), version: toSidebarItemsGeneratorVersion(version), })); @@ -117,7 +117,7 @@ export async function processSidebars( params: SidebarProcessorParams, ): Promise { const processedSidebars = await combinePromises( - mapValues(unprocessedSidebars, (unprocessedSidebar) => + _.mapValues(unprocessedSidebars, (unprocessedSidebar) => processSidebar(unprocessedSidebar, categoriesMetadata, params), ), ); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts index 8c172e55de..1948c6b09c 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts @@ -19,7 +19,7 @@ import type { SidebarNavigationItem, } from './types'; -import {mapValues, difference, uniq} from 'lodash'; +import _ from 'lodash'; import {getElementsAround, toMessageRelativeFilePath} from '@docusaurus/utils'; import type {DocMetadataBase, DocNavLink} from '../types'; @@ -110,13 +110,13 @@ export function collectSidebarNavigation( export function collectSidebarsDocIds( sidebars: Sidebars, ): Record { - return mapValues(sidebars, collectSidebarDocIds); + return _.mapValues(sidebars, collectSidebarDocIds); } export function collectSidebarsNavigations( sidebars: Sidebars, ): Record { - return mapValues(sidebars, collectSidebarNavigation); + return _.mapValues(sidebars, collectSidebarNavigation); } export type SidebarNavigation = { @@ -276,7 +276,7 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils { function checkSidebarsDocIds(validDocIds: string[], sidebarFilePath: string) { const allSidebarDocIds = Object.values(sidebarNameToDocIds).flat(); - const invalidSidebarDocIds = difference(allSidebarDocIds, validDocIds); + const invalidSidebarDocIds = _.difference(allSidebarDocIds, validDocIds); if (invalidSidebarDocIds.length > 0) { throw new Error( `Invalid sidebar file at "${toMessageRelativeFilePath( @@ -286,7 +286,7 @@ These sidebar document ids do not exist: - ${invalidSidebarDocIds.sort().join('\n- ')} Available document ids are: -- ${uniq(validDocIds).sort().join('\n- ')}`, +- ${_.uniq(validDocIds).sort().join('\n- ')}`, ); } } diff --git a/packages/docusaurus-plugin-content-docs/src/tags.ts b/packages/docusaurus-plugin-content-docs/src/tags.ts index 6d0c9a01f3..005b956bd8 100644 --- a/packages/docusaurus-plugin-content-docs/src/tags.ts +++ b/packages/docusaurus-plugin-content-docs/src/tags.ts @@ -7,11 +7,11 @@ import {groupTaggedItems} from '@docusaurus/utils'; import type {VersionTags, DocMetadata} from './types'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; export function getVersionTags(docs: DocMetadata[]): VersionTags { const groups = groupTaggedItems(docs, (doc) => doc.tags); - return mapValues(groups, (group) => ({ + return _.mapValues(groups, (group) => ({ name: group.tag.label, docIds: group.items.map((item) => item.id), permalink: group.tag.permalink, diff --git a/packages/docusaurus-plugin-content-docs/src/translations.ts b/packages/docusaurus-plugin-content-docs/src/translations.ts index d1d24172b7..47e82cf3a1 100644 --- a/packages/docusaurus-plugin-content-docs/src/translations.ts +++ b/packages/docusaurus-plugin-content-docs/src/translations.ts @@ -13,7 +13,7 @@ import type { Sidebars, } from './sidebars/types'; -import {chain, mapValues, keyBy} from 'lodash'; +import _ from 'lodash'; import { collectSidebarCategories, transformSidebarItems, @@ -146,13 +146,15 @@ function getSidebarTranslationFileContent( ); const links = collectSidebarLinks(sidebar); - const linksContent: TranslationFileContent = chain(links) - .keyBy((link) => `sidebar.${sidebarName}.link.${link.label}`) - .mapValues((link) => ({ - message: link.label, - description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`, - })) - .value(); + const linksContent: TranslationFileContent = Object.fromEntries( + links.map((link) => [ + `sidebar.${sidebarName}.link.${link.label}`, + { + message: link.label, + description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`, + }, + ]), + ); return mergeTranslations([categoryContent, linksContent]); } @@ -230,7 +232,7 @@ function translateSidebars( version: LoadedVersion, sidebarsTranslations: TranslationFileContent, ): Sidebars { - return mapValues(version.sidebars, (sidebar, sidebarName) => + return _.mapValues(version.sidebars, (sidebar, sidebarName) => translateSidebar({ sidebar, sidebarName: getNormalizedSidebarName({ @@ -302,7 +304,7 @@ export function translateLoadedContent( loadedContent: LoadedContent, translationFiles: TranslationFile[], ): LoadedContent { - const translationFilesMap: Record = keyBy( + const translationFilesMap: Record = _.keyBy( translationFiles, (f) => f.path, ); diff --git a/packages/docusaurus-plugin-content-docs/src/versions.ts b/packages/docusaurus-plugin-content-docs/src/versions.ts index 18031cfa9c..f886a93189 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions.ts @@ -28,7 +28,7 @@ import { posixPath, DEFAULT_PLUGIN_ID, } from '@docusaurus/utils'; -import {difference} from 'lodash'; +import _ from 'lodash'; import {resolveSidebarPathOption} from './sidebars'; // retro-compatibility: no prefix for the default plugin id @@ -486,7 +486,7 @@ function checkVersionsOptions( `Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`, ); } - const unknownVersionConfigNames = difference( + const unknownVersionConfigNames = _.difference( Object.keys(options.versions), availableVersionNames, ); @@ -504,7 +504,7 @@ function checkVersionsOptions( `Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`, ); } - const unknownOnlyIncludeVersionNames = difference( + const unknownOnlyIncludeVersionNames = _.difference( options.onlyIncludeVersions, availableVersionNames, ); diff --git a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts index 67a2ec87a2..004594b5e7 100644 --- a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts +++ b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {merge} from 'lodash'; +import _ from 'lodash'; import {ThemeConfigSchema, DEFAULT_CONFIG} from '../validateThemeConfig'; import {normalizeThemeConfig} from '@docusaurus/utils-validation'; @@ -507,7 +507,7 @@ describe('themeConfig', () => { describe('color mode config', () => { const withDefaultValues = (colorMode) => - merge({}, DEFAULT_CONFIG.colorMode, colorMode); + _.merge({}, DEFAULT_CONFIG.colorMode, colorMode); test('minimal config', () => { const colorMode = { diff --git a/packages/docusaurus-theme-classic/src/translations.ts b/packages/docusaurus-theme-classic/src/translations.ts index 0ee15d9def..4fb2b6302b 100644 --- a/packages/docusaurus-theme-classic/src/translations.ts +++ b/packages/docusaurus-theme-classic/src/translations.ts @@ -15,7 +15,7 @@ import type { SimpleFooter, } from '@docusaurus/theme-common'; -import {keyBy, chain} from 'lodash'; +import _ from 'lodash'; import {mergeTranslations} from '@docusaurus/utils'; function getNavbarTranslationFile(navbar: Navbar): TranslationFileContent { @@ -30,15 +30,17 @@ function getNavbarTranslationFile(navbar: Navbar): TranslationFileContent { const allNavbarItems = flattenNavbarItems(navbar.items); - const navbarItemsTranslations: TranslationFileContent = chain( - allNavbarItems.filter((navbarItem) => !!navbarItem.label), - ) - .keyBy((navbarItem) => `item.label.${navbarItem.label}`) - .mapValues((navbarItem) => ({ - message: navbarItem.label!, - description: `Navbar item with label ${navbarItem.label}`, - })) - .value(); + const navbarItemsTranslations: TranslationFileContent = Object.fromEntries( + allNavbarItems + .filter((navbarItem) => navbarItem.label) + .map((navbarItem) => [ + `item.label.${navbarItem.label}`, + { + message: navbarItem.label!, + description: `Navbar item with label ${navbarItem.label}`, + }, + ]), + ); const titleTranslations: TranslationFileContent = navbar.title ? {title: {message: navbar.title, description: 'The title in the navbar'}} @@ -78,33 +80,33 @@ function isMultiColumnFooterLinks( } function getFooterTranslationFile(footer: Footer): TranslationFileContent { - const footerLinkTitles: TranslationFileContent = chain( - isMultiColumnFooterLinks(footer.links) - ? footer.links.filter((link) => !!link.title) - : [], - ) - .keyBy((link) => `link.title.${link.title}`) - .mapValues((link) => ({ - message: link.title!, - description: `The title of the footer links column with title=${link.title} in the footer`, - })) - .value(); + const footerLinkTitles: TranslationFileContent = Object.fromEntries( + (isMultiColumnFooterLinks(footer.links) + ? footer.links.filter((link) => link.title) + : [] + ).map((link) => [ + `link.title.${link.title}`, + { + message: link.title!, + description: `The title of the footer links column with title=${link.title} in the footer`, + }, + ]), + ); - const footerLinkLabels: TranslationFileContent = chain( - isMultiColumnFooterLinks(footer.links) - ? footer.links - .flatMap((link) => link.items) - .filter((link) => !!link.label) - : footer.links.filter((link) => !!link.label), - ) - .keyBy((linkItem) => `link.item.label.${linkItem.label}`) - .mapValues((linkItem) => ({ - message: linkItem.label!, - description: `The label of footer link with label=${ - linkItem.label - } linking to ${linkItem.to ?? linkItem.href}`, - })) - .value(); + const footerLinkLabels: TranslationFileContent = Object.fromEntries( + (isMultiColumnFooterLinks(footer.links) + ? footer.links.flatMap((link) => link.items).filter((link) => link.label) + : footer.links.filter((link) => link.label) + ).map((link) => [ + `link.item.label.${link.label}`, + { + message: link.label!, + description: `The label of footer link with label=${ + link.label + } linking to ${link.to ?? link.href}`, + }, + ]), + ); const copyright: TranslationFileContent = footer.copyright ? { @@ -176,7 +178,7 @@ export function translateThemeConfig({ themeConfig: ThemeConfig; translationFiles: TranslationFile[]; }): ThemeConfig { - const translationFilesMap: Record = keyBy( + const translationFilesMap: Record = _.keyBy( translationFiles, (f) => f.path, ); diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/tagUtils.test.ts b/packages/docusaurus-theme-common/src/utils/__tests__/tagUtils.test.ts index 028ad4f0be..a4ec4d13ce 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/tagUtils.test.ts +++ b/packages/docusaurus-theme-common/src/utils/__tests__/tagUtils.test.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {shuffle} from 'lodash'; +import _ from 'lodash'; import {listTagsByLetters} from '../tagsUtils'; describe('listTagsByLetters', () => { @@ -60,7 +60,9 @@ describe('listTagsByLetters', () => { listTagsByLetters([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1]), ).toEqual(expectedResult); expect( - listTagsByLetters(shuffle([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1])), + listTagsByLetters( + _.shuffle([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1]), + ), ).toEqual(expectedResult); }); }); diff --git a/packages/docusaurus-theme-search-algolia/src/index.ts b/packages/docusaurus-theme-search-algolia/src/index.ts index 90e1fa5b7b..1e38a7a898 100644 --- a/packages/docusaurus-theme-search-algolia/src/index.ts +++ b/packages/docusaurus-theme-search-algolia/src/index.ts @@ -12,12 +12,12 @@ import {normalizeUrl} from '@docusaurus/utils'; import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations'; import logger from '@docusaurus/logger'; import openSearchTemplate from './templates/opensearch'; -import {memoize} from 'lodash'; +import _ from 'lodash'; import type {LoadContext, Plugin} from '@docusaurus/types'; import type {ThemeConfig} from '@docusaurus/theme-search-algolia'; -const getCompiledOpenSearchTemplate = memoize(() => +const getCompiledOpenSearchTemplate = _.memoize(() => compile(openSearchTemplate.trim()), ); diff --git a/packages/docusaurus-theme-translations/__tests__/update.test.ts b/packages/docusaurus-theme-translations/__tests__/update.test.ts index 21a2573e82..b76e11d33a 100644 --- a/packages/docusaurus-theme-translations/__tests__/update.test.ts +++ b/packages/docusaurus-theme-translations/__tests__/update.test.ts @@ -8,7 +8,7 @@ import {extractThemeCodeMessages} from '../update'; import path from 'path'; import fs from 'fs-extra'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; // Seems the 5s default timeout fails sometimes jest.setTimeout(15000); @@ -37,7 +37,7 @@ describe('theme-translations package', () => { .flat() .filter(([key]) => !key.endsWith('___DESCRIPTION')), ); - const codeMessages = mapValues( + const codeMessages = _.mapValues( await extractThemeCodeMessages(), (translation) => translation.message, ); diff --git a/packages/docusaurus-theme-translations/update.js b/packages/docusaurus-theme-translations/update.js index f52bfad87e..e1570edb9a 100644 --- a/packages/docusaurus-theme-translations/update.js +++ b/packages/docusaurus-theme-translations/update.js @@ -11,7 +11,7 @@ const logger = require('@docusaurus/logger').default; const path = require('path'); const fs = require('fs-extra'); -const {mapValues, pickBy, difference, orderBy} = require('lodash'); +const _ = require('lodash'); const LocalesDirPath = path.join(__dirname, 'locales'); const Themes = [ @@ -80,7 +80,7 @@ function removeDescriptionSuffix(key) { */ function sortObjectKeys(obj) { let keys = Object.keys(obj); - keys = orderBy(keys, [(k) => removeDescriptionSuffix(k)]); + keys = _.orderBy(keys, [(k) => removeDescriptionSuffix(k)]); return keys.reduce((acc, key) => { acc[key] = obj[key]; return acc; @@ -179,18 +179,18 @@ const DescriptionSuffix = '___DESCRIPTION'; */ async function updateBaseFile(baseFile, targetDirs) { const baseMessagesWithDescriptions = await readMessagesFile(baseFile); - const baseMessages = pickBy( + const baseMessages = _.pickBy( baseMessagesWithDescriptions, - (_, key) => !key.endsWith(DescriptionSuffix), + (v, key) => !key.endsWith(DescriptionSuffix), ); const codeExtractedTranslations = await extractThemeCodeMessages(targetDirs); - const codeMessages = mapValues( + const codeMessages = _.mapValues( codeExtractedTranslations, (translation) => translation.message, ); - const unknownMessages = difference( + const unknownMessages = _.difference( Object.keys(baseMessages), Object.keys(codeMessages), ); @@ -236,7 +236,7 @@ They won't be removed automatically, so do the cleanup manually if necessary! co async function updateLocaleCodeTranslations(localeFile, baseFileMessages) { const localeFileMessages = await readMessagesFile(localeFile); - const unknownMessages = difference( + const unknownMessages = _.difference( Object.keys(localeFileMessages), Object.keys(baseFileMessages), ); diff --git a/packages/docusaurus-utils/src/__tests__/index.test.ts b/packages/docusaurus-utils/src/__tests__/index.test.ts index 098d6c0cf2..6b84a8b5d6 100644 --- a/packages/docusaurus-utils/src/__tests__/index.test.ts +++ b/packages/docusaurus-utils/src/__tests__/index.test.ts @@ -28,7 +28,7 @@ import { posixPath, readOutputHTMLFile, } from '../index'; -import {sum} from 'lodash'; +import _ from 'lodash'; import fs from 'fs-extra'; import path from 'path'; @@ -322,7 +322,7 @@ describe('mapAsyncSequential', () => { const timeTotal = timeAfter - timeBefore; - const totalTimeouts = sum(Object.values(itemToTimeout)); + const totalTimeouts = _.sum(Object.values(itemToTimeout)); expect(timeTotal).toBeGreaterThanOrEqual(totalTimeouts - 20); expect(itemMapStartsAt['1']).toBeGreaterThanOrEqual(0); diff --git a/packages/docusaurus-utils/src/hashUtils.ts b/packages/docusaurus-utils/src/hashUtils.ts index 40b9bde446..3ebb9bd84e 100644 --- a/packages/docusaurus-utils/src/hashUtils.ts +++ b/packages/docusaurus-utils/src/hashUtils.ts @@ -6,7 +6,7 @@ */ import {createHash} from 'crypto'; -import {kebabCase} from 'lodash'; +import _ from 'lodash'; import {shortName, isNameTooLong} from './pathUtils'; export function md5Hash(str: string): string { @@ -29,9 +29,9 @@ export function docuHash(str: string): string { return 'index'; } const shortHash = simpleHash(str, 3); - const parsedPath = `${kebabCase(str)}-${shortHash}`; + const parsedPath = `${_.kebabCase(str)}-${shortHash}`; if (isNameTooLong(parsedPath)) { - return `${shortName(kebabCase(str))}-${shortHash}`; + return `${shortName(_.kebabCase(str))}-${shortHash}`; } return parsedPath; } diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index 37405ee768..2ae82d7bbb 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -8,7 +8,7 @@ import logger from '@docusaurus/logger'; import path from 'path'; import {createHash} from 'crypto'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; import fs from 'fs-extra'; import {URL} from 'url'; import type { @@ -361,7 +361,7 @@ export function updateTranslationFileMessages( ): TranslationFile { return { ...translationFile, - content: mapValues(translationFile.content, (translation) => ({ + content: _.mapValues(translationFile.content, (translation) => ({ ...translation, message: updateMessage(translation.message), })), diff --git a/packages/docusaurus-utils/src/tags.ts b/packages/docusaurus-utils/src/tags.ts index 64940aef26..4c347faa33 100644 --- a/packages/docusaurus-utils/src/tags.ts +++ b/packages/docusaurus-utils/src/tags.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {kebabCase, uniq, uniqBy} from 'lodash'; +import _ from 'lodash'; import {normalizeUrl} from './urlUtils'; export type Tag = { @@ -22,7 +22,7 @@ export function normalizeFrontMatterTag( function toTagObject(tagString: string): Tag { return { label: tagString, - permalink: kebabCase(tagString), + permalink: _.kebabCase(tagString), }; } @@ -53,7 +53,7 @@ export function normalizeFrontMatterTags( normalizeFrontMatterTag(tagsPath, tag), ); - return uniqBy(tags, (tag) => tag.permalink); + return _.uniqBy(tags, (tag) => tag.permalink); } export type TaggedItemGroup = { @@ -98,7 +98,7 @@ export function groupTaggedItems( // If user add twice the same tag to a md doc (weird but possible), // we don't want the item to appear twice in the list... Object.values(result).forEach((group) => { - group.items = uniq(group.items); + group.items = _.uniq(group.items); }); return result; diff --git a/packages/docusaurus/src/client/serverEntry.tsx b/packages/docusaurus/src/client/serverEntry.tsx index 0388129bc8..7ff4588022 100644 --- a/packages/docusaurus/src/client/serverEntry.tsx +++ b/packages/docusaurus/src/client/serverEntry.tsx @@ -25,13 +25,13 @@ import { } from './LinksCollector'; import logger from '@docusaurus/logger'; // eslint-disable-next-line no-restricted-imports -import {memoize} from 'lodash'; +import _ from 'lodash'; import type {Locals} from '@slorber/static-site-generator-webpack-plugin'; // eslint-disable-next-line @typescript-eslint/no-var-requires const packageJson = require('../../package.json'); -const getCompiledSSRTemplate = memoize((template: string) => +const getCompiledSSRTemplate = _.memoize((template: string) => eta.compile(template.trim(), { rmWhitespace: true, }), diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts index 035a2b5297..706ff325a3 100644 --- a/packages/docusaurus/src/commands/start.ts +++ b/packages/docusaurus/src/commands/start.ts @@ -10,7 +10,7 @@ import logger from '@docusaurus/logger'; import chokidar from 'chokidar'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import path from 'path'; -import {debounce} from 'lodash'; +import _ from 'lodash'; import openBrowser from 'react-dev-utils/openBrowser'; import {prepareUrls} from 'react-dev-utils/WebpackDevServerUtils'; import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware'; @@ -63,7 +63,7 @@ export default async function start( logger.success`Docusaurus website is running at path=${openUrl}.`; // Reload files processing. - const reload = debounce(() => { + const reload = _.debounce(() => { loadSite() .then(({baseUrl: newBaseUrl}) => { const newOpenUrl = normalizeUrl([urls.localUrlForBrowser, newBaseUrl]); diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index 399bd928bf..5d65a521f8 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -13,14 +13,12 @@ import { } from '../i18n'; import {DEFAULT_I18N_CONFIG} from '../configValidation'; import path from 'path'; -import {chain, identity} from 'lodash'; import type {I18nConfig} from '@docusaurus/types'; function testLocaleConfigsFor(locales: string[]) { - return chain(locales) - .keyBy(identity) - .mapValues(getDefaultLocaleConfig) - .value(); + return Object.fromEntries( + locales.map((locale) => [locale, getDefaultLocaleConfig(locale)]), + ); } function loadI18nTest(i18nConfig: I18nConfig, locale?: string) { diff --git a/packages/docusaurus/src/server/brokenLinks.ts b/packages/docusaurus/src/server/brokenLinks.ts index 907b4762a2..84bc87c810 100644 --- a/packages/docusaurus/src/server/brokenLinks.ts +++ b/packages/docusaurus/src/server/brokenLinks.ts @@ -10,7 +10,7 @@ import { type RouteConfig as RRRouteConfig, } from 'react-router-config'; import fs from 'fs-extra'; -import {mapValues, pickBy, countBy} from 'lodash'; +import _ from 'lodash'; import type {RouteConfig, ReportingSeverity} from '@docusaurus/types'; import { removePrefix, @@ -84,12 +84,12 @@ export function getAllBrokenLinks({ }): Record { const filteredRoutes = filterIntermediateRoutes(routes); - const allBrokenLinks = mapValues(allCollectedLinks, (pageLinks, pagePath) => + const allBrokenLinks = _.mapValues(allCollectedLinks, (pageLinks, pagePath) => getPageBrokenLinks({pageLinks, pagePath, routes: filteredRoutes}), ); // remove pages without any broken link - return pickBy(allBrokenLinks, (brokenLinks) => brokenLinks.length > 0); + return _.pickBy(allBrokenLinks, (brokenLinks) => brokenLinks.length > 0); } export function getBrokenLinksErrorMessage( @@ -126,7 +126,7 @@ export function getBrokenLinksErrorMessage( brokenLinks.map((brokenLink) => ({pagePage, brokenLink})), ); - const countedBrokenLinks = countBy( + const countedBrokenLinks = _.countBy( flatList, (item) => item.brokenLink.link, ); @@ -197,7 +197,7 @@ export async function filterExistingFileLinks({ return filePathsToTry.some(isExistingFile); } - return mapValues(allCollectedLinks, (links) => + return _.mapValues(allCollectedLinks, (links) => links.filter((link) => !linkFileExists(link)), ); } diff --git a/packages/docusaurus/src/server/html-tags/htmlTags.ts b/packages/docusaurus/src/server/html-tags/htmlTags.ts index 56d671ec8f..d14dace0a5 100644 --- a/packages/docusaurus/src/server/html-tags/htmlTags.ts +++ b/packages/docusaurus/src/server/html-tags/htmlTags.ts @@ -5,14 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -import {isPlainObject} from 'lodash'; import type {HtmlTagObject} from '@docusaurus/types'; import htmlTags from 'html-tags'; import voidHtmlTags from 'html-tags/void'; import escapeHTML from 'escape-html'; function assertIsHtmlTagObject(val: unknown): asserts val is HtmlTagObject { - if (!isPlainObject(val)) { + if (typeof val !== 'object' || !val) { throw new Error(`"${val}" is not a valid HTML tag object.`); } if (typeof (val as HtmlTagObject).tagName !== 'string') { diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index 8b693284ba..88a2c022ce 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -37,7 +37,7 @@ import { readCodeTranslationFileContent, getPluginsDefaultCodeTranslationMessages, } from './translations/translations'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; import type {RuleSetRule} from 'webpack'; import admonitions from 'remark-admonitions'; import {createRequire} from 'module'; @@ -111,7 +111,7 @@ export async function loadContext( })) ?? {}; // We only need key->message for code translations - const codeTranslations = mapValues( + const codeTranslations = _.mapValues( codeTranslationFileContent, (value) => value.message, ); diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index fc3f354b11..5599e26b60 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -21,7 +21,7 @@ import type { } from '@docusaurus/types'; import initPlugins from './init'; import logger from '@docusaurus/logger'; -import {chain} from 'lodash'; +import _ from 'lodash'; import {localizePluginTranslationFile} from '../translations/translations'; import applyRouteTrailingSlash from './applyRouteTrailingSlash'; @@ -121,10 +121,10 @@ export async function loadPlugins({ }), ); - const allContent: AllContent = chain(loadedPlugins) + const allContent: AllContent = _.chain(loadedPlugins) .groupBy((item) => item.name) .mapValues((nameItems) => - chain(nameItems) + _.chain(nameItems) .groupBy((item) => item.options.id ?? DEFAULT_PLUGIN_ID) .mapValues((idItems) => idItems[0].content) .value(), diff --git a/packages/docusaurus/src/server/plugins/pluginIds.ts b/packages/docusaurus/src/server/plugins/pluginIds.ts index 494dea23fa..bd0635e19c 100644 --- a/packages/docusaurus/src/server/plugins/pluginIds.ts +++ b/packages/docusaurus/src/server/plugins/pluginIds.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {groupBy} from 'lodash'; +import _ from 'lodash'; import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; import type {InitializedPlugin} from '@docusaurus/types'; @@ -14,9 +14,9 @@ import type {InitializedPlugin} from '@docusaurus/types'; export function ensureUniquePluginInstanceIds( plugins: InitializedPlugin[], ): void { - const pluginsByName = groupBy(plugins, (p) => p.name); + const pluginsByName = _.groupBy(plugins, (p) => p.name); Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => { - const pluginInstancesById = groupBy( + const pluginInstancesById = _.groupBy( pluginInstances, (p) => p.options.id ?? DEFAULT_PLUGIN_ID, ); diff --git a/packages/docusaurus/src/server/routes.ts b/packages/docusaurus/src/server/routes.ts index 35ad9af0fd..0c3dcb4acd 100644 --- a/packages/docusaurus/src/server/routes.ts +++ b/packages/docusaurus/src/server/routes.ts @@ -12,7 +12,6 @@ import { simpleHash, escapePath, } from '@docusaurus/utils'; -import {has, isPlainObject, isString} from 'lodash'; import {stringify} from 'querystring'; import type { ChunkRegistry, @@ -85,10 +84,15 @@ const RoutesImportsCode = [ ].join('\n'); function isModule(value: unknown): value is Module { - if (isString(value)) { + if (typeof value === 'string') { return true; } - if (isPlainObject(value) && has(value, '__import') && has(value, 'path')) { + if ( + typeof value === 'object' && + // eslint-disable-next-line no-underscore-dangle + (value as Record)?.__import && + (value as Record)?.path + ) { return true; } return false; @@ -137,11 +141,10 @@ export default async function loadRoutes( ...props } = routeConfig; - if (!isString(routePath) || !component) { + if (typeof routePath !== 'string' || !component) { throw new Error( - `Invalid route config: path must be a string and component is required.\n${JSON.stringify( - routeConfig, - )}`, + `Invalid route config: path must be a string and component is required. +${JSON.stringify(routeConfig)}`, ); } diff --git a/packages/docusaurus/src/server/themes/alias.ts b/packages/docusaurus/src/server/themes/alias.ts index ec6508c046..3ced5b26be 100644 --- a/packages/docusaurus/src/server/themes/alias.ts +++ b/packages/docusaurus/src/server/themes/alias.ts @@ -9,7 +9,7 @@ import fs from 'fs-extra'; import path from 'path'; import {fileToPath, posixPath, normalizeUrl, Globby} from '@docusaurus/utils'; import type {ThemeAliases} from '@docusaurus/types'; -import {sortBy} from 'lodash'; +import _ from 'lodash'; // Order of Webpack aliases is important because one alias can shadow another // This ensure @theme/NavbarItem alias is after @theme/NavbarItem/LocaleDropdown @@ -17,7 +17,7 @@ import {sortBy} from 'lodash'; // See https://github.com/facebook/docusaurus/issues/5382 export function sortAliases(aliases: ThemeAliases): ThemeAliases { // Alphabetical order by default - const entries = sortBy(Object.entries(aliases), ([alias]) => alias); + const entries = _.sortBy(Object.entries(aliases), ([alias]) => alias); // @theme/NavbarItem should be after @theme/NavbarItem/LocaleDropdown entries.sort(([alias1], [alias2]) => alias1.includes(`${alias2}/`) ? -1 : 0, diff --git a/packages/docusaurus/src/server/translations/translations.ts b/packages/docusaurus/src/server/translations/translations.ts index 66f5179a89..ba9ab885f5 100644 --- a/packages/docusaurus/src/server/translations/translations.ts +++ b/packages/docusaurus/src/server/translations/translations.ts @@ -7,7 +7,7 @@ import path from 'path'; import fs from 'fs-extra'; -import {mapValues, difference} from 'lodash'; +import _ from 'lodash'; import type { TranslationFileContent, TranslationFile, @@ -75,7 +75,7 @@ function mergeTranslationFileContent({ options: WriteTranslationsOptions; }): TranslationFileContent { // Apply messagePrefix to all messages - const newContentTransformed = mapValues(newContent, (value) => ({ + const newContentTransformed = _.mapValues(newContent, (value) => ({ ...value, message: `${options.messagePrefix ?? ''}${value.message}`, })); @@ -110,7 +110,7 @@ export async function writeTranslationFileContent({ const existingContent = await readTranslationFileContent(filePath); // Warn about potential legacy keys - const unknownKeys = difference( + const unknownKeys = _.difference( Object.keys(existingContent ?? {}), Object.keys(newContent), ); @@ -276,7 +276,7 @@ export function applyDefaultCodeTranslations({ extractedCodeTranslations: Record; defaultCodeMessages: Record; }): Record { - const unusedDefaultCodeMessages = difference( + const unusedDefaultCodeMessages = _.difference( Object.keys(defaultCodeMessages), Object.keys(extractedCodeTranslations), ); @@ -285,7 +285,7 @@ export function applyDefaultCodeTranslations({ Please report this Docusaurus issue. name=${unusedDefaultCodeMessages}`; } - return mapValues( + return _.mapValues( extractedCodeTranslations, (messageTranslation, messageId) => ({ ...messageTranslation, diff --git a/packages/docusaurus/src/webpack/__tests__/base.test.ts b/packages/docusaurus/src/webpack/__tests__/base.test.ts index ca2ce707c6..14c41df56e 100644 --- a/packages/docusaurus/src/webpack/__tests__/base.test.ts +++ b/packages/docusaurus/src/webpack/__tests__/base.test.ts @@ -15,7 +15,7 @@ import { } from '../base'; import * as utils from '@docusaurus/utils/lib/webpackUtils'; import {posixPath} from '@docusaurus/utils'; -import {mapValues} from 'lodash'; +import _ from 'lodash'; import type {Props, ThemeAliases} from '@docusaurus/types'; describe('babel transpilation exclude logic', () => { @@ -70,7 +70,7 @@ describe('babel transpilation exclude logic', () => { describe('getDocusaurusAliases()', () => { test('return appropriate webpack aliases', () => { // using relative paths makes tests work everywhere - const relativeDocusaurusAliases = mapValues( + const relativeDocusaurusAliases = _.mapValues( getDocusaurusAliases(), (aliasValue) => posixPath(path.relative(__dirname, aliasValue)), ); @@ -125,7 +125,7 @@ describe('base webpack config', () => { const aliases: ThemeAliases = createBaseConfig(props, true).resolve?.alias ?? {}; // Make aliases relative so that test work on all computers - const relativeAliases = mapValues(aliases, (a) => + const relativeAliases = _.mapValues(aliases, (a) => posixPath(path.relative(props.siteDir, a)), ); expect(relativeAliases).toMatchSnapshot(); diff --git a/packages/docusaurus/src/webpack/utils.ts b/packages/docusaurus/src/webpack/utils.ts index acc265eb35..6d7e31b6fa 100644 --- a/packages/docusaurus/src/webpack/utils.ts +++ b/packages/docusaurus/src/webpack/utils.ts @@ -31,7 +31,7 @@ import type { ConfigureWebpackUtils, } from '@docusaurus/types'; import {BABEL_CONFIG_FILE_NAME} from '@docusaurus/utils'; -import {memoize} from 'lodash'; +import _ from 'lodash'; // Utility method to get style loaders export function getStyleLoaders( @@ -164,7 +164,7 @@ export const getCustomizableJSLoader = : jsLoader(isServer); // TODO remove this before end of 2021? -const warnBabelLoaderOnce = memoize(() => { +const warnBabelLoaderOnce = _.memoize(() => { logger.warn`Docusaurus plans to support multiple JS loader strategies (Babel, esbuild...): code=${'getBabelLoader(isServer)'} is now deprecated in favor of code=${'getJSLoader(isServer)'}.`; }); const getBabelLoaderDeprecated = function getBabelLoaderDeprecated( @@ -176,7 +176,7 @@ const getBabelLoaderDeprecated = function getBabelLoaderDeprecated( }; // TODO remove this before end of 2021 ? -const warnCacheLoaderOnce = memoize(() => { +const warnCacheLoaderOnce = _.memoize(() => { logger.warn`Docusaurus uses Webpack 5 and code=${'getCacheLoader()'} usage is now deprecated.`; }); function getCacheLoaderDeprecated() { diff --git a/packages/lqip-loader/src/utils.ts b/packages/lqip-loader/src/utils.ts index 558ddb71a7..a757d28a80 100644 --- a/packages/lqip-loader/src/utils.ts +++ b/packages/lqip-loader/src/utils.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {sortBy} from 'lodash'; +import _ from 'lodash'; import type {Palette} from 'node-vibrant/lib/color'; /** @@ -29,7 +29,7 @@ const toPalette = (swatch: Palette): string[] => { } return result; }, [] as {popularity: number; hex: string}[]); - palette = sortBy(palette, ['popularity']); + palette = _.sortBy(palette, ['popularity']); return palette.map((color) => color.hex).reverse(); };