Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nunjucks

Package Overview
Dependencies
Maintainers
2
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nunjucks - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

appveyor.yml

72

bench/run.js

@@ -0,1 +1,3 @@

'use strict';
var fs = require('fs');

@@ -18,47 +20,47 @@ var bench = require('bench');

current: true,
name: "James"
name: 'James'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
},
{
name: "Foo",
url: "http://example.com"
{
name: 'Foo',
url: 'http://example.com'
}

@@ -77,3 +79,3 @@ ]

'new-nunjucks': function(done) {
tmpl.render(ctx, done);
tmpl.render(ctx, done);
}

@@ -80,0 +82,0 @@ };

@@ -1,2 +0,2 @@

// Browser bundle of nunjucks 1.1.0 (slim, only works with precompiled templates)
// Browser bundle of nunjucks 1.3.0 (slim, only works with precompiled templates)

@@ -6,2 +6,3 @@ (function() {

(function() {
'use strict';

@@ -23,4 +24,4 @@ // A simple class system, more documentation to come

if(typeof parent == "function" &&
typeof src == "function" &&
if(typeof parent === 'function' &&
typeof src === 'function' &&
fnTest.test(src)) {

@@ -58,5 +59,5 @@ prototype[k] = (function (src, parent) {

new_cls.extend = function(name, props) {
if(typeof name == "object") {
if(typeof name === 'object') {
props = name;
name = "anonymous";
name = 'anonymous';
}

@@ -69,5 +70,7 @@ return extend(new_cls, name, props);

modules['object'] = extend(Object, "Object", {});
modules['object'] = extend(Object, 'Object', {});
})();
(function() {
'use strict';
var ArrayProto = Array.prototype;

@@ -79,5 +82,5 @@ var ObjProto = Object.prototype;

'"': '"',
"'": ''',
"<": '&lt;',
">": '&gt;'
'\'': '&#39;',
'<': '&lt;',
'>': '&gt;'
};

@@ -119,3 +122,3 @@

err = message;
message = message.name + ": " + message.message;
message = message.name + ': ' + message.message;
} else {

@@ -134,3 +137,3 @@ if(Error.captureStackTrace) {

err.Update = function(path) {
var message = "(" + (path || "unknown path") + ")";
var message = '(' + (path || 'unknown path') + ')';

@@ -168,15 +171,15 @@ // only show lineno + colno next to path of template

exports.isFunction = function(obj) {
return ObjProto.toString.call(obj) == '[object Function]';
return ObjProto.toString.call(obj) === '[object Function]';
};
exports.isArray = Array.isArray || function(obj) {
return ObjProto.toString.call(obj) == '[object Array]';
return ObjProto.toString.call(obj) === '[object Array]';
};
exports.isString = function(obj) {
return ObjProto.toString.call(obj) == '[object String]';
return ObjProto.toString.call(obj) === '[object String]';
};
exports.isObject = function(obj) {
return ObjProto.toString.call(obj) == '[object Object]';
return ObjProto.toString.call(obj) === '[object Object]';
};

@@ -236,3 +239,3 @@

if(ArrayProto.each && obj.each == ArrayProto.each) {
if(ArrayProto.each && obj.each === ArrayProto.each) {
obj.forEach(func, context);

@@ -337,3 +340,3 @@ }

Array.prototype.map = function() {
throw new Error("map is unimplemented for this js engine");
throw new Error('map is unimplemented for this js engine');
};

@@ -358,2 +361,4 @@ }

(function() {
'use strict';
var lib = modules["lib"];

@@ -377,3 +382,3 @@ var Obj = modules["object"];

var frame = this;
if(resolveUp) {

@@ -419,3 +424,3 @@ if((frame = this.resolve(parts[0]))) {

var val = this.variables[name];
if(val != null) {
if(val !== undefined && val !== null) {
return this;

@@ -513,3 +518,3 @@ }

function SafeString(val) {
if(typeof val != 'string') {
if(typeof val !== 'string') {
return val;

@@ -559,5 +564,5 @@ }

function suppressValue(val, autoescape) {
val = (val !== undefined && val !== null) ? val : "";
val = (val !== undefined && val !== null) ? val : '';
if(autoescape && typeof val === "string") {
if(autoescape && typeof val === 'string') {
val = lib.escape(val);

@@ -639,3 +644,3 @@ }

if(finished == len) {
if(finished === len) {
cb(null, outputArr.join(''));

@@ -649,3 +654,3 @@ }

if(len == 0) {
if(len === 0) {
cb(null, '');

@@ -673,3 +678,3 @@ }

if(len == 0) {
if(len === 0) {
cb(null, '');

@@ -706,2 +711,5 @@ }

(function() {
'use strict';
var path = modules["path"];
var Obj = modules["object"];

@@ -725,2 +733,10 @@ var lib = modules["lib"];

}
},
resolve: function(from, to) {
return path.resolve(path.dirname(from), to);
},
isRelative: function(filename) {
return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0);
}

@@ -732,2 +748,4 @@ });

(function() {
'use strict';
var Loader = modules["loader"];

@@ -749,3 +767,3 @@

return {
src: { type: "code",
src: { type: 'code',
obj: this.precompiled[name] },

@@ -777,3 +795,3 @@ path: name

else if(window.ActiveXObject) { // IE 8 and older
ajax = new ActiveXObject("Microsoft.XMLHTTP");
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}

@@ -805,2 +823,4 @@

(function() {
'use strict';
if(typeof window === 'undefined' || window !== this) {

@@ -814,2 +834,4 @@ modules['loaders'] = modules["node-loaders"];

(function() {
'use strict';
var lib = modules["lib"];

@@ -862,4 +884,4 @@ var r = modules["runtime"];

var spaces = width - str.length;
var pre = lib.repeat(" ", spaces/2 - spaces % 2);
var post = lib.repeat(" ", spaces/2);
var pre = lib.repeat(' ', spaces/2 - spaces % 2);
var post = lib.repeat(' ', spaces/2);
return r.copySafeness(str, pre + str + post);

@@ -874,3 +896,3 @@ },

if (!lib.isObject(val)) {
throw new lib.TemplateError("dictsort filter: val must be an object");
throw new lib.TemplateError('dictsort filter: val must be an object');
}

@@ -885,9 +907,9 @@

var si;
if (by === undefined || by === "key") {
if (by === undefined || by === 'key') {
si = 0;
} else if (by === "value") {
} else if (by === 'value') {
si = 1;
} else {
throw new lib.TemplateError(
"dictsort filter: You can only sort by either key or value");
'dictsort filter: You can only sort by either key or value');
}

@@ -908,3 +930,3 @@

return a > b ? 1 : (a == b ? 0 : -1);
return a > b ? 1 : (a === b ? 0 : -1);
});

@@ -916,3 +938,3 @@

escape: function(str) {
if(typeof str == 'string' ||
if(typeof str === 'string' ||
str instanceof r.SafeString) {

@@ -943,3 +965,3 @@ return lib.escape(str);

for(var i=0; i<lines.length; i++) {
if(i == 0 && !indentfirst) {
if(i === 0 && !indentfirst) {
res += lines[i] + '\n';

@@ -996,4 +1018,7 @@ }

}
else if(lib.isArray(val)) {
return val;
}
else {
throw new lib.TemplateError("list filter: type not iterable");
throw new lib.TemplateError('list filter: type not iterable');
}

@@ -1010,2 +1035,14 @@ },

rejectattr: function(arr, attr) {
return arr.filter(function (item) {
return !item[attr];
});
},
selectattr: function(arr, attr) {
return arr.filter(function (item) {
return !!item[attr];
});
},
replace: function(str, old, new_, maxCount) {

@@ -1021,3 +1058,3 @@ if (old instanceof RegExp) {

while(last != res) {
while(last !== res) {
if(count >= maxCount) {

@@ -1058,6 +1095,6 @@ break;

if(method == 'ceil') {
if(method === 'ceil') {
rounder = Math.ceil;
}
else if(method == 'floor') {
else if(method === 'floor') {
rounder = Math.floor;

@@ -1265,2 +1302,3 @@ }

(function() {
'use strict';

@@ -1334,2 +1372,4 @@ function cycler(items) {

(function() {
'use strict';
var path = modules["path"];

@@ -1354,5 +1394,4 @@ var lib = modules["lib"];

// defaults to false
opts = opts || {};
this.dev = !!opts.dev;
this.lexerTags = opts.tags;
var opts = this.opts = opts || {};
this.opts.dev = !!opts.dev;

@@ -1363,4 +1402,8 @@ // The autoescape flag sets global autoescaping. If true,

// defaults to false
this.autoesc = !!opts.autoescape;
this.opts.autoescape = !!opts.autoescape;
this.opts.trimBlocks = !!opts.trimBlocks;
this.opts.lstripBlocks = !!opts.lstripBlocks;
if(!loaders) {

@@ -1392,13 +1435,11 @@ // The filesystem loader is only available client-side

// Caching and cache busting
var cache = {};
lib.each(this.loaders, function(loader) {
loader.cache = {};
lib.each(this.loaders, function(loader) {
if(typeof loader.on === 'function'){
if(typeof loader.on === 'function') {
loader.on('update', function(template) {
cache[template] = null;
loader.cache[template] = null;
});
}
});
this.cache = cache;
},

@@ -1436,3 +1477,10 @@

getTemplate: function(name, eagerCompile, cb) {
resolveTemplate: function(loader, parentName, filename) {
var isRelative = (loader.isRelative && parentName)? loader.isRelative(filename) : false;
return (isRelative && loader.resolve)? loader.resolve(parentName, filename) : filename;
},
getTemplate: function(name, eagerCompile, parentName, cb) {
var that = this;
var tmpl = null;
if(name && name.raw) {

@@ -1443,2 +1491,8 @@ // this fixes autoescape for templates referenced in symbols

if(lib.isFunction(parentName)) {
cb = parentName;
parentName = null;
eagerCompile = eagerCompile || false;
}
if(lib.isFunction(eagerCompile)) {

@@ -1453,3 +1507,7 @@ cb = eagerCompile;

var tmpl = this.cache[name];
for (var i = 0; i < this.loaders.length; i++) {
var _name = this.resolveTemplate(this.loaders[i], parentName, name);
tmpl = this.loaders[i].cache[_name];
if (tmpl) break;
}

@@ -1473,2 +1531,3 @@ if(tmpl) {

if(src) {
src.loader = loader;
done(src);

@@ -1481,2 +1540,5 @@ }

// Resolve name relative to parentName
name = that.resolveTemplate(loader, parentName, name);
if(loader.async) {

@@ -1506,3 +1568,3 @@ loader.getSource(name, function(err, src) {

if(!info.noCache) {
this.cache[name] = tmpl;
info.loader.cache[name] = tmpl;
}

@@ -1572,4 +1634,10 @@

renderString: function(src, ctx, cb) {
var tmpl = new Template(src, this);
renderString: function(src, ctx, opts, cb) {
if(lib.isFunction(opts)) {
cb = opts;
opts = {};
}
opts = opts || {};
var tmpl = new Template(src, this, opts.path);
return tmpl.render(ctx, cb);

@@ -1627,3 +1695,3 @@ }

if(idx == -1 || !blk) {
if(idx === -1 || !blk) {
throw new Error('no super block available for "' + name + '"');

@@ -1663,4 +1731,4 @@ }

else {
throw new Error("src must be a string or an object describing " +
"the source");
throw new Error('src must be a string or an object describing ' +
'the source');
}

@@ -1764,3 +1832,3 @@

this.path,
this.env.lexerTags);
this.env.opts);

@@ -1780,3 +1848,3 @@ var func = new Function(source);

for(var k in props) {
if(k.slice(0, 2) == 'b_') {
if(k.slice(0, 2) === 'b_') {
blocks[k.slice(2)] = props[k];

@@ -1783,0 +1851,0 @@ }

@@ -1,3 +0,3 @@

// Browser bundle of nunjucks 1.1.0 (slim, only works with precompiled templates)
// Browser bundle of nunjucks 1.3.0 (slim, only works with precompiled templates)
(function(){var modules={};(function(){function extend(cls,name,props){var F=function(){};F.prototype=cls.prototype;var prototype=new F;var fnTest=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;props=props||{};for(var k in props){var src=props[k];var parent=prototype[k];if(typeof parent=="function"&&typeof src=="function"&&fnTest.test(src)){prototype[k]=function(src,parent){return function(){var tmp=this.parent;this.parent=parent;var res=src.apply(this,arguments);this.parent=tmp;return res}}(src,parent)}else{prototype[k]=src}}prototype.typename=name;var new_cls=function(){if(prototype.init){prototype.init.apply(this,arguments)}};new_cls.prototype=prototype;new_cls.prototype.constructor=new_cls;new_cls.extend=function(name,props){if(typeof name=="object"){props=name;name="anonymous"}return extend(new_cls,name,props)};return new_cls}modules["object"]=extend(Object,"Object",{})})();(function(){var ArrayProto=Array.prototype;var ObjProto=Object.prototype;var escapeMap={"&":"&amp;",'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;"};var escapeRegex=/[&"'<>]/g;var lookupEscape=function(ch){return escapeMap[ch]};var exports=modules["lib"]={};exports.withPrettyErrors=function(path,withInternals,func){try{return func()}catch(e){if(!e.Update){e=new exports.TemplateError(e)}e.Update(path);if(!withInternals){var old=e;e=new Error(old.message);e.name=old.name}throw e}};exports.TemplateError=function(message,lineno,colno){var err=this;if(message instanceof Error){err=message;message=message.name+": "+message.message}else{if(Error.captureStackTrace){Error.captureStackTrace(err)}}err.name="Template render error";err.message=message;err.lineno=lineno;err.colno=colno;err.firstUpdate=true;err.Update=function(path){var message="("+(path||"unknown path")+")";if(this.firstUpdate){if(this.lineno&&this.colno){message+=" [Line "+this.lineno+", Column "+this.colno+"]"}else if(this.lineno){message+=" [Line "+this.lineno+"]"}}message+="\n ";if(this.firstUpdate){message+=" "}this.message=message+(this.message||"");this.firstUpdate=false;return this};return err};exports.TemplateError.prototype=Error.prototype;exports.escape=function(val){return val.replace(escapeRegex,lookupEscape)};exports.isFunction=function(obj){return ObjProto.toString.call(obj)=="[object Function]"};exports.isArray=Array.isArray||function(obj){return ObjProto.toString.call(obj)=="[object Array]"};exports.isString=function(obj){return ObjProto.toString.call(obj)=="[object String]"};exports.isObject=function(obj){return ObjProto.toString.call(obj)=="[object Object]"};exports.groupBy=function(obj,val){var result={};var iterator=exports.isFunction(val)?val:function(obj){return obj[val]};for(var i=0;i<obj.length;i++){var value=obj[i];var key=iterator(value,i);(result[key]||(result[key]=[])).push(value)}return result};exports.toArray=function(obj){return Array.prototype.slice.call(obj)};exports.without=function(array){var result=[];if(!array){return result}var index=-1,length=array.length,contains=exports.toArray(arguments).slice(1);while(++index<length){if(exports.indexOf(contains,array[index])===-1){result.push(array[index])}}return result};exports.extend=function(obj,obj2){for(var k in obj2){obj[k]=obj2[k]}return obj};exports.repeat=function(char_,n){var str="";for(var i=0;i<n;i++){str+=char_}return str};exports.each=function(obj,func,context){if(obj==null){return}if(ArrayProto.each&&obj.each==ArrayProto.each){obj.forEach(func,context)}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i<l;i++){func.call(context,obj[i],i,obj)}}};exports.map=function(obj,func){var results=[];if(obj==null){return results}if(ArrayProto.map&&obj.map===ArrayProto.map){return obj.map(func)}for(var i=0;i<obj.length;i++){results[results.length]=func(obj[i],i)}if(obj.length===+obj.length){results.length=obj.length}return results};exports.asyncIter=function(arr,iter,cb){var i=-1;function next(){i++;if(i<arr.length){iter(arr[i],i,next,cb)}else{cb()}}next()};exports.asyncFor=function(obj,iter,cb){var keys=exports.keys(obj);var len=keys.length;var i=-1;function next(){i++;var k=keys[i];if(i<len){iter(k,obj[k],i,len,next)}else{cb()}}next()};exports.indexOf=Array.prototype.indexOf?function(arr,searchElement,fromIndex){return Array.prototype.indexOf.call(arr,searchElement,fromIndex)}:function(arr,searchElement,fromIndex){var length=this.length>>>0;fromIndex=+fromIndex||0;if(Math.abs(fromIndex)===Infinity){fromIndex=0}if(fromIndex<0){fromIndex+=length;if(fromIndex<0){fromIndex=0}}for(;fromIndex<length;fromIndex++){if(arr[fromIndex]===searchElement){return fromIndex}}return-1};if(!Array.prototype.map){Array.prototype.map=function(){throw new Error("map is unimplemented for this js engine")}}exports.keys=function(obj){if(Object.prototype.keys){return obj.keys()}else{var keys=[];for(var k in obj){if(obj.hasOwnProperty(k)){keys.push(k)}}return keys}}})();(function(){var lib=modules["lib"];var Obj=modules["object"];var Frame=Obj.extend({init:function(parent){this.variables={};this.parent=parent},set:function(name,val,resolveUp){var parts=name.split(".");var obj=this.variables;var frame=this;if(resolveUp){if(frame=this.resolve(parts[0])){frame.set(name,val);return}frame=this}for(var i=0;i<parts.length-1;i++){var id=parts[i];if(!obj[id]){obj[id]={}}obj=obj[id]}obj[parts[parts.length-1]]=val},get:function(name){var val=this.variables[name];if(val!==undefined&&val!==null){return val}return null},lookup:function(name){var p=this.parent;var val=this.variables[name];if(val!==undefined&&val!==null){return val}return p&&p.lookup(name)},resolve:function(name){var p=this.parent;var val=this.variables[name];if(val!=null){return this}return p&&p.resolve(name)},push:function(){return new Frame(this)},pop:function(){return this.parent}});function makeMacro(argNames,kwargNames,func){return function(){var argCount=numArgs(arguments);var args;var kwargs=getKeywordArgs(arguments);if(argCount>argNames.length){args=Array.prototype.slice.call(arguments,0,argNames.length);var vals=Array.prototype.slice.call(arguments,args.length,argCount);for(var i=0;i<vals.length;i++){if(i<kwargNames.length){kwargs[kwargNames[i]]=vals[i]}}args.push(kwargs)}else if(argCount<argNames.length){args=Array.prototype.slice.call(arguments,0,argCount);for(var i=argCount;i<argNames.length;i++){var arg=argNames[i];args.push(kwargs[arg]);delete kwargs[arg]}args.push(kwargs)}else{args=arguments}return func.apply(this,args)}}function makeKeywordArgs(obj){obj.__keywords=true;return obj}function getKeywordArgs(args){var len=args.length;if(len){var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return lastArg}}return{}}function numArgs(args){var len=args.length;if(len===0){return 0}var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return len-1}else{return len}}function SafeString(val){if(typeof val!="string"){return val}this.val=val}SafeString.prototype=Object.create(String.prototype);SafeString.prototype.valueOf=function(){return this.val};SafeString.prototype.toString=function(){return this.val};function copySafeness(dest,target){if(dest instanceof SafeString){return new SafeString(target)}return target.toString()}function markSafe(val){var type=typeof val;if(type==="string"){return new SafeString(val)}else if(type!=="function"){return val}else{return function(){var ret=val.apply(this,arguments);if(typeof ret==="string"){return new SafeString(ret)}return ret}}}function suppressValue(val,autoescape){val=val!==undefined&&val!==null?val:"";if(autoescape&&typeof val==="string"){val=lib.escape(val)}return val}function memberLookup(obj,val){obj=obj||{};if(typeof obj[val]==="function"){return function(){return obj[val].apply(obj,arguments)}}return obj[val]}function callWrap(obj,name,args){if(!obj){throw new Error("Unable to call `"+name+"`, which is undefined or falsey")}else if(typeof obj!=="function"){throw new Error("Unable to call `"+name+"`, which is not a function")}return obj.apply(this,args)}function contextOrFrameLookup(context,frame,name){var val=frame.lookup(name);return val!==undefined&&val!==null?val:context.lookup(name)}function handleError(error,lineno,colno){if(error.lineno){return error}else{return new lib.TemplateError(error,lineno,colno)}}function asyncEach(arr,dimen,iter,cb){if(lib.isArray(arr)){var len=arr.length;lib.asyncIter(arr,function(item,i,next){switch(dimen){case 1:iter(item,i,len,next);break;case 2:iter(item[0],item[1],i,len,next);break;case 3:iter(item[0],item[1],item[2],i,len,next);break;default:item.push(i,next);iter.apply(this,item)}},cb)}else{lib.asyncFor(arr,function(key,val,i,len,next){iter(key,val,i,len,next)},cb)}}function asyncAll(arr,dimen,func,cb){var finished=0;var len;var outputArr;function done(i,output){finished++;outputArr[i]=output;if(finished==len){cb(null,outputArr.join(""))}}if(lib.isArray(arr)){len=arr.length;outputArr=new Array(len);if(len==0){cb(null,"")}else{for(var i=0;i<arr.length;i++){var item=arr[i];switch(dimen){case 1:func(item,i,len,done);break;case 2:func(item[0],item[1],i,len,done);break;case 3:func(item[0],item[1],item[2],i,len,done);break;default:item.push(i,done);func.apply(this,item)}}}}else{var keys=lib.keys(arr);len=keys.length;outputArr=new Array(len);if(len==0){cb(null,"")}else{for(var i=0;i<keys.length;i++){var k=keys[i];func(k,arr[k],i,len,done)}}}}modules["runtime"]={Frame:Frame,makeMacro:makeMacro,makeKeywordArgs:makeKeywordArgs,numArgs:numArgs,suppressValue:suppressValue,memberLookup:memberLookup,contextOrFrameLookup:contextOrFrameLookup,callWrap:callWrap,handleError:handleError,isArray:lib.isArray,keys:lib.keys,SafeString:SafeString,copySafeness:copySafeness,markSafe:markSafe,asyncEach:asyncEach,asyncAll:asyncAll}})();(function(){var Obj=modules["object"];var lib=modules["lib"];var Loader=Obj.extend({on:function(name,func){this.listeners=this.listeners||{};this.listeners[name]=this.listeners[name]||[];this.listeners[name].push(func)},emit:function(name){var args=Array.prototype.slice.call(arguments,1);if(this.listeners&&this.listeners[name]){lib.each(this.listeners[name],function(listener){listener.apply(null,args)})}}});modules["loader"]=Loader})();(function(){var Loader=modules["loader"];var WebLoader=Loader.extend({init:function(baseURL,neverUpdate){this.precompiled=window.nunjucksPrecompiled||{};this.baseURL=baseURL||"";this.neverUpdate=neverUpdate},getSource:function(name){if(this.precompiled[name]){return{src:{type:"code",obj:this.precompiled[name]},path:name}}else{var src=this.fetch(this.baseURL+"/"+name);if(!src){return null}return{src:src,path:name,noCache:!this.neverUpdate}}},fetch:function(url,callback){var ajax;var loading=true;var src;if(window.XMLHttpRequest){ajax=new XMLHttpRequest}else if(window.ActiveXObject){ajax=new ActiveXObject("Microsoft.XMLHTTP")}ajax.onreadystatechange=function(){if(ajax.readyState===4&&(ajax.status===0||ajax.status===200)&&loading){loading=false;src=ajax.responseText}};url+=(url.indexOf("?")===-1?"?":"&")+"s="+(new Date).getTime();ajax.open("GET",url,false);ajax.send();return src}});modules["web-loaders"]={WebLoader:WebLoader}})();(function(){if(typeof window==="undefined"||window!==this){modules["loaders"]=modules["node-loaders"]}else{modules["loaders"]=modules["web-loaders"]}})();(function(){var lib=modules["lib"];var r=modules["runtime"];var filters={abs:function(n){return Math.abs(n)},batch:function(arr,linecount,fill_with){var res=[];var tmp=[];for(var i=0;i<arr.length;i++){if(i%linecount===0&&tmp.length){res.push(tmp);tmp=[]}tmp.push(arr[i])}if(tmp.length){if(fill_with){for(var i=tmp.length;i<linecount;i++){tmp.push(fill_with)}}res.push(tmp)}return res},capitalize:function(str){var ret=str.toLowerCase();return r.copySafeness(str,ret.charAt(0).toUpperCase()+ret.slice(1))},center:function(str,width){width=width||80;if(str.length>=width){return str}var spaces=width-str.length;var pre=lib.repeat(" ",spaces/2-spaces%2);var post=lib.repeat(" ",spaces/2);return r.copySafeness(str,pre+str+post)},"default":function(val,def){return val?val:def},dictsort:function(val,case_sensitive,by){if(!lib.isObject(val)){throw new lib.TemplateError("dictsort filter: val must be an object")}var array=[];for(var k in val){array.push([k,val[k]])}var si;if(by===undefined||by==="key"){si=0}else if(by==="value"){si=1}else{throw new lib.TemplateError("dictsort filter: You can only sort by either key or value")}array.sort(function(t1,t2){var a=t1[si];var b=t2[si];if(!case_sensitive){if(lib.isString(a)){a=a.toUpperCase()}if(lib.isString(b)){b=b.toUpperCase()}}return a>b?1:a==b?0:-1});return array},escape:function(str){if(typeof str=="string"||str instanceof r.SafeString){return lib.escape(str)}return str},safe:function(str){return r.markSafe(str)},first:function(arr){return arr[0]},groupby:function(arr,attr){return lib.groupBy(arr,attr)},indent:function(str,width,indentfirst){width=width||4;var res="";var lines=str.split("\n");var sp=lib.repeat(" ",width);for(var i=0;i<lines.length;i++){if(i==0&&!indentfirst){res+=lines[i]+"\n"}else{res+=sp+lines[i]+"\n"}}return r.copySafeness(str,res)},join:function(arr,del,attr){del=del||"";if(attr){arr=lib.map(arr,function(v){return v[attr]})}return arr.join(del)},last:function(arr){return arr[arr.length-1]},length:function(arr){return arr!==undefined?arr.length:0},list:function(val){if(lib.isString(val)){return val.split("")}else if(lib.isObject(val)){var keys=[];if(Object.keys){keys=Object.keys(val)}else{for(var k in val){keys.push(k)}}return lib.map(keys,function(k){return{key:k,value:val[k]}})}else{throw new lib.TemplateError("list filter: type not iterable")}},lower:function(str){return str.toLowerCase()},random:function(arr){return arr[Math.floor(Math.random()*arr.length)]},replace:function(str,old,new_,maxCount){if(old instanceof RegExp){return str.replace(old,new_)}var res=str;var last=res;var count=1;res=res.replace(old,new_);while(last!=res){if(count>=maxCount){break}last=res;res=res.replace(old,new_);count++}return r.copySafeness(str,res)},reverse:function(val){var arr;if(lib.isString(val)){arr=filters.list(val)}else{arr=lib.map(val,function(v){return v})}arr.reverse();if(lib.isString(val)){return r.copySafeness(val,arr.join(""))}return arr},round:function(val,precision,method){precision=precision||0;var factor=Math.pow(10,precision);var rounder;if(method=="ceil"){rounder=Math.ceil}else if(method=="floor"){rounder=Math.floor}else{rounder=Math.round}return rounder(val*factor)/factor},slice:function(arr,slices,fillWith){var sliceLength=Math.floor(arr.length/slices);var extra=arr.length%slices;var offset=0;var res=[];for(var i=0;i<slices;i++){var start=offset+i*sliceLength;if(i<extra){offset++}var end=offset+(i+1)*sliceLength;var slice=arr.slice(start,end);if(fillWith&&i>=extra){slice.push(fillWith)}res.push(slice)}return res},sort:function(arr,reverse,caseSens,attr){arr=lib.map(arr,function(v){return v});arr.sort(function(a,b){var x,y;if(attr){x=a[attr];y=b[attr]}else{x=a;y=b}if(!caseSens&&lib.isString(x)&&lib.isString(y)){x=x.toLowerCase();y=y.toLowerCase()}if(x<y){return reverse?1:-1}else if(x>y){return reverse?-1:1}else{return 0}});return arr},string:function(obj){return r.copySafeness(obj,obj)},title:function(str){var words=str.split(" ");for(var i=0;i<words.length;i++){words[i]=filters.capitalize(words[i])}return r.copySafeness(str,words.join(" "))},trim:function(str){return r.copySafeness(str,str.replace(/^\s*|\s*$/g,""))},truncate:function(input,length,killwords,end){var orig=input;length=length||255;if(input.length<=length)return input;if(killwords){input=input.substring(0,length)}else{var idx=input.lastIndexOf(" ",length);if(idx===-1){idx=length}input=input.substring(0,idx)}input+=end!==undefined&&end!==null?end:"...";return r.copySafeness(orig,input)},upper:function(str){return str.toUpperCase()},urlencode:function(obj){var enc=encodeURIComponent;if(lib.isString(obj)){return enc(obj)}else{var parts;if(lib.isArray(obj)){parts=obj.map(function(item){return enc(item[0])+"="+enc(item[1])})}else{parts=[];for(var k in obj){if(obj.hasOwnProperty(k)){parts.push(enc(k)+"="+enc(obj[k]))}}}return parts.join("&")}},urlize:function(str,length,nofollow){if(isNaN(length))length=Infinity;var noFollowAttr=nofollow===true?' rel="nofollow"':"";var puncRE=/^(?:\(|<|&lt;)?(.*?)(?:\.|,|\)|\n|&gt;)?$/;var emailRE=/^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;var httpHttpsRE=/^https?:\/\/.*$/;var wwwRE=/^www\./;var tldRE=/\.(?:org|net|com)(?:\:|\/|$)/;var words=str.split(/\s+/).filter(function(word){return word&&word.length}).map(function(word){var matches=word.match(puncRE);var possibleUrl=matches&&matches[1]||word;if(httpHttpsRE.test(possibleUrl))return'<a href="'+possibleUrl+'"'+noFollowAttr+">"+possibleUrl.substr(0,length)+"</a>";if(wwwRE.test(possibleUrl))return'<a href="http://'+possibleUrl+'"'+noFollowAttr+">"+possibleUrl.substr(0,length)+"</a>";if(emailRE.test(possibleUrl))return'<a href="mailto:'+possibleUrl+'">'+possibleUrl+"</a>";if(tldRE.test(possibleUrl))return'<a href="http://'+possibleUrl+'"'+noFollowAttr+">"+possibleUrl.substr(0,length)+"</a>";return word});return words.join(" ")},wordcount:function(str){var words=str?str.match(/\w+/g):null;return words?words.length:null},"float":function(val,def){var res=parseFloat(val);return isNaN(res)?def:res},"int":function(val,def){var res=parseInt(val,10);return isNaN(res)?def:res}};filters.d=filters["default"];filters.e=filters.escape;modules["filters"]=filters})();(function(){function cycler(items){var index=-1;return{current:null,reset:function(){index=-1;this.current=null},next:function(){index++;if(index>=items.length){index=0}this.current=items[index];return this.current}}}function joiner(sep){sep=sep||",";var first=true;return function(){var val=first?"":sep;first=false;return val}}var globals={range:function(start,stop,step){if(!stop){stop=start;start=0;step=1}else if(!step){step=1}var arr=[];for(var i=start;i<stop;i+=step){arr.push(i)}return arr},cycler:function(){return cycler(Array.prototype.slice.call(arguments))},joiner:function(sep){return joiner(sep)}};modules["globals"]=globals})();(function(){var path=modules["path"];var lib=modules["lib"];var Obj=modules["object"];var lexer=modules["lexer"];var compiler=modules["compiler"];var builtin_filters=modules["filters"];var builtin_loaders=modules["loaders"];var runtime=modules["runtime"];var globals=modules["globals"];var Frame=runtime.Frame;var Environment=Obj.extend({init:function(loaders,opts){opts=opts||{};this.dev=!!opts.dev;this.lexerTags=opts.tags;this.autoesc=!!opts.autoescape;if(!loaders){if(builtin_loaders.FileSystemLoader){this.loaders=[new builtin_loaders.FileSystemLoader("views")]}else{this.loaders=[new builtin_loaders.WebLoader("/views")]}}else{this.loaders=lib.isArray(loaders)?loaders:[loaders]}this.initCache();this.filters={};this.asyncFilters=[];this.extensions={};this.extensionsList=[];for(var name in builtin_filters){this.addFilter(name,builtin_filters[name])}},initCache:function(){var cache={};lib.each(this.loaders,function(loader){if(typeof loader.on==="function"){loader.on("update",function(template){cache[template]=null})}});this.cache=cache},addExtension:function(name,extension){extension._name=name;this.extensions[name]=extension;this.extensionsList.push(extension)},getExtension:function(name){return this.extensions[name]},addGlobal:function(name,value){globals[name]=value},addFilter:function(name,func,async){var wrapped=func;if(async){this.asyncFilters.push(name)}this.filters[name]=wrapped},getFilter:function(name){if(!this.filters[name]){throw new Error("filter not found: "+name)}return this.filters[name]},getTemplate:function(name,eagerCompile,cb){if(name&&name.raw){name=name.raw}if(lib.isFunction(eagerCompile)){cb=eagerCompile;eagerCompile=false}if(typeof name!=="string"){throw new Error("template names must be a string: "+name)}var tmpl=this.cache[name];if(tmpl){if(eagerCompile){tmpl.compile()}if(cb){cb(null,tmpl)}else{return tmpl}}else{var syncResult;lib.asyncIter(this.loaders,function(loader,i,next,done){function handle(src){if(src){done(src)}else{next()}}if(loader.async){loader.getSource(name,function(err,src){if(err){throw err}handle(src)})}else{handle(loader.getSource(name))}},function(info){if(!info){var err=new Error("template not found: "+name);if(cb){cb(err)}else{throw err}}else{var tmpl=new Template(info.src,this,info.path,eagerCompile);if(!info.noCache){this.cache[name]=tmpl}if(cb){cb(null,tmpl)}else{syncResult=tmpl}}}.bind(this));return syncResult}},express:function(app){var env=this;function NunjucksView(name,opts){this.name=name;this.path=name;this.defaultEngine=opts.defaultEngine;this.ext=path.extname(name);if(!this.ext&&!this.defaultEngine)throw new Error("No default engine was specified and no extension was provided.");if(!this.ext)this.name+=this.ext=("."!==this.defaultEngine[0]?".":"")+this.defaultEngine}NunjucksView.prototype.render=function(opts,cb){env.render(this.name,opts,cb)};app.set("view",NunjucksView)},render:function(name,ctx,cb){if(lib.isFunction(ctx)){cb=ctx;ctx=null}var syncResult=null;this.getTemplate(name,function(err,tmpl){if(err&&cb){cb(err)}else if(err){throw err}else{tmpl.render(ctx,cb||function(err,res){if(err){throw err}syncResult=res})}});return syncResult},renderString:function(src,ctx,cb){var tmpl=new Template(src,this);return tmpl.render(ctx,cb)}});var Context=Obj.extend({init:function(ctx,blocks){this.ctx=ctx;this.blocks={};this.exported=[];for(var name in blocks){this.addBlock(name,blocks[name])}},lookup:function(name){if(name in globals&&!(name in this.ctx)){return globals[name]}else{return this.ctx[name]}},setVariable:function(name,val){this.ctx[name]=val},getVariables:function(){return this.ctx},addBlock:function(name,block){this.blocks[name]=this.blocks[name]||[];this.blocks[name].push(block)},getBlock:function(name){if(!this.blocks[name]){throw new Error('unknown block "'+name+'"')}return this.blocks[name][0]},getSuper:function(env,name,block,frame,runtime,cb){var idx=lib.indexOf(this.blocks[name]||[],block);var blk=this.blocks[name][idx+1];var context=this;if(idx==-1||!blk){throw new Error('no super block available for "'+name+'"')}blk(env,context,frame,runtime,cb)},addExport:function(name){this.exported.push(name)},getExported:function(){var exported={};for(var i=0;i<this.exported.length;i++){var name=this.exported[i];exported[name]=this.ctx[name]}return exported}});var Template=Obj.extend({init:function(src,env,path,eagerCompile){this.env=env||new Environment;if(lib.isObject(src)){switch(src.type){case"code":this.tmplProps=src.obj;break;case"string":this.tmplStr=src.obj;break}}else if(lib.isString(src)){this.tmplStr=src}else{throw new Error("src must be a string or an object describing "+"the source")}this.path=path;if(eagerCompile){lib.withPrettyErrors(this.path,this.env.dev,this._compile.bind(this))}else{this.compiled=false}},render:function(ctx,frame,cb){if(typeof ctx==="function"){cb=ctx;ctx={}}else if(typeof frame==="function"){cb=frame;frame=null}return lib.withPrettyErrors(this.path,this.env.dev,function(){try{this.compile()}catch(e){if(cb)return cb(e);else throw e}var context=new Context(ctx||{},this.blocks);var syncResult=null;this.rootRenderFunc(this.env,context,frame||new Frame,runtime,cb||function(err,res){if(err){throw err}syncResult=res});return syncResult}.bind(this))},getExported:function(ctx,frame,cb){if(typeof ctx==="function"){cb=ctx;ctx={}}if(typeof frame==="function"){cb=frame;frame=null}try{this.compile()}catch(e){if(cb)return cb(e);else throw e}var context=new Context(ctx||{},this.blocks);this.rootRenderFunc(this.env,context,frame||new Frame,runtime,function(){cb(null,context.getExported())})},compile:function(){if(!this.compiled){this._compile()}},_compile:function(){var props;if(this.tmplProps){props=this.tmplProps}else{var source=compiler.compile(this.tmplStr,this.env.asyncFilters,this.env.extensionsList,this.path,this.env.lexerTags);var func=new Function(source);props=func()}this.blocks=this._getBlocks(props);this.rootRenderFunc=props.root;this.compiled=true},_getBlocks:function(props){var blocks={};for(var k in props){if(k.slice(0,2)=="b_"){blocks[k.slice(2)]=props[k]}}return blocks}});modules["environment"]={Environment:Environment,Template:Template}})();var nunjucks;var lib=modules["lib"];var env=modules["environment"];var compiler=modules["compiler"];var parser=modules["parser"];var lexer=modules["lexer"];var runtime=modules["runtime"];var Loader=modules["loader"];var loaders=modules["loaders"];var precompile=modules["precompile"];nunjucks={};nunjucks.Environment=env.Environment;nunjucks.Template=env.Template;nunjucks.Loader=Loader;nunjucks.FileSystemLoader=loaders.FileSystemLoader;nunjucks.WebLoader=loaders.WebLoader;nunjucks.compiler=compiler;nunjucks.parser=parser;nunjucks.lexer=lexer;nunjucks.runtime=runtime;var e;nunjucks.configure=function(templatesPath,opts){opts=opts||{};if(lib.isObject(templatesPath)){opts=templatesPath;templatesPath=null}var noWatch="watch"in opts?!opts.watch:false;var loader=loaders.FileSystemLoader||loaders.WebLoader;e=new env.Environment(new loader(templatesPath,noWatch),opts);if(opts&&opts.express){e.express(opts.express)}return e};nunjucks.compile=function(src,env,path,eagerCompile){if(!e){nunjucks.configure()}return new nunjucks.Template(src,env,path,eagerCompile)};nunjucks.render=function(name,ctx,cb){if(!e){nunjucks.configure()}return e.render(name,ctx,cb)};nunjucks.renderString=function(src,ctx,cb){if(!e){nunjucks.configure()}return e.renderString(src,ctx,cb)};if(precompile){nunjucks.precompile=precompile.precompile;nunjucks.precompileString=precompile.precompileString}nunjucks.require=function(name){return modules[name]};if(typeof define==="function"&&define.amd){define(function(){return nunjucks})}else{window.nunjucks=nunjucks;if(typeof module!=="undefined")module.exports=nunjucks}})();
(function(){var modules={};(function(){"use strict";function extend(cls,name,props){var F=function(){};F.prototype=cls.prototype;var prototype=new F;var fnTest=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;props=props||{};for(var k in props){var src=props[k];var parent=prototype[k];if(typeof parent==="function"&&typeof src==="function"&&fnTest.test(src)){prototype[k]=function(src,parent){return function(){var tmp=this.parent;this.parent=parent;var res=src.apply(this,arguments);this.parent=tmp;return res}}(src,parent)}else{prototype[k]=src}}prototype.typename=name;var new_cls=function(){if(prototype.init){prototype.init.apply(this,arguments)}};new_cls.prototype=prototype;new_cls.prototype.constructor=new_cls;new_cls.extend=function(name,props){if(typeof name==="object"){props=name;name="anonymous"}return extend(new_cls,name,props)};return new_cls}modules["object"]=extend(Object,"Object",{})})();(function(){"use strict";var ArrayProto=Array.prototype;var ObjProto=Object.prototype;var escapeMap={"&":"&amp;",'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;"};var escapeRegex=/[&"'<>]/g;var lookupEscape=function(ch){return escapeMap[ch]};var exports=modules["lib"]={};exports.withPrettyErrors=function(path,withInternals,func){try{return func()}catch(e){if(!e.Update){e=new exports.TemplateError(e)}e.Update(path);if(!withInternals){var old=e;e=new Error(old.message);e.name=old.name}throw e}};exports.TemplateError=function(message,lineno,colno){var err=this;if(message instanceof Error){err=message;message=message.name+": "+message.message}else{if(Error.captureStackTrace){Error.captureStackTrace(err)}}err.name="Template render error";err.message=message;err.lineno=lineno;err.colno=colno;err.firstUpdate=true;err.Update=function(path){var message="("+(path||"unknown path")+")";if(this.firstUpdate){if(this.lineno&&this.colno){message+=" [Line "+this.lineno+", Column "+this.colno+"]"}else if(this.lineno){message+=" [Line "+this.lineno+"]"}}message+="\n ";if(this.firstUpdate){message+=" "}this.message=message+(this.message||"");this.firstUpdate=false;return this};return err};exports.TemplateError.prototype=Error.prototype;exports.escape=function(val){return val.replace(escapeRegex,lookupEscape)};exports.isFunction=function(obj){return ObjProto.toString.call(obj)==="[object Function]"};exports.isArray=Array.isArray||function(obj){return ObjProto.toString.call(obj)==="[object Array]"};exports.isString=function(obj){return ObjProto.toString.call(obj)==="[object String]"};exports.isObject=function(obj){return ObjProto.toString.call(obj)==="[object Object]"};exports.groupBy=function(obj,val){var result={};var iterator=exports.isFunction(val)?val:function(obj){return obj[val]};for(var i=0;i<obj.length;i++){var value=obj[i];var key=iterator(value,i);(result[key]||(result[key]=[])).push(value)}return result};exports.toArray=function(obj){return Array.prototype.slice.call(obj)};exports.without=function(array){var result=[];if(!array){return result}var index=-1,length=array.length,contains=exports.toArray(arguments).slice(1);while(++index<length){if(exports.indexOf(contains,array[index])===-1){result.push(array[index])}}return result};exports.extend=function(obj,obj2){for(var k in obj2){obj[k]=obj2[k]}return obj};exports.repeat=function(char_,n){var str="";for(var i=0;i<n;i++){str+=char_}return str};exports.each=function(obj,func,context){if(obj==null){return}if(ArrayProto.each&&obj.each===ArrayProto.each){obj.forEach(func,context)}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i<l;i++){func.call(context,obj[i],i,obj)}}};exports.map=function(obj,func){var results=[];if(obj==null){return results}if(ArrayProto.map&&obj.map===ArrayProto.map){return obj.map(func)}for(var i=0;i<obj.length;i++){results[results.length]=func(obj[i],i)}if(obj.length===+obj.length){results.length=obj.length}return results};exports.asyncIter=function(arr,iter,cb){var i=-1;function next(){i++;if(i<arr.length){iter(arr[i],i,next,cb)}else{cb()}}next()};exports.asyncFor=function(obj,iter,cb){var keys=exports.keys(obj);var len=keys.length;var i=-1;function next(){i++;var k=keys[i];if(i<len){iter(k,obj[k],i,len,next)}else{cb()}}next()};exports.indexOf=Array.prototype.indexOf?function(arr,searchElement,fromIndex){return Array.prototype.indexOf.call(arr,searchElement,fromIndex)}:function(arr,searchElement,fromIndex){var length=this.length>>>0;fromIndex=+fromIndex||0;if(Math.abs(fromIndex)===Infinity){fromIndex=0}if(fromIndex<0){fromIndex+=length;if(fromIndex<0){fromIndex=0}}for(;fromIndex<length;fromIndex++){if(arr[fromIndex]===searchElement){return fromIndex}}return-1};if(!Array.prototype.map){Array.prototype.map=function(){throw new Error("map is unimplemented for this js engine")}}exports.keys=function(obj){if(Object.prototype.keys){return obj.keys()}else{var keys=[];for(var k in obj){if(obj.hasOwnProperty(k)){keys.push(k)}}return keys}}})();(function(){"use strict";var lib=modules["lib"];var Obj=modules["object"];var Frame=Obj.extend({init:function(parent){this.variables={};this.parent=parent},set:function(name,val,resolveUp){var parts=name.split(".");var obj=this.variables;var frame=this;if(resolveUp){if(frame=this.resolve(parts[0])){frame.set(name,val);return}frame=this}for(var i=0;i<parts.length-1;i++){var id=parts[i];if(!obj[id]){obj[id]={}}obj=obj[id]}obj[parts[parts.length-1]]=val},get:function(name){var val=this.variables[name];if(val!==undefined&&val!==null){return val}return null},lookup:function(name){var p=this.parent;var val=this.variables[name];if(val!==undefined&&val!==null){return val}return p&&p.lookup(name)},resolve:function(name){var p=this.parent;var val=this.variables[name];if(val!==undefined&&val!==null){return this}return p&&p.resolve(name)},push:function(){return new Frame(this)},pop:function(){return this.parent}});function makeMacro(argNames,kwargNames,func){return function(){var argCount=numArgs(arguments);var args;var kwargs=getKeywordArgs(arguments);if(argCount>argNames.length){args=Array.prototype.slice.call(arguments,0,argNames.length);var vals=Array.prototype.slice.call(arguments,args.length,argCount);for(var i=0;i<vals.length;i++){if(i<kwargNames.length){kwargs[kwargNames[i]]=vals[i]}}args.push(kwargs)}else if(argCount<argNames.length){args=Array.prototype.slice.call(arguments,0,argCount);for(var i=argCount;i<argNames.length;i++){var arg=argNames[i];args.push(kwargs[arg]);delete kwargs[arg]}args.push(kwargs)}else{args=arguments}return func.apply(this,args)}}function makeKeywordArgs(obj){obj.__keywords=true;return obj}function getKeywordArgs(args){var len=args.length;if(len){var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return lastArg}}return{}}function numArgs(args){var len=args.length;if(len===0){return 0}var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return len-1}else{return len}}function SafeString(val){if(typeof val!=="string"){return val}this.val=val}SafeString.prototype=Object.create(String.prototype);SafeString.prototype.valueOf=function(){return this.val};SafeString.prototype.toString=function(){return this.val};function copySafeness(dest,target){if(dest instanceof SafeString){return new SafeString(target)}return target.toString()}function markSafe(val){var type=typeof val;if(type==="string"){return new SafeString(val)}else if(type!=="function"){return val}else{return function(){var ret=val.apply(this,arguments);if(typeof ret==="string"){return new SafeString(ret)}return ret}}}function suppressValue(val,autoescape){val=val!==undefined&&val!==null?val:"";if(autoescape&&typeof val==="string"){val=lib.escape(val)}return val}function memberLookup(obj,val){obj=obj||{};if(typeof obj[val]==="function"){return function(){return obj[val].apply(obj,arguments)}}return obj[val]}function callWrap(obj,name,args){if(!obj){throw new Error("Unable to call `"+name+"`, which is undefined or falsey")}else if(typeof obj!=="function"){throw new Error("Unable to call `"+name+"`, which is not a function")}return obj.apply(this,args)}function contextOrFrameLookup(context,frame,name){var val=frame.lookup(name);return val!==undefined&&val!==null?val:context.lookup(name)}function handleError(error,lineno,colno){if(error.lineno){return error}else{return new lib.TemplateError(error,lineno,colno)}}function asyncEach(arr,dimen,iter,cb){if(lib.isArray(arr)){var len=arr.length;lib.asyncIter(arr,function(item,i,next){switch(dimen){case 1:iter(item,i,len,next);break;case 2:iter(item[0],item[1],i,len,next);break;case 3:iter(item[0],item[1],item[2],i,len,next);break;default:item.push(i,next);iter.apply(this,item)}},cb)}else{lib.asyncFor(arr,function(key,val,i,len,next){iter(key,val,i,len,next)},cb)}}function asyncAll(arr,dimen,func,cb){var finished=0;var len;var outputArr;function done(i,output){finished++;outputArr[i]=output;if(finished===len){cb(null,outputArr.join(""))}}if(lib.isArray(arr)){len=arr.length;outputArr=new Array(len);if(len===0){cb(null,"")}else{for(var i=0;i<arr.length;i++){var item=arr[i];switch(dimen){case 1:func(item,i,len,done);break;case 2:func(item[0],item[1],i,len,done);break;case 3:func(item[0],item[1],item[2],i,len,done);break;default:item.push(i,done);func.apply(this,item)}}}}else{var keys=lib.keys(arr);len=keys.length;outputArr=new Array(len);if(len===0){cb(null,"")}else{for(var i=0;i<keys.length;i++){var k=keys[i];func(k,arr[k],i,len,done)}}}}modules["runtime"]={Frame:Frame,makeMacro:makeMacro,makeKeywordArgs:makeKeywordArgs,numArgs:numArgs,suppressValue:suppressValue,memberLookup:memberLookup,contextOrFrameLookup:contextOrFrameLookup,callWrap:callWrap,handleError:handleError,isArray:lib.isArray,keys:lib.keys,SafeString:SafeString,copySafeness:copySafeness,markSafe:markSafe,asyncEach:asyncEach,asyncAll:asyncAll}})();(function(){"use strict";var path=modules["path"];var Obj=modules["object"];var lib=modules["lib"];var Loader=Obj.extend({on:function(name,func){this.listeners=this.listeners||{};this.listeners[name]=this.listeners[name]||[];this.listeners[name].push(func)},emit:function(name){var args=Array.prototype.slice.call(arguments,1);if(this.listeners&&this.listeners[name]){lib.each(this.listeners[name],function(listener){listener.apply(null,args)})}},resolve:function(from,to){return path.resolve(path.dirname(from),to)},isRelative:function(filename){return filename.indexOf("./")===0||filename.indexOf("../")===0}});modules["loader"]=Loader})();(function(){"use strict";var Loader=modules["loader"];var WebLoader=Loader.extend({init:function(baseURL,neverUpdate){this.precompiled=window.nunjucksPrecompiled||{};this.baseURL=baseURL||"";this.neverUpdate=neverUpdate},getSource:function(name){if(this.precompiled[name]){return{src:{type:"code",obj:this.precompiled[name]},path:name}}else{var src=this.fetch(this.baseURL+"/"+name);if(!src){return null}return{src:src,path:name,noCache:!this.neverUpdate}}},fetch:function(url,callback){var ajax;var loading=true;var src;if(window.XMLHttpRequest){ajax=new XMLHttpRequest}else if(window.ActiveXObject){ajax=new ActiveXObject("Microsoft.XMLHTTP")}ajax.onreadystatechange=function(){if(ajax.readyState===4&&(ajax.status===0||ajax.status===200)&&loading){loading=false;src=ajax.responseText}};url+=(url.indexOf("?")===-1?"?":"&")+"s="+(new Date).getTime();ajax.open("GET",url,false);ajax.send();return src}});modules["web-loaders"]={WebLoader:WebLoader}})();(function(){"use strict";if(typeof window==="undefined"||window!==this){modules["loaders"]=modules["node-loaders"]}else{modules["loaders"]=modules["web-loaders"]}})();(function(){"use strict";var lib=modules["lib"];var r=modules["runtime"];var filters={abs:function(n){return Math.abs(n)},batch:function(arr,linecount,fill_with){var res=[];var tmp=[];for(var i=0;i<arr.length;i++){if(i%linecount===0&&tmp.length){res.push(tmp);tmp=[]}tmp.push(arr[i])}if(tmp.length){if(fill_with){for(var i=tmp.length;i<linecount;i++){tmp.push(fill_with)}}res.push(tmp)}return res},capitalize:function(str){var ret=str.toLowerCase();return r.copySafeness(str,ret.charAt(0).toUpperCase()+ret.slice(1))},center:function(str,width){width=width||80;if(str.length>=width){return str}var spaces=width-str.length;var pre=lib.repeat(" ",spaces/2-spaces%2);var post=lib.repeat(" ",spaces/2);return r.copySafeness(str,pre+str+post)},"default":function(val,def){return val?val:def},dictsort:function(val,case_sensitive,by){if(!lib.isObject(val)){throw new lib.TemplateError("dictsort filter: val must be an object")}var array=[];for(var k in val){array.push([k,val[k]])}var si;if(by===undefined||by==="key"){si=0}else if(by==="value"){si=1}else{throw new lib.TemplateError("dictsort filter: You can only sort by either key or value")}array.sort(function(t1,t2){var a=t1[si];var b=t2[si];if(!case_sensitive){if(lib.isString(a)){a=a.toUpperCase()}if(lib.isString(b)){b=b.toUpperCase()}}return a>b?1:a===b?0:-1});return array},escape:function(str){if(typeof str==="string"||str instanceof r.SafeString){return lib.escape(str)}return str},safe:function(str){return r.markSafe(str)},first:function(arr){return arr[0]},groupby:function(arr,attr){return lib.groupBy(arr,attr)},indent:function(str,width,indentfirst){width=width||4;var res="";var lines=str.split("\n");var sp=lib.repeat(" ",width);for(var i=0;i<lines.length;i++){if(i===0&&!indentfirst){res+=lines[i]+"\n"}else{res+=sp+lines[i]+"\n"}}return r.copySafeness(str,res)},join:function(arr,del,attr){del=del||"";if(attr){arr=lib.map(arr,function(v){return v[attr]})}return arr.join(del)},last:function(arr){return arr[arr.length-1]},length:function(arr){return arr!==undefined?arr.length:0},list:function(val){if(lib.isString(val)){return val.split("")}else if(lib.isObject(val)){var keys=[];if(Object.keys){keys=Object.keys(val)}else{for(var k in val){keys.push(k)}}return lib.map(keys,function(k){return{key:k,value:val[k]}})}else if(lib.isArray(val)){return val}else{throw new lib.TemplateError("list filter: type not iterable")}},lower:function(str){return str.toLowerCase()},random:function(arr){return arr[Math.floor(Math.random()*arr.length)]},rejectattr:function(arr,attr){return arr.filter(function(item){return!item[attr]})},selectattr:function(arr,attr){return arr.filter(function(item){return!!item[attr]})},replace:function(str,old,new_,maxCount){if(old instanceof RegExp){return str.replace(old,new_)}var res=str;var last=res;var count=1;res=res.replace(old,new_);while(last!==res){if(count>=maxCount){break}last=res;res=res.replace(old,new_);count++}return r.copySafeness(str,res)},reverse:function(val){var arr;if(lib.isString(val)){arr=filters.list(val)}else{arr=lib.map(val,function(v){return v})}arr.reverse();if(lib.isString(val)){return r.copySafeness(val,arr.join(""))}return arr},round:function(val,precision,method){precision=precision||0;var factor=Math.pow(10,precision);var rounder;if(method==="ceil"){rounder=Math.ceil}else if(method==="floor"){rounder=Math.floor}else{rounder=Math.round}return rounder(val*factor)/factor},slice:function(arr,slices,fillWith){var sliceLength=Math.floor(arr.length/slices);var extra=arr.length%slices;var offset=0;var res=[];for(var i=0;i<slices;i++){var start=offset+i*sliceLength;if(i<extra){offset++}var end=offset+(i+1)*sliceLength;var slice=arr.slice(start,end);if(fillWith&&i>=extra){slice.push(fillWith)}res.push(slice)}return res},sort:function(arr,reverse,caseSens,attr){arr=lib.map(arr,function(v){return v});arr.sort(function(a,b){var x,y;if(attr){x=a[attr];y=b[attr]}else{x=a;y=b}if(!caseSens&&lib.isString(x)&&lib.isString(y)){x=x.toLowerCase();y=y.toLowerCase()}if(x<y){return reverse?1:-1}else if(x>y){return reverse?-1:1}else{return 0}});return arr},string:function(obj){return r.copySafeness(obj,obj)},title:function(str){var words=str.split(" ");for(var i=0;i<words.length;i++){words[i]=filters.capitalize(words[i])}return r.copySafeness(str,words.join(" "))},trim:function(str){return r.copySafeness(str,str.replace(/^\s*|\s*$/g,""))},truncate:function(input,length,killwords,end){var orig=input;length=length||255;if(input.length<=length)return input;if(killwords){input=input.substring(0,length)}else{var idx=input.lastIndexOf(" ",length);if(idx===-1){idx=length}input=input.substring(0,idx)}input+=end!==undefined&&end!==null?end:"...";return r.copySafeness(orig,input)},upper:function(str){return str.toUpperCase()},urlencode:function(obj){var enc=encodeURIComponent;if(lib.isString(obj)){return enc(obj)}else{var parts;if(lib.isArray(obj)){parts=obj.map(function(item){return enc(item[0])+"="+enc(item[1])})}else{parts=[];for(var k in obj){if(obj.hasOwnProperty(k)){parts.push(enc(k)+"="+enc(obj[k]))}}}return parts.join("&")}},urlize:function(str,length,nofollow){if(isNaN(length))length=Infinity;var noFollowAttr=nofollow===true?' rel="nofollow"':"";var puncRE=/^(?:\(|<|&lt;)?(.*?)(?:\.|,|\)|\n|&gt;)?$/;var emailRE=/^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;var httpHttpsRE=/^https?:\/\/.*$/;var wwwRE=/^www\./;var tldRE=/\.(?:org|net|com)(?:\:|\/|$)/;var words=str.split(/\s+/).filter(function(word){return word&&word.length}).map(function(word){var matches=word.match(puncRE);var possibleUrl=matches&&matches[1]||word;if(httpHttpsRE.test(possibleUrl))return'<a href="'+possibleUrl+'"'+noFollowAttr+">"+possibleUrl.substr(0,length)+"</a>";if(wwwRE.test(possibleUrl))return'<a href="http://'+possibleUrl+'"'+noFollowAttr+">"+possibleUrl.substr(0,length)+"</a>";if(emailRE.test(possibleUrl))return'<a href="mailto:'+possibleUrl+'">'+possibleUrl+"</a>";if(tldRE.test(possibleUrl))return'<a href="http://'+possibleUrl+'"'+noFollowAttr+">"+possibleUrl.substr(0,length)+"</a>";return word});return words.join(" ")},wordcount:function(str){var words=str?str.match(/\w+/g):null;return words?words.length:null},"float":function(val,def){var res=parseFloat(val);return isNaN(res)?def:res},"int":function(val,def){var res=parseInt(val,10);return isNaN(res)?def:res}};filters.d=filters["default"];filters.e=filters.escape;modules["filters"]=filters})();(function(){"use strict";function cycler(items){var index=-1;return{current:null,reset:function(){index=-1;this.current=null},next:function(){index++;if(index>=items.length){index=0}this.current=items[index];return this.current}}}function joiner(sep){sep=sep||",";var first=true;return function(){var val=first?"":sep;first=false;return val}}var globals={range:function(start,stop,step){if(!stop){stop=start;start=0;step=1}else if(!step){step=1}var arr=[];for(var i=start;i<stop;i+=step){arr.push(i)}return arr},cycler:function(){return cycler(Array.prototype.slice.call(arguments))},joiner:function(sep){return joiner(sep)}};modules["globals"]=globals})();(function(){"use strict";var path=modules["path"];var lib=modules["lib"];var Obj=modules["object"];var lexer=modules["lexer"];var compiler=modules["compiler"];var builtin_filters=modules["filters"];var builtin_loaders=modules["loaders"];var runtime=modules["runtime"];var globals=modules["globals"];var Frame=runtime.Frame;var Environment=Obj.extend({init:function(loaders,opts){var opts=this.opts=opts||{};this.opts.dev=!!opts.dev;this.opts.autoescape=!!opts.autoescape;this.opts.trimBlocks=!!opts.trimBlocks;this.opts.lstripBlocks=!!opts.lstripBlocks;if(!loaders){if(builtin_loaders.FileSystemLoader){this.loaders=[new builtin_loaders.FileSystemLoader("views")]}else{this.loaders=[new builtin_loaders.WebLoader("/views")]}}else{this.loaders=lib.isArray(loaders)?loaders:[loaders]}this.initCache();this.filters={};this.asyncFilters=[];this.extensions={};this.extensionsList=[];for(var name in builtin_filters){this.addFilter(name,builtin_filters[name])}},initCache:function(){lib.each(this.loaders,function(loader){loader.cache={};if(typeof loader.on==="function"){loader.on("update",function(template){loader.cache[template]=null})}})},addExtension:function(name,extension){extension._name=name;this.extensions[name]=extension;this.extensionsList.push(extension)},getExtension:function(name){return this.extensions[name]},addGlobal:function(name,value){globals[name]=value},addFilter:function(name,func,async){var wrapped=func;if(async){this.asyncFilters.push(name)}this.filters[name]=wrapped},getFilter:function(name){if(!this.filters[name]){throw new Error("filter not found: "+name)}return this.filters[name]},resolveTemplate:function(loader,parentName,filename){var isRelative=loader.isRelative&&parentName?loader.isRelative(filename):false;return isRelative&&loader.resolve?loader.resolve(parentName,filename):filename},getTemplate:function(name,eagerCompile,parentName,cb){var that=this;var tmpl=null;if(name&&name.raw){name=name.raw}if(lib.isFunction(parentName)){cb=parentName;parentName=null;eagerCompile=eagerCompile||false}if(lib.isFunction(eagerCompile)){cb=eagerCompile;eagerCompile=false}if(typeof name!=="string"){throw new Error("template names must be a string: "+name)}for(var i=0;i<this.loaders.length;i++){var _name=this.resolveTemplate(this.loaders[i],parentName,name);tmpl=this.loaders[i].cache[_name];if(tmpl)break}if(tmpl){if(eagerCompile){tmpl.compile()}if(cb){cb(null,tmpl)}else{return tmpl}}else{var syncResult;lib.asyncIter(this.loaders,function(loader,i,next,done){function handle(src){if(src){src.loader=loader;done(src)}else{next()}}name=that.resolveTemplate(loader,parentName,name);if(loader.async){loader.getSource(name,function(err,src){if(err){throw err}handle(src)})}else{handle(loader.getSource(name))}},function(info){if(!info){var err=new Error("template not found: "+name);if(cb){cb(err)}else{throw err}}else{var tmpl=new Template(info.src,this,info.path,eagerCompile);if(!info.noCache){info.loader.cache[name]=tmpl}if(cb){cb(null,tmpl)}else{syncResult=tmpl}}}.bind(this));return syncResult}},express:function(app){var env=this;function NunjucksView(name,opts){this.name=name;this.path=name;this.defaultEngine=opts.defaultEngine;this.ext=path.extname(name);if(!this.ext&&!this.defaultEngine)throw new Error("No default engine was specified and no extension was provided.");if(!this.ext)this.name+=this.ext=("."!==this.defaultEngine[0]?".":"")+this.defaultEngine}NunjucksView.prototype.render=function(opts,cb){env.render(this.name,opts,cb)};app.set("view",NunjucksView)},render:function(name,ctx,cb){if(lib.isFunction(ctx)){cb=ctx;ctx=null}var syncResult=null;this.getTemplate(name,function(err,tmpl){if(err&&cb){cb(err)}else if(err){throw err}else{tmpl.render(ctx,cb||function(err,res){if(err){throw err}syncResult=res})}});return syncResult},renderString:function(src,ctx,opts,cb){if(lib.isFunction(opts)){cb=opts;opts={}}opts=opts||{};var tmpl=new Template(src,this,opts.path);return tmpl.render(ctx,cb)}});var Context=Obj.extend({init:function(ctx,blocks){this.ctx=ctx;this.blocks={};this.exported=[];for(var name in blocks){this.addBlock(name,blocks[name])}},lookup:function(name){if(name in globals&&!(name in this.ctx)){return globals[name]}else{return this.ctx[name]}},setVariable:function(name,val){this.ctx[name]=val},getVariables:function(){return this.ctx},addBlock:function(name,block){this.blocks[name]=this.blocks[name]||[];this.blocks[name].push(block)},getBlock:function(name){if(!this.blocks[name]){throw new Error('unknown block "'+name+'"')}return this.blocks[name][0]},getSuper:function(env,name,block,frame,runtime,cb){var idx=lib.indexOf(this.blocks[name]||[],block);var blk=this.blocks[name][idx+1];var context=this;if(idx===-1||!blk){throw new Error('no super block available for "'+name+'"')}blk(env,context,frame,runtime,cb)},addExport:function(name){this.exported.push(name)},getExported:function(){var exported={};for(var i=0;i<this.exported.length;i++){var name=this.exported[i];exported[name]=this.ctx[name]}return exported}});var Template=Obj.extend({init:function(src,env,path,eagerCompile){this.env=env||new Environment;if(lib.isObject(src)){switch(src.type){case"code":this.tmplProps=src.obj;break;case"string":this.tmplStr=src.obj;break}}else if(lib.isString(src)){this.tmplStr=src}else{throw new Error("src must be a string or an object describing "+"the source")}this.path=path;if(eagerCompile){lib.withPrettyErrors(this.path,this.env.dev,this._compile.bind(this))}else{this.compiled=false}},render:function(ctx,frame,cb){if(typeof ctx==="function"){cb=ctx;ctx={}}else if(typeof frame==="function"){cb=frame;frame=null}return lib.withPrettyErrors(this.path,this.env.dev,function(){try{this.compile()}catch(e){if(cb)return cb(e);else throw e}var context=new Context(ctx||{},this.blocks);var syncResult=null;this.rootRenderFunc(this.env,context,frame||new Frame,runtime,cb||function(err,res){if(err){throw err}syncResult=res});return syncResult}.bind(this))},getExported:function(ctx,frame,cb){if(typeof ctx==="function"){cb=ctx;ctx={}}if(typeof frame==="function"){cb=frame;frame=null}try{this.compile()}catch(e){if(cb)return cb(e);else throw e}var context=new Context(ctx||{},this.blocks);this.rootRenderFunc(this.env,context,frame||new Frame,runtime,function(){cb(null,context.getExported())})},compile:function(){if(!this.compiled){this._compile()}},_compile:function(){var props;if(this.tmplProps){props=this.tmplProps}else{var source=compiler.compile(this.tmplStr,this.env.asyncFilters,this.env.extensionsList,this.path,this.env.opts);var func=new Function(source);props=func()}this.blocks=this._getBlocks(props);this.rootRenderFunc=props.root;this.compiled=true},_getBlocks:function(props){var blocks={};for(var k in props){if(k.slice(0,2)==="b_"){blocks[k.slice(2)]=props[k]}}return blocks}});modules["environment"]={Environment:Environment,Template:Template}})();var nunjucks;var lib=modules["lib"];var env=modules["environment"];var compiler=modules["compiler"];var parser=modules["parser"];var lexer=modules["lexer"];var runtime=modules["runtime"];var Loader=modules["loader"];var loaders=modules["loaders"];var precompile=modules["precompile"];nunjucks={};nunjucks.Environment=env.Environment;nunjucks.Template=env.Template;nunjucks.Loader=Loader;nunjucks.FileSystemLoader=loaders.FileSystemLoader;nunjucks.WebLoader=loaders.WebLoader;nunjucks.compiler=compiler;nunjucks.parser=parser;nunjucks.lexer=lexer;nunjucks.runtime=runtime;var e;nunjucks.configure=function(templatesPath,opts){opts=opts||{};if(lib.isObject(templatesPath)){opts=templatesPath;templatesPath=null}var noWatch="watch"in opts?!opts.watch:false;var loader=loaders.FileSystemLoader||loaders.WebLoader;e=new env.Environment(new loader(templatesPath,noWatch),opts);if(opts&&opts.express){e.express(opts.express)}return e};nunjucks.compile=function(src,env,path,eagerCompile){if(!e){nunjucks.configure()}return new nunjucks.Template(src,env,path,eagerCompile)};nunjucks.render=function(name,ctx,cb){if(!e){nunjucks.configure()}return e.render(name,ctx,cb)};nunjucks.renderString=function(src,ctx,cb){if(!e){nunjucks.configure()}return e.renderString(src,ctx,cb)};if(precompile){nunjucks.precompile=precompile.precompile;nunjucks.precompileString=precompile.precompileString}nunjucks.require=function(name){return modules[name]};if(typeof define==="function"&&define.amd){define(function(){return nunjucks})}else{window.nunjucks=nunjucks;if(typeof module!=="undefined")module.exports=nunjucks}})();

@@ -19,3 +19,3 @@

```
$ make browserfiles
$ npm run browserfiles
```

@@ -22,0 +22,0 @@

{
"name": "nunjucks",
"description": "A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)",
"version": "1.2.0",
"version": "1.3.0",
"author": "James Long <longster@gmail.com>",

@@ -23,3 +23,4 @@ "dependencies": {

"scripts": {
"test": "make test"
"test": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha -- -b -R tap tests",
"browserfiles": "./bin/bundle browser/nunjucks; SLIM=1 ./bin/bundle browser/nunjucks-slim"
},

@@ -34,2 +35,6 @@ "bin": {

},
"keywords": [
"template",
"templating"
],
"license": [{

@@ -36,0 +41,0 @@ "type": "BSD",

@@ -0,1 +1,3 @@

'use strict';
var lib = require('./lib');

@@ -28,11 +30,5 @@ var parser = require('./parser');

// Generate an array of strings
function quotedArray(arr) {
return '[' +
lib.map(arr, function(x) { return '"' + x + '"'; }) +
']';
}
var Compiler = Object.extend({
init: function() {
init: function(templateName) {
this.templateName = templateName;
this.codebuf = [];

@@ -68,3 +64,3 @@ this.lastId = 0;

emitLine: function(code) {
this.emit(code + "\n");
this.emit(code + '\n');
},

@@ -132,6 +128,10 @@

_templateName: function() {
return this.templateName == null? 'undefined' : JSON.stringify(this.templateName);
},
_bufferAppend: function(func) {
this.emit(this.buffer + ' += runtime.suppressValue(');
func.call(this);
this.emit(', env.autoesc);\n');
this.emit(', env.opts.autoescape);\n');
},

@@ -210,3 +210,3 @@

if(!success) {
this.fail("assertType: invalid type: " + node.typename,
this.fail('assertType: invalid type: ' + node.typename,
node.lineno,

@@ -247,3 +247,3 @@ node.colno);

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

@@ -285,3 +285,3 @@ }

this.emitLine(', ' + this.makeCallback(res));
this.emitLine(this.buffer + ' += runtime.suppressValue(' + res + ', ' + autoescape + ' && env.autoesc);');
this.emitLine(this.buffer + ' += runtime.suppressValue(' + res + ', ' + autoescape + ' && env.opts.autoescape);');
this.addScopeLevel();

@@ -291,3 +291,3 @@ }

this.emit(')');
this.emit(', ' + autoescape + ' && env.autoesc);\n');
this.emit(', ' + autoescape + ' && env.opts.autoescape);\n');
}

@@ -305,8 +305,8 @@ },

compileLiteral: function(node, frame) {
if(typeof node.value == "string") {
if(typeof node.value === 'string') {
var val = node.value.replace(/\\/g, '\\\\');
val = val.replace(/"/g, '\\"');
val = val.replace(/\n/g, "\\n");
val = val.replace(/\r/g, "\\r");
val = val.replace(/\t/g, "\\t");
val = val.replace(/\n/g, '\\n');
val = val.replace(/\r/g, '\\r');
val = val.replace(/\t/g, '\\t');
this.emit('"' + val + '"');

@@ -352,4 +352,4 @@ }

else if(!(key instanceof nodes.Literal &&
typeof key.value == "string")) {
this.fail("compilePair: Dict keys must be strings or names",
typeof key.value === 'string')) {
this.fail('compilePair: Dict keys must be strings or names',
key.lineno,

@@ -439,3 +439,3 @@ key.colno);

this._compileExpression(node.val, frame);
this.emit(', env.autoesc)');
this.emit(', env.opts.autoescape)');
},

@@ -524,3 +524,3 @@

if (id == null) {
if (id === null || id === undefined) {
id = this.tmpid();

@@ -550,3 +550,3 @@

this.emitLine('context.setVariable("' + name + '", ' + id + ');');
if(name.charAt(0) != '_') {
if(name.charAt(0) !== '_') {
this.emitLine('context.addExport("' + name + '");');

@@ -886,3 +886,3 @@ }

else {
if(node.name.value.charAt(0) != '_') {
if(node.name.value.charAt(0) !== '_') {
this.emitLine('context.addExport("' + name + '");');

@@ -907,3 +907,3 @@ }

this._compileExpression(node.template, frame);
this.emitLine(', ' + this.makeCallback(id));
this.emitLine(', false, '+this._templateName()+', ' + this.makeCallback(id));
this.addScopeLevel();

@@ -931,3 +931,3 @@

this._compileExpression(node.template, frame);
this.emitLine(', ' + this.makeCallback(importedId));
this.emitLine(', false, '+this._templateName()+', ' + this.makeCallback(importedId));
this.addScopeLevel();

@@ -1007,3 +1007,3 @@

this._compileExpression(node.template, frame);
this.emitLine(', true, ' + this.makeCallback('parentTemplate'));
this.emitLine(', true, '+this._templateName()+', ' + this.makeCallback('parentTemplate'));

@@ -1025,3 +1025,3 @@ this.emitLine('for(var ' + k + ' in parentTemplate.blocks) {');

this._compileExpression(node.template, frame);
this.emitLine(', ' + this.makeCallback(id));
this.emitLine(', false, '+this._templateName()+', '+ this.makeCallback(id));
this.addScopeLevel();

@@ -1054,3 +1054,3 @@

this.compile(children[i], frame);
this.emit(', env.autoesc);\n');
this.emit(', env.opts.autoescape);\n');
}

@@ -1062,3 +1062,3 @@ }

if(frame) {
this.fail("compileRoot: root node can't have frame");
this.fail('compileRoot: root node can\'t have frame');
}

@@ -1100,3 +1100,3 @@

compile: function (node, frame) {
var _compile = this["compile" + node.typename];
var _compile = this['compile' + node.typename];
if(_compile) {

@@ -1106,3 +1106,3 @@ _compile.call(this, node, frame);

else {
this.fail("compile: Cannot compile node: " + node.typename,
this.fail('compile: Cannot compile node: ' + node.typename,
node.lineno,

@@ -1127,4 +1127,4 @@ node.colno);

module.exports = {
compile: function(src, asyncFilters, extensions, name, lexerTags) {
var c = new Compiler();
compile: function(src, asyncFilters, extensions, name, opts) {
var c = new Compiler(name);

@@ -1140,3 +1140,5 @@ // Run the extension preprocessors against the source.

c.compile(transformer.transform(parser.parse(src, extensions, lexerTags),
c.compile(transformer.transform(parser.parse(src,
extensions,
opts),
asyncFilters,

@@ -1143,0 +1145,0 @@ name));

@@ -0,1 +1,3 @@

'use strict';
var path = require('path');

@@ -20,5 +22,4 @@ var lib = require('./lib');

// defaults to false
opts = opts || {};
this.dev = !!opts.dev;
this.lexerTags = opts.tags;
var opts = this.opts = opts || {};
this.opts.dev = !!opts.dev;

@@ -29,4 +30,8 @@ // The autoescape flag sets global autoescaping. If true,

// defaults to false
this.autoesc = !!opts.autoescape;
this.opts.autoescape = !!opts.autoescape;
this.opts.trimBlocks = !!opts.trimBlocks;
this.opts.lstripBlocks = !!opts.lstripBlocks;
if(!loaders) {

@@ -58,13 +63,11 @@ // The filesystem loader is only available client-side

// Caching and cache busting
var cache = {};
lib.each(this.loaders, function(loader) {
loader.cache = {};
lib.each(this.loaders, function(loader) {
if(typeof loader.on === 'function'){
if(typeof loader.on === 'function') {
loader.on('update', function(template) {
cache[template] = null;
loader.cache[template] = null;
});
}
});
this.cache = cache;
},

@@ -102,3 +105,10 @@

getTemplate: function(name, eagerCompile, cb) {
resolveTemplate: function(loader, parentName, filename) {
var isRelative = (loader.isRelative && parentName)? loader.isRelative(filename) : false;
return (isRelative && loader.resolve)? loader.resolve(parentName, filename) : filename;
},
getTemplate: function(name, eagerCompile, parentName, cb) {
var that = this;
var tmpl = null;
if(name && name.raw) {

@@ -109,2 +119,8 @@ // this fixes autoescape for templates referenced in symbols

if(lib.isFunction(parentName)) {
cb = parentName;
parentName = null;
eagerCompile = eagerCompile || false;
}
if(lib.isFunction(eagerCompile)) {

@@ -119,3 +135,7 @@ cb = eagerCompile;

var tmpl = this.cache[name];
for (var i = 0; i < this.loaders.length; i++) {
var _name = this.resolveTemplate(this.loaders[i], parentName, name);
tmpl = this.loaders[i].cache[_name];
if (tmpl) break;
}

@@ -139,2 +159,3 @@ if(tmpl) {

if(src) {
src.loader = loader;
done(src);

@@ -147,2 +168,5 @@ }

// Resolve name relative to parentName
name = that.resolveTemplate(loader, parentName, name);
if(loader.async) {

@@ -172,3 +196,3 @@ loader.getSource(name, function(err, src) {

if(!info.noCache) {
this.cache[name] = tmpl;
info.loader.cache[name] = tmpl;
}

@@ -238,4 +262,10 @@

renderString: function(src, ctx, cb) {
var tmpl = new Template(src, this);
renderString: function(src, ctx, opts, cb) {
if(lib.isFunction(opts)) {
cb = opts;
opts = {};
}
opts = opts || {};
var tmpl = new Template(src, this, opts.path);
return tmpl.render(ctx, cb);

@@ -293,3 +323,3 @@ }

if(idx == -1 || !blk) {
if(idx === -1 || !blk) {
throw new Error('no super block available for "' + name + '"');

@@ -329,4 +359,4 @@ }

else {
throw new Error("src must be a string or an object describing " +
"the source");
throw new Error('src must be a string or an object describing ' +
'the source');
}

@@ -430,3 +460,3 @@

this.path,
this.env.lexerTags);
this.env.opts);

@@ -446,3 +476,3 @@ var func = new Function(source);

for(var k in props) {
if(k.slice(0, 2) == 'b_') {
if(k.slice(0, 2) === 'b_') {
blocks[k.slice(2)] = props[k];

@@ -449,0 +479,0 @@ }

@@ -0,1 +1,3 @@

'use strict';
var lib = require('./lib');

@@ -48,4 +50,4 @@ var r = require('./runtime');

var spaces = width - str.length;
var pre = lib.repeat(" ", spaces/2 - spaces % 2);
var post = lib.repeat(" ", spaces/2);
var pre = lib.repeat(' ', spaces/2 - spaces % 2);
var post = lib.repeat(' ', spaces/2);
return r.copySafeness(str, pre + str + post);

@@ -60,3 +62,3 @@ },

if (!lib.isObject(val)) {
throw new lib.TemplateError("dictsort filter: val must be an object");
throw new lib.TemplateError('dictsort filter: val must be an object');
}

@@ -71,9 +73,9 @@

var si;
if (by === undefined || by === "key") {
if (by === undefined || by === 'key') {
si = 0;
} else if (by === "value") {
} else if (by === 'value') {
si = 1;
} else {
throw new lib.TemplateError(
"dictsort filter: You can only sort by either key or value");
'dictsort filter: You can only sort by either key or value');
}

@@ -94,3 +96,3 @@

return a > b ? 1 : (a == b ? 0 : -1);
return a > b ? 1 : (a === b ? 0 : -1);
});

@@ -102,3 +104,3 @@

escape: function(str) {
if(typeof str == 'string' ||
if(typeof str === 'string' ||
str instanceof r.SafeString) {

@@ -129,3 +131,3 @@ return lib.escape(str);

for(var i=0; i<lines.length; i++) {
if(i == 0 && !indentfirst) {
if(i === 0 && !indentfirst) {
res += lines[i] + '\n';

@@ -182,4 +184,7 @@ }

}
else if(lib.isArray(val)) {
return val;
}
else {
throw new lib.TemplateError("list filter: type not iterable");
throw new lib.TemplateError('list filter: type not iterable');
}

@@ -196,2 +201,14 @@ },

rejectattr: function(arr, attr) {
return arr.filter(function (item) {
return !item[attr];
});
},
selectattr: function(arr, attr) {
return arr.filter(function (item) {
return !!item[attr];
});
},
replace: function(str, old, new_, maxCount) {

@@ -207,3 +224,3 @@ if (old instanceof RegExp) {

while(last != res) {
while(last !== res) {
if(count >= maxCount) {

@@ -244,6 +261,6 @@ break;

if(method == 'ceil') {
if(method === 'ceil') {
rounder = Math.ceil;
}
else if(method == 'floor') {
else if(method === 'floor') {
rounder = Math.floor;

@@ -250,0 +267,0 @@ }

@@ -0,1 +1,2 @@

'use strict';

@@ -2,0 +3,0 @@ function cycler(items) {

@@ -0,38 +1,40 @@

'use strict';
var lib = require('./lib');
var whitespaceChars = " \n\t\r\u00A0";
var delimChars = "()[]{}%*-+/#,:|.<>=!";
var intChars = "0123456789";
var whitespaceChars = ' \n\t\r\u00A0';
var delimChars = '()[]{}%*-+/#,:|.<>=!';
var intChars = '0123456789';
var BLOCK_START = "{%";
var BLOCK_END = "%}";
var VARIABLE_START = "{{";
var VARIABLE_END = "}}";
var COMMENT_START = "{#";
var COMMENT_END = "#}";
var BLOCK_START = '{%';
var BLOCK_END = '%}';
var VARIABLE_START = '{{';
var VARIABLE_END = '}}';
var COMMENT_START = '{#';
var COMMENT_END = '#}';
var TOKEN_STRING = "string";
var TOKEN_WHITESPACE = "whitespace";
var TOKEN_DATA = "data";
var TOKEN_BLOCK_START = "block-start";
var TOKEN_BLOCK_END = "block-end";
var TOKEN_VARIABLE_START = "variable-start";
var TOKEN_VARIABLE_END = "variable-end";
var TOKEN_COMMENT = "comment";
var TOKEN_LEFT_PAREN = "left-paren";
var TOKEN_RIGHT_PAREN = "right-paren";
var TOKEN_LEFT_BRACKET = "left-bracket";
var TOKEN_RIGHT_BRACKET = "right-bracket";
var TOKEN_LEFT_CURLY = "left-curly";
var TOKEN_RIGHT_CURLY = "right-curly";
var TOKEN_OPERATOR = "operator";
var TOKEN_COMMA = "comma";
var TOKEN_COLON = "colon";
var TOKEN_PIPE = "pipe";
var TOKEN_INT = "int";
var TOKEN_FLOAT = "float";
var TOKEN_BOOLEAN = "boolean";
var TOKEN_SYMBOL = "symbol";
var TOKEN_SPECIAL = "special";
var TOKEN_REGEX = "regex";
var TOKEN_STRING = 'string';
var TOKEN_WHITESPACE = 'whitespace';
var TOKEN_DATA = 'data';
var TOKEN_BLOCK_START = 'block-start';
var TOKEN_BLOCK_END = 'block-end';
var TOKEN_VARIABLE_START = 'variable-start';
var TOKEN_VARIABLE_END = 'variable-end';
var TOKEN_COMMENT = 'comment';
var TOKEN_LEFT_PAREN = 'left-paren';
var TOKEN_RIGHT_PAREN = 'right-paren';
var TOKEN_LEFT_BRACKET = 'left-bracket';
var TOKEN_RIGHT_BRACKET = 'right-bracket';
var TOKEN_LEFT_CURLY = 'left-curly';
var TOKEN_RIGHT_CURLY = 'right-curly';
var TOKEN_OPERATOR = 'operator';
var TOKEN_COMMA = 'comma';
var TOKEN_COLON = 'colon';
var TOKEN_PIPE = 'pipe';
var TOKEN_INT = 'int';
var TOKEN_FLOAT = 'float';
var TOKEN_BOOLEAN = 'boolean';
var TOKEN_SYMBOL = 'symbol';
var TOKEN_SPECIAL = 'special';
var TOKEN_REGEX = 'regex';

@@ -48,3 +50,3 @@ function token(type, value, lineno, colno) {

function Tokenizer(str, tags) {
function Tokenizer(str, opts) {
this.str = str;

@@ -58,3 +60,5 @@ this.index = 0;

tags = tags || {};
opts = opts || {};
var tags = opts.tags || {};
this.tags = {

@@ -68,2 +72,5 @@ BLOCK_START: tags.blockStart || BLOCK_START,

};
this.trimBlocks = !!opts.trimBlocks;
this.lstripBlocks = !!opts.lstripBlocks;
}

@@ -74,2 +81,3 @@

var colno = this.colno;
var tok;

@@ -79,3 +87,2 @@ if(this.in_code) {

var cur = this.current();
var tok;

@@ -86,3 +93,3 @@ if(this.is_finished()) {

}
else if(cur == "\"" || cur == "'") {
else if(cur === '"' || cur === '\'') {
// We've hit a string

@@ -104,2 +111,9 @@ return token(TOKEN_STRING, this.parseString(cur), lineno, colno);

this.in_code = false;
if(this.trimBlocks) {
cur = this.current();
if(cur === '\n') {
// Skip newline
this.forward();
}
}
return token(TOKEN_BLOCK_END, tok, lineno, colno);

@@ -144,3 +158,3 @@ }

}
else if(delimChars.indexOf(cur) != -1) {
else if(delimChars.indexOf(cur) !== -1) {
// We've hit a delimiter (a special char like a bracket)

@@ -158,11 +172,11 @@ this.forward();

switch(cur) {
case "(": type = TOKEN_LEFT_PAREN; break;
case ")": type = TOKEN_RIGHT_PAREN; break;
case "[": type = TOKEN_LEFT_BRACKET; break;
case "]": type = TOKEN_RIGHT_BRACKET; break;
case "{": type = TOKEN_LEFT_CURLY; break;
case "}": type = TOKEN_RIGHT_CURLY; break;
case ",": type = TOKEN_COMMA; break;
case ":": type = TOKEN_COLON; break;
case "|": type = TOKEN_PIPE; break;
case '(': type = TOKEN_LEFT_PAREN; break;
case ')': type = TOKEN_RIGHT_PAREN; break;
case '[': type = TOKEN_LEFT_BRACKET; break;
case ']': type = TOKEN_RIGHT_BRACKET; break;
case '{': type = TOKEN_LEFT_CURLY; break;
case '}': type = TOKEN_RIGHT_CURLY; break;
case ',': type = TOKEN_COMMA; break;
case ':': type = TOKEN_COLON; break;
case '|': type = TOKEN_PIPE; break;
default: type = TOKEN_OPERATOR;

@@ -179,3 +193,3 @@ }

if(tok.match(/^[-+]?[0-9]+$/)) {
if(this.current() == '.') {
if(this.current() === '.') {
this.forward();

@@ -196,3 +210,3 @@ var dec = this._extract(intChars);

else {
throw new Error("Unexpected value while parsing: " + tok);
throw new Error('Unexpected value while parsing: ' + tok);
}

@@ -209,3 +223,2 @@ }

this.tags.COMMENT_END.charAt(0));
var tok;

@@ -247,2 +260,17 @@ if(this.is_finished()) {

!in_comment) {
if(this.lstripBlocks &&
this._matches(this.tags.BLOCK_START) &&
this.colno > 0 &&
this.colno <= tok.length) {
var lastLine = tok.slice(-this.colno);
if(/^\s+$/.test(lastLine)) {
// Remove block leading whitespace from beginning of the string
tok = tok.slice(0, -this.colno);
if(!tok.length) {
// All data removed, collapse to avoid unnecessary nodes
// by returning next token (block start)
return this.nextToken();
}
}
}
// If it is a start tag, stop looping

@@ -253,3 +281,3 @@ break;

if(!in_comment) {
throw new Error("unexpected end of comment");
throw new Error('unexpected end of comment');
}

@@ -268,3 +296,3 @@ tok += this._extractString(this.tags.COMMENT_END);

if(data === null && in_comment) {
throw new Error("expected end of comment, got end of file");
throw new Error('expected end of comment, got end of file');
}

@@ -279,3 +307,3 @@

throw new Error("Could not parse text");
throw new Error('Could not parse text');
};

@@ -288,13 +316,13 @@

var colno = this.colno;
var str = "";
var str = '';
while(!this.is_finished() && this.current() != delimiter) {
while(!this.is_finished() && this.current() !== delimiter) {
var cur = this.current();
if(cur == "\\") {
if(cur === '\\') {
this.forward();
switch(this.current()) {
case "n": str += "\n"; break;
case "t": str += "\t"; break;
case "r": str += "\r"; break;
case 'n': str += '\n'; break;
case 't': str += '\t'; break;
case 'r': str += '\r'; break;
default:

@@ -321,3 +349,3 @@ str += this.current();

var m = this.str.slice(this.index, this.index + str.length);
return m == str;
return m === str;
};

@@ -336,3 +364,3 @@

// to everything
return this._extractMatching(true, charString || "");
return this._extractMatching(true, charString || '');
};

@@ -358,4 +386,4 @@

// Only proceed if the first character doesn't meet our condition
if((breakOnMatch && first == -1) ||
(!breakOnMatch && first != -1)) {
if((breakOnMatch && first === -1) ||
(!breakOnMatch && first !== -1)) {
var t = this.current();

@@ -368,4 +396,4 @@ this.forward();

while(((breakOnMatch && idx == -1) ||
(!breakOnMatch && idx != -1)) && !this.is_finished()) {
while(((breakOnMatch && idx === -1) ||
(!breakOnMatch && idx !== -1)) && !this.is_finished()) {
t += this.current();

@@ -380,3 +408,3 @@ this.forward();

return "";
return '';
};

@@ -397,3 +425,3 @@

if(this.previous() == "\n") {
if(this.previous() === '\n') {
this.lineno++;

@@ -410,7 +438,7 @@ this.colno = 0;

if(this.current() == "\n") {
if(this.current() === '\n') {
this.lineno--;
var idx = this.src.lastIndexOf("\n", this.index-1);
if(idx == -1) {
var idx = this.src.lastIndexOf('\n', this.index-1);
if(idx === -1) {
this.colno = this.index;

@@ -431,3 +459,3 @@ }

}
return "";
return '';
};

@@ -440,4 +468,4 @@

module.exports = {
lex: function(src, tags) {
return new Tokenizer(src, tags);
lex: function(src, opts) {
return new Tokenizer(src, opts);
},

@@ -444,0 +472,0 @@

@@ -0,1 +1,3 @@

'use strict';
var ArrayProto = Array.prototype;

@@ -7,5 +9,5 @@ var ObjProto = Object.prototype;

'"': '&quot;',
"'": '&#39;',
"<": '&lt;',
">": '&gt;'
'\'': '&#39;',
'<': '&lt;',
'>': '&gt;'
};

@@ -47,3 +49,3 @@

err = message;
message = message.name + ": " + message.message;
message = message.name + ': ' + message.message;
} else {

@@ -62,3 +64,3 @@ if(Error.captureStackTrace) {

err.Update = function(path) {
var message = "(" + (path || "unknown path") + ")";
var message = '(' + (path || 'unknown path') + ')';

@@ -96,15 +98,15 @@ // only show lineno + colno next to path of template

exports.isFunction = function(obj) {
return ObjProto.toString.call(obj) == '[object Function]';
return ObjProto.toString.call(obj) === '[object Function]';
};
exports.isArray = Array.isArray || function(obj) {
return ObjProto.toString.call(obj) == '[object Array]';
return ObjProto.toString.call(obj) === '[object Array]';
};
exports.isString = function(obj) {
return ObjProto.toString.call(obj) == '[object String]';
return ObjProto.toString.call(obj) === '[object String]';
};
exports.isObject = function(obj) {
return ObjProto.toString.call(obj) == '[object Object]';
return ObjProto.toString.call(obj) === '[object Object]';
};

@@ -164,3 +166,3 @@

if(ArrayProto.each && obj.each == ArrayProto.each) {
if(ArrayProto.each && obj.each === ArrayProto.each) {
obj.forEach(func, context);

@@ -265,3 +267,3 @@ }

Array.prototype.map = function() {
throw new Error("map is unimplemented for this js engine");
throw new Error('map is unimplemented for this js engine');
};

@@ -268,0 +270,0 @@ }

@@ -0,1 +1,4 @@

'use strict';
var path = require('path');
var Obj = require('./object');

@@ -19,2 +22,10 @@ var lib = require('./lib');

}
},
resolve: function(from, to) {
return path.resolve(path.dirname(from), to);
},
isRelative: function(filename) {
return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0);
}

@@ -21,0 +32,0 @@ });

@@ -0,1 +1,3 @@

'use strict';
if(typeof window === 'undefined' || window !== this) {

@@ -2,0 +4,0 @@ module.exports = require('./node-loaders');

@@ -0,1 +1,3 @@

'use strict';
var fs = require('fs');

@@ -11,4 +13,5 @@ var path = require('path');

var FileSystemLoader = Loader.extend({
init: function(searchPaths, noWatch) {
init: function(searchPaths, noWatch, noCache) {
this.pathsToNames = {};
this.noCache = !!noCache;

@@ -29,6 +32,7 @@ if(searchPaths) {

if(existsSync(p)) {
var watcher = chokidar.watch(p, { ignoreInitial: true });
var watcher = chokidar.watch(p);
watcher.on("all", function(event, fullname) {
if(event == "change" && fullname in this.pathsToNames) {
watcher.on('all', function(event, fullname) {
fullname = path.resolve(fullname);
if(event === 'change' && fullname in this.pathsToNames) {
this.emit('update', this.pathsToNames[fullname]);

@@ -47,8 +51,8 @@ }

for(var i=0; i<paths.length; i++) {
var p = path.join(paths[i], name);
var basePath = path.resolve(paths[i]);
var p = path.resolve(paths[i], name);
// Only allow the current directory and anything
// underneath it to be searched
if((paths[i] == '.' || p.indexOf(paths[i]) === 0) &&
existsSync(p)) {
if(p.indexOf(basePath) === 0 && existsSync(p)) {
fullpath = p;

@@ -66,3 +70,4 @@ break;

return { src: fs.readFileSync(fullpath, 'utf-8'),
path: fullpath };
path: fullpath,
noCache: this.noCache };
}

@@ -69,0 +74,0 @@ });

@@ -0,1 +1,3 @@

'use strict';
var util = require('util');

@@ -15,3 +17,3 @@ var lib = require('./lib');

var Node = Object.extend("Node", {
var Node = Object.extend('Node', {
init: function(lineno, colno) {

@@ -67,6 +69,6 @@ this.lineno = lineno;

// Abstract nodes
var Value = Node.extend("Value", { fields: ['value'] });
var Value = Node.extend('Value', { fields: ['value'] });
// Concrete nodes
var NodeList = Node.extend("NodeList", {
var NodeList = Node.extend('NodeList', {
fields: ['children'],

@@ -83,20 +85,20 @@

var Root = NodeList.extend("Root");
var Literal = Value.extend("Literal");
var Symbol = Value.extend("Symbol");
var Group = NodeList.extend("Group");
var Array = NodeList.extend("Array");
var Pair = Node.extend("Pair", { fields: ['key', 'value'] });
var Dict = NodeList.extend("Dict");
var LookupVal = Node.extend("LookupVal", { fields: ['target', 'val'] });
var If = Node.extend("If", { fields: ['cond', 'body', 'else_'] });
var IfAsync = If.extend("IfAsync");
var InlineIf = Node.extend("InlineIf", { fields: ['cond', 'body', 'else_'] });
var For = Node.extend("For", { fields: ['arr', 'name', 'body', 'else_'] });
var AsyncEach = For.extend("AsyncEach");
var AsyncAll = For.extend("AsyncAll");
var Macro = Node.extend("Macro", { fields: ['name', 'args', 'body'] });
var Caller = Macro.extend("Caller");
var Import = Node.extend("Import", { fields: ['template', 'target', 'withContext'] });
var FromImport = Node.extend("FromImport", {
var Root = NodeList.extend('Root');
var Literal = Value.extend('Literal');
var Symbol = Value.extend('Symbol');
var Group = NodeList.extend('Group');
var Array = NodeList.extend('Array');
var Pair = Node.extend('Pair', { fields: ['key', 'value'] });
var Dict = NodeList.extend('Dict');
var LookupVal = Node.extend('LookupVal', { fields: ['target', 'val'] });
var If = Node.extend('If', { fields: ['cond', 'body', 'else_'] });
var IfAsync = If.extend('IfAsync');
var InlineIf = Node.extend('InlineIf', { fields: ['cond', 'body', 'else_'] });
var For = Node.extend('For', { fields: ['arr', 'name', 'body', 'else_'] });
var AsyncEach = For.extend('AsyncEach');
var AsyncAll = For.extend('AsyncAll');
var Macro = Node.extend('Macro', { fields: ['name', 'args', 'body'] });
var Caller = Macro.extend('Caller');
var Import = Node.extend('Import', { fields: ['template', 'target', 'withContext'] });
var FromImport = Node.extend('FromImport', {
fields: ['template', 'names', 'withContext'],

@@ -110,37 +112,37 @@

});
var FunCall = Node.extend("FunCall", { fields: ['name', 'args'] });
var Filter = FunCall.extend("Filter");
var FilterAsync = Filter.extend("FilterAsync", {
var FunCall = Node.extend('FunCall', { fields: ['name', 'args'] });
var Filter = FunCall.extend('Filter');
var FilterAsync = Filter.extend('FilterAsync', {
fields: ['name', 'args', 'symbol']
});
var KeywordArgs = Dict.extend("KeywordArgs");
var Block = Node.extend("Block", { fields: ['name', 'body'] });
var Super = Node.extend("Super", { fields: ['blockName', 'symbol'] });
var TemplateRef = Node.extend("TemplateRef", { fields: ['template'] });
var Extends = TemplateRef.extend("Extends");
var Include = TemplateRef.extend("Include");
var Set = Node.extend("Set", { fields: ['targets', 'value'] });
var Output = NodeList.extend("Output");
var TemplateData = Literal.extend("TemplateData");
var UnaryOp = Node.extend("UnaryOp", { fields: ['target'] });
var BinOp = Node.extend("BinOp", { fields: ['left', 'right'] });
var In = BinOp.extend("In");
var Or = BinOp.extend("Or");
var And = BinOp.extend("And");
var Not = UnaryOp.extend("Not");
var Add = BinOp.extend("Add");
var Sub = BinOp.extend("Sub");
var Mul = BinOp.extend("Mul");
var Div = BinOp.extend("Div");
var FloorDiv = BinOp.extend("FloorDiv");
var Mod = BinOp.extend("Mod");
var Pow = BinOp.extend("Pow");
var Neg = UnaryOp.extend("Neg");
var Pos = UnaryOp.extend("Pos");
var Compare = Node.extend("Compare", { fields: ['expr', 'ops'] });
var CompareOperand = Node.extend("CompareOperand", {
var KeywordArgs = Dict.extend('KeywordArgs');
var Block = Node.extend('Block', { fields: ['name', 'body'] });
var Super = Node.extend('Super', { fields: ['blockName', 'symbol'] });
var TemplateRef = Node.extend('TemplateRef', { fields: ['template'] });
var Extends = TemplateRef.extend('Extends');
var Include = TemplateRef.extend('Include');
var Set = Node.extend('Set', { fields: ['targets', 'value'] });
var Output = NodeList.extend('Output');
var TemplateData = Literal.extend('TemplateData');
var UnaryOp = Node.extend('UnaryOp', { fields: ['target'] });
var BinOp = Node.extend('BinOp', { fields: ['left', 'right'] });
var In = BinOp.extend('In');
var Or = BinOp.extend('Or');
var And = BinOp.extend('And');
var Not = UnaryOp.extend('Not');
var Add = BinOp.extend('Add');
var Sub = BinOp.extend('Sub');
var Mul = BinOp.extend('Mul');
var Div = BinOp.extend('Div');
var FloorDiv = BinOp.extend('FloorDiv');
var Mod = BinOp.extend('Mod');
var Pow = BinOp.extend('Pow');
var Neg = UnaryOp.extend('Neg');
var Pos = UnaryOp.extend('Pos');
var Compare = Node.extend('Compare', { fields: ['expr', 'ops'] });
var CompareOperand = Node.extend('CompareOperand', {
fields: ['expr', 'type']
});
var CustomTag = Node.extend("CustomTag", {
var CustomTag = Node.extend('CustomTag', {
init: function(lineno, colno, name) {

@@ -153,3 +155,3 @@ this.lineno = lineno;

var CallExtension = Node.extend("CallExtension", {
var CallExtension = Node.extend('CallExtension', {
fields: ['extName', 'prop', 'args', 'contentArgs'],

@@ -166,3 +168,3 @@

var CallExtensionAsync = CallExtension.extend("CallExtensionAsync");
var CallExtensionAsync = CallExtension.extend('CallExtensionAsync');

@@ -175,3 +177,3 @@ // Print the AST in a nicely formatted tree format for debuggin

function print(str, indent, inline) {
var lines = str.split("\n");
var lines = str.split('\n');

@@ -182,3 +184,3 @@ for(var i=0; i<lines.length; i++) {

for(var j=0; j<indent; j++) {
util.print(" ");
util.print(' ');
}

@@ -197,3 +199,3 @@ }

print(node.typename + ": ", indent);
print(node.typename + ': ', indent);

@@ -200,0 +202,0 @@ if(node instanceof NodeList) {

@@ -0,1 +1,2 @@

'use strict';

@@ -17,4 +18,4 @@ // A simple class system, more documentation to come

if(typeof parent == "function" &&
typeof src == "function" &&
if(typeof parent === 'function' &&
typeof src === 'function' &&
fnTest.test(src)) {

@@ -52,5 +53,5 @@ prototype[k] = (function (src, parent) {

new_cls.extend = function(name, props) {
if(typeof name == "object") {
if(typeof name === 'object') {
props = name;
name = "anonymous";
name = 'anonymous';
}

@@ -63,2 +64,2 @@ return extend(new_cls, name, props);

module.exports = extend(Object, "Object", {});
module.exports = extend(Object, 'Object', {});

@@ -0,1 +1,3 @@

'use strict';
var lexer = require('./lexer');

@@ -20,3 +22,3 @@ var nodes = require('./nodes');

if(this.peeked) {
if(!withWhitespace && this.peeked.type == lexer.TOKEN_WHITESPACE) {
if(!withWhitespace && this.peeked.type === lexer.TOKEN_WHITESPACE) {
this.peeked = null;

@@ -34,3 +36,3 @@ }

if(!withWhitespace) {
while(tok && tok.type == lexer.TOKEN_WHITESPACE) {
while(tok && tok.type === lexer.TOKEN_WHITESPACE) {
tok = this.tokens.nextToken();

@@ -50,3 +52,3 @@ }

if(this.peeked) {
throw new Error("pushToken: can only push one token on between reads");
throw new Error('pushToken: can only push one token on between reads');
}

@@ -70,3 +72,3 @@ this.peeked = tok;

var tok = this.nextToken();
if(!tok || tok.type != type) {
if(!tok || tok.type !== type) {
this.pushToken(tok);

@@ -90,3 +92,3 @@ return false;

var tok = this.nextToken();
if(!tok || tok.type != type || tok.value != val) {
if(!tok || tok.type !== type || tok.value !== val) {
this.pushToken(tok);

@@ -114,5 +116,5 @@ return false;

if(tok.type != lexer.TOKEN_SYMBOL) {
this.fail("advanceAfterBlockEnd: expected symbol token or " +
"explicit name to be passed");
if(tok.type !== lexer.TOKEN_SYMBOL) {
this.fail('advanceAfterBlockEnd: expected symbol token or ' +
'explicit name to be passed');
}

@@ -125,3 +127,3 @@

if(tok && tok.type == lexer.TOKEN_BLOCK_END) {
if(tok && tok.type === lexer.TOKEN_BLOCK_END) {
if(tok.value.charAt(0) === '-') {

@@ -132,3 +134,3 @@ this.dropLeadingWhitespace = true;

else {
this.fail("expected block end in " + name + " statement");
this.fail('expected block end in ' + name + ' statement');
}

@@ -139,3 +141,3 @@ },

if(!this.skip(lexer.TOKEN_VARIABLE_END)) {
this.fail("expected variable end");
this.fail('expected variable end');
}

@@ -162,3 +164,3 @@ },

else {
this.fail("parseFor: expected for{Async}", forTok.lineno, forTok.colno);
this.fail('parseFor: expected for{Async}', forTok.lineno, forTok.colno);
}

@@ -173,3 +175,3 @@

var type = this.peekToken().type;
if(type == lexer.TOKEN_COMMA) {
if(type === lexer.TOKEN_COMMA) {
// key/value iteration

@@ -210,3 +212,3 @@ var key = node.name;

if(!this.skipSymbol('macro')) {
this.fail("expected macro");
this.fail('expected macro');
}

@@ -233,3 +235,3 @@

if(!this.skipSymbol('call')) {
this.fail("expected call");
this.fail('expected call');
}

@@ -295,3 +297,3 @@

if(!this.skipSymbol('import')) {
this.fail("parseImport: expected import",
this.fail('parseImport: expected import',
importTok.lineno,

@@ -327,3 +329,3 @@ importTok.colno);

if(!this.skipSymbol('from')) {
this.fail("parseFrom: expected from");
this.fail('parseFrom: expected from');
}

@@ -334,3 +336,3 @@

if(!this.skipSymbol('import')) {
this.fail("parseFrom: expected import",
this.fail('parseFrom: expected import',
fromTok.lineno,

@@ -345,3 +347,3 @@ fromTok.colno);

var nextTok = this.peekToken();
if(nextTok.type == lexer.TOKEN_BLOCK_END) {
if(nextTok.type === lexer.TOKEN_BLOCK_END) {
if(!names.children.length) {

@@ -356,3 +358,3 @@ this.fail('parseFrom: Expected at least one import name',

// this is done in `advanceAfterBlockEnd`
if(nextTok.value.charAt(0) == '-') {
if(nextTok.value.charAt(0) === '-') {
this.dropLeadingWhitespace = true;

@@ -372,3 +374,3 @@ }

var name = this.parsePrimary();
if(name.value.charAt(0) == '_') {
if(name.value.charAt(0) === '_') {
this.fail('parseFrom: names starting with an underscore ' +

@@ -461,3 +463,3 @@ 'cannot be imported',

else {
this.fail("parseIf: expected if or elif",
this.fail('parseIf: expected if or elif',
tag.lineno,

@@ -474,11 +476,11 @@ tag.colno);

switch(tok && tok.value) {
case "elif":
case 'elif':
node.else_ = this.parseIf();
break;
case "else":
case 'else':
this.advanceAfterBlockEnd();
node.else_ = this.parseUntilBlocks("endif");
node.else_ = this.parseUntilBlocks('endif');
this.advanceAfterBlockEnd();
break;
case "endif":
case 'endif':
node.else_ = null;

@@ -528,3 +530,3 @@ this.advanceAfterBlockEnd();

if(tok.type != lexer.TOKEN_SYMBOL) {
if(tok.type !== lexer.TOKEN_SYMBOL) {
this.fail('tag name expected', tok.lineno, tok.colno);

@@ -581,6 +583,6 @@ }

if(!tok) {
this.fail("expected endraw, got end of file");
this.fail('expected endraw, got end of file');
}
if(tok.type == lexer.TOKEN_BLOCK_START) {
if(tok.type === lexer.TOKEN_BLOCK_START) {
// We need to look for the `endraw` block statement,

@@ -592,3 +594,3 @@ // which involves a lookahead so carefully keep track

if(name.type == lexer.TOKEN_WHITESPACE) {
if(name.type === lexer.TOKEN_WHITESPACE) {
ws = name;

@@ -598,4 +600,4 @@ name = this.nextToken();

if(name.type == lexer.TOKEN_SYMBOL &&
name.value == 'endraw') {
if(name.type === lexer.TOKEN_SYMBOL &&
name.value === 'endraw') {
this.advanceAfterBlockEnd(name.value);

@@ -634,3 +636,3 @@ break;

while(tok) {
if(tok.type == lexer.TOKEN_LEFT_PAREN) {
if(tok.type === lexer.TOKEN_LEFT_PAREN) {
// Function call

@@ -642,3 +644,3 @@ node = new nodes.FunCall(tok.lineno,

}
else if(tok.type == lexer.TOKEN_LEFT_BRACKET) {
else if(tok.type === lexer.TOKEN_LEFT_BRACKET) {
// Reference

@@ -655,3 +657,3 @@ var lookup = this.parseAggregate();

}
else if(tok.type == lexer.TOKEN_OPERATOR && tok.value == '.') {
else if(tok.type === lexer.TOKEN_OPERATOR && tok.value === '.') {
// Reference

@@ -661,3 +663,3 @@ this.nextToken();

if(val.type != lexer.TOKEN_SYMBOL) {
if(val.type !== lexer.TOKEN_SYMBOL) {
this.fail('expected name as lookup value, got ' + val.value,

@@ -752,3 +754,3 @@ val.lineno,

if (!tok) { break; }
var invert = tok.type == lexer.TOKEN_SYMBOL && tok.value == 'not';
var invert = tok.type === lexer.TOKEN_SYMBOL && tok.value === 'not';
// if it wasn't 'not', put it back

@@ -928,20 +930,20 @@ if (!invert) { this.pushToken(tok); }

}
else if(tok.type == lexer.TOKEN_STRING) {
else if(tok.type === lexer.TOKEN_STRING) {
val = tok.value;
}
else if(tok.type == lexer.TOKEN_INT) {
else if(tok.type === lexer.TOKEN_INT) {
val = parseInt(tok.value, 10);
}
else if(tok.type == lexer.TOKEN_FLOAT) {
else if(tok.type === lexer.TOKEN_FLOAT) {
val = parseFloat(tok.value);
}
else if(tok.type == lexer.TOKEN_BOOLEAN) {
if(tok.value == "true") {
else if(tok.type === lexer.TOKEN_BOOLEAN) {
if(tok.value === 'true') {
val = true;
}
else if(tok.value == "false") {
else if(tok.value === 'false') {
val = false;
}
else {
this.fail("invalid boolean: " + tok.value,
this.fail('invalid boolean: ' + tok.value,
tok.lineno,

@@ -951,3 +953,3 @@ tok.colno);

}
else if (tok.type == lexer.TOKEN_REGEX) {
else if (tok.type === lexer.TOKEN_REGEX) {
val = new RegExp(tok.value.body, tok.value.flags);

@@ -959,3 +961,3 @@ }

}
else if(tok.type == lexer.TOKEN_SYMBOL) {
else if(tok.type === lexer.TOKEN_SYMBOL) {
node = new nodes.Symbol(tok.lineno, tok.colno, tok.value);

@@ -1005,3 +1007,3 @@

if(this.peekToken().type == lexer.TOKEN_LEFT_PAREN) {
if(this.peekToken().type === lexer.TOKEN_LEFT_PAREN) {
// Get a FunCall node and add the parameters to the

@@ -1034,5 +1036,5 @@ // filter

var type = this.peekToken().type;
if(type == lexer.TOKEN_RIGHT_PAREN ||
type == lexer.TOKEN_RIGHT_BRACKET ||
type == lexer.TOKEN_RIGHT_CURLY) {
if(type === lexer.TOKEN_RIGHT_PAREN ||
type === lexer.TOKEN_RIGHT_BRACKET ||
type === lexer.TOKEN_RIGHT_CURLY) {
this.nextToken();

@@ -1044,3 +1046,3 @@ break;

if(!this.skip(lexer.TOKEN_COMMA)) {
this.fail("parseAggregate: expected comma after expression",
this.fail('parseAggregate: expected comma after expression',
tok.lineno,

@@ -1058,3 +1060,3 @@ tok.colno);

if(!this.skip(lexer.TOKEN_COLON)) {
this.fail("parseAggregate: expected colon after dict key",
this.fail('parseAggregate: expected colon after dict key',
tok.lineno,

@@ -1083,3 +1085,3 @@ tok.colno);

var tok = this.peekToken();
if(!noParens && tok.type != lexer.TOKEN_LEFT_PAREN) {
if(!noParens && tok.type !== lexer.TOKEN_LEFT_PAREN) {
if(tolerant) {

@@ -1093,3 +1095,3 @@ return null;

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

@@ -1105,7 +1107,7 @@ }

tok = this.peekToken();
if(!noParens && 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) {
else if(noParens && tok.type === lexer.TOKEN_BLOCK_END) {
break;

@@ -1115,3 +1117,3 @@ }

if(checkComma && !this.skip(lexer.TOKEN_COMMA)) {
this.fail("parseSignature: expected comma after expression",
this.fail('parseSignature: expected comma after expression',
tok.lineno,

@@ -1161,3 +1163,3 @@ tok.colno);

while((tok = this.nextToken())) {
if(tok.type == lexer.TOKEN_DATA) {
if(tok.type === lexer.TOKEN_DATA) {
var data = tok.value;

@@ -1178,4 +1180,4 @@ var nextToken = this.peekToken();

if(nextToken &&
nextToken.type == lexer.TOKEN_BLOCK_START &&
nextVal.charAt(nextVal.length - 1) == '-') {
nextToken.type === lexer.TOKEN_BLOCK_START &&
nextVal.charAt(nextVal.length - 1) === '-') {
// TODO: this could be optimized (don't use regex)

@@ -1191,3 +1193,3 @@ data = data.replace(/\s*$/, '');

}
else if(tok.type == lexer.TOKEN_BLOCK_START) {
else if(tok.type === lexer.TOKEN_BLOCK_START) {
var n = this.parseStatement();

@@ -1199,3 +1201,3 @@ if(!n) {

}
else if(tok.type == lexer.TOKEN_VARIABLE_START) {
else if(tok.type === lexer.TOKEN_VARIABLE_START) {
var e = this.parseExpression();

@@ -1205,5 +1207,5 @@ this.advanceAfterVariableEnd();

}
else if(tok.type != lexer.TOKEN_COMMENT) {
else if(tok.type !== lexer.TOKEN_COMMENT) {
// Ignore comments, otherwise this should be an error
this.fail("Unexpected token at top-level: " +
this.fail('Unexpected token at top-level: ' +
tok.type, tok.lineno, tok.colno);

@@ -1238,4 +1240,4 @@ }

module.exports = {
parse: function(src, extensions, lexerTags) {
var p = new Parser(lexer.lex(src, lexerTags));
parse: function(src, extensions, opts) {
var p = new Parser(lexer.lex(src, opts));
if (extensions !== undefined) {

@@ -1242,0 +1244,0 @@ p.extensions = extensions;

@@ -0,1 +1,3 @@

'use strict';
var fs = require('fs');

@@ -38,3 +40,24 @@ var path = require('path');

var output = '';
var templates = [];
function addTemplates(dir) {
var files = fs.readdirSync(dir);
for(var i=0; i<files.length; i++) {
var filepath = path.join(dir, files[i]);
var subpath = filepath.substr(path.join(input, '/').length);
var stat = fs.statSync(filepath);
if(stat && stat.isDirectory()) {
subpath += '/';
if (!match(subpath, opts.exclude)) {
addTemplates(filepath);
}
}
else if(match(subpath, opts.include)) {
templates.push(filepath);
}
}
}
if(opts.isString) {

@@ -58,24 +81,2 @@ if(!opts.name) {

else if(pathStats.isDirectory()) {
var templates = [];
function addTemplates(dir) {
var files = fs.readdirSync(dir);
for(var i=0; i<files.length; i++) {
var filepath = path.join(dir, files[i]);
var subpath = filepath.substr(path.join(input, '/').length);
var stat = fs.statSync(filepath);
if(stat && stat.isDirectory()) {
subpath += '/';
if (!match(subpath, opts.exclude)) {
addTemplates(filepath);
}
}
else if(match(subpath, opts.include)) {
templates.push(filepath);
}
}
}
addTemplates(input);

@@ -82,0 +83,0 @@

@@ -0,1 +1,3 @@

'use strict';
var lib = require('./lib');

@@ -19,3 +21,3 @@ var Obj = require('./object');

var frame = this;
if(resolveUp) {

@@ -61,3 +63,3 @@ if((frame = this.resolve(parts[0]))) {

var val = this.variables[name];
if(val != null) {
if(val !== undefined && val !== null) {
return this;

@@ -155,3 +157,3 @@ }

function SafeString(val) {
if(typeof val != 'string') {
if(typeof val !== 'string') {
return val;

@@ -201,5 +203,5 @@ }

function suppressValue(val, autoescape) {
val = (val !== undefined && val !== null) ? val : "";
val = (val !== undefined && val !== null) ? val : '';
if(autoescape && typeof val === "string") {
if(autoescape && typeof val === 'string') {
val = lib.escape(val);

@@ -281,3 +283,3 @@ }

if(finished == len) {
if(finished === len) {
cb(null, outputArr.join(''));

@@ -291,3 +293,3 @@ }

if(len == 0) {
if(len === 0) {
cb(null, '');

@@ -315,3 +317,3 @@ }

if(len == 0) {
if(len === 0) {
cb(null, '');

@@ -318,0 +320,0 @@ }

@@ -0,1 +1,3 @@

'use strict';
var nodes = require('./nodes');

@@ -161,3 +163,3 @@ var lib = require('./lib');

if(node instanceof nodes.FunCall &&
node.name.value == 'super') {
node.name.value === 'super') {
hasSuper = true;

@@ -164,0 +166,0 @@ return new nodes.Symbol(node.lineno, node.colno, symbol);

@@ -0,1 +1,3 @@

'use strict';
var Loader = require('./loader');

@@ -17,3 +19,3 @@

return {
src: { type: "code",
src: { type: 'code',
obj: this.precompiled[name] },

@@ -45,3 +47,3 @@ path: name

else if(window.ActiveXObject) { // IE 8 and older
ajax = new ActiveXObject("Microsoft.XMLHTTP");
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}

@@ -48,0 +50,0 @@

(function() {
var expect, Environment, Loader, templatesPath;
'use strict';
if(typeof require != 'undefined') {
var expect, util, Environment, Loader, templatesPath;
var path = require('path');
var os = require('os');
if(typeof require !== 'undefined') {
expect = require('expect.js');
util = require('./util');
Environment = require('../src/environment').Environment;

@@ -25,3 +30,28 @@ Loader = require('../src/node-loaders').FileSystemLoader;

});
it('should handle correctly relative paths', function() {
var env = new Environment(new Loader(templatesPath));
var child1 = env.getTemplate('relative/test1.html');
var child2 = env.getTemplate('relative/test2.html');
expect(child1.render()).to.be('FooTest1BazFizzle');
expect(child2.render()).to.be('FooTest2BazFizzle');
});
it('should handle correctly cache for relative paths', function() {
var env = new Environment(new Loader(templatesPath));
var test = env.getTemplate('relative/test-cache.html');
expect(util.normEOL(test.render())).to.be('Test1\nTest2');
});
it('should handle correctly relative paths in renderString', function() {
var env = new Environment(new Loader(templatesPath));
expect(env.renderString('{% extends "./relative/test1.html" %}{% block block1 %}Test3{% endblock %}', {}, {
path: path.resolve(templatesPath, 'string.html')
})).to.be('FooTest3BazFizzle');
});
});
})();
(function() {
'use strict';
var expect, util, Environment, Template, fs;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -493,7 +495,7 @@ util = require('./util');

'{{ imp.foo() }} {{ imp.bar }}',
"Here's a macro baz");
'Here\'s a macro baz');
equal('{% from "import.html" import foo as baz, bar %}' +
'{{ bar }} {{ baz() }}',
"baz Here's a macro");
'baz Here\'s a macro');

@@ -518,3 +520,3 @@ // TODO: Should the for loop create a new frame for each

'{{ imp.foo() }}',
"Here's BAR");
'Here\'s BAR');

@@ -524,3 +526,3 @@ equal('{% set bar = "BAR" %}' +

'{{ foo() }}',
"Here's BAR");
'Here\'s BAR');

@@ -534,3 +536,3 @@ finish(done);

'{{ imp.foo() }}',
"Here's ");
'Here\'s ');

@@ -540,3 +542,3 @@ equal('{% set bar = "BAR" %}' +

'{{ foo() }}',
"Here's ");
'Here\'s ');

@@ -550,3 +552,3 @@ finish(done);

'{{ imp.foo() }}',
"Here's ");
'Here\'s ');

@@ -556,3 +558,3 @@ equal('{% set bar = "BAR" %}' +

'{{ foo() }}',
"Here's ");
'Here\'s ');

@@ -619,7 +621,7 @@ finish(done);

equal('hello world {% include tmpl %}',
{ name: 'thedude', tmpl: "include.html" },
{ name: 'thedude', tmpl: 'include.html' },
'hello world FooInclude thedude');
equal('hello world {% include data.tmpl %}',
{ name: 'thedude', data: {tmpl: "include.html"} },
{ name: 'thedude', data: {tmpl: 'include.html'} },
'hello world FooInclude thedude');

@@ -763,3 +765,3 @@

var content = parser.parseUntilBlocks("endtest");
var content = parser.parseUntilBlocks('endtest');
var tag = new nodes.CallExtension(this, 'run', null, [content]);

@@ -773,3 +775,3 @@ parser.advanceAfterBlockEnd();

// Reverse the string
return content().split("").reverse().join("");
return content().split('').reverse().join('');
};

@@ -800,3 +802,3 @@ }

// Reverse the string
return arg1.split("").reverse().join("");
return arg1.split('').reverse().join('');
};

@@ -837,6 +839,6 @@ }

this.run = function(context, body, intermediate) {
var output = body().split("").join(",");
var output = body().split('').join(',');
if(intermediate) {
// Reverse the string.
output += intermediate().split("").reverse().join("");
output += intermediate().split('').reverse().join('');
}

@@ -885,3 +887,3 @@ return output;

this.run = function(context, prefix, kwargs, body) {
if(typeof prefix == 'function') {
if(typeof prefix === 'function') {
body = prefix;

@@ -891,3 +893,3 @@ prefix = '';

}
else if(typeof kwargs == 'function') {
else if(typeof kwargs === 'function') {
body = kwargs;

@@ -894,0 +896,0 @@ kwargs = {};

(function() {
'use strict';
var expect, util, lib;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -65,3 +67,3 @@ util = require('./util');

it("dictsort", function(done) {
it('dictsort', function(done) {
// no real foolproof way to test that a js obj has been transformed

@@ -77,8 +79,8 @@ // from unsorted -> sorted, as its enumeration ordering is undefined

items: {
"e": 1,
"d": 2,
"c": 3,
"a": 4,
"f": 5,
"b": 6
'e': 1,
'd': 2,
'c': 3,
'a': 4,
'f': 5,
'b': 6
}

@@ -92,9 +94,9 @@ },

items: {
"ABC": 6,
"ABc": 5,
"Abc": 1,
"abc": 2
'ABC': 6,
'ABc': 5,
'Abc': 1,
'abc': 2
}
},
"ABC,ABc,Abc,abc,");
'ABC,ABc,Abc,abc,');

@@ -105,6 +107,6 @@ // use values for sort

items: {
"a": 6,
"b": 5,
"c": 1,
"d": 2
'a': 6,
'b': 5,
'c': 1,
'd': 2
}

@@ -196,4 +198,8 @@ },

it('list', function(done) {
var person = {name: 'Joe', age: 83};
equal('{% for i in "foobar" | list %}{{ i }},{% endfor %}',
'f,o,o,b,a,r,');
equal('{% for pair in person | list %}{{ pair.key }}: {{ pair.value }} - {% endfor %}',
{person: person}, 'name: Joe - age: 83 - ');
equal('{% for i in [1, 2] | list %}{{ i }}{% endfor %}', '12');
finish(done);

@@ -218,2 +224,14 @@ });

it('rejectattr', function(done) {
var foods = [{tasty: true}, {tasty: false}, {tasty: true}];
equal('{{ foods | rejectattr("tasty") | length }}', {foods: foods}, '1');
finish(done);
});
it('selectattr', function(done) {
var foods = [{tasty: true}, {tasty: false}, {tasty: true}];
equal('{{ foods | selectattr("tasty") | length }}', {foods: foods}, '2');
finish(done);
});
it('replace', function(done) {

@@ -333,3 +351,3 @@ equal('{{ "aaabbbccc" | replace("a", "x") }}', 'xxxbbbccc');

'foo <a href="http://www.example.com/">' +
'http://www.example.com/</a> bar')
'http://www.example.com/</a> bar');

@@ -336,0 +354,0 @@ // additional tests

(function() {
var expect, util, lib;
'use strict';
if(typeof require != 'undefined') {
var expect, util, lib, Environment, Loader, templatesPath;
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -6,0 +8,0 @@ util = require('./util');

(function() {
'use strict';
var expect, lib, lexer;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -21,3 +23,3 @@ lib = require('../src/lib');

if(!ws) {
while(tok && tok.type == lexer.TOKEN_WHITESPACE) {
while(tok && tok.type === lexer.TOKEN_WHITESPACE) {
tok = tokens.nextToken();

@@ -75,2 +77,47 @@ }

it('should trim blocks', function () {
tokens = lexer.lex(' {% if true %}\n foo\n {% endif %}\n', {trimBlocks: true});
hasTokens(tokens,
[lexer.TOKEN_DATA, ' '],
lexer.TOKEN_BLOCK_START,
lexer.TOKEN_SYMBOL,
lexer.TOKEN_BOOLEAN,
lexer.TOKEN_BLOCK_END,
[lexer.TOKEN_DATA, ' foo\n '],
lexer.TOKEN_BLOCK_START,
lexer.TOKEN_SYMBOL,
lexer.TOKEN_BLOCK_END);
});
it('should lstrip and trim blocks', function () {
tokens = lexer.lex('test\n {% if true %}\n foo\n {% endif %}\n</div>', {
lstripBlocks: true,
trimBlocks: true
});
hasTokens(tokens,
[lexer.TOKEN_DATA, 'test\n'],
lexer.TOKEN_BLOCK_START,
lexer.TOKEN_SYMBOL,
lexer.TOKEN_BOOLEAN,
lexer.TOKEN_BLOCK_END,
[lexer.TOKEN_DATA, ' foo\n'],
lexer.TOKEN_BLOCK_START,
lexer.TOKEN_SYMBOL,
lexer.TOKEN_BLOCK_END,
[lexer.TOKEN_DATA, '</div>']);
});
it('should lstrip and not collapse whitespace between blocks', function () {
tokens = lexer.lex(' {% t %} {% t %}', {lstripBlocks: true});
hasTokens(tokens,
lexer.TOKEN_BLOCK_START,
lexer.TOKEN_SYMBOL,
lexer.TOKEN_BLOCK_END,
[lexer.TOKEN_DATA, ' '],
lexer.TOKEN_BLOCK_START,
lexer.TOKEN_SYMBOL,
lexer.TOKEN_BLOCK_END);
});
it('should parse variable start and end', function() {

@@ -92,3 +139,3 @@ tokens = lexer.lex('data {{ foo }} bar bizzle');

expect(tok.type).to.be(lexer.TOKEN_SYMBOL);
expect(tok.value).to.be("foo");
expect(tok.value).to.be('foo');
});

@@ -248,3 +295,3 @@

it('should allow changing the variable start and end', function() {
tokens = lexer.lex('data {= var =}', {variableStart: '{=', variableEnd: '=}'});
tokens = lexer.lex('data {= var =}', {tags: {variableStart: '{=', variableEnd: '=}'}});
hasTokens(tokens,

@@ -258,3 +305,3 @@ lexer.TOKEN_DATA,

it('should allow changing the block start and end', function() {
tokens = lexer.lex('{= =}', {blockStart: '{=', blockEnd: '=}'});
tokens = lexer.lex('{= =}', {tags: {blockStart: '{=', blockEnd: '=}'}});
hasTokens(tokens,

@@ -266,3 +313,3 @@ lexer.TOKEN_BLOCK_START,

it('should allow changing the variable start and end', function() {
tokens = lexer.lex('data {= var =}', {variableStart: '{=', variableEnd: '=}'});
tokens = lexer.lex('data {= var =}', {tags: {variableStart: '{=', variableEnd: '=}'}});
hasTokens(tokens,

@@ -276,3 +323,3 @@ lexer.TOKEN_DATA,

it('should allow changing the comment start and end', function() {
tokens = lexer.lex('<!-- A comment! -->', {commentStart: '<!--', commentEnd: '-->'});
tokens = lexer.lex('<!-- A comment! -->', {tags: {commentStart: '<!--', commentEnd: '-->'}});
hasTokens(tokens,

@@ -286,3 +333,3 @@ lexer.TOKEN_COMMENT);

it('should have individual lexer tag settings for each environment', function() {
tokens = lexer.lex('{=', {variableStart: '{='});
tokens = lexer.lex('{=', {tags: {variableStart: '{='}});
hasTokens(tokens, lexer.TOKEN_VARIABLE_START);

@@ -293,3 +340,3 @@

tokens = lexer.lex('{{', {variableStart: '<<<'});
tokens = lexer.lex('{{', {tags: {variableStart: '<<<'}});
hasTokens(tokens, lexer.TOKEN_DATA);

@@ -296,0 +343,0 @@

(function() {
'use strict';
var expect, Environment, Loader, templatesPath;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -25,4 +27,4 @@ Environment = require('../src/environment').Environment;

MyLoader.prototype.getSource = function(name) {
return { src: "Hello World",
path: "/tmp/somewhere" };
return { src: 'Hello World',
path: '/tmp/somewhere' };
};

@@ -29,0 +31,0 @@

(function() {
'use strict';
var expect, lib, nodes, parser;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -145,3 +147,3 @@ lib = require('../src/lib');

isAST(parser.parse("{{ 'foo' }}"),
isAST(parser.parse('{{ \'foo\' }}'),
[nodes.Root,

@@ -151,3 +153,3 @@ [nodes.Output,

isAST(parser.parse("{{ true }}"),
isAST(parser.parse('{{ true }}'),
[nodes.Root,

@@ -157,3 +159,3 @@ [nodes.Output,

isAST(parser.parse("{{ false }}"),
isAST(parser.parse('{{ false }}'),
[nodes.Root,

@@ -163,3 +165,3 @@ [nodes.Output,

isAST(parser.parse("{{ foo }}"),
isAST(parser.parse('{{ foo }}'),
[nodes.Root,

@@ -169,3 +171,3 @@ [nodes.Output,

isAST(parser.parse("{{ r/23/gi }}"),
isAST(parser.parse('{{ r/23/gi }}'),
[nodes.Root,

@@ -177,3 +179,3 @@ [nodes.Output,

it('should parse aggregate types', function() {
isAST(parser.parse("{{ [1,2,3] }}"),
isAST(parser.parse('{{ [1,2,3] }}'),
[nodes.Root,

@@ -186,3 +188,3 @@ [nodes.Output,

isAST(parser.parse("{{ (1,2,3) }}"),
isAST(parser.parse('{{ (1,2,3) }}'),
[nodes.Root,

@@ -195,3 +197,3 @@ [nodes.Output,

isAST(parser.parse("{{ {foo: 1, 'two': 2} }}"),
isAST(parser.parse('{{ {foo: 1, \'two\': 2} }}'),
[nodes.Root,

@@ -450,3 +452,3 @@ [nodes.Output,

[nodes.FromImport,
[nodes.Literal, "foo/bar.html"],
[nodes.Literal, 'foo/bar.html'],
[nodes.NodeList,

@@ -639,3 +641,3 @@ [nodes.Symbol, 'baz'],

[nodes.Output,
[nodes.TemplateData, "sdfd"]]]]]]);
[nodes.TemplateData, 'sdfd']]]]]]);

@@ -658,7 +660,7 @@ isAST(parser.parse('{% testblocktag %}{{ 123 }}{% endtestblocktag %}',

[nodes.Literal, 123],
[nodes.Literal, "abc"],
[nodes.Literal, 'abc'],
[nodes.KeywordArgs,
[nodes.Pair,
[nodes.Symbol, "foo"],
[nodes.Literal, "bar"]]]]]]);
[nodes.Symbol, 'foo'],
[nodes.Literal, 'bar']]]]]]);

@@ -665,0 +667,0 @@ isAST(parser.parse('{% testargs %}', extensions),

(function() {
'use strict';
var expect, util;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
expect = require('expect.js');

@@ -6,0 +8,0 @@ util = require('./util');

(function() {
'use strict';
var Environment, Template, loader, templatesPath, expect;
if(typeof require != 'undefined') {
if(typeof require !== 'undefined') {
Environment = require('../src/environment').Environment;

@@ -53,2 +55,7 @@ Template = require('../src/environment').Template;

function normEOL(str) {
if (!str) return str;
return str.replace(/\r\n|\r/g, "\n");
}
function render(str, ctx, opts, cb) {

@@ -72,3 +79,3 @@ if(!opts) {

e.addFilter(name, opts.filters[name]);
}
}
}

@@ -79,3 +86,3 @@

e.addFilter(name, opts.asyncFilters[name], true);
}
}
}

@@ -99,7 +106,7 @@

cb(err, res);
cb(err, normEOL(res));
doneAsyncs++;
if(numAsyncs == doneAsyncs && doneHandler) {
if(numAsyncs === doneAsyncs && doneHandler) {
doneHandler();

@@ -111,6 +118,7 @@ }

if(typeof module != 'undefined') {
if(typeof module !== 'undefined') {
module.exports.render = render;
module.exports.equal = equal;
module.exports.finish = finish;
module.exports.normEOL = normEOL;
}

@@ -121,5 +129,6 @@ else {

equal: equal,
finish: finish
finish: finish,
normEOL: normEOL
};
}
})();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc