@@ -7,13 +7,15 @@ import { is_keyframes_node } from '../../css.js';
77import { is_global , is_unscoped_pseudo_class } from './utils.js' ;
88
99/**
10- * @typedef {Visitors<
11- * AST.CSS.Node,
12- * {
13- * keyframes: string[];
14- * rule: AST.CSS.Rule | null;
15- * }
16- * >} CssVisitors
10+ * @typedef {{
11+ * keyframes: string[];
12+ * rule: AST.CSS.Rule | null;
13+ * analysis: ComponentAnalysis;
14+ * }} CssState
15+ */
16+
17+ /**
18+ * @typedef {Visitors<AST.CSS.Node, CssState> } CssVisitors
1719 */
1820
1921/**
@@ -28,6 +30,15 @@ function is_global_block_selector(simple_selector) {
2830 ) ;
2931}
3032
33+ /**
34+ * @param {AST.SvelteNode[] } path
35+ */
36+ function is_unscoped ( path ) {
37+ return path
38+ . filter ( ( node ) => node . type === 'Rule' )
39+ . every ( ( node ) => node . metadata . has_global_selectors ) ;
40+ }
41+
3142/**
3243 *
3344 * @param {Array<AST.CSS.Node> } path
@@ -42,6 +53,9 @@ const css_visitors = {
4253 if ( is_keyframes_node ( node ) ) {
4354 if ( ! node . prelude . startsWith ( '-global-' ) && ! is_in_global_block ( context . path ) ) {
4455 context . state . keyframes . push ( node . prelude ) ;
56+ } else if ( node . prelude . startsWith ( '-global-' ) ) {
57+ // we don't check if the block.children.length because the keyframe is still added even if empty
58+ context . state . analysis . css . has_global ||= is_unscoped ( context . path ) ;
4559 }
4660 }
4761
@@ -99,10 +113,12 @@ const css_visitors = {
99113
100114 node . metadata . rule = context . state . rule ;
101115
102- node . metadata . used || = node . children . every (
116+ node . metadata . is_global = node . children . every (
103117 ( { metadata } ) => metadata . is_global || metadata . is_global_like
104118 ) ;
105119
120+ node . metadata . used ||= node . metadata . is_global ;
121+
106122 if (
107123 node . metadata . rule ?. metadata . parent_rule &&
108124 node . children [ 0 ] ?. selectors [ 0 ] ?. type === 'NestingSelector'
@@ -190,6 +206,7 @@ const css_visitors = {
190206
191207 if ( idx !== - 1 ) {
192208 is_global_block = true ;
209+
193210 for ( let i = idx + 1 ; i < child . selectors . length ; i ++ ) {
194211 walk ( /** @type {AST.CSS.Node } */ ( child . selectors [ i ] ) , null , {
195212 ComplexSelector ( node ) {
@@ -242,16 +259,26 @@ const css_visitors = {
242259 }
243260 }
244261
245- context . next ( {
246- ...context . state ,
247- rule : node
248- } ) ;
262+ const state = { ...context . state , rule : node } ;
249263
250- node . metadata . has_local_selectors = node . prelude . children . some ( ( selector ) => {
251- return selector . children . some (
252- ( { metadata } ) => ! metadata . is_global && ! metadata . is_global_like
253- ) ;
254- } ) ;
264+ // visit selector list first, to populate child selector metadata
265+ context . visit ( node . prelude , state ) ;
266+
267+ for ( const selector of node . prelude . children ) {
268+ node . metadata . has_global_selectors ||= selector . metadata . is_global ;
269+ node . metadata . has_local_selectors ||= ! selector . metadata . is_global ;
270+ }
271+
272+ // if this rule has a ComplexSelector whose RelativeSelector children are all
273+ // `:global(...)`, and the rule contains declarations (rather than just
274+ // nested rules) then the component as a whole includes global CSS
275+ context . state . analysis . css . has_global ||=
276+ node . metadata . has_global_selectors &&
277+ node . block . children . filter ( ( child ) => child . type === 'Declaration' ) . length > 0 &&
278+ is_unscoped ( context . path ) ;
279+
280+ // visit block list, so parent rule metadata is populated
281+ context . visit ( node . block , state ) ;
255282 } ,
256283 NestingSelector ( node , context ) {
257284 const rule = /** @type {AST.CSS.Rule } */ ( context . state . rule ) ;
@@ -289,5 +316,12 @@ const css_visitors = {
289316 * @param {ComponentAnalysis } analysis
290317 */
291318export function analyze_css ( stylesheet , analysis ) {
292- walk ( stylesheet , { keyframes : analysis . css . keyframes , rule : null } , css_visitors ) ;
319+ /** @type {CssState } */
320+ const css_state = {
321+ keyframes : analysis . css . keyframes ,
322+ rule : null ,
323+ analysis
324+ } ;
325+
326+ walk ( stylesheet , css_state , css_visitors ) ;
293327}
0 commit comments