body.rs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. use proc_macro2::TokenStream as TokenStream2;
  2. use quote::{quote, ToTokens, TokenStreamExt};
  3. use syn::{
  4. parse::{Parse, ParseStream},
  5. Ident, Result, Token,
  6. };
  7. use super::*;
  8. pub struct CallBody {
  9. custom_context: Option<Ident>,
  10. roots: Vec<BodyNode>,
  11. }
  12. /// The custom rusty variant of parsing rsx!
  13. impl Parse for CallBody {
  14. fn parse(input: ParseStream) -> Result<Self> {
  15. let custom_context = try_parse_custom_context(input)?;
  16. let (_, roots, _) = BodyConfig::new_call_body().parse_component_body(input)?;
  17. Ok(Self {
  18. custom_context,
  19. roots,
  20. })
  21. }
  22. }
  23. fn try_parse_custom_context(input: ParseStream) -> Result<Option<Ident>> {
  24. let res = if input.peek(Ident) && input.peek2(Token![,]) {
  25. let name = input.parse::<Ident>()?;
  26. input.parse::<Token![,]>()?;
  27. Some(name)
  28. } else {
  29. None
  30. };
  31. Ok(res)
  32. }
  33. /// Serialize the same way, regardless of flavor
  34. impl ToTokens for CallBody {
  35. fn to_tokens(&self, out_tokens: &mut TokenStream2) {
  36. let inner = if self.roots.len() == 1 {
  37. let inner = &self.roots[0];
  38. quote! {#inner}
  39. } else {
  40. let childs = &self.roots;
  41. quote! { __cx.fragment_root([ #(#childs),* ]) }
  42. };
  43. match &self.custom_context {
  44. // The `in cx` pattern allows directly rendering
  45. Some(ident) => out_tokens.append_all(quote! {
  46. #ident.render(LazyNodes::new_some(move |__cx: NodeFactory| -> VNode {
  47. use dioxus_elements::{GlobalAttributes, SvgAttributes};
  48. #inner
  49. }))
  50. }),
  51. // Otherwise we just build the LazyNode wrapper
  52. None => out_tokens.append_all(quote! {
  53. LazyNodes::new_some(move |__cx: NodeFactory| -> VNode {
  54. use dioxus_elements::{GlobalAttributes, SvgAttributes};
  55. #inner
  56. })
  57. }),
  58. };
  59. }
  60. }