Expand description
A blazing fast type-checked HTML macro crate.
Features
Speed
The macros generate code that is as fast as writing HTML to a string by
hand, and intelligently combines what would be multiple push_str
calls
into one if there is no dynamic content between them.
The entire crate is #![no_std]
compatible, and allocation is completely
optional if you don’t use any dynamic content. Disabling the alloc
feature
and using maud_static!
/rsx_static!
will result in an
Rendered<&str>
, which can even be used in const
contexts!
The crate gives extreme importance to lazy rendering and minimizing
allocation, so it will only render the HTML to a string when you finally
call Renderable::render
at the end. This makes composing nested HTML
elements extremely cheap.
Type-Checking
All macros are validated at compile time, so you can’t ever misspell an element/attribute or use invalid attributes.
It does this by looking for a module in your current namespace named
html_elements
(all the valid HTML elements are defined in this crate
already in html_elements
, but it doesn’t hard-code this module so you
can define your own elements).
It then imports each element you use in your macro invocation as a struct, and then proceeds to attempt to access the corresponding associated type for each attribute you use.
Examples
use hypertext::{html_elements, maud, GlobalAttributes, Renderable};
maud! {
div #main title="Main Div" {
h1.important {
"Hello, world!"
}
}
}
.render()
// expands to (roughly):
{
const _: () = {
html_elements::div;
html_elements::h1;
let _: hypertext::Attribute = html_elements::div::id;
let _: hypertext::Attribute = html_elements::div::title;
let _: hypertext::Attribute = html_elements::h1::class;
};
|hypertext_output: &mut String| {
hypertext_output.push_str(
r#"<div id="main" title="Main Div"><h1 class="important">Hello, world!</h1></div>"#
);
}
}
.render()
This approach is also extremely extensible, as you can define your own
traits to add attributes for your favourite libraries! In fact, this is
exactly what GlobalAttributes
does, and why it is required in the above
example. GlobalAttributes
defines all the global attributes that can be
used on any element, for example id
,
class
and title
.
Here’s an example of how you could define your own attributes for use with the wonderful frontend library htmx:
use hypertext::{html_elements, maud, Attribute, GlobalAttributes, Renderable};
trait HtmxAttributes: GlobalAttributes {
const hx_get: Attribute = Attribute;
const hx_post: Attribute = Attribute;
// ...
}
impl<T: GlobalAttributes> HtmxAttributes for T {}
assert_eq!(
// vvvvvv note that it converts `-` to `_` for you during checking!
maud! { div hx-get="/api/endpoint" { "Hello, world!" } }.render(),
r#"<div hx-get="/api/endpoint">Hello, world!</div>"#,
);
Modules
- HTML elements.
Macros
- Generate HTML using
maud
syntax. - Generate HTML using
maud
syntax. - Render static HTML using
maud
syntax. - Generate HTML using rsx syntax.
- Generate HTML using
rsx!
syntax. - Render static HTML using rsx syntax.
Structs
- An HTML attribute.
- An HTML attribute namespace.
- Displayed
alloc
A value rendered via itsDisplay
implementation. - Raw
alloc
A raw value that is rendered without escaping. - A rendered HTML string.
Traits
- Global HTML attributes.
- RenderIterator
alloc
An extension trait forIntoIterator
s that can be rendered. - Renderable
alloc
A type that can be rendered to a string. - Elements that can be self-closing.