Skip to content
This repository has been archived by the owner on Aug 22, 2023. It is now read-only.

Customize grunt-swig with additional tags. #26

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ module.exports = function (grunt) {
siteUrl: 'http://mydomain.net/',
generateSitemap: true,
generateRobotstxt: true,
tags: {
countargs: require('./test/tag'),
markdown: require('./node_modules/swig-extras/lib/tags/markdown')
},
test: {
var1: 'long path file',
var2: 'short path file'
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ swig: {
init: {
autoescape: true
},
tags: {
countargs: require('./test/tag')
},
dest: "www/",
src: ['**/*.swig'],
generateSitemap: true,
Expand Down Expand Up @@ -70,6 +73,28 @@ You need to give the relative path to the output html file for this to work.
Path and base name of the source template file are available in `tplFile` variable, `tplFile.path` for
the path and `tplFile.basename` for the basename.

The 'tags' property is an object that allows you to extend swig with any tag found on
internet with the [common structure](https://github.com/paularmstrong/swig/blob/v1.3.2/lib/tags/block.js).
Key, value of the object is respectively: name of the tag, library/file required.
Value it's always a `require()`, it may be a _custom_ file of yours or another NPM library.
[swig-extras](https://github.com/paularmstrong/swig-extras) and
[swig-extensions](https://github.com/assemble/swig-extensions) tags are supported, you need to require
directly the file, ex: `require('./node_modules/swig-extras/lib/tags/markdown')`

Common structure:
```javascript
exports.parse = function(str, line, parser, types, stack, options)
exports.compile = function(compiler, args, content, parents, options, blockName)
exports.ends = true/false
exports.block = true/false
```
Refer to [official Swig documentation](http://paularmstrong.github.io/swig/docs/extending/#tags).

The 'filters' property allows you to expose custom filters to your templates.
In the above example the filter `f` is created and mapped to the CommonJS file
module named `myfilter.js` at the root of the project. The module must export a
function whose name matches the filter ('f' in this case).

## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"grunt": "~0.4.1",
"grunt-contrib-clean": "~0.5.0",
"grunt-mocha-test": "~0.7.0",
"grunt-contrib-jshint": "~0.7.2"
"grunt-contrib-jshint": "~0.7.2",
"swig-extras": "0.0.1"
},
"peerDependencies": {
"grunt": "~0.4.1"
Expand Down
14 changes: 14 additions & 0 deletions tasks/swig.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ module.exports = function(grunt) {
swig.setDefaults(config.data.init);
}

if (config.data.tags !== undefined) {
Object.keys(config.data.tags).forEach(function (tag, index) {
var tagObj = config.data.tags[tag];
// compatibility with swig-extentions and swig-extras
var block = tagObj.blockLevel !== undefined ? tagObj.blockLevel : tagObj.block;
// ext is an extension to the interpreter, usually exposes functionality, ex: a markdown compiler
// as an object in the swig context (_ctx.<objectname>)
if (tagObj.ext) {
swig.setExtension(tagObj.ext.name, tagObj.ext.obj);
}
swig.setTag(tag, tagObj.parse, tagObj.compile, tagObj.ends, block);
});
}

try {
globalVars = grunt.util._.extend(config.data, grunt.file.readJSON(process.cwd() + '/global.json'));
} catch (err) {
Expand Down
29 changes: 29 additions & 0 deletions test/fixtures/markdown.swig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{% markdown %}
# swig extensions

> Tags, filters, and extensions for [Swig](http://paularmstrong.github.io/swig/), the most awesome template engine for node.js.

This project is based on (and complementary to) [swig-extras](https://github.com/paularmstrong/swig-extras), from [@paularmstrong](https://github.com/paularmstrong)


## Getting started

Use a filter:

```
var swig = require('swig');
var extensions = require('swig-extensions');

extensions.useFilter(swig, 'markdown');
```

Use a tag:

```
var swig = require('swig');
var extensions = require('swig-extensions');
var mySwig = new swig.Swig();

extensions.useTag(mySwig, 'markdown');
```
{% endmarkdown %}
3 changes: 3 additions & 0 deletions test/fixtures/tag.swig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% countargs 'firstarg' 'secondarg' %}
This part gets ignored in this test!
{% endcountargs %}
9 changes: 9 additions & 0 deletions test/swig_test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global describe:false, it:false */
'use strict';

var assert = require('assert'),
Expand Down Expand Up @@ -45,4 +46,12 @@ describe('grunt-swig', function() {
helpers.assertFile('test/dest/robots.txt');
});

it('should compile a custom tag', function () {
helpers.assertFile('test/dest/fixtures/tag.html', /args\:.*firstarg/);
});

it('should compile a custom tag from swig-extras', function () {
helpers.assertFile('test/dest/fixtures/markdown.html', /a href=.http\:\/\/paularmstrong/);
});

});
27 changes: 27 additions & 0 deletions test/tag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Official documentation about extending Swig Tags
// http://paularmstrong.github.io/swig/docs/extending/#tags

// Source code of how parse is defined:
// https://github.com/paularmstrong/swig/blob/v1.3.2/lib/parser.js#L550-L570
//
// Correctly writing swig extensions might be tricky, get an idea about what
// a TokenParser is: https://github.com/paularmstrong/swig/blob/v1.3.2/lib/parser.js#L109-L127
exports.parse = function(str, line, parser, types, stack, options) {
parser.on(types.STRING, function (token) {
// strip quote or double quote, they _also_ get matched
token.match = token.match.replace(/^("|')|("|')$/g, '');
this.out.push(token.match);
});
return true;
};

// Source code, to see how it gets used:
// https://github.com/paularmstrong/swig/blob/v1.3.2/lib/parser.js#L720-L738
//
exports.compile = function(compiler, args, content, parents, options, blockName) {
var concatArgs = '[ ' + args.join(', ') + ' ]';
return '_output += "args: ' + concatArgs + '";\n';
};

exports.ends = true;
exports.block = true;