@@ -6,6 +6,8 @@ use css::{
66 rm_css_comment:: rm_css_comment,
77 style_selector:: StyleSelector ,
88} ;
9+
10+ use crate :: utils:: expression_to_code;
911use oxc_ast:: ast:: TemplateLiteral ;
1012
1113use crate :: extract_style:: {
@@ -32,8 +34,6 @@ pub fn css_to_style_literal<'a>(
3234 level : u8 ,
3335 selector : & Option < StyleSelector > ,
3436) -> Vec < CssToStyleResult > {
35- use crate :: utils:: expression_to_code;
36-
3737 let mut styles = vec ! [ ] ;
3838
3939 // If there are no expressions, just process quasis as static CSS
@@ -93,15 +93,11 @@ pub fn css_to_style_literal<'a>(
9393 let mut literal_values = Vec :: new ( ) ;
9494
9595 for ( _, idx) in & found_placeholders {
96- if * idx < css. expressions . len ( ) {
97- if let Some ( literal_value) =
96+ if * idx < css. expressions . len ( )
97+ && let Some ( literal_value) =
9898 get_string_by_literal_expression ( & css. expressions [ * idx] )
99- {
100- literal_values. push ( ( * idx, literal_value) ) ;
101- } else {
102- all_literals = false ;
103- break ;
104- }
99+ {
100+ literal_values. push ( ( * idx, literal_value) ) ;
105101 } else {
106102 all_literals = false ;
107103 break ;
@@ -125,15 +121,14 @@ pub fn css_to_style_literal<'a>(
125121 style. level ( ) ,
126122 style. selector ( ) . cloned ( ) ,
127123 ) ) ) ;
128- continue ;
129- }
130-
131- // Not all expressions are literals - need to create dynamic style
132- // Check if value is just a placeholder (no surrounding text)
133- if found_placeholders. len ( ) == 1 {
134- let ( placeholder, idx) = & found_placeholders[ 0 ] ;
135- let trimmed_value = value. trim ( ) ;
136- if trimmed_value == placeholder. as_str ( ) && * idx < css. expressions . len ( ) {
124+ } else {
125+ // Not all expressions are literals - need to create dynamic style
126+ // Check if value is just a placeholder (no surrounding text)
127+ if found_placeholders. len ( ) == 1
128+ && let ( placeholder, idx) = & found_placeholders[ 0 ]
129+ && value. trim ( ) == placeholder. as_str ( )
130+ && * idx < css. expressions . len ( )
131+ {
137132 // Value is just the expression - use expression code directly
138133 let expr = & css. expressions [ * idx] ;
139134
@@ -150,6 +145,7 @@ pub fn css_to_style_literal<'a>(
150145 // 1. Remove newlines and tabs, replace with spaces
151146 identifier = identifier. replace ( [ '\n' , '\t' ] , " " ) ;
152147 // 2. Normalize multiple spaces to single space
148+
153149 while identifier. contains ( " " ) {
154150 identifier = identifier. replace ( " " , " " ) ;
155151 }
@@ -159,7 +155,12 @@ pub fn css_to_style_literal<'a>(
159155 . replace ( " =>" , "=>" )
160156 . replace ( "=> " , "=>" ) ;
161157 // 4. Normalize function expression formatting
162- if is_function {
158+ // 5. Normalize quotes
159+ if !is_function {
160+ // For non-function expressions, convert property access quotes
161+ // object["color"] -> object['color']
162+ identifier = identifier. replace ( "[\" " , "['" ) . replace ( "\" ]" , "']" ) ;
163+ } else {
163164 // Normalize function() { } to function(){ }
164165 identifier = identifier. replace ( "function() {" , "function(){" ) ;
165166 identifier = identifier. replace ( "function (" , "function(" ) ;
@@ -176,13 +177,6 @@ pub fn css_to_style_literal<'a>(
176177 }
177178 // Add (rest) call
178179 identifier = format ! ( "{}(rest)" , identifier) ;
179- }
180- // 5. Normalize quotes
181- if !is_function {
182- // For non-function expressions, convert property access quotes
183- // object["color"] -> object['color']
184- identifier = identifier. replace ( "[\" " , "['" ) . replace ( "\" ]" , "']" ) ;
185- } else {
186180 // For function expressions, convert string literals in ternary operators
187181 // This handles cases like: (props)=>props.b ? "a" : "b" -> (props)=>props.b ? 'a' : 'b'
188182 // Use simple pattern matching for ternary operator string literals
@@ -240,72 +234,69 @@ pub fn css_to_style_literal<'a>(
240234 & identifier,
241235 style. selector ( ) . cloned ( ) ,
242236 ) ) ) ;
243- continue ;
244- }
245- }
237+ } else {
238+ // Value has surrounding text - need to create template literal
239+ // Reconstruct the template literal by replacing placeholders with ${expr} syntax
240+ // The value contains placeholders like "__EXPR_0__px", we need to convert to `${expr}px`
246241
247- // Value has surrounding text - need to create template literal
248- // Reconstruct the template literal by replacing placeholders with ${expr} syntax
249- // The value contains placeholders like "__EXPR_0__px", we need to convert to `${expr}px`
242+ let mut template_literal = value. to_string ( ) ;
250243
251- let mut template_literal = value. to_string ( ) ;
244+ // Sort placeholders by their position in reverse order to avoid index shifting
245+ found_placeholders. sort_by ( |( a_placeholder, _) , ( b_placeholder, _) | {
246+ template_literal
247+ . rfind ( a_placeholder)
248+ . cmp ( & template_literal. rfind ( b_placeholder) )
249+ } ) ;
252250
253- // Sort placeholders by their position in reverse order to avoid index shifting
254- found_placeholders. sort_by ( |( a_placeholder, _) , ( b_placeholder, _) | {
255- template_literal
256- . rfind ( a_placeholder)
257- . cmp ( & template_literal. rfind ( b_placeholder) )
258- } ) ;
251+ // Replace each placeholder with the actual expression in template literal format
252+ for ( placeholder, idx) in & found_placeholders {
253+ if * idx < css. expressions . len ( ) {
254+ let expr = & css. expressions [ * idx] ;
255+ let expr_code = expression_to_code ( expr) ;
256+ // Normalize the expression code
257+ let mut normalized_code = expr_code. replace ( [ '\n' , '\t' ] , " " ) ;
258+ while normalized_code. contains ( " " ) {
259+ normalized_code = normalized_code. replace ( " " , " " ) ;
260+ }
261+ normalized_code = normalized_code. trim ( ) . to_string ( ) ;
259262
260- // Replace each placeholder with the actual expression in template literal format
261- for ( placeholder, idx) in & found_placeholders {
262- if * idx < css. expressions . len ( ) {
263- let expr = & css. expressions [ * idx] ;
264- let expr_code = expression_to_code ( expr) ;
265- // Normalize the expression code
266- let mut normalized_code = expr_code. replace ( [ '\n' , '\t' ] , " " ) ;
267- while normalized_code. contains ( " " ) {
268- normalized_code = normalized_code. replace ( " " , " " ) ;
263+ // Replace placeholder with ${expr} syntax
264+ let expr_template = format ! ( "${{{}}}" , normalized_code) ;
265+ template_literal =
266+ template_literal. replace ( placeholder. as_str ( ) , & expr_template) ;
267+ }
269268 }
270- normalized_code = normalized_code. trim ( ) . to_string ( ) ;
271269
272- // Replace placeholder with ${expr} syntax
273- let expr_template = format ! ( "${{{}}}" , normalized_code) ;
274- template_literal =
275- template_literal. replace ( placeholder. as_str ( ) , & expr_template) ;
270+ // Wrap in template literal backticks
271+ let final_identifier = format ! ( "`{}`" , template_literal) ;
272+
273+ styles. push ( CssToStyleResult :: Dynamic ( ExtractDynamicStyle :: new (
274+ style. property ( ) ,
275+ style. level ( ) ,
276+ & final_identifier,
277+ style. selector ( ) . cloned ( ) ,
278+ ) ) ) ;
276279 }
277280 }
281+ } else {
282+ // Check if property name contains a dynamic expression placeholder
283+ let property = style. property ( ) ;
284+ let mut prop_is_dynamic = false ;
278285
279- // Wrap in template literal backticks
280- let final_identifier = format ! ( "`{}`" , template_literal) ;
281-
282- styles. push ( CssToStyleResult :: Dynamic ( ExtractDynamicStyle :: new (
283- style. property ( ) ,
284- style. level ( ) ,
285- & final_identifier,
286- style. selector ( ) . cloned ( ) ,
287- ) ) ) ;
288- continue ;
289- }
290-
291- // Check if property name contains a dynamic expression placeholder
292- let property = style. property ( ) ;
293- let mut prop_is_dynamic = false ;
286+ for placeholder in expression_map. keys ( ) {
287+ if property. contains ( placeholder) {
288+ prop_is_dynamic = true ;
289+ break ;
290+ }
291+ }
294292
295- for placeholder in expression_map. keys ( ) {
296- if property. contains ( placeholder) {
297- prop_is_dynamic = true ;
298- break ;
293+ if !prop_is_dynamic {
294+ // Static style
295+ styles. push ( CssToStyleResult :: Static ( style) ) ;
299296 }
300- }
301297
302- if prop_is_dynamic {
303298 // Property name is dynamic - skip for now as it's more complex
304- continue ;
305299 }
306-
307- // Static style
308- styles. push ( CssToStyleResult :: Static ( style) ) ;
309300 }
310301
311302 styles
0 commit comments