refactor: ensure lodash is default-imported (#6716)

This commit is contained in:
Joshua Chen 2022-02-19 18:15:02 +08:00 committed by GitHub
parent 47c9a37c5f
commit ea6ceaa371
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 239 additions and 221 deletions

View file

@ -69,31 +69,44 @@ module.exports = {
'no-param-reassign': [WARNING, {props: false}], 'no-param-reassign': [WARNING, {props: false}],
'no-prototype-builtins': WARNING, 'no-prototype-builtins': WARNING,
'no-restricted-exports': OFF, 'no-restricted-exports': OFF,
'no-restricted-imports': [ 'no-restricted-properties': [
ERROR, ERROR,
{ ...[
paths: [
{
name: 'lodash',
importNames: [
// TODO: TS doesn't make Boolean a narrowing function yet, // TODO: TS doesn't make Boolean a narrowing function yet,
// so filter(Boolean) is problematic type-wise // so filter(Boolean) is problematic type-wise
// 'compact', // ['compact', 'Array#filter(Boolean)'],
'filter', ['concat', 'Array#concat'],
'flatten', ['drop', 'Array#slice(n)'],
'flatMap', ['dropRight', 'Array#slice(0, -n)'],
'map', ['fill', 'Array#fill'],
'reduce', ['filter', 'Array#filter'],
'take', ['find', 'Array#find'],
'takeRight', ['findIndex', 'Array#findIndex'],
'head', ['first', 'foo[0]'],
'tail', ['flatten', 'Array#flat'],
'initial', ['flattenDeep', 'Array#flat(Infinity)'],
], ['flatMap', 'Array#flatMap'],
message: 'These APIs have their ES counterparts.', ['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': [ 'no-restricted-syntax': [
WARNING, WARNING,

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {uniqBy, difference, groupBy} from 'lodash'; import _ from 'lodash';
import type { import type {
PluginOptions, PluginOptions,
RedirectOption, RedirectOption,
@ -79,7 +79,7 @@ function validateCollectedRedirects(
const allowedToPaths = pluginContext.relativeRoutesPaths; const allowedToPaths = pluginContext.relativeRoutesPaths;
const toPaths = redirects.map((redirect) => redirect.to); const toPaths = redirects.map((redirect) => redirect.to);
const illegalToPaths = difference(toPaths, allowedToPaths); const illegalToPaths = _.difference(toPaths, allowedToPaths);
if (illegalToPaths.length > 0) { if (illegalToPaths.length > 0) {
throw new Error( throw new Error(
`You are trying to create client-side redirections to paths that do not exist: `You are trying to create client-side redirections to paths that do not exist:
@ -98,7 +98,7 @@ function filterUnwantedRedirects(
): RedirectMetadata[] { ): RedirectMetadata[] {
// we don't want to create twice the same redirect // we don't want to create twice the same redirect
// that would lead to writing twice the same html redirection file // 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]) => { ([from, groupedFromRedirects]) => {
if (groupedFromRedirects.length > 1) { if (groupedFromRedirects.length > 1) {
logger.error`name=${'@docusaurus/plugin-client-redirects'}: multiple redirects are created with the same "from" pathname: path=${from} 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! // We don't want to override an already existing route with a redirect file!
const redirectsOverridingExistingPath = collectedRedirects.filter( const redirectsOverridingExistingPath = collectedRedirects.filter(

View file

@ -7,13 +7,13 @@
import * as eta from 'eta'; import * as eta from 'eta';
import redirectPageTemplate from './templates/redirectPage.template.html'; import redirectPageTemplate from './templates/redirectPage.template.html';
import {memoize} from 'lodash'; import _ from 'lodash';
type CreateRedirectPageOptions = { type CreateRedirectPageOptions = {
toUrl: string; toUrl: string;
}; };
const getCompiledRedirectPageTemplate = memoize(() => const getCompiledRedirectPageTemplate = _.memoize(() =>
eta.compile(redirectPageTemplate.trim()), eta.compile(redirectPageTemplate.trim()),
); );

View file

@ -7,7 +7,7 @@
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import {memoize} from 'lodash'; import _ from 'lodash';
import type {PluginContext, RedirectMetadata} from './types'; import type {PluginContext, RedirectMetadata} from './types';
import createRedirectPageContent from './createRedirectPageContent'; import createRedirectPageContent from './createRedirectPageContent';
@ -63,7 +63,7 @@ export function toRedirectFilesMetadata(
// Perf: avoid rendering the template twice with the exact same "props" // Perf: avoid rendering the template twice with the exact same "props"
// We might create multiple redirect pages for the same destination url // We might create multiple redirect pages for the same destination url
// note: the first fn arg is the cache key! // note: the first fn arg is the cache key!
const createPageContentMemoized = memoize((toUrl: string) => const createPageContentMemoized = _.memoize((toUrl: string) =>
createRedirectPageContent({toUrl}), createRedirectPageContent({toUrl}),
); );

View file

@ -8,7 +8,7 @@
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import readingTime from 'reading-time'; import readingTime from 'reading-time';
import {keyBy, mapValues} from 'lodash'; import _ from 'lodash';
import type { import type {
BlogPost, BlogPost,
BlogContentPaths, BlogContentPaths,
@ -46,9 +46,8 @@ export function truncate(fileString: string, truncateMarker: RegExp): string {
export function getSourceToPermalink( export function getSourceToPermalink(
blogPosts: BlogPost[], blogPosts: BlogPost[],
): Record<string, string> { ): Record<string, string> {
return mapValues( return Object.fromEntries(
keyBy(blogPosts, (item) => item.metadata.source), blogPosts.map(({metadata: {source, permalink}}) => [source, permalink]),
(v) => v.metadata.permalink,
); );
} }
@ -112,19 +111,16 @@ export function getBlogTags({
(blogPost) => blogPost.metadata.tags, (blogPost) => blogPost.metadata.tags,
); );
return mapValues(groups, (group) => { return _.mapValues(groups, ({tag, items: tagBlogPosts}) => ({
const {tag, items: tagBlogPosts} = group;
return {
name: tag.label, name: tag.label,
items: tagBlogPosts.map((item) => item.id), items: tagBlogPosts.map((item) => item.id),
permalink: tag.permalink, permalink: tag.permalink,
pages: paginateBlogPosts({ pages: paginateBlogPosts({
blogPosts: tagBlogPosts, blogPosts: tagBlogPosts,
basePageUrl: group.tag.permalink, basePageUrl: tag.permalink,
...params, ...params,
}), }),
}; }));
});
} }
const DATE_FILENAME_REGEX = const DATE_FILENAME_REGEX =

View file

@ -8,7 +8,7 @@
import path from 'path'; import path from 'path';
import {isMatch} from 'picomatch'; import {isMatch} from 'picomatch';
import commander from 'commander'; import commander from 'commander';
import {kebabCase, orderBy} from 'lodash'; import _ from 'lodash';
import fs from 'fs-extra'; import fs from 'fs-extra';
import pluginContentDocs from '../index'; import pluginContentDocs from '../index';
@ -89,7 +89,7 @@ Entries created:
checkVersionMetadataPropCreated: (version: LoadedVersion) => { checkVersionMetadataPropCreated: (version: LoadedVersion) => {
const versionMetadataProp = getCreatedDataByPrefix( const versionMetadataProp = getCreatedDataByPrefix(
`version-${kebabCase(version.versionName)}-metadata-prop`, `version-${_.kebabCase(version.versionName)}-metadata-prop`,
); );
expect(versionMetadataProp.docsSidebars).toEqual(toSidebarsProp(version)); expect(versionMetadataProp.docsSidebars).toEqual(toSidebarsProp(version));
}, },
@ -815,7 +815,7 @@ describe('site with custom sidebar items generator', () => {
): SidebarItemsGeneratorOptionArgs { ): SidebarItemsGeneratorOptionArgs {
return { return {
...arg, ...arg,
docs: orderBy(arg.docs, 'id'), docs: _.orderBy(arg.docs, 'id'),
version: { version: {
...arg.version, ...arg.version,
contentPath: path.relative(siteDir, arg.version.contentPath), contentPath: path.relative(siteDir, arg.version.contentPath),

View file

@ -17,7 +17,7 @@ import type {
GlobalVersion, GlobalVersion,
ActivePlugin, ActivePlugin,
} from '@docusaurus/plugin-content-docs/client'; } from '@docusaurus/plugin-content-docs/client';
import {shuffle} from 'lodash'; import _ from 'lodash';
describe('docsClientUtils', () => { describe('docsClientUtils', () => {
test('getActivePlugin', () => { test('getActivePlugin', () => {
@ -227,7 +227,7 @@ describe('docsClientUtils', () => {
}; };
// shuffle, because order shouldn't matter // shuffle, because order shouldn't matter
const versions: GlobalVersion[] = shuffle([ const versions: GlobalVersion[] = _.shuffle([
versionNext, versionNext,
version2, version2,
version1, version1,
@ -356,7 +356,7 @@ describe('docsClientUtils', () => {
}; };
// shuffle, because order shouldn't matter // shuffle, because order shouldn't matter
const versions: GlobalVersion[] = shuffle([ const versions: GlobalVersion[] = _.shuffle([
versionNext, versionNext,
version2, version2,
version1, version1,

View file

@ -8,7 +8,6 @@
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import {keyBy} from 'lodash';
import { import {
aliasedSitePath, aliasedSitePath,
getEditUrl, getEditUrl,
@ -444,8 +443,10 @@ export function getDocIds(doc: DocMetadataBase): [string, string] {
export function createDocsByIdIndex< export function createDocsByIdIndex<
Doc extends {id: string; unversionedId: string}, Doc extends {id: string; unversionedId: string},
>(docs: Doc[]): Record<string, Doc> { >(docs: Doc[]): Record<string, Doc> {
return { return Object.fromEntries(
...keyBy(docs, (doc) => doc.unversionedId), docs.flatMap((doc) => [
...keyBy(docs, (doc) => doc.id), [doc.unversionedId, doc],
}; [doc.id, doc],
]),
);
} }

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {mapValues} from 'lodash'; import _ from 'lodash';
import {normalizeUrl} from '@docusaurus/utils'; import {normalizeUrl} from '@docusaurus/utils';
import type {Sidebars} from './sidebars/types'; import type {Sidebars} from './sidebars/types';
import {createSidebarsUtils} from './sidebars/utils'; import {createSidebarsUtils} from './sidebars/utils';
@ -43,7 +43,7 @@ export function toGlobalSidebars(
version: LoadedVersion, version: LoadedVersion,
): Record<string, GlobalSidebar> { ): Record<string, GlobalSidebar> {
const {getFirstLink} = createSidebarsUtils(sidebars); const {getFirstLink} = createSidebarsUtils(sidebars);
return mapValues(sidebars, (sidebar, sidebarId) => { return _.mapValues(sidebars, (sidebar, sidebarId) => {
const firstLink = getFirstLink(sidebarId); const firstLink = getFirstLink(sidebarId);
if (!firstLink) { if (!firstLink) {
return {}; return {};

View file

@ -42,7 +42,6 @@ import type {
import type {RuleSetRule} from 'webpack'; import type {RuleSetRule} from 'webpack';
import {cliDocsVersionCommand} from './cli'; import {cliDocsVersionCommand} from './cli';
import {VERSIONS_JSON_FILE} from './constants'; import {VERSIONS_JSON_FILE} from './constants';
import {keyBy, mapValues} from 'lodash';
import {toGlobalDataVersion} from './globalData'; import {toGlobalDataVersion} from './globalData';
import {toTagDocListProp} from './props'; import {toTagDocListProp} from './props';
import { import {
@ -311,9 +310,8 @@ export default async function pluginContentDocs(
function getSourceToPermalink(): SourceToPermalink { function getSourceToPermalink(): SourceToPermalink {
const allDocs = content.loadedVersions.flatMap((v) => v.docs); const allDocs = content.loadedVersions.flatMap((v) => v.docs);
return mapValues( return Object.fromEntries(
keyBy(allDocs, (d) => d.source), allDocs.map(({source, permalink}) => [source, permalink]),
(d) => d.permalink,
); );
} }

View file

@ -22,7 +22,7 @@ import type {
PropTagDocListDoc, PropTagDocListDoc,
PropSidebarItemLink, PropSidebarItemLink,
} from '@docusaurus/plugin-content-docs'; } from '@docusaurus/plugin-content-docs';
import {compact, keyBy, mapValues} from 'lodash'; import _ from 'lodash';
import {createDocsByIdIndex} from './docs'; import {createDocsByIdIndex} from './docs';
export function toSidebarsProp(loadedVersion: LoadedVersion): PropSidebars { 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 // Transform the sidebar so that all sidebar item will be in the
// form of 'link' or 'category' only. // form of 'link' or 'category' only.
// This is what will be passed as props to the UI component. // 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 { function toVersionDocsProp(loadedVersion: LoadedVersion): PropVersionDocs {
return mapValues( return Object.fromEntries(
keyBy(loadedVersion.docs, (doc) => doc.unversionedId), loadedVersion.docs.map((doc) => [
(doc) => ({ doc.unversionedId,
{
id: doc.unversionedId, id: doc.unversionedId,
title: doc.title, title: doc.title,
description: doc.description, description: doc.description,
sidebar: doc.sidebar, sidebar: doc.sidebar,
}), },
]),
); );
} }
@ -135,7 +139,7 @@ export function toTagDocListProp({
docs: Pick<DocMetadata, 'id' | 'title' | 'description' | 'permalink'>[]; docs: Pick<DocMetadata, 'id' | 'title' | 'description' | 'permalink'>[];
}): PropTagDocList { }): PropTagDocList {
function toDocListProp(): PropTagDocListDoc[] { function toDocListProp(): PropTagDocListDoc[] {
const list = compact( const list = _.compact(
tag.docIds.map((id) => docs.find((doc) => doc.id === id)), tag.docIds.map((id) => docs.find((doc) => doc.id === id)),
); );
// Sort docs by title // Sort docs by title

View file

@ -13,7 +13,7 @@ import type {
NormalizedSidebarItem, NormalizedSidebarItem,
SidebarItemCategoryLinkConfig, SidebarItemCategoryLinkConfig,
} from './types'; } from './types';
import {sortBy, last} from 'lodash'; import _ from 'lodash';
import {addTrailingSlash, posixPath} from '@docusaurus/utils'; import {addTrailingSlash, posixPath} from '@docusaurus/utils';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import path from 'path'; import path from 'path';
@ -25,7 +25,7 @@ const docIdPrefix = '$doc$/';
// Just an alias to the make code more explicit // Just an alias to the make code more explicit
function getLocalDocId(docId: string): string { function getLocalDocId(docId: string): string {
return last(docId.split('/'))!; return _.last(docId.split('/'))!;
} }
export const CategoryMetadataFilenameBase = '_category_'; export const CategoryMetadataFilenameBase = '_category_';
@ -248,7 +248,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
} }
return item; return item;
}); });
const sortedSidebarItems = sortBy( const sortedSidebarItems = _.sortBy(
processedSidebarItems, processedSidebarItems,
(item) => item.position, (item) => item.position,
); );

View file

@ -17,7 +17,7 @@ import {Globby} from '@docusaurus/utils';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import type {PluginOptions} from '@docusaurus/plugin-content-docs'; import type {PluginOptions} from '@docusaurus/plugin-content-docs';
import Yaml from 'js-yaml'; import Yaml from 'js-yaml';
import {groupBy, mapValues} from 'lodash'; import _ from 'lodash';
import combinePromises from 'combine-promises'; import combinePromises from 'combine-promises';
export const DefaultSidebars: SidebarsConfig = { export const DefaultSidebars: SidebarsConfig = {
@ -46,9 +46,9 @@ async function readCategoriesMetadata(contentPath: string) {
const categoryFiles = await Globby('**/_category_.{json,yml,yaml}', { const categoryFiles = await Globby('**/_category_.{json,yml,yaml}', {
cwd: contentPath, cwd: contentPath,
}); });
const categoryToFile = groupBy(categoryFiles, path.dirname); const categoryToFile = _.groupBy(categoryFiles, path.dirname);
return combinePromises( return combinePromises(
mapValues(categoryToFile, async (files, folder) => { _.mapValues(categoryToFile, async (files, folder) => {
const [filePath] = files; const [filePath] = files;
if (files.length > 1) { if (files.length > 1) {
logger.warn`There are more than one category metadata files for path=${folder}: ${files.join( logger.warn`There are more than one category metadata files for path=${folder}: ${files.join(

View file

@ -17,7 +17,7 @@ import type {
NormalizedSidebarItemCategory, NormalizedSidebarItemCategory,
} from './types'; } from './types';
import {isCategoriesShorthand} from './utils'; import {isCategoriesShorthand} from './utils';
import {mapValues} from 'lodash'; import _ from 'lodash';
function normalizeCategoriesShorthand( function normalizeCategoriesShorthand(
sidebar: SidebarCategoriesShorthand, sidebar: SidebarCategoriesShorthand,
@ -81,5 +81,5 @@ function normalizeSidebar(sidebar: SidebarConfig): NormalizedSidebar {
export function normalizeSidebars( export function normalizeSidebars(
sidebars: SidebarsConfig, sidebars: SidebarsConfig,
): NormalizedSidebars { ): NormalizedSidebars {
return mapValues(sidebars, normalizeSidebar); return _.mapValues(sidebars, normalizeSidebar);
} }

View file

@ -15,7 +15,7 @@ import type {
ProcessedSidebars, ProcessedSidebars,
SidebarItemCategoryLink, SidebarItemCategoryLink,
} from './types'; } from './types';
import {mapValues} from 'lodash'; import _ from 'lodash';
function normalizeCategoryLink( function normalizeCategoryLink(
category: ProcessedSidebarItemCategory, category: ProcessedSidebarItemCategory,
@ -88,7 +88,7 @@ export function postProcessSidebars(
sidebars: ProcessedSidebars, sidebars: ProcessedSidebars,
params: SidebarProcessorParams, params: SidebarProcessorParams,
): Sidebars { ): Sidebars {
return mapValues(sidebars, (sidebar) => return _.mapValues(sidebars, (sidebar) =>
sidebar.map((item) => postProcessSidebarItem(item, params)), sidebar.map((item) => postProcessSidebarItem(item, params)),
); );
} }

View file

@ -21,14 +21,14 @@ import type {
} from './types'; } from './types';
import {DefaultSidebarItemsGenerator} from './generator'; import {DefaultSidebarItemsGenerator} from './generator';
import {validateSidebars} from './validation'; import {validateSidebars} from './validation';
import {mapValues, memoize, pick} from 'lodash'; import _ from 'lodash';
import combinePromises from 'combine-promises'; import combinePromises from 'combine-promises';
import {isCategoryIndex} from '../docs'; import {isCategoryIndex} from '../docs';
function toSidebarItemsGeneratorDoc( function toSidebarItemsGeneratorDoc(
doc: DocMetadataBase, doc: DocMetadataBase,
): SidebarItemsGeneratorDoc { ): SidebarItemsGeneratorDoc {
return pick(doc, [ return _.pick(doc, [
'id', 'id',
'unversionedId', 'unversionedId',
'frontMatter', 'frontMatter',
@ -41,7 +41,7 @@ function toSidebarItemsGeneratorDoc(
function toSidebarItemsGeneratorVersion( function toSidebarItemsGeneratorVersion(
version: VersionMetadata, version: VersionMetadata,
): SidebarItemsGeneratorVersion { ): SidebarItemsGeneratorVersion {
return pick(version, ['versionName', 'contentPath']); return _.pick(version, ['versionName', 'contentPath']);
} }
// Handle the generation of autogenerated sidebar items and other // Handle the generation of autogenerated sidebar items and other
@ -60,7 +60,7 @@ async function processSidebar(
} = params; } = params;
// Just a minor lazy transformation optimization // Just a minor lazy transformation optimization
const getSidebarItemsGeneratorDocsAndVersion = memoize(() => ({ const getSidebarItemsGeneratorDocsAndVersion = _.memoize(() => ({
docs: docs.map(toSidebarItemsGeneratorDoc), docs: docs.map(toSidebarItemsGeneratorDoc),
version: toSidebarItemsGeneratorVersion(version), version: toSidebarItemsGeneratorVersion(version),
})); }));
@ -117,7 +117,7 @@ export async function processSidebars(
params: SidebarProcessorParams, params: SidebarProcessorParams,
): Promise<ProcessedSidebars> { ): Promise<ProcessedSidebars> {
const processedSidebars = await combinePromises( const processedSidebars = await combinePromises(
mapValues(unprocessedSidebars, (unprocessedSidebar) => _.mapValues(unprocessedSidebars, (unprocessedSidebar) =>
processSidebar(unprocessedSidebar, categoriesMetadata, params), processSidebar(unprocessedSidebar, categoriesMetadata, params),
), ),
); );

View file

@ -19,7 +19,7 @@ import type {
SidebarNavigationItem, SidebarNavigationItem,
} from './types'; } from './types';
import {mapValues, difference, uniq} from 'lodash'; import _ from 'lodash';
import {getElementsAround, toMessageRelativeFilePath} from '@docusaurus/utils'; import {getElementsAround, toMessageRelativeFilePath} from '@docusaurus/utils';
import type {DocMetadataBase, DocNavLink} from '../types'; import type {DocMetadataBase, DocNavLink} from '../types';
@ -110,13 +110,13 @@ export function collectSidebarNavigation(
export function collectSidebarsDocIds( export function collectSidebarsDocIds(
sidebars: Sidebars, sidebars: Sidebars,
): Record<string, string[]> { ): Record<string, string[]> {
return mapValues(sidebars, collectSidebarDocIds); return _.mapValues(sidebars, collectSidebarDocIds);
} }
export function collectSidebarsNavigations( export function collectSidebarsNavigations(
sidebars: Sidebars, sidebars: Sidebars,
): Record<string, SidebarNavigationItem[]> { ): Record<string, SidebarNavigationItem[]> {
return mapValues(sidebars, collectSidebarNavigation); return _.mapValues(sidebars, collectSidebarNavigation);
} }
export type SidebarNavigation = { export type SidebarNavigation = {
@ -276,7 +276,7 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
function checkSidebarsDocIds(validDocIds: string[], sidebarFilePath: string) { function checkSidebarsDocIds(validDocIds: string[], sidebarFilePath: string) {
const allSidebarDocIds = Object.values(sidebarNameToDocIds).flat(); const allSidebarDocIds = Object.values(sidebarNameToDocIds).flat();
const invalidSidebarDocIds = difference(allSidebarDocIds, validDocIds); const invalidSidebarDocIds = _.difference(allSidebarDocIds, validDocIds);
if (invalidSidebarDocIds.length > 0) { if (invalidSidebarDocIds.length > 0) {
throw new Error( throw new Error(
`Invalid sidebar file at "${toMessageRelativeFilePath( `Invalid sidebar file at "${toMessageRelativeFilePath(
@ -286,7 +286,7 @@ These sidebar document ids do not exist:
- ${invalidSidebarDocIds.sort().join('\n- ')} - ${invalidSidebarDocIds.sort().join('\n- ')}
Available document ids are: Available document ids are:
- ${uniq(validDocIds).sort().join('\n- ')}`, - ${_.uniq(validDocIds).sort().join('\n- ')}`,
); );
} }
} }

View file

@ -7,11 +7,11 @@
import {groupTaggedItems} from '@docusaurus/utils'; import {groupTaggedItems} from '@docusaurus/utils';
import type {VersionTags, DocMetadata} from './types'; import type {VersionTags, DocMetadata} from './types';
import {mapValues} from 'lodash'; import _ from 'lodash';
export function getVersionTags(docs: DocMetadata[]): VersionTags { export function getVersionTags(docs: DocMetadata[]): VersionTags {
const groups = groupTaggedItems(docs, (doc) => doc.tags); const groups = groupTaggedItems(docs, (doc) => doc.tags);
return mapValues(groups, (group) => ({ return _.mapValues(groups, (group) => ({
name: group.tag.label, name: group.tag.label,
docIds: group.items.map((item) => item.id), docIds: group.items.map((item) => item.id),
permalink: group.tag.permalink, permalink: group.tag.permalink,

View file

@ -13,7 +13,7 @@ import type {
Sidebars, Sidebars,
} from './sidebars/types'; } from './sidebars/types';
import {chain, mapValues, keyBy} from 'lodash'; import _ from 'lodash';
import { import {
collectSidebarCategories, collectSidebarCategories,
transformSidebarItems, transformSidebarItems,
@ -146,13 +146,15 @@ function getSidebarTranslationFileContent(
); );
const links = collectSidebarLinks(sidebar); const links = collectSidebarLinks(sidebar);
const linksContent: TranslationFileContent = chain(links) const linksContent: TranslationFileContent = Object.fromEntries(
.keyBy((link) => `sidebar.${sidebarName}.link.${link.label}`) links.map((link) => [
.mapValues((link) => ({ `sidebar.${sidebarName}.link.${link.label}`,
{
message: link.label, message: link.label,
description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`, description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`,
})) },
.value(); ]),
);
return mergeTranslations([categoryContent, linksContent]); return mergeTranslations([categoryContent, linksContent]);
} }
@ -230,7 +232,7 @@ function translateSidebars(
version: LoadedVersion, version: LoadedVersion,
sidebarsTranslations: TranslationFileContent, sidebarsTranslations: TranslationFileContent,
): Sidebars { ): Sidebars {
return mapValues(version.sidebars, (sidebar, sidebarName) => return _.mapValues(version.sidebars, (sidebar, sidebarName) =>
translateSidebar({ translateSidebar({
sidebar, sidebar,
sidebarName: getNormalizedSidebarName({ sidebarName: getNormalizedSidebarName({
@ -302,7 +304,7 @@ export function translateLoadedContent(
loadedContent: LoadedContent, loadedContent: LoadedContent,
translationFiles: TranslationFile[], translationFiles: TranslationFile[],
): LoadedContent { ): LoadedContent {
const translationFilesMap: Record<string, TranslationFile> = keyBy( const translationFilesMap: Record<string, TranslationFile> = _.keyBy(
translationFiles, translationFiles,
(f) => f.path, (f) => f.path,
); );

View file

@ -28,7 +28,7 @@ import {
posixPath, posixPath,
DEFAULT_PLUGIN_ID, DEFAULT_PLUGIN_ID,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import {difference} from 'lodash'; import _ from 'lodash';
import {resolveSidebarPathOption} from './sidebars'; import {resolveSidebarPathOption} from './sidebars';
// retro-compatibility: no prefix for the default plugin id // retro-compatibility: no prefix for the default plugin id
@ -486,7 +486,7 @@ function checkVersionsOptions(
`Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`, `Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
); );
} }
const unknownVersionConfigNames = difference( const unknownVersionConfigNames = _.difference(
Object.keys(options.versions), Object.keys(options.versions),
availableVersionNames, availableVersionNames,
); );
@ -504,7 +504,7 @@ function checkVersionsOptions(
`Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`, `Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`,
); );
} }
const unknownOnlyIncludeVersionNames = difference( const unknownOnlyIncludeVersionNames = _.difference(
options.onlyIncludeVersions, options.onlyIncludeVersions,
availableVersionNames, availableVersionNames,
); );

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {merge} from 'lodash'; import _ from 'lodash';
import {ThemeConfigSchema, DEFAULT_CONFIG} from '../validateThemeConfig'; import {ThemeConfigSchema, DEFAULT_CONFIG} from '../validateThemeConfig';
import {normalizeThemeConfig} from '@docusaurus/utils-validation'; import {normalizeThemeConfig} from '@docusaurus/utils-validation';
@ -507,7 +507,7 @@ describe('themeConfig', () => {
describe('color mode config', () => { describe('color mode config', () => {
const withDefaultValues = (colorMode) => const withDefaultValues = (colorMode) =>
merge({}, DEFAULT_CONFIG.colorMode, colorMode); _.merge({}, DEFAULT_CONFIG.colorMode, colorMode);
test('minimal config', () => { test('minimal config', () => {
const colorMode = { const colorMode = {

View file

@ -15,7 +15,7 @@ import type {
SimpleFooter, SimpleFooter,
} from '@docusaurus/theme-common'; } from '@docusaurus/theme-common';
import {keyBy, chain} from 'lodash'; import _ from 'lodash';
import {mergeTranslations} from '@docusaurus/utils'; import {mergeTranslations} from '@docusaurus/utils';
function getNavbarTranslationFile(navbar: Navbar): TranslationFileContent { function getNavbarTranslationFile(navbar: Navbar): TranslationFileContent {
@ -30,15 +30,17 @@ function getNavbarTranslationFile(navbar: Navbar): TranslationFileContent {
const allNavbarItems = flattenNavbarItems(navbar.items); const allNavbarItems = flattenNavbarItems(navbar.items);
const navbarItemsTranslations: TranslationFileContent = chain( const navbarItemsTranslations: TranslationFileContent = Object.fromEntries(
allNavbarItems.filter((navbarItem) => !!navbarItem.label), allNavbarItems
) .filter((navbarItem) => navbarItem.label)
.keyBy((navbarItem) => `item.label.${navbarItem.label}`) .map((navbarItem) => [
.mapValues((navbarItem) => ({ `item.label.${navbarItem.label}`,
{
message: navbarItem.label!, message: navbarItem.label!,
description: `Navbar item with label ${navbarItem.label}`, description: `Navbar item with label ${navbarItem.label}`,
})) },
.value(); ]),
);
const titleTranslations: TranslationFileContent = navbar.title const titleTranslations: TranslationFileContent = navbar.title
? {title: {message: navbar.title, description: 'The title in the navbar'}} ? {title: {message: navbar.title, description: 'The title in the navbar'}}
@ -78,33 +80,33 @@ function isMultiColumnFooterLinks(
} }
function getFooterTranslationFile(footer: Footer): TranslationFileContent { function getFooterTranslationFile(footer: Footer): TranslationFileContent {
const footerLinkTitles: TranslationFileContent = chain( const footerLinkTitles: TranslationFileContent = Object.fromEntries(
isMultiColumnFooterLinks(footer.links) (isMultiColumnFooterLinks(footer.links)
? footer.links.filter((link) => !!link.title) ? footer.links.filter((link) => link.title)
: [], : []
) ).map((link) => [
.keyBy((link) => `link.title.${link.title}`) `link.title.${link.title}`,
.mapValues((link) => ({ {
message: link.title!, message: link.title!,
description: `The title of the footer links column with title=${link.title} in the footer`, description: `The title of the footer links column with title=${link.title} in the footer`,
})) },
.value(); ]),
);
const footerLinkLabels: TranslationFileContent = chain( const footerLinkLabels: TranslationFileContent = Object.fromEntries(
isMultiColumnFooterLinks(footer.links) (isMultiColumnFooterLinks(footer.links)
? footer.links ? footer.links.flatMap((link) => link.items).filter((link) => link.label)
.flatMap((link) => link.items) : footer.links.filter((link) => link.label)
.filter((link) => !!link.label) ).map((link) => [
: footer.links.filter((link) => !!link.label), `link.item.label.${link.label}`,
) {
.keyBy((linkItem) => `link.item.label.${linkItem.label}`) message: link.label!,
.mapValues((linkItem) => ({
message: linkItem.label!,
description: `The label of footer link with label=${ description: `The label of footer link with label=${
linkItem.label link.label
} linking to ${linkItem.to ?? linkItem.href}`, } linking to ${link.to ?? link.href}`,
})) },
.value(); ]),
);
const copyright: TranslationFileContent = footer.copyright const copyright: TranslationFileContent = footer.copyright
? { ? {
@ -176,7 +178,7 @@ export function translateThemeConfig({
themeConfig: ThemeConfig; themeConfig: ThemeConfig;
translationFiles: TranslationFile[]; translationFiles: TranslationFile[];
}): ThemeConfig { }): ThemeConfig {
const translationFilesMap: Record<string, TranslationFile> = keyBy( const translationFilesMap: Record<string, TranslationFile> = _.keyBy(
translationFiles, translationFiles,
(f) => f.path, (f) => f.path,
); );

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {shuffle} from 'lodash'; import _ from 'lodash';
import {listTagsByLetters} from '../tagsUtils'; import {listTagsByLetters} from '../tagsUtils';
describe('listTagsByLetters', () => { describe('listTagsByLetters', () => {
@ -60,7 +60,9 @@ describe('listTagsByLetters', () => {
listTagsByLetters([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1]), listTagsByLetters([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1]),
).toEqual(expectedResult); ).toEqual(expectedResult);
expect( expect(
listTagsByLetters(shuffle([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1])), listTagsByLetters(
_.shuffle([tagzxy, tagdef, tagaaa, tag2, tagAbc, tag1]),
),
).toEqual(expectedResult); ).toEqual(expectedResult);
}); });
}); });

View file

@ -12,12 +12,12 @@ import {normalizeUrl} from '@docusaurus/utils';
import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations'; import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import openSearchTemplate from './templates/opensearch'; import openSearchTemplate from './templates/opensearch';
import {memoize} from 'lodash'; import _ from 'lodash';
import type {LoadContext, Plugin} from '@docusaurus/types'; import type {LoadContext, Plugin} from '@docusaurus/types';
import type {ThemeConfig} from '@docusaurus/theme-search-algolia'; import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
const getCompiledOpenSearchTemplate = memoize(() => const getCompiledOpenSearchTemplate = _.memoize(() =>
compile(openSearchTemplate.trim()), compile(openSearchTemplate.trim()),
); );

View file

@ -8,7 +8,7 @@
import {extractThemeCodeMessages} from '../update'; import {extractThemeCodeMessages} from '../update';
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {mapValues} from 'lodash'; import _ from 'lodash';
// Seems the 5s default timeout fails sometimes // Seems the 5s default timeout fails sometimes
jest.setTimeout(15000); jest.setTimeout(15000);
@ -37,7 +37,7 @@ describe('theme-translations package', () => {
.flat() .flat()
.filter(([key]) => !key.endsWith('___DESCRIPTION')), .filter(([key]) => !key.endsWith('___DESCRIPTION')),
); );
const codeMessages = mapValues( const codeMessages = _.mapValues(
await extractThemeCodeMessages(), await extractThemeCodeMessages(),
(translation) => translation.message, (translation) => translation.message,
); );

View file

@ -11,7 +11,7 @@
const logger = require('@docusaurus/logger').default; const logger = require('@docusaurus/logger').default;
const path = require('path'); const path = require('path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const {mapValues, pickBy, difference, orderBy} = require('lodash'); const _ = require('lodash');
const LocalesDirPath = path.join(__dirname, 'locales'); const LocalesDirPath = path.join(__dirname, 'locales');
const Themes = [ const Themes = [
@ -80,7 +80,7 @@ function removeDescriptionSuffix(key) {
*/ */
function sortObjectKeys(obj) { function sortObjectKeys(obj) {
let keys = Object.keys(obj); let keys = Object.keys(obj);
keys = orderBy(keys, [(k) => removeDescriptionSuffix(k)]); keys = _.orderBy(keys, [(k) => removeDescriptionSuffix(k)]);
return keys.reduce((acc, key) => { return keys.reduce((acc, key) => {
acc[key] = obj[key]; acc[key] = obj[key];
return acc; return acc;
@ -179,18 +179,18 @@ const DescriptionSuffix = '___DESCRIPTION';
*/ */
async function updateBaseFile(baseFile, targetDirs) { async function updateBaseFile(baseFile, targetDirs) {
const baseMessagesWithDescriptions = await readMessagesFile(baseFile); const baseMessagesWithDescriptions = await readMessagesFile(baseFile);
const baseMessages = pickBy( const baseMessages = _.pickBy(
baseMessagesWithDescriptions, baseMessagesWithDescriptions,
(_, key) => !key.endsWith(DescriptionSuffix), (v, key) => !key.endsWith(DescriptionSuffix),
); );
const codeExtractedTranslations = await extractThemeCodeMessages(targetDirs); const codeExtractedTranslations = await extractThemeCodeMessages(targetDirs);
const codeMessages = mapValues( const codeMessages = _.mapValues(
codeExtractedTranslations, codeExtractedTranslations,
(translation) => translation.message, (translation) => translation.message,
); );
const unknownMessages = difference( const unknownMessages = _.difference(
Object.keys(baseMessages), Object.keys(baseMessages),
Object.keys(codeMessages), 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) { async function updateLocaleCodeTranslations(localeFile, baseFileMessages) {
const localeFileMessages = await readMessagesFile(localeFile); const localeFileMessages = await readMessagesFile(localeFile);
const unknownMessages = difference( const unknownMessages = _.difference(
Object.keys(localeFileMessages), Object.keys(localeFileMessages),
Object.keys(baseFileMessages), Object.keys(baseFileMessages),
); );

View file

@ -28,7 +28,7 @@ import {
posixPath, posixPath,
readOutputHTMLFile, readOutputHTMLFile,
} from '../index'; } from '../index';
import {sum} from 'lodash'; import _ from 'lodash';
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
@ -322,7 +322,7 @@ describe('mapAsyncSequential', () => {
const timeTotal = timeAfter - timeBefore; const timeTotal = timeAfter - timeBefore;
const totalTimeouts = sum(Object.values(itemToTimeout)); const totalTimeouts = _.sum(Object.values(itemToTimeout));
expect(timeTotal).toBeGreaterThanOrEqual(totalTimeouts - 20); expect(timeTotal).toBeGreaterThanOrEqual(totalTimeouts - 20);
expect(itemMapStartsAt['1']).toBeGreaterThanOrEqual(0); expect(itemMapStartsAt['1']).toBeGreaterThanOrEqual(0);

View file

@ -6,7 +6,7 @@
*/ */
import {createHash} from 'crypto'; import {createHash} from 'crypto';
import {kebabCase} from 'lodash'; import _ from 'lodash';
import {shortName, isNameTooLong} from './pathUtils'; import {shortName, isNameTooLong} from './pathUtils';
export function md5Hash(str: string): string { export function md5Hash(str: string): string {
@ -29,9 +29,9 @@ export function docuHash(str: string): string {
return 'index'; return 'index';
} }
const shortHash = simpleHash(str, 3); const shortHash = simpleHash(str, 3);
const parsedPath = `${kebabCase(str)}-${shortHash}`; const parsedPath = `${_.kebabCase(str)}-${shortHash}`;
if (isNameTooLong(parsedPath)) { if (isNameTooLong(parsedPath)) {
return `${shortName(kebabCase(str))}-${shortHash}`; return `${shortName(_.kebabCase(str))}-${shortHash}`;
} }
return parsedPath; return parsedPath;
} }

View file

@ -8,7 +8,7 @@
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import path from 'path'; import path from 'path';
import {createHash} from 'crypto'; import {createHash} from 'crypto';
import {mapValues} from 'lodash'; import _ from 'lodash';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {URL} from 'url'; import {URL} from 'url';
import type { import type {
@ -361,7 +361,7 @@ export function updateTranslationFileMessages(
): TranslationFile { ): TranslationFile {
return { return {
...translationFile, ...translationFile,
content: mapValues(translationFile.content, (translation) => ({ content: _.mapValues(translationFile.content, (translation) => ({
...translation, ...translation,
message: updateMessage(translation.message), message: updateMessage(translation.message),
})), })),

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {kebabCase, uniq, uniqBy} from 'lodash'; import _ from 'lodash';
import {normalizeUrl} from './urlUtils'; import {normalizeUrl} from './urlUtils';
export type Tag = { export type Tag = {
@ -22,7 +22,7 @@ export function normalizeFrontMatterTag(
function toTagObject(tagString: string): Tag { function toTagObject(tagString: string): Tag {
return { return {
label: tagString, label: tagString,
permalink: kebabCase(tagString), permalink: _.kebabCase(tagString),
}; };
} }
@ -53,7 +53,7 @@ export function normalizeFrontMatterTags(
normalizeFrontMatterTag(tagsPath, tag), normalizeFrontMatterTag(tagsPath, tag),
); );
return uniqBy(tags, (tag) => tag.permalink); return _.uniqBy(tags, (tag) => tag.permalink);
} }
export type TaggedItemGroup<Item> = { export type TaggedItemGroup<Item> = {
@ -98,7 +98,7 @@ export function groupTaggedItems<Item>(
// If user add twice the same tag to a md doc (weird but possible), // 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... // we don't want the item to appear twice in the list...
Object.values(result).forEach((group) => { Object.values(result).forEach((group) => {
group.items = uniq(group.items); group.items = _.uniq(group.items);
}); });
return result; return result;

View file

@ -25,13 +25,13 @@ import {
} from './LinksCollector'; } from './LinksCollector';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import {memoize} from 'lodash'; import _ from 'lodash';
import type {Locals} from '@slorber/static-site-generator-webpack-plugin'; import type {Locals} from '@slorber/static-site-generator-webpack-plugin';
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const packageJson = require('../../package.json'); const packageJson = require('../../package.json');
const getCompiledSSRTemplate = memoize((template: string) => const getCompiledSSRTemplate = _.memoize((template: string) =>
eta.compile(template.trim(), { eta.compile(template.trim(), {
rmWhitespace: true, rmWhitespace: true,
}), }),

View file

@ -10,7 +10,7 @@ import logger from '@docusaurus/logger';
import chokidar from 'chokidar'; import chokidar from 'chokidar';
import HtmlWebpackPlugin from 'html-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin';
import path from 'path'; import path from 'path';
import {debounce} from 'lodash'; import _ from 'lodash';
import openBrowser from 'react-dev-utils/openBrowser'; import openBrowser from 'react-dev-utils/openBrowser';
import {prepareUrls} from 'react-dev-utils/WebpackDevServerUtils'; import {prepareUrls} from 'react-dev-utils/WebpackDevServerUtils';
import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware'; 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}.`; logger.success`Docusaurus website is running at path=${openUrl}.`;
// Reload files processing. // Reload files processing.
const reload = debounce(() => { const reload = _.debounce(() => {
loadSite() loadSite()
.then(({baseUrl: newBaseUrl}) => { .then(({baseUrl: newBaseUrl}) => {
const newOpenUrl = normalizeUrl([urls.localUrlForBrowser, newBaseUrl]); const newOpenUrl = normalizeUrl([urls.localUrlForBrowser, newBaseUrl]);

View file

@ -13,14 +13,12 @@ import {
} from '../i18n'; } from '../i18n';
import {DEFAULT_I18N_CONFIG} from '../configValidation'; import {DEFAULT_I18N_CONFIG} from '../configValidation';
import path from 'path'; import path from 'path';
import {chain, identity} from 'lodash';
import type {I18nConfig} from '@docusaurus/types'; import type {I18nConfig} from '@docusaurus/types';
function testLocaleConfigsFor(locales: string[]) { function testLocaleConfigsFor(locales: string[]) {
return chain(locales) return Object.fromEntries(
.keyBy(identity) locales.map((locale) => [locale, getDefaultLocaleConfig(locale)]),
.mapValues(getDefaultLocaleConfig) );
.value();
} }
function loadI18nTest(i18nConfig: I18nConfig, locale?: string) { function loadI18nTest(i18nConfig: I18nConfig, locale?: string) {

View file

@ -10,7 +10,7 @@ import {
type RouteConfig as RRRouteConfig, type RouteConfig as RRRouteConfig,
} from 'react-router-config'; } from 'react-router-config';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {mapValues, pickBy, countBy} from 'lodash'; import _ from 'lodash';
import type {RouteConfig, ReportingSeverity} from '@docusaurus/types'; import type {RouteConfig, ReportingSeverity} from '@docusaurus/types';
import { import {
removePrefix, removePrefix,
@ -84,12 +84,12 @@ export function getAllBrokenLinks({
}): Record<string, BrokenLink[]> { }): Record<string, BrokenLink[]> {
const filteredRoutes = filterIntermediateRoutes(routes); const filteredRoutes = filterIntermediateRoutes(routes);
const allBrokenLinks = mapValues(allCollectedLinks, (pageLinks, pagePath) => const allBrokenLinks = _.mapValues(allCollectedLinks, (pageLinks, pagePath) =>
getPageBrokenLinks({pageLinks, pagePath, routes: filteredRoutes}), getPageBrokenLinks({pageLinks, pagePath, routes: filteredRoutes}),
); );
// remove pages without any broken link // remove pages without any broken link
return pickBy(allBrokenLinks, (brokenLinks) => brokenLinks.length > 0); return _.pickBy(allBrokenLinks, (brokenLinks) => brokenLinks.length > 0);
} }
export function getBrokenLinksErrorMessage( export function getBrokenLinksErrorMessage(
@ -126,7 +126,7 @@ export function getBrokenLinksErrorMessage(
brokenLinks.map((brokenLink) => ({pagePage, brokenLink})), brokenLinks.map((brokenLink) => ({pagePage, brokenLink})),
); );
const countedBrokenLinks = countBy( const countedBrokenLinks = _.countBy(
flatList, flatList,
(item) => item.brokenLink.link, (item) => item.brokenLink.link,
); );
@ -197,7 +197,7 @@ export async function filterExistingFileLinks({
return filePathsToTry.some(isExistingFile); return filePathsToTry.some(isExistingFile);
} }
return mapValues(allCollectedLinks, (links) => return _.mapValues(allCollectedLinks, (links) =>
links.filter((link) => !linkFileExists(link)), links.filter((link) => !linkFileExists(link)),
); );
} }

View file

@ -5,14 +5,13 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {isPlainObject} from 'lodash';
import type {HtmlTagObject} from '@docusaurus/types'; import type {HtmlTagObject} from '@docusaurus/types';
import htmlTags from 'html-tags'; import htmlTags from 'html-tags';
import voidHtmlTags from 'html-tags/void'; import voidHtmlTags from 'html-tags/void';
import escapeHTML from 'escape-html'; import escapeHTML from 'escape-html';
function assertIsHtmlTagObject(val: unknown): asserts val is HtmlTagObject { 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.`); throw new Error(`"${val}" is not a valid HTML tag object.`);
} }
if (typeof (val as HtmlTagObject).tagName !== 'string') { if (typeof (val as HtmlTagObject).tagName !== 'string') {

View file

@ -37,7 +37,7 @@ import {
readCodeTranslationFileContent, readCodeTranslationFileContent,
getPluginsDefaultCodeTranslationMessages, getPluginsDefaultCodeTranslationMessages,
} from './translations/translations'; } from './translations/translations';
import {mapValues} from 'lodash'; import _ from 'lodash';
import type {RuleSetRule} from 'webpack'; import type {RuleSetRule} from 'webpack';
import admonitions from 'remark-admonitions'; import admonitions from 'remark-admonitions';
import {createRequire} from 'module'; import {createRequire} from 'module';
@ -111,7 +111,7 @@ export async function loadContext(
})) ?? {}; })) ?? {};
// We only need key->message for code translations // We only need key->message for code translations
const codeTranslations = mapValues( const codeTranslations = _.mapValues(
codeTranslationFileContent, codeTranslationFileContent,
(value) => value.message, (value) => value.message,
); );

View file

@ -21,7 +21,7 @@ import type {
} from '@docusaurus/types'; } from '@docusaurus/types';
import initPlugins from './init'; import initPlugins from './init';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import {chain} from 'lodash'; import _ from 'lodash';
import {localizePluginTranslationFile} from '../translations/translations'; import {localizePluginTranslationFile} from '../translations/translations';
import applyRouteTrailingSlash from './applyRouteTrailingSlash'; 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) .groupBy((item) => item.name)
.mapValues((nameItems) => .mapValues((nameItems) =>
chain(nameItems) _.chain(nameItems)
.groupBy((item) => item.options.id ?? DEFAULT_PLUGIN_ID) .groupBy((item) => item.options.id ?? DEFAULT_PLUGIN_ID)
.mapValues((idItems) => idItems[0].content) .mapValues((idItems) => idItems[0].content)
.value(), .value(),

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * 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 {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
import type {InitializedPlugin} from '@docusaurus/types'; import type {InitializedPlugin} from '@docusaurus/types';
@ -14,9 +14,9 @@ import type {InitializedPlugin} from '@docusaurus/types';
export function ensureUniquePluginInstanceIds( export function ensureUniquePluginInstanceIds(
plugins: InitializedPlugin[], plugins: InitializedPlugin[],
): void { ): void {
const pluginsByName = groupBy(plugins, (p) => p.name); const pluginsByName = _.groupBy(plugins, (p) => p.name);
Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => { Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => {
const pluginInstancesById = groupBy( const pluginInstancesById = _.groupBy(
pluginInstances, pluginInstances,
(p) => p.options.id ?? DEFAULT_PLUGIN_ID, (p) => p.options.id ?? DEFAULT_PLUGIN_ID,
); );

View file

@ -12,7 +12,6 @@ import {
simpleHash, simpleHash,
escapePath, escapePath,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import {has, isPlainObject, isString} from 'lodash';
import {stringify} from 'querystring'; import {stringify} from 'querystring';
import type { import type {
ChunkRegistry, ChunkRegistry,
@ -85,10 +84,15 @@ const RoutesImportsCode = [
].join('\n'); ].join('\n');
function isModule(value: unknown): value is Module { function isModule(value: unknown): value is Module {
if (isString(value)) { if (typeof value === 'string') {
return true; 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<string, unknown>)?.__import &&
(value as Record<string, unknown>)?.path
) {
return true; return true;
} }
return false; return false;
@ -137,11 +141,10 @@ export default async function loadRoutes(
...props ...props
} = routeConfig; } = routeConfig;
if (!isString(routePath) || !component) { if (typeof routePath !== 'string' || !component) {
throw new Error( throw new Error(
`Invalid route config: path must be a string and component is required.\n${JSON.stringify( `Invalid route config: path must be a string and component is required.
routeConfig, ${JSON.stringify(routeConfig)}`,
)}`,
); );
} }

View file

@ -9,7 +9,7 @@ import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import {fileToPath, posixPath, normalizeUrl, Globby} from '@docusaurus/utils'; import {fileToPath, posixPath, normalizeUrl, Globby} from '@docusaurus/utils';
import type {ThemeAliases} from '@docusaurus/types'; 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 // Order of Webpack aliases is important because one alias can shadow another
// This ensure @theme/NavbarItem alias is after @theme/NavbarItem/LocaleDropdown // 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 // See https://github.com/facebook/docusaurus/issues/5382
export function sortAliases(aliases: ThemeAliases): ThemeAliases { export function sortAliases(aliases: ThemeAliases): ThemeAliases {
// Alphabetical order by default // 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 // @theme/NavbarItem should be after @theme/NavbarItem/LocaleDropdown
entries.sort(([alias1], [alias2]) => entries.sort(([alias1], [alias2]) =>
alias1.includes(`${alias2}/`) ? -1 : 0, alias1.includes(`${alias2}/`) ? -1 : 0,

View file

@ -7,7 +7,7 @@
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {mapValues, difference} from 'lodash'; import _ from 'lodash';
import type { import type {
TranslationFileContent, TranslationFileContent,
TranslationFile, TranslationFile,
@ -75,7 +75,7 @@ function mergeTranslationFileContent({
options: WriteTranslationsOptions; options: WriteTranslationsOptions;
}): TranslationFileContent { }): TranslationFileContent {
// Apply messagePrefix to all messages // Apply messagePrefix to all messages
const newContentTransformed = mapValues(newContent, (value) => ({ const newContentTransformed = _.mapValues(newContent, (value) => ({
...value, ...value,
message: `${options.messagePrefix ?? ''}${value.message}`, message: `${options.messagePrefix ?? ''}${value.message}`,
})); }));
@ -110,7 +110,7 @@ export async function writeTranslationFileContent({
const existingContent = await readTranslationFileContent(filePath); const existingContent = await readTranslationFileContent(filePath);
// Warn about potential legacy keys // Warn about potential legacy keys
const unknownKeys = difference( const unknownKeys = _.difference(
Object.keys(existingContent ?? {}), Object.keys(existingContent ?? {}),
Object.keys(newContent), Object.keys(newContent),
); );
@ -276,7 +276,7 @@ export function applyDefaultCodeTranslations({
extractedCodeTranslations: Record<string, TranslationMessage>; extractedCodeTranslations: Record<string, TranslationMessage>;
defaultCodeMessages: Record<string, string>; defaultCodeMessages: Record<string, string>;
}): Record<string, TranslationMessage> { }): Record<string, TranslationMessage> {
const unusedDefaultCodeMessages = difference( const unusedDefaultCodeMessages = _.difference(
Object.keys(defaultCodeMessages), Object.keys(defaultCodeMessages),
Object.keys(extractedCodeTranslations), Object.keys(extractedCodeTranslations),
); );
@ -285,7 +285,7 @@ export function applyDefaultCodeTranslations({
Please report this Docusaurus issue. name=${unusedDefaultCodeMessages}`; Please report this Docusaurus issue. name=${unusedDefaultCodeMessages}`;
} }
return mapValues( return _.mapValues(
extractedCodeTranslations, extractedCodeTranslations,
(messageTranslation, messageId) => ({ (messageTranslation, messageId) => ({
...messageTranslation, ...messageTranslation,

View file

@ -15,7 +15,7 @@ import {
} from '../base'; } from '../base';
import * as utils from '@docusaurus/utils/lib/webpackUtils'; import * as utils from '@docusaurus/utils/lib/webpackUtils';
import {posixPath} from '@docusaurus/utils'; import {posixPath} from '@docusaurus/utils';
import {mapValues} from 'lodash'; import _ from 'lodash';
import type {Props, ThemeAliases} from '@docusaurus/types'; import type {Props, ThemeAliases} from '@docusaurus/types';
describe('babel transpilation exclude logic', () => { describe('babel transpilation exclude logic', () => {
@ -70,7 +70,7 @@ describe('babel transpilation exclude logic', () => {
describe('getDocusaurusAliases()', () => { describe('getDocusaurusAliases()', () => {
test('return appropriate webpack aliases', () => { test('return appropriate webpack aliases', () => {
// using relative paths makes tests work everywhere // using relative paths makes tests work everywhere
const relativeDocusaurusAliases = mapValues( const relativeDocusaurusAliases = _.mapValues(
getDocusaurusAliases(), getDocusaurusAliases(),
(aliasValue) => posixPath(path.relative(__dirname, aliasValue)), (aliasValue) => posixPath(path.relative(__dirname, aliasValue)),
); );
@ -125,7 +125,7 @@ describe('base webpack config', () => {
const aliases: ThemeAliases = const aliases: ThemeAliases =
createBaseConfig(props, true).resolve?.alias ?? {}; createBaseConfig(props, true).resolve?.alias ?? {};
// Make aliases relative so that test work on all computers // 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)), posixPath(path.relative(props.siteDir, a)),
); );
expect(relativeAliases).toMatchSnapshot(); expect(relativeAliases).toMatchSnapshot();

View file

@ -31,7 +31,7 @@ import type {
ConfigureWebpackUtils, ConfigureWebpackUtils,
} from '@docusaurus/types'; } from '@docusaurus/types';
import {BABEL_CONFIG_FILE_NAME} from '@docusaurus/utils'; import {BABEL_CONFIG_FILE_NAME} from '@docusaurus/utils';
import {memoize} from 'lodash'; import _ from 'lodash';
// Utility method to get style loaders // Utility method to get style loaders
export function getStyleLoaders( export function getStyleLoaders(
@ -164,7 +164,7 @@ export const getCustomizableJSLoader =
: jsLoader(isServer); : jsLoader(isServer);
// TODO remove this before end of 2021? // 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)'}.`; 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( const getBabelLoaderDeprecated = function getBabelLoaderDeprecated(
@ -176,7 +176,7 @@ const getBabelLoaderDeprecated = function getBabelLoaderDeprecated(
}; };
// TODO remove this before end of 2021 ? // 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.`; logger.warn`Docusaurus uses Webpack 5 and code=${'getCacheLoader()'} usage is now deprecated.`;
}); });
function getCacheLoaderDeprecated() { function getCacheLoaderDeprecated() {

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * 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'; import type {Palette} from 'node-vibrant/lib/color';
/** /**
@ -29,7 +29,7 @@ const toPalette = (swatch: Palette): string[] => {
} }
return result; return result;
}, [] as {popularity: number; hex: string}[]); }, [] as {popularity: number; hex: string}[]);
palette = sortBy(palette, ['popularity']); palette = _.sortBy(palette, ['popularity']);
return palette.map((color) => color.hex).reverse(); return palette.map((color) => color.hex).reverse();
}; };