summary refs log tree commit diff
path: root/modules/morgana_proc/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'modules/morgana_proc/src/lib.rs')
-rw-r--r--modules/morgana_proc/src/lib.rs62
1 files changed, 47 insertions, 15 deletions
diff --git a/modules/morgana_proc/src/lib.rs b/modules/morgana_proc/src/lib.rs
index 8061b1b..7730f6b 100644
--- a/modules/morgana_proc/src/lib.rs
+++ b/modules/morgana_proc/src/lib.rs
@@ -4,7 +4,9 @@ use unsynn::*;
 use quote::quote;
 
 unsynn! {
-    struct MorxBlock(Vec<Either<MorxNode, MorxChild, Literal>>);
+    keyword MorxDocKey = "doctype";
+    struct MorxBlock(Vec<Either<MorxDoctype, MorxNode, MorxChild, Literal>>);
+    struct MorxDoctype(Cons<PunctAny<'!'>, MorxDocKey, Vec<Either<Ident, LiteralString>>, NodeSeparator>);
     struct MorxNode(Cons<Ident, Either<
         NodeSeparator,
         MorxChildren,
@@ -27,7 +29,7 @@ pub fn morx(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
 
     let child_vec_expr = generate_block(&ast);
     quote! {
-        RenderNode::Fragment {
+        ::morgana::RenderNode::Fragment {
             children: #child_vec_expr
         }
     }.into()
@@ -36,10 +38,10 @@ pub fn morx(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
 fn generate_block(ast: &MorxBlock) -> unsynn::TokenStream {
     let children: Vec<unsynn::TokenStream> = ast.0.iter().map(|child| {
         match child {
-            Either::First(node) => generate_node(node),
-            Either::Second(child_expression) => generate_expr_node(&child_expression.0.second),
-            Either::Third(literal) => generate_literal(literal),
-            _ => unreachable!("Invalid morx block AST"),
+            Either::First(doctype) => generate_doctype(doctype),
+            Either::Second(node) => generate_node(node),
+            Either::Third(child_expression) => generate_expr_node(&child_expression.0.second),
+            Either::Fourth(literal) => generate_literal(literal),
         }
     }).collect();
 
@@ -50,6 +52,28 @@ fn generate_block(ast: &MorxBlock) -> unsynn::TokenStream {
     }.into()
 }
 
+fn generate_doctype(ast: &MorxDoctype) -> unsynn::TokenStream {
+    let elem_expressions: Vec<unsynn::TokenStream> = ast.0.third.iter().map(|elem| {
+        match elem {
+            Either::First(ident) => {
+                let ident_string = Literal::string(&ident.to_string()).into_token_stream();
+                quote! {::morgana::DoctypeElem::Word( #ident_string )}
+            },
+            Either::Second(literal) => {
+                let literal = literal.clone().into_token_stream();
+                quote! {::morgana::DoctypeElem::String( #literal )}
+            },
+            _ => unreachable!("Invalid doctype AST"),
+        }
+    }).collect();
+    
+    quote! {
+        ::morgana::RenderNode::Doctype(vec![
+            #(#elem_expressions),*
+        ])
+    }
+}
+
 fn generate_node(ast: &MorxNode) -> unsynn::TokenStream {
     let elem_name = &ast.0.first;
     let attrs_or_props = match &ast.0.second {
@@ -72,7 +96,10 @@ fn generate_node(ast: &MorxNode) -> unsynn::TokenStream {
         let value = match &attr.1 {
             Some(Either::First(literal)) => quote!{ format!("{}", #literal) },
             Some(Either::Second(ident)) => quote!{ format!("{}", #ident) },
-            Some(Either::Third(bracegroup)) => bracegroup.0.stream(),
+            Some(Either::Third(bracegroup)) => {
+                let inner = bracegroup.0.stream();
+                quote!{ {#inner}.into() }
+            },
             Some(Either::Fourth(_invalid)) => unreachable!("Invalid element attribute type"),
             None => quote!{ String::new() },
         };
@@ -83,9 +110,12 @@ fn generate_node(ast: &MorxNode) -> unsynn::TokenStream {
     let elem_props = attrs_or_props.iter().map(|attr| {
         let name = &attr.0;
         let value = match &attr.1 {
-            Some(Either::First(literal)) => quote!{ format!("{}", #literal) },
-            Some(Either::Second(ident)) => quote!{ #ident },
-            Some(Either::Third(bracegroup)) => bracegroup.0.stream(),
+            Some(Either::First(literal)) => quote!{ {String::from(#literal).into()} },
+            Some(Either::Second(ident)) => quote!{ {String::from(#ident).into()} },
+            Some(Either::Third(bracegroup)) => {
+                let inner = bracegroup.0.stream();
+                quote!{ {#inner}.into() }
+            },
             Some(Either::Fourth(_invalid)) => unreachable!("Invalid element attribute type"),
             None => quote!{ true },
         };
@@ -107,17 +137,17 @@ fn generate_node(ast: &MorxNode) -> unsynn::TokenStream {
 
     if is_component_node {
         quote! {
-            RenderNode::Component(
+            ::morgana::RenderNode::Component(
                 Box::new({ #elem_name {
+                    children: #children,
                     #(#elem_props),*
-                    children: #children
                 } })
             )
         }.into()
     } else {
         let elem_name = Literal::string(&elem_name.to_string()).into_token_stream();
         quote! {
-            RenderNode::Element {
+            ::morgana::RenderNode::Element {
                 name: #elem_name.to_string(),
                 children: #children,
                 attributes: std::collections::HashMap::from([#(#elem_attrs),*])
@@ -133,7 +163,9 @@ fn generate_expr_node(ast: &Either<Literal, BraceGroup, EndOfStream>) -> unsynn:
         Either::Second(brace_expr) => {
             let children = brace_expr.0.stream();
             quote! {
-                RenderNode::Fragment { children: #children }
+                ::morgana::RenderNode::Fragment {
+                    children: ::morgana::IntoRender::into_render(#children)
+                }
             }
         },
         _ => unreachable!("Invalid expr node"),
@@ -142,6 +174,6 @@ fn generate_expr_node(ast: &Either<Literal, BraceGroup, EndOfStream>) -> unsynn:
 
 fn generate_literal(ast: &Literal) -> unsynn::TokenStream {
     quote! {
-        RenderNode::TextNode { content: format!("{}", #ast) }
+        ::morgana::RenderNode::TextNode { content: format!("{}", #ast) }
     }
 }