From 22a73b7e75e8fbf7038488324ee245563301b1f2 Mon Sep 17 00:00:00 2001 From: MarkXian Date: Thu, 16 Jul 2026 10:38:17 +0800 Subject: [PATCH] Fix duplicated prefixed selectors on reformatted CSS The `already()` check compared `before.selector` to the generated prefixed selector with strict equality. Generated prefixed selectors always join the comma list with `', '`, so once an existing prefixed rule had its selector list reformatted (e.g. one selector per line by a formatter), the comparison failed and Autoprefixer inserted a duplicate prefixed rule on every run. Normalize the compared selector with `list.comma(...).join(', ')` so whitespace differences in the selector list no longer defeat the duplication check. Closes #1497 --- lib/selector.js | 4 +++- test/selector.test.js | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/selector.js b/lib/selector.js index 3aaa6ff36..efc7ed26d 100644 --- a/lib/selector.js +++ b/lib/selector.js @@ -38,10 +38,12 @@ class Selector extends Prefixer { return false } + let beforeSelector = list.comma(before.selector).join(', ') + let some = false for (let key in prefixeds[this.name]) { let prefixed = prefixeds[this.name][key] - if (before.selector === prefixed) { + if (beforeSelector === prefixed) { if (prefix === key) { return true } else { diff --git a/test/selector.test.js b/test/selector.test.js index edbab3a91..e45bb303c 100644 --- a/test/selector.test.js +++ b/test/selector.test.js @@ -86,6 +86,15 @@ test('finds prefixed even if unknown prefix is between', () => { is(selector.already(css.nodes[2], prefixeds, '-moz-'), true) }) +test('finds prefixed even if selector list was reformatted', () => { + let css = parse( + '.a::-moz-selection,\n.b::-moz-selection {}\n' + + '.a::selection,\n.b::selection {}' + ) + let prefixeds2 = selector.prefixeds(css.nodes[1]) + is(selector.already(css.nodes[1], prefixeds2, '-moz-'), true) +}) + test('adds prefix to selectors', () => { equal( selector.replace('body ::selection, input::selection, a', '-ms-'),