]> git.proxmox.com Git - rustc.git/blob - vendor/handlebars/src/helpers/helper_with.rs
4b68b783e22e6273f1f293489ab6a2bc12e09233
[rustc.git] / vendor / handlebars / src / helpers / helper_with.rs
1 use super::block_util::create_block;
2 use crate::block::BlockParams;
3 use crate::context::Context;
4 use crate::error::RenderError;
5 use crate::helpers::{HelperDef, HelperResult};
6 use crate::json::value::JsonTruthy;
7 use crate::output::Output;
8 use crate::registry::Registry;
9 use crate::render::{Helper, RenderContext, Renderable};
10
11 #[derive(Clone, Copy)]
12 pub struct WithHelper;
13
14 impl HelperDef for WithHelper {
15 fn call<'reg: 'rc, 'rc>(
16 &self,
17 h: &Helper<'reg, 'rc>,
18 r: &'reg Registry<'reg>,
19 ctx: &'rc Context,
20 rc: &mut RenderContext<'reg, 'rc>,
21 out: &mut dyn Output,
22 ) -> HelperResult {
23 let param = h
24 .param(0)
25 .ok_or_else(|| RenderError::new("Param not found for helper \"with\""))?;
26
27 let not_empty = param.value().is_truthy(false);
28 let template = if not_empty { h.template() } else { h.inverse() };
29
30 if not_empty {
31 let mut block = create_block(&param)?;
32
33 if let Some(block_param) = h.block_param() {
34 let mut params = BlockParams::new();
35 if param.context_path().is_some() {
36 params.add_path(block_param, Vec::with_capacity(0))?;
37 } else {
38 params.add_value(block_param, param.value().clone())?;
39 }
40
41 block.set_block_params(params);
42 }
43
44 rc.push_block(block);
45 }
46
47 let result = match template {
48 Some(t) => t.render(r, ctx, rc, out),
49 None => Ok(()),
50 };
51
52 if not_empty {
53 rc.pop_block();
54 }
55 result
56 }
57 }
58
59 pub static WITH_HELPER: WithHelper = WithHelper;
60
61 #[cfg(test)]
62 mod test {
63 use crate::json::value::to_json;
64 use crate::registry::Registry;
65
66 #[derive(Serialize)]
67 struct Address {
68 city: String,
69 country: String,
70 }
71
72 #[derive(Serialize)]
73 struct Person {
74 name: String,
75 age: i16,
76 addr: Address,
77 titles: Vec<String>,
78 }
79
80 #[test]
81 fn test_with() {
82 let addr = Address {
83 city: "Beijing".to_string(),
84 country: "China".to_string(),
85 };
86
87 let person = Person {
88 name: "Ning Sun".to_string(),
89 age: 27,
90 addr,
91 titles: vec!["programmer".to_string(), "cartographier".to_string()],
92 };
93
94 let mut handlebars = Registry::new();
95 assert!(handlebars
96 .register_template_string("t0", "{{#with addr}}{{city}}{{/with}}")
97 .is_ok());
98 assert!(handlebars
99 .register_template_string("t1", "{{#with notfound}}hello{{else}}world{{/with}}")
100 .is_ok());
101 assert!(handlebars
102 .register_template_string("t2", "{{#with addr/country}}{{this}}{{/with}}")
103 .is_ok());
104
105 let r0 = handlebars.render("t0", &person);
106 assert_eq!(r0.ok().unwrap(), "Beijing".to_string());
107
108 let r1 = handlebars.render("t1", &person);
109 assert_eq!(r1.ok().unwrap(), "world".to_string());
110
111 let r2 = handlebars.render("t2", &person);
112 assert_eq!(r2.ok().unwrap(), "China".to_string());
113 }
114
115 #[test]
116 fn test_with_block_param() {
117 let addr = Address {
118 city: "Beijing".to_string(),
119 country: "China".to_string(),
120 };
121
122 let person = Person {
123 name: "Ning Sun".to_string(),
124 age: 27,
125 addr,
126 titles: vec!["programmer".to_string(), "cartographier".to_string()],
127 };
128
129 let mut handlebars = Registry::new();
130 assert!(handlebars
131 .register_template_string("t0", "{{#with addr as |a|}}{{a.city}}{{/with}}")
132 .is_ok());
133 assert!(handlebars
134 .register_template_string("t1", "{{#with notfound as |c|}}hello{{else}}world{{/with}}")
135 .is_ok());
136 assert!(handlebars
137 .register_template_string("t2", "{{#with addr/country as |t|}}{{t}}{{/with}}")
138 .is_ok());
139
140 let r0 = handlebars.render("t0", &person);
141 assert_eq!(r0.ok().unwrap(), "Beijing".to_string());
142
143 let r1 = handlebars.render("t1", &person);
144 assert_eq!(r1.ok().unwrap(), "world".to_string());
145
146 let r2 = handlebars.render("t2", &person);
147 assert_eq!(r2.ok().unwrap(), "China".to_string());
148 }
149
150 #[test]
151 fn test_with_in_each() {
152 let addr = Address {
153 city: "Beijing".to_string(),
154 country: "China".to_string(),
155 };
156
157 let person = Person {
158 name: "Ning Sun".to_string(),
159 age: 27,
160 addr,
161 titles: vec!["programmer".to_string(), "cartographier".to_string()],
162 };
163
164 let addr2 = Address {
165 city: "Beijing".to_string(),
166 country: "China".to_string(),
167 };
168
169 let person2 = Person {
170 name: "Ning Sun".to_string(),
171 age: 27,
172 addr: addr2,
173 titles: vec!["programmer".to_string(), "cartographier".to_string()],
174 };
175
176 let people = vec![person, person2];
177
178 let mut handlebars = Registry::new();
179 assert!(handlebars
180 .register_template_string(
181 "t0",
182 "{{#each this}}{{#with addr}}{{city}}{{/with}}{{/each}}"
183 )
184 .is_ok());
185 assert!(handlebars
186 .register_template_string(
187 "t1",
188 "{{#each this}}{{#with addr}}{{../age}}{{/with}}{{/each}}"
189 )
190 .is_ok());
191 assert!(handlebars
192 .register_template_string(
193 "t2",
194 "{{#each this}}{{#with addr}}{{@../index}}{{/with}}{{/each}}"
195 )
196 .is_ok());
197
198 let r0 = handlebars.render("t0", &people);
199 assert_eq!(r0.ok().unwrap(), "BeijingBeijing".to_string());
200
201 let r1 = handlebars.render("t1", &people);
202 assert_eq!(r1.ok().unwrap(), "2727".to_string());
203
204 let r2 = handlebars.render("t2", &people);
205 assert_eq!(r2.ok().unwrap(), "01".to_string());
206 }
207
208 #[test]
209 fn test_path_up() {
210 let mut handlebars = Registry::new();
211 assert!(handlebars
212 .register_template_string("t0", "{{#with a}}{{#with b}}{{../../d}}{{/with}}{{/with}}")
213 .is_ok());
214 let data = btreemap! {
215 "a".to_string() => to_json(&btreemap! {
216 "b".to_string() => vec![btreemap!{"c".to_string() => vec![1]}]
217 }),
218 "d".to_string() => to_json(1)
219 };
220
221 let r0 = handlebars.render("t0", &data);
222 assert_eq!(r0.ok().unwrap(), "1".to_string());
223 }
224
225 #[test]
226 fn test_else_context() {
227 let reg = Registry::new();
228 let template = "{{#with list}}A{{else}}{{foo}}{{/with}}";
229 let input = json!({"list": [], "foo": "bar"});
230 let rendered = reg.render_template(template, &input).unwrap();
231 assert_eq!("bar", rendered);
232 }
233
234 #[test]
235 fn test_derived_value() {
236 let hb = Registry::new();
237 let data = json!({"a": {"b": {"c": "d"}}});
238 let template = "{{#with (lookup a.b \"c\")}}{{this}}{{/with}}";
239 assert_eq!("d", hb.render_template(template, &data).unwrap());
240 }
241
242 #[test]
243 fn test_nested_derived_value() {
244 let hb = Registry::new();
245 let data = json!({"a": {"b": {"c": "d"}}});
246 let template = "{{#with (lookup a \"b\")}}{{#with this}}{{c}}{{/with}}{{/with}}";
247 assert_eq!("d", hb.render_template(template, &data).unwrap());
248 }
249 }