Skip to content

Commit

Permalink
Rewrite docs (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
lambda-fairy committed Nov 1, 2020
1 parent 39a866d commit 3af1397
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 201 deletions.
2 changes: 1 addition & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
slugs := index getting-started basic-syntax dynamic-content partials control-structures traits web-frameworks faq
slugs := index getting-started text-escaping elements-attributes splices-toggles control-structures partials render-trait web-frameworks faq

slug_to_md = content/$(1).md
slug_to_html = site/$(1).html
Expand Down
163 changes: 0 additions & 163 deletions docs/content/basic-syntax.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/content/control-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ html! {
}
```

`@if let` is supported as well. It works as you'd expect:
`@if let` is supported as well:

```rust
let user = Some("Pinkie Pie");
Expand Down
101 changes: 101 additions & 0 deletions docs/content/elements-attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Elements and attributes

## Elements: `p`

Write an element using curly braces: `p { ... }`.

Terminate a void element using a semicolon: `br;`. Note that the result will be rendered with HTML syntax – `<br>` not `<br />`.

```rust
html! {
h1 { "Poem" }
p {
"Rock, you are a rock."
br;
"Gray, you are gray,"
br;
"Like a rock, which you are."
br;
"Rock."
}
}
```

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

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

## Custom elements

Maud also supports [custom elements].

```rust
html! {
blog-post {
title { "My blog" }
}
}
```

[custom elements]: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements

## 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.

```rust
html! {
ul {
li {
a href="about:blank" { "Apple Bloom" }
}
li class="lower-middle" {
"Sweetie Belle"
}
li dir="rtl" {
"Scootaloo "
small { "(also a chicken)" }
}
}
}
```

## Empty attributes: `checked?`

Declare an empty attribute using a `?` suffix: `checked?`.

```rust
html! {
form {
input type="checkbox" name="cupcakes" checked?;
" "
label for="cupcakes" { "Do you like cupcakes?" }
}
}
```

## 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:

```rust
html! {
input#cannon.big.scary.bright-red type="button" value="Launch Party Cannon";
}
```

## Implicit `div` elements

If the element name is omitted, but there is a class or ID, then it is assumed to be a `div`.

```rust
html! {
#main {
"Main content!"
}
}
```
59 changes: 48 additions & 11 deletions docs/content/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,73 @@

## What is the origin of the name "Maud"?

Maud is named after a [character](http://mlp.wikia.com/wiki/Maud_Pie) from *My Little Pony: Friendship is Magic*. It does not refer to the [poem](https://en.wikipedia.org/wiki/Maud_and_other_poems) by Alfred Tennyson, though other people have brought that up in the past.
Maud is named after a [character] from *My Little Pony: Friendship is Magic*.
It does not refer to the [poem] by Alfred Tennyson,
though other people have brought that up in the past.

Here are some reasons why I chose this name:

* "Maud" shares three letters with "markup";

* The library is efficient and austere, like the character;

* Google used to maintain a site called ["HTML5 Rocks"](https://techcrunch.com/2010/06/22/html5rocks-google/), and Maud (the character) is a geologist.
* Google used to maintain a site called ["HTML5 Rocks"],
and Maud (the character) is a geologist.

[character]: http://mlp.wikia.com/wiki/Maud_Pie
[poem]: https://en.wikipedia.org/wiki/Maud_and_other_poems
["HTML5 Rocks"]: https://techcrunch.com/2010/06/22/html5rocks-google/

## Why does `html!` always allocate a `String`? Wouldn't it be more efficient if it wrote to a handle directly?

Good question! In fact, Maud did work this way in the past.

Sadly, that kind of thing didn't work out that well in practice. Having to pass the handle around made templates hard to compose, which is important in any non-trivial project. Furthermore, Iron (and other middleware frameworks) likes to take ownership of the response body, so we'd need to do some closure gymnastics to get everything to work together. To put the nail in the coffin, benchmarks showed that a `String` based solution is actually faster than one which avoids allocations.

For these reasons, I changed `html!` to return a `String` in version 0.11.
But it's hard to support buffer reuse in an ergonomic way.
The approaches I tried
either involved too much boilerplate,
or caused mysterious lifetime issues,
or both.
Moreover, Maud's allocation pattern—with small, short-lived buffers—follow the fast path in modern allocators.
These reasons are why I changed `html!` to return a `String` in version 0.11.

That said,
Rust has changed a lot since then,
and some of those old assumptions
might no longer hold today.
So this decision could be revisited
prior to the 1.0 release.

## Why is Maud written as a procedural macro? Can't it use `macro_rules!` instead?

This is certainly possible, and in fact the [Horrorshow](https://github.com/Stebalien/horrorshow-rs) library works this way.
This is certainly possible, and indeed the [Horrorshow] library works this way.

I use procedural macros because they are more flexible. There are some syntax constructs in Maud that cannot be parsed with `macro_rules!`; better diagnostics are a bonus as well.
I use procedural macros because they are more flexible.
There are some syntax constructs in Maud that are hard to parse with `macro_rules!`;
better diagnostics are a bonus as well.

[Horrorshow]: https://github.com/Stebalien/horrorshow-rs

## Maud has had a lot of releases so far. When will it reach 1.0?

I plan to make a 1.0 release when the library can be used on stable Rust.
I originally planned to cut a 1.0
after implementing stable support.
But now that's happened,
I've realized that there are a couple design questions
that I'd like to resolve
before marking that milestone.
Expect a blog post on this topic Very Soon®.

## Why doesn't Maud implement [context-aware escaping]?

## Why doesn't Maud implement [context-aware escaping](https://security.googleblog.com/2009/03/reducing-xss-by-way-of-automatic.html)?
I agree that context-aware escaping is very important,
especially for the kind of small-scale development
that Maud is used for.
But it's a complex feature,
with security implications,
so I want to take the time
to get it right.

If a project follows best practices in separating HTML and CSS/JavaScript, then context-aware escaping is unnecessary.
Please follow [#181] for the latest developments!

Google uses context-aware escaping because it has a large, decades-old code base, much of it written before these best practices were well known. Any project that uses Maud is neither large nor decades-old, and so should not have the need for this feature.
[context-aware escaping]: https://security.googleblog.com/2009/03/reducing-xss-by-way-of-automatic.html
[#181]: https://github.com/lambda-fairy/maud/issues/181
Loading

0 comments on commit 3af1397

Please sign in to comment.