Skip to content

Commit

Permalink
bunch of improvements to make custom tags easier to write, and variou…
Browse files Browse the repository at this point in the history
…s tweaks
  • Loading branch information
jlongster committed May 31, 2013
1 parent 52a7ab3 commit 6d7313e
Show file tree
Hide file tree
Showing 17 changed files with 316 additions and 207 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Expand Up @@ -3,8 +3,9 @@ Changelog for versions previous to v0.1.9 are located at http://nunjucks.tumblr.

# v0.1.9 (May 29, 2013)

* support for custom tags
* autoescaping
* autoescaping ([docs](http://nunjucks.jlongster.com/api#Autoescaping))
* support for custom tags ([docs](http://nunjucks.jlongster.com/api#Custom-Tags-%2526-Extensions))
* the API for the `Environment` object changed slightly ([docs](http://nunjucks.jlongster.com/api#new-Environment%28%255Bloaders%255D%252C-%255Boptions%255D%29))
* ternary conditional operator added (foo if bar else baz)
* various optimizations, comilation is now 1.4x faster
* fix too aggressive caching of templates from HTTP loader
Expand Down
2 changes: 1 addition & 1 deletion bower.json
@@ -1,6 +1,6 @@
{
"name": "nunjucks",
"version": "0.1.8",
"version": "0.1.9",
"main": "browser/nunjucks-min.js",
"ignore": [
"Makefile",
Expand Down
135 changes: 75 additions & 60 deletions browser/nunjucks-dev.js
Expand Up @@ -2099,9 +2099,9 @@ var Parser = Object.extend({
return node;
},

parseSignature: function(tolerant) {
parseSignature: function(tolerant, noParens) {
var tok = this.peekToken();
if(tok.type != lexer.TOKEN_LEFT_PAREN) {
if(!noParens && tok.type != lexer.TOKEN_LEFT_PAREN) {
if(tolerant) {
return null;
}
Expand All @@ -2110,18 +2110,24 @@ var Parser = Object.extend({
}
}

tok = this.nextToken();
if(tok.type == lexer.TOKEN_LEFT_PAREN) {
tok = this.nextToken();
}

var args = new nodes.NodeList(tok.lineno, tok.colno);
var kwargs = new nodes.KeywordArgs(tok.lineno, tok.colno);
var kwnames = [];
var checkComma = false;

while(1) {
tok = this.peekToken();
if(tok.type == lexer.TOKEN_RIGHT_PAREN) {
if(!noParens && tok.type == lexer.TOKEN_RIGHT_PAREN) {
this.nextToken();
break;
}
else if(noParens && tok.type == lexer.TOKEN_BLOCK_END) {
break;
}

if(checkComma && !this.skip(lexer.TOKEN_COMMA)) {
this.fail("parseSignature: expected comma after expression",
Expand Down Expand Up @@ -2434,56 +2440,56 @@ var Compiler = Object.extend({
var contentArgs = node.contentArgs;
var transformedArgs = [];

this._bufferAppend(function() {
this.emit('env.getExtension("' + node.extName + '")["' + node.prop + '"](');
this.emit('context');
this.emit(this.buffer + ' += runtime.suppressValue(');
this.emit('env.getExtension("' + node.extName + '")["' + node.prop + '"](');
this.emit('context');

if(args || contentArgs) {
this.emit(',');
}

if(args || contentArgs) {
this.emit(',');
if(args) {
if(!(args instanceof nodes.NodeList)) {
this.fail('compileCallExtension: arguments must be a NodeList, ' +
'use `parser.parseSignature`');
}

if(args) {
if(!(args instanceof nodes.NodeList)) {
this.fail('compileCallExtension: arguments must be a NodeList, ' +
'use `parser.parseSignature`');
}

lib.each(args.children, function(arg, i) {
// Tag arguments are passed normally to the call. Note
// that keyword arguments are turned into a single js
// object as the last argument, if they exist.
this._compileExpression(arg, frame);
lib.each(args.children, function(arg, i) {
// Tag arguments are passed normally to the call. Note
// that keyword arguments are turned into a single js
// object as the last argument, if they exist.
this._compileExpression(arg, frame);

if(i != args.children.length || contentArgs) {
this.emit(',');
}
}, this);
}
if(i != args.children.length || contentArgs) {
this.emit(',');
}
}, this);
}

if(contentArgs) {
lib.each(contentArgs, function(arg, i) {
if(i > 0) {
this.emit(',');
}
if(contentArgs) {
lib.each(contentArgs, function(arg, i) {
if(i > 0) {
this.emit(',');
}

if(arg) {
var id = this.tmpid();
if(arg) {
var id = this.tmpid();

this.emit('function() {');
this.pushBufferId(id);
this.compile(arg, frame);
this.popBufferId();
this.emitLine('return ' + id + ';\n' +
'}');
}
else {
this.emit('null');
}
}, this);
}
this.emit('function() {');
this.pushBufferId(id);
this.compile(arg, frame);
this.popBufferId();
this.emitLine('return ' + id + ';\n' +
'}');
}
else {
this.emit('null');
}
}, this);
}

this.emit(')');
});
this.emit(')');
this.emit(', env.autoesc);\n');
},

compileNodeList: function(node, frame) {
Expand Down Expand Up @@ -3065,21 +3071,23 @@ var Compiler = Object.extend({
},

compileOutput: function(node, frame) {
if (node.children.length == 1 &&
node.children[0].typename == 'TemplateData') {
var val = node.children[0].value;
if (val !== undefined && val !== null) {
this.emit(this.buffer + ' += ');
this.compileLiteral(node.children[0], frame);
this.emit(';\n');
return;
var children = node.children;
for(var i=0, l=children.length; i<l; i++) {
// TemplateData is a special case because it is never
// autoescaped, so simply output it for optimization
if(children[i] instanceof nodes.TemplateData) {
if(children[i].value) {
this.emit(this.buffer + ' += ');
this.compileLiteral(children[i], frame);
this.emitLine(';');
}
}
else {
this.emit(this.buffer + ' += runtime.suppressValue(');
this.compile(children[i], frame);
this.emit(', env.autoesc);\n');
}
}

var _this = this;
this._bufferAppend(function() {
_this._compileChildren(node, frame);
});
},

compileRoot: function(node, frame) {
Expand Down Expand Up @@ -3511,7 +3519,12 @@ var filters = {
if (killwords) {
input = input.substring(0, length);
} else {
input = input.substring(0, input.lastIndexOf(' ', length));
var idx = input.lastIndexOf(' ', length);
if(idx === -1) {
idx = length;
}

input = input.substring(0, idx);
}

input += (end !== undefined && end !== null) ? end : '...';
Expand Down Expand Up @@ -4048,6 +4061,7 @@ var env = modules["environment"];
var compiler = modules["compiler"];
var parser = modules["parser"];
var lexer = modules["lexer"];
var runtime = modules["runtime"];
var loaders = modules["loaders"];

nunjucks = {};
Expand All @@ -4067,6 +4081,7 @@ if(loaders) {
nunjucks.compiler = compiler;
nunjucks.parser = parser;
nunjucks.lexer = lexer;
nunjucks.runtime = runtime;

nunjucks.require = function(name) { return modules[name]; };

Expand Down
2 changes: 1 addition & 1 deletion browser/nunjucks-min.js

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion browser/nunjucks.js
Expand Up @@ -824,7 +824,12 @@ var filters = {
if (killwords) {
input = input.substring(0, length);
} else {
input = input.substring(0, input.lastIndexOf(' ', length));
var idx = input.lastIndexOf(' ', length);
if(idx === -1) {
idx = length;
}

input = input.substring(0, idx);
}

input += (end !== undefined && end !== null) ? end : '...';
Expand Down Expand Up @@ -1302,6 +1307,7 @@ var env = modules["environment"];
var compiler = modules["compiler"];
var parser = modules["parser"];
var lexer = modules["lexer"];
var runtime = modules["runtime"];
var loaders = modules["loaders"];

nunjucks = {};
Expand All @@ -1321,6 +1327,7 @@ if(loaders) {
nunjucks.compiler = compiler;
nunjucks.parser = parser;
nunjucks.lexer = lexer;
nunjucks.runtime = runtime;

nunjucks.require = function(name) { return modules[name]; };

Expand Down
4 changes: 3 additions & 1 deletion index.js
Expand Up @@ -3,6 +3,7 @@ var env = require('./src/environment');
var compiler = require('./src/compiler');
var parser = require('./src/parser');
var lexer = require('./src/lexer');
var runtime = require('./src/runtime');
var loaders = require('./src/loaders');

module.exports = {};
Expand All @@ -21,4 +22,5 @@ if(loaders) {

module.exports.compiler = compiler;
module.exports.parser = parser;
module.exports.lexer = lexer;
module.exports.lexer = lexer;
module.exports.runtime = runtime;

0 comments on commit 6d7313e

Please sign in to comment.