Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Commit

Permalink
Add support for template inheritance from content
Browse files Browse the repository at this point in the history
There is no common way of specifying blocks, so the patterns are specified by user. See extends test cases for example use.
  • Loading branch information
mayo committed Aug 31, 2014
1 parent 2a7d907 commit 43a2d0d
Show file tree
Hide file tree
Showing 17 changed files with 252 additions and 4 deletions.
61 changes: 58 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ var join = require('path').join;
var match = require('multimatch');
var omit = require('lodash.omit');

var util = require('util');

/**
* Expose `plugin`.
*/
Expand All @@ -17,7 +19,7 @@ module.exports = plugin;
* Settings.
*/

var settings = ['engine', 'directory', 'pattern', 'inPlace', 'default'];
var settings = ['engine', 'directory', 'pattern', 'inPlace', 'default', 'useExtends', 'defaultExtends', 'defaultBlock'];

/**
* Metalsmith plugin to run files through any template in a template `dir`.
Expand All @@ -28,6 +30,11 @@ var settings = ['engine', 'directory', 'pattern', 'inPlace', 'default'];
* @property {String} engine
* @property {String} inPlace (optional)
* @property {String} pattern (optional)
* @property {Boolean} useExtends (optional)
* @property {String} defaultExtends (optional)
* @property {String} defaultBlock (optional)
* @property {String} extendsPattern (optional)
* @property {String} blockPattern (optional)
* @return {Function}
*/

Expand All @@ -41,6 +48,29 @@ function plugin(opts){
var pattern = opts.pattern;
var inPlace = opts.inPlace;
var def = opts.default;

var useExtends = opts.useExtends;
var defaultExtends = opts.defaultExtends;
var defaultBlock = opts.defaultBlock;
var extendsPattern = opts.extendsPattern;
var blockPattern = opts.blockPattern;

if ((defaultExtends || defaultBlock) && !useExtends) {
throw new Error('"useExtends" option required to use defaultExtends or defaultBlock');
}

if (useExtends && !extendsPattern) {
throw new Error('"extendsPattern" required with "useExtends"');
}

if (useExtends && defaultBlock && !blockPattern) {
throw new Error('"blockPattern" required with "useExtends" and "defaultBlock"');
}

if (blockPattern && !(Array.isArray(blockPattern) && blockPattern.length >= 1)) {
throw new Error('"blockPattern" must be an array with at least one element (block opening pattern).');
}

var params = omit(opts, settings);

return function(files, metalsmith, done){
Expand All @@ -49,8 +79,10 @@ function plugin(opts){
function check(file){
var data = files[file];
var tmpl = data.template || def;
var ext = useExtends ? data.extends || defaultExtends : false;

if (pattern && !match(file, pattern)[0]) return false;
if (!inPlace && !tmpl) return false;
if (!inPlace && !tmpl && !ext) return false;
return true;
}

Expand All @@ -74,6 +106,29 @@ function plugin(opts){
if (inPlace) {
str = clone.contents;
render = consolidate[engine].render;

} else if (useExtends) {
if (useExtends) {
clone.extends = data.extends || defaultExtends;
//fake a filename, make it in templates directory, so rest of templates
//in inheritance chain can be resolves
clone.filename = metalsmith.join(dir, clone.extends);
}

str = util.format(extendsPattern, clone.extends);

if (defaultBlock) {
str += util.format(blockPattern[0], defaultBlock);
}

str += clone.contents;

if (defaultBlock && blockPattern.length > 1) {
str += util.format(blockPattern[1], defaultBlock);
}

render = consolidate[engine].render;

} else {
str = metalsmith.join(dir, data.template || def);
render = consolidate[engine];
Expand All @@ -87,4 +142,4 @@ function plugin(opts){
});
}
};
}
}
12 changes: 12 additions & 0 deletions test/fixtures/extends-def_block/build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<html>
<head>
<title>TITLE</title>
<style>

</style>
</head>
<body>
CONTENT here

</body>
</html>
Binary file not shown.
Binary file not shown.
12 changes: 12 additions & 0 deletions test/fixtures/extends-def_block/expected/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<html>
<head>
<title>TITLE</title>
<style>

</style>
</head>
<body>
CONTENT here

</body>
</html>
6 changes: 6 additions & 0 deletions test/fixtures/extends-def_block/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: TITLE
content: CONTENT
extends: base.html
---
{{ content }} here
11 changes: 11 additions & 0 deletions test/fixtures/extends-def_block/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<head>
<title>{{ title }}</title>
<style>
{% block css %}{% endblock %}
</style>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
15 changes: 15 additions & 0 deletions test/fixtures/extends-def_extends/build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>
<head>
<title>TITLE</title>
<style>

/* CSS here */

</style>
</head>
<body>

CONTENT here

</body>
</html>
Binary file not shown.
15 changes: 15 additions & 0 deletions test/fixtures/extends-def_extends/expected/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>
<head>
<title>TITLE</title>
<style>

/* CSS here */

</style>
</head>
<body>

CONTENT here

</body>
</html>
11 changes: 11 additions & 0 deletions test/fixtures/extends-def_extends/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: TITLE
content: CONTENT
---
{% block css %}
/* CSS here */
{% endblock %}

{% block content %}
{{ content }} here
{% endblock %}
11 changes: 11 additions & 0 deletions test/fixtures/extends-def_extends/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<head>
<title>{{ title }}</title>
<style>
{% block css %}{% endblock %}
</style>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
15 changes: 15 additions & 0 deletions test/fixtures/extends/build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>
<head>
<title>TITLE</title>
<style>

/* CSS here */

</style>
</head>
<body>

CONTENT here

</body>
</html>
15 changes: 15 additions & 0 deletions test/fixtures/extends/expected/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>
<head>
<title>TITLE</title>
<style>

/* CSS here */

</style>
</head>
<body>

CONTENT here

</body>
</html>
12 changes: 12 additions & 0 deletions test/fixtures/extends/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: TITLE
content: CONTENT
extends: base.html
---
{% block css %}
/* CSS here */
{% endblock %}

{% block content %}
{{ content }} here
{% endblock %}
11 changes: 11 additions & 0 deletions test/fixtures/extends/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<head>
<title>{{ title }}</title>
<style>
{% block css %}{% endblock %}
</style>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
49 changes: 48 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,51 @@ describe('metalsmith-templates', function(){
done();
});
});
});

it('should extend templates', function(done){
Metalsmith('test/fixtures/extends')
.use(templates({
engine: 'swig',
useExtends: true,
extendsPattern: '{% extends "%s" %}'
}))
.build(function(err){
if (err) return done(err);
equal('test/fixtures/extends/expected', 'test/fixtures/extends/build');
done();
});
});

it('should extend using default block', function(done){
Metalsmith('test/fixtures/extends-def_block')
.use(templates({
engine: 'swig',
useExtends: true,
defaultBlock: 'content',
extendsPattern: '{% extends "%s" %}',
blockPattern: [ '{% block %s %}', '{% endblock %}' ]
}))
.build(function(err){
if (err) return done(err);
equal('test/fixtures/extends-def_block/expected', 'test/fixtures/extends-def_block/build');
done();
});

});

it('should extend using default extends', function(done){
Metalsmith('test/fixtures/extends-def_extends')
.use(templates({
engine: 'swig',
useExtends: true,
defaultExtends: 'base.html',
extendsPattern: '{% extends "%s" %}'
}))
.build(function(err){
if (err) return done(err);
equal('test/fixtures/extends-def_extends/expected', 'test/fixtures/extends-def_extends/build');
done();
});
});

});

0 comments on commit 43a2d0d

Please sign in to comment.