1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! rustlavel-view: templating in the spirit of Blade, written from scratch.
//!
//! A template is parsed once into an AST and then interpreted. That choice is
//! what makes [`Engine::with_reload`] possible: with reload on, a designer
//! edits `resources/views/pages/home.rl.html`, refreshes the browser, and sees
//! the result without a recompile — the single ergonomic advantage Blade has
//! over compiled Rust templates, and the one worth keeping.
//!
//! ```ignore
//! use rustlavel_view::{Context, Engine};
//!
//! let engine = Engine::default().with_reload(!config.is_production());
//! let html = engine.render("pages.home", &Context::new().with("title", "Home"))?;
//! ```
//!
//! # The syntax
//!
//! ```html
//! {{ user.name }} escaped output — always, no opt-out
//! {!! post.body !!} raw output, for HTML you already trust
//! {{-- a note --}} stripped before rendering
//!
//! @if(user.admin) ... @elseif(user.editor) ... @else ... @endif
//! @foreach(posts as post) {{ loop.index }} {{ post.title }} @endforeach
//!
//! @extends("layouts.app")
//! @section("title", page.name)
//! @section("body") ... @endsection
//! @yield("body")
//! @include("parts.nav")
//! ```
//!
//! Inside `@foreach`, `loop` carries `index`, `iteration`, `first`, `last`, and
//! `count`. A structural directive alone on a line takes the line with it, so
//! the rendered HTML looks like HTML.
//!
//! `@include` renders a partial in place, with the scope it was included from —
//! a partial used inside a loop can read the loop's item and its `loop`
//! variable, which is what makes `@include` worth having at all.
//!
//! # What is missing on purpose
//!
//! `@php` does not exist and will not. A template that can run code stops being
//! reviewable as markup, hides logic from the compiler and from tests, and
//! turns "just a view change" into a deployment risk. Compute the value in
//! Rust, put it in the [`Context`], and render it. Templates using `@php` are
//! rejected with an error that says exactly this.
//!
//! Expressions are equally limited — paths, literals, comparisons, `&&`, `||`,
//! `!` — for the same reason. There is no arithmetic and there are no calls.
//!
//! # Escaping
//!
//! `{{ }}` escapes `&`, `<`, `>`, `"` and `'`, every time, with no way to turn
//! it off. Markup that is genuinely trusted asks for [`escape`]'s absence out
//! loud with `{!! !!}`, which makes the dangerous case the one that stands out
//! in a diff.
pub use ;
pub use ;
pub use ;
pub use escape;
pub use ;
pub use ;