1 use std
::collections
::HashMap
;
3 use serde_json
::value
::Value
as Json
;
5 use crate::context
::{merge_json, Context}
;
6 use crate::error
::RenderError
;
7 use crate::json
::path
::Path
;
8 use crate::output
::Output
;
9 use crate::registry
::Registry
;
10 use crate::render
::{Decorator, Evaluable, RenderContext, Renderable}
;
11 use crate::template
::Template
;
13 fn render_partial
<'reg
: 'rc
, 'rc
>(
15 d
: &Decorator
<'reg
, 'rc
>,
16 r
: &'reg Registry
<'reg
>,
18 local_rc
: &mut RenderContext
<'reg
, 'rc
>,
20 ) -> Result
<(), RenderError
> {
21 // partial context path
22 if let Some(ref param_ctx
) = d
.param(0) {
23 if let (Some(p
), Some(block
)) = (param_ctx
.context_path(), local_rc
.block_mut()) {
24 *block
.base_path_mut() = p
.clone();
29 if let Some(t
) = d
.template() {
30 local_rc
.set_partial("@partial-block".to_owned(), t
);
33 let result
= if d
.hash().is_empty() {
34 t
.render(r
, ctx
, local_rc
, out
)
39 .map(|(k
, v
)| (k
, v
.value()))
40 .collect
::<HashMap
<&&str, &Json
>>();
41 let current_path
= Path
::current();
43 merge_json(local_rc
.evaluate2(ctx
, ¤t_path
)?
.as_json(), &hash_ctx
);
44 let ctx
= Context
::wraps(&partial_context
)?
;
45 let mut partial_rc
= local_rc
.new_for_block();
46 t
.render(r
, &ctx
, &mut partial_rc
, out
)
49 local_rc
.remove_partial("@partial-block");
54 pub fn expand_partial
<'reg
: 'rc
, 'rc
>(
55 d
: &Decorator
<'reg
, 'rc
>,
56 r
: &'reg Registry
<'reg
>,
58 rc
: &mut RenderContext
<'reg
, 'rc
>,
60 ) -> Result
<(), RenderError
> {
61 // try eval inline partials first
62 if let Some(t
) = d
.template() {
67 if rc
.is_current_template(tname
) {
68 return Err(RenderError
::new("Cannot include self in >"));
71 let partial
= rc
.get_partial(tname
);
75 let mut local_rc
= rc
.clone();
76 render_partial(&t
, d
, r
, ctx
, &mut local_rc
, out
)?
;
79 if let Some(t
) = r
.get_template(tname
).or_else(|| d
.template()) {
80 let mut local_rc
= rc
.clone();
81 render_partial(t
, d
, r
, ctx
, &mut local_rc
, out
)?
;
91 use crate::context
::Context
;
92 use crate::error
::RenderError
;
93 use crate::output
::Output
;
94 use crate::registry
::Registry
;
95 use crate::render
::{Helper, RenderContext}
;
99 let mut handlebars
= Registry
::new();
101 .register_template_string("t0", "{{> t1}}")
104 .register_template_string("t1", "{{this}}")
107 .register_template_string("t2", "{{#> t99}}not there{{/t99}}")
110 .register_template_string("t3", "{{#*inline \"t31\"}}{{this}}{{/inline}}{{> t31}}")
113 .register_template_string(
115 "{{#> t5}}{{#*inline \"nav\"}}navbar{{/inline}}{{/t5}}"
119 .register_template_string("t5", "include {{> nav}}")
122 .register_template_string("t6", "{{> t1 a}}")
125 .register_template_string(
127 "{{#*inline \"t71\"}}{{a}}{{/inline}}{{> t71 a=\"world\"}}"
130 assert
!(handlebars
.register_template_string("t8", "{{a}}").is_ok());
132 .register_template_string("t9", "{{> t8 a=2}}")
135 assert_eq
!(handlebars
.render("t0", &1).ok().unwrap(), "1".to_string());
137 handlebars
.render("t2", &1).ok().unwrap(),
138 "not there".to_string()
140 assert_eq
!(handlebars
.render("t3", &1).ok().unwrap(), "1".to_string());
142 handlebars
.render("t4", &1).ok().unwrap(),
143 "include navbar".to_string()
147 .render("t6", &btreemap
! {"a".to_string() => "2".to_string()}
)
153 handlebars
.render("t7", &1).ok().unwrap(),
156 assert_eq
!(handlebars
.render("t9", &1).ok().unwrap(), "2".to_string());
160 fn test_include_partial_block() {
161 let t0
= "hello {{> @partial-block}}";
162 let t1
= "{{#> t0}}inner {{this}}{{/t0}}";
164 let mut handlebars
= Registry
::new();
165 assert
!(handlebars
.register_template_string("t0", t0
).is_ok());
166 assert
!(handlebars
.register_template_string("t1", t1
).is_ok());
168 let r0
= handlebars
.render("t1", &true);
169 assert_eq
!(r0
.ok().unwrap(), "hello inner true".to_string());
173 fn test_self_inclusion() {
174 let t0
= "hello {{> t1}} {{> t0}}";
175 let t1
= "some template";
176 let mut handlebars
= Registry
::new();
177 assert
!(handlebars
.register_template_string("t0", t0
).is_ok());
178 assert
!(handlebars
.register_template_string("t1", t1
).is_ok());
180 let r0
= handlebars
.render("t0", &true);
181 assert
!(r0
.is_err());
185 fn test_issue_143() {
186 let main_template
= "one{{> two }}three{{> two }}";
187 let two_partial
= "--- two ---";
189 let mut handlebars
= Registry
::new();
191 .register_template_string("template", main_template
)
194 .register_template_string("two", two_partial
)
197 let r0
= handlebars
.render("template", &true);
198 assert_eq
!(r0
.ok().unwrap(), "one--- two ---three--- two ---");
202 fn test_hash_context_outscope() {
203 let main_template
= "In: {{> p a=2}} Out: {{a}}";
204 let p_partial
= "{{a}}";
206 let mut handlebars
= Registry
::new();
208 .register_template_string("template", main_template
)
210 assert
!(handlebars
.register_template_string("p", p_partial
).is_ok());
212 let r0
= handlebars
.render("template", &true);
213 assert_eq
!(r0
.ok().unwrap(), "In: 2 Out: ");
217 fn test_partial_context_hash() {
218 let mut hbs
= Registry
::new();
219 hbs
.register_template_string("one", "This is a test. {{> two name=\"fred\" }}")
221 hbs
.register_template_string("two", "Lets test {{name}}")
224 "This is a test. Lets test fred",
225 hbs
.render("one", &0).unwrap()
230 fn test_partial_subexpression_context_hash() {
231 let mut hbs
= Registry
::new();
232 hbs
.register_template_string("one", "This is a test. {{> (x @root) name=\"fred\" }}")
234 hbs
.register_template_string("two", "Lets test {{name}}")
243 _
: &mut RenderContext
<'_
, '_
>,
244 out
: &mut dyn Output
|
245 -> Result
<(), RenderError
> {
252 "This is a test. Lets test fred",
253 hbs
.render("one", &0).unwrap()
258 fn test_nested_partial_scope() {
259 let t
= "{{#*inline \"pp\"}}{{a}} {{b}}{{/inline}}{{#each c}}{{> pp a=2}}{{/each}}";
260 let data
= json
!({"c": [{"b": true}
, {"b": false}
]});
262 let mut handlebars
= Registry
::new();
263 assert
!(handlebars
.register_template_string("t", t
).is_ok());
264 let r0
= handlebars
.render("t", &data
);
265 assert_eq
!(r0
.ok().unwrap(), "2 true2 false");
269 fn test_up_to_partial_level() {
270 let outer
= r
#"{{>inner name="fruit:" vegetables=fruits}}"#;
271 let inner
= "{{#each vegetables}}{{../name}} {{this}},{{/each}}";
273 let data
= json
!({ "fruits": ["carrot", "tomato"] }
);
275 let mut handlebars
= Registry
::new();
276 handlebars
.register_template_string("outer", outer
).unwrap();
277 handlebars
.register_template_string("inner", inner
).unwrap();
280 handlebars
.render("outer", &data
).unwrap(),
281 "fruit: carrot,fruit: tomato,"