Using `#[template(source = "…")]` is tiresome, because you have to
escape the input. That makes it difficult to read, too. Using
`#[template(path = "…")` can be tiresome, too, if the code is small
and/or if you just want to prototype something.
This PR adds a third option to supply the source of a template: You can
supply the source in the comments of a template. This works similar to
doctest. Any <code>```rinja```</code> block gets extracted, and the
combined blocks are the source code of the template.
In generated code or macros, it might be useful to emit multiple
`#[template]` attributes. E.g.
```rust
#[template(source = "Hello!")]
#[template(ext = "txt")]
struct Hello;
```
The filters `|linebreaks`, `|linebreaksbr` and `|paragraphbreaks`
generate HTML code to be embedded in a page. Having to specify that the
output of these filters is `|safe` is cumbersome. Also, these filters
need to operate on already escaped HTML data. This could be done by
writing `{{ s|escape|linebreaks|safe }}`.
This PR does the input and output formatting escaping for the user. The
input gets escaped for HTML (invariant of the selected escaper), and the
output gets marked as HTML safe.
This PR reimplements the code generation for `{% filter %}` blocks, so
that the data is written directly into its destination writer, without
using a buffer. This way it behaves like a specialized
`{{ expr|filter1|filter2 }}` would, if the `expr` was a `Template` that
contained the body of the filter block.
By using codepoint entities like `'&'` → `"&"`, we have a much
smaller lookup table (58 bytes instead of 29× pointer size ~= 232
bytes). This makes the cache happy, and the benchmark run about ~20%
faster.
```text
$ cargo bench --bench escape
Escaping time: [3.4087 µs 3.4126 µs 3.4168 µs]
change: [-19.790% -19.580% -19.354%] (p = 0.00 < 0.05)
Performance has improved.
```
This PR configures the formatting with a few defaults that aid
readability, in my opinion. One drawback of adding this file is that
rustfmt uses unstable features, now, and you have to use nightly to run
it:
```sh
cargo +nightly fmt --all
```