@@ -7,41 +7,41 @@ use swc_ecma_ast::*;
7
7
use swc_ecma_utils:: quote_ident;
8
8
use swc_ecma_visit:: { noop_fold_type, Fold , FoldWith } ;
9
9
10
- pub fn aleph_jsx_fold ( resolver : Rc < RefCell < Resolver > > , source : Rc < SourceMap > ) -> impl Fold {
11
- AlephJsxFold {
10
+ pub fn jsx_magic_fold ( resolver : Rc < RefCell < Resolver > > , source : Rc < SourceMap > ) -> impl Fold {
11
+ JSXMagicFold {
12
12
resolver : resolver. clone ( ) ,
13
13
source,
14
14
inline_style_idx : 0 ,
15
15
}
16
16
}
17
17
18
- pub fn aleph_jsx_pass2_fold (
18
+ pub fn jsx_magic_pass_2_fold (
19
19
resolver : Rc < RefCell < Resolver > > ,
20
20
source : Rc < SourceMap > ,
21
21
is_dev : bool ,
22
22
) -> impl Fold {
23
- AlephJsxPass2Fold {
23
+ JSXMagicPass2Fold {
24
24
resolver : resolver. clone ( ) ,
25
25
source,
26
26
is_dev,
27
27
}
28
28
}
29
29
30
- /// aleph.js jsx fold, core functions include:
30
+ /// JSX magic fold, core functions include:
31
31
/// - add `__sourceFile` prop in development mode
32
32
/// - resolve `a` to `Anchor`
33
33
/// - resolve `head` to `Head`
34
34
/// - resolve `link` to `StyleLink`
35
35
/// - resolve `style` to `InlineStyle`
36
36
/// - resolve `script` to `CustomScript`
37
37
/// - optimize `img` in producation mode
38
- struct AlephJsxFold {
38
+ struct JSXMagicFold {
39
39
resolver : Rc < RefCell < Resolver > > ,
40
40
source : Rc < SourceMap > ,
41
41
inline_style_idx : i32 ,
42
42
}
43
43
44
- impl AlephJsxFold {
44
+ impl JSXMagicFold {
45
45
fn new_inline_style_ident ( & mut self ) -> String {
46
46
let resolver = self . resolver . borrow ( ) ;
47
47
let mut ident: String = "inline-style-" . to_owned ( ) ;
@@ -234,7 +234,7 @@ impl AlephJsxFold {
234
234
}
235
235
}
236
236
237
- impl Fold for AlephJsxFold {
237
+ impl Fold for JSXMagicFold {
238
238
noop_fold_type ! ( ) ;
239
239
240
240
fn fold_jsx_element ( & mut self , mut el : JSXElement ) -> JSXElement {
@@ -264,8 +264,7 @@ impl Fold for AlephJsxFold {
264
264
es. push ( raw. into ( ) ) ;
265
265
}
266
266
for quasi in quasis {
267
- let raw = self . source . span_to_snippet ( quasi. span . clone ( ) ) . unwrap ( ) ;
268
- qs. push ( raw. into ( ) ) ;
267
+ qs. push ( quasi. raw . value . to_string ( ) ) ;
269
268
}
270
269
let ( t, id) = inline_style;
271
270
resolver. inline_styles . insert (
@@ -306,13 +305,63 @@ impl Fold for AlephJsxFold {
306
305
}
307
306
}
308
307
309
- struct AlephJsxPass2Fold {
308
+ struct JSXMagicPass2Fold {
310
309
resolver : Rc < RefCell < Resolver > > ,
311
310
source : Rc < SourceMap > ,
312
311
is_dev : bool ,
313
312
}
314
313
315
- impl AlephJsxPass2Fold {
314
+ impl JSXMagicPass2Fold {
315
+ fn record_jsx_class_name ( & mut self , expr : Box < Expr > ) {
316
+ match expr. as_ref ( ) {
317
+ Expr :: Lit ( Lit :: Str ( Str { value, .. } ) ) => {
318
+ let s = value. as_ref ( ) ;
319
+ if s != "" {
320
+ self
321
+ . resolver
322
+ . borrow_mut ( )
323
+ . jsx_static_class_names
324
+ . insert ( s. into ( ) ) ;
325
+ }
326
+ }
327
+ Expr :: Lit ( Lit :: JSXText ( JSXText { value, .. } ) ) => {
328
+ let s = value. as_ref ( ) ;
329
+ if s != "" {
330
+ self
331
+ . resolver
332
+ . borrow_mut ( )
333
+ . jsx_static_class_names
334
+ . insert ( s. into ( ) ) ;
335
+ }
336
+ }
337
+ Expr :: Cond ( CondExpr { cons, alt, .. } ) => {
338
+ self . record_jsx_class_name ( cons. clone ( ) ) ;
339
+ self . record_jsx_class_name ( alt. clone ( ) ) ;
340
+ }
341
+ Expr :: Bin ( BinExpr {
342
+ op, left, right, ..
343
+ } ) => {
344
+ if * op == BinaryOp :: Add {
345
+ self . record_jsx_class_name ( left. clone ( ) ) ;
346
+ self . record_jsx_class_name ( right. clone ( ) ) ;
347
+ }
348
+ }
349
+ Expr :: Tpl ( Tpl { exprs, quasis, .. } ) => {
350
+ for expr in exprs {
351
+ self . record_jsx_class_name ( expr. clone ( ) ) ;
352
+ }
353
+ let mut resolver = self . resolver . borrow_mut ( ) ;
354
+ for quasi in quasis {
355
+ let s = quasi. raw . value . as_ref ( ) ;
356
+ if s != "" {
357
+ resolver. jsx_static_class_names . insert ( s. into ( ) ) ;
358
+ }
359
+ }
360
+ }
361
+ _ => { }
362
+ }
363
+ }
364
+
316
365
fn fold_jsx_opening_element ( & mut self , mut el : JSXOpeningElement ) -> JSXOpeningElement {
317
366
let extra_imports = self . resolver . borrow ( ) . extra_imports . clone ( ) ;
318
367
let mut css_modules = false ;
@@ -324,21 +373,22 @@ impl AlephJsxPass2Fold {
324
373
}
325
374
}
326
375
327
- if css_modules {
328
- let mut i: Option < usize > = None ;
329
- let mut class_name_value_expr: Option < Box < Expr > > = None ;
330
-
331
- for ( index, attr) in el. attrs . iter ( ) . enumerate ( ) {
332
- match & attr {
333
- JSXAttrOrSpread :: JSXAttr ( JSXAttr {
334
- name : JSXAttrName :: Ident ( id) ,
335
- value : Some ( value) ,
336
- ..
337
- } ) => {
338
- if id. sym . eq ( "className" ) {
339
- match value {
340
- JSXAttrValue :: Lit ( lit) => {
341
- class_name_value_expr = Some ( Box :: new ( Expr :: Call ( CallExpr {
376
+ let mut class_name_index: Option < usize > = None ;
377
+ let mut class_name_cx_expr: Option < Box < Expr > > = None ;
378
+
379
+ for ( index, attr) in el. attrs . iter ( ) . enumerate ( ) {
380
+ match & attr {
381
+ JSXAttrOrSpread :: JSXAttr ( JSXAttr {
382
+ name : JSXAttrName :: Ident ( id) ,
383
+ value : Some ( value) ,
384
+ ..
385
+ } ) => {
386
+ if id. sym . eq ( "className" ) {
387
+ match value {
388
+ JSXAttrValue :: Lit ( lit) => {
389
+ self . record_jsx_class_name ( Box :: new ( Expr :: Lit ( lit. clone ( ) ) ) ) ;
390
+ if css_modules {
391
+ class_name_cx_expr = Some ( Box :: new ( Expr :: Call ( CallExpr {
342
392
span : DUMMY_SP ,
343
393
callee : ExprOrSuper :: Expr ( Box :: new ( Expr :: Ident ( quote_ident ! ( "__ALEPH__CX" ) ) ) ) ,
344
394
args : vec ! [ ExprOrSpread {
@@ -348,9 +398,12 @@ impl AlephJsxPass2Fold {
348
398
type_args : None ,
349
399
} ) ) )
350
400
}
351
- JSXAttrValue :: JSXExprContainer ( JSXExprContainer { expr, .. } ) => {
352
- if let JSXExpr :: Expr ( expr) = expr {
353
- class_name_value_expr = Some ( Box :: new ( Expr :: Call ( CallExpr {
401
+ }
402
+ JSXAttrValue :: JSXExprContainer ( JSXExprContainer { expr, .. } ) => {
403
+ if let JSXExpr :: Expr ( expr) = expr {
404
+ self . record_jsx_class_name ( expr. clone ( ) ) ;
405
+ if css_modules {
406
+ class_name_cx_expr = Some ( Box :: new ( Expr :: Call ( CallExpr {
354
407
span : DUMMY_SP ,
355
408
callee : ExprOrSuper :: Expr ( Box :: new ( Expr :: Ident ( quote_ident ! ( "__ALEPH__CX" ) ) ) ) ,
356
409
args : vec ! [ ExprOrSpread {
@@ -361,33 +414,33 @@ impl AlephJsxPass2Fold {
361
414
} ) ) )
362
415
}
363
416
}
364
- _ => { }
365
- } ;
366
- i = Some ( index ) ;
367
- break ;
368
- }
417
+ }
418
+ _ => { }
419
+ } ;
420
+ class_name_index = Some ( index ) ;
421
+ break ;
369
422
}
370
- _ => { }
371
- } ;
372
- }
423
+ }
424
+ _ => { }
425
+ } ;
426
+ }
373
427
374
- if let Some ( index) = i {
375
- if let Some ( expr) = class_name_value_expr {
376
- el. attrs [ index] = JSXAttrOrSpread :: JSXAttr ( JSXAttr {
428
+ if let Some ( index) = class_name_index {
429
+ if let Some ( expr) = class_name_cx_expr {
430
+ el. attrs [ index] = JSXAttrOrSpread :: JSXAttr ( JSXAttr {
431
+ span : DUMMY_SP ,
432
+ name : JSXAttrName :: Ident ( quote_ident ! ( "className" ) ) ,
433
+ value : Some ( JSXAttrValue :: JSXExprContainer ( JSXExprContainer {
377
434
span : DUMMY_SP ,
378
- name : JSXAttrName :: Ident ( quote_ident ! ( "className" ) ) ,
379
- value : Some ( JSXAttrValue :: JSXExprContainer ( JSXExprContainer {
380
- span : DUMMY_SP ,
381
- expr : JSXExpr :: Expr ( expr) ,
382
- } ) ) ,
383
- } ) ;
384
- }
435
+ expr : JSXExpr :: Expr ( expr) ,
436
+ } ) ) ,
437
+ } ) ;
385
438
}
386
439
}
387
440
388
441
// copy from https://github.com/swc-project/swc/blob/master/ecmascript/transforms/src/react/jsx_src.rs
389
442
if self . is_dev {
390
- let resolver = self . resolver . borrow_mut ( ) ;
443
+ let resolver = self . resolver . borrow ( ) ;
391
444
match self . source . span_to_lines ( el. span ) {
392
445
Ok ( file_lines) => {
393
446
el. attrs . push ( JSXAttrOrSpread :: JSXAttr ( JSXAttr {
@@ -430,7 +483,7 @@ impl AlephJsxPass2Fold {
430
483
}
431
484
}
432
485
433
- impl Fold for AlephJsxPass2Fold {
486
+ impl Fold for JSXMagicPass2Fold {
434
487
noop_fold_type ! ( ) ;
435
488
436
489
fn fold_jsx_element ( & mut self , el : JSXElement ) -> JSXElement {
@@ -482,6 +535,7 @@ mod tests {
482
535
}
483
536
"# ;
484
537
let ( code, resolver) = st ( "/pages/index.tsx" , source, false ) ;
538
+ let r = resolver. borrow_mut ( ) ;
485
539
assert ! ( code. contains(
486
540
"import __ALEPH__Anchor from \" ../-/deno.land/x/[email protected] /framework/react/components/Anchor.js\" "
487
541
) ) ;
@@ -502,12 +556,11 @@ mod tests {
502
556
assert ! ( code. contains( "href: \" /style/index.css\" " ) ) ;
503
557
assert ! ( code. contains(
504
558
format!(
505
- "import \" ../style/index.css.js#{}@000000\" " ,
559
+ "import \" ../style/index.css.js#{}@000000\" " ,
506
560
"/style/index.css"
507
561
)
508
562
. as_str( )
509
563
) ) ;
510
- let r = resolver. borrow_mut ( ) ;
511
564
assert_eq ! (
512
565
r. deps
513
566
. iter( )
@@ -535,12 +588,14 @@ mod tests {
535
588
<link rel="stylesheet" href="../style/app.module.css" />
536
589
<link rel="stylesheet" href="../style/index.module.css" />
537
590
<h2 className="$title $bold">Hi :)</h2>
538
- <p className={'$' + 'desc'}>Welcom</p>
591
+ <p className={'$' + 'desc'}>Welcome</p>
592
+ <p className={`bold ${'lg'}`}>Thanks</p>
539
593
</>
540
594
)
541
595
}
542
596
"# ;
543
597
let ( code, resolver) = st ( "/pages/index.tsx" , source, false ) ;
598
+ let r = resolver. borrow_mut ( ) ;
544
599
assert ! ( code. contains(
545
600
"import __ALEPH__StyleLink from \" ../-/deno.land/x/[email protected] /framework/react/components/StyleLink.js\" "
546
601
) ) ;
@@ -563,7 +618,8 @@ mod tests {
563
618
assert ! ( code. contains( "const __ALEPH__CX = (c)=>typeof c === \" string\" ? c.split(\" \" ).map((n)=>n.charAt(0) === \" $\" ? __ALEPH__CSS_MODULES_ALL[n.slice(1)] || n : n\n ).join(\" \" ) : c" ) ) ;
564
619
assert ! ( code. contains( "className: __ALEPH__CX(\" $title $bold\" )" ) ) ;
565
620
assert ! ( code. contains( "className: __ALEPH__CX('$' + 'desc')" ) ) ;
566
- let r = resolver. borrow_mut ( ) ;
621
+ assert ! ( code. contains( "className: __ALEPH__CX(`bold ${'lg'}`)" ) ) ;
622
+ assert_eq ! ( r. jsx_static_class_names. len( ) , 5 ) ;
567
623
assert_eq ! (
568
624
r. deps
569
625
. iter( )
@@ -601,12 +657,12 @@ mod tests {
601
657
}
602
658
"# ;
603
659
let ( code, resolver) = st ( "/pages/index.tsx" , source, false ) ;
660
+ let r = resolver. borrow_mut ( ) ;
604
661
assert ! ( code. contains(
605
662
"import __ALEPH__InlineStyle from \" ../-/deno.land/x/[email protected] /framework/react/components/InlineStyle.js\" "
606
663
) ) ;
607
664
assert ! ( code. contains( "React.createElement(__ALEPH__InlineStyle," ) ) ;
608
665
assert ! ( code. contains( "__styleId: \" inline-style-" ) ) ;
609
- let r = resolver. borrow_mut ( ) ;
610
666
assert ! ( r. inline_styles. len( ) == 2 ) ;
611
667
}
612
668
}
0 commit comments