You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At Twitter we run into a very common case where we want to have one template where we maintain the "bones" of the page and each real page on the site merely replaces sections of that page with appropriate content. We would like to avoid putting any business logic in the bones of the page for including the right content, nor do we want to write custom backing code for each of those pages.
I'm pretty uninterested in the logic-less template stuff, but this strikes me as something that could be really useful to have, and so I'd like to see something like this.
But what strikes me about it is that sub.mustache is not really a mustache template but more of a list of substitutions (which are mustache templates). Is there any way an inheriting template isn't just a list of substitutions? Because if not, why couldn't it just be defined that if an implementation wants to create a mechanism for creating derived templates, it can do that by letting you define (however you like; json? yaml? list of mustache sections?) a mapping of names to mustache-template strings or mustache files and replacing regular interpolation tags with the indicated mustache code when the derived template is loaded? It seems to me (albeit after only like 4 minutes thought) that this would potentially be even more convenient while simultaneously not requiring major changes to the parsers of existing mustaches. And also, it would prevent us from using up two precious special characters to implement this proposal. But, I'm probably missing something in that logic.
As @davidsantiago, I regret that sub.mustache is "not really a mustache template", and, more specifically, that we don't know what happens when sub.mustache contains content outside of the substitutions blocks. That alone makes the gist weird, even though the need is pretty clear.
I know about a solution for this problem: Ruby on Rails' one : one template is rendered in one layout.
This gist show hows a Rails-like two-pass rendering could look in Mustache (the syntax mimics Rail's one) : https://gist.github.com/1855111
Thanks for the feedback. sub.mustache is actually a mustache template, the example usage failed to show that in all its glory. Another example that has come up for us is for having similar widgets that are displayed differently in different places but use the same base template. I do agree though that within the {{<super}}, the top level has to be replacements. However, nothing stops you from using the {{<}} syntax anywhere within any template. {{<}} means "replace any blocks in this partial with blocks that i have specified within this tag, then include the partial".
The RoR solution lacks the ability to have multiple layouts in a single page, also I need some external mechanism to connect the two templates. It also doesn't seem to support a large hierarchy of template "classes". For example, we might have:
Re: characters. This scheme can be implemented without introducing new characters through some elaborate lambda gymnastics but it wouldn't be very clear what was going on when you looked at the template. Could be ameliorated by using a naming convention e.g. {{#<super}} and {{#$content}}. My personal opinion is that this is such a widespread issue with real life mustache usages that it just might be worth it.
{{<}} means "replace any blocks in this partial with blocks that i have specified within this tag, then include the partial".
Thanks for this sentence. It's quite clear, now.
It's also clear that {{<}} can be seen as a kind of inheritance, and as well as a function call with arguments. More people should know Handlebars.js. In Handlebars, no need for new punctuation, no need for an extension to the spec: I quite think you could just write a simple 'content_for' helper, and write : https://gist.github.com/1855986.
That is pretty close. The only gap is that when you use multi-level inheritance the higher one in the stack wins instead of the lowest one in the stack. Default content also doesn't work with this model.
OK, yeah, that functionality wasn't clear to me from the initial example. That does leave the "templateness" of sub.mustache intact. However, as you say, there is still the way that the inside of the ">" tag is basically putting forth a map notation for mustache. Mustache has always seemingly been happy to leave maps to the language implementing it, so I still feel a little uncomfortable with this and can't say why. I just wish that the inside of that tag didn't require so much special meaning and new parsing. That is why I still really like the idea of letting this just be a partial with template substitutions for interpolation tags. The spec is already vague about where exactly the implementation should go looking for partials, so this could be very easily slipped into current implementations with a minimum of new syntax, just an expansion of what partials mean, in that partials might have associated files that create substitutions when they are loaded.
Regarding the other character, I was saying that I think you could leave off the $, and just jam the template into the ordinary interpolation tags. This is already kind of what lambdas do, in that a lambda passed in for an interpolation tag will return mustache code that is then parsed and rendered in that context. So there is already a precedent for a regular interpolation tag being used as a site for more template code to be inserted. The difference here would be that instead of this happening due to a function passed into the context map, it's happening because a derived template is instantiating itself (and thus wouldn't need to happen every time the template is called).
The biggest problem with using # is that the identity transformation is so goofy. Even though it looks like you are replacing it with the same thing, they would be interpreted much differently:
Ah sorry, by "identity transformation" I mean a replacement that leaves you with the original. If we reuse # tags we have the issue that to replace the section with something that means the same thing you have to double them.
OK, I see now what you're saying. If we grant the syntax you want for using sections as keys and their values in a partial, the repetition in that example seems clear enough to me. Certainly the identity transformation is not a motivating use case for this feature, and having the source code for it, when it is necessary, shake out in this way doesn't strike me as sufficient motivation for the addition of a new tag type. There are no current semantics defined for sections when they are being used as the sites of template inheritance replacements, so there is some leeway here to posit new rules if that's necessary.
So currently the semantics for # sections is such that if they are not present in the backing code, they are "false". It might make more sense to use {{^}} instead in this case to get something that is closer to the {{$}} behavior. Not sure if I am explaining this well enough, but {{#}} has very different semantics.
I don't know if you're explaining it well enough, but I'm not quite following you. I assume you're talking about the resolution rules hereabouts: https://github.com/mustache/spec/blob/master/specs/sections.yml#L11 Those rules name a few different places to look for the contents of a section tag... is there some reason another place to look couldn't be added to those rules? I'm not seeing it.
So lets take the example where you want a page to evaluate two different ways, once with the default text and once with your modified text. In order for that to work, based on Rule 2), you have to have a singular valued hash matching the name of the section in the top level template so the section renders at all:
Walk the context stack from top to bottom, finding the first context
that is a) a hash containing the name as a key OR b) an object responding
to a method with the given name.
If you don't have that, the section won't be evaluated. When I extend the top level template, suddenly that "section" is satisfied and it doesn't even reference the section code that I use in the super template. Having to offer specific backing code in order for the template to render properly is what I am trying to avoid by suggesting a declarative template inheritance feature. This is why the sub template isn't just a hash of values but literally replaces the template code in the super template. The real issue is the default for {{#}} is false, not true -- which is why I suggested that {{^}} would be more appropriate.
OK, gotcha, thanks. I had not been considering the use case of wanting to have default code for when nothing is provided by a derived template and there is no desire to have a flag in the context to control whether that default code renders or not. I agree that that's not desirable.
If a partial has {{something}}, {{#something}}{{/something}} or {{^something}}{{/something}}, I thought we'd like to have a way to replace that tag with an arbitrary expansion, but Mustache doesn't currently have a way to name groups of code other than sections and inverted sections. So then you'd have to say: when you're replacing, match the tag names regardless of the tag type. That way you could get a section/inverted section named "something" inserted in the place of {{something}} or whatever. Here we're using sections/inverted sections just for their code-grouping semantic to define the key/value syntax for the replacement part of the {{<}} tag. Although you're right that {{^}} would be more natural for the replacement sites, it's not clear to me which is more natural and meaningful in the key/value replacement syntax, especially when you add on the question of whether they should match the replacement site or be the opposite for the replacement to avoid confusion about "double negatives."
That makes me unhappy, and you already had a solution to that, which was to define a new tag type that allows you to name a group of code, but without the implied "here or not" choice between a section or inverted section. So {{#}} means "Render this group of code if we are given a truthy value for its name," {{^}} means "Render this group of code if we aren't given a truthy value for its name," and {{$}} means "Render this group of code if we aren't given a substitution from a partial, and if we are, render that replacement." This expansion of syntax allows more information to remain "in mustache," as mustache is then expanded to mean more things. This trades away the ability to "replace anything" in the parent template for one that has to be prepared with replacement sites and requires a special idea of what is "default" in the template that is above and beyond just the template itself as it would already exist in mustache as it is today.
I also had a solution to that, which was to not get into the key/value syntax business in the first place and leave those to the implementation's maps. In that world, {{}}, {{#}}, and {{^}} can all be replaced equally naturally when the super (actually just a partial, now) is loaded by the implementation with the use of a map of the tag name->source code replacements that the implementation knows how to find. All that's needed is some rules for how those replacements should be made from the map, assuming this map already exists. This offers "replace anything" capability and retains implementation simplicity by avoiding the addition of any new syntax, but it comes at the cost of requiring that derived templates have some external storage format outside of mustache to store their replacement maps (the spec itself shows that mustache can be very naturally embedded in YAML, for one example). I think we assign different weights to how much we value these things; I don't value having a mustache version of a key/value map that much.
Anyhow, I think your idea for derived templates is great, and I think I'm gonna try adding my version to my mustache implementation just to check it out. I just hope the mustache language stays small and provides a small number of very flexible primitives. The language is pretty much defined by the 5 or 6 special characters that start tags, and I hope the language doesn't expand to many more tags than that, or it'll stop being easy to learn and keep in your head.
I have an issue. I am doing the inheritance
{{<../email_base}}
{{$email_title}}Your Title here{{/email_title}}
{{$email_content}}
{{/email_content}}
{{/../email_base}}
The only thing is I have two separate folders and my email_base is outside that folder. When I run my project on Intellij I can see everything properly. But mvn fails
mvn test -DskipTests=false passes
mvn verify -DskipTests=false fails
giving me an error
com.github.mustachejava.MustacheNotFoundException: Template developer/../email_developer_base.html.mustache not found
P.S. Very new to mustache
I have an issue. I am doing the inheritance
{{<../email_base}}
{{$email_title}}Your Title here{{/email_title}}
{{$email_content}}
{{/email_content}}
{{/../email_base}}
The only thing is I have two separate folders and my email_base is outside
that folder. When I run my project on Intellij I can see everything
properly. But mvn fails
mvn test -DskipTests=false passes
mvn verify -DskipTests=false fails
giving me an error
com.github.mustachejava.MustacheNotFoundException: Template
developer/../email_developer_base.html.mustache not found
P.S. Very new to mustache
—
Reply to this email directly or view it on GitHub #38 (comment).
@theLucid I am revisiting this thread as I got a request from someone to conditionally render based on whether a section was overridden. After writing some horrid code to implement it with pragmas I'm think that your {{?id}} syntax might be great for this. Did you ultimately end up using that?
Activity
davidsantiago commentedon Feb 17, 2012
I'm pretty uninterested in the logic-less template stuff, but this strikes me as something that could be really useful to have, and so I'd like to see something like this.
But what strikes me about it is that sub.mustache is not really a mustache template but more of a list of substitutions (which are mustache templates). Is there any way an inheriting template isn't just a list of substitutions? Because if not, why couldn't it just be defined that if an implementation wants to create a mechanism for creating derived templates, it can do that by letting you define (however you like; json? yaml? list of mustache sections?) a mapping of names to mustache-template strings or mustache files and replacing regular interpolation tags with the indicated mustache code when the derived template is loaded? It seems to me (albeit after only like 4 minutes thought) that this would potentially be even more convenient while simultaneously not requiring major changes to the parsers of existing mustaches. And also, it would prevent us from using up two precious special characters to implement this proposal. But, I'm probably missing something in that logic.
groue commentedon Feb 17, 2012
Two cents:
As @davidsantiago, I regret that sub.mustache is "not really a mustache template", and, more specifically, that we don't know what happens when sub.mustache contains content outside of the substitutions blocks. That alone makes the gist weird, even though the need is pretty clear.
I know about a solution for this problem: Ruby on Rails' one : one template is rendered in one layout.
This gist show hows a Rails-like two-pass rendering could look in Mustache (the syntax mimics Rail's one) : https://gist.github.com/1855111
The main differences with @spullara's gist:
spullara commentedon Feb 17, 2012
Thanks for the feedback. sub.mustache is actually a mustache template, the example usage failed to show that in all its glory. Another example that has come up for us is for having similar widgets that are displayed differently in different places but use the same base template. I do agree though that within the {{<super}}, the top level has to be replacements. However, nothing stops you from using the {{<}} syntax anywhere within any template. {{<}} means "replace any blocks in this partial with blocks that i have specified within this tag, then include the partial".
The RoR solution lacks the ability to have multiple layouts in a single page, also I need some external mechanism to connect the two templates. It also doesn't seem to support a large hierarchy of template "classes". For example, we might have:
General Twitter Page < Settings style page < Profile settings page
Re: characters. This scheme can be implemented without introducing new characters through some elaborate lambda gymnastics but it wouldn't be very clear what was going on when you looked at the template. Could be ameliorated by using a naming convention e.g. {{#<super}} and {{#$content}}. My personal opinion is that this is such a widespread issue with real life mustache usages that it just might be worth it.
groue commentedon Feb 17, 2012
Thanks for this sentence. It's quite clear, now.
It's also clear that {{<}} can be seen as a kind of inheritance, and as well as a function call with arguments. More people should know Handlebars.js. In Handlebars, no need for new punctuation, no need for an extension to the spec: I quite think you could just write a simple 'content_for' helper, and write : https://gist.github.com/1855986.
Really, Yehuda Katz's announcement is refreshing: http://yehudakatz.com/2010/09/09/announcing-handlebars-js/
Handlebars.js website: http://handlebarsjs.com/
spullara commentedon Feb 17, 2012
That is pretty close. The only gap is that when you use multi-level inheritance the higher one in the stack wins instead of the lowest one in the stack. Default content also doesn't work with this model.
davidsantiago commentedon Feb 18, 2012
OK, yeah, that functionality wasn't clear to me from the initial example. That does leave the "templateness" of sub.mustache intact. However, as you say, there is still the way that the inside of the ">" tag is basically putting forth a map notation for mustache. Mustache has always seemingly been happy to leave maps to the language implementing it, so I still feel a little uncomfortable with this and can't say why. I just wish that the inside of that tag didn't require so much special meaning and new parsing. That is why I still really like the idea of letting this just be a partial with template substitutions for interpolation tags. The spec is already vague about where exactly the implementation should go looking for partials, so this could be very easily slipped into current implementations with a minimum of new syntax, just an expansion of what partials mean, in that partials might have associated files that create substitutions when they are loaded.
Regarding the other character, I was saying that I think you could leave off the $, and just jam the template into the ordinary interpolation tags. This is already kind of what lambdas do, in that a lambda passed in for an interpolation tag will return mustache code that is then parsed and rendered in that context. So there is already a precedent for a regular interpolation tag being used as a site for more template code to be inserted. The difference here would be that instead of this happening due to a function passed into the context map, it's happening because a derived template is instantiating itself (and thus wouldn't need to happen every time the template is called).
spullara commentedon Feb 22, 2012
The biggest problem with using # is that the identity transformation is so goofy. Even though it looks like you are replacing it with the same thing, they would be interpreted much differently:
https://gist.github.com/1881261
davidsantiago commentedon Feb 22, 2012
I'm not at all following what you're saying... What is it about the # tags? What is the identity transformation?
spullara commentedon Feb 22, 2012
Ah sorry, by "identity transformation" I mean a replacement that leaves you with the original. If we reuse # tags we have the issue that to replace the section with something that means the same thing you have to double them.
davidsantiago commentedon Feb 22, 2012
OK, I see now what you're saying. If we grant the syntax you want for using sections as keys and their values in a partial, the repetition in that example seems clear enough to me. Certainly the identity transformation is not a motivating use case for this feature, and having the source code for it, when it is necessary, shake out in this way doesn't strike me as sufficient motivation for the addition of a new tag type. There are no current semantics defined for sections when they are being used as the sites of template inheritance replacements, so there is some leeway here to posit new rules if that's necessary.
spullara commentedon Feb 22, 2012
So currently the semantics for # sections is such that if they are not present in the backing code, they are "false". It might make more sense to use {{^}} instead in this case to get something that is closer to the {{$}} behavior. Not sure if I am explaining this well enough, but {{#}} has very different semantics.
davidsantiago commentedon Feb 22, 2012
I don't know if you're explaining it well enough, but I'm not quite following you. I assume you're talking about the resolution rules hereabouts: https://github.com/mustache/spec/blob/master/specs/sections.yml#L11 Those rules name a few different places to look for the contents of a section tag... is there some reason another place to look couldn't be added to those rules? I'm not seeing it.
spullara commentedon Feb 22, 2012
So lets take the example where you want a page to evaluate two different ways, once with the default text and once with your modified text. In order for that to work, based on Rule 2), you have to have a singular valued hash matching the name of the section in the top level template so the section renders at all:
that is a) a hash containing the name as a key OR b) an object responding
to a method with the given name.
If you don't have that, the section won't be evaluated. When I extend the top level template, suddenly that "section" is satisfied and it doesn't even reference the section code that I use in the super template. Having to offer specific backing code in order for the template to render properly is what I am trying to avoid by suggesting a declarative template inheritance feature. This is why the sub template isn't just a hash of values but literally replaces the template code in the super template. The real issue is the default for {{#}} is false, not true -- which is why I suggested that {{^}} would be more appropriate.
davidsantiago commentedon Feb 22, 2012
OK, gotcha, thanks. I had not been considering the use case of wanting to have default code for when nothing is provided by a derived template and there is no desire to have a flag in the context to control whether that default code renders or not. I agree that that's not desirable.
If a partial has {{something}}, {{#something}}{{/something}} or {{^something}}{{/something}}, I thought we'd like to have a way to replace that tag with an arbitrary expansion, but Mustache doesn't currently have a way to name groups of code other than sections and inverted sections. So then you'd have to say: when you're replacing, match the tag names regardless of the tag type. That way you could get a section/inverted section named "something" inserted in the place of {{something}} or whatever. Here we're using sections/inverted sections just for their code-grouping semantic to define the key/value syntax for the replacement part of the {{<}} tag. Although you're right that {{^}} would be more natural for the replacement sites, it's not clear to me which is more natural and meaningful in the key/value replacement syntax, especially when you add on the question of whether they should match the replacement site or be the opposite for the replacement to avoid confusion about "double negatives."
That makes me unhappy, and you already had a solution to that, which was to define a new tag type that allows you to name a group of code, but without the implied "here or not" choice between a section or inverted section. So {{#}} means "Render this group of code if we are given a truthy value for its name," {{^}} means "Render this group of code if we aren't given a truthy value for its name," and {{$}} means "Render this group of code if we aren't given a substitution from a partial, and if we are, render that replacement." This expansion of syntax allows more information to remain "in mustache," as mustache is then expanded to mean more things. This trades away the ability to "replace anything" in the parent template for one that has to be prepared with replacement sites and requires a special idea of what is "default" in the template that is above and beyond just the template itself as it would already exist in mustache as it is today.
I also had a solution to that, which was to not get into the key/value syntax business in the first place and leave those to the implementation's maps. In that world, {{}}, {{#}}, and {{^}} can all be replaced equally naturally when the super (actually just a partial, now) is loaded by the implementation with the use of a map of the tag name->source code replacements that the implementation knows how to find. All that's needed is some rules for how those replacements should be made from the map, assuming this map already exists. This offers "replace anything" capability and retains implementation simplicity by avoiding the addition of any new syntax, but it comes at the cost of requiring that derived templates have some external storage format outside of mustache to store their replacement maps (the spec itself shows that mustache can be very naturally embedded in YAML, for one example). I think we assign different weights to how much we value these things; I don't value having a mustache version of a key/value map that much.
Anyhow, I think your idea for derived templates is great, and I think I'm gonna try adding my version to my mustache implementation just to check it out. I just hope the mustache language stays small and provides a small number of very flexible primitives. The language is pretty much defined by the 5 or 6 special characters that start tags, and I hope the language doesn't expand to many more tags than that, or it'll stop being easy to learn and keep in your head.
sayrer commentedon Mar 20, 2012
I added this feature to Hogan as well as the Ruby implementation (not submitted yet).
It's useful and helps avoid triple stache usage.
146 remaining items
groue commentedon Dec 22, 2015
Well done, and thank you, @theLucid ! :-)
nkurothec commentedon Dec 23, 2015
I have an issue. I am doing the inheritance
{{<../email_base}}
{{$email_title}}Your Title here{{/email_title}}
{{$email_content}}
{{/email_content}}
{{/../email_base}}
The only thing is I have two separate folders and my email_base is outside that folder. When I run my project on Intellij I can see everything properly. But mvn fails
mvn test -DskipTests=false passes
mvn verify -DskipTests=false fails
giving me an error
com.github.mustachejava.MustacheNotFoundException: Template developer/../email_developer_base.html.mustache not found
P.S. Very new to mustache
spullara commentedon Dec 23, 2015
Sounds like this is specific to mustache.java. I would post to the google
group:
https://groups.google.com/forum/#!forum/mustachejava
On Tue, Dec 22, 2015 at 5:31 PM, nkurothec notifications@github.com wrote:
dasilvacontin commentedon Apr 5, 2016
@theLucid
{{#renderId}}id="{{id}}"{{/renderId}}. If it depends on whether theidvalue is provided or not,{{#id}}id="{{.}}"{{/id}}.groue commentedon Apr 5, 2016
@theLucid: why don't you just add a regular {{#conditional}} section around the block that you want to optionally render?
spullara commentedon Apr 6, 2016
just include the id= in the the content.
I kind of think of your example is an abuse of the idea of "layout".
bekce commentedon Nov 30, 2017
Hello, can we get a working TL;DR? Thanks
spullara commentedon Jan 25, 2018
@theLucid I am revisiting this thread as I got a request from someone to conditionally render based on whether a section was overridden. After writing some horrid code to implement it with pragmas I'm think that your {{?id}} syntax might be great for this. Did you ultimately end up using that?
jgonggrijp commentedon Aug 9, 2022
Implemented in #75 and #125.