3 unstable releases
0.2.0 | Apr 26, 2025 |
---|---|
0.1.1 | Oct 17, 2024 |
0.1.0 | Oct 15, 2024 |
#200 in Template engine
154 downloads per month
40KB
928 lines
vy
A convenient, type-safe HTML templating library for Rust
Usage
Create a typical HTML page:
use vy::prelude::*;
fn page(content: impl IntoHtml) -> impl IntoHtml {
(
DOCTYPE,
html!(
head!(
meta!(charset = "UTF-8"),
title!("My Title"),
meta!(
name = "viewport",
content = "width=device-width,initial-scale=1"
),
meta!(name = "description", content = ""),
link!(rel = "icon", href = "favicon.ico")
),
body!(
h1!("My Heading"),
content
)
),
)
}
Key features to note:
- Tag macros: HTML elements are created using dedicated macros.
- Inline attributes: Attributes are declared directly within macro bodies using
key = value
syntax. - Zero wrapping: No need for container macros – elements compose naturally.
- Void element support: Automatically handles self-closing tags like
<meta>
,<img>
, etc.
Syntax
The macro grammar follows this pattern:
element := [attribute],* [content],*
content := expression
attribute := name['?'] '=' expression
name := identifier | text
Key design choices
- Parenthesis-based: Works with
rustfmt
formatting constraints. - Reserved word handling: Attributes like
type
andfor
use string syntax, e.g.,"type" = ".."
instead oftype = ".."
. - Optional attributes:
?
marks optional attributes (e.g.,disabled? = Some("")
).
Why this syntax?
The macro design balances several constraints:
- Compatibility with Rust's syntax tree.
rustfmt
compatibility (requires parenthesis syntax, e.g.,div!()
instead ofdiv!{}
).- Natural HTML-like authoring experience.
- Compile-time validation.
Escaping
Escaping is done automatically, but can be opted out by wrapping a type with PreEscaped(..)
.
Performance
vy
utilizes a few practices for fast rendering times:
- Pre-calculated sizing: HTML output size is estimated before allocation.
- Single-allocation rendering: Most templates render in one memory allocation.
- Zero-cost composition: Macros expand to tuple-based
IntoHtml
types without closures.
Dependencies
~320–780KB
~17K SLoC