]> git.proxmox.com Git - rustc.git/blame - vendor/handlebars/src/directives/mod.rs
New upstream version 1.42.0+dfsg0+pve1
[rustc.git] / vendor / handlebars / src / directives / mod.rs
CommitLineData
416331ca
XL
1use crate::context::Context;
2use crate::error::RenderError;
3use crate::registry::Registry;
4use crate::render::{Directive, RenderContext};
8bb4bdeb
XL
5
6pub use self::inline::INLINE_DIRECTIVE;
7
9fa01778
XL
8pub type DirectiveResult = Result<(), RenderError>;
9
8bb4bdeb
XL
10/// Decorator Definition
11///
12/// Implement this trait to define your own decorators or directives. Currently
13/// decorator shares same definition with helper.
14///
9fa01778 15/// In handlebars, it is recommended to use decorator to change context data and update helper
7cac9316 16/// definition.
8bb4bdeb
XL
17/// ## Updating context data
18///
19/// In decorator, you can change some context data your are about to render.
20///
041b39d2 21/// ```
8bb4bdeb 22/// use handlebars::*;
8bb4bdeb 23///
9fa01778 24/// fn update_data<'reg: 'rc, 'rc>(_: &Decorator, _: &Handlebars, ctx: &Context, rc: &mut RenderContext)
7cac9316 25/// -> Result<(), RenderError> {
8bb4bdeb 26/// // modify json object
9fa01778
XL
27/// let mut new_ctx = ctx.clone();
28/// {
29/// let mut data = new_ctx.data_mut();
30/// if let Some(ref mut m) = data.as_object_mut() {
31/// m.insert("hello".to_string(), to_json("world"));
32/// }
8bb4bdeb 33/// }
9fa01778 34/// rc.set_context(new_ctx);
8bb4bdeb
XL
35/// Ok(())
36/// }
37///
38/// ```
39///
40/// ## Define local helper
41///
42/// You can override behavior of a helper from position of decorator to the end of template.
43///
44/// ```
45/// use handlebars::*;
46///
9fa01778 47/// fn override_helper(_: &Decorator, _: &Handlebars, _: &Context, rc: &mut RenderContext)
7cac9316 48/// -> Result<(), RenderError> {
416331ca 49/// let new_helper = |h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut dyn Output|
7cac9316 50/// -> Result<(), RenderError> {
8bb4bdeb
XL
51/// // your helper logic
52/// Ok(())
53/// };
54/// rc.register_local_helper("distance", Box::new(new_helper));
55/// Ok(())
56/// }
57/// ```
58///
59pub trait DirectiveDef: Send + Sync {
9fa01778
XL
60 fn call<'reg: 'rc, 'rc>(
61 &'reg self,
62 d: &Directive<'reg, 'rc>,
63 r: &'reg Registry,
64 ctx: &'rc Context,
65 rc: &mut RenderContext<'reg>,
66 ) -> DirectiveResult;
8bb4bdeb
XL
67}
68
69/// implement DirectiveDef for bare function so we can use function as directive
ea8adc8c 70impl<
9fa01778
XL
71 F: Send
72 + Sync
416331ca
XL
73 + for<'reg, 'rc> Fn(
74 &Directive<'reg, 'rc>,
75 &'reg Registry,
76 &'rc Context,
77 &mut RenderContext,
78 ) -> DirectiveResult,
9fa01778 79 > DirectiveDef for F
83c7162d 80{
9fa01778
XL
81 fn call<'reg: 'rc, 'rc>(
82 &'reg self,
83 d: &Directive<'reg, 'rc>,
84 reg: &'reg Registry,
85 ctx: &'rc Context,
86 rc: &mut RenderContext,
87 ) -> DirectiveResult {
88 (*self)(d, reg, ctx, rc)
8bb4bdeb
XL
89 }
90}
91
92mod inline;
93
94#[cfg(test)]
95mod test {
416331ca
XL
96 use crate::context::Context;
97 use crate::error::RenderError;
98 use crate::output::Output;
99 use crate::registry::Registry;
100 use crate::render::{Directive, Helper, RenderContext};
101 use crate::value::{as_string, to_json};
8bb4bdeb
XL
102
103 #[test]
104 fn test_register_decorator() {
105 let mut handlebars = Registry::new();
ea8adc8c
XL
106 handlebars
107 .register_template_string("t0", "{{*foo}}".to_string())
108 .unwrap();
8bb4bdeb 109
83c7162d 110 let data = btreemap! {
8bb4bdeb
XL
111 "hello".to_string() => "world".to_string()
112 };
113
114 assert!(handlebars.render("t0", &data).is_err());
115
ea8adc8c
XL
116 handlebars.register_decorator(
117 "foo",
83c7162d 118 Box::new(
9fa01778
XL
119 |_: &Directive,
120 _: &Registry,
121 _: &Context,
122 _: &mut RenderContext|
123 -> Result<(), RenderError> { Ok(()) },
83c7162d 124 ),
ea8adc8c 125 );
8bb4bdeb
XL
126 assert_eq!(handlebars.render("t0", &data).ok().unwrap(), "".to_string());
127 }
128
9fa01778 129 // updating context data disabled for now
8bb4bdeb
XL
130 #[test]
131 fn test_update_data_with_decorator() {
132 let mut handlebars = Registry::new();
ea8adc8c
XL
133 handlebars
134 .register_template_string("t0", "{{hello}}{{*foo}}{{hello}}".to_string())
7cac9316 135 .unwrap();
8bb4bdeb 136
83c7162d 137 let data = btreemap! {
8bb4bdeb
XL
138 "hello".to_string() => "world".to_string()
139 };
140
ea8adc8c
XL
141 handlebars.register_decorator(
142 "foo",
83c7162d 143 Box::new(
9fa01778
XL
144 |_: &Directive,
145 _: &Registry,
146 ctx: &Context,
147 rc: &mut RenderContext|
148 -> Result<(), RenderError> {
83c7162d 149 // modify json object
9fa01778
XL
150 let mut new_ctx = ctx.clone();
151 {
152 let data = new_ctx.data_mut();
153 if let Some(ref mut m) = data.as_object_mut().as_mut() {
154 m.insert("hello".to_string(), to_json("war"));
155 }
83c7162d 156 }
9fa01778 157 rc.set_context(new_ctx);
83c7162d
XL
158 Ok(())
159 },
160 ),
ea8adc8c
XL
161 );
162
163 assert_eq!(
164 handlebars.render("t0", &data).ok().unwrap(),
165 "worldwar".to_string()
166 );
8bb4bdeb
XL
167
168 let data2 = 0;
ea8adc8c
XL
169 handlebars.register_decorator(
170 "bar",
83c7162d 171 Box::new(
9fa01778
XL
172 |d: &Directive,
173 _: &Registry,
174 _: &Context,
175 rc: &mut RenderContext|
176 -> Result<(), RenderError> {
83c7162d 177 // modify value
9fa01778
XL
178 let v = d
179 .param(0)
83c7162d
XL
180 .and_then(|v| Context::wraps(v.value()).ok())
181 .unwrap_or(Context::null());
9fa01778 182 rc.set_context(v);
83c7162d
XL
183 Ok(())
184 },
185 ),
ea8adc8c
XL
186 );
187 handlebars
188 .register_template_string("t1", "{{this}}{{*bar 1}}{{this}}".to_string())
7cac9316 189 .unwrap();
ea8adc8c
XL
190 assert_eq!(
191 handlebars.render("t1", &data2).ok().unwrap(),
192 "01".to_string()
193 );
194
195 handlebars
196 .register_template_string(
197 "t2",
198 "{{this}}{{*bar \"string_literal\"}}{{this}}".to_string(),
199 )
7cac9316 200 .unwrap();
ea8adc8c
XL
201 assert_eq!(
202 handlebars.render("t2", &data2).ok().unwrap(),
203 "0string_literal".to_string()
204 );
8bb4bdeb 205
ea8adc8c
XL
206 handlebars
207 .register_template_string("t3", "{{this}}{{*bar}}{{this}}".to_string())
208 .unwrap();
209 assert_eq!(
210 handlebars.render("t3", &data2).ok().unwrap(),
211 "0".to_string()
212 );
8bb4bdeb
XL
213 }
214
215 #[test]
216 fn test_local_helper_with_decorator() {
217 let mut handlebars = Registry::new();
ea8adc8c
XL
218 handlebars
219 .register_template_string(
220 "t0",
221 "{{distance 4.5}},{{*foo \"miles\"}}{{distance 10.1}},{{*bar}}{{distance 3.4}}"
222 .to_string(),
223 )
224 .unwrap();
225
226 handlebars.register_helper(
227 "distance",
83c7162d 228 Box::new(
9fa01778
XL
229 |h: &Helper,
230 _: &Registry,
231 _: &Context,
232 _: &mut RenderContext,
416331ca 233 out: &mut dyn Output|
9fa01778 234 -> Result<(), RenderError> {
ea8adc8c 235 let s = format!(
83c7162d 236 "{}m",
9fa01778
XL
237 h.param(0)
238 .as_ref()
239 .map(|v| v.value())
240 .unwrap_or(&to_json(0))
ea8adc8c 241 );
9fa01778 242 out.write(s.as_ref())?;
ea8adc8c 243 Ok(())
83c7162d
XL
244 },
245 ),
246 );
247 handlebars.register_decorator(
248 "foo",
249 Box::new(
9fa01778
XL
250 |d: &Directive,
251 _: &Registry,
252 _: &Context,
253 rc: &mut RenderContext|
254 -> Result<(), RenderError> {
255 let new_unit = d
256 .param(0)
257 .as_ref()
83c7162d
XL
258 .and_then(|v| as_string(v.value()))
259 .unwrap_or("")
260 .to_owned();
261 let new_helper = move |h: &Helper,
262 _: &Registry,
9fa01778
XL
263 _: &Context,
264 _: &mut RenderContext,
416331ca 265 out: &mut dyn Output|
83c7162d
XL
266 -> Result<(), RenderError> {
267 let s = format!(
268 "{}{}",
9fa01778
XL
269 h.param(0)
270 .as_ref()
271 .map(|v| v.value())
272 .unwrap_or(&to_json(0)),
83c7162d
XL
273 new_unit
274 );
9fa01778 275 out.write(s.as_ref())?;
83c7162d
XL
276 Ok(())
277 };
278
279 rc.register_local_helper("distance", Box::new(new_helper));
280 Ok(())
281 },
282 ),
ea8adc8c
XL
283 );
284 handlebars.register_decorator(
285 "bar",
83c7162d 286 Box::new(
9fa01778
XL
287 |_: &Directive,
288 _: &Registry,
289 _: &Context,
290 rc: &mut RenderContext|
291 -> Result<(), RenderError> {
83c7162d
XL
292 rc.unregister_local_helper("distance");
293 Ok(())
294 },
295 ),
ea8adc8c
XL
296 );
297 assert_eq!(
298 handlebars.render("t0", &0).ok().unwrap(),
299 "4.5m,10.1miles,3.4m".to_owned()
300 );
8bb4bdeb
XL
301 }
302}