avosetta 0.2.3

Rust-native HTML templates with compile-time optimization.
Documentation

avosetta

Rust-native HTML templates with compile-time optimization.

GitHub Actions Workflow Status Crates.io Version docs.rs Crates.io Total Downloads GitHub License

about

avosetta is a Rust-native HTML templating library built around the asx! proc macro. Templates use a compact, Rust-like syntax and expand to values implementing Html, which render directly into a String.

The generated code is designed to leave very little work for runtime: adjacent static output is combined into larger string writes, and static string literals are HTML-escaped during compilation. Dynamic values are rendered through the Html trait and escaped where appropriate.

  • Rust-like elements, attributes, interpolation, and control flow
  • Compile-time escaping of static string literals
  • Coalesced static output for fewer runtime string operations
  • Runtime escaping for dynamic strings and characters
  • Conditional attributes through bool and Option
  • Direct composition through the Html trait
  • No intermediate template tree or virtual DOM

installation

Add avosetta with macro support:

cargo add avosetta --features macros

quick start

use avosetta::{asx, Html};

let name = "<Ada>";
let page = asx! {
    main[class="profile"] {
        h1 { "Hello, " @name }
        input[disabled=true];
    }
};

let mut html = String::new();
page.write(&mut html);

assert_eq!(
    html,
    r#"<main class="profile"><h1>Hello, &lt;Ada&gt;</h1><input disabled="disabled"></main>"#,
);

asx! returns an opaque value implementing Html. Call Html::write to append the rendered template to a string buffer.

syntax at a glance

Elements use braces for children, while void elements end with a semicolon. Prefix Rust expressions and control flow with @:

use avosetta::{asx, Html};

let title = "Messages";
let messages = ["Hello", "<Welcome>"];

let page = asx! {
    section[class="messages"] {
        h1 { @title }

        @if messages.is_empty() {
            p { "No messages" }
        } else {
            ul {
                @for message in messages {
                    li { @message }
                }
            }
        }
    }
};

let mut html = String::new();
page.write(&mut html);

Attribute values are Rust expressions. String literals can be written directly as template text, and names that are not Rust identifiers can be quoted:

"x-user-card"["aria-label"=label] {
    span { "Profile" }
}

See the crate-level API documentation for the complete syntax reference, including match, local Rust statements, quoted names, and attribute behavior.

escaping

Escaping is the default:

  • Static string literals are escaped at compile time.
  • Dynamic strings and characters are escaped when rendered.
  • false and None omit an attribute.
  • true emits a boolean attribute as name="name".

Use Raw only for trusted, already-rendered markup:

use avosetta::{asx, Html, Raw};

let trusted = "<strong>Already rendered</strong>";
let template = asx! {
    div { @Raw(trusted) }
};

let mut html = String::new();
template.write(&mut html);

Raw bypasses HTML escaping. Never use it with untrusted or user-controlled input.

performance

avosetta generates string-writing code rather than constructing an intermediate representation at runtime. Static runs are combined, static text is escaped during compilation, and dynamic values write directly into the destination buffer through Html.

This keeps the runtime path close to the final operation the application needs: appending HTML to a String.

license

avosetta is licensed under the MIT License. See LICENSE for details.

contributing

Contributions are welcome.

Please follow the existing code style and conventions used throughout the project. If you're proposing a new feature or API, opening an issue first is often the easiest way to discuss the design.