#[macro_export]
macro_rules! reactant {
// Converts (function) {...} into element
( $f:ident $t:tt ) => {
{
let mut elem = HtmlElement::new($f);
reactant!(@expand elem $t);
elem
}
};
// Expands {...} and parses each internal node individually
( @expand $self:ident { $($t:tt),* } ) => {
$(
reactant!(@generate $self $t);
)*
};
// Takes a (function) {...} node, feeds it back recursively, and pushes it into parent
( @generate $self:ident $t1:tt $t2:tt) => {
{
$self.push_inner(reactant!($t1 $t2));
}
};
// Takes a literal and sets the parent internal to a string
( @generate $self:ident $l:literal) => {
{
$self.set_inner(String::from($l)).unwrap();
}
};
}
#[allow(unused_macros)]
#[cfg(test)]
mod tests {
use crate::html::types::*;
use crate::html::HtmlElement;
use crate::reactant;
#[test]
fn test() {
// Doesn't work, not expecting '{' after second div, although the first one works fine
let x = reactant!(div {
div {
"test"
}
});
// Works, outputs <div>thing</div>
let y = reactant!(div {
"hello",
"thing"
});
}
}
I am working on making an uncreatively named HTML library in Rust, and am also learning macros at the same time (the macro documentation is confusing). Part of the project is making a macro that generates HTML elements recursively to make a document, in a similar appearance to serde_json. The syntax is shown in the test cases. Basically, every HTML element (div, h1, etc.) is mapped to a function that outputs a struct that I have crafted for HTML elements. I managed to get the macro working in one way, but it only allowed for HTML children when I want it to also take literals to fill in, say, an h1 with a string (test case 1). Test case 2 shows where it doesn't work, and I am not understanding why it can't read the {.