Macro mox::mox [−][src]
mox!() { /* proc-macro */ }
Expand description
Accepts an XML-like expression and expands it to builder-like method calls.
Outputs
The mox!
macro’s contents are expanded to method calls, with .build()
called on the outmost expression.
Tags
Each tag expands to a function call with the same name as the tag.
Each attribute expands to a method called on the value returned from the tag opening or the previous attribute. The attribute name is used as the method name, with the attribute value passed as the argument.
A tag with children has each child passed as the argument to a call to
.child(...)
, one per child in order of declaration. The calls to child
come after attributes.
Fragments
Fragments are not yet supported. See this issue for discussion.
Inputs
Each macro invocation must resolve to a single item. Items can be tags, fragments, or content.
syn-rsx is used to tokenize the input as JSX(ish).
Tags
Tags always have a name and can have zero or more arguments, attributes, and children.
They take the form <NAME ATTR=VAL ...> CHILDREN </NAME>
. Each optional
portion can be omitted.
Attributes
Each attribute takes the form NAME=VAL
where NAME
is an identifier and
VALUE
is an expression.
If the attribute’s name is async
, for
, loop
, or type
an underscore
is appended to avoid colliding with the Rust keyword.
Children
Tags have zero or more nested items (tags, fragments, content) as children.
If there are no children the tag can be “self-closing”: <NAME ... />
.
Each child can be either another tag, a Rust literal, or a Rust block (an
expression wrapped in {
and }
).
Block expressions can optionally be opened with {%
to denote a “formatter”
item. The enclosed tokens are passed to the format_args!
macro.
Hyphenated Names
Tag and attribute names can by hyphenated. The underlying function and method names will have hyphens replaced with underscores. Multiple consecutive hyphens are not supported.
Fragments
Fragments are opened with <>
and closed with </>
. Their only purpose is
to provide a parent for children. They do not accept arguments or
attributes.
Example
use mox::mox;
#[derive(Debug, PartialEq)]
struct Tag {
name: String,
children: Vec<Tag>,
}
fn built() -> TagBuilder {
TagBuilder::default()
}
#[derive(Default)]
struct TagBuilder {
name: Option<String>,
children: Vec<Tag>,
}
impl TagBuilder {
fn name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
fn child(mut self, child: TagBuilder) -> Self {
self.children.push(child.build());
self
}
fn build(self) -> Tag {
Tag { name: self.name.unwrap(), children: self.children }
}
}
assert_eq!(
mox! {
<built name="alice">
<!-- "This is a comment" -->
<built name="bob"/>
</built>
},
Tag {
name: String::from("alice"),
children: vec![Tag { name: String::from("bob"), children: vec![] }],
},
);