mustache / spec

The Mustache spec.
MIT License
361 stars 71 forks source link

Specification is ambiguous on dotted name context handling #133

Closed spullara closed 2 years ago

spullara commented 2 years ago

I recently got a bug report with mustache.java that I wasn't handling dotted names properly:

https://github.com/spullara/mustache.java/issues/275

The crux of the issue is that the reported believes that {{#a.b}} ... {{/a.b}} should be equivalent to {{#a}}{{#b}} ... {{/b}}{{/a}}. However, I do not evaluate it that way, there is only the context of the evaluation of a.b in mustache.java - a is not on the stack. How do other implementations act? If they also work the way the reporter wants I'm happy to change the behavior but would like a spec test added that checks for it.

gasche commented 2 years ago

To me the specification on sections clearly suggests that {{#a.b}} will not push #a into the context. The specification is as follows:

Section tags and End Section tags are used in combination to wrap a section of the template for iteration [..] This tag's content names the data to replace the tag. Name resolution is as follows: 1) Split the name on periods; the first part is the name to resolve, any remaining parts should be retained. [...] 3) If the context is a hash, the data is the value associated with the name. [...] 6) If any name parts were retained in step 1, each should be resolved against a context stack containing only the result from the former resolution. If any part fails resolution, the result should be considered falsey, and should interpolate as the empty string.

For each element in the data list, the element MUST be pushed onto the context stack, the section MUST be rendered, and the element MUST be popped off the context stack.

In other words: the section context describes resolves to one piece of data that is then used for iteration; {{#a.b}} resolves the data at address a.b in the context, it does not recursively iterate on a then b.

This is the current specification as I understand it. Now in terms of "what would be best":

This latter behavior is not suggested by the current specification (which says nothing of name resolution where the value of intermediate name elements are lists), but it is also compatible in the sense that it corresponds to an unspecified case. The proposal to handle {{#a.b}} as {{#a}}{{#b}} is a more breaking change, in that it changes the semantics of currently-specified templates.

jgonggrijp commented 2 years ago

I agree mostly with @gasche, though I think that even in the list case, {{#a.b}} should not be equivalent to {{#a}}{{#b}}. Based on the specification, I actually expect the {{#a.b}} section not to be rendered at all in that case, since the a list doesn't have a b member.

spullara commented 2 years ago

6) definitely says that I am evaluating it the right way. Thanks.