Maud Documentation

repository·main·Indexed 24 days ago

https://github.com/lambda-fairy/maud

Maud is a macro-based HTML template engine for Rust that compiles markup into specialized Rust code at compile time for maximum performance and type safety. It features the `html!` macro for writing markup, support for control structures like `@if`, `@for`, and `@match`, and a `Render` trait for customizing HTML output. The engine allows for composition using Rust functions that return `Markup` and provides shorthand syntax for CSS classes and IDs.

Tokens
9.3K
Snippets
40
Records
59
Agent score
81%

What's inside Maud

  1. Overview of Maud HTML template engine

    main
    Maud is a high-performance HTML template engine for Rust. It uses the html! macro to compile markup directly into specialized Rust code at compile time. This approach provides high execution speed, strong type safety, and simplified deployment compared to runtime-interpreted template engines.
  2. Declare variables with `@let`

    main

    Declare new variables within a template using @let. This is particularly useful for performing computations or transformations on values inside a loop.

    let names = ["Applejack", "Rarity", "Fluttershy"];
    
    html! {
        @for name in &names {
            @let first_letter = name.chars().next().unwrap();
            p {
                "The first letter of "
                b { (name) }
                " is "
                b { (first_letter) }
                "."
            }
        }
    }
  3. Insert values using Splices `(foo)`

    main

    Use the (foo) syntax to insert the value of foo into your HTML at runtime. By default, all HTML special characters are escaped. You can also use a block expression { ... } inside a splice to execute arbitrary Rust code for complex expressions.

    let best_pony = "Pinkie Pie";
    let numbers = [1, 2, 3, 4];
    html! {
        p { "Hi, " (best_pony) "!" }
        p {
            "I have " (numbers.len()) " numbers, "
            "and the first one is " (numbers[0])
        }
    }
  4. Integrate Maud with Rouille

    main

    Maud works with Rouille out of the box without any extra features. You can pass the rendered Markup directly into rouille::Response::html().

    use maud::html;
    use rouille::{Response, router};
    
    fn main() {
        rouille::start_server("localhost:8000", move |request| {
            router!(request,
                (GET) (/{name: String}) => {
                    Response::html(html! {
                        h1 { "Hello, " (name) "!" }
                        p { "Nice to meet you!" }
                    })
                },
                _ => Response::empty_404()
            )
        });
    }
  5. Integrate Maud with Rocket

    main

    To use Maud with Rocket, enable the rocket feature in your Cargo.toml. This adds a Responder implementation for the Markup type, allowing you to return Markup directly from your routes.

    [dependencies]
    maud = { version = "*", features = ["rocket"] }
    use maud::{html, Markup};
    use rocket::{get, routes};
    
    #[get("/<name>")]
    fn hello(name: &str) -> Markup {
        html! {
            h1 { "Hello, " (name) "!" }
            p { "Nice to meet you!" }
        }
    }
    
    #[rocket::launch]
    fn launch() -> _ {
        rocket::build().mount("/", routes![hello])
    }
  6. Integrate Maud with Axum

    main

    To use Maud with Axum, enable the axum feature in your Cargo.toml. This adds an implementation of IntoResponse for Markup and PreEscaped<String>, allowing them to be used directly as responses.

    [dependencies]
    maud = { version = "*", features = ["axum"] }
    use maud::{html, Markup};
    use axum::{Router, routing::get};
    
    async fn hello_world() -> Markup {
        html! {
            h1 { "Hello, World!" }
        }
    }
    
    #[tokio::main]
    async fn main() {
        // build our application with a single route
        let app = Router::new().route("/", get(hello_world));
    
        // run it with hyper on localhost:3000
        let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    
        axum::serve(listener, app.into_make_service()).await.unwrap();
    }
  7. Branch with `@if` and `@else`

    main

    Use @if and @else to branch on a boolean expression within a html! macro. Braces are mandatory for the code blocks, and @else if or @else clauses are optional. Maud also supports the @if let syntax for pattern matching on Option or Result types.

    let user = Some("Pinkie Pie");
    
    html! {
        p {
            "Hello, "
            @if let Some(name) = user {
                (name)
            } @else {
                "stranger"
            }
            "!"
        }
    }
  8. Create void elements using semicolons

    main

    Void elements (elements that do not have closing tags, like <br> or <link>) are terminated using a semicolon ;. Maud renders these using standard HTML syntax (e.g., <br>) rather than self-closing XHTML syntax (e.g., <br />).

    html! {
        link rel="stylesheet" href="poetry.css";
        p {
            "Rock, you are a rock."
            br;
            "Gray, you are gray,"
            br;
        }
    }