From fa767eb880c0edf9ea19e8a8542ec290d041e274 Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Tue, 29 Nov 2022 17:58:56 +0100 Subject: [PATCH 1/2] Improve performance of control comments in postcss-custom-properties Co-authored-by: Marvin Hagemeister --- .../postcss-custom-properties/CHANGELOG.md | 4 ++ .../lib/get-custom-properties-from-root.ts | 22 ++++++----- .../src/lib/is-ignored.ts | 37 +++++++++++++------ .../src/lib/transform-properties.ts | 4 +- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/plugins/postcss-custom-properties/CHANGELOG.md b/plugins/postcss-custom-properties/CHANGELOG.md index 4693432ee..ec10fd379 100644 --- a/plugins/postcss-custom-properties/CHANGELOG.md +++ b/plugins/postcss-custom-properties/CHANGELOG.md @@ -1,5 +1,9 @@ # Changes to PostCSS Custom Properties +### Unreleased + +- Improve plugin performance + ### 12.1.10 (October 20, 2022) - Fix how `preserve: false` interacts with logic around duplicate code (see `12.1.9`). diff --git a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts b/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts index e177478fa..1ea953d63 100644 --- a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts +++ b/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts @@ -1,15 +1,18 @@ import valuesParser from 'postcss-value-parser'; -import { isBlockIgnored } from './is-ignored'; +import { isBlockIgnored, isDeclarationIgnored } from './is-ignored'; // return custom selectors from the css root, conditionally removing them export default function getCustomPropertiesFromRoot(root, opts): Map { // initialize custom selectors - const customPropertiesFromHtmlElement: Map = new Map(); - const customPropertiesFromRootPseudo: Map = new Map(); - const out: Map = new Map(); + const customPropertiesFromHtmlElement: Map = new Map(); + const customPropertiesFromRootPseudo: Map = new Map(); // for each html or :root rule root.nodes.slice().forEach(rule => { + if (isBlockIgnored(rule)) { + return; + } + const customPropertiesObject = isHtmlRule(rule) ? customPropertiesFromHtmlElement : isRootRule(rule) @@ -19,11 +22,11 @@ export default function getCustomPropertiesFromRoot(root, opts): Map { - if (decl.variable && !isBlockIgnored(decl)) { + if (decl.variable && !isDeclarationIgnored(decl)) { const { prop } = decl; // write the parsed value to the custom property - customPropertiesObject.set(prop, valuesParser(decl.value)); + customPropertiesObject.set(prop, decl.value); // conditionally remove the custom property declaration if (!opts.preserve) { @@ -33,18 +36,19 @@ export default function getCustomPropertiesFromRoot(root, opts): Map = new Map(); for (const [name, value] of customPropertiesFromHtmlElement.entries()) { - out.set(name, value); + out.set(name, valuesParser(value)); } for (const [name, value] of customPropertiesFromRootPseudo.entries()) { - out.set(name, value); + out.set(name, valuesParser(value)); } // return all custom properties, preferring :root properties over html properties diff --git a/plugins/postcss-custom-properties/src/lib/is-ignored.ts b/plugins/postcss-custom-properties/src/lib/is-ignored.ts index e1c5ccc5c..2ef388409 100644 --- a/plugins/postcss-custom-properties/src/lib/is-ignored.ts +++ b/plugins/postcss-custom-properties/src/lib/is-ignored.ts @@ -1,20 +1,35 @@ -function isBlockIgnored(ruleOrDeclaration) { - const rule = ruleOrDeclaration.selector ? - ruleOrDeclaration : ruleOrDeclaration.parent; +import type { Comment, Container, Declaration, Node } from 'postcss'; - return /(!\s*)?postcss-custom-properties:\s*off\b/i.test(rule.toString()); +const blockRegExp = /(!\s*)?postcss-custom-properties:\s*off\b/i; + +const blockIgnoredCache = new WeakMap(); + +function isBlockIgnored(container: Container) { + if (blockIgnoredCache.has(container)) { + return blockIgnoredCache.get(container); + } + + const result = container.some((child) => isIgnoreComment(child, blockRegExp)); + blockIgnoredCache.set(container, result); + + return result; } -function isRuleIgnored(rule) { - const previous = rule.prev(); +const declarationRegExp = /(!\s*)?postcss-custom-properties:\s*ignore\s+next\b/i; + +function isDeclarationIgnored(decl: Declaration) { + if (decl.parent && isBlockIgnored(decl.parent)) { + return true; + } + + return isIgnoreComment(decl.prev(), declarationRegExp); +} - return Boolean(isBlockIgnored(rule) || - previous && - previous.type === 'comment' && - /(!\s*)?postcss-custom-properties:\s*ignore\s+next\b/i.test(previous.text)); +function isIgnoreComment(node: Node, regexp: RegExp) { + return node && node.type === 'comment' && regexp.test((node as Comment).text); } export { isBlockIgnored, - isRuleIgnored, + isDeclarationIgnored, }; diff --git a/plugins/postcss-custom-properties/src/lib/transform-properties.ts b/plugins/postcss-custom-properties/src/lib/transform-properties.ts index da2a8147a..f0ac25055 100644 --- a/plugins/postcss-custom-properties/src/lib/transform-properties.ts +++ b/plugins/postcss-custom-properties/src/lib/transform-properties.ts @@ -1,11 +1,11 @@ import valuesParser from 'postcss-value-parser'; import transformValueAST from './transform-value-ast'; -import { isRuleIgnored } from './is-ignored'; import { Declaration } from 'postcss'; +import { isDeclarationIgnored } from './is-ignored'; // transform custom pseudo selectors with custom selectors export default (decl, customProperties, opts) => { - if (isTransformableDecl(decl) && !isRuleIgnored(decl)) { + if (isTransformableDecl(decl) && !isDeclarationIgnored(decl)) { const originalValue = decl.value; const valueAST = valuesParser(originalValue); let value = transformValueAST(valueAST, customProperties); From e9ab89ecd636f5df551c975c2157806134db64fa Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Tue, 29 Nov 2022 18:26:29 +0100 Subject: [PATCH 2/2] fix --- .../postcss-custom-properties/src/lib/is-ignored.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/postcss-custom-properties/src/lib/is-ignored.ts b/plugins/postcss-custom-properties/src/lib/is-ignored.ts index 2ef388409..9c3842f76 100644 --- a/plugins/postcss-custom-properties/src/lib/is-ignored.ts +++ b/plugins/postcss-custom-properties/src/lib/is-ignored.ts @@ -5,6 +5,10 @@ const blockRegExp = /(!\s*)?postcss-custom-properties:\s*off\b/i; const blockIgnoredCache = new WeakMap(); function isBlockIgnored(container: Container) { + if (!container || !container.nodes) { + return false; + } + if (blockIgnoredCache.has(container)) { return blockIgnoredCache.get(container); } @@ -18,7 +22,11 @@ function isBlockIgnored(container: Container) { const declarationRegExp = /(!\s*)?postcss-custom-properties:\s*ignore\s+next\b/i; function isDeclarationIgnored(decl: Declaration) { - if (decl.parent && isBlockIgnored(decl.parent)) { + if (!decl) { + return false; + } + + if (isBlockIgnored(decl.parent)) { return true; }