refactor: install eslint-plugin-regexp (#6906)

* refactor: install eslint-plugin-regexp

* simplify

* simplify

* fix
This commit is contained in:
Joshua Chen 2022-03-13 18:32:17 +08:00 committed by GitHub
parent 127183e70e
commit 3a4b9b4c30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 145 additions and 83 deletions

View file

@ -30,6 +30,7 @@ module.exports = {
'plugin:jest/recommended', 'plugin:jest/recommended',
'airbnb', 'airbnb',
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'plugin:regexp/recommended',
'prettier', 'prettier',
], ],
settings: { settings: {
@ -40,7 +41,7 @@ module.exports = {
}, },
}, },
reportUnusedDisableDirectives: true, reportUnusedDisableDirectives: true,
plugins: ['react-hooks', 'header', 'jest', '@typescript-eslint'], plugins: ['react-hooks', 'header', 'jest', '@typescript-eslint', 'regexp'],
rules: { rules: {
'array-callback-return': WARNING, 'array-callback-return': WARNING,
camelcase: WARNING, camelcase: WARNING,

View file

@ -146,7 +146,7 @@ function normalizePaths(value) {
// Convert win32 backslash's to forward slashes, \ -> /; // Convert win32 backslash's to forward slashes, \ -> /;
// ignore some that look like escape sequences. // ignore some that look like escape sequences.
(val) => val.replace(/\\(?!["])/g, '/'), (val) => val.replace(/\\(?!")/g, '/'),
]; ];
let result = value; let result = value;

View file

@ -89,6 +89,7 @@
"eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.29.3", "eslint-plugin-react": "^7.29.3",
"eslint-plugin-react-hooks": "^4.3.0", "eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-regexp": "^1.5.1",
"husky": "^7.0.4", "husky": "^7.0.4",
"image-size": "^1.0.1", "image-size": "^1.0.1",
"jest": "^27.5.1", "jest": "^27.5.1",

View file

@ -69,7 +69,7 @@ export function shouldQuotifyFrontMatter([key, value]: [
// TODO this is not ideal to have to maintain such a list of allowed chars // TODO this is not ideal to have to maintain such a list of allowed chars
// maybe we should quotify if gray-matter throws instead? // maybe we should quotify if gray-matter throws instead?
return !String(value).match( return !String(value).match(
// cSpell:ignore sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ // cSpell:ignore àáâãäåçèéêëìíîïðòóôõöùúûüýÿ
/^[\w .\-sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ!;,=+_?'`&#()[\]§%€$]+$/, /^[\w .\-àáâãäåçèéêëìíîïðòóôõöùúûüýÿ!;,=+?'`&#()[\]§%€$]+$/,
); );
} }

View file

@ -451,7 +451,7 @@ async function handleVersioning(context: MigrationContext) {
path.join(newDir, 'versions.json'), path.join(newDir, 'versions.json'),
); );
const versions = loadedVersions.reverse(); const versions = loadedVersions.reverse();
const versionRegex = new RegExp(`version-(${versions.join('|')})-`, 'mgi'); const versionRegex = new RegExp(`version-(${versions.join('|')})-`, 'gim');
await migrateVersionedSidebar(context, versions, versionRegex); await migrateVersionedSidebar(context, versions, versionRegex);
await fs.mkdirp(path.join(newDir, 'versioned_docs')); await fs.mkdirp(path.join(newDir, 'versioned_docs'));
await migrateVersionedDocs(context, versions, versionRegex); await migrateVersionedDocs(context, versions, versionRegex);

View file

@ -231,7 +231,7 @@ describe('docsVersion', () => {
expect(versions).toEqual(['1.0.0']); expect(versions).toEqual(['1.0.0']);
expect(consoleMock).toHaveBeenCalledWith( expect(consoleMock).toHaveBeenCalledWith(
expect.stringMatching( expect.stringMatching(
/.*\[SUCCESS\].* .*\[docs\].*: version .*1\.0\.0.* created!.*/, /.*\[SUCCESS\].*\[docs\].*: version .*1\.0\.0.* created!.*/,
), ),
); );
@ -286,7 +286,7 @@ describe('docsVersion', () => {
expect(versions).toEqual(['2.0.0', '1.0.1', '1.0.0', 'withSlugs']); expect(versions).toEqual(['2.0.0', '1.0.1', '1.0.0', 'withSlugs']);
expect(consoleMock).toHaveBeenCalledWith( expect(consoleMock).toHaveBeenCalledWith(
expect.stringMatching( expect.stringMatching(
/.*\[SUCCESS\].* .*\[docs\].*: version .*2\.0\.0.* created!.*/, /.*\[SUCCESS\].*\[docs\].*: version .*2\.0\.0.* created!.*/,
), ),
); );
@ -339,7 +339,7 @@ describe('docsVersion', () => {
expect(versions).toEqual(['2.0.0', '1.0.0']); expect(versions).toEqual(['2.0.0', '1.0.0']);
expect(consoleMock).toHaveBeenCalledWith( expect(consoleMock).toHaveBeenCalledWith(
expect.stringMatching( expect.stringMatching(
/.*\[SUCCESS\].* .*\[community\].*: version .*2.0.0.* created!.*/, /.*\[SUCCESS\].*\[community\].*: version .*2.0.0.* created!.*/,
), ),
); );

View file

@ -88,7 +88,7 @@ export async function cliDocsVersionCommand(
// Since we are going to create `version-${version}` folder, we need to make // Since we are going to create `version-${version}` folder, we need to make
// sure it's a valid pathname. // sure it's a valid pathname.
// eslint-disable-next-line no-control-regex // eslint-disable-next-line no-control-regex
if (/[<>:"|?*\x00-\x1F]/g.test(version)) { if (/[<>:"|?*\x00-\x1F]/.test(version)) {
throw new Error( throw new Error(
`${pluginIdLogPrefix}: invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0.`, `${pluginIdLogPrefix}: invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0.`,
); );

View file

@ -8,43 +8,33 @@
import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs'; import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs';
// Best-effort to avoid parsing some patterns as number prefix // Best-effort to avoid parsing some patterns as number prefix
const IgnoredPrefixPatterns = (() => {
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640 // ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
const DateLikePrefixRegex =
/^(?:\d{2}|\d{4})[-_.]\d{2}(?:[-_.](?:\d{2}|\d{4}))?.*$/;
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653 // ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
// note: we could try to parse float numbers in filenames but that is // Both of them would look like 7.0-foo or 2021-11-foo
// probably not worth it as a version such as "8.0" can be interpreted as both // note: we could try to parse float numbers in filenames, but that is probably
// a version and a float. User can configure her own NumberPrefixParser if // not worth it, as a version such as "8.0" can be interpreted as either a
// she wants 8.0 to be interpreted as a float // version or a float. User can configure her own NumberPrefixParser if she
const VersionLikePrefixRegex = /^\d+[-_.]\d+.*$/; // wants 8.0 to be interpreted as a float
const ignoredPrefixPattern = /^\d+[-_.]\d+/;
return new RegExp( const numberPrefixPattern =
`${DateLikePrefixRegex.source}|${VersionLikePrefixRegex.source}`, /^(?<numberPrefix>\d+)\s*[-_.]+\s*(?<suffix>[^-_.\s].*)$/;
);
})();
const NumberPrefixRegex =
/^(?<numberPrefix>\d+)(?<separator>\s*[-_.]+\s*)(?<suffix>.*)$/;
// 0-myDoc => {filename: myDoc, numberPrefix: 0} // 0-myDoc => {filename: myDoc, numberPrefix: 0}
// 003 - myDoc => {filename: myDoc, numberPrefix: 3} // 003 - myDoc => {filename: myDoc, numberPrefix: 3}
export const DefaultNumberPrefixParser: NumberPrefixParser = ( export const DefaultNumberPrefixParser: NumberPrefixParser = (
filename: string, filename: string,
) => { ) => {
if (IgnoredPrefixPatterns.exec(filename)) { if (ignoredPrefixPattern.test(filename)) {
return {filename, numberPrefix: undefined};
}
const match = numberPrefixPattern.exec(filename);
if (!match) {
return {filename, numberPrefix: undefined}; return {filename, numberPrefix: undefined};
} }
const match = NumberPrefixRegex.exec(filename);
const cleanFileName = match?.groups?.suffix ?? filename;
const numberPrefixString = match?.groups?.numberPrefix;
const numberPrefix = numberPrefixString
? parseInt(numberPrefixString, 10)
: undefined;
return { return {
filename: cleanFileName, filename: match.groups!.suffix!,
numberPrefix, numberPrefix: parseInt(match.groups!.numberPrefix!, 10),
}; };
}; };

View file

@ -44,7 +44,7 @@ describe('DefaultSidebarItemsGenerator', () => {
expect(sidebarSlice).toEqual([]); expect(sidebarSlice).toEqual([]);
expect(consoleWarn).toHaveBeenCalledWith( expect(consoleWarn).toHaveBeenCalledWith(
expect.stringMatching( expect.stringMatching(
/.*\[WARNING\].* No docs found in .*\..*: can't auto-generate a sidebar\..*/, /.*\[WARNING\].* No docs found in [^.]*\..*: can't auto-generate a sidebar\..*/,
), ),
); );
}); });

View file

@ -134,12 +134,12 @@ describe('loadSidebars', () => {
).rejects.toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not allowed"`); ).rejects.toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not allowed"`);
expect(consoleWarnMock).toBeCalledWith( expect(consoleWarnMock).toBeCalledWith(
expect.stringMatching( expect.stringMatching(
/.*\[WARNING].* There are more than one category metadata files for .*foo.*: foo\/_category_.json, foo\/_category_.yml. The behavior is undetermined./, /.*\[WARNING\].* There are more than one category metadata files for .*foo.*: foo\/_category_.json, foo\/_category_.yml. The behavior is undetermined./,
), ),
); );
expect(consoleErrorMock).toBeCalledWith( expect(consoleErrorMock).toBeCalledWith(
expect.stringMatching( expect.stringMatching(
/.*\[ERROR].* The docs sidebar category metadata file .*foo\/_category_.json.* looks invalid!/, /.*\[ERROR\].* The docs sidebar category metadata file .*foo\/_category_.json.* looks invalid!/,
), ),
); );
}); });

View file

@ -8,7 +8,7 @@
import rangeParser from 'parse-numeric-range'; import rangeParser from 'parse-numeric-range';
const codeBlockTitleRegex = /title=(?<quote>["'])(?<title>.*?)\1/; const codeBlockTitleRegex = /title=(?<quote>["'])(?<title>.*?)\1/;
const highlightLinesRangeRegex = /{(?<range>[\d,-]+)}/; const highlightLinesRangeRegex = /\{(?<range>[\d,-]+)\}/;
const commentTypes = ['js', 'jsBlock', 'jsx', 'python', 'html'] as const; const commentTypes = ['js', 'jsBlock', 'jsx', 'python', 'html'] as const;
type CommentType = typeof commentTypes[number]; type CommentType = typeof commentTypes[number];

View file

@ -11,7 +11,7 @@ import type {Tag} from '@docusaurus/utils';
import {JoiFrontMatter} from './JoiFrontMatter'; import {JoiFrontMatter} from './JoiFrontMatter';
export const PluginIdSchema = Joi.string() export const PluginIdSchema = Joi.string()
.regex(/^[a-zA-Z0-9_-]+$/) .regex(/^[\w-]+$/)
.message( .message(
'Illegal plugin ID value "{#value}": it should only contain alphanumerics, underscores, and dashes.', 'Illegal plugin ID value "{#value}": it should only contain alphanumerics, underscores, and dashes.',
) )

View file

@ -169,14 +169,16 @@ describe('reportMessage', () => {
`"Unexpected \\"reportingSeverity\\" value: foo."`, `"Unexpected \\"reportingSeverity\\" value: foo."`,
); );
expect(consoleLog).toBeCalledTimes(1); expect(consoleLog).toBeCalledTimes(1);
expect(consoleLog).toBeCalledWith(expect.stringMatching(/.*\[INFO].* hey/)); expect(consoleLog).toBeCalledWith(
expect.stringMatching(/.*\[INFO\].* hey/),
);
expect(consoleWarn).toBeCalledTimes(1); expect(consoleWarn).toBeCalledTimes(1);
expect(consoleWarn).toBeCalledWith( expect(consoleWarn).toBeCalledWith(
expect.stringMatching(/.*\[WARNING].* hey/), expect.stringMatching(/.*\[WARNING\].* hey/),
); );
expect(consoleError).toBeCalledTimes(1); expect(consoleError).toBeCalledTimes(1);
expect(consoleError).toBeCalledWith( expect(consoleError).toBeCalledWith(
expect.stringMatching(/.*\[ERROR].* hey/), expect.stringMatching(/.*\[ERROR\].* hey/),
); );
}); });
}); });

