@@ -86,11 +86,50 @@ function innerContent(input: string): string {
8686 return input . slice ( start + 1 , end ) . trim ( )
8787}
8888
89+ // Helper to extract individual gradient functions from comma-separated list
90+ function extractGradients ( input : string ) : string [ ] {
91+ const results : string [ ] = [ ]
92+ let depth = 0
93+ let current = ''
94+ let i = 0
95+
96+ while ( i < input . length ) {
97+ const ch = input [ i ]
98+
99+ if ( ch === '(' ) depth ++
100+ else if ( ch === ')' ) depth --
101+
102+ if ( ch === ',' && depth === 0 ) {
103+ const trimmed = current . trim ( )
104+ if ( trimmed && / ^ ( l i n e a r | r a d i a l | c o n i c ) - g r a d i e n t \s * \( / i. test ( trimmed ) ) {
105+ results . push ( trimmed )
106+ }
107+ current = ''
108+ } else {
109+ current += ch
110+ }
111+ i ++
112+ }
113+
114+ // Don't forget the last one
115+ const trimmed = current . trim ( )
116+ if ( trimmed && / ^ ( l i n e a r | r a d i a l | c o n i c ) - g r a d i e n t \s * \( / i. test ( trimmed ) ) {
117+ results . push ( trimmed )
118+ }
119+
120+ return results . length > 0 ? results : [ input . trim ( ) ]
121+ }
122+
89123export function parseGradient ( input : string ) : ParsedGradient {
90124 // Strip trailing semicolons that may be present when copying from CSS rules
91125 const cleanedInput = input . trim ( ) . replace ( / ; + $ / , '' )
92- const type = classifyFunction ( cleanedInput )
93- const body = innerContent ( cleanedInput )
126+
127+ // Extract first gradient from potentially multiple gradients
128+ const gradients = extractGradients ( cleanedInput )
129+ const firstGradient = gradients [ 0 ]
130+
131+ const type = classifyFunction ( firstGradient )
132+ const body = innerContent ( firstGradient )
94133
95134 // split by top-level commas
96135 const segments = splitTopLevel ( body , ',' )
@@ -169,12 +208,18 @@ export function parseGradient(input: string): ParsedGradient {
169208 }
170209 } else if ( type === 'radial' ) {
171210 const shape = / ( c i r c l e | e l l i p s e ) / i. exec ( prelude ) ?. [ 1 ] ?. toLowerCase ( ) as 'circle' | 'ellipse' | undefined
172- // size keywords or length pairs
211+ // size keywords or length/percentage values
173212 const sizeKw = / ( c l o s e s t - s i d e | c l o s e s t - c o r n e r | f a r t h e s t - s i d e | f a r t h e s t - c o r n e r ) / i. exec ( prelude ) ?. [ 1 ]
174213 let size : string | undefined = sizeKw ?. toLowerCase ( )
175214 if ( ! size ) {
215+ // Try to match explicit size: single length (for circle) or pair of lengths (for ellipse)
216+ const singleSize = prelude . match ( / \b ( \d + (?: \. \d + ) ? (?: p x | e m | r e m | v w | v h | % ) ) (? ! \s + \d ) / i)
176217 const pair = prelude . match ( / \b ( \d + (?: \. \d + ) ? (?: % | p x | e m | r e m | v w | v h ) ) \s + ( \d + (?: \. \d + ) ? (?: % | p x | e m | r e m | v w | v h ) ) \b / )
177- if ( pair ) size = `${ pair [ 1 ] } ${ pair [ 2 ] } `
218+ if ( pair ) {
219+ size = `${ pair [ 1 ] } ${ pair [ 2 ] } `
220+ } else if ( singleSize ) {
221+ size = singleSize [ 1 ]
222+ }
178223 }
179224 const { namedPosition, position } = extractPosition ( prelude )
180225 radial = {
@@ -273,3 +318,18 @@ export function parseGradient(input: string): ParsedGradient {
273318 }
274319}
275320
321+ // Parse multiple gradients from a comma-separated string
322+ export function parseMultipleGradients ( input : string ) : ParsedGradient [ ] {
323+ const cleanedInput = input . trim ( ) . replace ( / ; + $ / , '' )
324+ const gradients = extractGradients ( cleanedInput )
325+
326+ return gradients . map ( g => {
327+ try {
328+ return parseGradient ( g )
329+ } catch ( e ) {
330+ // Skip invalid gradients
331+ return null
332+ }
333+ } ) . filter ( Boolean ) as ParsedGradient [ ]
334+ }
335+
0 commit comments