diff --git a/examples/parsetree.jade b/examples/parsetree.jade index 5640db68f..603cdab35 100644 --- a/examples/parsetree.jade +++ b/examples/parsetree.jade @@ -1,5 +1,8 @@ :conditionals if role == 'admin' - p User #{name} is an administrator + if name == 'tj' + p User is a wicked cool administrator + else + p User #{name} is an administrator else p User #{name} is a guest \ No newline at end of file diff --git a/examples/parsetree.js b/examples/parsetree.js index 2e576ea99..e92d9c6df 100644 --- a/examples/parsetree.js +++ b/examples/parsetree.js @@ -5,6 +5,7 @@ */ var jade = require('./../lib/jade'), + Compiler = jade.Compiler, nodes = jade.nodes; var options = { @@ -20,26 +21,39 @@ jade.renderFile(__dirname + '/parsetree.jade', options, function(err, html){ console.log(html); }); -// To support nesting etc you will need to create a more -// robust compiler, view ./lib/compiler.js for the core example. +jade.filters.conditionals = function(block, compiler){ + return new Visitor(block).compile(); +}; -// Without our filter we could either construct an entirely new string, -// and simply return it (using "buf.push('buffered text')") etc, or utilize -// the core compiler which is passed +function Visitor(node) { + this.node = node; +} -jade.filters.conditionals = function(block, compiler){ - block.nodes.forEach(function(node, i){ - switch (node.name) { - case 'if': - block.nodes[i] = new nodes.Code('if (' + node.block.nodes[0].lines[0] + ')'); - node.block.nodes.shift(); - block.nodes[i].block = node.block; - break; - case 'else': - block.nodes[i] = new nodes.Code('else'); - block.nodes[i].block = node.block; - break; - } - }); - compiler.visit(block); -}; \ No newline at end of file +Visitor.prototype.__proto__ = Compiler.prototype; + +Visitor.prototype.visit = function(node){ + if (node.name != 'else') this.line(node); + this.visitNode(node); +}; + +Visitor.prototype.visitTag = function(node){ + switch (node.name) { + case 'if': + var condition = node.block.nodes[0].lines[0], + block = node.block; + block.nodes.shift(); + node = new nodes.Code('if (' + condition + ')', false); + node.block = block; + this.visit(node); + break; + case 'else': + var block = node.block; + node = new nodes.Code('else', false); + node.block = block; + node.instrumentLineNumber = false; + this.visit(node); + break; + default: + Compiler.prototype.visitTag.call(this, node); + } +}; diff --git a/lib/compiler.js b/lib/compiler.js index 7f52cf97d..4a6a75803 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -74,6 +74,7 @@ Compiler.prototype = { */ line: function(node){ + if (node.instrumentLineNumber === false) return; this.buf.push('_.lineno = ' + node.line + ';'); }, @@ -85,11 +86,19 @@ Compiler.prototype = { */ visit: function(node){ - var name = node.constructor.name; - if (name != 'Code' || !node.val.match(/^ *else/)) { - this.line(node); - } - return this['visit' + name](node); + this.line(node); + return this.visitNode(node); + }, + + /** + * Visit `node`. + * + * @param {Node} node + * @api private + */ + + visitNode: function(node){ + return this['visit' + node.constructor.name](node); }, /** @@ -228,9 +237,9 @@ Compiler.prototype = { this.buf.push(code.val); } if (code.block) { - this.buf.push('(function(){'); + this.buf.push(' (function(){'); this.visit(code.block); - this.buf.push('}).call(this);'); + this.buf.push(' }).call(this);'); } }, diff --git a/lib/nodes/code.js b/lib/nodes/code.js index a76f6a805..77f565995 100644 --- a/lib/nodes/code.js +++ b/lib/nodes/code.js @@ -6,6 +6,7 @@ var Code = module.exports = function Code(val, buffer, escape) { this.val = val; this.buffer = buffer; this.escape = escape; + if (/^ *else/.test(val)) this.instrumentLineNumber = false; }; Code.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/test/jade.test.js b/test/jade.test.js index 1d3174eed..627947f67 100644 --- a/test/jade.test.js +++ b/test/jade.test.js @@ -594,6 +594,22 @@ module.exports = { '

no foo

' ].join(''); + assert.equal(html, render(str)); + + var str = [ + '- var foo;', + '- if (foo)', + ' p.hasFoo= foo', + '- else if (true)', + ' p kinda foo', + '- else', + ' p.noFoo no foo' + ].join('\n'); + + var html = [ + '

kinda foo

' + ].join(''); + assert.equal(html, render(str)); var str = [