diff --git a/.changeset/short-onions-play.md b/.changeset/short-onions-play.md new file mode 100644 index 0000000000..6dd42a22ec --- /dev/null +++ b/.changeset/short-onions-play.md @@ -0,0 +1,5 @@ +--- +"stylelint": patch +--- + +Fixed: `{selector,value}-no-vendor-prefix` performance diff --git a/lib/reference/prefixes.js b/lib/reference/prefixes.js new file mode 100644 index 0000000000..2dade42655 --- /dev/null +++ b/lib/reference/prefixes.js @@ -0,0 +1,5 @@ +const prefixes = new Set(['-webkit-', '-moz-', '-ms-', '-o-']); + +module.exports = { + prefixes, +}; diff --git a/lib/rules/selector-no-vendor-prefix/index.js b/lib/rules/selector-no-vendor-prefix/index.js index ff8645d160..afe591a8f7 100644 --- a/lib/rules/selector-no-vendor-prefix/index.js +++ b/lib/rules/selector-no-vendor-prefix/index.js @@ -1,5 +1,6 @@ 'use strict'; +const hasPrefix = require('../../utils/hasPrefix'); const isAutoprefixable = require('../../utils/isAutoprefixable'); const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const optionsMatches = require('../../utils/optionsMatches'); @@ -41,6 +42,8 @@ const rule = (primary, secondaryOptions, context) => { } root.walkRules((ruleNode) => { + if (!hasPrefix(ruleNode.selector)) return; + if (!isStandardSyntaxRule(ruleNode)) { return; } diff --git a/lib/rules/value-no-vendor-prefix/index.js b/lib/rules/value-no-vendor-prefix/index.js index e17e0e7cfe..98452948be 100644 --- a/lib/rules/value-no-vendor-prefix/index.js +++ b/lib/rules/value-no-vendor-prefix/index.js @@ -2,6 +2,7 @@ const valueParser = require('postcss-value-parser'); +const hasPrefix = require('../../utils/hasPrefix'); const isAutoprefixable = require('../../utils/isAutoprefixable'); const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration'); const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty'); @@ -24,18 +25,6 @@ const meta = { fixable: true, }; -const valuePrefixes = ['-webkit-', '-moz-', '-ms-', '-o-']; - -/** - * @param {string} value - * @returns {boolean} - */ -const hasPrefix = (value) => { - const lowerValue = value.toLowerCase(); - - return valuePrefixes.some((prefix) => lowerValue.startsWith(prefix)); -}; - /** @type {import('stylelint').Rule} */ const rule = (primary, secondaryOptions, context) => { return (root, result) => { @@ -59,11 +48,9 @@ const rule = (primary, secondaryOptions, context) => { root.walkDecls((decl) => { const { value } = decl; - if ( - !isStandardSyntaxDeclaration(decl) || - !isStandardSyntaxProperty(decl.prop) || - !value.startsWith('-') - ) { + if (!hasPrefix(value)) return; + + if (!isStandardSyntaxDeclaration(decl) || !isStandardSyntaxProperty(decl.prop)) { return; } @@ -74,10 +61,6 @@ const rule = (primary, secondaryOptions, context) => { const parsedValue = valueParser(value); parsedValue.walk((node) => { - if (!hasPrefix(node.value)) { - return; - } - if (!isAutoprefixable.propertyValue(node.value)) { return; } diff --git a/lib/utils/hasPrefix.js b/lib/utils/hasPrefix.js new file mode 100644 index 0000000000..07023ca6d8 --- /dev/null +++ b/lib/utils/hasPrefix.js @@ -0,0 +1,15 @@ +'use strict'; + +const { prefixes } = require('../reference/prefixes'); + +const HAS_PREFIX_REGEX = new RegExp(`(?:${[...prefixes].join('|')})`, 'i'); + +/** + * Check if a string contains any prefix + * + * @param {string} string + * @returns {boolean} + */ +module.exports = function hasPrefix(string) { + return HAS_PREFIX_REGEX.test(string); +};