refactor(utils): reorganize functions; move authors file resolution to utils (#6229)

* refactor(utils): reorganize functions; move authors file resolution to utils

* More refactor
This commit is contained in:
Joshua Chen 2021-12-31 11:55:42 +08:00 committed by GitHub
parent 7adc1c0cdb
commit 24d65d9bdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 533 additions and 747 deletions

View file

@ -8,8 +8,7 @@
import logger from '@docusaurus/logger';
import path from 'path';
import {createHash} from 'crypto';
import {camelCase, mapValues} from 'lodash';
import escapeStringRegexp from 'escape-string-regexp';
import {mapValues} from 'lodash';
import fs from 'fs-extra';
import {URL} from 'url';
import {
@ -20,30 +19,21 @@ import {
import resolvePathnameUnsafe from 'resolve-pathname';
import {posixPath as posixPathImport} from './posixPath';
import {simpleHash, docuHash} from './hashUtils';
import {normalizeUrl} from './normalizeUrl';
import {DEFAULT_PLUGIN_ID} from './constants';
export * from './constants';
export * from './mdxUtils';
export * from './normalizeUrl';
export * from './urlUtils';
export * from './tags';
export const posixPath = posixPathImport;
export * from './markdownParser';
export * from './markdownLinks';
export * from './escapePath';
export * from './slugger';
export {md5Hash, simpleHash, docuHash} from './hashUtils';
export {
Globby,
GlobExcludeDefault,
createMatcher,
createAbsoluteFilePathMatcher,
} from './globUtils';
export * from './pathUtils';
export * from './hashUtils';
export * from './globUtils';
export * from './webpackUtils';
export * from './dataFileUtils';
const fileHash = new Map();
export async function generate(
@ -80,18 +70,6 @@ export async function generate(
}
}
export function objectWithKeySorted<T>(
obj: Record<string, T>,
): Record<string, T> {
// https://github.com/lodash/lodash/issues/1459#issuecomment-460941233
return Object.keys(obj)
.sort()
.reduce((acc: Record<string, T>, key: string) => {
acc[key] = obj[key];
return acc;
}, {});
}
const indexRE = /(^|.*\/)index\.(md|mdx|js|jsx|ts|tsx)$/i;
const extRE = /\.(md|mdx|js|jsx|ts|tsx)$/;
@ -113,37 +91,6 @@ export function encodePath(userpath: string): string {
.join('/');
}
/**
* Convert first string character to the upper case.
* E.g: docusaurus -> Docusaurus
*/
export function upperFirst(str: string): string {
return str ? str.charAt(0).toUpperCase() + str.slice(1) : '';
}
/**
* Generate unique React Component Name.
* E.g: /foo-bar -> FooBar096
*/
export function genComponentName(pagePath: string): string {
if (pagePath === '/') {
return 'index';
}
const pageHash = docuHash(pagePath);
return upperFirst(camelCase(pageHash));
}
// When you want to display a path in a message/warning/error,
// it's more convenient to:
// - make it relative to cwd()
// - convert to posix (ie not using windows \ path separator)
// This way, Jest tests can run more reliably on any computer/CI
// on both Unix/Windows
// For Windows users this is not perfect (as they see / instead of \) but it's probably good enough
export function toMessageRelativeFilePath(filePath: string): string {
return posixPath(path.relative(process.cwd(), filePath));
}
const chunkNameCache = new Map();
/**
* Generate unique chunk name given a module path.
@ -172,52 +119,6 @@ export function genChunkName(
return chunkName;
}
// Too dynamic
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
export function idx(target: any, keyPaths?: string | (string | number)[]): any {
return (
target &&
keyPaths &&
(Array.isArray(keyPaths)
? keyPaths.reduce((obj, key) => obj && obj[key], target)
: target[keyPaths])
);
}
/**
* Given a filepath and dirpath, get the first directory.
*/
export function getSubFolder(file: string, refDir: string): string | null {
const separator = escapeStringRegexp(path.sep);
const baseDir = escapeStringRegexp(path.basename(refDir));
const regexSubFolder = new RegExp(
`${baseDir}${separator}(.*?)${separator}.*`,
);
const match = regexSubFolder.exec(file);
return match && match[1];
}
/**
* Alias filepath relative to site directory, very useful so that we
* don't expose user's site structure.
* Example: some/path/to/website/docs/foo.md -> @site/docs/foo.md
*/
export function aliasedSitePath(filePath: string, siteDir: string): string {
const relativePath = posixPath(path.relative(siteDir, filePath));
// Cannot use path.join() as it resolves '../' and removes
// the '@site'. Let webpack loader resolve it.
return `@site/${relativePath}`;
}
export function getEditUrl(
fileRelativePath: string,
editUrl?: string,
): string | undefined {
return editUrl
? normalizeUrl([editUrl, posixPath(fileRelativePath)])
: undefined;
}
export function isValidPathname(str: string): boolean {
if (!str.startsWith('/')) {
return false;
@ -306,7 +207,7 @@ export function getPluginI18nPath({
);
}
export async function mapAsyncSequencial<T, R>(
export async function mapAsyncSequential<T, R>(
array: T[],
action: (t: T) => Promise<R>,
): Promise<R[]> {
@ -332,35 +233,6 @@ export async function findAsyncSequential<T>(
return undefined;
}
// return the first folder path in which the file exists in
export async function findFolderContainingFile(
folderPaths: string[],
relativeFilePath: string,
): Promise<string | undefined> {
return findAsyncSequential(folderPaths, (folderPath) =>
fs.pathExists(path.join(folderPath, relativeFilePath)),
);
}
export async function getFolderContainingFile(
folderPaths: string[],
relativeFilePath: string,
): Promise<string> {
const maybeFolderPath = await findFolderContainingFile(
folderPaths,
relativeFilePath,
);
// should never happen, as the source was read from the FS anyway...
if (!maybeFolderPath) {
throw new Error(
`File "${relativeFilePath}" does not exist in any of these folders:\n- ${folderPaths.join(
'\n- ',
)}]`,
);
}
return maybeFolderPath;
}
export function reportMessage(
message: string,
reportingSeverity: ReportingSeverity,
@ -420,21 +292,3 @@ export function updateTranslationFileMessages(
})),
};
}
// Input: ## Some heading {#some-heading}
// Output: {text: "## Some heading", id: "some-heading"}
export function parseMarkdownHeadingId(heading: string): {
text: string;
id?: string;
} {
const customHeadingIdRegex = /^(.*?)\s*\{#([\w-]+)\}$/;
const matches = customHeadingIdRegex.exec(heading);
if (matches) {
return {
text: matches[1],
id: matches[2],
};
} else {
return {text: heading, id: undefined};
}
}