@@ -86,12 +86,20 @@ pub enum JSXStyle {
86
86
External ( ExternalStyle ) ,
87
87
}
88
88
89
+ enum StyleExpr < ' a > {
90
+ Str ( & ' a Str ) ,
91
+ Tpl ( & ' a Tpl , & ' a Expr ) ,
92
+ Ident ( & ' a Ident ) ,
93
+ }
94
+
89
95
impl Fold for StyledJSXTransformer {
90
96
fn fold_jsx_element ( & mut self , el : JSXElement ) -> JSXElement {
91
97
if is_styled_jsx ( & el) {
92
98
let parent_has_styled_jsx = self . has_styled_jsx ;
93
99
if !parent_has_styled_jsx {
94
- self . check_for_jsx_styles ( Some ( & el) , & el. children ) ;
100
+ if self . check_for_jsx_styles ( Some ( & el) , & el. children ) . is_err ( ) {
101
+ return el;
102
+ }
95
103
}
96
104
let el = match self . replace_jsx_style ( & el) {
97
105
Ok ( el) => el,
@@ -107,7 +115,9 @@ impl Fold for StyledJSXTransformer {
107
115
return el. fold_children_with ( self ) ;
108
116
}
109
117
110
- self . check_for_jsx_styles ( None , & el. children ) ;
118
+ if self . check_for_jsx_styles ( None , & el. children ) . is_err ( ) {
119
+ return el;
120
+ }
111
121
let el = el. fold_children_with ( self ) ;
112
122
self . reset_styles_state ( ) ;
113
123
@@ -119,7 +129,9 @@ impl Fold for StyledJSXTransformer {
119
129
return fragment. fold_children_with ( self ) ;
120
130
}
121
131
122
- self . check_for_jsx_styles ( None , & fragment. children ) ;
132
+ if self . check_for_jsx_styles ( None , & fragment. children ) . is_err ( ) {
133
+ return fragment;
134
+ } ;
123
135
let fragment = fragment. fold_children_with ( self ) ;
124
136
self . reset_styles_state ( ) ;
125
137
@@ -383,23 +395,29 @@ impl Fold for StyledJSXTransformer {
383
395
}
384
396
385
397
impl StyledJSXTransformer {
386
- fn check_for_jsx_styles ( & mut self , el : Option < & JSXElement > , children : & Vec < JSXElementChild > ) {
398
+ fn check_for_jsx_styles (
399
+ & mut self ,
400
+ el : Option < & JSXElement > ,
401
+ children : & [ JSXElementChild ] ,
402
+ ) -> Result < ( ) , Error > {
387
403
let mut styles = vec ! [ ] ;
388
404
let mut process_style = |el : & JSXElement | {
389
405
self . file_has_styled_jsx = true ;
390
406
self . has_styled_jsx = true ;
391
- let expr = get_style_expr ( el) ;
407
+ let expr = get_style_expr ( el) ? ;
392
408
let style_info = self . get_jsx_style ( expr, is_global ( el) ) ;
393
409
styles. insert ( 0 , style_info) ;
410
+
411
+ Ok ( ( ) )
394
412
} ;
395
413
396
414
if el. is_some ( ) && is_styled_jsx ( el. unwrap ( ) ) {
397
- process_style ( el. unwrap ( ) ) ;
415
+ process_style ( el. unwrap ( ) ) ? ;
398
416
} else {
399
417
for i in 0 ..children. len ( ) {
400
418
if let JSXElementChild :: JSXElement ( child_el) = & children[ i] {
401
419
if is_styled_jsx ( & child_el) {
402
- process_style ( & child_el) ;
420
+ process_style ( & child_el) ? ;
403
421
}
404
422
}
405
423
}
@@ -412,26 +430,31 @@ impl StyledJSXTransformer {
412
430
self . static_class_name = static_class_name;
413
431
self . class_name = class_name;
414
432
}
433
+
434
+ Ok ( ( ) )
415
435
}
416
436
417
- fn get_jsx_style ( & mut self , expr : & Expr , is_global_jsx_element : bool ) -> JSXStyle {
437
+ fn get_jsx_style ( & mut self , style_expr : StyleExpr , is_global_jsx_element : bool ) -> JSXStyle {
418
438
let mut hasher = DefaultHasher :: new ( ) ;
419
439
let css: String ;
420
440
let css_span: Span ;
421
441
let is_dynamic;
422
442
let mut expressions = vec ! [ ] ;
423
- match expr {
424
- Expr :: Lit ( Lit :: Str ( Str { value, span, .. } ) ) => {
443
+ match style_expr {
444
+ StyleExpr :: Str ( Str { value, span, .. } ) => {
425
445
hasher. write ( value. as_ref ( ) . as_bytes ( ) ) ;
426
446
css = value. to_string ( ) . clone ( ) ;
427
447
css_span = span. clone ( ) ;
428
448
is_dynamic = false ;
429
449
}
430
- Expr :: Tpl ( Tpl {
431
- exprs,
432
- quasis,
433
- span,
434
- } ) => {
450
+ StyleExpr :: Tpl (
451
+ Tpl {
452
+ exprs,
453
+ quasis,
454
+ span,
455
+ } ,
456
+ expr,
457
+ ) => {
435
458
if exprs. is_empty ( ) {
436
459
hasher. write ( quasis[ 0 ] . raw . value . as_bytes ( ) ) ;
437
460
css = quasis[ 0 ] . raw . value . to_string ( ) ;
@@ -463,7 +486,7 @@ impl StyledJSXTransformer {
463
486
expressions = exprs. clone ( ) ;
464
487
}
465
488
}
466
- Expr :: Ident ( ident) => {
489
+ StyleExpr :: Ident ( ident) => {
467
490
return JSXStyle :: External ( ExternalStyle {
468
491
expr : Expr :: Member ( MemberExpr {
469
492
obj : ExprOrSuper :: Expr ( Box :: new ( Expr :: Ident ( ident. clone ( ) ) ) ) ,
@@ -479,7 +502,6 @@ impl StyledJSXTransformer {
479
502
is_global : is_global_jsx_element,
480
503
} ) ;
481
504
}
482
- _ => panic ! ( "Not implemented" ) , // TODO: handle bad style input
483
505
}
484
506
485
507
return JSXStyle :: Local ( LocalStyle {
@@ -539,7 +561,11 @@ impl StyledJSXTransformer {
539
561
// references to this.something (e.g. props or state).
540
562
// We allow dynamic styles only when resolving styles.
541
563
}
542
- let style = self . get_jsx_style ( & Expr :: Tpl ( tagged_tpl. tpl . clone ( ) ) , false ) ;
564
+
565
+ let style = self . get_jsx_style (
566
+ StyleExpr :: Tpl ( & tagged_tpl. tpl , & Expr :: Tpl ( tagged_tpl. tpl . clone ( ) ) ) ,
567
+ false ,
568
+ ) ;
543
569
let styles = vec ! [ style] ;
544
570
let ( static_class_name, class_name) =
545
571
compute_class_names ( & styles, & self . style_import_name . as_ref ( ) . unwrap ( ) ) ;
@@ -657,7 +683,7 @@ fn is_global(el: &JSXElement) -> bool {
657
683
} )
658
684
}
659
685
660
- fn get_style_expr ( el : & JSXElement ) -> & Expr {
686
+ fn get_style_expr ( el : & JSXElement ) -> Result < StyleExpr , Error > {
661
687
let non_whitespace_children: & Vec < & JSXElementChild > = & el
662
688
. children
663
689
. iter ( )
@@ -677,34 +703,47 @@ fn get_style_expr(el: &JSXElement) -> &Expr {
677
703
. struct_span_err (
678
704
el. span ,
679
705
& format ! (
680
- "Expected one child under JSX style tag, but got {} (eg: <style \
681
- jsx>{{`hi`}}</style>)",
706
+ "Expected one child under JSX style tag, but got {}.\n Read more: https://nextjs.org/docs/messages/invalid-styled-jsx-children" ,
682
707
non_whitespace_children. len( )
683
708
) ,
684
709
)
685
710
. emit ( )
686
711
} ) ;
687
- panic ! ( "styled-jsx style error" ) ;
712
+ bail ! ( "styled-jsx style error" ) ;
688
713
}
689
714
690
715
if let JSXElementChild :: JSXExprContainer ( JSXExprContainer {
691
716
expr : JSXExpr :: Expr ( expr) ,
692
717
..
693
718
} ) = non_whitespace_children[ 0 ]
694
719
{
695
- return & * * expr;
720
+ return Ok ( match & * * expr {
721
+ Expr :: Lit ( Lit :: Str ( str) ) => StyleExpr :: Str ( str) ,
722
+ Expr :: Tpl ( tpl) => StyleExpr :: Tpl ( tpl, & * * expr) ,
723
+ Expr :: Ident ( ident) => StyleExpr :: Ident ( ident) ,
724
+ _ => {
725
+ HANDLER . with ( |handler| {
726
+ handler
727
+ . struct_span_err (
728
+ el. span ,
729
+ "Expected a template literal, string or identifier inside the JSXExpressionContainer.\n Read more: https://nextjs.org/docs/messages/invalid-styled-jsx-children" ,
730
+ )
731
+ . emit ( )
732
+ } ) ;
733
+ bail ! ( "wrong jsx expression container type" ) ;
734
+ }
735
+ } ) ;
696
736
}
697
737
698
738
HANDLER . with ( |handler| {
699
739
handler
700
740
. struct_span_err (
701
741
el. span ,
702
- "Expected a single child of type JSXExpressionContainer under JSX Style tag (eg: \
703
- <style jsx>{{`hi`}}</style>)",
742
+ "Expected a single child of type JSXExpressionContainer under JSX Style tag.\n Read more: https://nextjs.org/docs/messages/invalid-styled-jsx-children" ,
704
743
)
705
744
. emit ( )
706
745
} ) ;
707
- panic ! ( "next-swc compilation error" ) ;
746
+ bail ! ( "next-swc compilation error" ) ;
708
747
}
709
748
710
749
fn get_existing_class_name ( el : & JSXOpeningElement ) -> ( Option < Expr > , Option < usize > , Option < usize > ) {
0 commit comments