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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
//! Documentation of TinyTemplate's template syntax.
//!
//! ### Context Types
//!
//! TinyTemplate uses `serde_json`'s Value structure to represent the context. Therefore, any
//! `Serializable` structure can be used as a context. All values in such structures are mapped to
//! their JSON representations - booleans, numbers, strings, arrays, objects and nulls.
//!
//! ### Values
//!
//! Template values are marked with `{...}`. For example, this will look up the "name" field in
//! the context structure and insert it into the rendered string:
//!
//! ```text
//! Hello, {name}, how are you?
//! ```
//!
//! Optionally, a value formatter may be provided. One formatter, "unescaped", is provided by
//! default. Any other formatters must be registered with the
//! [`TinyTemplate.add_formatter`](../struct.TinyTemplate.html#method.add_formatter)
//! function prior to rendering or an error will be generated. This will call the formatter function
//! registered as "percent_formatter" with the value of the "percentage" field:
//!
//! ```text
//! Give it {percentage | percent_formatter}!
//! ```
//!
//! The value may be a dotted path through a hierarchy of context objects. This will look up the
//! "friend" field in the context structure, then substitute the "name" field from the "friend"
//! object.
//!
//! ```text
//! And hello to {friend.name} as well!
//! ```
//!
//! Additionally, you may use the `@root` keyword to refer to the root object of your context.
//! Since TinyTemplate can't normally print complex context objects, this is only useful if the
//! context is a simple object like an integer or string.
//!
//! ### Conditionals
//!
//! TinyTemplate blocks are marked with `{{...}}` - double-braces where values are single-braces.
//!
//! Conditionals are denoted by "{{ if path }}...{{ else }}...{{ endif }}". The Else block is
//! optional. Else-if is not currently supported. If "path" evaluates to a truthy expression
//! (true if boolean, non-zero if numeric, non-empty for strings and arrays, and non-null for
//! objects) then the section of the template between "if" and "else" is evaluated, otherwise the
//! section between "else" and "endif" (if present) is evaluated.
//!
//! ```text
//! {{ if user.is_birthday }}
//! Happy Birthday!
//! {{ else }}
//! Have a nice day!
//! {{ endif }}
//! ```
//!
//! The condition can be negated by using "{{ if not path }}":
//!
//! ```text
//! {{ if not user.is_birthday }}
//! Have a nice day!
//! {{ else }}
//! Happy Birthday!
//! {{ endif }}
//! ```
//!
//! If desired, the `@root` keyword can be used to branch on the root context object.
//!
//! ### Loops
//!
//! TinyTemplate supports iterating over the values of arrays. Only arrays are supported. Loops
//! are denoted by "{{ for value_name in value.path }}...{{ endfor }}". The section of the template between
//! the two tags will be executed once for each value in the array denoted by "value.path".
//!
//! ```text
//! Hello to {{ for name in guests }}
//! {name}
//! {{ endfor }}
//! ```
//!
//! If the iteration value chosen in the "for" tag is the same as that of a regular context value,
//! the name in the tag will shadow the context value for the scope of the loop. For nested loops,
//! inner loops will shadow the values of outer loops.
//!
//! ```text
//! {{ for person in guests }}
//! Hello to {person}{{ for person in person.friends }} and your friend {person}{{ endfor }}
//! {{ endfor }}
//! ```
//!
//! There are three special values which are available within a loop:
//!
//! * `@index` - zero-based index of the current value within the array.
//! * `@first` - true if this is the first iteration of the loop, otherwise false.
//! * `@last` - true if this is the last iteration of the loop, otherwise false.
//!
//! ```text
//! Hello to {{ for name in guests -}}
//! { @index }. {name},
//! {{- endfor }}
//! ```
//!
//!
//! In case of nested loops, these values refer to the innermost loop which contains them.
//!
//! If the root context object is an array, the `@root` keyword can be used to iterate over the
//! root object.
//!
//! ### With Blocks
//!
//! Templates can use with blocks to partially shadows the outer context, the same way that
//! for-loops do. These are formed like so:
//!
//! "{{ with path.to.value as name }}..{{ endwith }}""
//!
//! For example:
//!
//! ```text
//! {{ with person.spouse as s }}
//! Hello { s.name }!
//! {{ endwith }}
//! ```
//!
//! This looks up "person.spouse" and adds that to the context as "s" within the block. Only the
//! name "s" is shadowed within the with block and otherwise the outer context is still accessible.
//!
//! ### Trimming Whitespace
//!
//! If a block tag, comment or value tag includes a "-" character at the start, the trailing
//! whitespace of the previous text section will be skipped in the output. Likewise, if the tag
//! ends with a "-", the leading whitespace of the following text will be skipped.
//!
//! ```text
//! Hello { friend.name -}
//! , how are you?
//!
//! {{- if status.good }} I am fine. {{- endif }}
//! ```
//!
//! This will print "Hello friend, how are you? I am fine." without the newlines or extra spaces.
//!
//! ### Calling other Templates
//!
//! Templates may call other templates by name. The other template must have been registered using
//! the [`TinyTemplate.add_template`](../struct.TinyTemplate.html#method.add_template) function
//! before rendering or an error will be generated. This is done with the "call" tag:
//!
//! "{{ call template_name with path.to.context }}"
//!
//! The call tag has no closing tag. This will look up the "path.to.context" path in the current
//! context, then render the "template_name" template using the value at that path as the context
//! for the other template. The string produced by the called template is then inserted into the
//! output from the calling template. This can be used for a limited form of template code reuse.
//!
//! ### Comments
//!
//! Comments in the templates are denoted by "{# comment text #}". Comments will be skipped when
//! rendering the template, though whitespace adjacent to comments will not be stripped unless the
//! "-" is added. For example:
//!
//! ```text
//! Hello
//!
//! {#- This is a comment #} world!
//! ```
//!
//! This will print "Hello world!".
//!
//! ### Escaping Curly Braces
//!
//! If your template contains opening curly-braces (`{`), they must be escaped using a leading `\`
//! character. For example:
//!
//! ```text
//! h2 \{
//! font-size: {fontsize};
//! }
//! ```
//!
//! If using a string literal in rust source code, the `\` itself must be escaped, producing `\\{`.
//!
// There's nothing here, this module is solely for documentation.
|