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