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}