### Expected Output of Basic Example Source: https://maud.lambda.xyz/getting-started.html The rendered HTML output from the basic Maud program. ```text

Hi, Lyra!

``` -------------------------------- ### Basic Maud HTML Rendering Example Source: https://maud.lambda.xyz/getting-started.html A minimal Rust program demonstrating how to use the `maud::html!` macro to create and render an HTML string. The `html!` macro expands to a `Markup` type, which can be converted to a `String`. ```rust use maud::html; fn main() { let name = "Lyra"; let markup = html! { p { "Hi, " (name) "!" } }; println!("{}", markup.into_string()); } ``` -------------------------------- ### Render a Page Using Composed Markup Source: https://maud.lambda.xyz/partials.html Demonstrates how to use the `page` function to render the complete HTML structure, including dynamic content passed as Markup. This shows the practical application of the composed components. ```rust page("Hello!", html! { div { "Greetings, Maud." } }); ``` -------------------------------- ### Create a New Rust Project Source: https://maud.lambda.xyz/getting-started.html Use Cargo to create a new binary Rust project. This sets up the basic project structure. ```bash cargo new --bin pony-greeter cd pony-greeter ``` -------------------------------- ### Basic HTML Structure with Maud Macro Source: https://maud.lambda.xyz/ This snippet demonstrates the basic syntax of the `html!` macro for creating HTML elements and text content. It shows how to define a heading and a paragraph with a link. ```rust html! { h1 { "Hello, world!" } p.intro { "This is an example of the " a href="https://github.com/lambda-fairy/maud" { "Maud" } " template language." } } ``` -------------------------------- ### Using Classes and IDs Source: https://maud.lambda.xyz/elements-attributes.html Add classes and IDs using `.foo` and `#bar` syntax, which can be chained and mixed with other attributes. For Rust 2021 and later, `#` must be preceded by a space. ```rust html! { input #cannon .big.scary.bright-red type="button" value="Launch Party Cannon"; } ``` ```rust html! { // Works on all Rust editions input #pinkie; // Works on Rust 2018 and older only input#pinkie; } ``` ```rust html! { div."col-sm-2" { "Bootstrap column!" } } ``` -------------------------------- ### Define and Compose Header, Footer, and Page Markup Source: https://maud.lambda.xyz/partials.html Defines reusable header and footer components and a main page component that composes them. Use this pattern to build complex UIs from smaller, manageable parts. ```rust use maud::{DOCTYPE, html, Markup}; /// A basic header with a dynamic `page_title`. fn header(page_title: &str) -> Markup { html! { (DOCTYPE) meta charset="utf-8"; title { (page_title) } } } /// A static footer. fn footer() -> Markup { html! { footer { a href="rss.atom" { "RSS Feed" } } } } /// The final Markup, including `header` and `footer`. /// /// Additionally takes a `greeting_box` that's `Markup`, not `&str`. pub fn page(title: &str, greeting_box: Markup) -> Markup { html! { // Add the header markup to the page (header(title)) h1 { (title) } (greeting_box) (footer()) } } ``` -------------------------------- ### Axum Integration with Maud Source: https://maud.lambda.xyz/web-frameworks.html Demonstrates returning Maud's `Markup` directly as a response in an Axum application. This utilizes the 'axum' feature for `IntoResponse` implementation. ```rust 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(); } ``` -------------------------------- ### Rouille Integration with Maud Source: https://maud.lambda.xyz/web-frameworks.html Demonstrates how to directly use Maud's rendered HTML as a response in Rouille. No extra features are required. ```rust 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() ) }); } ``` -------------------------------- ### Submillisecond Route Returning Maud Markup Source: https://maud.lambda.xyz/web-frameworks.html Shows how to define a Submillisecond route that returns Maud's HTML markup directly as a response. ```rust use maud::{html, Markup}; use std::io::Result; use submillisecond::{router, Application}; fn main() -> Result<()> { Application::new(router! { GET "/hello" => helloworld }) .serve("0.0.0.0:3000") } fn helloworld() -> Markup { html! { h1 { "Hello, World!" } } } ``` -------------------------------- ### Creating Elements with Content Source: https://maud.lambda.xyz/elements-attributes.html Use curly braces `{}` to define elements that contain other elements or text. This is the standard way to build nested HTML structures. ```rust html! { h1 { "Poem" } p { strong { "Rock," } " you are a rock." } } ``` -------------------------------- ### Shorthand for Including CSS Stylesheets Source: https://maud.lambda.xyz/render-trait.html Implement `Render` for a `Css` struct to create a shorthand for linking CSS stylesheets, reducing repetitive HTML. ```rust use maud::{html, Markup, Render}; /// Links to a CSS stylesheet at the given path. struct Css(&'static str); impl Render for Css { fn render(&self) -> Markup { html! { link rel="stylesheet" type="text/css" href=(self.0); } } } ``` -------------------------------- ### Tide Integration with Maud Source: https://maud.lambda.xyz/web-frameworks.html Illustrates using Maud's `html!` macro to generate responses directly within a Tide web application. Requires the 'tide' feature. ```rust use maud::html; use tide::Request; use tide::prelude::*; #[async_std::main] async fn main() -> tide::Result<()> { let mut app = tide::new(); app.at("/hello/:name").get(|req: Request<()>| async move { let name: String = req.param("name")?.parse()?; Ok(html! { h1 { "Hello, " (name) "!" } p { "Nice to meet you!" } }) }); app.listen("127.0.0.1:8080").await?; Ok(()) } ``` -------------------------------- ### Actix Request Handler with Maud Markup Source: https://maud.lambda.xyz/web-frameworks.html Demonstrates an Actix request handler returning Maud's Markup, which implements actix_web::Responder. ```rust use actix_web::{get, App, HttpServer, Result as AwResult}; use maud::{html, Markup}; use std::io; #[get("/")] async fn index() -> AwResult { Ok(html! { html { body { h1 { "Hello World!" } } } }) } #[actix_web::main] async fn main() -> io::Result<()> { HttpServer::new(|| App::new().service(index)) .bind(("127.0.0.1", 8080))? .run() .await } ``` -------------------------------- ### Warp Handler Returning Maud Markup Source: https://maud.lambda.xyz/web-frameworks.html Demonstrates a Warp handler that directly returns Maud's HTML markup as a warp::Reply. ```rust use maud::html; use warp::Filter; #[tokio::main] async fn main() { let hello = warp::any().map(|| html! { h1 { "Hello, world!" } }); warp::serve(hello).run(([127, 0, 0, 1], 8000)).await; } ``` -------------------------------- ### Markdown Rendering with `pulldown-cmark` and `ammonia` Source: https://maud.lambda.xyz/render-trait.html Implement `Render` for a `Markdown` struct to convert Markdown text to sanitized HTML using `pulldown-cmark` for parsing and `ammonia` for security. ```rust use ammonia; use maud::{Markup, PreEscaped, Render}; use pulldown_cmark::{Parser, html}; /// Renders a block of Markdown using `pulldown-cmark`. struct Markdown(T); impl> Render for Markdown { fn render(&self) -> Markup { // Generate raw HTML let mut unsafe_html = String::new(); let parser = Parser::new(self.0.as_ref()); html::push_html(&mut unsafe_html, parser); // Sanitize it with ammonia let safe_html = ammonia::clean(&unsafe_html); PreEscaped(safe_html) } } ``` -------------------------------- ### Add Maud Dependency to Cargo.toml Source: https://maud.lambda.xyz/getting-started.html Specify the Maud crate as a dependency in your project's Cargo.toml file. The asterisk (*) indicates the latest compatible version. ```toml [dependencies] maud = "*" ``` -------------------------------- ### Add Actix-web Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Include the 'actix-web' feature in your Cargo.toml to enable Maud integration with Actix. ```toml # ... [dependencies] maud = { version = "*", features = ["actix-web"] } # ... ``` -------------------------------- ### Rocket Route Returning Maud Markup Source: https://maud.lambda.xyz/web-frameworks.html Shows a Rocket route handler that directly returns Maud's Markup, leveraging its Responder implementation. ```rust use maud::{html, Markup}; use rocket::{get, routes}; use std::borrow::Cow; #[get("/")] fn hello(name: &str) -> Markup { html! { h1 { "Hello, " (name) "!" } p { "Nice to meet you!" } } } #[rocket::launch] fn launch() -> _ { rocket::build().mount("/", routes![hello]) } ``` -------------------------------- ### Tide Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Shows the Cargo.toml dependency for enabling Tide support in Maud. This allows returning Maud's HTML directly as a Tide response. ```toml # ... [dependencies] maud = { version = "*", features = ["tide"] } # ... ``` -------------------------------- ### Poem Handler Returning Maud Markup Source: https://maud.lambda.xyz/web-frameworks.html Illustrates a Poem handler that returns Maud's HTML markup, which is automatically converted into a Poem response. ```rust use maud::{html, Markup}; use poem::{get, handler, listener::TcpListener, Route, Server}; #[handler] fn hello_world() -> Markup { html! { h1 { "Hello, World!" } } } #[tokio::main] async fn main() -> Result<(), std::io::Error> { let app = Route::new().at("/hello", get(hello_world)); Server::new(TcpListener::bind("0.0.0.0:3000")) .name("hello-world") .run(app) .await } ``` -------------------------------- ### Enable Submillisecond Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Add the 'submillisecond' feature to your Maud dependency in Cargo.toml to enable Submillisecond integration. ```toml # ... [dependencies] maud = { version = "*", features = ["submillisecond"] } # ... ``` -------------------------------- ### Enable Warp Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Add the 'warp' feature to your Maud dependency in Cargo.toml to enable Warp integration. ```toml # ... [dependencies] maud = { version = "*", features = ["warp"] } # ... ``` -------------------------------- ### Enable Poem Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Add the 'poem' feature to your Maud dependency in Cargo.toml to enable Poem integration. ```toml # ... [dependencies] maud = { version = "*", features = ["poem"] } # ... ``` -------------------------------- ### Pattern Matching with @match Source: https://maud.lambda.xyz/control-structures.html Implement exhaustive pattern matching using the @match construct, similar to Rust's match expressions. This allows for complex conditional logic based on enumerated types or other patterns. ```rust enum Princess { Celestia, Luna, Cadance, TwilightSparkle } let user = Princess::Celestia; html! { @match user { Princess::Luna => { h1 { "Super secret woona to-do list" } ul { li { "Nuke the Crystal Empire" } li { "Kick a puppy" } li { "Evil laugh" } } }, Princess::Celestia => { p { "Sister, please stop reading my diary. It's rude." } }, _ => p { "Nothing to see here; move along." } } } ``` -------------------------------- ### Looping with @for Source: https://maud.lambda.xyz/control-structures.html Iterate over elements of an iterator using the @for .. in .. syntax. This is suitable for rendering lists or collections dynamically. ```rust let names = ["Applejack", "Rarity", "Fluttershy"]; html! { p { "My favorite ponies are:" } ol { @for name in &names { li { (name) } } } } ``` -------------------------------- ### Axum Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Shows the Cargo.toml dependency for enabling Axum support in Maud. This allows Maud's output to be used directly with Axum's `IntoResponse` trait. ```toml # ... [dependencies] maud = { version = "*", features = ["axum"] } # ... ``` -------------------------------- ### Adding Non-Empty Attributes Source: https://maud.lambda.xyz/elements-attributes.html Attach attributes to elements using the `attr="value"` syntax. Attribute values must be quoted string literals. ```rust html! { ul { li { a href="about:blank" { "Apple Bloom" } } li class="lower-middle" { "Sweetie Belle" } li dir="rtl" { "Scootaloo " small { "(also a chicken)" } } } } ``` -------------------------------- ### Defining Void Elements Source: https://maud.lambda.xyz/elements-attributes.html Terminate void elements, such as `
`, using a semicolon `;`. This ensures they are rendered correctly in HTML. ```rust html! { link rel="stylesheet" href="poetry.css"; p { "Rock, you are a rock." br; "Gray, you are gray," br; "Like a rock, which you are." br; "Rock." } } ``` -------------------------------- ### Wrapper for `std::fmt::Debug` Rendering Source: https://maud.lambda.xyz/render-trait.html Use a `Debug` wrapper struct that implements `Render` to display internal state using the `Debug` trait when `Display` is not available. Overrides `.render_to()` for efficiency and uses `Escaper` to prevent XSS vulnerabilities. ```rust use maud::{Escaper, html, Render}; use std::fmt; use std::fmt::Write as _; /// Renders the given value using its `Debug` implementation. struct Debug(T); impl Render for Debug { fn render_to(&self, output: &mut String) { let mut escaper = Escaper::new(output); write!(escaper, "{{:?}}", self.0).unwrap(); } } ``` -------------------------------- ### Using DOCTYPE Constant for HTML Declaration Source: https://maud.lambda.xyz/text-escaping.html Insert a `` declaration using the `maud::DOCTYPE` constant for standard HTML5 document type. ```rust use maud::DOCTYPE; html! { (DOCTYPE) // } ``` -------------------------------- ### Conditional Branching with @if, @else if, and @else Source: https://maud.lambda.xyz/control-structures.html Use @if, @else if, and @else for conditional rendering based on boolean expressions. Braces are mandatory, and the @else clause is optional. This mirrors Rust's if-else if-else syntax. ```rust #[derive(PartialEq)] enum Princess { Celestia, Luna, Cadance, TwilightSparkle } let user = Princess::Celestia; html! { @if user == Princess::Luna { h1 { "Super secret woona to-do list" } ul { li { "Nuke the Crystal Empire" } li { "Kick a puppy" } li { "Evil laugh" } } } @else if user == Princess::Celestia { p { "Sister, please stop reading my diary. It's rude." } } @else { p { "Nothing to see here; move along." } } } ``` -------------------------------- ### Basic Splice Usage Source: https://maud.lambda.xyz/splices-toggles.html Insert dynamic string values and computed values into HTML elements. HTML special characters are escaped by default. ```rust 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]) } } ``` -------------------------------- ### Toggle Classes Source: https://maud.lambda.xyz/splices-toggles.html Conditionally apply CSS classes to HTML elements based on a Rust boolean expression. The class is added only if the expression evaluates to true. ```rust let cuteness = 95; html! { p.cute[cuteness > 50] { "Squee!" } } ``` -------------------------------- ### Variable Declaration with @let in Loops Source: https://maud.lambda.xyz/control-structures.html Declare new variables within a template scope using @let. This is particularly useful inside @for loops for intermediate calculations or transformations. ```rust 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) } "." } } } ``` -------------------------------- ### Splices in Classes and IDs Source: https://maud.lambda.xyz/splices-toggles.html Dynamically set HTML element classes and IDs using splices. This allows for conditional styling or element identification. ```rust let name = "rarity"; let severity = "critical"; html! { aside #(name) { p.{ "color-" (severity) } { "This is the worst! Possible! Thing!" } } } ``` -------------------------------- ### Add Rocket Feature for Maud Source: https://maud.lambda.xyz/web-frameworks.html Include the 'rocket' feature in your Cargo.toml to enable Maud integration with Rocket. ```toml # ... [dependencies] maud = { version = "*", features = ["rocket"] } # ... ``` -------------------------------- ### Optional Attributes with Values Source: https://maud.lambda.xyz/splices-toggles.html Render optional attributes using `attr=[Some(value)]` syntax. The attribute is rendered only if the value is `Some(T)`, and omitted if it's `None`. ```rust html! { p title=[Some("Good password")] { "Correct horse" } @let value = Some(42); input value=[value]; @let title: Option<&str> = None; p title=[title] { "Battery staple" } } ``` -------------------------------- ### Raw String for Long or Special Character Content Source: https://maud.lambda.xyz/text-escaping.html Employ raw strings (prefixed with `r#"`) for lengthy strings or those with numerous special characters to avoid manual escaping. ```rust html! { pre { r#" Rocks, these are my rocks. Sediments make me sedimental. Smooth and round, Asleep in the ground. Shades of brown And gray. "# } } ``` -------------------------------- ### Splicing Pre-Escaped Content Source: https://maud.lambda.xyz/splices-toggles.html Use the `PreEscaped` wrapper to insert HTML content directly without escaping. This is useful for rendering pre-formatted HTML strings. ```rust use maud::PreEscaped; let post = "

