@@ -90,115 +90,116 @@ pub fn css_to_style_literal<'a>(
9090
9191 if is_dynamic
9292 && let Some ( idx) = expr_idx
93- && idx < css. expressions . len ( ) {
94- // This is a dynamic style - the value comes from an expression
95- let expr = & css. expressions [ idx] ;
93+ && idx < css. expressions . len ( )
94+ {
95+ // This is a dynamic style - the value comes from an expression
96+ let expr = & css. expressions [ idx] ;
9697
97- // Check if expression is a function (arrow function or function expression)
98- let is_function = matches ! (
99- expr,
100- oxc_ast:: ast:: Expression :: ArrowFunctionExpression ( _)
101- | oxc_ast:: ast:: Expression :: FunctionExpression ( _)
102- ) ;
98+ // Check if expression is a function (arrow function or function expression)
99+ let is_function = matches ! (
100+ expr,
101+ oxc_ast:: ast:: Expression :: ArrowFunctionExpression ( _)
102+ | oxc_ast:: ast:: Expression :: FunctionExpression ( _)
103+ ) ;
103104
104- let mut identifier = expression_to_code ( expr) ;
105+ let mut identifier = expression_to_code ( expr) ;
105106
106- // Normalize the code string
107- // 1. Remove newlines and tabs, replace with spaces
108- identifier = identifier. replace ( [ '\n' , '\t' ] , " " ) ;
109- // 2. Normalize multiple spaces to single space
110- while identifier. contains ( " " ) {
111- identifier = identifier. replace ( " " , " " ) ;
112- }
113- // 3. Normalize arrow function whitespace
114- identifier = identifier
115- . replace ( " => " , "=>" )
116- . replace ( " =>" , "=>" )
117- . replace ( "=> " , "=>" ) ;
118- // 4. Normalize function expression formatting
119- if is_function {
120- // Normalize function() { } to function(){ }
121- identifier = identifier. replace ( "function() {" , "function(){" ) ;
122- identifier = identifier. replace ( "function (" , "function(" ) ;
123- // Remove trailing semicolon and spaces before closing brace
124- identifier = identifier. replace ( "; }" , "}" ) ;
125- identifier = identifier. replace ( " }" , "}" ) ;
107+ // Normalize the code string
108+ // 1. Remove newlines and tabs, replace with spaces
109+ identifier = identifier. replace ( [ '\n' , '\t' ] , " " ) ;
110+ // 2. Normalize multiple spaces to single space
111+ while identifier. contains ( " " ) {
112+ identifier = identifier. replace ( " " , " " ) ;
113+ }
114+ // 3. Normalize arrow function whitespace
115+ identifier = identifier
116+ . replace ( " => " , "=>" )
117+ . replace ( " =>" , "=>" )
118+ . replace ( "=> " , "=>" ) ;
119+ // 4. Normalize function expression formatting
120+ if is_function {
121+ // Normalize function() { } to function(){ }
122+ identifier = identifier. replace ( "function() {" , "function(){" ) ;
123+ identifier = identifier. replace ( "function (" , "function(" ) ;
124+ // Remove trailing semicolon and spaces before closing brace
125+ identifier = identifier. replace ( "; }" , "}" ) ;
126+ identifier = identifier. replace ( " }" , "}" ) ;
126127
127- // Wrap function in parentheses if not already wrapped
128- // and add (rest) call
129- let trimmed = identifier. trim ( ) ;
130- // Check if already wrapped in parentheses
131- if !( trimmed. starts_with ( '(' ) && trimmed. ends_with ( ')' ) ) {
132- identifier = format ! ( "({})" , trimmed) ;
133- }
134- // Add (rest) call
135- identifier = format ! ( "{}(rest)" , identifier) ;
136- }
137- // 5. Normalize quotes
138- if !is_function {
139- // For non-function expressions, convert property access quotes
140- // object["color"] -> object['color']
141- identifier = identifier. replace ( "[\" " , "['" ) . replace ( "\" ]" , "']" ) ;
142- } else {
143- // For function expressions, convert string literals in ternary operators
144- // This handles cases like: (props)=>props.b ? "a" : "b" -> (props)=>props.b ? 'a' : 'b'
145- // Use simple pattern matching for ternary operator string literals
146- // Pattern: ? "text" : "text" -> ? 'text' : 'text'
147- // We'll replace " with ' but only in the context of ternary operators
148- let mut result = String :: new ( ) ;
149- let mut chars = identifier. chars ( ) . peekable ( ) ;
150- let mut in_ternary_string = false ;
128+ // Wrap function in parentheses if not already wrapped
129+ // and add (rest) call
130+ let trimmed = identifier. trim ( ) ;
131+ // Check if already wrapped in parentheses
132+ if !( trimmed. starts_with ( '(' ) && trimmed. ends_with ( ')' ) ) {
133+ identifier = format ! ( "({})" , trimmed) ;
134+ }
135+ // Add (rest) call
136+ identifier = format ! ( "{}(rest)" , identifier) ;
137+ }
138+ // 5. Normalize quotes
139+ if !is_function {
140+ // For non-function expressions, convert property access quotes
141+ // object["color"] -> object['color']
142+ identifier = identifier. replace ( "[\" " , "['" ) . replace ( "\" ]" , "']" ) ;
143+ } else {
144+ // For function expressions, convert string literals in ternary operators
145+ // This handles cases like: (props)=>props.b ? "a" : "b" -> (props)=>props.b ? 'a' : 'b'
146+ // Use simple pattern matching for ternary operator string literals
147+ // Pattern: ? "text" : "text" -> ? 'text' : 'text'
148+ // We'll replace " with ' but only in the context of ternary operators
149+ let mut result = String :: new ( ) ;
150+ let mut chars = identifier. chars ( ) . peekable ( ) ;
151+ let mut in_ternary_string = false ;
151152
152- while let Some ( ch) = chars. next ( ) {
153- if ch == '?' || ch == ':' {
154- result. push ( ch) ;
155- // Skip whitespace
156- while let Some ( & ' ' ) = chars. peek ( ) {
157- result. push ( chars. next ( ) . unwrap ( ) ) ;
158- }
159- // Check if next is a string literal
160- if let Some ( & '"' ) = chars. peek ( ) {
161- in_ternary_string = true ;
162- result. push ( '\'' ) ;
163- chars. next ( ) ; // consume the "
164- continue ;
165- }
166- } else if in_ternary_string && ch == '"' {
167- // Check if this is a closing quote by looking ahead
168- let mut peeked = chars. clone ( ) ;
169- // Skip whitespace
170- while let Some ( & ' ' ) = peeked. peek ( ) {
171- peeked. next ( ) ;
172- }
173- // If next is : or ? or ) or } or end, it's a closing quote
174- if peeked. peek ( ) . is_none ( )
175- || matches ! (
176- peeked. peek( ) ,
177- Some ( & ':' ) | Some ( & '?' ) | Some ( & ')' ) | Some ( & '}' )
178- )
179- {
180- result. push ( '\'' ) ;
181- in_ternary_string = false ;
182- continue ;
183- }
184- // Not a closing quote, keep as is
185- result. push ( ch) ;
186- } else {
187- result. push ( ch) ;
188- }
153+ while let Some ( ch) = chars. next ( ) {
154+ if ch == '?' || ch == ':' {
155+ result. push ( ch) ;
156+ // Skip whitespace
157+ while let Some ( & ' ' ) = chars. peek ( ) {
158+ result. push ( chars. next ( ) . unwrap ( ) ) ;
189159 }
190- identifier = result;
160+ // Check if next is a string literal
161+ if let Some ( & '"' ) = chars. peek ( ) {
162+ in_ternary_string = true ;
163+ result. push ( '\'' ) ;
164+ chars. next ( ) ; // consume the "
165+ continue ;
166+ }
167+ } else if in_ternary_string && ch == '"' {
168+ // Check if this is a closing quote by looking ahead
169+ let mut peeked = chars. clone ( ) ;
170+ // Skip whitespace
171+ while let Some ( & ' ' ) = peeked. peek ( ) {
172+ peeked. next ( ) ;
173+ }
174+ // If next is : or ? or ) or } or end, it's a closing quote
175+ if peeked. peek ( ) . is_none ( )
176+ || matches ! (
177+ peeked. peek( ) ,
178+ Some ( & ':' ) | Some ( & '?' ) | Some ( & ')' ) | Some ( & '}' )
179+ )
180+ {
181+ result. push ( '\'' ) ;
182+ in_ternary_string = false ;
183+ continue ;
184+ }
185+ // Not a closing quote, keep as is
186+ result. push ( ch) ;
187+ } else {
188+ result. push ( ch) ;
191189 }
192- identifier = identifier. trim ( ) . to_string ( ) ;
193-
194- styles. push ( CssToStyleResult :: Dynamic ( ExtractDynamicStyle :: new (
195- style. property ( ) ,
196- style. level ( ) ,
197- & identifier,
198- style. selector ( ) . cloned ( ) ,
199- ) ) ) ;
200- continue ;
201190 }
191+ identifier = result;
192+ }
193+ identifier = identifier. trim ( ) . to_string ( ) ;
194+
195+ styles. push ( CssToStyleResult :: Dynamic ( ExtractDynamicStyle :: new (
196+ style. property ( ) ,
197+ style. level ( ) ,
198+ & identifier,
199+ style. selector ( ) . cloned ( ) ,
200+ ) ) ) ;
201+ continue ;
202+ }
202203
203204 // Check if property name contains a dynamic expression placeholder
204205 let property = style. property ( ) ;
0 commit comments