Skip to content

Commit

Permalink
fix additional comment on #3877 about :has(> &)
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Feb 4, 2025
1 parent 53a2fc4 commit f4cc689
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
33 changes: 21 additions & 12 deletions internal/css_ast/css_ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -796,23 +796,32 @@ func (s ComplexSelector) Clone() ComplexSelector {
return clone
}

func (sel ComplexSelector) IsRelative() bool {
if sel.Selectors[0].Combinator.Byte == 0 {
for _, inner := range sel.Selectors {
if len(inner.NestingSelectorLocs) > 0 {
return false
}
for _, ss := range inner.SubclassSelectors {
if pseudo, ok := ss.Data.(*SSPseudoClassWithSelectorList); ok {
for _, nested := range pseudo.Selectors {
if !nested.IsRelative() {
return false
}
func (sel ComplexSelector) ContainsNestingCombinator() bool {
for _, inner := range sel.Selectors {
if len(inner.NestingSelectorLocs) > 0 {
return true
}
for _, ss := range inner.SubclassSelectors {
if pseudo, ok := ss.Data.(*SSPseudoClassWithSelectorList); ok {
for _, nested := range pseudo.Selectors {
if nested.ContainsNestingCombinator() {
return true
}
}
}
}
}
return false
}

func (sel ComplexSelector) IsRelative() bool {
// https://www.w3.org/TR/css-nesting-1/#syntax
// "If a selector in the <relative-selector-list> does not start with a
// combinator but does contain the nesting selector, it is interpreted
// as a non-relative selector."
if sel.Selectors[0].Combinator.Byte == 0 && sel.ContainsNestingCombinator() {
return false
}
return true
}

Expand Down
2 changes: 2 additions & 0 deletions internal/css_parser/css_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,8 @@ func TestNestedSelector(t *testing.T) {
expectPrintedLowerUnsupported(t, nesting, ".demo { .lg { .triangle, .circle { color: red } } }", ".demo .lg .triangle,\n.demo .lg .circle {\n color: red;\n}\n", "")
expectPrintedLowerUnsupported(t, nesting, ".card { .featured & & & { color: red } }", ".featured .card .card .card {\n color: red;\n}\n", "")
expectPrintedLowerUnsupported(t, nesting, ".a :has(> .c) { .b & { color: red } }", ".b :is(.a :has(> .c)) {\n color: red;\n}\n", "")
expectPrintedLowerUnsupported(t, nesting, "a { :has(&) { color: red } }", ":has(a) {\n color: red;\n}\n", "")
expectPrintedLowerUnsupported(t, nesting, "a { :has(> &) { color: red } }", ":has(> a) {\n color: red;\n}\n", "")

// Duplicate "&" may be used to increase specificity
expectPrintedLowerUnsupported(t, nesting, ".foo { &&&.bar { color: red } }", ".foo.foo.foo.bar {\n color: red;\n}\n", "")
Expand Down
16 changes: 16 additions & 0 deletions scripts/browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,22 @@
})
},

// See: https://github.com/evanw/esbuild/issues/3877#issuecomment-2631385559
async cssNestingIssue3877Comment2631385559() {
await assertSameColorsWithNestingTransform(esbuild, {
css: `
.a {
:has(>&) {
color: red;
}
}
`,
html: `
<div class="a">a</div>
`,
})
},

// See: https://github.com/evanw/esbuild/issues/3997
async cssNestingIssue3997() {
await assertSameColorsWithNestingTransform(esbuild, {
Expand Down

0 comments on commit f4cc689

Please sign in to comment.