Skip to content

Commit

Permalink
Loosen :is() wrapping rules in applyImportantSelector for more readab…
Browse files Browse the repository at this point in the history
…le output.
  • Loading branch information
joshwilsonvu committed Jun 26, 2024
1 parent 0de1f0c commit fc09a31
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 18 deletions.
11 changes: 5 additions & 6 deletions src/util/applyImportantSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ export function applyImportantSelector(selector, important) {
let sel = parser().astSync(selector)

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')
// For nesting, we only need to wrap a selector with :is() if it has a top-level combinator,
// e.g. `.dark .text-white`, to be independent of DOM order. Any other selector, including
// combinators inside of pseudos like `:where()`, are ok to nest.
let shouldWrap = sel.nodes.some((node) => node.type === 'combinator')

if (!isWrapped) {
if (shouldWrap) {
sel.nodes = [
parser.pseudo({
value: ':is',
Expand Down
23 changes: 11 additions & 12 deletions tests/util/apply-important-selector.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@ import { applyImportantSelector } from '../../src/util/applyImportantSelector'

it.each`
before | after
${'.foo'} | ${'#app :is(.foo)'}
${'.foo'} | ${'#app .foo'}
${'.foo .bar'} | ${'#app :is(.foo .bar)'}
${'.foo:hover'} | ${'#app :is(.foo:hover)'}
${'.foo:hover'} | ${'#app .foo:hover'}
${'.foo .bar:hover'} | ${'#app :is(.foo .bar:hover)'}
${'.foo::before'} | ${'#app :is(.foo)::before'}
${'.foo::before'} | ${'#app :is(.foo)::before'}
${'.foo::file-selector-button'} | ${'#app :is(.foo)::file-selector-button'}
${'.foo::-webkit-progress-bar'} | ${'#app :is(.foo)::-webkit-progress-bar'}
${'.foo:hover::before'} | ${'#app :is(.foo:hover)::before'}
${'.foo::before'} | ${'#app .foo::before'}
${'.foo::file-selector-button'} | ${'#app .foo::file-selector-button'}
${'.foo::-webkit-progress-bar'} | ${'#app .foo::-webkit-progress-bar'}
${'.foo:hover::before'} | ${'#app .foo:hover::before'}
${':is(:where(.dark) :is(:where([dir="rtl"]) .foo::before))'} | ${'#app :is(:where(.dark) :is(:where([dir="rtl"]) .foo))::before'}
${':is(:where(.dark) .foo) .bar'} | ${'#app :is(:is(:where(.dark) .foo) .bar)'}
${':is(.foo) :is(.bar)'} | ${'#app :is(:is(.foo) :is(.bar))'}
${':is(.foo)::before'} | ${'#app :is(.foo)::before'}
${'.foo:before'} | ${'#app :is(.foo):before'}
${'.foo::some-uknown-pseudo'} | ${'#app :is(.foo)::some-uknown-pseudo'}
${'.foo::some-uknown-pseudo:hover'} | ${'#app :is(.foo)::some-uknown-pseudo:hover'}
${'.foo:focus::some-uknown-pseudo:hover'} | ${'#app :is(.foo:focus)::some-uknown-pseudo:hover'}
${'.foo:hover::some-uknown-pseudo:focus'} | ${'#app :is(.foo:hover)::some-uknown-pseudo:focus'}
${'.foo:before'} | ${'#app .foo:before'}
${'.foo::some-uknown-pseudo'} | ${'#app .foo::some-uknown-pseudo'}
${'.foo::some-uknown-pseudo:hover'} | ${'#app .foo::some-uknown-pseudo:hover'}
${'.foo:focus::some-uknown-pseudo:hover'} | ${'#app .foo:focus::some-uknown-pseudo:hover'}
${'.foo:hover::some-uknown-pseudo:focus'} | ${'#app .foo:hover::some-uknown-pseudo:focus'}
`('should generate "$after" from "$before"', ({ before, after }) => {
expect(applyImportantSelector(before, '#app')).toEqual(after)
})

0 comments on commit fc09a31

Please sign in to comment.