Mustache template inheritance extension

1,303 views
Skip to first unread message

Sam

unread,
Oct 28, 2011, 12:07:13 PM10/28/11
to mustache.java
I've just recently added a new set of commands to the mustache.java
implementation, I'd love to get feedback from the community on them.
Basically, it adds Django-like template inheritance in a declarative
fashion. This makes it much easier to create a top-level layout that
then every page inherits from and overrides. This makes building sites
in mustache much less verbose and allows you to ensure that behavior
and markup is being added to every page. It can even be used for
creating standard components that are reused.

The implementation is available in the latest 0.6-SNAPSHOT. I will
likely be cutting a 0.6 soon after I'm sure that this feature is
working as expected. In 0.7 I will be removing the now deprecated
MustacheCompiler in favor of the MustacheBuilder as the Compiler has
proven to be worse in almost every way (performance, extensibility,
etc).

Sam

Mustache Template Inheritance

Motivation

Mustache has no terse way to share layout between pages except through
redundant partial includes in every template. Django templates have a
nice system where you can inherit from a super template and leave
places in that template that can be filled in with subtemplates. This
design describes how we could do that in Mustache.

Requirements

- Layout should be easy to express in supertemplate and used by the
sub templates
- It should be easily implemented by our java, ruby and javascript
versions of mustache if necessary
- Performance impact should be minimal and not impose any restrictions
on subtemplates
- All of our tooling, like the Handlebar server, should work with the
new system natively

Design

We add 3 additional commands in mustache:

- {{<extend}}.. template text with replacement references..{{/
extend}}

In a sub-template you declare the inclusion of a super-template, each
default template text is replaced with its matching replacement
template text, everything else being ignored. This new template then
replaces the extend reference.

- {{$name}}.. default template text ..{{/name}}

A named section of a super-template that if not replaced results in
the default template text. Nothing stops a super-template from being
executed as a valid template that uses all default template text.

- {{=name}}.. replacement template text ..{{/name}}

This tag must be used in the context of an {{<extend}} operation and
match one of the named sections or result in an error.

Examples

super.mustache:
<html>
<head>
<title>{{$title}}Default Title{{/title}}</title>
{{$head}}{{/head}}
<script src="jquery.min.js"></script>
</head>
<body>
<div class="body">
{{$body}}Default Body{{/body}}
</div>
<div class="footer">
{{$footer}}{{/footer}}
</div>
</body>
</html>

sub.mustache:
{{<super}}
{{=title}}Subtitle{{/title}}
{{=body}}Hello, world!{{/body}}
{{/super}}

Would result in this equivalent template:
<html>
<head>
<title>Subtitle</title>
<script src="jquery.min.js"></script>
</head>
<body>
<div class="body">
Hello, world!
</div>
<div class="footer">
</div>
</body>
</html>

Mariano Campo

unread,
Oct 29, 2011, 2:41:35 PM10/29/11
to mustache.java
Thanks Sam! This feature is much appreciated, I tried it out and it
works great :)

I was evaluating mustache for a new project, and was already building
custom code arround it to support base templates. With this new
feature i'll definitely go with mustache.

One question though, why did you have to create a "replacement"
operator ('=')? Couldn't it just be a named section on the sub-
template that matches the name of an existing section on the super-
template?

Thanks again,
Mariano.

Sam Pullara

unread,
Oct 29, 2011, 2:54:20 PM10/29/11
to mustac...@googlegroups.com
Thanks for the feedback!

No real reason except for usability. Since they could be nested I
thought it would be confusing to see them used for two different
things in the same file. Does that make sense or do you still think it
was a mistake to make them distinct?

Sam

Sent from my iPhone

Mariano Campo

unread,
Oct 29, 2011, 4:10:20 PM10/29/11
to mustac...@googlegroups.com
The distinction does make sense if you think of the tags as operators. From that point of view I agree it's clearer to have a different symbol to mark a replacement, it's more explicit. But to me thinking of this as operations is another step away from the logic-less ideal.

However if you think of them as blocks that can be overriden in sub-templates (like Django blocks), i think it makes more sense to use the same symbol. I think this approach gives the templates a more declarative feeling, since you don't see section and replacement tags, you just see blocks.

Anyway, it's really just a detail, but since being logic-less (or looking like it) is one of mustache's goals i though i should mention it :)

Sam Pullara

unread,
Oct 29, 2011, 10:24:37 PM10/29/11
to mustac...@googlegroups.com
I'm sympathetic to your argument and have a branch where it is implemented like this and it works pretty well. Anyone else want to chime on in on their preferences?

Sam

Sam

unread,
Oct 30, 2011, 7:16:02 PM10/30/11
to mustache.java
Since I haven't heard anything and I like this a lot better, this is
what is now in 0.6-SNAPSHOT.

Sam

On Oct 29, 7:24 pm, Sam Pullara <s...@sampullara.com> wrote:
> I'm sympathetic to your argument and have a branch where it is implemented like this and it works pretty well. Anyone else want to chime on in on their preferences?
>
> Sam
>
> On Oct 29, 2011, at 1:10 PM, Mariano Campo wrote:
>
>
>
>
>
>
>
> > The distinction does make sense if you think of the tags as operators. From that point of view I agree it's clearer to have a different symbol to mark a replacement, it's more explicit. But to me thinking of this as operations is another step away from the logic-less ideal.
>
> > However if you think of them as blocks that can be overriden in sub-templates (like Django blocks), i think it makes more sense to use the same symbol. I think this approach gives the templates a more declarative feeling, since you don't see section and replacement tags, you just see blocks.
>
> > Anyway, it's really just a detail, but since being logic-less (or looking like it) is one of mustache's goals i though i should mention it :)
>
> > On Sat, Oct 29, 2011 at 3:54 PM, Sam Pullara <spull...@gmail.com> wrote:
> > Thanks for the feedback!
>
> > No real reason except for usability.  Since they could be nested I
> > thought it would be confusing to see them used for two different
> > things in the same file. Does that make sense or do you still think it
> > was a mistake to make them distinct?
>
> > Sam
>
> > Sent from my iPhone
>

Mariano Campo

unread,
Oct 31, 2011, 9:04:09 AM10/31/11
to mustac...@googlegroups.com
Cool Sam, thanks!

Amir Khawaja

unread,
Jan 29, 2012, 2:11:23 PM1/29/12
to mustac...@googlegroups.com
I have a newbie question.  Where might I find examples of using this feature?  Thank you.

Amir.

Sam

unread,
Jan 30, 2012, 12:02:31 PM1/30/12
to mustache.java
Hi Amir,

What kind of examples? I gave an example at the beginning of this
thread that should be illustrative. Do you mean an end-to-end example
with code? For that you can look at the test for the feature here:

https://github.com/spullara/mustache.java/blob/master/builder/src/test/java/com/sampullara/mustache/ExtensionTest.java

Sam
Message has been deleted

Sam Pullara

unread,
May 28, 2014, 4:26:30 PM5/28/14
to mustac...@googlegroups.com
That link is a github link to it in master. 

Sam

---
Sent from Boxer | http://getboxer.com
On May 28, 2014 at 12:48:36 PM PDT, Juan-Carlos Aguilar <jca...@gmail.com> wrote:
sam:

Is this available? I can't seem to find it in master.

JC

--
You received this message because you are subscribed to the Google Groups "mustache.java" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mustachejava...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages