Is it possible to use templates that extend each other?
Say, I have these files:
base.html:
<html><head>...<head><body>{{{ contents }}}</body></html>
threeColumns.html:
---
layout: base.html
---
<div class="three-cols-row">
<div class="first col">
{{> nav}}
</div>
<div class="second col">
{{{ contents }}}
</div>
<div class="third col">
{{> aside}}
</div>
</div>
somePost.html:
---
layout: threeColumns.html
---
My awesome blogbost
Desired output:
<html><head>...<head>
<body>
<div class="three-cols-row">
<div class="first col">
NAV CONTENT
</div>
<div class="second col">
My awesome blogbost
</div>
<div class="third col">
ASIDE CONTENT
</div>
</div>
</body>
</html>
I am using metalsmith-layouts.
It is, but not exactly in the way that you want to.
Metalsmith-layouts is meant to be a shim for template inheritance for languages that don't natively support it, like handlebars. To make this possible it parses the files that you pass to it, somePost.html
in this case, and looks for a layout
key in the front-matter. After that it processes the chosen layout, threeColumns.html
, by passing somePost.html
to threeColumns.html
as the variable contents
.
At that point the file is rendered with your chosen engine by consolidate. So the layout
key, which is specific to metalsmith-layouts
no longer works in threeColumns.html
because metalsmith-layouts doesn't process it. At this point the file is being processed by consolidate.
What you can do is use a language that natively supports template inheritance, like swig. Then you could do:
build.js
/**
* Dependencies
*/
var filenames = require('metalsmith-filenames');
var layouts = require('metalsmith-layouts');
var metalsmith = require('metalsmith');
/**
* Build
*/
metalsmith(__dirname)
.use(filenames()) // Necessary for extends and includes
.use(layouts('swig'))
.build(function(err){
if (err) throw err;
});
src/somePost.swig
---
layout: threeColumns.swig
---
<p>My awesome blogpost</p>
layouts/threeColumns.swig
{% extends "base.swig" %}
{% block body %}
<div class="three-cols-row">
<div class="first col">
{% include "nav.swig" %}
</div>
<div class="second col">
{{ contents | safe }}
</div>
<div class="third col">
{% include "aside.swig" %}
</div>
</div>
{% endblock %}
layouts/base.swig
<html>
<head><head>
<body>
{% block body %}{% endblock %}
</body>
</html>
layouts/nav.swig
<nav>Navigation</nav>
layouts/aside.swig
<aside>Aside content</aside>
If you then run node build.js
from the command line, it'll build it into a single page.