mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-16 18:46:57 +02:00
refactor: enforce named capture groups; clean up regexes (#6524)
* refactor: enforce named capture groups; clean up regexes * fixes * fix
This commit is contained in:
parent
c56e6194b4
commit
1cefb643dd
32 changed files with 80 additions and 77 deletions
|
@ -100,6 +100,7 @@ module.exports = {
|
|||
'no-restricted-syntax': WARNING,
|
||||
'no-unused-expressions': [WARNING, {allowTaggedTemplates: true}],
|
||||
'prefer-destructuring': WARNING,
|
||||
'prefer-named-capture-group': WARNING,
|
||||
'prefer-template': WARNING,
|
||||
yoda: WARNING,
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ export function shouldQuotifyFrontMatter([key, value]: [
|
|||
if (key === 'tags') {
|
||||
return false;
|
||||
}
|
||||
if (String(value).match(/^("|').+("|')$/)) {
|
||||
if (String(value).match(/^(?<quote>["']).+\1$/)) {
|
||||
return false;
|
||||
}
|
||||
// title: !something needs quotes because otherwise it's a YAML tag.
|
||||
|
@ -69,6 +69,6 @@ export function shouldQuotifyFrontMatter([key, value]: [
|
|||
// TODO this is not ideal to have to maintain such a list of allowed chars
|
||||
// maybe we should quotify if gray-matter throws instead?
|
||||
return !String(value).match(
|
||||
/^([\w .\-sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ!;,=+_?'`&#()[\]§%€$])+$/,
|
||||
/^[\w .\-sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ!;,=+_?'`&#()[\]§%€$]+$/,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ export function getBlogTags(blogPosts: BlogPost[]): BlogTags {
|
|||
}
|
||||
|
||||
const DATE_FILENAME_REGEX =
|
||||
/^(?<folder>.*)(?<date>\d{4}[-/]\d{1,2}[-/]\d{1,2})[-/]?(?<text>.*?)(\/index)?.mdx?$/;
|
||||
/^(?<folder>.*)(?<date>\d{4}[-/]\d{1,2}[-/]\d{1,2})[-/]?(?<text>.*?)(?:\/index)?.mdx?$/;
|
||||
|
||||
type ParsedBlogFileName = {
|
||||
date: Date | undefined;
|
||||
|
@ -83,7 +83,7 @@ export function parseBlogFileName(
|
|||
const slug = `/${slugDate}/${folder}${text}`;
|
||||
return {date, text, slug};
|
||||
}
|
||||
const text = blogSourceRelative.replace(/(\/index)?\.mdx?$/, '');
|
||||
const text = blogSourceRelative.replace(/(?:\/index)?\.mdx?$/, '');
|
||||
const slug = `/${text}`;
|
||||
return {date: undefined, text, slug};
|
||||
}
|
||||
|
|
|
@ -452,7 +452,7 @@ export default async function pluginContentBlog(
|
|||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /(\.mdx?)$/,
|
||||
test: /\.mdx?$/i,
|
||||
include: contentDirs
|
||||
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
||||
.map(addTrailingPathSeparator),
|
||||
|
|
|
@ -20,7 +20,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
|
|||
beforeDefaultRehypePlugins: [],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
admonitions: {},
|
||||
truncateMarker: /<!--\s*(truncate)\s*-->/,
|
||||
truncateMarker: /<!--\s*truncate\s*-->/,
|
||||
rehypePlugins: [],
|
||||
remarkPlugins: [],
|
||||
showReadingTime: true,
|
||||
|
|
|
@ -333,7 +333,7 @@ export default async function pluginContentDocs(
|
|||
function createMDXLoaderRule(): RuleSetRule {
|
||||
const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
|
||||
return {
|
||||
test: /(\.mdx?)$/,
|
||||
test: /\.mdx?$/i,
|
||||
include: contentDirs
|
||||
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
||||
.map(addTrailingPathSeparator),
|
||||
|
|
|
@ -10,7 +10,7 @@ import logger from '@docusaurus/logger';
|
|||
|
||||
type FileLastUpdateData = {timestamp?: number; author?: string};
|
||||
|
||||
const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(\d+),(.+)$/;
|
||||
const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(?<timestamp>\d+),(?<author>.+)$/;
|
||||
|
||||
let showedGitRequirementError = false;
|
||||
|
||||
|
@ -25,10 +25,10 @@ export async function getFileLastUpdate(
|
|||
return null;
|
||||
}
|
||||
|
||||
const temp = str.match(GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX);
|
||||
return !temp || temp.length < 3
|
||||
? null
|
||||
: {timestamp: +temp[1], author: temp[2]};
|
||||
const temp = str.match(GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX)?.groups;
|
||||
return temp
|
||||
? {timestamp: Number(temp.timestamp), author: temp.author}
|
||||
: null;
|
||||
}
|
||||
|
||||
// Wrap in try/catch in case the shell commands fail
|
||||
|
|
|
@ -11,14 +11,14 @@ import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs';
|
|||
const IgnoredPrefixPatterns = (() => {
|
||||
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
|
||||
const DateLikePrefixRegex =
|
||||
/^((\d{2}|\d{4})[-_.]\d{2}([-_.](\d{2}|\d{4}))?)(.*)$/;
|
||||
/^(?:\d{2}|\d{4})[-_.]\d{2}(?:[-_.](?:\d{2}|\d{4}))?.*$/;
|
||||
|
||||
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
|
||||
// note: we could try to parse float numbers in filenames but that is
|
||||
// probably not worth it as a version such as "8.0" can be interpreted as both
|
||||
// a version and a float. User can configure her own NumberPrefixParser if
|
||||
// she wants 8.0 to be interpreted as a float
|
||||
const VersionLikePrefixRegex = /^(\d+[-_.]\d+)(.*)$/;
|
||||
const VersionLikePrefixRegex = /^\d+[-_.]\d+.*$/;
|
||||
|
||||
return new RegExp(
|
||||
`${DateLikePrefixRegex.source}|${VersionLikePrefixRegex.source}`,
|
||||
|
|
|
@ -36,7 +36,7 @@ const sidebarItemAutogeneratedSchema =
|
|||
type: 'autogenerated',
|
||||
dirName: Joi.string()
|
||||
.required()
|
||||
.pattern(/^[^/](.*[^/])?$/)
|
||||
.pattern(/^[^/](?:.*[^/])?$/)
|
||||
.message(
|
||||
'"dirName" must be a dir path relative to the docs folder root, and should not start or end with slash',
|
||||
),
|
||||
|
|
|
@ -199,7 +199,7 @@ export default async function pluginContentPages(
|
|||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /(\.mdx?)$/,
|
||||
test: /\.mdx?$/i,
|
||||
include: contentDirs
|
||||
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
||||
.map(addTrailingPathSeparator),
|
||||
|
|
|
@ -57,7 +57,7 @@ export default function pluginIdealImage(
|
|||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(png|jpe?g|gif)$/i,
|
||||
test: /\.(?:png|jpe?g|gif)$/i,
|
||||
use: [
|
||||
require.resolve('@docusaurus/lqip-loader'),
|
||||
{
|
||||
|
|
|
@ -174,7 +174,7 @@ export default function pluginPWA(
|
|||
rules: [
|
||||
{
|
||||
test: swSourceFileTest,
|
||||
exclude: /(node_modules)/,
|
||||
exclude: /node_modules/,
|
||||
use: getSWBabelLoader(),
|
||||
},
|
||||
],
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import rangeParser from 'parse-numeric-range';
|
||||
|
||||
const codeBlockTitleRegex = /title=(["'])(.*?)\1/;
|
||||
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
||||
const codeBlockTitleRegex = /title=(?<quote>["'])(?<title>.*?)\1/;
|
||||
const highlightLinesRangeRegex = /{(?<range>[\d,-]+)}/;
|
||||
|
||||
const commentTypes = ['js', 'jsBlock', 'jsx', 'python', 'html'] as const;
|
||||
type CommentType = typeof commentTypes[number];
|
||||
|
@ -89,7 +89,7 @@ const magicCommentDirectiveRegex = (lang: string) => {
|
|||
};
|
||||
|
||||
export function parseCodeBlockTitle(metastring?: string): string {
|
||||
return metastring?.match(codeBlockTitleRegex)?.[2] ?? '';
|
||||
return metastring?.match(codeBlockTitleRegex)?.groups!.title ?? '';
|
||||
}
|
||||
|
||||
export function parseLanguage(className: string): string | undefined {
|
||||
|
@ -114,7 +114,8 @@ export function parseLines(
|
|||
let code = content.replace(/\n$/, '');
|
||||
// Highlighted lines specified in props: don't parse the content
|
||||
if (metastring && highlightLinesRangeRegex.test(metastring)) {
|
||||
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)![1];
|
||||
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)!
|
||||
.groups!.range;
|
||||
const highlightLines = rangeParser(highlightLinesRange)
|
||||
.filter((n) => n > 0)
|
||||
.map((n) => n - 1);
|
||||
|
|
|
@ -116,7 +116,7 @@ describe('createExcerpt', () => {
|
|||
|
||||
export function ItemCol(props) { return <Item {...props} className={'col col--6 margin-bottom--lg'}/> };
|
||||
|
||||
Lorem **ipsum** dolor sit \`amet\`[^1], consectetur _adipiscing_ elit. [**Vestibulum**](https://wiktionary.org/wiki/vestibulum) ex urna[^bignote], ~molestie~ et sagittis ut, varius ac justo :wink:.
|
||||
Lorem **ipsum** dolor sit \`amet\`[^1], consectetur _adipiscing_ elit. [**Vestibulum**](https://wiktionary.org/wiki/vestibulum) ex urna[^bignote], ~~molestie~~ et sagittis ut, varius ac justo :wink:.
|
||||
|
||||
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
||||
`),
|
||||
|
|
|
@ -69,8 +69,8 @@ export async function generate(
|
|||
}
|
||||
}
|
||||
|
||||
const indexRE = /(^|.*\/)index\.(md|mdx|js|jsx|ts|tsx)$/i;
|
||||
const extRE = /\.(md|mdx|js|jsx|ts|tsx)$/;
|
||||
const indexRE = /(?<dirname>^|.*\/)index\.(?:mdx?|jsx?|tsx?)$/i;
|
||||
const extRE = /\.(?:mdx?|jsx?|tsx?)$/;
|
||||
|
||||
/**
|
||||
* Convert filepath to url path.
|
||||
|
|
|
@ -67,11 +67,11 @@ export function replaceMarkdownLinks<T extends ContentPaths>({
|
|||
// ink
|
||||
// [doc1]: doc1.md -> we replace this doc1.md with correct link
|
||||
const mdRegex =
|
||||
/(?:(?:\]\()|(?:\]:\s?))(?!https?:\/\/|@site\/)([^'")\]\s>]+\.mdx?)/g;
|
||||
/(?:(?:\]\()|(?:\]:\s?))(?!https?:\/\/|@site\/)(?<filename>[^'")\]\s>]+\.mdx?)/g;
|
||||
let mdMatch = mdRegex.exec(modifiedLine);
|
||||
while (mdMatch !== null) {
|
||||
// Replace it to correct html link.
|
||||
const mdLink = mdMatch[1];
|
||||
const mdLink = mdMatch.groups!.filename;
|
||||
|
||||
const sourcesToTry = [
|
||||
path.resolve(path.dirname(filePath), decodeURIComponent(mdLink)),
|
||||
|
|
|
@ -14,12 +14,12 @@ export function parseMarkdownHeadingId(heading: string): {
|
|||
text: string;
|
||||
id?: string;
|
||||
} {
|
||||
const customHeadingIdRegex = /^(.*?)\s*\{#([\w-]+)\}$/;
|
||||
const customHeadingIdRegex = /^(?<text>.*?)\s*\{#(?<id>[\w-]+)\}$/;
|
||||
const matches = customHeadingIdRegex.exec(heading);
|
||||
if (matches) {
|
||||
return {
|
||||
text: matches[1],
|
||||
id: matches[2],
|
||||
text: matches.groups!.text,
|
||||
id: matches.groups!.id,
|
||||
};
|
||||
}
|
||||
return {text: heading, id: undefined};
|
||||
|
@ -46,7 +46,7 @@ export function createExcerpt(fileString: string): string | undefined {
|
|||
}
|
||||
|
||||
// Skip import/export declaration.
|
||||
if (/^\s*?import\s.*(from.*)?;?|export\s.*{.*};?/.test(fileLine)) {
|
||||
if (/^(?:import|export)\s.*/.test(fileLine)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -71,25 +71,27 @@ export function createExcerpt(fileString: string): string | undefined {
|
|||
// Remove HTML tags.
|
||||
.replace(/<[^>]*>/g, '')
|
||||
// Remove Title headers
|
||||
.replace(/^#\s*([^#]*)\s*#?/gm, '')
|
||||
.replace(/^#\s*[^#]*\s*#?/gm, '')
|
||||
// Remove Markdown + ATX-style headers
|
||||
.replace(/^#{1,6}\s*([^#]*)\s*(#{1,6})?/gm, '$1')
|
||||
// Remove emphasis and strikethroughs.
|
||||
.replace(/([*_~]{1,3})(\S.*?\S{0,1})\1/g, '$2')
|
||||
.replace(/^#{1,6}\s*(?<text>[^#]*)\s*(?:#{1,6})?/gm, '$1')
|
||||
// Remove emphasis.
|
||||
.replace(/(?<opening>[*_]{1,3})(?<text>.*?)\1/g, '$2')
|
||||
// Remove strikethroughs.
|
||||
.replace(/~~(?<text>\S.*\S)~~/g, '$1')
|
||||
// Remove images.
|
||||
.replace(/!\[(.*?)\][[(].*?[\])]/g, '$1')
|
||||
.replace(/!\[(?<alt>.*?)\][[(].*?[\])]/g, '$1')
|
||||
// Remove footnotes.
|
||||
.replace(/\[\^.+?\](: .*?$)?/g, '')
|
||||
.replace(/\[\^.+?\](?:: .*?$)?/g, '')
|
||||
// Remove inline links.
|
||||
.replace(/\[(.*?)\][[(].*?[\])]/g, '$1')
|
||||
.replace(/\[(?<alt>.*?)\][[(].*?[\])]/g, '$1')
|
||||
// Remove inline code.
|
||||
.replace(/`(.+?)`/g, '$1')
|
||||
.replace(/`(?<text>.+?)`/g, '$1')
|
||||
// Remove blockquotes.
|
||||
.replace(/^\s{0,3}>\s?/g, '')
|
||||
// Remove admonition definition.
|
||||
.replace(/(:{3}.*)/, '')
|
||||
.replace(/:::.*/, '')
|
||||
// Remove Emoji names within colons include preceding whitespace.
|
||||
.replace(/\s?(:(::|[^:\n])+:)/g, '')
|
||||
.replace(/\s?:(?:::|[^:\n])+:/g, '')
|
||||
// Remove custom Markdown heading id.
|
||||
.replace(/{#*[\w-]+}/, '')
|
||||
.trim();
|
||||
|
@ -134,9 +136,9 @@ export function parseMarkdownContentTitle(
|
|||
const content = contentUntrimmed.trim();
|
||||
|
||||
const IMPORT_STATEMENT =
|
||||
/import\s+(([\w*{}\s\n,]+)from\s+)?["'\s]([@\w/_.-]+)["'\s];?|\n/.source;
|
||||
/import\s+(?:[\w*{}\s\n,]+from\s+)?["'\s][@\w/_.-]+["'\s];?|\n/.source;
|
||||
const REGULAR_TITLE =
|
||||
/(?<pattern>#\s*(?<title>[^#\n{]*)+[ \t]*(?<suffix>({#*[\w-]+})|#)?\n*?)/
|
||||
/(?<pattern>#\s*(?<title>[^#\n{]*)+[ \t]*(?<suffix>(?:{#*[\w-]+})|#)?\n*?)/
|
||||
.source;
|
||||
const ALTERNATE_TITLE = /(?<pattern>\s*(?<title>[^\n]*)\s*\n[=]+)/.source;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ export function normalizeUrl(rawUrls: string[]): string {
|
|||
// There must be two or three slashes in the file protocol,
|
||||
// two slashes in anything else.
|
||||
const replacement = urls[0].match(/^file:\/\/\//) ? '$1:///' : '$1://';
|
||||
urls[0] = urls[0].replace(/^([^/:]+):\/*/, replacement);
|
||||
urls[0] = urls[0].replace(/^(?<protocol>[^/:]+):\/*/, replacement);
|
||||
|
||||
for (let i = 0; i < urls.length; i += 1) {
|
||||
let component = urls[i];
|
||||
|
@ -70,14 +70,14 @@ export function normalizeUrl(rawUrls: string[]): string {
|
|||
// except the possible first plain protocol part.
|
||||
|
||||
// Remove trailing slash before parameters or hash.
|
||||
str = str.replace(/\/(\?|&|#[^!])/g, '$1');
|
||||
str = str.replace(/\/(?<search>\?|&|#[^!])/g, '$1');
|
||||
|
||||
// Replace ? in parameters with &.
|
||||
const parts = str.split('?');
|
||||
str = parts.shift() + (parts.length > 0 ? '?' : '') + parts.join('&');
|
||||
|
||||
// Dedupe forward slashes in the entire path, avoiding protocol slashes.
|
||||
str = str.replace(/([^:/]\/)\/+/g, '$1');
|
||||
str = str.replace(/(?<textBefore>[^:/]\/)\/+/g, '$1');
|
||||
|
||||
// Dedupe forward slashes at the beginning of the path.
|
||||
str = str.replace(/^\/+/g, '/');
|
||||
|
|
|
@ -79,12 +79,12 @@ export function getFileLoaderUtils(): FileLoaderUtils {
|
|||
*/
|
||||
images: () => ({
|
||||
use: [loaders.url({folder: 'images'})],
|
||||
test: /\.(ico|jpg|jpeg|png|gif|webp)(\?.*)?$/,
|
||||
test: /\.(?:ico|jpe?g|png|gif|webp)(?:\?.*)?$/i,
|
||||
}),
|
||||
|
||||
fonts: () => ({
|
||||
use: [loaders.url({folder: 'fonts'})],
|
||||
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
||||
test: /\.(?:woff2?|eot|ttf|otf)$/i,
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -93,11 +93,11 @@ export function getFileLoaderUtils(): FileLoaderUtils {
|
|||
*/
|
||||
media: () => ({
|
||||
use: [loaders.url({folder: 'medias'})],
|
||||
test: /\.(mp4|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/,
|
||||
test: /\.(?:mp4|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/i,
|
||||
}),
|
||||
|
||||
svg: () => ({
|
||||
test: /\.svg?$/,
|
||||
test: /\.svg$/i,
|
||||
oneOf: [
|
||||
{
|
||||
use: [
|
||||
|
@ -126,7 +126,7 @@ export function getFileLoaderUtils(): FileLoaderUtils {
|
|||
// We don't want to use SVGR loader for non-React source code
|
||||
// ie we don't want to use SVGR for CSS files...
|
||||
issuer: {
|
||||
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
||||
and: [/\.(?:tsx?|jsx?|mdx?)$/i],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -137,7 +137,7 @@ export function getFileLoaderUtils(): FileLoaderUtils {
|
|||
|
||||
otherAssets: () => ({
|
||||
use: [loaders.file({folder: 'files'})],
|
||||
test: /\.(pdf|doc|docx|xls|xlsx|zip|rar)$/,
|
||||
test: /\.(?:pdf|docx?|xlsx?|zip|rar)$/i,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ const canPreload = (routePath: string) =>
|
|||
// Remove the last part containing the route hash
|
||||
// input: /blog/2018/12/14/Happy-First-Birthday-Slash-fe9
|
||||
// output: /blog/2018/12/14/Happy-First-Birthday-Slash
|
||||
const removeRouteNameHash = (str: string) => str.replace(/(-[^-]+)$/, '');
|
||||
const removeRouteNameHash = (str: string) => str.replace(/-[^-]+$/, '');
|
||||
|
||||
const getChunkNamesToLoad = (path: string): string[] =>
|
||||
Object.entries(routesChunkNames)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
export function hasProtocol(url: string): boolean {
|
||||
return /^(\w*:|\/\/)/.test(url) === true;
|
||||
return /^(?:\w*:|\/\/)/.test(url) === true;
|
||||
}
|
||||
|
||||
export default function isInternalUrl(url?: string): boolean {
|
||||
|
|
|
@ -54,7 +54,7 @@ export default async function render(
|
|||
${(e as Error).stack!}`;
|
||||
|
||||
const isNotDefinedErrorRegex =
|
||||
/(window|document|localStorage|navigator|alert|location|buffer|self) is not defined/i;
|
||||
/(?:window|document|localStorage|navigator|alert|location|buffer|self) is not defined/i;
|
||||
|
||||
if (isNotDefinedErrorRegex.test((e as Error).message)) {
|
||||
logger.info`It looks like you are using code that should run on the client-side only.
|
||||
|
|
|
@ -66,7 +66,7 @@ export function hasSSHProtocol(sourceRepoUrl: string): boolean {
|
|||
return false;
|
||||
} catch {
|
||||
// Fails when there isn't a protocol
|
||||
return /^([\w-]+@)?[\w.-]+:[\w./_-]+(\.git)?/.test(sourceRepoUrl); // git@github.com:facebook/docusaurus.git
|
||||
return /^(?:[\w-]+@)?[\w.-]+:[\w./_-]+/.test(sourceRepoUrl); // git@github.com:facebook/docusaurus.git
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ export function getPluginNames(plugins: PluginConfig[]): string[] {
|
|||
|
||||
const formatComponentName = (componentName: string): string =>
|
||||
componentName
|
||||
.replace(/(\/|\\)index\.(js|tsx|ts|jsx)/, '')
|
||||
.replace(/\.(js|tsx|ts|jsx)/, '');
|
||||
.replace(/[\\/]index\.(?:jsx?|tsx?)/, '')
|
||||
.replace(/\.(?:jsx?|tsx?)/, '');
|
||||
|
||||
function readComponent(themePath: string) {
|
||||
function walk(dir: string): Array<string> {
|
||||
|
|
|
@ -23,7 +23,7 @@ type Options = {
|
|||
};
|
||||
|
||||
function unwrapMarkdownLinks(line: string): string {
|
||||
return line.replace(/\[([^\]]+)\]\([^)]+\)/g, (match, p1) => p1);
|
||||
return line.replace(/\[(?<alt>[^\]]+)\]\([^)]+\)/g, (match, p1) => p1);
|
||||
}
|
||||
|
||||
function addHeadingId(
|
||||
|
|
|
@ -85,7 +85,7 @@ describe('loadConfig', () => {
|
|||
'docusaurus.config.js',
|
||||
);
|
||||
await expect(loadConfig(siteDir)).rejects.toThrowError(
|
||||
/Config file at "(.*?)__fixtures__[/\\]nonExisting[/\\]docusaurus.config.js" not found.$/,
|
||||
/Config file at ".*?__fixtures__[/\\]nonExisting[/\\]docusaurus.config.js" not found.$/,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -260,7 +260,7 @@ function createMDXFallbackPlugin({
|
|||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /(\.mdx?)$/,
|
||||
test: /\.mdx?$/i,
|
||||
exclude: getMDXFallbackExcludedPaths(),
|
||||
use: [
|
||||
getJSLoader({isServer}),
|
||||
|
|
|
@ -14,7 +14,7 @@ export function getNamePatterns(
|
|||
if (!moduleName.includes('/')) {
|
||||
return [`${moduleName}/docusaurus-${moduleType}`];
|
||||
}
|
||||
const [scope, packageName] = moduleName.split(/\/(.*)/);
|
||||
const [scope, packageName] = moduleName.split(/\/(?<rest>.*)/);
|
||||
return [
|
||||
`${scope}/${packageName}`,
|
||||
`${scope}/docusaurus-${moduleType}-${packageName}`,
|
||||
|
|
|
@ -28,7 +28,7 @@ type RegistryMap = {
|
|||
|
||||
function indent(str: string) {
|
||||
const spaces = ' ';
|
||||
return `${spaces}${str.replace(/(\n)/g, `\n${spaces}`)}`;
|
||||
return `${spaces}${str.replace(/\n/g, `\n${spaces}`)}`;
|
||||
}
|
||||
|
||||
const createRouteCodeString = ({
|
||||
|
|
|
@ -19,8 +19,8 @@ import {
|
|||
import {loadPluginsThemeAliases} from '../server/themes';
|
||||
import {md5Hash, getFileLoaderUtils} from '@docusaurus/utils';
|
||||
|
||||
const CSS_REGEX = /\.css$/;
|
||||
const CSS_MODULE_REGEX = /\.module\.css$/;
|
||||
const CSS_REGEX = /\.css$/i;
|
||||
const CSS_MODULE_REGEX = /\.module\.css$/i;
|
||||
export const clientDir = path.join(__dirname, '..', 'client');
|
||||
|
||||
const LibrariesToTranspile = [
|
||||
|
@ -39,7 +39,7 @@ export function excludeJS(modulePath: string): boolean {
|
|||
// Don't transpile node_modules except any docusaurus npm package
|
||||
return (
|
||||
/node_modules/.test(modulePath) &&
|
||||
!/(docusaurus)((?!node_modules).)*\.jsx?$/.test(modulePath) &&
|
||||
!/docusaurus(?:(?!node_modules).)*\.jsx?$/.test(modulePath) &&
|
||||
!LibrariesToTranspileRegex.test(modulePath)
|
||||
);
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ export function createBaseConfig(
|
|||
fileLoaderUtils.rules.svg(),
|
||||
fileLoaderUtils.rules.otherAssets(),
|
||||
{
|
||||
test: /\.(j|t)sx?$/,
|
||||
test: /\.[jt]sx?$/i,
|
||||
exclude: excludeJS,
|
||||
use: [
|
||||
getCustomizableJSLoader(siteConfig.webpack?.jsLoader)({
|
||||
|
|
|
@ -29,27 +29,26 @@ async function lqipLoader(
|
|||
|
||||
let content = contentBuffer.toString('utf8');
|
||||
const contentIsUrlExport =
|
||||
/^(?:export default|module.exports =) "data:(.*)base64,(.*)/.test(content);
|
||||
const contentIsFileExport = /^(?:export default|module.exports =) (.*)/.test(
|
||||
/^(?:export default|module.exports =) "data:.*base64,.*/.test(content);
|
||||
const contentIsFileExport = /^(?:export default|module.exports =) .*/.test(
|
||||
content,
|
||||
);
|
||||
|
||||
let source = '';
|
||||
const SOURCE_CHUNK = 1;
|
||||
|
||||
if (contentIsUrlExport) {
|
||||
source = content.match(/^(?:export default|module.exports =) (.*)/)![
|
||||
SOURCE_CHUNK
|
||||
];
|
||||
source = content.match(
|
||||
/^(?:export default|module.exports =) (?<source>.*)/,
|
||||
)!.groups!.source;
|
||||
} else {
|
||||
if (!contentIsFileExport) {
|
||||
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
|
||||
const fileLoader = require('file-loader');
|
||||
content = fileLoader.call(this, contentBuffer);
|
||||
}
|
||||
source = content.match(/^(?:export default|module.exports =) (.*);/)![
|
||||
SOURCE_CHUNK
|
||||
];
|
||||
source = content.match(
|
||||
/^(?:export default|module.exports =) (?<source>.*);/,
|
||||
)!.groups!.source;
|
||||
}
|
||||
|
||||
const outputPromises: [Promise<string> | null, Promise<string[]> | null] = [
|
||||
|
|
|
@ -60,7 +60,7 @@ function processSection(section) {
|
|||
});
|
||||
}
|
||||
let hour = 20;
|
||||
const date = title.match(/ \((.*)\)/)[1];
|
||||
const date = title.match(/ \((?<date>.*)\)/)?.groups.date;
|
||||
while (publishTimes.has(`${date}T${hour}:00`)) {
|
||||
hour -= 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue