@@ -9,6 +9,7 @@ use crate::{types::*, utils::{ast::*, css_builder::*, debug::inject_debug_commen
99pub fn visit_css_prop_jsx_opening_element (
1010 elem : & mut JSXOpeningElement ,
1111 state : & mut TransformState ,
12+ css_content_to_var : & mut std:: collections:: HashMap < String , String > ,
1213 collected_css_sheets : & mut Vec < ( String , String ) > ,
1314) -> bool {
1415 // Only process CSS props if compiled imports are enabled
@@ -60,7 +61,7 @@ pub fn visit_css_prop_jsx_opening_element(
6061 return transform_css_prop_variable_reference ( elem, index, expr) ;
6162 } else {
6263 // Handle object literals, arrays, etc.
63- return transform_css_prop_element ( elem, index, expr, state, collected_css_sheets) ;
64+ return transform_css_prop_element ( elem, index, expr, state, css_content_to_var , collected_css_sheets) ;
6465 }
6566 }
6667
@@ -73,15 +74,13 @@ fn transform_css_prop_element(
7374 css_attr_index : usize ,
7475 css_expr : Expr ,
7576 state : & TransformState ,
77+ css_content_to_var : & mut std:: collections:: HashMap < String , String > ,
7678 collected_css_sheets : & mut Vec < ( String , String ) > ,
7779) -> bool {
7880 // Process the CSS expression into CSS output
7981 if let Some ( css_output) = crate :: utils:: css_builder:: build_css_from_expression_with_context ( & css_expr, & state. variable_context ) {
80- // Generate a variable name for the CSS sheet
81- let var_name = format ! ( "_{}" , generate_unique_css_var_name( ) ) ;
82-
83- // Add the CSS sheet to the collection
84- collected_css_sheets. push ( ( var_name. clone ( ) , css_output. css_text . clone ( ) ) ) ;
82+ // Use deduplication to get the variable name
83+ let _var_name = add_css_sheet_with_deduplication ( & css_output. css_text , css_content_to_var, collected_css_sheets) ;
8584
8685 // Remove the css attribute
8786 elem. attrs . remove ( css_attr_index) ;
@@ -96,6 +95,27 @@ fn transform_css_prop_element(
9695 false
9796}
9897
98+ /// Add CSS sheet with deduplication - returns the variable name to use
99+ fn add_css_sheet_with_deduplication (
100+ css_content : & str ,
101+ css_content_to_var : & mut std:: collections:: HashMap < String , String > ,
102+ collected_css_sheets : & mut Vec < ( String , String ) > ,
103+ ) -> String {
104+ // Check if this CSS content already exists
105+ if let Some ( existing_var_name) = css_content_to_var. get ( css_content) {
106+ return existing_var_name. clone ( ) ;
107+ }
108+
109+ // Generate a new variable name
110+ let var_name = format ! ( "_css_{}" , collected_css_sheets. len( ) ) ;
111+
112+ // Store the mapping and add to collected sheets
113+ css_content_to_var. insert ( css_content. to_string ( ) , var_name. clone ( ) ) ;
114+ collected_css_sheets. push ( ( var_name. clone ( ) , css_content. to_string ( ) ) ) ;
115+
116+ var_name
117+ }
118+
99119/// Create className attribute with ax([class_name])
100120fn create_class_name_attr ( class_name : & str ) -> JSXAttrOrSpread {
101121 JSXAttrOrSpread :: JSXAttr ( JSXAttr {
@@ -122,13 +142,7 @@ fn create_class_name_attr(class_name: &str) -> JSXAttrOrSpread {
122142 } )
123143}
124144
125- /// Generate a unique variable name for CSS
126- fn generate_unique_css_var_name ( ) -> String {
127- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
128- static COUNTER : AtomicUsize = AtomicUsize :: new ( 0 ) ;
129- let count = COUNTER . fetch_add ( 1 , Ordering :: SeqCst ) ;
130- format ! ( "css_{}" , count)
131- }
145+
132146
133147/// Check if an expression is a variable reference (e.g., styles.danger, myVar, etc.)
134148fn is_variable_reference ( expr : & Expr ) -> bool {
@@ -212,6 +226,7 @@ fn create_css_object_from_string(css_str: &str) -> Expr {
212226pub fn visit_jsx_call_expr (
213227 call : & mut CallExpr ,
214228 state : & mut TransformState ,
229+ css_content_to_var : & mut std:: collections:: HashMap < String , String > ,
215230 collected_css_sheets : & mut Vec < ( String , String ) > ,
216231) -> bool {
217232 // Only process CSS props if compiled imports are enabled
@@ -268,7 +283,7 @@ pub fn visit_jsx_call_expr(
268283 }
269284
270285 if let Some ( ( css_prop_index, css_expr) ) = css_info {
271- return transform_jsx_call_css_prop ( object_lit, css_prop_index, & css_expr, state, collected_css_sheets) ;
286+ return transform_jsx_call_css_prop ( object_lit, css_prop_index, & css_expr, state, css_content_to_var , collected_css_sheets) ;
272287 }
273288 }
274289
@@ -281,15 +296,16 @@ fn transform_jsx_call_css_prop(
281296 css_prop_index : usize ,
282297 css_expr : & Expr ,
283298 state : & TransformState ,
299+ css_content_to_var : & mut std:: collections:: HashMap < String , String > ,
284300 collected_css_sheets : & mut Vec < ( String , String ) > ,
285301) -> bool {
286302 // Check if this is an object that we can process atomically
287303 if let Expr :: Object ( obj) = css_expr {
288304 // Use atomic CSS generation like Babel
289305 if let Some ( atomic_output) = build_atomic_css_from_object ( obj) {
290- // Add all atomic CSS sheets to the collection
291- for ( var_name , css_rule) in atomic_output. css_sheets {
292- collected_css_sheets . push ( ( var_name , css_rule ) ) ;
306+ // Add all atomic CSS sheets to the collection with deduplication
307+ for ( _ , css_rule) in atomic_output. css_sheets {
308+ let _var_name = add_css_sheet_with_deduplication ( & css_rule , css_content_to_var , collected_css_sheets ) ;
293309 }
294310
295311 // Remove the css property
@@ -325,12 +341,9 @@ fn transform_jsx_call_css_prop(
325341 }
326342
327343 // Fallback to the old approach for non-object expressions
328- if let Some ( css_output) = crate :: utils:: css_builder:: build_css_from_expression_with_context ( css_expr, & state. variable_context ) {
329- // Generate a variable name for the CSS sheet
330- let var_name = format ! ( "_{}" , generate_unique_css_var_name( ) ) ;
331-
332- // Add the CSS sheet to the collection
333- collected_css_sheets. push ( ( var_name. clone ( ) , css_output. css_text . clone ( ) ) ) ;
344+ if let Some ( css_output) = crate :: utils:: css_builder:: build_css_from_expression_with_context ( css_expr, & state. variable_context ) {
345+ // Use deduplication to get the variable name
346+ let _var_name = add_css_sheet_with_deduplication ( & css_output. css_text , css_content_to_var, collected_css_sheets) ;
334347
335348 // Remove the css property
336349 object_lit. props . remove ( css_prop_index) ;
0 commit comments