diff options
-rw-r--r-- | lib/template.js | 35 | ||||
-rw-r--r-- | lib/utils/string.js | 5 | ||||
-rw-r--r-- | test/plugins.js | 10 | ||||
-rw-r--r-- | test/plugins/blocks/index.js | 5 |
4 files changed, 54 insertions, 1 deletions
diff --git a/lib/template.js b/lib/template.js index ec1b391..070173c 100644 --- a/lib/template.js +++ b/lib/template.js @@ -4,6 +4,7 @@ var path = require("path"); var nunjucks = require("nunjucks"); var git = require("./utils/git"); +var stringUtils = require("./utils/string"); var fs = require("./utils/fs"); var pkg = require("../package.json"); @@ -65,6 +66,9 @@ var TemplateEngine = function(book) { } } ); + + // List of tags shortcuts + this.shortcuts = []; }; @@ -86,6 +90,7 @@ TemplateEngine.prototype.addBlock = function(name, block) { var that = this; block = _.defaults(block || {}, { + shortcuts: [], end: "end"+name, process: _.identity, blocks: [] @@ -93,7 +98,7 @@ TemplateEngine.prototype.addBlock = function(name, block) { var extName = 'Block'+name+'Extension'; if (this.env.getExtension(extName)) { - this.log.warn.ln("conflict in blocks, '"+extName+"' is already defined"); + this.log.warn.ln("conflict in blocks, '"+name+"' is already defined"); return false; } @@ -194,6 +199,31 @@ TemplateEngine.prototype.addBlock = function(name, block) { // Add the Extension this.env.addExtension(extName, new Ext()); + + // Add shortcuts + if (!_.isArray(block.shortcuts)) block.shortcuts = [block.shortcuts]; + _.each(block.shortcuts, function(shortcut) { + this.log.debug.ln("add template shortcut from '"+shortcut.start+"' to block '"+name+"'"); + this.shortcuts.push({ + start: shortcut.start, + end: shortcut.end, + tag: { + start: name, + end: block.end + } + }); + }, this); +}; + +// Apply a shortcut to a string +TemplateEngine.prototype._applyShortcut = function(content, shortcut) { + var regex = new RegExp( + stringUtils.escapeRegex(shortcut.start) + "\\s*([\\s\\S]*?[^\\$])\\s*" + stringUtils.escapeRegex(shortcut.end), + 'g' + ); + return content.replace(regex, function(all, match) { + return "{% "+shortcut.tag.start+" %}"+ match + "{% "+shortcut.tag.end+" %}"; + }); }; // Render a string from the book @@ -210,6 +240,9 @@ TemplateEngine.prototype.renderString = function(content, context, options) { options = _.defaults(options || {}, { path: null}); if (options.path) options.path = this.book.resolve(options.path); + // Replace shortcuts + content = _.reduce(this.shortcuts, this._applyShortcut.bind(this), content); + return Q.nfcall(this.env.renderString.bind(this.env), content, context, options); }; diff --git a/lib/utils/string.js b/lib/utils/string.js index 72a9ca0..588f4d9 100644 --- a/lib/utils/string.js +++ b/lib/utils/string.js @@ -20,7 +20,12 @@ function optionsToShellArgs(options) { .join(" "); } +function escapeRegex(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); +} + module.exports = { + escapeRegex: escapeRegex, escapeShellArg: escapeShellArg, optionsToShellArgs: optionsToShellArgs, toLowerCase: String.prototype.toLowerCase.call.bind(String.prototype.toLowerCase) diff --git a/test/plugins.js b/test/plugins.js index 3c60a20..43ce497 100644 --- a/test/plugins.js +++ b/test/plugins.js @@ -98,6 +98,16 @@ describe('Plugins', function () { ); }); + it('should correctly accept shortcuts', function(done) { + qdone( + books[0].template.renderString('$$hello$$') + .then(function(content) { + assert.equal(content, "testhellotest"); + }), + done + ); + }); + it('should correctly extend template blocks with defined end', function(done) { qdone( books[0].template.renderString('{% test2 %}hello{% endtest2end %}') diff --git a/test/plugins/blocks/index.js b/test/plugins/blocks/index.js index b8f72fe..0a02ff7 100644 --- a/test/plugins/blocks/index.js +++ b/test/plugins/blocks/index.js @@ -3,6 +3,11 @@ var assert = require("assert"); module.exports = { blocks: { "test": { + shortcuts: { + parsers: ["markdown"], + start: "$$", + end: "$$" + }, process: function(blk) { return "test"+blk.body+"test"; } |