diff options
-rw-r--r-- | lib/template.js | 61 | ||||
-rw-r--r-- | test/plugins.js | 122 | ||||
-rw-r--r-- | test/plugins/blocks/index.js | 11 |
3 files changed, 102 insertions, 92 deletions
diff --git a/lib/template.js b/lib/template.js index 41362c8..d9d3a2f 100644 --- a/lib/template.js +++ b/lib/template.js @@ -1,13 +1,12 @@ var _ = require("lodash"); var Q = require("q"); -var path = require("path"); var nunjucks = require("nunjucks"); var escapeStringRegexp = require("escape-string-regexp"); var batch = require("./utils/batch"); var pkg = require("../package.json"); var defaultBlocks = require("./blocks"); -var BookLoader = require("./conrefs_loader") +var BookLoader = require("./conrefs_loader"); // Normalize result from a block function normBlockResult(blk) { @@ -29,12 +28,12 @@ var TemplateEngine = function(book) { // Tags tags: { - blockStart: '{%', - blockEnd: '%}', - variableStart: '{{', - variableEnd: '}}', - commentStart: '{###', - commentEnd: '###}' + blockStart: "{%", + blockEnd: "%}", + variableStart: "{{", + variableEnd: "}}", + commentStart: "{###", + commentEnd: "###}" } } ); @@ -63,7 +62,7 @@ TemplateEngine.prototype.processBlock = function(blk) { }); blk.id = _.uniqueId("blk"); - var toAdd = (!blk.parse) || (blk.post != undefined); + var toAdd = (!blk.parse) || (blk.post !== undefined); // Add to global map if (toAdd) this.blockBodies[blk.id] = blk; @@ -111,11 +110,11 @@ TemplateEngine.prototype.bindContext = function(func) { TemplateEngine.prototype.addFilter = function(filterName, func) { try { this.env.getFilter(filterName); - this.log.warn.ln("conflict in filters, '"+filterName+"' is already set"); + this.log.warn.ln("conflict in filters, \""+filterName+"\" is already set"); return false; } catch(e) {} - this.log.debug.ln("add filter '"+filterName+"'"); + this.log.debug.ln("add filter \""+filterName+"\""); this.env.addFilter(filterName, this.bindContext(function() { var ctx = this; var args = Array.prototype.slice.apply(arguments); @@ -139,7 +138,7 @@ TemplateEngine.prototype.addFilters = function(filters) { // Return nunjucks extension name of a block TemplateEngine.prototype.blockExtName = function(name) { - return 'Block'+name+'Extension'; + return "Block"+name+"Extension"; }; // Test if a block is defined @@ -173,22 +172,22 @@ TemplateEngine.prototype.addBlock = function(name, block) { blocks: [] }); - var extName = this.blockExtName(name); + extName = this.blockExtName(name); if (this.hasBlock(name) && !defaultBlocks[name]) { - this.log.warn.ln("conflict in blocks, '"+name+"' is already defined"); + this.log.warn.ln("conflict in blocks, \""+name+"\" is already defined"); } // Cleanup previous block this.removeBlock(name); - this.log.debug.ln("add block '"+name+"'"); + this.log.debug.ln("add block \""+name+"\""); this.blocks[name] = block; - var Ext = function () { + Ext = function () { this.tags = [name]; - this.parse = function(parser, nodes, lexer) { + this.parse = function(parser, nodes) { var body = null; var lastBlockName = null; var lastBlockArgs = null; @@ -229,7 +228,7 @@ TemplateEngine.prototype.addBlock = function(name, block) { var bodies = [body]; _.each(block.blocks, function(blockName) { subbodies[blockName] = subbodies[blockName] || []; - if (subbodies[blockName].length == 0) { + if (subbodies[blockName].length === 0) { subbodies[blockName].push({ args: new nodes.NodeList(), body: new nodes.NodeList() @@ -239,7 +238,7 @@ TemplateEngine.prototype.addBlock = function(name, block) { bodies.push(subbodies[blockName][0].body); }); - return new nodes.CallExtensionAsync(this, 'run', args, bodies); + return new nodes.CallExtensionAsync(this, "run", args, bodies); }; this.run = function(context) { @@ -273,12 +272,12 @@ TemplateEngine.prototype.addBlock = function(name, block) { args: args, kwargs: kwargs, blocks: _blocks - }); + }, context); }) // process the block returned .then(that.processBlock) - .nodeify(callback) + .nodeify(callback); }; }; @@ -288,7 +287,7 @@ TemplateEngine.prototype.addBlock = function(name, block) { // 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+"' for parsers ", shortcut.parsers); + this.log.debug.ln("add template shortcut from \""+shortcut.start+"\" to block \""+name+"\" for parsers ", shortcut.parsers); this.shortcuts.push({ block: name, parsers: shortcut.parsers, @@ -311,11 +310,11 @@ TemplateEngine.prototype.addBlocks = function(blocks) { // Apply a block to some content // This method result depends on the type of block (async or sync) -TemplateEngine.prototype.applyBlock = function(name, blk) { - var func, block, func, r; +TemplateEngine.prototype.applyBlock = function(name, blk, ctx) { + var func, block, r; block = this.blocks[name]; - if (!block) throw new Error('Block not found "'+name+'"'); + if (!block) throw new Error("Block not found \""+name+"\""); if (_.isString(blk)) { blk = { body: blk @@ -330,7 +329,7 @@ TemplateEngine.prototype.applyBlock = function(name, blk) { // Bind and call block processor func = this.bindContext(block.process); - r = func(blk); + r = func.call(ctx || {}, blk); if (Q.isPromise(r)) return r.then(normBlockResult); else return normBlockResult(r); @@ -341,7 +340,7 @@ TemplateEngine.prototype._applyShortcut = function(parser, content, shortcut) { if (!_.contains(shortcut.parsers, parser)) return content; var regex = new RegExp( escapeStringRegexp(shortcut.start) + "([\\s\\S]*?[^\\$])" + escapeStringRegexp(shortcut.end), - 'g' + "g" ); return content.replace(regex, function(all, match) { return "{% "+shortcut.tag.start+" %}"+ match + "{% "+shortcut.tag.end+" %}"; @@ -350,7 +349,7 @@ TemplateEngine.prototype._applyShortcut = function(parser, content, shortcut) { // Render a string from the book TemplateEngine.prototype.renderString = function(content, context, options) { - var context = _.extend({}, context, { + context = _.extend({}, context, { // Variables from book.json book: this.book.options.variables, @@ -382,8 +381,8 @@ TemplateEngine.prototype.renderString = function(content, context, options) { }; // Render a file from the book -TemplateEngine.prototype.renderFile = function(filename, options) { - var that = this, context; +TemplateEngine.prototype.renderFile = function(filename) { + var that = this; return that.book.readFile(filename) .then(function(content) { @@ -395,7 +394,7 @@ TemplateEngine.prototype.renderFile = function(filename, options) { // Render a page from the book TemplateEngine.prototype.renderPage = function(page) { - var that = this, context; + var that = this; return that.book.statFile(page.path) .then(function(stat) { diff --git a/test/plugins.js b/test/plugins.js index 6d5b9de..e6df389 100644 --- a/test/plugins.js +++ b/test/plugins.js @@ -1,13 +1,12 @@ -var _ = require('lodash'); -var should = require('should'); -var path = require('path'); -var fs = require('fs'); +var _ = require("lodash"); +var should = require("should"); +var path = require("path"); -var Plugin = require('../lib/plugin'); +var Plugin = require("../lib/plugin"); var parsers = require("gitbook-parsers"); -var PLUGINS_ROOT = path.resolve(__dirname, 'plugins'); +var PLUGINS_ROOT = path.resolve(__dirname, "plugins"); -describe('Plugins', function () { +describe("Plugins", function () { var book; before(function() { @@ -17,7 +16,7 @@ describe('Plugins', function () { }); }); - describe('Invalid', function() { + describe("Invalid", function() { var plugin; before(function() { @@ -25,12 +24,12 @@ describe('Plugins', function () { plugin.load("./invalid", PLUGINS_ROOT); }); - it('should be detected', function() { + it("should be detected", function() { should(plugin.isValid()).be.exactly(false); }); }); - describe('Empty', function() { + describe("Empty", function() { var plugin; before(function() { @@ -38,11 +37,11 @@ describe('Plugins', function () { plugin.load("./empty", PLUGINS_ROOT); }); - it('should valid a plugin', function() { + it("should valid a plugin", function() { should(plugin.isValid()).be.exactly(true); }); - it('should return an empty list of resources', function() { + it("should return an empty list of resources", function() { return plugin.getResources() .then(function(resources) { _.each(Plugin.RESOURCES, function(resName) { @@ -52,7 +51,7 @@ describe('Plugins', function () { }); }); - describe('Resources', function() { + describe("Resources", function() { var plugin; before(function() { @@ -62,45 +61,45 @@ describe('Plugins', function () { return book.plugins.load(plugin); }); - it('should valid a plugin', function() { + it("should valid a plugin", function() { should(plugin.isValid()).be.exactly(true); }); - describe('Website', function() { - it('should return a valid list of resources', function() { + describe("Website", function() { + it("should return a valid list of resources", function() { return plugin.getResources("website") .then(function(resources) { - resources["js"].should.have.lengthOf(1); + resources.js.should.have.lengthOf(1); }); }); - it('should extend books plugins', function() { + it("should extend books plugins", function() { var resources = book.plugins.resources("website"); - resources["js"].should.have.lengthOf(1); + resources.js.should.have.lengthOf(1); }); }); - describe('eBook', function() { - it('should return a valid list of resources', function() { + describe("eBook", function() { + it("should return a valid list of resources", function() { return plugin.getResources("ebook") .then(function(resources) { - resources["css"].should.have.lengthOf(1); + resources.css.should.have.lengthOf(1); }); }); - it('should extend books plugins', function() { + it("should extend books plugins", function() { var resources = book.plugins.resources("ebook"); // There is resources from highlight plugin and this plugin - resources["css"].should.have.lengthOf(2); - should.exist(_.find(resources["css"], { - path: './resources/test' + resources.css.should.have.lengthOf(2); + should.exist(_.find(resources.css, { + path: "./resources/test" })); }); }); }); - describe('Filters', function() { + describe("Filters", function() { var plugin; before(function() { @@ -110,11 +109,11 @@ describe('Plugins', function () { return book.plugins.load(plugin); }); - it('should valid a plugin', function() { + it("should valid a plugin", function() { should(plugin.isValid()).be.exactly(true); }); - it('should return a map of filters', function() { + it("should return a map of filters", function() { var filters = plugin.getFilters(); _.size(filters).should.equal(2); @@ -122,22 +121,22 @@ describe('Plugins', function () { filters.should.have.property("helloCtx"); }); - it('should correctly extend template filters', function() { - return book.template.renderString('{{ "World"|hello }}') + it("should correctly extend template filters", function() { + return book.template.renderString("{{ \"World\"|hello }}") .then(function(content) { content.should.equal("Hello World"); }); }); - it('should correctly set book as context', function() { - return book.template.renderString('{{ "root"|helloCtx }}') + it("should correctly set book as context", function() { + return book.template.renderString("{{ \"root\"|helloCtx }}") .then(function(content) { content.should.equal("root:"+book.root); }); }); }); - describe('Blocks', function() { + describe("Blocks", function() { var plugin; before(function() { @@ -149,22 +148,22 @@ describe('Plugins', function () { var testTpl = function(str, args, options) { return book.template.renderString(str, args, options) - .then(book.template.postProcess) + .then(book.template.postProcess); }; - it('should valid a plugin', function() { + it("should valid a plugin", function() { should(plugin.isValid()).be.exactly(true); }); - it('should correctly extend template blocks', function() { - return testTpl('{% test %}hello{% endtest %}') + it("should correctly extend template blocks", function() { + return testTpl("{% test %}hello{% endtest %}") .then(function(content) { content.should.equal("testhellotest"); }); }); - it('should correctly accept shortcuts', function() { - return testTpl('$$hello$$', {}, { + it("should correctly accept shortcuts", function() { + return testTpl("$$hello$$", {}, { type: "markdown" }) .then(function(content) { @@ -172,43 +171,50 @@ describe('Plugins', function () { }); }); - it('should correctly extend template blocks with defined end', function() { - return testTpl('{% test2 %}hello{% endtest2end %}') + it("should correctly extend template blocks with defined end", function() { + return testTpl("{% test2 %}hello{% endtest2end %}") .then(function(content) { content.should.equal("test2hellotest2"); }); }); - it('should correctly extend template blocks with sub-blocks', function() { - return testTpl('{% test3join separator=";" %}hello{% also %}world{% endtest3join %}') + it("should correctly extend template blocks with sub-blocks", function() { + return testTpl("{% test3join separator=\";\" %}hello{% also %}world{% endtest3join %}") .then(function(content) { content.should.equal("hello;world"); }); }); - it('should correctly extend template blocks with different sub-blocks', function() { - return testTpl('{% test4join separator=";" %}hello{% also %}the{% finally %}world{% endtest4join %}') + it("should correctly extend template blocks with different sub-blocks", function() { + return testTpl("{% test4join separator=\";\" %}hello{% also %}the{% finally %}world{% endtest4join %}") .then(function(content) { content.should.equal("hello;the;world"); }); }); - it('should correctly extend template blocks with arguments', function() { - return testTpl('{% test5args "a", "b", "c" %}{% endtest5args %}') + it("should correctly extend template blocks with arguments", function() { + return testTpl("{% test5args 'a', 'b', 'c' %}{% endtest5args %}") .then(function(content) { content.should.equal("test5a,b,ctest5"); }); }); - it('should correctly extend template blocks with args and kwargs', function() { - return testTpl('{% test5kwargs "a", "b", "c", d="test", e="test2" %}{% endtest5kwargs %}') + it("should correctly extend template blocks with args and kwargs", function() { + return testTpl("{% test5kwargs 'a', 'b', 'c', d='test', e='test2' %}{% endtest5kwargs %}") .then(function(content) { content.should.equal("test5a,b,c,d:test,e:test2,__keywords:truetest5"); }); }); + + it("should correctly extend template blocks with access to context", function() { + return testTpl("{% set name = 'john' %}{% test6context %}{% endtest6context %}", {}) + .then(function(content) { + content.should.equal("test6johntest6"); + }); + }); }); - describe('Blocks without parsing', function() { + describe("Blocks without parsing", function() { var plugin; before(function() { @@ -222,21 +228,21 @@ describe('Plugins', function () { var filetype = parsers.get(markup); return book.template.renderString(str, args, options) - .then(filetype.page).get('sections').get(0).get('content') - .then(book.template.postProcess) + .then(filetype.page).get("sections").get(0).get("content") + .then(book.template.postProcess); }; - it('should correctly process unparsable for markdown', function() { - return testTpl('.md', '{% test %}**hello**{% endtest %}') + it("should correctly process unparsable for markdown", function() { + return testTpl(".md", "{% test %}**hello**{% endtest %}") .then(function(content) { content.should.equal("<p>test**hello**test</p>\n"); }); }); - it('should correctly process unparsable for asciidoc', function() { - return testTpl('.adoc', '{% test %}**hello**{% endtest %}') + it("should correctly process unparsable for asciidoc", function() { + return testTpl(".adoc", "{% test %}**hello**{% endtest %}") .then(function(content) { - content.should.equal('<div class="paragraph">\n<p>test**hello**test</p>\n</div>'); + content.should.equal("<div class=\"paragraph\">\n<p>test**hello**test</p>\n</div>"); }); }); }); diff --git a/test/plugins/blocks/index.js b/test/plugins/blocks/index.js index 0848238..9bdbe86 100644 --- a/test/plugins/blocks/index.js +++ b/test/plugins/blocks/index.js @@ -39,18 +39,23 @@ module.exports = { }, "test5args": { process: function(blk) { - return "test5"+blk.args.join(',')+"test5"; + return "test5"+blk.args.join(",")+"test5"; } }, "test5kwargs": { process: function(blk) { - var s = blk.args.join(','); + var s = blk.args.join(","); for (var key in blk.kwargs) { - s = s + ','+key+':'+blk.kwargs[key]; + s = s + ","+key+":"+blk.kwargs[key]; } return "test5"+s+"test5"; } }, + "test6context": { + process: function() { + return "test6"+(this.ctx.name)+"test6"; + } + }, } };
\ No newline at end of file |