@@ -25,7 +25,54 @@ const shorthandBorderProps = [
2525 "border-style" ,
2626] ;
2727
28- const transformDecls = ( styles , declarations , result ) => {
28+ /**
29+ * Extracts @keyframes from CSS and returns the cleaned CSS and keyframes object
30+ * @param {string } css - The input CSS string
31+ * @returns {{css: string, keyframes: Object} } - Cleaned CSS and keyframes object
32+ */
33+ const extractKeyframes = ( css ) => {
34+ const keyframes = { } ;
35+ let cleanedCss = css ;
36+
37+ // Find @keyframes by manually parsing to handle nested braces
38+ let index = 0 ;
39+ while ( index < css . length ) {
40+ const keyframesMatch = css . slice ( index ) . match ( / @ k e y f r a m e s \s + ( [ ^ \s { ] + ) \s * { / ) ;
41+ if ( ! keyframesMatch ) break ;
42+
43+ const startIndex = index + keyframesMatch . index ;
44+ const nameEndIndex = startIndex + keyframesMatch [ 0 ] . length ;
45+ const name = keyframesMatch [ 1 ] ;
46+
47+ // Find the matching closing brace
48+ let braceCount = 1 ;
49+ let currentIndex = nameEndIndex ;
50+ while ( currentIndex < css . length && braceCount > 0 ) {
51+ if ( css [ currentIndex ] === '{' ) {
52+ braceCount ++ ;
53+ } else if ( css [ currentIndex ] === '}' ) {
54+ braceCount -- ;
55+ }
56+ currentIndex ++ ;
57+ }
58+
59+ if ( braceCount === 0 ) {
60+ // Extract the body (without the outer braces)
61+ const body = css . slice ( nameEndIndex , currentIndex - 1 ) . trim ( ) ;
62+ keyframes [ name ] = body ;
63+
64+ // Mark for removal by replacing with spaces to maintain positions
65+ const fullKeyframe = css . slice ( startIndex , currentIndex ) ;
66+ cleanedCss = cleanedCss . replace ( fullKeyframe , '' ) ;
67+ }
68+
69+ index = currentIndex ;
70+ }
71+
72+ return { css : cleanedCss , keyframes } ;
73+ } ;
74+
75+ const transformDecls = ( styles , declarations , result , keyframes ) => {
2976 for ( const d in declarations ) {
3077 const declaration = declarations [ d ] ;
3178 if ( declaration . type !== "declaration" ) continue ;
@@ -64,13 +111,30 @@ const transformDecls = (styles, declarations, result) => {
64111 } else {
65112 Object . assign ( styles , transformed ) ;
66113 }
114+ } else if ( [ 'animation' , 'animation-name' ] . includes ( property ) && keyframes && Object . keys ( keyframes ) . length > 0 ) {
115+ // Pass all keyframes to transformCSS - it will figure out which ones to use
116+ const keyframeDeclarations = [ ] ;
117+ for ( const name in keyframes ) {
118+ keyframeDeclarations . push ( [ '@keyframes ' + name , keyframes [ name ] ] ) ;
119+ }
120+ const transformed = transformCSS ( [
121+ ...keyframeDeclarations ,
122+ [ property , value ]
123+ ] ) ;
124+ Object . assign ( styles , transformed ) ;
67125 } else {
68126 Object . assign ( styles , transformCSS ( [ [ property , value ] ] ) ) ;
69127 }
70128 }
71129} ;
72130
73131const transform = ( css , options ) => {
132+ // Extract keyframes and store them separately, before parsing (remove them from css)
133+ let keyframes ;
134+ if ( options ?. parseKeyframes ) {
135+ ( { css, keyframes } = extractKeyframes ( css ) ) ;
136+ }
137+
74138 const { stylesheet } = parseCSS ( css ) ;
75139 const rules = sortRules ( stylesheet . rules ) ;
76140
@@ -126,7 +190,7 @@ const transform = (css, options) => {
126190
127191 const selector = rule . selectors [ s ] . replace ( / ^ \. / , "" ) ;
128192 const styles = ( result [ selector ] = result [ selector ] || { } ) ;
129- transformDecls ( styles , rule . declarations , result ) ;
193+ transformDecls ( styles , rule . declarations , result , keyframes ) ;
130194 }
131195
132196 if (
@@ -179,14 +243,18 @@ const transform = (css, options) => {
179243 const selector = ruleRule . selectors [ s ] . replace ( / ^ \. / , "" ) ;
180244 const mediaStyles = ( result [ media ] [ selector ] =
181245 result [ media ] [ selector ] || { } ) ;
182- transformDecls ( mediaStyles , ruleRule . declarations , result ) ;
246+ transformDecls ( mediaStyles , ruleRule . declarations , result , keyframes ) ;
183247 }
184248 }
185249 }
186250 }
187251
188252 if ( result . __exportProps ) {
189- Object . assign ( result , result . __exportProps ) ;
253+ if ( Object . keys ( result . __exportProps ) . length === 0 ) {
254+ delete result . __exportProps ;
255+ } else {
256+ Object . assign ( result , result . __exportProps ) ;
257+ }
190258 }
191259
192260 return result ;
0 commit comments