From 933606ad03edcbeaaee2c909eeec097c08aed31e Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Wed, 29 Mar 2023 11:39:28 -0400 Subject: [PATCH] Update important selector handling for :is and :has --- src/util/applyImportantSelector.js | 34 ++++++++++++++++++++---------- tests/important-selector.test.js | 7 ++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/util/applyImportantSelector.js b/src/util/applyImportantSelector.js index 69de63325c79..dbaf136cce20 100644 --- a/src/util/applyImportantSelector.js +++ b/src/util/applyImportantSelector.js @@ -1,19 +1,31 @@ import { splitAtTopLevelOnly } from './splitAtTopLevelOnly' +import parser from 'postcss-selector-parser' +import { collectPseudoElements, sortSelector } from './formatVariantSelector.js' export function applyImportantSelector(selector, important) { - let matches = /^(.*?)(:before|:after|::[\w-]+)(\)*)$/g.exec(selector) - if (!matches) return `${important} ${wrapWithIs(selector)}` + let sel = parser().astSync(selector) - let [, before, pseudo, brackets] = matches - return `${important} ${wrapWithIs(before + brackets)}${pseudo}` -} + sel.each((sel) => { + // Wrap with :is if it's not already wrapped + let isWrapped = + sel.nodes[0].type === 'pseudo' && + sel.nodes[0].value === ':is' && + sel.nodes.every((node) => node.type !== 'combinator') -function wrapWithIs(selector) { - let parts = splitAtTopLevelOnly(selector, ' ') + if (!isWrapped) { + sel.nodes = [ + parser.pseudo({ + value: ':is', + nodes: [sel.clone()], + }), + ] + } - if (parts.length === 1 && parts[0].startsWith(':is(') && parts[0].endsWith(')')) { - return selector - } + let [pseudoElements] = collectPseudoElements(sel) + if (pseudoElements.length > 0) { + sel.nodes.push(...pseudoElements.sort(sortSelector)) + } + }) - return `:is(${selector})` + return `${important} ${sel.toString()}` } diff --git a/tests/important-selector.test.js b/tests/important-selector.test.js index 5c6515e43086..22edafb94dd1 100644 --- a/tests/important-selector.test.js +++ b/tests/important-selector.test.js @@ -21,6 +21,7 @@ crosscheck(({ stable, oxide }) => {
+
`, }, ], @@ -155,6 +156,12 @@ crosscheck(({ stable, oxide }) => { text-align: right; } } + #app + :is( + [dir='rtl'] :is(.dark .hover\:\[\&\:\:file-selector-button\]\:rtl\:dark\:bg-black\/100) + )::file-selector-button:hover { + background-color: #000; + } `) }) })