@@ -186,8 +186,10 @@ const extractIfFunctions = (cssText) => {
186186/**
187187 * Parse if() function content - supports both single conditions and multiple chained conditions
188188 */
189- const parseIfFunction = ( content ) => {
190- // Split content by semicolons, but respect parentheses and quotes
189+ /**
190+ * Split content by semicolons, respecting parentheses and quotes
191+ */
192+ const splitIfConditionSegments = ( content ) => {
191193 const segments = [ ] ;
192194 let currentSegment = '' ;
193195 let parenDepth = 0 ;
@@ -230,7 +232,51 @@ const parseIfFunction = (content) => {
230232 segments . push ( currentSegment . trim ( ) ) ;
231233 }
232234
233- // Parse segments into conditions and values
235+ return segments ;
236+ } ;
237+
238+ /**
239+ * Find colon outside of parentheses and quotes
240+ */
241+ const findConditionValueSeparator = ( segment ) => {
242+ let parenDepth = 0 ;
243+ let inQuotes = false ;
244+ let quoteChar = '' ;
245+
246+ for ( let i = 0 ; i < segment . length ; i ++ ) {
247+ const char = segment [ i ] ;
248+ const previousChar = i > 0 ? segment [ i - 1 ] : '' ;
249+
250+ // Handle quotes
251+ if ( ( char === '"' || char === "'" ) && previousChar !== '\\' ) {
252+ if ( ! inQuotes ) {
253+ inQuotes = true ;
254+ quoteChar = char ;
255+ } else if ( char === quoteChar ) {
256+ inQuotes = false ;
257+ quoteChar = '' ;
258+ }
259+ }
260+
261+ if ( ! inQuotes ) {
262+ if ( char === '(' ) {
263+ parenDepth ++ ;
264+ } else if ( char === ')' ) {
265+ parenDepth -- ;
266+ } else if ( char === ':' && parenDepth === 0 ) {
267+ return i ;
268+ }
269+ }
270+ }
271+
272+ return - 1 ;
273+ } ;
274+
275+ /**
276+ * Parse if() function content - supports both single conditions and multiple chained conditions
277+ */
278+ const parseIfFunction = ( content ) => {
279+ const segments = splitIfConditionSegments ( content ) ;
234280 const conditions = [ ] ;
235281 let elseValue = null ;
236282
@@ -243,39 +289,7 @@ const parseIfFunction = (content) => {
243289 }
244290
245291 // Parse condition: value format
246- let colonIndex = - 1 ;
247- let parenDepth = 0 ;
248- let inQuotes = false ;
249- let quoteChar = '' ;
250-
251- // Find the colon that's outside of parentheses and quotes
252- for ( let i = 0 ; i < segment . length ; i ++ ) {
253- const char = segment [ i ] ;
254- const previousChar = i > 0 ? segment [ i - 1 ] : '' ;
255-
256- // Handle quotes
257- if ( ( char === '"' || char === "'" ) && previousChar !== '\\' ) {
258- if ( ! inQuotes ) {
259- inQuotes = true ;
260- quoteChar = char ;
261- } else if ( char === quoteChar ) {
262- inQuotes = false ;
263- quoteChar = '' ;
264- }
265- }
266-
267- if ( ! inQuotes ) {
268- if ( char === '(' ) {
269- parenDepth ++ ;
270- } else if ( char === ')' ) {
271- parenDepth -- ;
272- } else if ( char === ':' && parenDepth === 0 ) {
273- colonIndex = i ;
274- break ;
275- }
276- }
277- }
278-
292+ const colonIndex = findConditionValueSeparator ( segment ) ;
279293 if ( colonIndex === - 1 ) {
280294 throw new Error ( 'Invalid if() function: missing colon in segment' ) ;
281295 }
@@ -304,21 +318,10 @@ const parseIfFunction = (content) => {
304318 throw new Error ( 'Invalid if() function: missing else clause' ) ;
305319 }
306320
307- // For backward compatibility, if there's only one condition, return the old format
308- if ( conditions . length === 1 ) {
309- return {
310- conditionType : conditions [ 0 ] . conditionType ,
311- conditionExpression : conditions [ 0 ] . conditionExpression ,
312- trueValue : conditions [ 0 ] . value ,
313- falseValue : elseValue
314- } ;
315- }
316-
317- // For multiple conditions, return the new format
318321 return {
319322 conditions,
320- falseValue : elseValue ,
321- isMultipleConditions : true
323+ elseValue,
324+ isMultipleConditions : conditions . length > 1
322325 } ;
323326} ;
324327
@@ -344,60 +347,13 @@ const transformPropertyToNative = (selector, property, value) => {
344347 try {
345348 const parsed = parseIfFunction ( ifFunc . content ) ;
346349
347- // Handle multiple conditions format
348- if ( parsed . isMultipleConditions ) {
349- // Check if any condition uses style() - if so, needs runtime processing
350- const hasStyleCondition = parsed . conditions . some (
351- ( condition ) => condition . conditionType === 'style'
352- ) ;
353-
354- if ( hasStyleCondition ) {
355- // If any condition uses style(), fall back to runtime processing
356- runtimeRules . push ( {
357- selector,
358- property,
359- value,
360- condition : parsed
361- } ) ;
362- continue ;
363- }
364-
365- // All conditions are media() or supports() - can transform to native CSS
366- // Create fallback rule first
367- const fallbackValue = value . replace (
368- ifFunc . fullFunction ,
369- parsed . falseValue
370- ) ;
371- nativeRules . push ( {
372- condition : null , // No condition = fallback
373- rule : `${ selector } { ${ property } : ${ fallbackValue } ; }`
374- } ) ;
375-
376- // Create conditional rules for each condition (in reverse order for CSS cascade)
377- const { conditions } = parsed ;
378- for ( let i = conditions . length - 1 ; i >= 0 ; i -- ) {
379- const condition = conditions [ i ] ;
380- const nativeCondition =
381- condition . conditionType === 'media'
382- ? `@media (${ condition . conditionExpression } )`
383- : `@supports (${ condition . conditionExpression } )` ;
384-
385- const conditionalValue = value . replace (
386- ifFunc . fullFunction ,
387- condition . value
388- ) ;
389- nativeRules . push ( {
390- condition : nativeCondition ,
391- rule : `${ selector } { ${ property } : ${ conditionalValue } ; }`
392- } ) ;
393- }
394-
395- continue ;
396- }
350+ // Check if any condition uses style() - if so, needs runtime processing
351+ const hasStyleCondition = parsed . conditions . some (
352+ ( condition ) => condition . conditionType === 'style'
353+ ) ;
397354
398- // Handle single condition format (backward compatibility)
399- if ( parsed . conditionType === 'style' ) {
400- // Style() conditions need runtime processing
355+ if ( hasStyleCondition ) {
356+ // If any condition uses style(), fall back to runtime processing
401357 runtimeRules . push ( {
402358 selector,
403359 property,
@@ -407,31 +363,35 @@ const transformPropertyToNative = (selector, property, value) => {
407363 continue ;
408364 }
409365
410- // Media() and supports() can be transformed to native CSS
411- const nativeCondition =
412- parsed . conditionType === 'media'
413- ? `@media (${ parsed . conditionExpression } )`
414- : `@supports (${ parsed . conditionExpression } )` ;
415-
416- // Create conditional rule with true value
417- const trueValue = value . replace (
418- ifFunc . fullFunction ,
419- parsed . trueValue
420- ) ;
421- nativeRules . push ( {
422- condition : nativeCondition ,
423- rule : `${ selector } { ${ property } : ${ trueValue } ; }`
424- } ) ;
425-
426- // Create fallback rule with false value
427- const falseValue = value . replace (
366+ // All conditions are media() or supports() - can transform to native CSS
367+ // Create fallback rule first
368+ const fallbackValue = value . replace (
428369 ifFunc . fullFunction ,
429- parsed . falseValue
370+ parsed . elseValue
430371 ) ;
431372 nativeRules . push ( {
432373 condition : null , // No condition = fallback
433- rule : `${ selector } { ${ property } : ${ falseValue } ; }`
374+ rule : `${ selector } { ${ property } : ${ fallbackValue } ; }`
434375 } ) ;
376+
377+ // Create conditional rules for each condition (in reverse order for CSS cascade)
378+ const { conditions } = parsed ;
379+ for ( let i = conditions . length - 1 ; i >= 0 ; i -- ) {
380+ const condition = conditions [ i ] ;
381+ const nativeCondition =
382+ condition . conditionType === 'media'
383+ ? `@media (${ condition . conditionExpression } )`
384+ : `@supports (${ condition . conditionExpression } )` ;
385+
386+ const conditionalValue = value . replace (
387+ ifFunc . fullFunction ,
388+ condition . value
389+ ) ;
390+ nativeRules . push ( {
391+ condition : nativeCondition ,
392+ rule : `${ selector } { ${ property } : ${ conditionalValue } ; }`
393+ } ) ;
394+ }
435395 } catch ( error ) {
436396 // If parsing fails, fall back to runtime processing
437397 runtimeRules . push ( {
0 commit comments