1+ use super :: styled_jsx:: StyledJsx ;
12use rustc_hash:: FxHashMap ;
23
34use crate :: {
@@ -44,6 +45,7 @@ const STYLED_FACTORY: &str =
4445/// only the runtime gives the component
4546struct Base < ' a > {
4647 name : String ,
48+ target : Option < Expression < ' a > > ,
4749 styles : Option < Vec < ExtractStyleValue > > ,
4850 bound : Option < Expression < ' a > > ,
4951}
@@ -52,6 +54,7 @@ impl<'a> Base<'a> {
5254 const fn named ( name : String ) -> Self {
5355 Self {
5456 name,
57+ target : None ,
5558 styles : None ,
5659 bound : None ,
5760 }
@@ -113,10 +116,14 @@ fn tag_from_argument<'a>(
113116 }
114117 Some ( jsx_name ( argument) . map_or_else (
115118 || Base {
119+ target : Some ( Expression :: new_identifier ( SPAN , STYLED_BASE , ast_builder) ) ,
116120 bound : Some ( argument. clone_in ( ast_builder. allocator ( ) ) ) ,
117121 ..Base :: named ( STYLED_BASE . to_string ( ) )
118122 } ,
119- Base :: named,
123+ |name| Base {
124+ target : Some ( argument. clone_in ( ast_builder. allocator ( ) ) ) ,
125+ ..Base :: named ( name)
126+ } ,
120127 ) )
121128}
122129
@@ -185,6 +192,7 @@ pub fn extract_style_from_styled<'a>(
185192 split_filename : Option < & str > ,
186193 imports : & FxHashMap < String , ExportVariableKind > ,
187194 attrs : & [ Expression < ' a > ] ,
195+ helper : & mut Option < StyledJsx > ,
188196) -> ( ExtractResult < ' a > , Expression < ' a > , Vec < ( u32 , String ) > ) {
189197 let original_scope = expression. clone_in ( ast_builder. allocator ( ) ) ;
190198 let mut composed_classes = Vec :: new ( ) ;
@@ -286,12 +294,13 @@ pub fn extract_style_from_styled<'a>(
286294 ) ) ;
287295 let component = create_styled_component (
288296 ast_builder,
289- & base. name ,
297+ & base,
290298 StyledRender {
291299 class_name : & class_name,
292300 style_vars : & gen_styles ( ast_builder, & props_styles, None ) ,
293301 bindings : Vec :: new ( ) ,
294302 } ,
303+ helper,
295304 ) ;
296305 let styled_component = base. render ( ast_builder, apply_attrs ( ast_builder, component, attrs) ) ;
297306
@@ -363,12 +372,13 @@ pub fn extract_style_from_styled<'a>(
363372 ) ;
364373 let component = create_styled_component (
365374 ast_builder,
366- & base. name ,
375+ & base,
367376 StyledRender {
368377 class_name : & class_name,
369378 style_vars : & gen_styles ( ast_builder, & styles, None ) ,
370379 bindings,
371380 } ,
381+ helper,
372382 ) ;
373383 let styled_component = base. render ( ast_builder, apply_attrs ( ast_builder, component, attrs) ) ;
374384
@@ -575,8 +585,9 @@ struct StyledRender<'b, 'a> {
575585
576586fn create_styled_component < ' a > (
577587 ast_builder : & AstBuilder < ' a > ,
578- tag_name : & str ,
588+ base : & Base < ' a > ,
579589 render : StyledRender < ' _ , ' a > ,
590+ helper : & mut Option < StyledJsx > ,
580591) -> Expression < ' a > {
581592 let StyledRender {
582593 class_name,
@@ -637,92 +648,93 @@ fn create_styled_component<'a>(
637648 None :: < oxc_allocator:: Box < oxc_ast:: ast:: FormalParameterRest < ' a > > > ,
638649 ast_builder,
639650 ) ;
640- let body = Expression :: new_jsx_element (
641- SPAN ,
642- JSXOpeningElement :: boxed (
651+ let class_name = class_name. as_ref ( ) . map_or_else (
652+ || Expression :: new_identifier ( SPAN , "className" , ast_builder) ,
653+ |name| {
654+ wrap_array_filter (
655+ ast_builder,
656+ & [
657+ name. clone_in ( ast_builder. allocator ( ) ) ,
658+ Expression :: new_identifier ( SPAN , "className" , ast_builder) ,
659+ ] ,
660+ )
661+ . unwrap_or_else ( || name. clone_in ( ast_builder. allocator ( ) ) )
662+ } ,
663+ ) ;
664+ let style = style_vars. as_ref ( ) . map_or_else (
665+ || Expression :: new_identifier ( SPAN , "style" , ast_builder) ,
666+ |style_vars| {
667+ merge_object_expressions (
668+ ast_builder,
669+ & [
670+ style_vars. clone_in ( ast_builder. allocator ( ) ) ,
671+ Expression :: new_identifier ( SPAN , "style" , ast_builder) ,
672+ ] ,
673+ )
674+ . unwrap_or_else ( || style_vars. clone_in ( ast_builder. allocator ( ) ) )
675+ } ,
676+ ) ;
677+ let body = if let Some ( helper) = helper {
678+ let target = base. target . as_ref ( ) . map_or_else (
679+ || {
680+ Expression :: new_string_literal (
681+ SPAN ,
682+ Str :: from_in ( & base. name , ast_builder. allocator ( ) ) ,
683+ None ,
684+ ast_builder,
685+ )
686+ } ,
687+ |target| target. clone_in ( ast_builder. allocator ( ) ) ,
688+ ) ;
689+ helper. render ( ast_builder, target, ( class_name, style) )
690+ } else {
691+ Expression :: new_jsx_element (
643692 SPAN ,
644- JSXElementName :: new_identifier (
693+ JSXOpeningElement :: boxed (
645694 SPAN ,
646- Str :: from_in ( tag_name, ast_builder. allocator ( ) ) ,
647- ast_builder,
648- ) ,
649- None :: < oxc_allocator:: Box < oxc_ast:: ast:: TSTypeParameterInstantiation < ' a > > > ,
650- oxc_allocator:: Vec :: from_iter_in (
651- vec ! [
652- JSXAttributeItem :: new_spread_attribute(
653- SPAN ,
654- Expression :: new_identifier( SPAN , "rest" , ast_builder) ,
655- ast_builder,
656- ) ,
657- JSXAttributeItem :: new_attribute(
658- SPAN ,
659- JSXAttributeName :: new_identifier( SPAN , "className" , ast_builder) ,
660- Some ( JSXAttributeValue :: new_expression_container(
695+ JSXElementName :: new_identifier (
696+ SPAN ,
697+ Str :: from_in ( & base. name , ast_builder. allocator ( ) ) ,
698+ ast_builder,
699+ ) ,
700+ None :: < oxc_allocator:: Box < oxc_ast:: ast:: TSTypeParameterInstantiation < ' a > > > ,
701+ oxc_allocator:: Vec :: from_iter_in (
702+ vec ! [
703+ JSXAttributeItem :: new_spread_attribute(
661704 SPAN ,
662- class_name
663- . as_ref( )
664- . map_or_else(
665- || Expression :: new_identifier( SPAN , "className" , ast_builder) ,
666- |name| {
667- wrap_array_filter(
668- ast_builder,
669- & [
670- name. clone_in( ast_builder. allocator( ) ) ,
671- Expression :: new_identifier(
672- SPAN ,
673- "className" ,
674- ast_builder,
675- ) ,
676- ] ,
677- )
678- . unwrap_or_else( || name. clone_in( ast_builder. allocator( ) ) )
679- } ,
680- )
681- . into( ) ,
705+ Expression :: new_identifier( SPAN , "rest" , ast_builder) ,
682706 ast_builder,
683- ) ) ,
684- ast_builder,
685- ) ,
686- JSXAttributeItem :: new_attribute(
687- SPAN ,
688- JSXAttributeName :: new_identifier( SPAN , "style" , ast_builder) ,
689- Some ( JSXAttributeValue :: new_expression_container(
707+ ) ,
708+ JSXAttributeItem :: new_attribute(
690709 SPAN ,
691- style_vars
692- . as_ref( )
693- . map_or_else(
694- || Expression :: new_identifier( SPAN , "style" , ast_builder) ,
695- |style_vars| {
696- merge_object_expressions(
697- ast_builder,
698- & [
699- style_vars. clone_in( ast_builder. allocator( ) ) ,
700- Expression :: new_identifier(
701- SPAN ,
702- "style" ,
703- ast_builder,
704- ) ,
705- ] ,
706- )
707- . unwrap_or_else(
708- || style_vars. clone_in( ast_builder. allocator( ) ) ,
709- )
710- } ,
711- )
712- . into( ) ,
710+ JSXAttributeName :: new_identifier( SPAN , "className" , ast_builder) ,
711+ Some ( JSXAttributeValue :: new_expression_container(
712+ SPAN ,
713+ class_name. into( ) ,
714+ ast_builder,
715+ ) ) ,
713716 ast_builder,
714- ) ) ,
715- ast_builder,
716- ) ,
717- ] ,
717+ ) ,
718+ JSXAttributeItem :: new_attribute(
719+ SPAN ,
720+ JSXAttributeName :: new_identifier( SPAN , "style" , ast_builder) ,
721+ Some ( JSXAttributeValue :: new_expression_container(
722+ SPAN ,
723+ style. into( ) ,
724+ ast_builder,
725+ ) ) ,
726+ ast_builder,
727+ ) ,
728+ ] ,
729+ ast_builder,
730+ ) ,
718731 ast_builder,
719732 ) ,
733+ oxc_allocator:: Vec :: new_in ( ast_builder) ,
734+ None :: < oxc_allocator:: Box < oxc_ast:: ast:: JSXClosingElement < ' a > > > ,
720735 ast_builder,
721- ) ,
722- oxc_allocator:: Vec :: new_in ( ast_builder) ,
723- None :: < oxc_allocator:: Box < oxc_ast:: ast:: JSXClosingElement < ' a > > > ,
724- ast_builder,
725- ) ;
736+ )
737+ } ;
726738 Expression :: new_arrow_function_expression (
727739 SPAN ,
728740 false ,
0 commit comments