View file

@ -404,7 +404,7 @@ Lorem Ipsum
expect( expect(
parseMarkdownContentTitle(markdown, {removeContentTitle: true}), parseMarkdownContentTitle(markdown, {removeContentTitle: true}),
).toEqual({ ).toEqual({
content: markdown.trim().replace('# Markdown Title', ''), content: markdown.trim().replace('# Markdown Title\n', ''),
contentTitle: 'Markdown Title', contentTitle: 'Markdown Title',
}); });
}); });
@ -444,7 +444,7 @@ Lorem Ipsum
expect( expect(
parseMarkdownContentTitle(markdown, {removeContentTitle: true}), parseMarkdownContentTitle(markdown, {removeContentTitle: true}),
).toEqual({ ).toEqual({
content: markdown.replace('Markdown Title\n==============\n\n', ''), content: markdown.replace('Markdown Title\n==============\n', ''),
contentTitle: 'Markdown Title', contentTitle: 'Markdown Title',
}); });
}); });
@ -547,7 +547,7 @@ Lorem Ipsum
expect( expect(
parseMarkdownContentTitle(markdown, {removeContentTitle: true}), parseMarkdownContentTitle(markdown, {removeContentTitle: true}),
).toEqual({ ).toEqual({
content: markdown.replace('# Markdown Title', ''), content: markdown.replace('# Markdown Title\n', ''),
contentTitle: 'Markdown Title', contentTitle: 'Markdown Title',
}); });
}); });

