Skip to content

Commit

Permalink
Make #each handle non-iterable values like the original JS library.
Browse files Browse the repository at this point in the history
Previously things like `{{#each "foo"}}` were render errors. Now
non-iterable values are treated like empty iterables. This brings
handlebars-rust's behavior closer in line with the original JavaScript
library.

Here are the two new test cases in the handlebars playground:

1. https://handlebarsjs.com/playground.html#format=1&currentExample=%7B%22template%22%3A%22%7B%7B%23each%20this%7D%7Deach%20block%7B%7Belse%7D%7Delse%20block%7B%7B%2Feach%7D%7D%22%2C%22partials%22%3A%5B%5D%2C%22input%22%3A%22%5C%22strings%20aren't%20iterable%5C%22%22%2C%22output%22%3A%22else%20block%22%2C%22preparationScript%22%3A%22%22%2C%22handlebarsVersion%22%3A%224.7.6%22%7D

2. https://handlebarsjs.com/playground.html#format=1&currentExample=%7B%22template%22%3A%22%7B%7B%23*inline%20%5C%22walk%5C%22%7D%7D(%7B%7B%23each%20this%7D%7D%7B%7B%23if%20%40key%7D%7D%7B%7B%40key%7D%7D%7B%7Belse%7D%7D%7B%7B%40index%7D%7D%7B%7B%2Fif%7D%7D%3A%20%7B%7Bthis%7D%7D%20%7B%7B%3E%20walk%20this%7D%7D%2C%20%7B%7B%2Feach%7D%7D)%7B%7B%2Finline%7D%7D%5Cn%7B%7B%3E%20walk%7D%7D%22%2C%22partials%22%3A%5B%5D%2C%22input%22%3A%22%7B%5Cn%20%20%20%20%5C%22array%5C%22%3A%20%5B42%2C%20%7B%5C%22wow%5C%22%3A%20%5C%22cool%5C%22%7D%2C%20%5B%5B%5D%5D%5D%2C%5Cn%20%20%20%20%5C%22object%5C%22%3A%20%7B%20%5C%22a%5C%22%3A%20%7B%20%5C%22b%5C%22%3A%20%5C%22c%5C%22%2C%20%5C%22d%5C%22%3A%20%5B%5C%22e%5C%22%5D%20%7D%20%7D%2C%5Cn%20%20%20%20%5C%22string%5C%22%3A%20%5C%22hi%5C%22%5Cn%7D%22%2C%22output%22%3A%22%5Cn(array%3A%2042%2C%5Bobject%20Object%5D%2C%20(0%3A%2042%20()%2C%201%3A%20%5Bobject%20Object%5D%20(wow%3A%20cool%20()%2C%20)%2C%202%3A%20%20(0%3A%20%20()%2C%20)%2C%20)%2C%20object%3A%20%5Bobject%20Object%5D%20(a%3A%20%5Bobject%20Object%5D%20(b%3A%20c%20()%2C%20d%3A%20e%20(0%3A%20e%20()%2C%20)%2C%20)%2C%20)%2C%20string%3A%20hi%20()%2C%20)%22%2C%22preparationScript%22%3A%22%22%2C%22handlebarsVersion%22%3A%224.7.6%22%7D
  • Loading branch information
mkantor committed Sep 7, 2020
1 parent 3d845e2 commit 57af8f4
Showing 1 changed file with 50 additions and 5 deletions.
55 changes: 50 additions & 5 deletions src/helpers/helper_each.rs
Expand Up @@ -136,16 +136,12 @@ impl HelperDef for EachHelper {
rc.pop_block();
Ok(())
}
(false, _) => {
_ => {
if let Some(else_template) = h.inverse() {
else_template.render(r, ctx, rc, out)?;
}
Ok(())
}
_ => Err(RenderError::new(format!(
"Param type is not iterable: {:?}",
value.value()
))),
},
None => Ok(()),
}
Expand Down Expand Up @@ -479,4 +475,53 @@ mod test {
let rendered = reg.render_template(template, &input).unwrap();
assert_eq!("01", rendered);
}

#[test]
fn test_non_iterable() {
let reg = Registry::new();
let template = "{{#each this}}each block{{else}}else block{{/each}}";
let input = json!("strings aren't iterable");
let rendered = reg.render_template(template, &input).unwrap();
assert_eq!("else block", rendered);
}

#[test]
fn test_recursion() {
let mut reg = Registry::new();
assert!(reg
.register_template_string(
"walk",
"(\
{{#each this}}\
{{#if @key}}{{@key}}{{else}}{{@index}}{{/if}}: \
{{this}} \
{{> walk this}}, \
{{/each}}\
)",
)
.is_ok());

let input = json!({
"array": [42, {"wow": "cool"}, [[]]],
"object": { "a": { "b": "c", "d": ["e"] } },
"string": "hi"
});
let expected_output = "(\
array: [42, [object], [[], ], ] (\
0: 42 (), \
1: [object] (wow: cool (), ), \
2: [[], ] (0: [] (), ), \
), \
object: [object] (\
a: [object] (\
b: c (), \
d: [e, ] (0: e (), ), \
), \
), \
string: hi (), \
)";

let rendered = reg.render("walk", &input).unwrap();
assert_eq!(expected_output, rendered);
}
}

0 comments on commit 57af8f4

Please sign in to comment.