import MagicString from 'magic-string' ; import debug from '../util/debug' ; import walk from 'acorn-walk' ; import { Node } from 'acorn' ; import { Root , ChildNode , Rule } from 'postcss' ; import { TransformResult } from 'rollup' ; export default function transformTsx ( code , node , cssRoot ) { let match = /= (.*?Style);/ . exec ( code ) ; if ( match ) { debug . red ( 'transformTsx:code:\n' , code ) ; const s = new MagicString ( code ) ; const utilityClasses = _buildTailwindClassList ( node , cssRoot ) ; if ( utilityClasses ) { s . overwrite ( match . index , match . index + match [ 1 ] . length + 2 , `= \`${ utilityClasses } \${${ match [ 1 ] }}\`` ) ; } return { code : s . toString ( ) . replace ( /\\:/g , '\\\\:' ) } ; } } function _buildTailwindClassList ( node , cssRoot ) { const classes = _parseClasses ( node ) ; if ( classes . length ) { return cssRoot ?. nodes ?. filter ( isRule ) . reduce ( ( acc , rule ) => { const match = rule . selector . replace ( /\\/ , '' ) . match ( /([a-zA-Z0-9-]+$|[a-zA-Z0-9-]+:[a-zA-Z0-9-]+)/ ) ; if ( match && classes . includes ( match ! [ 0 ] ) ) { return rule . toString ( ) . replace ( /\s+/gm , ' ' ) + ' \\n' + acc ; } return acc ; } , '' ) ; } } function _parseClasses ( node ) { return _parseStyleDecorator ( node ) . concat ( _parseInlineClasses ( node ) ) ; } function _parseInlineClasses ( node ) { let result = [ ] ; walk . simple ( node , { Property ( prop ) { if ( prop ?. key ?. name === 'class' ) { walk . simple ( prop ?. value , { Literal ( n ) { result = result . concat ( _trimSizingDslSyntax ( n . value ) . split ( ' ' ) ) ; } } ) ; } } } ) ; return result ; } function _parseStyleDecorator ( node ) { let result = [ ] ; walk . simple ( node , { CallExpression ( ce ) { if ( ce . callee ?. name === '__decorate' ) { walk . simple ( ce , { Literal ( lit ) { walk . simple ( node , { AssignmentExpression ( ae ) { if ( ae . left . property ?. name === lit . value ) { walk . simple ( ae . right . body , { Property ( prop ) { result = result . concat ( _trimSizingDslSyntax ( prop . key . value ) . split ( ' ' ) ) ; } } ) ; } } } ) ; } } ) ; } } , } ) ; return result ; } function _trimSizingDslSyntax ( s ) { return s . toString ( ) . replace ( /\S+<|[<>]/gm , '' ) ; } function isRule ( node ) { return ( node as Rule ) . selector !== undefined ; }