View file

@ -68,7 +68,7 @@ export function replaceMarkdownLinks<T extends ContentPaths>({
// ink // ink
// [doc1]: doc1.md -> we replace this doc1.md with correct link // [doc1]: doc1.md -> we replace this doc1.md with correct link
const mdRegex = const mdRegex =
/(?:(?:\]\()|(?:\]:\s*))(?!https?:\/\/|@site\/)(?<filename>[^'")\]\s>]+\.mdx?)/g; /(?:\]\(|\]:\s*)(?!https?:\/\/|@site\/)(?<filename>[^'")\]\s>]+\.mdx?)/g;
let mdMatch = mdRegex.exec(modifiedLine); let mdMatch = mdRegex.exec(modifiedLine);
while (mdMatch !== null) { while (mdMatch !== null) {
// Replace it to correct html link. // Replace it to correct html link.

View file

@ -14,11 +14,11 @@ export function parseMarkdownHeadingId(heading: string): {
text: string; text: string;
id?: string; id?: string;
} { } {
const customHeadingIdRegex = /^(?<text>.*?)\s*\{#(?<id>[\w-]+)\}$/; const customHeadingIdRegex = /\s*\{#(?<id>[\w-]+)\}$/;
const matches = customHeadingIdRegex.exec(heading); const matches = customHeadingIdRegex.exec(heading);
if (matches) { if (matches) {
return { return {
text: matches.groups!.text!, text: heading.replace(matches[0]!, ''),
id: matches.groups!.id!, id: matches.groups!.id!,
}; };
} }
@ -69,9 +69,9 @@ export function createExcerpt(fileString: string): string | undefined {
// Remove HTML tags. // Remove HTML tags.
.replace(/<[^>]*>/g, '') .replace(/<[^>]*>/g, '')
// Remove Title headers // Remove Title headers
.replace(/^#\s*[^#]*\s*#?/gm, '') .replace(/^#[^#]+#?/gm, '')
// Remove Markdown + ATX-style headers // Remove Markdown + ATX-style headers
.replace(/^#{1,6}\s*(?<text>[^#]*)\s*(?:#{1,6})?/gm, '$1') .replace(/^#{1,6}\s*(?<text>[^#]*)\s*#{0,6}/gm, '$1')
// Remove emphasis. // Remove emphasis.
.replace(/(?<opening>[*_]{1,3})(?<text>.*?)\1/g, '$2') .replace(/(?<opening>[*_]{1,3})(?<text>.*?)\1/g, '$2')
// Remove strikethroughs. // Remove strikethroughs.
@ -79,7 +79,7 @@ export function createExcerpt(fileString: string): string | undefined {
// Remove images. // Remove images.
.replace(/!\[(?<alt>.*?)\][[(].*?[\])]/g, '$1') .replace(/!\[(?<alt>.*?)\][[(].*?[\])]/g, '$1')
// Remove footnotes. // Remove footnotes.
.replace(/\[\^.+?\](?:: .*?$)?/g, '') .replace(/\[\^.+?\](?:: .*$)?/g, '')
// Remove inline links. // Remove inline links.
.replace(/\[(?<alt>.*?)\][[(].*?[\])]/g, '$1') .replace(/\[(?<alt>.*?)\][[(].*?[\])]/g, '$1')
// Remove inline code. // Remove inline code.
@ -91,7 +91,7 @@ export function createExcerpt(fileString: string): string | undefined {
// Remove Emoji names within colons include preceding whitespace. // Remove Emoji names within colons include preceding whitespace.
.replace(/\s?:(?:::|[^:\n])+:/g, '') .replace(/\s?:(?:::|[^:\n])+:/g, '')
// Remove custom Markdown heading id. // Remove custom Markdown heading id.
.replace(/{#*[\w-]+}/, '') .replace(/\{#*[\w-]+\}/, '')
.trim(); .trim();
if (cleanedLine) { if (cleanedLine) {
@ -132,35 +132,42 @@ export function parseMarkdownContentTitle(
const removeContentTitleOption = options?.removeContentTitle ?? false; const removeContentTitleOption = options?.removeContentTitle ?? false;
const content = contentUntrimmed.trim(); const content = contentUntrimmed.trim();
// We only need to detect import statements that will be parsed by MDX as
// `import` nodes, as broken syntax can't render anyways. That means any block
// that has `import` at the very beginning and surrounded by empty lines.
const contentWithoutImport = content
.replace(/^(?:import\s(?:.|\n(?!\n))*\n{2,})*/, '')
.trim();
const IMPORT_STATEMENT = const regularTitleMatch = /^#[ \t]+(?<title>[^ \t].*)(?:\n|$)/.exec(
/import\s+(?:[\w*{}\s\n,]+from\s+)?["'\s][@\w/_.-]+["'\s];?|\n/.source; contentWithoutImport,
const REGULAR_TITLE = );
/(?<pattern>#\s*(?<title>[^#\n{]*)+[ \t]*(?<suffix>(?:{#*[\w-]+})|#)?\n*?)/ const alternateTitleMatch = /^(?<title>.*)\n=+(?:\n|$)/.exec(
.source; contentWithoutImport,
const ALTERNATE_TITLE = /(?<pattern>\s*(?<title>[^\n]*)\s*\n[=]+)/.source; );
const regularTitleMatch = new RegExp(
`^(?:${IMPORT_STATEMENT})*?${REGULAR_TITLE}`,
'g',
).exec(content);
const alternateTitleMatch = new RegExp(
`^(?:${IMPORT_STATEMENT})*?${ALTERNATE_TITLE}`,
'g',
).exec(content);
const titleMatch = regularTitleMatch ?? alternateTitleMatch; const titleMatch = regularTitleMatch ?? alternateTitleMatch;
const {pattern, title} = titleMatch?.groups ?? {}; if (!titleMatch) {
if (!pattern || !title) {
return {content, contentTitle: undefined}; return {content, contentTitle: undefined};
} }
const newContent = removeContentTitleOption const newContent = removeContentTitleOption
? content.replace(pattern, '') ? content.replace(titleMatch[0]!, '')
: content; : content;
if (regularTitleMatch) {
return { return {
content: newContent.trim(), content: newContent.trim(),
contentTitle: toTextContentTitle(title.trim()).trim(), contentTitle: toTextContentTitle(
regularTitleMatch
.groups!.title!.trim()
.replace(/\s*(?:\{#*[\w-]+\}|#+)$/, ''),
).trim(),
};
}
return {
content: newContent.trim(),
contentTitle: toTextContentTitle(
alternateTitleMatch!.groups!.title!.trim().replace(/\s*=+$/, ''),
).trim(),
}; };
} }

View file

@ -58,7 +58,7 @@ export function normalizeUrl(rawUrls: string[]): string {
if (i > 0) { if (i > 0) {
// Removing the starting slashes for each component but the first. // Removing the starting slashes for each component but the first.
component = component.replace( component = component.replace(
/^[/]+/, /^\/+/,
// Special case where the first element of rawUrls is empty // Special case where the first element of rawUrls is empty
// ["", "/hello"] => /hello // ["", "/hello"] => /hello
component[0] === '/' && !hasStartingSlash ? '/' : '', component[0] === '/' && !hasStartingSlash ? '/' : '',
@ -68,7 +68,7 @@ export function normalizeUrl(rawUrls: string[]): string {
hasEndingSlash = component[component.length - 1] === '/'; hasEndingSlash = component[component.length - 1] === '/';
// Removing the ending slashes for each component but the last. For the // Removing the ending slashes for each component but the last. For the
// last component we will combine multiple slashes to a single one. // last component we will combine multiple slashes to a single one.
component = component.replace(/[/]+$/, i < urls.length - 1 ? '' : '/'); component = component.replace(/\/+$/, i < urls.length - 1 ? '' : '/');
} }
hasStartingSlash = true; hasStartingSlash = true;

View file

@ -18,7 +18,7 @@ We don't ship a markdown parser nor a feature-complete i18n library on purpose.
More details here: https://github.com/facebook/docusaurus/pull/4295 More details here: https://github.com/facebook/docusaurus/pull/4295
*/ */
const ValueRegexp = /{\w+}/g; const ValueRegexp = /\{\w+\}/g;
const ValueFoundMarker = '{}'; // does not care much const ValueFoundMarker = '{}'; // does not care much
// If all the values are plain strings, then interpolate returns a simple string // If all the values are plain strings, then interpolate returns a simple string

View file

@ -66,7 +66,7 @@ export function hasSSHProtocol(sourceRepoUrl: string): boolean {
return false; return false;
} catch { } catch {
// Fails when there isn't a protocol // Fails when there isn't a protocol
return /^(?:[\w-]+@)?[\w.-]+:[\w./_-]+/.test(sourceRepoUrl); // git@github.com:facebook/docusaurus.git return /^(?:[\w-]+@)?[\w.-]+:[\w./-]+/.test(sourceRepoUrl); // git@github.com:facebook/docusaurus.git
} }
} }

View file

@ -37,7 +37,7 @@ function processSection(section) {
.trim() .trim()
.replace('running_woman', 'running'); .replace('running_woman', 'running');
let authors = content.match(/## Committers: \d+.*/ms); let authors = content.match(/## Committers: \d.*/s);
if (authors) { if (authors) {
authors = authors[0] authors = authors[0]
.match(/- .*/g) .match(/- .*/g)
@ -105,7 +105,7 @@ async function ChangelogPlugin(context, options) {
async loadContent() { async loadContent() {
const fileContent = await fs.readFile(changelogPath, 'utf-8'); const fileContent = await fs.readFile(changelogPath, 'utf-8');
const sections = fileContent const sections = fileContent
.split(/(?=\n## )/ms) .split(/(?=\n## )/)
.map(processSection) .map(processSection)
.filter(Boolean); .filter(Boolean);
await Promise.all( await Promise.all(

View file

@ -30,7 +30,7 @@ export default function plugin() {
const { const {
groups: {presetOptionName, presetOptionText}, groups: {presetOptionName, presetOptionText},
} = presetMeta.match( } = presetMeta.match(
/\/\/(?<presetOptionText>.*?): (?<presetOptionName>[A-Za-z]+)/i, /\/\/(?<presetOptionText>.*?): (?<presetOptionName>[A-Z]+)/i,
) ?? { ) ?? {
groups: { groups: {
presetOptionName: '[translation failure]', presetOptionName: '[translation failure]',
@ -40,7 +40,7 @@ export default function plugin() {
const { const {
groups: {pluginName, pluginText}, groups: {pluginName, pluginText},
} = pluginMeta.match( } = pluginMeta.match(
/\/\/(?<pluginText>.*?): (?<pluginName>[A-Za-z@/-]+)/i, /\/\/(?<pluginText>.*?): (?<pluginName>[A-Z@/-]+)/i,
) ?? { ) ?? {
groups: { groups: {
pluginName: '[translation failure]', pluginName: '[translation failure]',

View file

@ -100,7 +100,7 @@ export function updateDOMColors(
isDarkTheme: boolean, isDarkTheme: boolean,
): void { ): void {
const styleSheet = Array.from(document.styleSheets).find((item) => const styleSheet = Array.from(document.styleSheets).find((item) =>
item.href?.match(/styles(?:\.[0-9a-f]+)?\.css/), item.href?.match(/styles(?:\.[\da-f]+)?\.css/),
)!; )!;
const rules = Array.from(styleSheet.cssRules) as CSSStyleRule[]; const rules = Array.from(styleSheet.cssRules) as CSSStyleRule[];
// The rule that looks the most like definition for custom theme colors // The rule that looks the most like definition for custom theme colors

View file

@ -6559,6 +6559,11 @@ comment-json@^4.2.2:
has-own-prop "^2.0.0" has-own-prop "^2.0.0"
repeat-string "^1.6.1" repeat-string "^1.6.1"
comment-parser@^1.1.2:
version "1.3.0"
resolved "https://registry.npmmirror.com/comment-parser/-/comment-parser-1.3.0.tgz#68beb7dbe0849295309b376406730cd16c719c44"
integrity sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA==
common-path-prefix@^3.0.0: common-path-prefix@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0"
@ -8452,6 +8457,20 @@ eslint-plugin-react@^7.29.3:
semver "^6.3.0" semver "^6.3.0"
string.prototype.matchall "^4.0.6" string.prototype.matchall "^4.0.6"
eslint-plugin-regexp@^1.5.1:
version "1.5.1"
resolved "https://registry.npmmirror.com/eslint-plugin-regexp/-/eslint-plugin-regexp-1.5.1.tgz#982ea8936283035897d6bb1ba32c0ea5d9a4dee0"
integrity sha512-5v0rQIi54m2KycQHqmOAHrZhvI56GHmI2acr6zEffAqfeifTtobAEapv9Uf4o8//lGvwVkHKyjLoSbBNEFcfOA==
dependencies:
comment-parser "^1.1.2"
eslint-utils "^3.0.0"
grapheme-splitter "^1.0.4"
jsdoctypeparser "^9.0.0"
refa "^0.9.0"
regexp-ast-analysis "^0.3.0"
regexpp "^3.2.0"
scslre "^0.1.6"
eslint-scope@5.1.1, eslint-scope@^5.1.1: eslint-scope@5.1.1, eslint-scope@^5.1.1:
version "5.1.1" version "5.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
@ -9889,6 +9908,11 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
grapheme-splitter@^1.0.4:
version "1.0.4"
resolved "https://registry.npmmirror.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
graphql@16.0.0: graphql@16.0.0:
version "16.0.0" version "16.0.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.0.0.tgz#5724f2767aefa543418e83671372117c39408c8f" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.0.0.tgz#5724f2767aefa543418e83671372117c39408c8f"
@ -11869,6 +11893,11 @@ jscodeshift@^0.13.0:
temp "^0.8.4" temp "^0.8.4"
write-file-atomic "^2.3.0" write-file-atomic "^2.3.0"
jsdoctypeparser@^9.0.0:
version "9.0.0"
resolved "https://registry.npmmirror.com/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz#8c97e2fb69315eb274b0f01377eaa5c940bd7b26"
integrity sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==
jsdom@^16.6.0: jsdom@^16.6.0:
version "16.7.0" version "16.7.0"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
@ -16204,6 +16233,13 @@ redent@^3.0.0:
indent-string "^4.0.0" indent-string "^4.0.0"
strip-indent "^3.0.0" strip-indent "^3.0.0"
refa@^0.9.0:
version "0.9.1"
resolved "https://registry.npmmirror.com/refa/-/refa-0.9.1.tgz#12731fce378d235731b1f73182b20083c8a75ca8"
integrity sha512-egU8LgFq2VXlAfUi8Jcbr5X38wEOadMFf8tCbshgcpVCYlE7k84pJOSlnvXF+muDB4igkdVMq7Z/kiNPqDT9TA==
dependencies:
regexpp "^3.2.0"
regenerate-unicode-properties@^10.0.1: regenerate-unicode-properties@^10.0.1:
version "10.0.1" version "10.0.1"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
@ -16243,6 +16279,22 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2" extend-shallow "^3.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
regexp-ast-analysis@^0.2.3:
version "0.2.4"
resolved "https://registry.npmmirror.com/regexp-ast-analysis/-/regexp-ast-analysis-0.2.4.tgz#a497a7c8bfbba51438693821e4b0e3ed43e20f1b"
integrity sha512-8L7kOZQaKPxKKAwGuUZxTQtlO3WZ+tiXy4s6G6PKL6trbOXcZoumwC3AOHHFtI/xoSbNxt7jgLvCnP1UADLWqg==
dependencies:
refa "^0.9.0"
regexpp "^3.2.0"
regexp-ast-analysis@^0.3.0:
version "0.3.0"
resolved "https://registry.npmmirror.com/regexp-ast-analysis/-/regexp-ast-analysis-0.3.0.tgz#386f177dfe5abc5ac58b51eb5962beac64e898ce"
integrity sha512-11PlbBSUxwWpdj6BdZUKfhDdV9g+cveqHB+BqBQDBD7ZermDBVgtyowUaXTvT0dO3tZYo2bDIr/GoED6X1aYSA==
dependencies:
refa "^0.9.0"
regexpp "^3.2.0"
regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307"
@ -16868,6 +16920,15 @@ screenfull@^5.1.0:
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==
scslre@^0.1.6:
version "0.1.6"
resolved "https://registry.npmmirror.com/scslre/-/scslre-0.1.6.tgz#71a2832e4bf3a9254973a04fbed90aec94f75757"
integrity sha512-JORxVRlQTfjvlOAaiQKebgFElyAm5/W8b50lgaZ0OkEnKnagJW2ufDh3xRfU75UD9z3FGIu1gL1IyR3Poa6Qmw==
dependencies:
refa "^0.9.0"
regexp-ast-analysis "^0.2.3"
regexpp "^3.2.0"
section-matter@^1.0.0: section-matter@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167"