1 | use crate::context::Context; |
2 | use crate::error::RenderError; |
3 | use crate::helpers::{HelperDef, HelperResult}; |
4 | use crate::json::value::JsonTruthy; |
5 | use crate::output::Output; |
6 | use crate::registry::Registry; |
7 | use crate::render::{Helper, RenderContext, Renderable}; |
8 | |
9 | #[derive (Clone, Copy)] |
10 | pub struct IfHelper { |
11 | positive: bool, |
12 | } |
13 | |
14 | impl HelperDef for IfHelper { |
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 \"if \"" ))?; |
26 | let include_zero = h |
27 | .hash_get("includeZero" ) |
28 | .and_then(|v| v.value().as_bool()) |
29 | .unwrap_or(false); |
30 | |
31 | let mut value = param.value().is_truthy(include_zero); |
32 | |
33 | if !self.positive { |
34 | value = !value; |
35 | } |
36 | |
37 | let tmpl = if value { h.template() } else { h.inverse() }; |
38 | match tmpl { |
39 | Some(t) => t.render(r, ctx, rc, out), |
40 | None => Ok(()), |
41 | } |
42 | } |
43 | } |
44 | |
45 | pub static IF_HELPER: IfHelper = IfHelper { positive: true }; |
46 | pub static UNLESS_HELPER: IfHelper = IfHelper { positive: false }; |
47 | |
48 | #[cfg (test)] |
49 | mod test { |
50 | use crate::helpers::WITH_HELPER; |
51 | use crate::registry::Registry; |
52 | use serde_json::value::Value as Json; |
53 | use std::str::FromStr; |
54 | |
55 | #[test ] |
56 | fn test_if() { |
57 | let mut handlebars = Registry::new(); |
58 | assert!(handlebars |
59 | .register_template_string("t0" , "{{#if this}}hello{{/if}}" ) |
60 | .is_ok()); |
61 | assert!(handlebars |
62 | .register_template_string("t1" , "{{#unless this}}hello{{else}}world{{/unless}}" ) |
63 | .is_ok()); |
64 | |
65 | let r0 = handlebars.render("t0" , &true); |
66 | assert_eq!(r0.ok().unwrap(), "hello" .to_string()); |
67 | |
68 | let r1 = handlebars.render("t1" , &true); |
69 | assert_eq!(r1.ok().unwrap(), "world" .to_string()); |
70 | |
71 | let r2 = handlebars.render("t0" , &false); |
72 | assert_eq!(r2.ok().unwrap(), "" .to_string()); |
73 | } |
74 | |
75 | #[test ] |
76 | fn test_if_context() { |
77 | let json_str = r#"{"a":{"b":99,"c":{"d": true}}}"# ; |
78 | let data = Json::from_str(json_str).unwrap(); |
79 | |
80 | let mut handlebars = Registry::new(); |
81 | handlebars.register_helper("with" , Box::new(WITH_HELPER)); |
82 | assert!(handlebars |
83 | .register_template_string("t0" , "{{#if a.c.d}}hello {{a.b}}{{/if}}" ) |
84 | .is_ok()); |
85 | assert!(handlebars |
86 | .register_template_string( |
87 | "t1" , |
88 | "{{#with a}}{{#if c.d}}hello {{../a.b}}{{/if}}{{/with}}" |
89 | ) |
90 | .is_ok()); |
91 | |
92 | let r0 = handlebars.render("t0" , &data); |
93 | assert_eq!(r0.unwrap(), "hello 99" .to_string()); |
94 | |
95 | let r1 = handlebars.render("t1" , &data); |
96 | assert_eq!(r1.unwrap(), "hello 99" .to_string()); |
97 | } |
98 | |
99 | #[test ] |
100 | fn test_if_include_zero() { |
101 | use std::f64; |
102 | let handlebars = Registry::new(); |
103 | |
104 | assert_eq!( |
105 | "0" .to_owned(), |
106 | handlebars |
107 | .render_template("{{#if a}}1{{else}}0{{/if}}" , &json!({"a" : 0})) |
108 | .unwrap() |
109 | ); |
110 | assert_eq!( |
111 | "1" .to_owned(), |
112 | handlebars |
113 | .render_template( |
114 | "{{#if a includeZero=true}}1{{else}}0{{/if}}" , |
115 | &json!({"a" : 0}) |
116 | ) |
117 | .unwrap() |
118 | ); |
119 | assert_eq!( |
120 | "0" .to_owned(), |
121 | handlebars |
122 | .render_template( |
123 | "{{#if a includeZero=true}}1{{else}}0{{/if}}" , |
124 | &json!({ "a" : f64::NAN }) |
125 | ) |
126 | .unwrap() |
127 | ); |
128 | } |
129 | |
130 | #[test ] |
131 | fn test_invisible_line_stripping() { |
132 | let hbs = Registry::new(); |
133 | assert_eq!( |
134 | "yes \n" , |
135 | hbs.render_template("{{#if a}} \nyes \n{{/if}} \n" , &json!({"a" : true})) |
136 | .unwrap() |
137 | ); |
138 | |
139 | assert_eq!( |
140 | "yes \r\n" , |
141 | hbs.render_template("{{#if a}} \r\nyes \r\n{{/if}} \r\n" , &json!({"a" : true})) |
142 | .unwrap() |
143 | ); |
144 | |
145 | assert_eq!( |
146 | "x \ny" , |
147 | hbs.render_template("{{#if a}}x{{/if}} \ny" , &json!({"a" : true})) |
148 | .unwrap() |
149 | ); |
150 | |
151 | assert_eq!( |
152 | "y \nz" , |
153 | hbs.render_template("{{#if a}} \nx \n{{^}} \ny \n{{/if}} \nz" , &json!({"a" : false})) |
154 | .unwrap() |
155 | ); |
156 | |
157 | assert_eq!( |
158 | r#"yes |
159 | foo |
160 | bar |
161 | baz"# , |
162 | hbs.render_template( |
163 | r#"yes |
164 | {{#if true}} |
165 | foo |
166 | bar |
167 | {{/if}} |
168 | baz"# , |
169 | &json!({}) |
170 | ) |
171 | .unwrap() |
172 | ); |
173 | |
174 | assert_eq!( |
175 | r#" foo |
176 | bar |
177 | baz"# , |
178 | hbs.render_template( |
179 | r#" {{#if true}} |
180 | foo |
181 | bar |
182 | {{/if}} |
183 | baz"# , |
184 | &json!({}) |
185 | ) |
186 | .unwrap() |
187 | ); |
188 | } |
189 | } |
190 | |