Switch documentation to semantic line breaks ()

mdformat will preserve semantic line breaks, so we may as well commit to
using them.

cc 
This commit is contained in:
Chris Wong 2021-01-22 19:31:51 +13:00 committed by GitHub
parent eaf552d417
commit 75b6801f47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 155 additions and 48 deletions

View file

@ -3,11 +3,18 @@
[![Cargo](https://img.shields.io/crates/v/maud.svg)](https://crates.io/crates/maud) [![Cargo](https://img.shields.io/crates/v/maud.svg)](https://crates.io/crates/maud)
[![API reference](https://docs.rs/maud/badge.svg)](https://docs.rs/maud/) [![API reference](https://docs.rs/maud/badge.svg)](https://docs.rs/maud/)
[Documentation][book] ([source][booksrc]) • [API reference][apiref] • [Change log][changelog] [Documentation][book] ([source][booksrc]) •
[API reference][apiref] •
[Change log][changelog]
Maud is an HTML template engine for Rust. It's implemented as a macro, `html!`, which compiles your markup to specialized Rust code. This unique approach makes Maud templates blazing fast, super type-safe, and easy to deploy. Maud is an HTML template engine for Rust.
It's implemented as a macro, `html!`,
which compiles your markup to specialized Rust code.
This unique approach makes Maud templates
blazing fast, super type-safe, and easy to deploy.
For more info on Maud, see the [official book][book]. For more info on Maud,
see the [official book][book].
[book]: https://maud.lambda.xyz/ [book]: https://maud.lambda.xyz/
[booksrc]: https://github.com/lambda-fairy/maud/tree/master/docs [booksrc]: https://github.com/lambda-fairy/maud/tree/master/docs

View file

@ -1,10 +1,14 @@
# Control structures # Control structures
Maud provides various control structures for adding dynamic elements to your templates. Maud provides various control structures
for adding dynamic elements to your templates.
## Branching with `@if` and `@else` ## Branching with `@if` and `@else`
Use `@if` and `@else` to branch on a boolean expression. As with Rust, braces are mandatory and the `@else` clause is optional. Use `@if` and `@else` to branch on a boolean expression.
As with Rust,
braces are mandatory
and the `@else` clause is optional.
```rust ```rust
#[derive(PartialEq)] #[derive(PartialEq)]
@ -69,7 +73,8 @@ html! {
## Declaring variables with `@let` ## Declaring variables with `@let`
Declare a new variable within a template using `@let`. This can be useful when working with values in a for loop. Declare a new variable within a template using `@let`.
This can be useful when working with values in a for loop.
```rust ```rust
let names = ["Applejack", "Rarity", "Fluttershy"]; let names = ["Applejack", "Rarity", "Fluttershy"];

View file

@ -16,7 +16,10 @@ html! {
# ; # ;
``` ```
Before version 0.18, Maud allowed the curly braces to be omitted. This syntax was [removed][#137] and now causes an error instead. Before version 0.18,
Maud allowed the curly braces to be omitted.
This syntax was [removed][#137]
and now causes an error instead.
[#137]: https://github.com/lambda-fairy/maud/pull/137 [#137]: https://github.com/lambda-fairy/maud/pull/137
@ -41,15 +44,20 @@ html! {
# ; # ;
``` ```
The result will be rendered with HTML syntax `<br>` not `<br />`. The result will be rendered with HTML syntax
`<br>` not `<br />`.
Maud also supports ending a void element with a slash: `br /`. This syntax is [deprecated][#96] and should not be used in new code. Maud also supports ending a void element with a slash:
`br /`.
This syntax is [deprecated][#96]
and should not be used in new code.
[#96]: https://github.com/lambda-fairy/maud/pull/96 [#96]: https://github.com/lambda-fairy/maud/pull/96
## Custom elements and `data` attributes ## Custom elements and `data` attributes
Maud also supports elements and attributes with hyphens in them. This includes [custom elements], [data attributes], and [ARIA annotations]. Maud also supports elements and attributes with hyphens in them.
This includes [custom elements], [data attributes], and [ARIA annotations].
```rust ```rust
# let _ = maud:: # let _ = maud::
@ -68,7 +76,11 @@ html! {
## Non-empty attributes: `title="yay"` ## Non-empty attributes: `title="yay"`
Add attributes using the syntax: `attr="value"`. You can attach any number of attributes to an element. The values must be quoted: they are parsed as string literals. Add attributes using the syntax:
`attr="value"`.
You can attach any number of attributes to an element.
The values must be quoted:
they are parsed as string literals.
```rust ```rust
# let _ = maud:: # let _ = maud::
@ -105,13 +117,20 @@ html! {
# ; # ;
``` ```
Before version 0.22.2, Maud required a `?` suffix on empty attributes: `checked?`. This is no longer necessary ([#238]), but still supported for backward compatibility. Before version 0.22.2,
Maud required a `?` suffix on empty attributes:
`checked?`.
This is no longer necessary ([#238]),
but still supported for backward compatibility.
[#238]: https://github.com/lambda-fairy/maud/pull/238 [#238]: https://github.com/lambda-fairy/maud/pull/238
## Classes and IDs: `.foo` `#bar` ## Classes and IDs: `.foo` `#bar`
Add classes and IDs to an element using `.foo` and `#bar` syntax. You can chain multiple classes and IDs together, and mix and match them with other attributes: Add classes and IDs to an element
using `.foo` and `#bar` syntax.
You can chain multiple classes and IDs together,
and mix and match them with other attributes:
```rust ```rust
# let _ = maud:: # let _ = maud::
@ -121,7 +140,9 @@ html! {
# ; # ;
``` ```
The classes and IDs can be quoted. This is useful for names with numbers or symbols which otherwise wouldn't parse: The classes and IDs can be quoted.
This is useful for names with numbers or symbols
which otherwise wouldn't parse:
```rust ```rust
# let _ = maud:: # let _ = maud::
@ -133,7 +154,9 @@ html! {
## Implicit `div` elements ## Implicit `div` elements
If the element name is omitted, but there is a class or ID, then it is assumed to be a `div`. If the element name is omitted,
but there is a class or ID,
then it is assumed to be a `div`.
```rust ```rust
# let _ = maud:: # let _ = maud::

View file

@ -31,11 +31,15 @@ fn main() {
} }
``` ```
`html!` takes a single argument: a template using Maud's custom syntax. This call expands to an expression of type [`Markup`][Markup], which can then be converted to a `String` using `.into_string()`. `html!` takes a single argument:
a template using Maud's custom syntax.
This call expands to an expression of type [`Markup`][Markup],
which can then be converted to a `String` using `.into_string()`.
[Markup]: https://docs.rs/maud/*/maud/type.Markup.html [Markup]: https://docs.rs/maud/*/maud/type.Markup.html
Run this program with `cargo run`, and you should get the following: Run this program with `cargo run`,
and you should get the following:
```html ```html
<p>Hi, Lyra!</p> <p>Hi, Lyra!</p>

View file

@ -15,25 +15,41 @@ html! {
# ; # ;
``` ```
Maud is an HTML [template engine] for Rust. It's implemented as a macro, `html!`, which compiles your markup to specialized Rust code. This unique approach makes Maud templates blazing fast, super type-safe, and easy to deploy. Maud is an HTML [template engine] for Rust.
It's implemented as a macro, `html!`,
which compiles your markup to specialized Rust code.
This unique approach makes Maud templates
blazing fast, super type-safe, and easy to deploy.
[template engine]: https://www.simple-is-better.org/template/ [template engine]: https://www.simple-is-better.org/template/
## Tight integration with Rust ## Tight integration with Rust
Since Maud is a Rust macro, it can borrow most of its features from the host language. Pattern matching and `for` loops work as they do in Rust. There is no need to derive JSON conversions, as your templates can work with Rust values directly. Since Maud is a Rust macro,
it can borrow most of its features from the host language.
Pattern matching and `for` loops work as they do in Rust.
There is no need to derive JSON conversions,
as your templates can work with Rust values directly.
## Type safety ## Type safety
Your templates are checked by the compiler, just like the code around them. Any typos will be caught at compile time, not after your app has already started. Your templates are checked by the compiler,
just like the code around them.
Any typos will be caught at compile time,
not after your app has already started.
## Minimal runtime ## Minimal runtime
Since most of the work happens at compile time, the runtime footprint is small. The Maud runtime library, including integration with the [Rocket] and [Actix] web frameworks, is around 100 SLoC. Since most of the work happens at compile time,
the runtime footprint is small.
The Maud runtime library,
including integration with the [Rocket] and [Actix] web frameworks,
is around 100 SLoC.
[Rocket]: https://rocket.rs/ [Rocket]: https://rocket.rs/
[Actix]: https://actix.rs/ [Actix]: https://actix.rs/
## Simple deployment ## Simple deployment
There is no need to track separate template files, since all relevant code is linked into the final executable. There is no need to track separate template files,
since all relevant code is linked into the final executable.

View file

@ -1,6 +1,8 @@
# Partials # Partials
Maud does not have a built-in concept of partials or sub-templates. Instead, you can compose your markup with any function that returns `Markup`. Maud does not have a built-in concept of partials or sub-templates.
Instead,
you can compose your markup with any function that returns `Markup`.
The following example defines a `header` and `footer` function. The following example defines a `header` and `footer` function.
These functions are combined to form the final `page`. These functions are combined to form the final `page`.

View file

@ -1,14 +1,22 @@
# The `Render` trait # The `Render` trait
By default, a [`(splice)`](splices-toggles.md) is rendered using the [`std::fmt::Display`][Display] trait, with any HTML special characters escaped automatically. By default,
a [`(splice)`](splices-toggles.md) is rendered using the [`std::fmt::Display`][Display] trait,
with any HTML special characters escaped automatically.
To change this behavior, implement the [`Render`][Render] trait for your type. Then, when a value of this type is used in a template, Maud will call your custom code instead. To change this behavior,
implement the [`Render`][Render] trait for your type.
Then, when a value of this type is used in a template,
Maud will call your custom code instead.
Below are some examples of using `Render`. Feel free to use these snippets in your own project! Below are some examples of using `Render`.
Feel free to use these snippets in your own project!
## Example: a shorthand for including CSS stylesheets ## Example: a shorthand for including CSS stylesheets
When writing a web page, it can be annoying to write `link rel="stylesheet"` over and over again. This example provides a shorthand for linking to CSS stylesheets. When writing a web page,
it can be annoying to write `link rel="stylesheet"` over and over again.
This example provides a shorthand for linking to CSS stylesheets.
```rust ```rust
use maud::{html, Markup, Render}; use maud::{html, Markup, Render};
@ -27,9 +35,15 @@ impl Render for Css {
## Example: a wrapper that calls `std::fmt::Debug` ## Example: a wrapper that calls `std::fmt::Debug`
When debugging an application, it can be useful to see its internal state. But these internal data types often don't implement `Display`. This wrapper lets us use the [`Debug`][Debug] trait instead. When debugging an application,
it can be useful to see its internal state.
But these internal data types often don't implement `Display`.
This wrapper lets us use the [`Debug`][Debug] trait instead.
To avoid extra allocation, we override the `.render_to()` method instead of `.render()`. This doesn't do any escaping by default, so we wrap the output in an `Escaper` as well. To avoid extra allocation,
we override the `.render_to()` method instead of `.render()`.
This doesn't do any escaping by default,
so we wrap the output in an `Escaper` as well.
```rust ```rust
use maud::{Escaper, html, Render}; use maud::{Escaper, html, Render};
@ -49,9 +63,11 @@ impl<T: fmt::Debug> Render for Debug<T> {
## Example: rendering Markdown using `pulldown-cmark` and `ammonia` ## Example: rendering Markdown using `pulldown-cmark` and `ammonia`
[`pulldown-cmark`][pulldown-cmark] is a popular library for converting Markdown to HTML. [`pulldown-cmark`][pulldown-cmark] is a popular library
for converting Markdown to HTML.
We also use the [`ammonia`][ammonia] library, which sanitizes the resulting markup. We also use the [`ammonia`][ammonia] library,
which sanitizes the resulting markup.
```rust ```rust
use ammonia; use ammonia;

View file

@ -2,7 +2,8 @@
## Splices: `(foo)` ## Splices: `(foo)`
Use `(foo)` syntax to insert the value of `foo` at runtime. Any HTML special characters are escaped by default. Use `(foo)` syntax to insert the value of `foo` at runtime.
Any HTML special characters are escaped by default.
```rust ```rust
let best_pony = "Pinkie Pie"; let best_pony = "Pinkie Pie";
@ -18,7 +19,9 @@ html! {
# ; # ;
``` ```
Arbitrary Rust code can be included in a splice by using a [block](https://doc.rust-lang.org/reference.html#block-expressions). This can be helpful for complex expressions that would be difficult to read otherwise. Arbitrary Rust code can be included in a splice by using a [block].
This can be helpful for complex expressions
that would be difficult to read otherwise.
```rust ```rust
# struct Foo; # struct Foo;
@ -41,6 +44,8 @@ html! {
# } # }
``` ```
[block]: https://doc.rust-lang.org/reference.html#block-expressions
### Splices in attributes ### Splices in attributes
Splices work in attributes as well. Splices work in attributes as well.
@ -56,7 +61,9 @@ html! {
# ; # ;
``` ```
To concatenate multiple values within an attribute, wrap the whole thing in braces. This syntax is useful for building URLs. To concatenate multiple values within an attribute,
wrap the whole thing in braces.
This syntax is useful for building URLs.
```rust ```rust
const GITHUB: &'static str = "https://github.com"; const GITHUB: &'static str = "https://github.com";
@ -87,9 +94,16 @@ html! {
### What can be spliced? ### What can be spliced?
You can splice any value that implements [`std::fmt::Display`][Display]. Most primitive types (such as `str` and `i32`) implement this trait, so they should work out of the box. You can splice any value that implements [`std::fmt::Display`][Display].
Most primitive types (such as `str` and `i32`) implement this trait,
so they should work out of the box.
To change this behavior for some type, you can implement the [`Render`][Render] trait by hand. The [`PreEscaped`][PreEscaped] wrapper type, which outputs its argument without escaping, works this way. See the [traits](render-trait.md) section for details. To change this behavior for some type,
you can implement the [`Render`][Render] trait by hand.
The [`PreEscaped`][PreEscaped] wrapper type,
which outputs its argument without escaping,
works this way.
See the [traits](render-trait.md) section for details.
```rust ```rust
use maud::PreEscaped; use maud::PreEscaped;
@ -108,7 +122,8 @@ html! {
## Toggles: `[foo]` ## Toggles: `[foo]`
Use `[foo]` syntax to show or hide something based on a boolean expression `foo`. Use `[foo]` syntax to show or hide something
based on a boolean expression `foo`.
This works on empty attributes: This works on empty attributes:

View file

@ -2,7 +2,9 @@
## Text ## Text
Literal strings use the same syntax as Rust. Wrap them in double quotes, and use a backslash for escapes. Literal strings use the same syntax as Rust.
Wrap them in double quotes,
and use a backslash for escapes.
```rust ```rust
# let _ = maud:: # let _ = maud::
@ -14,7 +16,9 @@ html! {
## Raw strings ## Raw strings
If the string is long, or contains many special characters, then it may be worth using [raw strings] instead: If the string is long,
or contains many special characters,
then it may be worth using [raw strings] instead:
```rust ```rust
# let _ = maud:: # let _ = maud::
@ -37,7 +41,11 @@ html! {
## Escaping and `PreEscaped` ## Escaping and `PreEscaped`
By default, HTML special characters are escaped automatically. Wrap the string in `(PreEscaped())` to disable this escaping. (See the section on [splices](splices-toggles.md) to learn more about how this works.) By default,
HTML special characters are escaped automatically.
Wrap the string in `(PreEscaped())` to disable this escaping.
(See the section on [splices](splices-toggles.md) to
learn more about how this works.)
```rust ```rust
use maud::PreEscaped; use maud::PreEscaped;
@ -51,7 +59,9 @@ html! {
## The `DOCTYPE` constant ## The `DOCTYPE` constant
If you want to add a `<!DOCTYPE html>` declaration to your page, you may use the `maud::DOCTYPE` constant instead of writing it out by hand: If you want to add a `<!DOCTYPE html>` declaration to your page,
you may use the `maud::DOCTYPE` constant
instead of writing it out by hand:
```rust ```rust
use maud::DOCTYPE; use maud::DOCTYPE;

View file

@ -1,6 +1,7 @@
# Web framework integration # Web framework integration
Maud includes support for these web frameworks: [Actix], [Iron], [Rocket], and [Rouille]. Maud includes support for these web frameworks:
[Actix], [Iron], [Rocket], and [Rouille].
[Actix]: https://actix.rs/ [Actix]: https://actix.rs/
[Iron]: http://ironframework.io [Iron]: http://ironframework.io
@ -18,7 +19,8 @@ maud = { version = "*", features = ["actix-web"] }
# ... # ...
``` ```
Actix request handlers can use a `Markup` that implements the `actix_web::Responder` trait. Actix request handlers can use a `Markup`
that implements the `actix_web::Responder` trait.
```rust,no_run ```rust,no_run
use actix_web::{get, App, HttpServer, Result as AwResult}; use actix_web::{get, App, HttpServer, Result as AwResult};
@ -56,7 +58,9 @@ maud = { version = "*", features = ["iron"] }
# ... # ...
``` ```
With this feature enabled, you can then build a `Response` from a `Markup` object directly. Here's an example application using Iron and Maud: With this feature enabled,
you can then build a `Response` from a `Markup` object directly.
Here's an example application using Iron and Maud:
```rust,no_run ```rust,no_run
use iron::prelude::*; use iron::prelude::*;
@ -76,11 +80,13 @@ fn main() {
} }
``` ```
`Markup` will set the content type of the response automatically, so you don't need to add it yourself. `Markup` will set the content type of the response automatically,
so you don't need to add it yourself.
# Rocket # Rocket
Rocket works in a similar way, except using the `rocket` feature: Rocket works in a similar way,
except using the `rocket` feature:
```toml ```toml
# ... # ...
@ -89,7 +95,8 @@ maud = { version = "*", features = ["rocket"] }
# ... # ...
``` ```
This adds a `Responder` implementation for the `Markup` type, so you can return the result directly: This adds a `Responder` implementation for the `Markup` type,
so you can return the result directly:
```rust,no_run ```rust,no_run
#![feature(decl_macro)] #![feature(decl_macro)]
@ -113,7 +120,9 @@ fn main() {
# Rouille # Rouille
Unlike with the other frameworks, Rouille doesn't need any extra features at all! Calling `Response::html` on the rendered `Markup` will Just Work®. Unlike with the other frameworks,
Rouille doesn't need any extra features at all!
Calling `Response::html` on the rendered `Markup` will Just Work®.
```rust,no_run ```rust,no_run
use maud::html; use maud::html;