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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! Macros for [`tour`] template
//!
//! # `tour::Template` Trait
//!
//! The goal is to generate `tour::Template` trait implementation.
//!
//! All code generation requires [`Template`] struct. To build it, requires [`Metadata`] and
//! [`File`].
//!
//! # [`Metadata`]
//!
//! `Metadata` contains template identity that explicitly set by user.
//!
//! `Metadata` can be represented by:
//!
//! - [`Attribute`], e.g. `#[template(path = "index.html")]`
//! - [`LayoutTempl`], e.g. `{{ layout "layout.html" }}`
//! - [`RenderTempl`], e.g. `{{ render "navbar.html" }}`
//! - [`UseTempl`], e.g. `{{ use "button.html" as Button }}`
//!
//! # [`File`]
//!
//! `File` contains the actual template content.
//!
//! `File` can be created using [`Metadata`].
//!
//! # Code generation
//!
//! For the `tour::Template` trait, code will be generated for the following methods:
//!
//! ## `render_into()`, `render_block_into()` and `contains_block()`
//!
//! `render_into()` is the main template rendering logic. Generated code includes:
//!
//! - destructured fields, for convenient
//! - `include_str!()` the template file, to trigger recompile when changed
//! - static content reparsing for runtime reload
//! - the main template content rendering
//!
//! `render_block_into()` contains the same code but for selected block only.
//!
//! Block can be rendered at runtime only when declared with the `pub` keyword.
//!
//! `contains_block()` contains basic check whether a block is available to be rendered at runtime.
//!
//! ## `size_hint()` and `size_hint_block()`
//!
//! `size_hint()` will calculate the lower and upper bounds of the rendered template length.
//!
//! `size_hint_block()` is the same but for selected block only.
//!
//! Note that currently, size hint calculation does not do any runtime check. So rendered template
//! may exceed the upper bounds. But lower bounds is pretty much accurate.
//!
//! Runtime check like an `if` branch expression that have been evaluated in struct field, can
//! produce much more accurate size hints. This will be improved in the future.
//!
//! For now, size hint is statically calculated. Its better than nothing.
//!
//! # External template
//!
//! Other external template that is referenced will also be generated.
//!
//! External template can be referenced by:
//!
//! - [`LayoutTempl`], e.g. `{{ layout "layout.html" }}`
//! - [`RenderTempl`], e.g. `{{ render "navbar.html" }}`
//! - [`UseTempl`], e.g. `{{ use "button.html" as Button }}`
//!
//! [`tour`]: <https://docs.rs/tour>
//! [`Template`]: data::Template
//! [`Metadata`]: metadata::Metadata
//! [`File`]: file::File
//! [`Attribute`]: syn::Attribute
//! [`LayoutTempl`]: syntax::LayoutTempl
//! [`RenderTempl`]: syntax::RenderTempl
//! [`UseTempl`]: syntax::UseTempl
// ===== Input =====
// ===== Data =====
// ===== Output =====