use crate::util::is_valid_tag; use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{ parse::{Parse, ParseStream}, Error, Ident, Result, Token, }; use super::*; pub struct RsxBody { custom_context: Option, roots: Vec>, } /// The custom rusty variant of parsing rsx! impl Parse for RsxBody { fn parse(input: ParseStream) -> Result { let custom_context = try_parse_custom_context(input)?; let (_, roots, _) = BodyParseConfig::::new_as_body().parse_component_body(&input)?; Ok(Self { custom_context, roots, }) } } /// The HTML variant of parsing rsx! impl Parse for RsxBody { fn parse(input: ParseStream) -> Result { let custom_context = try_parse_custom_context(input)?; let (_, roots, _) = BodyParseConfig::::new_as_body().parse_component_body(&input)?; Ok(Self { custom_context, roots, }) } } fn try_parse_custom_context(input: ParseStream) -> Result> { let res = if input.peek(Token![in]) && input.peek2(Ident) && input.peek3(Token![,]) { let _ = input.parse::()?; let name = input.parse::()?; input.parse::()?; Some(name) } else { None }; Ok(res) } /// Serialize the same way, regardless of flavor impl ToTokens for RsxBody { fn to_tokens(&self, out_tokens: &mut TokenStream2) { let inner = if self.roots.len() == 1 { let inner = &self.roots[0]; quote! {#inner} } else { let childs = &self.roots; quote! { __cx.fragment_from_iter([ #(#childs),* ]) } }; match &self.custom_context { // The `in cx` pattern allows directly rendering Some(ident) => out_tokens.append_all(quote! { #ident.render(dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{ use dioxus_elements::{GlobalAttributes, SvgAttributes}; #inner })) }), // Otherwise we just build the LazyNode wrapper None => out_tokens.append_all(quote! { dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{ use dioxus_elements::{GlobalAttributes, SvgAttributes}; #inner }) }), }; } }