Browse Source

make creating rsx nodes from macros possible

Evan Almloff 2 năm trước cách đây
mục cha
commit
8f67d0aafd

+ 0 - 1
packages/autofmt/src/element.rs

@@ -48,7 +48,6 @@ impl Writer<'_> {
             key,
             attributes,
             children,
-            _is_static,
             brace,
         } = el;
 

+ 2 - 2
packages/router-macro/src/lib.rs

@@ -126,9 +126,9 @@ pub fn routable(input: TokenStream) -> TokenStream {
         }
 
         #error_type
-        
+
         #display_impl
-        
+
         #routable_impl
 
         #parse_impl

+ 0 - 1
packages/rsx-rosetta/src/lib.rs

@@ -71,7 +71,6 @@ pub fn rsx_node_from_html(node: &Node) -> Option<BodyNode> {
                 name: el_name,
                 children,
                 attributes,
-                _is_static: false,
                 key: None,
                 brace: Default::default(),
             }))

+ 1 - 0
packages/rsx/src/component.rs

@@ -164,6 +164,7 @@ impl ToTokens for Component {
                 if !self.children.is_empty() {
                     let renderer: TemplateRenderer = TemplateRenderer {
                         roots: &self.children,
+                        location: None,
                     };
 
                     toks.append_all(quote! {

+ 0 - 2
packages/rsx/src/element.rs

@@ -20,7 +20,6 @@ pub struct Element {
     pub key: Option<IfmtInput>,
     pub attributes: Vec<ElementAttrNamed>,
     pub children: Vec<BodyNode>,
-    pub _is_static: bool,
     pub brace: syn::token::Brace,
 }
 
@@ -158,7 +157,6 @@ impl Parse for Element {
             attributes,
             children,
             brace,
-            _is_static: false,
         })
     }
 }

+ 7 - 0
packages/rsx/src/ifmt.rs

@@ -20,6 +20,13 @@ pub struct IfmtInput {
 }
 
 impl IfmtInput {
+    pub fn new_static(input: &str) -> Self {
+        Self {
+            source: None,
+            segments: vec![Segment::Literal(input.to_string())],
+        }
+    }
+
     pub fn is_static(&self) -> bool {
         matches!(self.segments.as_slice(), &[Segment::Literal(_)] | &[])
     }

+ 40 - 11
packages/rsx/src/lib.rs

@@ -59,9 +59,26 @@ impl CallBody {
         template: Option<CallBody>,
         location: &'static str,
     ) -> Option<Template<'static>> {
-        let mut renderer: TemplateRenderer = TemplateRenderer { roots: &self.roots };
+        let mut renderer: TemplateRenderer = TemplateRenderer {
+            roots: &self.roots,
+            location: None,
+        };
         renderer.update_template::<Ctx>(template, location)
     }
+
+    /// Render the template with a manually set file location. This should be used when multiple rsx! calls are used in the same macro
+    pub fn render_with_location(&self, location: String) -> TokenStream2 {
+        let body = TemplateRenderer {
+            roots: &self.roots,
+            location: Some(location),
+        };
+
+        quote! {
+            ::dioxus::core::LazyNodes::new( move | __cx: &::dioxus::core::ScopeState| -> ::dioxus::core::VNode {
+                #body
+            })
+        }
+    }
 }
 
 impl Parse for CallBody {
@@ -85,7 +102,10 @@ impl Parse for CallBody {
 /// Serialize the same way, regardless of flavor
 impl ToTokens for CallBody {
     fn to_tokens(&self, out_tokens: &mut TokenStream2) {
-        let body = TemplateRenderer { roots: &self.roots };
+        let body = TemplateRenderer {
+            roots: &self.roots,
+            location: None,
+        };
 
         out_tokens.append_all(quote! {
             ::dioxus::core::LazyNodes::new( move | __cx: &::dioxus::core::ScopeState| -> ::dioxus::core::VNode {
@@ -102,6 +122,7 @@ impl ToTokens for RenderCallBody {
     fn to_tokens(&self, out_tokens: &mut TokenStream2) {
         let body: TemplateRenderer = TemplateRenderer {
             roots: &self.0.roots,
+            location: None,
         };
 
         out_tokens.append_all(quote! {
@@ -115,6 +136,7 @@ impl ToTokens for RenderCallBody {
 
 pub struct TemplateRenderer<'a> {
     pub roots: &'a [BodyNode],
+    pub location: Option<String>,
 }
 
 impl<'a> TemplateRenderer<'a> {
@@ -185,6 +207,21 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
             out
         });
 
+        let name = match self.location {
+            Some(ref loc) => quote! { #loc },
+            None => quote! {
+                concat!(
+                    file!(),
+                    ":",
+                    line!(),
+                    ":",
+                    column!(),
+                    ":",
+                    #root_col
+                )
+            },
+        };
+
         // Render and release the mutable borrow on context
         let roots = quote! { #( #root_printer ),* };
         let node_printer = &context.dynamic_nodes;
@@ -194,15 +231,7 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
 
         out_tokens.append_all(quote! {
             static TEMPLATE: ::dioxus::core::Template = ::dioxus::core::Template {
-                name: concat!(
-                    file!(),
-                    ":",
-                    line!(),
-                    ":",
-                    column!(),
-                    ":",
-                    #root_col
-                ),
+                name: #name,
                 roots: &[ #roots ],
                 node_paths: &[ #(#node_paths),* ],
                 attr_paths: &[ #(#attr_paths),* ],

+ 4 - 1
packages/rsx/src/node.rs

@@ -132,7 +132,10 @@ impl ToTokens for BodyNode {
                     pat, expr, body, ..
                 } = exp;
 
-                let renderer: TemplateRenderer = TemplateRenderer { roots: body };
+                let renderer: TemplateRenderer = TemplateRenderer {
+                    roots: body,
+                    location: None,
+                };
 
                 tokens.append_all(quote! {
                      __cx.make_node(