This weekend I learned some unfamiliar behaviors with the way Handlebars
handles nested variable scopes. I typically use Handlebars via the
handlebars-rust implementation
which aims to maintain nearly one to one compatibility with the JavaScript
implementation. They have block scope helpers such
as #each and #with, both of which create an inner scope for variable
resolution. Unfortunately, the syntax can be quite unintuitive for accessing outer
scope once in those nested scopes.
Handlebars is a largely declarative templating syntax which uses curlybraces
such as {{var}} for variable and helper substitution. The #each helper is
important for loops, imagine the following data structure:
{
  "repos" : [
    {
      "name" : "otto"
    },
    {
      "name" : "l4bsd"
    }
  ],
  "mood" : "cool"
}
This could be rendered into a list on a page via:
<ul>
    {{#each data.repos}}
        <li>{{name}}</li>
    {{/each}}
</ul>
Inside the #each block the values of the indexed object become the scope for
variable resolution, such that {{name}} actually refers to
data.repos[i].name. This presents problems when the template must refer to
outer scope variables, such as mood. In the Rust implementation this variable
resolution can be accomplished through a path traversal style syntax such as:
<ul>
    {{#each data.repos}}
        <li>{{name}} is {{../data.mood}}</li>
    {{/each}}
</ul>
The ../data.mood is all that’s needed to refer to the variable in the outer
scope of variables. Not what I expected at all, and the only reason I found it
was because I found an old
issue which alluded to
the syntax and gave it a try.