damask
React-like components for Rust whose templates compile away.
React-like components for Rust, resolved entirely at build time. A component is
a struct — its fields are its props — paired with an HTML template written in a
{ … } tag syntax. The Component derive finds the .dmk file sitting next to
the struct and compiles it into a render method, so what runs is plain,
allocation-light Rust: no template engine, no parsing, nothing to load at
startup. There is no build.rs and nothing to configure; editing a template
rebuilds the crate.
Most of the interest is in what the compiler is made to catch. Capitalized tags
are components, and an attribute no field declares is a build failure naming it
— a misspelled prop cannot quietly render into the page. Attribute values are
typed rather than stringified: a bool writes a bare disabled or nothing at
all, an Option writes nothing when None, because in HTML the presence of
the attribute is what disables the control. {@tokens} builds one value out of
many parts, {@attrs} expands into a run of data-* or aria-* pairs, and
{...expr} splices attributes a component cannot name.
Slots are the web-component pair — <slot/> places, slot="…" fills — and live
off the struct, so a template declares as many as it likes without the type
changing; a <slot> written where a fill goes forwards it to a child. Snippets
are reusable fragments with parameters, which is how render-props are spelled.
And .await anywhere the template holds Rust compiles that component to an
async render path — decided from the template itself, at no cost to one that
does not await. The render future is Send, so a request handler can await it.
Beside the crate: a language server with diagnostics and completion, a Zed extension, and a Tree-sitter grammar the documentation site highlights with — so a snippet reads the same on the page as it does in an editor.
Rust, MIT, on crates.io: cargo add damask, with cargo install damask-lsp
for the language server.