@ -77,38 +77,9 @@ const visitors = {
}
} ,
ComplexSelector ( node , context ) {
const selectors = truncate ( node ) ;
const selectors = get_relative _selectors ( node ) ;
const inner = selectors [ selectors . length - 1 ] ;
if ( node . metadata . rule ? . metadata . parent _rule && selectors . length > 0 ) {
let has _explicit _nesting _selector = false ;
// nesting could be inside pseudo classes like :is, :has or :where
for ( let selector of selectors ) {
walk (
selector ,
{ } ,
{
// @ts-ignore
NestingSelector ( ) {
has _explicit _nesting _selector = true ;
}
}
) ;
// if we found one we can break from the others
if ( has _explicit _nesting _selector ) break ;
}
if ( ! has _explicit _nesting _selector ) {
selectors [ 0 ] = {
... selectors [ 0 ] ,
combinator : descendant _combinator
} ;
selectors . unshift ( nesting _selector ) ;
}
}
if ( context . state . from _render _tag ) {
// We're searching for a match that crosses a render tag boundary. That means we have to both traverse up
// the element tree (to see if we find an entry point) but also remove selectors from the end (assuming
@ -156,6 +127,50 @@ const visitors = {
}
} ;
/ * *
* Retrieves the relative selectors ( minus the trailing globals ) from a complex selector .
* Also searches them for any existing ` & ` selectors and adds one if none are found .
* This ensures we traverse up to the parent rule when the inner selectors match and we ' re
* trying to see if the parent rule also matches .
* @ param { Compiler . Css . ComplexSelector } node
* /
function get _relative _selectors ( node ) {
const selectors = truncate ( node ) ;
if ( node . metadata . rule ? . metadata . parent _rule && selectors . length > 0 ) {
let has _explicit _nesting _selector = false ;
// nesting could be inside pseudo classes like :is, :has or :where
for ( let selector of selectors ) {
walk (
selector ,
{ } ,
{
// @ts-ignore
NestingSelector ( ) {
has _explicit _nesting _selector = true ;
}
}
) ;
// if we found one we can break from the others
if ( has _explicit _nesting _selector ) break ;
}
if ( ! has _explicit _nesting _selector ) {
if ( selectors [ 0 ] . combinator === null ) {
selectors [ 0 ] = {
... selectors [ 0 ] ,
combinator : descendant _combinator
} ;
}
selectors . unshift ( nesting _selector ) ;
}
}
return selectors ;
}
/ * *
* Discard trailing ` :global(...) ` selectors without a ` :has/is/where/not(...) ` modifier , these are unused for scoping purposes
* @ param { Compiler . Css . ComplexSelector } node
@ -641,7 +656,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
const parent = /** @type {Compiler.Css.Rule} */ ( rule . metadata . parent _rule ) ;
for ( const complex _selector of parent . prelude . children ) {
if ( apply _selector ( truncate ( complex _selector ) , parent , element , state ) ) {
if ( apply _selector ( get_relative _selectors ( complex _selector ) , parent , element , state ) ) {
complex _selector . metadata . used = true ;
matched = true ;
}