Skip to content

Commit 615eb21

Browse files
authored
fix: parse nested selectors without & (#1144)
* fix: parse nested selectors without & Parse nested selector rules that omit & so scoping and :global() handling apply correctly. Fixes withastro/astro#10721 * Add comment
1 parent 91f8402 commit 615eb21

3 files changed

Lines changed: 25 additions & 1 deletion

File tree

.changeset/tame-lemons-nest.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@astrojs/compiler": patch
3+
---
4+
5+
Fix CSS nesting so nested selectors without an ampersand are parsed and scoped correctly.

internal/transform/scope-css_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ func TestScopeStyle(t *testing.T) {
270270
source: ".header { background-color: white; &.dark { background-color: blue; }}",
271271
want: ".header:where(.astro-xxxxxx){background-color:white;&.dark{background-color:blue}}",
272272
},
273+
{
274+
name: "nesting without ampersand",
275+
source: ".nesting-root{p{color:#123456}:global(h1){color:#abcdef}}",
276+
want: ".nesting-root:where(.astro-xxxxxx){p:where(.astro-xxxxxx){color:#123456}h1{color:#abcdef}}",
277+
},
273278
{
274279
name: "@container",
275280
source: `@container (min-width: 200px) and (min-height: 200px) {

lib/esbuild/css_parser/css_parser.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,25 @@ func (p *parser) parseListOfDeclarations() (list []css_ast.Rule) {
308308
list = append(list, p.parseSelectorRuleFrom(p.index, parseSelectorOpts{allowNesting: true}))
309309

310310
default:
311-
list = append(list, p.parseDeclaration())
311+
if p.shouldParseNestedSelector() {
312+
list = append(list, p.parseSelectorRuleFrom(p.index, parseSelectorOpts{allowNesting: true}))
313+
} else {
314+
list = append(list, p.parseDeclaration())
315+
}
312316
}
313317
}
314318
}
315319

320+
func (p *parser) shouldParseNestedSelector() bool {
321+
clone := *p
322+
clone.log = logger.Log{AddMsg: func(msg logger.Msg) {}}
323+
// Peek ahead to treat declarations that actually start a nested rule as selector rules.
324+
if _, ok := clone.parseSelectorList(parseSelectorOpts{allowNesting: true}); !ok {
325+
return false
326+
}
327+
return clone.peek(css_lexer.TOpenBrace)
328+
}
329+
316330
func mangleRules(rules []css_ast.Rule) []css_ast.Rule {
317331
type hashEntry struct {
318332
indices []uint32

0 commit comments

Comments
 (0)