I'm playing around with this right now in Python (note I'm the creator of Mako), adding in a dynamic context that captures sections seems to be doing the right thing, though I'd need to test this a lot more.
Basically we are using lambdas, where a "<" prefix indicates "inherit from this template" (similar to the syntax discussed at https://github.com/mustache/spec/issues/38) and a "$" prefix indicates "this is an inherited section".
import pystache
class NameSpace(object):
def __init__(self, renderer, vars_={}):
self.renderer = renderer
self._content = {}
self.vars = vars_
def add_content(self, name, value):
self._content[name] = value
def __getattr__(self, key):
if key in self.vars:
# regular symbol in the vars dictionary
return self.vars[key]
elif key.startswith("<"):
# an "inherit from this template" directive
name = key[1:]
return inheritor(self, name)
elif key.startswith("$"):
# a "here's a replaceable section" directive
name = key[1:]
if name in self._content:
# if we have this section collected, return the rendered
# version
return sub_renderer(self, name)
else:
# else render it here and collect it
return collector(self, name)
else:
# unknown key.
raise AttributeError(key)
def sub_renderer(namespace, key):
def go():
def render(nested):
return namespace._content[key]
return render
return go
def collector(namespace, key):
def go():
def render(nested):
content = namespace.renderer.render(nested, namespace)
namespace.add_content(key, content)
return content
return render
return go
def inheritor(namespace, name):
def go():
def render(nested):
namespace.renderer.render(nested, namespace)
return namespace.renderer.render_name(name, namespace)
return render
return go
So here's some templates. base.mustache:
<html>
{{#$header}}
default header
{{/$header}}
{{#$body}}
default body
{{/$body}}
{{#$footer}}
default footer, using {{local key}}
{{/$footer}}
</html>
hello.mustache:
{{#<base}}
{{#$header}}
new header
{{/$header}}
{{#$body}}
new body, with {{local key}}
{{/$body}}
{{/<base}}
and then to play with three levels deep, subhello.mustache:
{{#<hello}}
{{#$footer}}
im some new footer
{{/$footer}}
{{/<hello}}
Rendering hello.mustache like this:
renderer = pystache.Renderer(search_dirs=["./templates/"])
print renderer.render_name("hello",
NameSpace(renderer, {"local key": "some local key"}))
output:
<html>
new header
new body, with some local key
default footer, using some local key
</html>
Rendering subhello.mustache:
print renderer.render_name("subhello",
NameSpace(renderer, {"local key": "some local key"}))
output:
<html>
new header
new body, with some local key
im some new footer
</html>
I just wrote this in twenty minutes, and I've only used handlebars.js a little bit in the past and pystache for the first time just now so the whole "mustache" idea is not deep for me yet. But this seems to work ?