6
6
#![ allow( clippy:: not_unsafe_ptr_arg_deref) ]
7
7
8
8
mod css;
9
+ mod engine;
9
10
#[ cfg( test) ]
10
11
mod test;
11
12
12
13
use nom_locate:: LocatedSpan ;
14
+ use serde:: Deserialize ;
13
15
use swc_core:: {
14
16
common:: {
15
17
errors:: { DiagnosticBuilder , Handler } ,
@@ -18,10 +20,11 @@ use swc_core::{
18
20
} ,
19
21
ecma:: {
20
22
ast:: {
21
- ArrayLit , CallExpr , Callee , Expr , ExprOrSpread , Ident , ImportDecl , JSXAttr ,
22
- JSXAttrName , JSXAttrOrSpread , JSXAttrValue , JSXElementName , JSXExpr , JSXExprContainer ,
23
- JSXOpeningElement , Lit , MemberExpr , MemberProp , Module , ModuleDecl , ModuleItem ,
24
- ObjectLit , Program , Str , TaggedTpl , Tpl , TplElement ,
23
+ ArrayLit , CallExpr , Callee , Expr , ExprOrSpread , Ident , ImportDecl ,
24
+ ImportNamedSpecifier , ImportSpecifier , JSXAttr , JSXAttrName , JSXAttrOrSpread ,
25
+ JSXAttrValue , JSXElementName , JSXExpr , JSXExprContainer , JSXOpeningElement , Lit ,
26
+ MemberExpr , MemberProp , Module , ModuleDecl , ModuleItem , ObjectLit , Program , Str ,
27
+ TaggedTpl , Tpl , TplElement ,
25
28
} ,
26
29
atoms:: Atom ,
27
30
visit:: { as_folder, FoldWith , VisitMut , VisitMutWith } ,
@@ -39,6 +42,21 @@ pub struct AppConfig<'a> {
39
42
/// Strict mode throws an error when an unknown class is used.
40
43
#[ serde( default ) ]
41
44
pub strict : bool ,
45
+
46
+ pub engine : Engine ,
47
+ }
48
+
49
+ #[ derive( Deserialize , Debug ) ]
50
+ #[ serde( rename_all = "kebab-case" ) ]
51
+ pub enum Engine {
52
+ Emotion ,
53
+ StyledComponents ,
54
+ }
55
+
56
+ impl Default for Engine {
57
+ fn default ( ) -> Self {
58
+ Self :: Emotion
59
+ }
42
60
}
43
61
44
62
#[ derive( Debug ) ]
@@ -55,6 +73,7 @@ enum TplTransform {
55
73
pub struct TransformVisitor < ' a > {
56
74
config : TailwindConfig < ' a > ,
57
75
strict : bool ,
76
+ engine : Engine ,
58
77
/// This is treated as a stack because tw attrs can be nested
59
78
tw_attr_stack : DepthStack < ( Span , ObjectLit ) > ,
60
79
tw_tpl : Option < TplTransform > ,
@@ -130,6 +149,7 @@ impl<'a> TransformVisitor<'a> {
130
149
Self {
131
150
config : config. config ,
132
151
strict : config. strict ,
152
+ engine : config. engine ,
133
153
..Default :: default ( )
134
154
}
135
155
}
@@ -224,44 +244,16 @@ impl<'a> VisitMut for TransformVisitor<'a> {
224
244
/// b) extract any tw attributes and transform them into a css declarations
225
245
fn visit_mut_jsx_opening_element ( & mut self , n : & mut JSXOpeningElement ) {
226
246
if self . tw_style_imported && let JSXElementName :: Ident ( i) = & n. name && i. sym . eq ( "TailwindStyle" ) {
227
-
228
247
let atom: Atom = css:: format_css (
229
248
true ,
230
249
self . config . theme . font_family . get ( "sans" ) . map ( |v| v. as_slice ( ) ) . unwrap_or ( & [ ] ) ,
231
250
self . config . theme . font_family . get ( "mono" ) . map ( |v| v. as_slice ( ) ) . unwrap_or ( & [ ] )
232
251
) . into ( ) ;
233
252
234
- n. name = JSXElementName :: Ident ( Ident :: new ( "Global" . into ( ) , i. span ) ) ;
235
- n. attrs . push ( JSXAttrOrSpread :: JSXAttr (
236
- JSXAttr {
237
- span : n. span ,
238
- name : JSXAttrName :: Ident ( Ident :: new ( "styles" . into ( ) , n. span ) ) ,
239
- value : Some ( JSXAttrValue :: JSXExprContainer ( JSXExprContainer {
240
- span : n. span ,
241
- expr : JSXExpr :: Expr ( Box :: new ( Expr :: TaggedTpl (
242
- TaggedTpl {
243
- span : n. span ,
244
- tag : Box :: new ( Expr :: Ident ( Ident {
245
- span : n. span ,
246
- sym : "css" . into ( ) ,
247
- optional : false
248
- } ) ) ,
249
- type_params : None , tpl : Tpl {
250
- span : n. span ,
251
- exprs : vec ! [ ] ,
252
- quasis : vec ! [ TplElement {
253
- cooked: Some ( atom. clone( ) ) ,
254
- raw: atom,
255
- span: n. span,
256
- tail: true
257
- } ] ,
258
- }
259
- } )
260
-
261
- ) )
262
- } ) ) ,
263
- }
264
- ) ) ;
253
+ match self . engine {
254
+ Engine :: Emotion => self . emotion_global ( i. span , n, atom) ,
255
+ Engine :: StyledComponents => self . styled_components_global ( i. span , n, atom) ,
256
+ }
265
257
}
266
258
267
259
self . tw_attr_stack . inc_depth ( ) ;
@@ -483,7 +475,6 @@ impl<'a> VisitMut for TransformVisitor<'a> {
483
475
{
484
476
let has_style_import = specifiers. iter ( ) . any ( |s| match s {
485
477
ImportSpecifier :: Named ( ImportNamedSpecifier { local, .. } ) => {
486
- println ! ( "{:?}" , local) ;
487
478
local. sym . eq ( "TailwindStyle" )
488
479
}
489
480
_ => false ,
@@ -497,6 +488,35 @@ impl<'a> VisitMut for TransformVisitor<'a> {
497
488
498
489
false
499
490
} ) ;
491
+
492
+ if self . tw_style_imported {
493
+ match self . engine {
494
+ Engine :: Emotion => {
495
+ // no-op
496
+ }
497
+ Engine :: StyledComponents => {
498
+ // import createGlobalStyle and create the Global object
499
+ n. body
500
+ . push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
501
+ src : Box :: new ( Str {
502
+ raw : Some ( "styled-components" . into ( ) ) ,
503
+ value : "styled-components" . into ( ) ,
504
+ span : DUMMY_SP ,
505
+ } ) ,
506
+ span : DUMMY_SP ,
507
+ specifiers : vec ! [ ImportSpecifier :: Named ( ImportNamedSpecifier {
508
+ span: DUMMY_SP ,
509
+ local: Ident :: new( "createGlobalStyle" . into( ) , DUMMY_SP ) ,
510
+ is_type_only: false ,
511
+ imported: None ,
512
+ } ) ] ,
513
+ asserts : None ,
514
+ type_only : false ,
515
+ } ) ) )
516
+ }
517
+ }
518
+ }
519
+
500
520
n. visit_mut_children_with ( self ) ;
501
521
}
502
522
}
0 commit comments