-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify substituted block scope resolution #129
Specify substituted block scope resolution #129
Conversation
Personally I don't have an opinion in one direction or another; I made the choice that would match a test in the mustache.php testsuite. It's good that you have an intuition on which direction should be taken! Thanks for your work on the Mustache spec. |
Bump! |
Confirmed that this test passes with mustache.php. 🙂 |
This does indeed seem like the most reasonable interpretation. Thank you for your continued contributions! Merging and tagging |
Verified that it works as specified on mustache.java. |
Guys I have a really hard time accepting the interpretation of block scoping. I know the ship has sailed on this but I think it is wrong. I think that the block should be evaluated immediately and thus in the child's context.
If folks are interested I can provide numerous examples of how easy it is too screw it up. I can also show how very few templating languages do it the way mustache is doing (that is most evaluate eagerly). Anyway prior to inheritance (and apparently it still will be the case) there was absolutely no way to pass a rendered text to something else as lambdas only accept unrendered text. I was hoping inheritance would do this. And in general it might provided you don't do weird things in your parent like nesting a block in a section (assuming the child passes its current context to the parent which again I'm fairly sure it does but not entirely). In fact if the context was passed to lambdas (which is the case for some implementations and possibly the future with power lambdas) one could easily implement single inheritance with custom lambdas as the lambdas will accept unrendered text. That is instead of:
You could do:
(in this case the lambda name is the template to load but you could use another block parameter like say {{$template}}). Now the lambda author has to do all the work of replacing blocks and loading the parent but it is probably largely a simple search and replace. Yes it is not standardized and you have to write a custom lambda but you could make it library and thus standardize that library... ie you could spec it there. My point is passing around unrendered text that then gets expanded in mustache was a solved problem. What we don't have is the ability to pass rendered (ie eagerly evaluated) text to then be used which is important for componentization. A component should not have to need to know what the model is of the child. The child adapts the model to what the component needs. Anyway given that this apparently has reached consensus and given that if one is careful with parents the blocks will largely act like eager evaluation anyway I will still try to implement block scoping (provided the child is passing the context to the parent as its starting point) but I am concerned. (apologies for the edits) |
Just for completeness, let me refer to #131 (comment). Halfway in that comment, I illustrate how the present block scoping rules logically follow from a mental substitution of the parent template for the parent tag pair, overriding blocks as provided. I am aware that you (@agentgt) already read that, but with hindsight, it belonged here in the first place. Adding to that comment, I should mention that this mental substitution is a natural extension of the semantics of old-fashioned partials, as described in the manpage. (Note that this same explanation already appeared in the original, outdated manpage, long before I touched it.) With this justification in mind, let me address some details of your post:
The child knows more about how the block should be filled, so in that sense you are right. However, the parent knows more about where the block will be placed. As we have seen, that might be inside a section. It might even be passed on as an argument to another parent (which in turn might also be nested inside a section, or nest the block in a section internally, or both).
This is true regardless of whether context is evaluated in the child or in the parent.
This is not really different from old-fashioned partials, or even templates in general. You need to know what data to pass to a template in order to render it. Keep in mind that partials, parents and blocks are just templates; they have exactly the same semantics as the "main" or "entry" template.
Mustache works with an implicit context stack. This is a cost we have to pay for the logic-free syntax. Other template languages do not even need to distinguish between "eager" and "lazy" evaluation, because they don't work with a context stack in the first place.
No (if you mean the root from the child);
yes;
the spec does actually define these semantics here and here. The manpage also states that partials (and by extension, parents) "inherit the calling context".
You can provide as many examples as you wish, but they are not going to change the fact that, given the use of an implicit context stack, inheritance cannot work correctly unless the block is evaluated in the context of the parent.
I understand this is disappointing. Blocks were never intended as a general solution for passing information around; they are only meant as inline templates with which you can fill slots inside other templates. Power lambdas (#135) would probably be a better solution to what you are trying to achieve.
I would like to emphasize that nesting a block in a section is a perfectly reasonable thing to do. For illustration, I might have a parent template for listing news headlines ( {{#headlines}}
{{$headline-format}}
<div class="headline">
<h2><a href="{{&url}}">{{title}}</a></h2>
<p>{{synopsis}}</p>
</div>
{{/headline-format}}
<a href="#top">Back to top</a>
{{/headlines}} In a child template, I might want to override the format to use more modern, semantic html: {{<frontpage}}
{{$headline-format}}
<article class="headine">
<heading><h2><a href="{{&url}}">{{title}}</a></h2></heading>
<p>{{synopsis}}</p>
</article>
{{/headline-format}}
{{/frontpage}}
Here you are losing me. What is that second template supposed to do?
What do you mean by "componentization" and "component"?
If you substitute "parent" for "component", then these sentences are already true under the current spec. But I suspect that is not what you meant. |
This is my first follow-up on #125. I planned this addition already in April, but the work was delayed until now due to other projects intervening.
The diff, which is very small, probably speaks for itself. I wrote this spec after completing my own implementation of template inheritance, and I didn't need to change my implementation in order to pass the new spec. If I understood correctly, at least Mustache.php by @bobthecow and Ocaml-Mustache by @gasche already implement this spec, too. To me this seems the most intuitive interpretation of scope in a substituted block, so I hope it will be fairly uncontroversial.