@@ -58,21 +58,6 @@ interface CacheStatus {
5858 metrics : CacheMetrics | null ;
5959}
6060
61- interface GlobalBreakdown {
62- css : string ; // prettified tasty global CSS
63- totalRules : number ;
64- totalCSSSize : number ;
65- selectors : {
66- elements : string [ ] ;
67- classes : string [ ] ;
68- ids : string [ ] ;
69- pseudoClasses : string [ ] ;
70- mediaQueries : string [ ] ;
71- keyframes : string [ ] ;
72- other : string [ ] ;
73- } ;
74- }
75-
7661interface Definitions {
7762 properties : string [ ] ; // defined via @property
7863 keyframes : Array < { name : string ; refCount : number } > ;
@@ -96,17 +81,26 @@ interface Summary {
9681 // Tasty CSS sizes
9782 activeCSSSize : number ;
9883 unusedCSSSize : number ;
99- totalCSSSize : number ; // tasty-only: active + unused + tasty global
84+ globalCSSSize : number ; // injectGlobal() CSS
85+ rawCSSSize : number ; // createGlobalStyle() CSS
86+ keyframesCSSSize : number ; // @keyframes CSS
87+ propertyCSSSize : number ; // @property CSS
88+ totalCSSSize : number ; // all tasty CSS (active + unused + global + raw + keyframes + property)
10089
10190 // Tasty CSS payloads
10291 activeCSS : string ;
10392 unusedCSS : string ;
104- allCSS : string ; // tasty-only CSS (active + unused + tasty global)
93+ globalCSS : string ; // injectGlobal() CSS
94+ rawCSS : string ; // createGlobalStyle() CSS
95+ keyframesCSS : string ; // @keyframes CSS
96+ propertyCSS : string ; // @property CSS
97+ allCSS : string ; // all tasty CSS combined
10598
106- // Tasty global (createGlobalStyle)
107- globalCSS : string ;
108- globalCSSSize : number ;
99+ // Rule counts
109100 globalRuleCount : number ;
101+ rawRuleCount : number ;
102+ keyframesRuleCount : number ;
103+ propertyRuleCount : number ;
110104
111105 // Page-level CSS (across all stylesheets, not only tasty) — shown when includePageCSS != false
112106 page ?: {
@@ -584,86 +578,88 @@ export const tastyDebug = {
584578 injector . instance . resetMetrics ( { root } ) ;
585579 } ,
586580
587- // 5) Tasty global CSS and selector analysis
588- global ( opts ?: {
589- root ?: Document | ShadowRoot ;
590- log ?: boolean ;
591- } ) : GlobalBreakdown {
592- const { root = document , log = false } = opts || { } ;
593- const allCSS = injector . instance . getCssText ( { root } ) ;
594- const rules = extractCSSRules ( allCSS ) ;
595-
596- const globalRules = rules . filter ( ( rule ) => {
597- const selectors = rule . selector . split ( ',' ) . map ( ( s ) => s . trim ( ) ) ;
598- return ! selectors . every ( ( selector ) => {
599- const cleanSelector = selector . replace ( / [ . # : \s > + ~ [ \] ( ) ] / g, ' ' ) ;
600- const parts = cleanSelector . split ( / \s + / ) . filter ( Boolean ) ;
601- return parts . length > 0 && parts . every ( ( part ) => / ^ t \d + $ / . test ( part ) ) ;
602- } ) ;
603- } ) ;
581+ // 5) Get CSS for specific global types
582+ getGlobalTypeCSS (
583+ type : 'global' | 'raw' | 'keyframes' | 'property' ,
584+ opts ?: { root ?: Document | ShadowRoot } ,
585+ ) : { css : string ; ruleCount : number ; size : number } {
586+ const { root = document } = opts || { } ;
587+ const registry = ( injector . instance as any ) [ 'sheetManager' ] ?. getRegistry (
588+ root ,
589+ ) ;
604590
605- // Calculate raw CSS size for consistent size calculations
606- const rawGlobalCSS = globalRules
607- . map ( ( rule ) => `${ rule . selector } { ${ rule . declarations } }` )
608- . join ( '\n' ) ;
609-
610- // Use prettified CSS for display
611- const css = prettifyCSS ( rawGlobalCSS ) ;
612-
613- // Analyze selectors
614- const selectors = {
615- elements : [ ] as string [ ] ,
616- classes : [ ] as string [ ] ,
617- ids : [ ] as string [ ] ,
618- pseudoClasses : [ ] as string [ ] ,
619- mediaQueries : [ ] as string [ ] ,
620- keyframes : [ ] as string [ ] ,
621- other : [ ] as string [ ] ,
622- } ;
591+ if ( ! registry ) {
592+ return { css : '' , ruleCount : 0 , size : 0 } ;
593+ }
623594
624- globalRules . forEach ( ( rule ) => {
625- const selector = rule . selector ;
626- if ( selector . startsWith ( '@media' ) ) {
627- selectors . mediaQueries . push ( selector ) ;
628- } else if ( selector . startsWith ( '@keyframes' ) ) {
629- selectors . keyframes . push ( selector ) ;
630- } else if (
631- selector . includes ( '.' ) &&
632- ! selector . includes ( '#' ) &&
633- ! selector . includes ( ':' )
634- ) {
635- selectors . classes . push ( selector ) ;
636- } else if (
637- selector . includes ( '#' ) &&
638- ! selector . includes ( '.' ) &&
639- ! selector . includes ( ':' )
640- ) {
641- selectors . ids . push ( selector ) ;
642- } else if ( selector . includes ( ':' ) ) {
643- selectors . pseudoClasses . push ( selector ) ;
644- } else if ( / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 ] * $ / . test ( selector . trim ( ) ) ) {
645- selectors . elements . push ( selector ) ;
646- } else {
647- selectors . other . push ( selector ) ;
595+ const cssChunks : string [ ] = [ ] ;
596+ let ruleCount = 0 ;
597+
598+ if ( type === 'keyframes' ) {
599+ // Handle keyframes separately - they're stored in keyframesCache
600+ for ( const [ , entry ] of registry . keyframesCache ) {
601+ const info = entry . info ;
602+ const sheet = registry . sheets [ info . sheetIndex ] ;
603+ const styleSheet = sheet ?. sheet ?. sheet ;
604+
605+ if ( styleSheet && info . ruleIndex < styleSheet . cssRules . length ) {
606+ const rule = styleSheet . cssRules [ info . ruleIndex ] as
607+ | CSSRule
608+ | undefined ;
609+ if ( rule ) {
610+ cssChunks . push ( rule . cssText ) ;
611+ ruleCount ++ ;
612+ }
613+ } else if ( info . cssText ) {
614+ cssChunks . push ( info . cssText ) ;
615+ ruleCount ++ ;
616+ }
648617 }
649- } ) ;
650-
651- const result = {
652- css,
653- totalRules : globalRules . length ,
654- totalCSSSize : rawGlobalCSS . length , // Use raw CSS length for consistent size calculations
655- selectors,
656- } ;
618+ } else {
619+ // Handle other global types stored in globalRules
620+ const prefix =
621+ type === 'global' ? 'global:' : type === 'raw' ? 'raw:' : 'property:' ;
622+
623+ for ( const [ key , ruleInfo ] of registry . globalRules ) {
624+ if ( key . startsWith ( prefix ) ) {
625+ const sheet = registry . sheets [ ruleInfo . sheetIndex ] ;
626+ const styleSheet = sheet ?. sheet ?. sheet ;
627+ if ( styleSheet ) {
628+ const start = Math . max ( 0 , ruleInfo . ruleIndex ) ;
629+ const end = Math . min (
630+ styleSheet . cssRules . length - 1 ,
631+ ( ruleInfo . endRuleIndex as number ) ?? ruleInfo . ruleIndex ,
632+ ) ;
657633
658- if ( log ) {
659- console . group ( `🌍 Global CSS (${ result . totalRules } rules)` ) ;
660- console . log ( `📊 Size: ${ result . totalCSSSize } characters` ) ;
661- console . log ( '🎯 Selector breakdown:' , result . selectors ) ;
662- console . log ( '🎨 CSS:\n' + result . css ) ;
663- console . groupEnd ( ) ;
634+ if (
635+ start >= 0 &&
636+ end >= start &&
637+ start < styleSheet . cssRules . length
638+ ) {
639+ for ( let i = start ; i <= end ; i ++ ) {
640+ const rule = styleSheet . cssRules [ i ] as CSSRule | undefined ;
641+ if ( rule ) {
642+ cssChunks . push ( rule . cssText ) ;
643+ ruleCount ++ ;
644+ }
645+ }
646+ }
647+ } else if ( ruleInfo . cssText && ruleInfo . cssText . length ) {
648+ // Fallback in environments without CSSOM access
649+ cssChunks . push ( ...ruleInfo . cssText ) ;
650+ ruleCount += ruleInfo . cssText . length ;
651+ }
652+ }
653+ }
664654 }
665655
666- return result ;
656+ const rawCSS = cssChunks . join ( '\n' ) ;
657+
658+ return {
659+ css : prettifyCSS ( rawCSS ) ,
660+ ruleCount,
661+ size : rawCSS . length ,
662+ } ;
667663 } ,
668664
669665 // 6) Defined @property and keyframes
@@ -729,14 +725,19 @@ export const tastyDebug = {
729725 summary ( opts ?: SummaryOptions ) : Summary {
730726 const { root = document , log = false , includePageCSS = false } = opts || { } ;
731727 const cacheStatus = this . cache ( { root } ) ;
732- const globalBreakdown = this . global ( { root } ) ;
733728 const definitions = this . defs ( { root } ) ;
734729 const metrics = this . metrics ( { root } ) ;
735730
736731 const activeCSS = this . css ( 'active' , { root, prettify : false } ) ;
737732 const unusedCSS = this . css ( 'unused' , { root, prettify : false } ) ;
738733 const allCSS = this . css ( 'all' , { root, prettify : false } ) ;
739734
735+ // Get CSS for each global type separately
736+ const globalData = this . getGlobalTypeCSS ( 'global' , { root } ) ;
737+ const rawData = this . getGlobalTypeCSS ( 'raw' , { root } ) ;
738+ const keyframesData = this . getGlobalTypeCSS ( 'keyframes' , { root } ) ;
739+ const propertyData = this . getGlobalTypeCSS ( 'property' , { root } ) ;
740+
740741 // Build cleanup summary from metrics
741742 const cleanupSummary = {
742743 enabled : ! ! metrics ,
@@ -793,13 +794,22 @@ export const tastyDebug = {
793794 totalStyledClasses : cacheStatus . classes . all ,
794795 activeCSSSize : activeCSS . length ,
795796 unusedCSSSize : unusedCSS . length ,
796- totalCSSSize : allCSS . length , // This includes active + unused + global CSS
797+ globalCSSSize : globalData . size ,
798+ rawCSSSize : rawData . size ,
799+ keyframesCSSSize : keyframesData . size ,
800+ propertyCSSSize : propertyData . size ,
801+ totalCSSSize : allCSS . length ,
797802 activeCSS : prettifyCSS ( activeCSS ) ,
798803 unusedCSS : prettifyCSS ( unusedCSS ) ,
804+ globalCSS : globalData . css ,
805+ rawCSS : rawData . css ,
806+ keyframesCSS : keyframesData . css ,
807+ propertyCSS : propertyData . css ,
799808 allCSS : prettifyCSS ( allCSS ) ,
800- globalCSS : globalBreakdown . css ,
801- globalCSSSize : globalBreakdown . totalCSSSize ,
802- globalRuleCount : globalBreakdown . totalRules ,
809+ globalRuleCount : globalData . ruleCount ,
810+ rawRuleCount : rawData . ruleCount ,
811+ keyframesRuleCount : keyframesData . ruleCount ,
812+ propertyRuleCount : propertyData . ruleCount ,
803813 page,
804814 metrics,
805815 definedProperties : definitions . properties ,
@@ -825,9 +835,34 @@ export const tastyDebug = {
825835 console . log ( ` • Active CSS: ${ summary . activeCSSSize } characters` ) ;
826836 console . log ( ` • Unused CSS: ${ summary . unusedCSSSize } characters` ) ;
827837 console . log (
828- ` • Global CSS: ${ summary . globalCSSSize } characters (${ summary . globalRuleCount } rules)` ,
838+ ` • Global CSS (injectGlobal): ${ summary . globalCSSSize } characters (${ summary . globalRuleCount } rules)` ,
839+ ) ;
840+ console . log (
841+ ` • Raw CSS (createGlobalStyle): ${ summary . rawCSSSize } characters (${ summary . rawRuleCount } rules)` ,
842+ ) ;
843+ console . log (
844+ ` • Keyframes CSS: ${ summary . keyframesCSSSize } characters (${ summary . keyframesRuleCount } rules)` ,
829845 ) ;
830- console . log ( ` • Total CSS: ${ summary . totalCSSSize } characters` ) ;
846+ console . log (
847+ ` • Property CSS: ${ summary . propertyCSSSize } characters (${ summary . propertyRuleCount } rules)` ,
848+ ) ;
849+
850+ // Show breakdown calculation
851+ const calculatedTotal =
852+ summary . activeCSSSize +
853+ summary . unusedCSSSize +
854+ summary . globalCSSSize +
855+ summary . rawCSSSize +
856+ summary . keyframesCSSSize +
857+ summary . propertyCSSSize ;
858+ console . log ( ` • Calculated Total: ${ calculatedTotal } characters` ) ;
859+ console . log ( ` • Actual Total: ${ summary . totalCSSSize } characters` ) ;
860+
861+ if ( Math . abs ( calculatedTotal - summary . totalCSSSize ) > 100 ) {
862+ console . warn (
863+ ` ⚠️ Size mismatch: ${ Math . abs ( calculatedTotal - summary . totalCSSSize ) } characters difference` ,
864+ ) ;
865+ }
831866
832867 if ( page ) {
833868 console . log ( `📄 Page CSS:` ) ;
0 commit comments