-
Notifications
You must be signed in to change notification settings - Fork 424
BLOCKS pragma
Make sure you're using Mustache.php v2.7.0 or higher, so that you can use the BLOCKS pragma.
{
"require": {
"mustache/mustache": "~2.7"
}
}
Install the package with composer install
or composer update
.
Let's adapt the hello world example from the repo README to use blocks.
<?php
require 'vendor/autoload.php';
$m = new Mustache_Engine([
'partials' => [
'parent' => '{{% BLOCKS }}Hello {{$ planet }}planet{{/ planet }}'
],
]);
echo $m->render('{{% BLOCKS }}{{< parent }}{{$ planet }}world!{{/ planet }}{{/ parent }}', []);
This returns:
Hello world!
If you know you are going to be using the BLOCKS pragma throughout your entire
application you can also enable globally when constructing the Mustache_Engine
:
$m = new Mustache_Engine([
'pragmas' => [Mustache_Engine::PRAGMA_BLOCKS],
'partials' => [
'parent' => 'Hello {{$ planet }}planet{{/ planet }}'
],
]);
echo $m->render('{{< parent }}{{$ planet }}World!{{/ planet }}{{/ parent }}', []);
Say we have a template named layout.mustache
. This would be our generic site
layout template, consisting of all the sorts of things you'd expect in a layout
template. Many of these values in layout.mustache
would really be dependent on
what is being rendered into it. For example each page probably specifies
additional JavaScript files that should be loaded. Beyond that, it is nice to
have a convenient way for pages to share common markup, without having to split
the common markup into {{> top }}
and {{> bottom }}
partials.
In other templating languages this behavior is achieved using a feature called template inheritance. Content templates are said "inherit" from layout templates. We have chosen to call this feature "blocks", as inheritance is an overloaded term.
Let's take a look at a content template that inherits from a layout template.
<!-- layout.mustache -->
{{% BLOCKS }}
<!DOCTYPE html>
<html>
<head>
<title>{{$ title }}My Awesome Site{{/ title }}</title>
{{$ stylesheets }}
<link rel="stylesheet" href="/assets/css/default.css">
{{/ stylesheets }}
</head>
<body>
<header>
{{$ header }}
<h1>Welcome to My Awesome Site</h1>
{{/ header }}
</header>
<div id="content">
{{$ content }}
<p>Hello, World!</p>
{{/ content }}
</div>
{{$ scripts }}
<script src="/assets/js/default.js"></script>
{{/ scripts }}
</body>
</html>
<!-- article.mustache -->
{{% BLOCKS }}
{{< layout }}
{{$ title }}{{ article.title }}{{/ title }}
{{$ stylesheets }}
<link rel="stylesheet" href="/assets/css/default.css">
<link rel="stylesheet" href="/assets/css/article.css">
{{/ stylesheets }}
{{$ content }}
<p>{{ article.body }}</p>
{{/ content }}
{{$ scripts }}
<script src="/assets/js/default.js"></script>
<script src="/assets/js/article.js"></script>
{{/ scripts }}
{{/ layout }}
Rendering article.mustache with this context:
[
'article' => [
'title' => 'How to do x, y and z',
'body' => '<p>First do x, then do y, then do z.</p>'
],
]
would result in this rendered output:
<!-- layout.mustache -->
<!DOCTYPE html>
<html>
<head>
<title>How to do x, y and z</title>
<link rel="stylesheet" href="/assets/css/default.css">
<link rel="stylesheet" href="/assets/css/article.css">
</head>
<body>
<header>
<h1>Welcome to My Awesome Site</h1>
</header>
<section id="content">
<p>First do x, then do y, then do z.</p>
</section>
<script src="/assets/js/default.js"></script>
<script src="/assets/js/article.js"></script>
</body>
</html>
Many tokens are not allowed directly inside the parent ({{< }}
) tags including sections
({{# }}
), inverted sections ({{^ }}
), partials ({{> }}
) and tokenizer
directives ({{= }}
). For example, all of the following templates will result
in compiler errors:
{{< foo }}{{# bar }}{{$ baz }}{{/ baz }}{{/ bar }}{{/ foo }}
{{< foo }}{{^ bar }}{{$ baz }}set by template{{/ baz }}{{/ bar }}{{/ foo }}
{{< foo }}{{> qux }}{{$ baz }}set by template{{/ baz }}{{/ foo }}
{{< foo }}{{=<% %>=}}<%={{ }}=%>{{/ foo }}
Extensive template inheritance tests are available here.
Ongoing discussion on the semantics of template inheritance as it relates to the mustache spec can be found at this mustache spec pull request.
Thanks to @sayrer for the template inheritance feature in hogan.js, which we stole, tests and all. Much thanks to my coworkers @dtb, @mdg and @benburry at @Etsy. And thanks to @bobthecow for a lot of feedback and help with this implementation.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.