Pre-escaped

"; html! { h1 { "My super duper blog post" } (PreEscaped(post)) } ``` -------------------------------- ### Declaring Empty Attributes Source: https://maud.lambda.xyz/elements-attributes.html Declare an empty attribute by omitting its value. Previously, a `?` suffix was required, but this is no longer necessary for new code. ```rust html! { form { input type="checkbox" name="cupcakes" checked; " " label for="cupcakes" { "Do you like cupcakes?" } } } ``` -------------------------------- ### Conditional Let Binding with @if let Source: https://maud.lambda.xyz/control-structures.html Supports @if let for handling optional values or pattern matching within conditional blocks. The @else clause provides a fallback when the pattern does not match. ```rust let user = Some("Pinkie Pie"); html! { p { "Hello, " @if let Some(name) = user { (name) } @else { "stranger" } "!" } } ``` -------------------------------- ### Custom Elements and Data Attributes Source: https://maud.lambda.xyz/elements-attributes.html Maud supports elements and attributes with hyphens, including custom elements, data attributes (e.g., `data-index`), and ARIA annotations. ```rust html! { article data-index="12345" { h1 { "My blog" } tag-cloud { "pinkie pie pony cute" } } } ``` -------------------------------- ### Concatenating Values in Attributes Source: https://maud.lambda.xyz/splices-toggles.html Wrap multiple values in braces within an attribute to concatenate them. This is useful for constructing URLs or complex attribute values. ```rust const GITHUB: &'static str = "https://github.com"; html! { a href={ (GITHUB) "/lambda-fairy/maud" } { "Fork me on GitHub" } } ``` -------------------------------- ### Toggle Boolean Attributes Source: https://maud.lambda.xyz/splices-toggles.html Conditionally render boolean HTML attributes based on a Rust boolean expression. The attribute is added only if the expression evaluates to true. ```rust let allow_editing = true; html! { p contenteditable[allow_editing] { "Edit me, I " em { "dare" } " you." } } ``` -------------------------------- ### Literal String in Maud Source: https://maud.lambda.xyz/text-escaping.html Use double quotes for literal strings in Maud, similar to Rust. Backslashes are used for escape sequences. ```rust html! { "Oatmeal, are you crazy?" } ``` -------------------------------- ### Implicit Div Elements Source: https://maud.lambda.xyz/elements-attributes.html If an element name is omitted but a class or ID is provided, Maud assumes it is a `div` element. ```rust html! { #main { "Main content!" .tip { "Storing food in a refrigerator can make it 20% cooler." } } } ``` -------------------------------- ### Splice with Arbitrary Rust Code Source: https://maud.lambda.xyz/splices-toggles.html Use Rust code blocks within splices for complex expressions that are difficult to read inline. Ensure the code block returns a value that implements the `Render` trait. ```rust html! { p { ({ let f: Foo = something_convertible_to_foo()?; f.time().format("%H%Mh") }) } } ``` -------------------------------- ### Splice in HTML Attributes Source: https://maud.lambda.xyz/splices-toggles.html Insert dynamic string values into HTML attributes. The value is automatically escaped. ```rust let secret_message = "Surprise!"; html! { p title=(secret_message) { "Nothing to see here, move along." } } ``` -------------------------------- ### Disabling HTML Escaping with PreEscaped Source: https://maud.lambda.xyz/text-escaping.html Wrap strings in `PreEscaped()` to prevent Maud from automatically escaping HTML special characters. This is useful for including raw HTML or script content. ```rust use maud::PreEscaped; html! { "" // <script>... (PreEscaped("")) //