mustache / mustache.github.com

The {{official}} website
http://mustache.github.io/
Other
2.29k stars 292 forks source link

{{#item.0}} checks #148

Closed DeeHants closed 1 year ago

DeeHants commented 1 year ago

Not sure if this counts as a bug, and seems to be by design as per the wording of the docs, and (at least) the perl and JS implementations, but a gotcha...

We make extensive use of {{#items.0}} type checks to see if an array has any items before rendering the container and the items themselves ({{#items}}{{value1}}{{value2}}{{/items}}). This gives example code like:

{{#items.0}}
  <p>found items</p>
  {{#items}}
    {{#first}}
      <li><strong>{{name}}</strong></li>
    {{/first}}
    {{#link}}
      <li><a href="{{url}}">{{name}}</a></li>
    {{/link}}
  {{/items}}
{{/items.0}}
{{^items.0}}
  <p>no items</p>
{{/items.0}}

The issue here is that the 0th item is now part of the context stack, meaning that if items 1+ do not have a specific named value, but the 0th does, that value will be rendered instead. If you put the above mustache into the demo, you get this broken output:

<p>found items</p>
<li><strong>red</strong></li>
<li><strong>green</strong></li>
<li><a href="#Green">green</a></li>
<li><strong>blue</strong></li>
<li><a href="#Blue">blue</a></li>

It now thinks every item is "first" as it pulls that value from the {{#items.0}} context.

We can work around it in some cases, by changing {{subitem.value}} (which also exists at .0) to {{#subitem}}{{value}}{{/subitem}}. This works, as the .n entries will have a subitem which becomes the new context, and then looks for value which .0 (and .n) doesn't.

DeeHants commented 1 year ago

Moved in to the Spec repo, #138