mustache / spec

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

Are Lambda sections standalone? #140

Closed agentgt closed 1 year ago

agentgt commented 1 year ago

Are lambda sections arity 1 standalone?

I'm fairly sure they are but maybe a spec test should be there and the spec should say that.

(there might even already be an implicit test of it in one of the other tests similar to #139)

Also although it is obvious what happens on the outside of a lambda it isn't for the body that gets passed (I'm going to represent newline in brackets for clarity):

{{#lambda}}[newline-1]
content[newline-2]
{{/lambda}}[newline-3]

Now let's say our lambda just returns the raw contents (which may or may not be interpolated depending on implementation but let's ignore that for now).

Do we get:

Output 1: the lambda never sees newline-1 and the outside tags are considered standalone

content[newline-2]

Output 2: the lambda does see newline-1 and the outside lambda tags are standalone

[newline-1]
content[newline-2]

Output 3: lambda tags are not considered standalone

[newline-1]
content[newline-2]
[newline-3]

Output 4: trimming everything... this one is probably very wrong

content

My current implementation does Output 1.

Also I forgot to add another use case:

{{#lambda}}[newline-1]
{{#fakesection}}
content[newline-2]
{{/fakesection}}{{/lambda}}[newline-3]

My implementation still does Output 1 (this was accidental but I believe it ironically follows the block parent pairing logic).

Another follow up question is what is not allowed in a block lambda:

{{#lambda}}[newline-1]
{{/fakesection}}[newline-2]
{{/lambda}}[newline-3]

In theory the above is legal but probably brakes most implementations (I believe it works in mine).

agentgt commented 1 year ago

BTW Wontache fails for:

{{#lambda}}
{{/fakesection}}
{{/lambda}}

With:

SyntaxError: Nonmatching keys at begin and end of section: {{#lambda}}...{{/fakesection}}

Otherwise it seems to be following the same output as mine (Output 1).

EDIT: I should add I didn't expect it to work as templates get compiled without a data model/schema so you don't know if the field is a lambda.

The question is if I have to guarantee that it is valid mustache as I currently do not.

jgonggrijp commented 1 year ago

Are lambda sections arity 1 standalone?

Quick answer before I dive into details: sections follow a more old-fashioned concept of standalone than what I'm currently proposing for parents and blocks in #131. Sections as a whole are not standalone, but the opening tag and the closing tag can be standalone independently from each other. If I recall correctly, changing this into the more "holistic" concept from #131 would be a breaking change, although I and @gasche believe that would be better in principle.

I am not sure what you mean by "arity 1" here. Do you mean to refer to non-power lambdas? What kind of value is passed into the section does not matter for the whitespace handling, as far as the Mustache syntax is concerned.

I'm fairly sure they are but maybe a spec test should be there and the spec should say that.

(there might even already be an implicit test of it in one of the other tests similar to #139)

Yes, this is the case. You need to follow very particular rules in order to pass all the whitespace-related tests.

{{#lambda}}[newline-1]
content[newline-2]
{{/lambda}}[newline-3]

Both the {{#lambda}} and the {{/lambda}} tag are standalone in this example. Only [newline-2] is part of the content, as you rightly concluded.

{{#lambda}}[newline-1]
{{#fakesection}}
content[newline-2]
{{/fakesection}}{{/lambda}}[newline-3]

If you mean this:

{{#lambda}}[newline-1]
{{#fakesection}} content[newline-2]
{{/fakesection}}{{/lambda}}[newline-3]

then only {{#lambda}} is standalone (so not {{#fakesection}}, {{/fakesection}} or {{/lambda}}). [newline-2] and [newline-3] are part of the content (but [newline-2] repeats and [newline-3] does not).

However, if you forgot a newline and actually meant this:

{{#lambda}}[newline-1]
{{#fakesection}}[newline-1b]
content[newline-2]
{{/fakesection}}{{/lambda}}[newline-3]

then both {{#lambda}} and {{#fakesection}} are standalone. [newline-2] and [newline-3] are still both part of the content.

Regardless, I think that {{#fakesection}}...{{/fakesection}} is a very real section. ;-)

My implementation still does Output 1 (this was accidental but I believe it ironically follows the block parent pairing logic).

While I am not sure that will pass all tests in the spec, one could argue that your implementation is doing better than the spec in that case.

Another follow up question is what is not allowed in a block lambda:

{{#lambda}}[newline-1]
{{/fakesection}}[newline-2]
{{/lambda}}[newline-3]

In theory the above is legal but probably brakes most implementations (I believe it works in mine).

The template is not well-formed; template authors should never write that. However, I agree that the spec does not discuss anywhere what implementations should do with such templates. Basically, that means that the behavior is undefined and that every implementation can do whatever the implementer wants. Given garbage input, the output can never be "right", anyway.

Wontache validates the matching and nesting of paired tags, but permits some other types of user errors. For example, I think it will accept {{#section}} content }} more content {{/section}} and simply include the stray closing delimiters in the content. Your implementation allows stray ending tags, but checks types; that is up to you.

I will close this now on the assumption that the question is answered, but please still feel free to respond.