cercis_rsx/
lib.rs

1use crate::node::NodeTree;
2use crate::prelude::*;
3
4mod node;
5mod prelude;
6
7struct BodyCall(Vec<NodeTree>);
8
9impl Parse for BodyCall {
10    fn parse(input: ParseStream) -> Result<Self> {
11        let mut nodes = Vec::new();
12
13        while !input.is_empty() {
14            nodes.push(input.parse()?);
15        }
16
17        Ok(Self(nodes))
18    }
19}
20
21impl ToTokens for BodyCall {
22    fn to_tokens(&self, tokens: &mut TokenStream2) {
23        let nodes = self.0.as_slice();
24
25        quote!({
26            use ::cercis::html::*;
27            VBody::new()#(.child(#nodes))*
28        })
29        .to_tokens(tokens)
30    }
31}
32
33/// Macro ```rsx!``` write HTML templates in Rust code like jsx
34///
35/// > Return VBody struct that can render to string by ```.render()``` method
36///
37/// # Examples
38///
39/// ## Formatting
40///
41/// ```
42/// use cercis::prelude::*;
43///
44/// let text = "Hello World!";
45/// rsx!(h1 { "{text}" });
46/// ```
47///
48/// ## Nested
49///
50/// ```
51/// use cercis::prelude::*;
52///
53/// let text = "Hello World!";
54/// rsx!(div {
55///   p { "{text}" }
56///   span { "Lorem ipsum" }
57/// });
58/// ```
59///
60/// ## Attributes
61///
62/// ```
63/// use cercis::prelude::*;
64///
65/// let container_name = "main";
66/// rsx!(div {
67///   class: "container-{container_name}",
68///   
69///   p { "Lorem ipsum" }
70/// });
71/// ```
72#[proc_macro]
73pub fn rsx(input: TokenStream) -> TokenStream {
74    match syn::parse::<BodyCall>(input) {
75        Ok(body) => body.into_token_stream().into(),
76        Err(err) => err.to_compile_error().into(),
77    }
78}