11import { parseSync , Visitor } from 'oxc-parser'
22import { generateHash } from '@/utils'
3- import type { TransformResult , CssVarDecl , CssVarRef , Replacement } from '@/types'
3+ import type { TransformResult , Replacement } from '@/types'
44
55export const transform = ( file : string , source : string ) : TransformResult => {
66 const { program } = parseSync ( file , source )
7- const cssVarDecls : CssVarDecl [ ] = [ ]
8- const cssVarRefs : CssVarRef [ ] = [ ]
7+ const fileHash = generateHash ( file )
8+ let transformed = source
9+ let css = ''
910 const replacements : Replacement [ ] = [ ]
10- let isInClassNameAttr = false
11- let activeRange : { start : number , end : number } | null
12- let currentVarName : string | null
11+ let activeVarName : string | null
1312
1413 new Visitor ( {
1514 ImportDeclaration ( node ) {
@@ -24,74 +23,37 @@ export const transform = (file: string, source: string): TransformResult => {
2423 }
2524 } ,
2625
27- JSXAttribute ( node ) {
28- if ( node . name . name !== 'className' ) return
29- if ( node . value ?. type !== 'JSXExpressionContainer' ) return
30- isInClassNameAttr = true
31- } ,
32-
33- Identifier ( node ) {
34- if ( ! isInClassNameAttr ) return
35- cssVarRefs . push ( { name : node . name , start : node . start , end : node . end } )
36- } ,
37-
38- 'JSXAttribute:exit' ( ) {
39- isInClassNameAttr = false
40- } ,
41-
4226 VariableDeclaration ( node ) {
4327 const variableDeclarator = node . declarations [ 0 ]
4428 const identifier = variableDeclarator . id
4529 if ( identifier . type !== 'Identifier' ) return
46- currentVarName = identifier . name
47- activeRange = { start : node . start , end : node . end }
30+ activeVarName = identifier . name
4831 } ,
4932
5033 'VariableDeclaration:exit' ( ) {
51- currentVarName = null
52- activeRange = null
53- } ,
54-
55- ExpressionStatement ( node ) {
56- activeRange = { start : node . start , end : node . end }
57- } ,
58-
59- 'ExpressionStatement:exit' ( ) {
60- activeRange = null
34+ activeVarName = null
6135 } ,
6236
6337 TaggedTemplateExpression ( node ) {
6438 const tag = node . tag
6539 if ( tag . type !== 'Identifier' || ! / ^ g ? c s s $ / . test ( tag . name ) ) return
66- const template = node . quasi . quasis . map ( q => {
67- const tpl = q . value . cooked ?? ''
68- const indent = ( / ^ ( [ ^ \n ] * ?) \S / m. exec ( tpl ) ) ?. [ 1 ] ?? ''
69- return tpl . split ( '\n' ) . map ( line => line . replace ( indent , '' ) ) . join ( '\n' ) . trim ( )
70- } ) . join ( '' )
71- if ( ! activeRange ) return
72- cssVarDecls . push ( { name : currentVarName ?? '' , tag : tag . name , template, start : activeRange . start , end : activeRange . end } )
73- replacements . push ( { start : activeRange . start , end : activeRange . end , replacement : '' } )
74- } ,
75- } ) . visit ( program )
7640
77- let transformed = source
78- const hash = generateHash ( file )
79- let css = ''
41+ const cssTpl = source . slice ( node . quasi . start + 1 , node . quasi . end - 1 )
42+ let rep = ''
43+ if ( tag . name === 'gcss' ) {
44+ css += cssTpl
45+ rep = '""'
46+ } else {
47+ const clName = `${ activeVarName } _${ fileHash } `
48+ css += `.${ clName } {${ cssTpl } }`
49+ rep = `'${ activeVarName } _${ fileHash } '`
50+ }
8051
81- for ( const cssVar of cssVarDecls ) {
82- if ( cssVar . tag === 'gcss' ) {
83- css += cssVar . template
84- } else if ( cssVar . tag === 'css' ) {
85- const className = `${ cssVar . name } _${ hash } `
86- const refs = cssVarRefs . filter ( ref => ref . name === cssVar . name )
87- if ( ! refs . length ) continue
88- for ( const ref of refs ) replacements . push ( { start : ref . start , end : ref . end , replacement : `'${ className } '` } )
89- css += `.${ className } {${ cssVar . template } }`
90- }
91- }
52+ replacements . push ( { start : node . start , end : node . end , replacement : rep } )
53+ } ,
54+ } ) . visit ( program )
9255
9356 replacements . sort ( ( a , b ) => b . start - a . start )
94-
9557 for ( const rep of replacements ) transformed = transformed . slice ( 0 , rep . start ) + rep . replacement + transformed . slice ( rep . end )
9658
9759 return { transformed, css }
0 commit comments