From cc837247634c3025ca03280df1d481482c2266f2 Mon Sep 17 00:00:00 2001 From: James Long Date: Fri, 3 Apr 2015 12:36:31 -0400 Subject: [PATCH] prep for v1.3.0 --- MAINTENANCE.md | 2 +- browser/nunjucks-slim.js | 139 +++++---- browser/nunjucks-slim.min.js | 4 +- browser/nunjucks.js | 573 +++++++++++++++++++---------------- browser/nunjucks.min.js | 8 +- package.json | 2 +- 6 files changed, 398 insertions(+), 330 deletions(-) diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 84310d89..b40b7114 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -16,7 +16,7 @@ Replace `v1.2.3` with whatever the last version was, and you'll see all the chan 3. Run the command to make sure the ready-made files for the browser are up-to-date. ``` -$ make browserfiles +$ npm run browserfiles ``` 4. Update the version in `package.json` diff --git a/browser/nunjucks-slim.js b/browser/nunjucks-slim.js index 64e32075..4a6fdb9a 100644 --- a/browser/nunjucks-slim.js +++ b/browser/nunjucks-slim.js @@ -1,8 +1,9 @@ -// Browser bundle of nunjucks 1.2.0 (slim, only works with precompiled templates) +// Browser bundle of nunjucks 1.3.0 (slim, only works with precompiled templates) (function() { var modules = {}; (function() { +'use strict'; // A simple class system, more documentation to come @@ -19,8 +20,8 @@ function extend(cls, name, props) { var src = props[k]; var parent = prototype[k]; - if(typeof parent == "function" && - typeof src == "function" && + if(typeof parent === 'function' && + typeof src === 'function' && fnTest.test(src)) { prototype[k] = (function (src, parent) { return function() { @@ -53,9 +54,9 @@ function extend(cls, name, props) { new_cls.prototype.constructor = new_cls; new_cls.extend = function(name, props) { - if(typeof name == "object") { + if(typeof name === 'object') { props = name; - name = "anonymous"; + name = 'anonymous'; } return extend(new_cls, name, props); }; @@ -63,18 +64,20 @@ function extend(cls, name, props) { return new_cls; } -modules['object'] = extend(Object, "Object", {}); +modules['object'] = extend(Object, 'Object', {}); })(); (function() { +'use strict'; + var ArrayProto = Array.prototype; var ObjProto = Object.prototype; var escapeMap = { '&': '&', '"': '"', - "'": ''', - "<": '<', - ">": '>' + '\'': ''', + '<': '<', + '>': '>' }; var escapeRegex = /[&"'<>]/g; @@ -111,7 +114,7 @@ exports.TemplateError = function(message, lineno, colno) { if (message instanceof Error) { // for casting regular js errors err = message; - message = message.name + ": " + message.message; + message = message.name + ': ' + message.message; } else { if(Error.captureStackTrace) { Error.captureStackTrace(err); @@ -125,7 +128,7 @@ exports.TemplateError = function(message, lineno, colno) { err.firstUpdate = true; err.Update = function(path) { - var message = "(" + (path || "unknown path") + ")"; + var message = '(' + (path || 'unknown path') + ')'; // only show lineno + colno next to path of template // where error occurred @@ -158,19 +161,19 @@ exports.escape = function(val) { }; 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]'; }; exports.groupBy = function(obj, val) { @@ -225,7 +228,7 @@ exports.each = function(obj, func, context) { return; } - if(ArrayProto.each && obj.each == ArrayProto.each) { + if(ArrayProto.each && obj.each === ArrayProto.each) { obj.forEach(func, context); } else if(obj.length === +obj.length) { @@ -325,7 +328,7 @@ exports.indexOf = Array.prototype.indexOf ? if(!Array.prototype.map) { Array.prototype.map = function() { - throw new Error("map is unimplemented for this js engine"); + throw new Error('map is unimplemented for this js engine'); }; } @@ -345,6 +348,8 @@ exports.keys = function(obj) { } })(); (function() { +'use strict'; + var lib = modules["lib"]; var Obj = modules["object"]; @@ -363,7 +368,7 @@ var Frame = Obj.extend({ var parts = name.split('.'); var obj = this.variables; var frame = this; - + if(resolveUp) { if((frame = this.resolve(parts[0]))) { frame.set(name, val); @@ -404,7 +409,7 @@ var Frame = Obj.extend({ resolve: function(name) { var p = this.parent; var val = this.variables[name]; - if(val != null) { + if(val !== undefined && val !== null) { return this; } return p && p.resolve(name); @@ -497,7 +502,7 @@ function numArgs(args) { // autoescaped. This happens magically because autoescaping only // occurs on primitive string objects. function SafeString(val) { - if(typeof val != 'string') { + if(typeof val !== 'string') { return val; } @@ -542,9 +547,9 @@ function markSafe(val) { } 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); } @@ -621,7 +626,7 @@ function asyncAll(arr, dimen, func, cb) { finished++; outputArr[i] = output; - if(finished == len) { + if(finished === len) { cb(null, outputArr.join('')); } } @@ -630,7 +635,7 @@ function asyncAll(arr, dimen, func, cb) { len = arr.length; outputArr = new Array(len); - if(len == 0) { + if(len === 0) { cb(null, ''); } else { @@ -653,7 +658,7 @@ function asyncAll(arr, dimen, func, cb) { len = keys.length; outputArr = new Array(len); - if(len == 0) { + if(len === 0) { cb(null, ''); } else { @@ -685,6 +690,8 @@ modules['runtime'] = { }; })(); (function() { +'use strict'; + var path = modules["path"]; var Obj = modules["object"]; var lib = modules["lib"]; @@ -708,12 +715,18 @@ var Loader = Obj.extend({ 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({ @@ -730,7 +743,7 @@ var WebLoader = Loader.extend({ getSource: function(name) { if(this.precompiled[name]) { return { - src: { type: "code", + src: { type: 'code', obj: this.precompiled[name] }, path: name }; @@ -757,7 +770,7 @@ var WebLoader = Loader.extend({ ajax = new XMLHttpRequest(); } else if(window.ActiveXObject) { // IE 8 and older - ajax = new ActiveXObject("Microsoft.XMLHTTP"); + ajax = new ActiveXObject('Microsoft.XMLHTTP'); } ajax.onreadystatechange = function() { @@ -784,6 +797,8 @@ modules['web-loaders'] = { }; })(); (function() { +'use strict'; + if(typeof window === 'undefined' || window !== this) { modules['loaders'] = modules["node-loaders"]; } @@ -792,6 +807,8 @@ else { } })(); (function() { +'use strict'; + var lib = modules["lib"]; var r = modules["runtime"]; @@ -839,8 +856,8 @@ var filters = { } 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); }, @@ -850,7 +867,7 @@ var filters = { dictsort: function(val, case_sensitive, by) { 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'); } var array = []; @@ -860,13 +877,13 @@ var filters = { } 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'); } array.sort(function(t1, t2) { @@ -882,14 +899,14 @@ var filters = { } } - return a > b ? 1 : (a == b ? 0 : -1); + return a > b ? 1 : (a === b ? 0 : -1); }); return array; }, escape: function(str) { - if(typeof str == 'string' || + if(typeof str === 'string' || str instanceof r.SafeString) { return lib.escape(str); } @@ -915,7 +932,7 @@ var filters = { var sp = lib.repeat(' ', width); for(var i=0; i= maxCount) { break; } @@ -1041,10 +1058,10 @@ var filters = { var factor = Math.pow(10, precision); var rounder; - if(method == 'ceil') { + if(method === 'ceil') { rounder = Math.ceil; } - else if(method == 'floor') { + else if(method === 'floor') { rounder = Math.floor; } else { @@ -1247,6 +1264,7 @@ filters.e = filters.escape; modules['filters'] = filters; })(); (function() { +'use strict'; function cycler(items) { var index = -1; @@ -1315,6 +1333,8 @@ var globals = { modules['globals'] = globals; })(); (function() { +'use strict'; + var path = modules["path"]; var lib = modules["lib"]; var Obj = modules["object"]; @@ -1373,17 +1393,15 @@ var Environment = Obj.extend({ initCache: function() { // Caching and cache busting - var cache = {}; - lib.each(this.loaders, function(loader) { - if(typeof loader.on === 'function'){ + loader.cache = {}; + + if(typeof loader.on === 'function') { loader.on('update', function(template) { - cache[template] = null; + loader.cache[template] = null; }); } }); - - this.cache = cache; }, addExtension: function(name, extension) { @@ -1416,7 +1434,14 @@ var Environment = Obj.extend({ 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) { // this fixes autoescape for templates referenced in symbols name = name.raw; @@ -1437,7 +1462,11 @@ var Environment = Obj.extend({ throw new Error('template names must be a string: ' + name); } - 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; + } if(tmpl) { if(eagerCompile) { @@ -1456,6 +1485,7 @@ var Environment = Obj.extend({ lib.asyncIter(this.loaders, function(loader, i, next, done) { function handle(src) { if(src) { + src.loader = loader; done(src); } else { @@ -1464,10 +1494,7 @@ var Environment = Obj.extend({ } // Resolve name relative to parentName - if (parentName && (name.indexOf("./") == 0 || - name.indexOf("../") == 0)) { - name = loader.resolve(parentName, name); - } + name = that.resolveTemplate(loader, parentName, name); if(loader.async) { loader.getSource(name, function(err, src) { @@ -1493,7 +1520,7 @@ var Environment = Obj.extend({ info.path, eagerCompile); if(!info.noCache) { - this.cache[name] = tmpl; + info.loader.cache[name] = tmpl; } if(cb) { @@ -1618,7 +1645,7 @@ var Context = Obj.extend({ var blk = this.blocks[name][idx + 1]; var context = this; - if(idx == -1 || !blk) { + if(idx === -1 || !blk) { throw new Error('no super block available for "' + name + '"'); } @@ -1653,8 +1680,8 @@ var Template = Obj.extend({ this.tmplStr = src; } 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'); } this.path = path; @@ -1768,7 +1795,7 @@ var Template = Obj.extend({ var blocks = {}; for(var k in props) { - if(k.slice(0, 2) == 'b_') { + if(k.slice(0, 2) === 'b_') { blocks[k.slice(2)] = props[k]; } } diff --git a/browser/nunjucks-slim.min.js b/browser/nunjucks-slim.min.js index 8d2e8fe9..43a0228f 100644 --- a/browser/nunjucks-slim.min.js +++ b/browser/nunjucks-slim.min.js @@ -1,3 +1,3 @@ -// Browser bundle of nunjucks 1.2.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={"&":"&",'"':""","'":"'","<":"<",">":">"};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>>0;fromIndex=+fromIndex||0;if(Math.abs(fromIndex)===Infinity){fromIndex=0}if(fromIndex<0){fromIndex+=length;if(fromIndex<0){fromIndex=0}}for(;fromIndexargNames.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=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=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=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(xy){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"+possibleUrl.substr(0,length)+"";if(wwwRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";if(emailRE.test(possibleUrl))return''+possibleUrl+"";if(tldRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";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":">"};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>>0;fromIndex=+fromIndex||0;if(Math.abs(fromIndex)===Infinity){fromIndex=0}if(fromIndex<0){fromIndex+=length;if(fromIndex<0){fromIndex=0}}for(;fromIndexargNames.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=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=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=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(xy){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"+possibleUrl.substr(0,length)+"";if(wwwRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";if(emailRE.test(possibleUrl))return''+possibleUrl+"";if(tldRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";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": '>' + '\'': ''', + '<': '<', + '>': '>' }; var escapeRegex = /[&"'<>]/g; @@ -111,7 +114,7 @@ exports.TemplateError = function(message, lineno, colno) { if (message instanceof Error) { // for casting regular js errors err = message; - message = message.name + ": " + message.message; + message = message.name + ': ' + message.message; } else { if(Error.captureStackTrace) { Error.captureStackTrace(err); @@ -125,7 +128,7 @@ exports.TemplateError = function(message, lineno, colno) { err.firstUpdate = true; err.Update = function(path) { - var message = "(" + (path || "unknown path") + ")"; + var message = '(' + (path || 'unknown path') + ')'; // only show lineno + colno next to path of template // where error occurred @@ -158,19 +161,19 @@ exports.escape = function(val) { }; 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]'; }; exports.groupBy = function(obj, val) { @@ -225,7 +228,7 @@ exports.each = function(obj, func, context) { return; } - if(ArrayProto.each && obj.each == ArrayProto.each) { + if(ArrayProto.each && obj.each === ArrayProto.each) { obj.forEach(func, context); } else if(obj.length === +obj.length) { @@ -325,7 +328,7 @@ exports.indexOf = Array.prototype.indexOf ? if(!Array.prototype.map) { Array.prototype.map = function() { - throw new Error("map is unimplemented for this js engine"); + throw new Error('map is unimplemented for this js engine'); }; } @@ -345,6 +348,8 @@ exports.keys = function(obj) { } })(); (function() { +'use strict'; + var util = modules["util"]; var lib = modules["lib"]; var Object = modules["object"]; @@ -359,7 +364,7 @@ function traverseAndCheck(obj, type, results) { } } -var Node = Object.extend("Node", { +var Node = Object.extend('Node', { init: function(lineno, colno) { this.lineno = lineno; this.colno = colno; @@ -410,10 +415,10 @@ var Node = Object.extend("Node", { }); // 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'], init: function(lineno, colno, nodes) { @@ -425,24 +430,24 @@ var NodeList = Node.extend("NodeList", { } }); -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'], init: function(lineno, colno, template, names, withContext) { @@ -451,41 +456,41 @@ var FromImport = Node.extend("FromImport", { names || new NodeList(), withContext); } }); -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) { this.lineno = lineno; this.colno = colno; @@ -493,7 +498,7 @@ var CustomTag = Node.extend("CustomTag", { } }); -var CallExtension = Node.extend("CallExtension", { +var CallExtension = Node.extend('CallExtension', { fields: ['extName', 'prop', 'args', 'contentArgs'], init: function(ext, prop, args, contentArgs) { @@ -505,7 +510,7 @@ var CallExtension = Node.extend("CallExtension", { } }); -var CallExtensionAsync = CallExtension.extend("CallExtensionAsync"); +var CallExtensionAsync = CallExtension.extend('CallExtensionAsync'); // Print the AST in a nicely formatted tree format for debuggin function printNodes(node, indent) { @@ -513,13 +518,13 @@ function printNodes(node, indent) { // This is hacky, but this is just a debugging function anyway function print(str, indent, inline) { - var lines = str.split("\n"); + var lines = str.split('\n'); for(var i=0; i 0) || !inline) { for(var j=0; j=', '//', '**']; @@ -1152,15 +1161,15 @@ Tokenizer.prototype.nextToken = function() { } 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; } @@ -1172,7 +1181,7 @@ Tokenizer.prototype.nextToken = function() { tok = this._extractUntil(whitespaceChars + delimChars); if(tok.match(/^[-+]?[0-9]+$/)) { - if(this.current() == '.') { + if(this.current() === '.') { this.forward(); var dec = this._extract(intChars); return token(TOKEN_FLOAT, tok + '.' + dec, lineno, colno); @@ -1188,7 +1197,7 @@ Tokenizer.prototype.nextToken = function() { return token(TOKEN_SYMBOL, tok, lineno, colno); } else { - throw new Error("Unexpected value while parsing: " + tok); + throw new Error('Unexpected value while parsing: ' + tok); } } } @@ -1256,7 +1265,7 @@ Tokenizer.prototype.nextToken = function() { } else if(this._matches(this.tags.COMMENT_END)) { if(!in_comment) { - throw new Error("unexpected end of comment"); + throw new Error('unexpected end of comment'); } tok += this._extractString(this.tags.COMMENT_END); break; @@ -1270,7 +1279,7 @@ Tokenizer.prototype.nextToken = function() { } 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'); } return token(in_comment ? TOKEN_COMMENT : TOKEN_DATA, @@ -1280,7 +1289,7 @@ Tokenizer.prototype.nextToken = function() { } } - throw new Error("Could not parse text"); + throw new Error('Could not parse text'); }; Tokenizer.prototype.parseString = function(delimiter) { @@ -1288,17 +1297,17 @@ Tokenizer.prototype.parseString = function(delimiter) { var lineno = this.lineno; 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: str += this.current(); } @@ -1320,7 +1329,7 @@ Tokenizer.prototype._matches = function(str) { } var m = this.str.slice(this.index, this.index + str.length); - return m == str; + return m === str; }; Tokenizer.prototype._extractString = function(str) { @@ -1334,7 +1343,7 @@ Tokenizer.prototype._extractString = function(str) { Tokenizer.prototype._extractUntil = function(charString) { // Extract all non-matching chars, with the default matching set // to everything - return this._extractMatching(true, charString || ""); + return this._extractMatching(true, charString || ''); }; Tokenizer.prototype._extract = function(charString) { @@ -1355,8 +1364,8 @@ Tokenizer.prototype._extractMatching = function (breakOnMatch, charString) { var first = charString.indexOf(this.current()); // 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(); this.forward(); @@ -1364,8 +1373,8 @@ Tokenizer.prototype._extractMatching = function (breakOnMatch, charString) { // breaking char var idx = charString.indexOf(this.current()); - while(((breakOnMatch && idx == -1) || - (!breakOnMatch && idx != -1)) && !this.is_finished()) { + while(((breakOnMatch && idx === -1) || + (!breakOnMatch && idx !== -1)) && !this.is_finished()) { t += this.current(); this.forward(); @@ -1375,7 +1384,7 @@ Tokenizer.prototype._extractMatching = function (breakOnMatch, charString) { return t; } - return ""; + return ''; }; Tokenizer.prototype.is_finished = function() { @@ -1391,7 +1400,7 @@ Tokenizer.prototype.forwardN = function(n) { Tokenizer.prototype.forward = function() { this.index++; - if(this.previous() == "\n") { + if(this.previous() === '\n') { this.lineno++; this.colno = 0; } @@ -1403,11 +1412,11 @@ Tokenizer.prototype.forward = function() { Tokenizer.prototype.back = function() { this.index--; - 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; } else { @@ -1423,7 +1432,7 @@ Tokenizer.prototype.current = function() { if(!this.is_finished()) { return this.str.charAt(this.index); } - return ""; + return ''; }; Tokenizer.prototype.previous = function() { @@ -1462,6 +1471,8 @@ modules['lexer'] = { }; })(); (function() { +'use strict'; + var lexer = modules["lexer"]; var nodes = modules["nodes"]; var Object = modules["object"]; @@ -1481,7 +1492,7 @@ var Parser = Object.extend({ var tok; if(this.peeked) { - if(!withWhitespace && this.peeked.type == lexer.TOKEN_WHITESPACE) { + if(!withWhitespace && this.peeked.type === lexer.TOKEN_WHITESPACE) { this.peeked = null; } else { @@ -1494,7 +1505,7 @@ var Parser = Object.extend({ tok = this.tokens.nextToken(); if(!withWhitespace) { - while(tok && tok.type == lexer.TOKEN_WHITESPACE) { + while(tok && tok.type === lexer.TOKEN_WHITESPACE) { tok = this.tokens.nextToken(); } } @@ -1509,7 +1520,7 @@ var Parser = Object.extend({ pushToken: function(tok) { 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'); } this.peeked = tok; }, @@ -1528,7 +1539,7 @@ var Parser = Object.extend({ skip: function(type) { var tok = this.nextToken(); - if(!tok || tok.type != type) { + if(!tok || tok.type !== type) { this.pushToken(tok); return false; } @@ -1547,7 +1558,7 @@ var Parser = Object.extend({ skipValue: function(type, val) { var tok = this.nextToken(); - if(!tok || tok.type != type || tok.value != val) { + if(!tok || tok.type !== type || tok.value !== val) { this.pushToken(tok); return false; } @@ -1570,9 +1581,9 @@ var Parser = Object.extend({ this.fail('unexpected end of file'); } - 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'); } name = this.nextToken().value; @@ -1580,19 +1591,19 @@ var Parser = Object.extend({ var tok = this.nextToken(); - if(tok && tok.type == lexer.TOKEN_BLOCK_END) { + if(tok && tok.type === lexer.TOKEN_BLOCK_END) { if(tok.value.charAt(0) === '-') { this.dropLeadingWhitespace = true; } } else { - this.fail("expected block end in " + name + " statement"); + this.fail('expected block end in ' + name + ' statement'); } }, advanceAfterVariableEnd: function() { if(!this.skip(lexer.TOKEN_VARIABLE_END)) { - this.fail("expected variable end"); + this.fail('expected variable end'); } }, @@ -1614,7 +1625,7 @@ var Parser = Object.extend({ endBlock = 'endall'; } else { - this.fail("parseFor: expected for{Async}", forTok.lineno, forTok.colno); + this.fail('parseFor: expected for{Async}', forTok.lineno, forTok.colno); } node.name = this.parsePrimary(); @@ -1624,7 +1635,7 @@ var Parser = Object.extend({ } var type = this.peekToken().type; - if(type == lexer.TOKEN_COMMA) { + if(type === lexer.TOKEN_COMMA) { // key/value iteration var key = node.name; node.name = new nodes.Array(key.lineno, key.colno); @@ -1660,7 +1671,7 @@ var Parser = Object.extend({ parseMacro: function() { var macroTok = this.peekToken(); if(!this.skipSymbol('macro')) { - this.fail("expected macro"); + this.fail('expected macro'); } var name = this.parsePrimary(true); @@ -1682,7 +1693,7 @@ var Parser = Object.extend({ // 'caller' kwarg which is a Caller node. var callTok = this.peekToken(); if(!this.skipSymbol('call')) { - this.fail("expected call"); + this.fail('expected call'); } var callerArgs = this.parseSignature(true) || new nodes.NodeList(); @@ -1743,7 +1754,7 @@ var Parser = Object.extend({ parseImport: function() { var importTok = this.peekToken(); if(!this.skipSymbol('import')) { - this.fail("parseImport: expected import", + this.fail('parseImport: expected import', importTok.lineno, importTok.colno); } @@ -1774,13 +1785,13 @@ var Parser = Object.extend({ parseFrom: function() { var fromTok = this.peekToken(); if(!this.skipSymbol('from')) { - this.fail("parseFrom: expected from"); + this.fail('parseFrom: expected from'); } var template = this.parsePrimary(); if(!this.skipSymbol('import')) { - this.fail("parseFrom: expected import", + this.fail('parseFrom: expected import', fromTok.lineno, fromTok.colno); } @@ -1790,7 +1801,7 @@ var Parser = Object.extend({ while(1) { var nextTok = this.peekToken(); - if(nextTok.type == lexer.TOKEN_BLOCK_END) { + if(nextTok.type === lexer.TOKEN_BLOCK_END) { if(!names.children.length) { this.fail('parseFrom: Expected at least one import name', fromTok.lineno, @@ -1800,7 +1811,7 @@ var Parser = Object.extend({ // Since we are manually advancing past the block end, // need to keep track of whitespace control (normally // this is done in `advanceAfterBlockEnd` - if(nextTok.value.charAt(0) == '-') { + if(nextTok.value.charAt(0) === '-') { this.dropLeadingWhitespace = true; } @@ -1815,7 +1826,7 @@ var Parser = Object.extend({ } var name = this.parsePrimary(); - if(name.value.charAt(0) == '_') { + if(name.value.charAt(0) === '_') { this.fail('parseFrom: names starting with an underscore ' + 'cannot be imported', name.lineno, @@ -1903,7 +1914,7 @@ var Parser = Object.extend({ node = new nodes.IfAsync(tag.lineno, tag.colno); } else { - this.fail("parseIf: expected if or elif", + this.fail('parseIf: expected if or elif', tag.lineno, tag.colno); } @@ -1915,15 +1926,15 @@ var Parser = Object.extend({ var tok = this.peekToken(); 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; this.advanceAfterBlockEnd(); break; @@ -1968,7 +1979,7 @@ var Parser = Object.extend({ var tok = this.peekToken(); var node; - if(tok.type != lexer.TOKEN_SYMBOL) { + if(tok.type !== lexer.TOKEN_SYMBOL) { this.fail('tag name expected', tok.lineno, tok.colno); } @@ -2020,23 +2031,23 @@ var Parser = Object.extend({ var tok = this.nextToken(true); 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, // which involves a lookahead so carefully keep track // of whitespace var ws = null; var name = this.nextToken(true); - if(name.type == lexer.TOKEN_WHITESPACE) { + if(name.type === lexer.TOKEN_WHITESPACE) { ws = name; 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); break; } @@ -2070,14 +2081,14 @@ var Parser = Object.extend({ var tok = this.peekToken(); while(tok) { - if(tok.type == lexer.TOKEN_LEFT_PAREN) { + if(tok.type === lexer.TOKEN_LEFT_PAREN) { // Function call node = new nodes.FunCall(tok.lineno, tok.colno, node, this.parseSignature()); } - else if(tok.type == lexer.TOKEN_LEFT_BRACKET) { + else if(tok.type === lexer.TOKEN_LEFT_BRACKET) { // Reference var lookup = this.parseAggregate(); if(lookup.children.length > 1) { @@ -2089,12 +2100,12 @@ var Parser = Object.extend({ node, lookup.children[0]); } - else if(tok.type == lexer.TOKEN_OPERATOR && tok.value == '.') { + else if(tok.type === lexer.TOKEN_OPERATOR && tok.value === '.') { // Reference this.nextToken(); var val = this.nextToken(); - if(val.type != lexer.TOKEN_SYMBOL) { + if(val.type !== lexer.TOKEN_SYMBOL) { this.fail('expected name as lookup value, got ' + val.value, val.lineno, val.colno); @@ -2184,7 +2195,7 @@ var Parser = Object.extend({ // check if the next token is 'not' var tok = this.nextToken(); 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 if (!invert) { this.pushToken(tok); } if (this.skipSymbol('in')) { @@ -2359,36 +2370,36 @@ var Parser = Object.extend({ if(!tok) { this.fail('expected expression, got end of file'); } - 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, 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); } if(val !== null) { node = new nodes.Literal(tok.lineno, tok.colno, val); } - else if(tok.type == lexer.TOKEN_SYMBOL) { + else if(tok.type === lexer.TOKEN_SYMBOL) { node = new nodes.Symbol(tok.lineno, tok.colno, tok.value); if(!noPostfix) { @@ -2433,7 +2444,7 @@ var Parser = Object.extend({ [node]) ); - 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 // filter var call = this.parsePostfix(node); @@ -2461,16 +2472,16 @@ var Parser = Object.extend({ while(1) { 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(); break; } if(node.children.length > 0) { if(!this.skip(lexer.TOKEN_COMMA)) { - this.fail("parseAggregate: expected comma after expression", + this.fail('parseAggregate: expected comma after expression', tok.lineno, tok.colno); } @@ -2483,7 +2494,7 @@ var Parser = Object.extend({ // We expect a key/value pair for dicts, separated by a // colon if(!this.skip(lexer.TOKEN_COLON)) { - this.fail("parseAggregate: expected colon after dict key", + this.fail('parseAggregate: expected colon after dict key', tok.lineno, tok.colno); } @@ -2507,7 +2518,7 @@ var Parser = Object.extend({ parseSignature: function(tolerant, noParens) { var tok = this.peekToken(); - if(!noParens && tok.type != lexer.TOKEN_LEFT_PAREN) { + if(!noParens && tok.type !== lexer.TOKEN_LEFT_PAREN) { if(tolerant) { return null; } @@ -2516,7 +2527,7 @@ var Parser = Object.extend({ } } - if(tok.type == lexer.TOKEN_LEFT_PAREN) { + if(tok.type === lexer.TOKEN_LEFT_PAREN) { tok = this.nextToken(); } @@ -2527,16 +2538,16 @@ var Parser = Object.extend({ while(1) { 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; } if(checkComma && !this.skip(lexer.TOKEN_COMMA)) { - this.fail("parseSignature: expected comma after expression", + this.fail('parseSignature: expected comma after expression', tok.lineno, tok.colno); } @@ -2581,7 +2592,7 @@ var Parser = Object.extend({ var buf = []; while((tok = this.nextToken())) { - if(tok.type == lexer.TOKEN_DATA) { + if(tok.type === lexer.TOKEN_DATA) { var data = tok.value; var nextToken = this.peekToken(); var nextVal = nextToken && nextToken.value; @@ -2597,8 +2608,8 @@ var Parser = Object.extend({ // Same for the succeding block start token 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) data = data.replace(/\s*$/, ''); } @@ -2609,21 +2620,21 @@ var Parser = Object.extend({ tok.colno, data)])); } - else if(tok.type == lexer.TOKEN_BLOCK_START) { + else if(tok.type === lexer.TOKEN_BLOCK_START) { var n = this.parseStatement(); if(!n) { break; } buf.push(n); } - else if(tok.type == lexer.TOKEN_VARIABLE_START) { + else if(tok.type === lexer.TOKEN_VARIABLE_START) { var e = this.parseExpression(); this.advanceAfterVariableEnd(); buf.push(new nodes.Output(tok.lineno, tok.colno, [e])); } - 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); } } @@ -2663,6 +2674,8 @@ modules['parser'] = { }; })(); (function() { +'use strict'; + var nodes = modules["nodes"]; var lib = modules["lib"]; @@ -2823,7 +2836,7 @@ function liftSuper(ast) { blockNode.body = walk(blockNode.body, function(node) { if(node instanceof nodes.FunCall && - node.name.value == 'super') { + node.name.value === 'super') { hasSuper = true; return new nodes.Symbol(node.lineno, node.colno, symbol); } @@ -2899,6 +2912,8 @@ modules['transformer'] = { }; })(); (function() { +'use strict'; + var lib = modules["lib"]; var parser = modules["parser"]; var transformer = modules["transformer"]; @@ -2959,7 +2974,7 @@ var Compiler = Object.extend({ }, emitLine: function(code) { - this.emit(code + "\n"); + this.emit(code + '\n'); }, emitLines: function() { @@ -3022,6 +3037,10 @@ var Compiler = Object.extend({ return 't_' + this.lastId; }, + _templateName: function() { + return this.templateName == null? 'undefined' : JSON.stringify(this.templateName); + }, + _bufferAppend: function(func) { this.emit(this.buffer + ' += runtime.suppressValue('); func.call(this); @@ -3099,7 +3118,7 @@ var Compiler = Object.extend({ } if(!success) { - this.fail("assertType: invalid type: " + node.typename, + this.fail('assertType: invalid type: ' + node.typename, node.lineno, node.colno); } @@ -3135,7 +3154,7 @@ var Compiler = Object.extend({ // object as the last argument, if they exist. this._compileExpression(arg, frame); - if(i != args.children.length - 1 || contentArgs.length) { + if(i !== args.children.length - 1 || contentArgs.length) { this.emit(','); } }, this); @@ -3190,12 +3209,12 @@ var Compiler = Object.extend({ }, 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 + '"'); } else { @@ -3236,8 +3255,8 @@ var Compiler = Object.extend({ key = new nodes.Literal(key.lineno, key.colno, key.value); } 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, key.colno); } @@ -3406,7 +3425,7 @@ var Compiler = Object.extend({ var name = target.value; var id = frame.lookup(name); - if (id == null) { + if (id === null || id === undefined) { id = this.tmpid(); // Note: This relies on js allowing scope across @@ -3431,7 +3450,7 @@ var Compiler = Object.extend({ // uncommon to assign to multiple vars anyway this.emitLine('if(!frame.parent) {'); this.emitLine('context.setVariable("' + name + '", ' + id + ');'); - if(name.charAt(0) != '_') { + if(name.charAt(0) !== '_') { this.emitLine('context.addExport("' + name + '");'); } this.emitLine('}'); @@ -3766,7 +3785,7 @@ var Compiler = Object.extend({ this.emitLine('frame.set("' + name + '", ' + funcId + ');'); } else { - if(node.name.value.charAt(0) != '_') { + if(node.name.value.charAt(0) !== '_') { this.emitLine('context.addExport("' + name + '");'); } this.emitLine('context.setVariable("' + name + '", ' + funcId + ');'); @@ -3786,7 +3805,7 @@ var Compiler = Object.extend({ this.emit('env.getTemplate('); this._compileExpression(node.template, frame); - this.emitLine(', false, "' + this.templateName + '", ' + this.makeCallback(id)); + this.emitLine(', false, '+this._templateName()+', ' + this.makeCallback(id)); this.addScopeLevel(); this.emitLine(id + '.getExported(' + @@ -3809,7 +3828,7 @@ var Compiler = Object.extend({ this.emit('env.getTemplate('); this._compileExpression(node.template, frame); - this.emitLine(', false, "' + this.templateName + '", ' + this.makeCallback(importedId)); + this.emitLine(', false, '+this._templateName()+', ' + this.makeCallback(importedId)); this.addScopeLevel(); this.emitLine(importedId + '.getExported(' + @@ -3884,7 +3903,7 @@ var Compiler = Object.extend({ this.emit('env.getTemplate('); this._compileExpression(node.template, frame); - this.emitLine(', true, "' + this.templateName + '", ' + this.makeCallback('parentTemplate')); + this.emitLine(', true, '+this._templateName()+', ' + this.makeCallback('parentTemplate')); this.emitLine('for(var ' + k + ' in parentTemplate.blocks) {'); this.emitLine('context.addBlock(' + k + @@ -3901,7 +3920,7 @@ var Compiler = Object.extend({ this.emit('env.getTemplate('); this._compileExpression(node.template, frame); - this.emitLine(', false, "' + this.templateName + '", '+ this.makeCallback(id)); + this.emitLine(', false, '+this._templateName()+', '+ this.makeCallback(id)); this.addScopeLevel(); this.emitLine(id + '.render(' + @@ -3936,7 +3955,7 @@ var Compiler = Object.extend({ compileRoot: function(node, frame) { if(frame) { - this.fail("compileRoot: root node can't have frame"); + this.fail('compileRoot: root node can\'t have frame'); } frame = new Frame(); @@ -3973,12 +3992,12 @@ var Compiler = Object.extend({ }, compile: function (node, frame) { - var _compile = this["compile" + node.typename]; + var _compile = this['compile' + node.typename]; if(_compile) { _compile.call(this, node, frame); } else { - this.fail("compile: Cannot compile node: " + node.typename, + this.fail('compile: Cannot compile node: ' + node.typename, node.lineno, node.colno); } @@ -4022,6 +4041,8 @@ modules['compiler'] = { }; })(); (function() { +'use strict'; + var lib = modules["lib"]; var r = modules["runtime"]; @@ -4069,8 +4090,8 @@ var filters = { } 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); }, @@ -4080,7 +4101,7 @@ var filters = { dictsort: function(val, case_sensitive, by) { 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'); } var array = []; @@ -4090,13 +4111,13 @@ var filters = { } 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'); } array.sort(function(t1, t2) { @@ -4112,14 +4133,14 @@ var filters = { } } - return a > b ? 1 : (a == b ? 0 : -1); + return a > b ? 1 : (a === b ? 0 : -1); }); return array; }, escape: function(str) { - if(typeof str == 'string' || + if(typeof str === 'string' || str instanceof r.SafeString) { return lib.escape(str); } @@ -4145,7 +4166,7 @@ var filters = { var sp = lib.repeat(' ', width); for(var i=0; i= maxCount) { break; } @@ -4271,10 +4292,10 @@ var filters = { var factor = Math.pow(10, precision); var rounder; - if(method == 'ceil') { + if(method === 'ceil') { rounder = Math.ceil; } - else if(method == 'floor') { + else if(method === 'floor') { rounder = Math.floor; } else { @@ -4477,6 +4498,7 @@ filters.e = filters.escape; modules['filters'] = filters; })(); (function() { +'use strict'; function cycler(items) { var index = -1; @@ -4545,6 +4567,8 @@ var globals = { modules['globals'] = globals; })(); (function() { +'use strict'; + var path = modules["path"]; var Obj = modules["object"]; var lib = modules["lib"]; @@ -4568,12 +4592,18 @@ var Loader = Obj.extend({ 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({ @@ -4590,7 +4620,7 @@ var WebLoader = Loader.extend({ getSource: function(name) { if(this.precompiled[name]) { return { - src: { type: "code", + src: { type: 'code', obj: this.precompiled[name] }, path: name }; @@ -4617,7 +4647,7 @@ var WebLoader = Loader.extend({ ajax = new XMLHttpRequest(); } else if(window.ActiveXObject) { // IE 8 and older - ajax = new ActiveXObject("Microsoft.XMLHTTP"); + ajax = new ActiveXObject('Microsoft.XMLHTTP'); } ajax.onreadystatechange = function() { @@ -4644,6 +4674,8 @@ modules['web-loaders'] = { }; })(); (function() { +'use strict'; + if(typeof window === 'undefined' || window !== this) { modules['loaders'] = modules["node-loaders"]; } @@ -4652,6 +4684,8 @@ else { } })(); (function() { +'use strict'; + var path = modules["path"]; var lib = modules["lib"]; var Obj = modules["object"]; @@ -4710,17 +4744,15 @@ var Environment = Obj.extend({ initCache: function() { // Caching and cache busting - var cache = {}; - lib.each(this.loaders, function(loader) { - if(typeof loader.on === 'function'){ + loader.cache = {}; + + if(typeof loader.on === 'function') { loader.on('update', function(template) { - cache[template] = null; + loader.cache[template] = null; }); } }); - - this.cache = cache; }, addExtension: function(name, extension) { @@ -4753,7 +4785,14 @@ var Environment = Obj.extend({ 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) { // this fixes autoescape for templates referenced in symbols name = name.raw; @@ -4774,7 +4813,11 @@ var Environment = Obj.extend({ throw new Error('template names must be a string: ' + name); } - 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; + } if(tmpl) { if(eagerCompile) { @@ -4793,6 +4836,7 @@ var Environment = Obj.extend({ lib.asyncIter(this.loaders, function(loader, i, next, done) { function handle(src) { if(src) { + src.loader = loader; done(src); } else { @@ -4801,10 +4845,7 @@ var Environment = Obj.extend({ } // Resolve name relative to parentName - if (parentName && (name.indexOf("./") == 0 || - name.indexOf("../") == 0)) { - name = loader.resolve(parentName, name); - } + name = that.resolveTemplate(loader, parentName, name); if(loader.async) { loader.getSource(name, function(err, src) { @@ -4830,7 +4871,7 @@ var Environment = Obj.extend({ info.path, eagerCompile); if(!info.noCache) { - this.cache[name] = tmpl; + info.loader.cache[name] = tmpl; } if(cb) { @@ -4955,7 +4996,7 @@ var Context = Obj.extend({ var blk = this.blocks[name][idx + 1]; var context = this; - if(idx == -1 || !blk) { + if(idx === -1 || !blk) { throw new Error('no super block available for "' + name + '"'); } @@ -4990,8 +5031,8 @@ var Template = Obj.extend({ this.tmplStr = src; } 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'); } this.path = path; @@ -5105,7 +5146,7 @@ var Template = Obj.extend({ var blocks = {}; for(var k in props) { - if(k.slice(0, 2) == 'b_') { + if(k.slice(0, 2) === 'b_') { blocks[k.slice(2)] = props[k]; } } diff --git a/browser/nunjucks.min.js b/browser/nunjucks.min.js index d55a6b9d..5934fbdd 100644 --- a/browser/nunjucks.min.js +++ b/browser/nunjucks.min.js @@ -1,5 +1,5 @@ -// Browser bundle of nunjucks 1.2.0 +// Browser bundle of nunjucks 1.3.0 -(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={"&":"&",'"':""","'":"'","<":"<",">":">"};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>>0;fromIndex=+fromIndex||0;if(Math.abs(fromIndex)===Infinity){fromIndex=0}if(fromIndex<0){fromIndex+=length;if(fromIndex<0){fromIndex=0}}for(;fromIndex0||!inline){for(var j=0;jargNames.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=","//","**"];var curComplex=cur+this.current();var type;if(lib.indexOf(complexOps,curComplex)!==-1){this.forward();cur=curComplex}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;default:type=TOKEN_OPERATOR}return token(type,cur,lineno,colno)}else{tok=this._extractUntil(whitespaceChars+delimChars);if(tok.match(/^[-+]?[0-9]+$/)){if(this.current()=="."){this.forward();var dec=this._extract(intChars);return token(TOKEN_FLOAT,tok+"."+dec,lineno,colno)}else{return token(TOKEN_INT,tok,lineno,colno)}}else if(tok.match(/^(true|false)$/)){return token(TOKEN_BOOLEAN,tok,lineno,colno)}else if(tok){return token(TOKEN_SYMBOL,tok,lineno,colno)}else{throw new Error("Unexpected value while parsing: "+tok)}}}else{var beginChars=this.tags.BLOCK_START.charAt(0)+this.tags.VARIABLE_START.charAt(0)+this.tags.COMMENT_START.charAt(0)+this.tags.COMMENT_END.charAt(0);if(this.is_finished()){return null}else if((tok=this._extractString(this.tags.BLOCK_START+"-"))||(tok=this._extractString(this.tags.BLOCK_START))){this.in_code=true;return token(TOKEN_BLOCK_START,tok,lineno,colno)}else if(tok=this._extractString(this.tags.VARIABLE_START)){this.in_code=true;return token(TOKEN_VARIABLE_START,tok,lineno,colno)}else{tok="";var data;var in_comment=false;if(this._matches(this.tags.COMMENT_START)){in_comment=true;tok=this._extractString(this.tags.COMMENT_START)}while((data=this._extractUntil(beginChars))!==null){tok+=data;if((this._matches(this.tags.BLOCK_START)||this._matches(this.tags.VARIABLE_START)||this._matches(this.tags.COMMENT_START))&&!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)){tok=tok.slice(0,-this.colno);if(!tok.length){return this.nextToken()}}}break}else if(this._matches(this.tags.COMMENT_END)){if(!in_comment){throw new Error("unexpected end of comment")}tok+=this._extractString(this.tags.COMMENT_END);break}else{tok+=this.current();this.forward()}}if(data===null&&in_comment){throw new Error("expected end of comment, got end of file")}return token(in_comment?TOKEN_COMMENT:TOKEN_DATA,tok,lineno,colno)}}throw new Error("Could not parse text")};Tokenizer.prototype.parseString=function(delimiter){this.forward();var lineno=this.lineno;var colno=this.colno;var str="";while(!this.is_finished()&&this.current()!=delimiter){var cur=this.current();if(cur=="\\"){this.forward();switch(this.current()){case"n":str+="\n";break;case"t":str+=" ";break;case"r":str+="\r";break;default:str+=this.current()}this.forward()}else{str+=cur;this.forward()}}this.forward();return str};Tokenizer.prototype._matches=function(str){if(this.index+str.length>this.len){return null}var m=this.str.slice(this.index,this.index+str.length);return m==str};Tokenizer.prototype._extractString=function(str){if(this._matches(str)){this.index+=str.length;return str}return null};Tokenizer.prototype._extractUntil=function(charString){return this._extractMatching(true,charString||"")};Tokenizer.prototype._extract=function(charString){return this._extractMatching(false,charString)};Tokenizer.prototype._extractMatching=function(breakOnMatch,charString){if(this.is_finished()){return null}var first=charString.indexOf(this.current());if(breakOnMatch&&first==-1||!breakOnMatch&&first!=-1){var t=this.current();this.forward();var idx=charString.indexOf(this.current());while((breakOnMatch&&idx==-1||!breakOnMatch&&idx!=-1)&&!this.is_finished()){t+=this.current();this.forward();idx=charString.indexOf(this.current())}return t}return""};Tokenizer.prototype.is_finished=function(){return this.index>=this.len};Tokenizer.prototype.forwardN=function(n){for(var i=0;i0&&!this.skip(lexer.TOKEN_COMMA)){this.fail("parseFrom: expected comma",fromTok.lineno,fromTok.colno)}var name=this.parsePrimary();if(name.value.charAt(0)=="_"){this.fail("parseFrom: names starting with an underscore "+"cannot be imported",name.lineno,name.colno)}if(this.skipSymbol("as")){var alias=this.parsePrimary();names.addChild(new nodes.Pair(name.lineno,name.colno,name,alias))}else{names.addChild(name)}withContext=this.parseWithContext()}return new nodes.FromImport(fromTok.lineno,fromTok.colno,template,names,withContext)},parseBlock:function(){var tag=this.peekToken();if(!this.skipSymbol("block")){this.fail("parseBlock: expected block",tag.lineno,tag.colno)}var node=new nodes.Block(tag.lineno,tag.colno);node.name=this.parsePrimary();if(!(node.name instanceof nodes.Symbol)){this.fail("parseBlock: variable name expected",tag.lineno,tag.colno)}this.advanceAfterBlockEnd(tag.value);node.body=this.parseUntilBlocks("endblock");if(!this.peekToken()){this.fail("parseBlock: expected endblock, got end of file")}this.advanceAfterBlockEnd();return node},parseTemplateRef:function(tagName,nodeType){var tag=this.peekToken();if(!this.skipSymbol(tagName)){this.fail("parseTemplateRef: expected "+tagName)}var node=new nodeType(tag.lineno,tag.colno);node.template=this.parseExpression();this.advanceAfterBlockEnd(tag.value);return node},parseExtends:function(){return this.parseTemplateRef("extends",nodes.Extends)},parseInclude:function(){return this.parseTemplateRef("include",nodes.Include)},parseIf:function(){var tag=this.peekToken();var node;if(this.skipSymbol("if")||this.skipSymbol("elif")){node=new nodes.If(tag.lineno,tag.colno)}else if(this.skipSymbol("ifAsync")){node=new nodes.IfAsync(tag.lineno,tag.colno)}else{this.fail("parseIf: expected if or elif",tag.lineno,tag.colno)}node.cond=this.parseExpression();this.advanceAfterBlockEnd(tag.value);node.body=this.parseUntilBlocks("elif","else","endif");var tok=this.peekToken();switch(tok&&tok.value){case"elif":node.else_=this.parseIf();break;case"else":this.advanceAfterBlockEnd();node.else_=this.parseUntilBlocks("endif");this.advanceAfterBlockEnd();break;case"endif":node.else_=null;this.advanceAfterBlockEnd();break;default:this.fail("parseIf: expected endif, else, or endif, "+"got end of file")}return node},parseSet:function(){var tag=this.peekToken();if(!this.skipSymbol("set")){this.fail("parseSet: expected set",tag.lineno,tag.colno)}var node=new nodes.Set(tag.lineno,tag.colno,[]);var target;while(target=this.parsePrimary()){node.targets.push(target);if(!this.skip(lexer.TOKEN_COMMA)){break}}if(!this.skipValue(lexer.TOKEN_OPERATOR,"=")){this.fail("parseSet: expected = in set tag",tag.lineno,tag.colno) -}node.value=this.parseExpression();this.advanceAfterBlockEnd(tag.value);return node},parseStatement:function(){var tok=this.peekToken();var node;if(tok.type!=lexer.TOKEN_SYMBOL){this.fail("tag name expected",tok.lineno,tok.colno)}if(this.breakOnBlocks&&lib.indexOf(this.breakOnBlocks,tok.value)!==-1){return null}switch(tok.value){case"raw":return this.parseRaw();case"if":case"ifAsync":return this.parseIf();case"for":case"asyncEach":case"asyncAll":return this.parseFor();case"block":return this.parseBlock();case"extends":return this.parseExtends();case"include":return this.parseInclude();case"set":return this.parseSet();case"macro":return this.parseMacro();case"call":return this.parseCall();case"import":return this.parseImport();case"from":return this.parseFrom();default:if(this.extensions.length){for(var i=0;i1){this.fail("invalid index")}node=new nodes.LookupVal(tok.lineno,tok.colno,node,lookup.children[0])}else if(tok.type==lexer.TOKEN_OPERATOR&&tok.value=="."){this.nextToken();var val=this.nextToken();if(val.type!=lexer.TOKEN_SYMBOL){this.fail("expected name as lookup value, got "+val.value,val.lineno,val.colno)}var lookup=new nodes.Literal(val.lineno,val.colno,val.value);node=new nodes.LookupVal(tok.lineno,tok.colno,node,lookup)}else{break}tok=this.peekToken()}return node},parseExpression:function(){var node=this.parseInlineIf();return node},parseInlineIf:function(){var node=this.parseOr();if(this.skipSymbol("if")){var cond_node=this.parseOr();var body_node=node;node=new nodes.InlineIf(node.lineno,node.colno);node.body=body_node;node.cond=cond_node;if(this.skipSymbol("else")){node.else_=this.parseOr()}else{node.else_=null}}return node},parseOr:function(){var node=this.parseAnd();while(this.skipSymbol("or")){var node2=this.parseAnd();node=new nodes.Or(node.lineno,node.colno,node,node2)}return node},parseAnd:function(){var node=this.parseNot();while(this.skipSymbol("and")){var node2=this.parseNot();node=new nodes.And(node.lineno,node.colno,node,node2)}return node},parseNot:function(){var tok=this.peekToken();if(this.skipSymbol("not")){return new nodes.Not(tok.lineno,tok.colno,this.parseNot())}return this.parseIn()},parseIn:function(){var node=this.parseCompare();while(1){var tok=this.nextToken();if(!tok){break}var invert=tok.type==lexer.TOKEN_SYMBOL&&tok.value=="not";if(!invert){this.pushToken(tok)}if(this.skipSymbol("in")){var node2=this.parseCompare();node=new nodes.In(node.lineno,node.colno,node,node2);if(invert){node=new nodes.Not(node.lineno,node.colno,node)}}else{if(invert){this.pushToken(tok)}break}}return node},parseCompare:function(){var compareOps=["==","!=","<",">","<=",">="];var expr=this.parseAdd();var ops=[];while(1){var tok=this.nextToken();if(!tok){break}else if(lib.indexOf(compareOps,tok.value)!==-1){ops.push(new nodes.CompareOperand(tok.lineno,tok.colno,this.parseAdd(),tok.value))}else{this.pushToken(tok);break}}if(ops.length){return new nodes.Compare(ops[0].lineno,ops[0].colno,expr,ops)}else{return expr}},parseAdd:function(){var node=this.parseSub();while(this.skipValue(lexer.TOKEN_OPERATOR,"+")){var node2=this.parseSub();node=new nodes.Add(node.lineno,node.colno,node,node2)}return node},parseSub:function(){var node=this.parseMul();while(this.skipValue(lexer.TOKEN_OPERATOR,"-")){var node2=this.parseMul();node=new nodes.Sub(node.lineno,node.colno,node,node2)}return node},parseMul:function(){var node=this.parseDiv();while(this.skipValue(lexer.TOKEN_OPERATOR,"*")){var node2=this.parseDiv();node=new nodes.Mul(node.lineno,node.colno,node,node2)}return node},parseDiv:function(){var node=this.parseFloorDiv();while(this.skipValue(lexer.TOKEN_OPERATOR,"/")){var node2=this.parseFloorDiv();node=new nodes.Div(node.lineno,node.colno,node,node2)}return node},parseFloorDiv:function(){var node=this.parseMod();while(this.skipValue(lexer.TOKEN_OPERATOR,"//")){var node2=this.parseMod();node=new nodes.FloorDiv(node.lineno,node.colno,node,node2)}return node},parseMod:function(){var node=this.parsePow();while(this.skipValue(lexer.TOKEN_OPERATOR,"%")){var node2=this.parsePow();node=new nodes.Mod(node.lineno,node.colno,node,node2)}return node},parsePow:function(){var node=this.parseUnary();while(this.skipValue(lexer.TOKEN_OPERATOR,"**")){var node2=this.parseUnary();node=new nodes.Pow(node.lineno,node.colno,node,node2)}return node},parseUnary:function(noFilters){var tok=this.peekToken();var node;if(this.skipValue(lexer.TOKEN_OPERATOR,"-")){node=new nodes.Neg(tok.lineno,tok.colno,this.parseUnary(true))}else if(this.skipValue(lexer.TOKEN_OPERATOR,"+")){node=new nodes.Pos(tok.lineno,tok.colno,this.parseUnary(true))}else{node=this.parsePrimary()}if(!noFilters){node=this.parseFilter(node)}return node},parsePrimary:function(noPostfix){var tok=this.nextToken();var val=null;var node=null;if(!tok){this.fail("expected expression, got end of file")}else if(tok.type==lexer.TOKEN_STRING){val=tok.value}else if(tok.type==lexer.TOKEN_INT){val=parseInt(tok.value,10)}else if(tok.type==lexer.TOKEN_FLOAT){val=parseFloat(tok.value)}else if(tok.type==lexer.TOKEN_BOOLEAN){if(tok.value=="true"){val=true}else if(tok.value=="false"){val=false}else{this.fail("invalid boolean: "+tok.value,tok.lineno,tok.colno)}}else if(tok.type==lexer.TOKEN_REGEX){val=new RegExp(tok.value.body,tok.value.flags)}if(val!==null){node=new nodes.Literal(tok.lineno,tok.colno,val)}else if(tok.type==lexer.TOKEN_SYMBOL){node=new nodes.Symbol(tok.lineno,tok.colno,tok.value);if(!noPostfix){node=this.parsePostfix(node)}}else{this.pushToken(tok);node=this.parseAggregate()}if(node){return node}else{this.fail("unexpected token: "+tok.value,tok.lineno,tok.colno)}},parseFilter:function(node){while(this.skip(lexer.TOKEN_PIPE)){var tok=this.expect(lexer.TOKEN_SYMBOL);var name=tok.value;while(this.skipValue(lexer.TOKEN_OPERATOR,".")){name+="."+this.expect(lexer.TOKEN_SYMBOL).value}node=new nodes.Filter(tok.lineno,tok.colno,new nodes.Symbol(tok.lineno,tok.colno,name),new nodes.NodeList(tok.lineno,tok.colno,[node]));if(this.peekToken().type==lexer.TOKEN_LEFT_PAREN){var call=this.parsePostfix(node);node.args.children=node.args.children.concat(call.args.children)}}return node},parseAggregate:function(){var tok=this.nextToken();var node;switch(tok.type){case lexer.TOKEN_LEFT_PAREN:node=new nodes.Group(tok.lineno,tok.colno);break;case lexer.TOKEN_LEFT_BRACKET:node=new nodes.Array(tok.lineno,tok.colno);break;case lexer.TOKEN_LEFT_CURLY:node=new nodes.Dict(tok.lineno,tok.colno);break;default:return null}while(1){var type=this.peekToken().type;if(type==lexer.TOKEN_RIGHT_PAREN||type==lexer.TOKEN_RIGHT_BRACKET||type==lexer.TOKEN_RIGHT_CURLY){this.nextToken();break}if(node.children.length>0){if(!this.skip(lexer.TOKEN_COMMA)){this.fail("parseAggregate: expected comma after expression",tok.lineno,tok.colno)}}if(node instanceof nodes.Dict){var key=this.parsePrimary();if(!this.skip(lexer.TOKEN_COLON)){this.fail("parseAggregate: expected colon after dict key",tok.lineno,tok.colno)}var value=this.parseExpression();node.addChild(new nodes.Pair(key.lineno,key.colno,key,value))}else{var expr=this.parseExpression();node.addChild(expr)}}return node},parseSignature:function(tolerant,noParens){var tok=this.peekToken();if(!noParens&&tok.type!=lexer.TOKEN_LEFT_PAREN){if(tolerant){return null}else{this.fail("expected arguments",tok.lineno,tok.colno)}}if(tok.type==lexer.TOKEN_LEFT_PAREN){tok=this.nextToken()}var args=new nodes.NodeList(tok.lineno,tok.colno);var kwargs=new nodes.KeywordArgs(tok.lineno,tok.colno);var kwnames=[];var checkComma=false;while(1){tok=this.peekToken();if(!noParens&&tok.type==lexer.TOKEN_RIGHT_PAREN){this.nextToken();break}else if(noParens&&tok.type==lexer.TOKEN_BLOCK_END){break}if(checkComma&&!this.skip(lexer.TOKEN_COMMA)){this.fail("parseSignature: expected comma after expression",tok.lineno,tok.colno)}else{var arg=this.parseExpression();if(this.skipValue(lexer.TOKEN_OPERATOR,"=")){kwargs.addChild(new nodes.Pair(arg.lineno,arg.colno,arg,this.parseExpression()))}else{args.addChild(arg)}}checkComma=true}if(kwargs.children.length){args.addChild(kwargs)}return args},parseUntilBlocks:function(){var prev=this.breakOnBlocks;this.breakOnBlocks=lib.toArray(arguments);var ret=this.parse();this.breakOnBlocks=prev;return ret},parseNodes:function(){var tok;var buf=[];while(tok=this.nextToken()){if(tok.type==lexer.TOKEN_DATA){var data=tok.value;var nextToken=this.peekToken();var nextVal=nextToken&&nextToken.value;if(this.dropLeadingWhitespace){data=data.replace(/^\s*/,"");this.dropLeadingWhitespace=false}if(nextToken&&nextToken.type==lexer.TOKEN_BLOCK_START&&nextVal.charAt(nextVal.length-1)=="-"){data=data.replace(/\s*$/,"")}buf.push(new nodes.Output(tok.lineno,tok.colno,[new nodes.TemplateData(tok.lineno,tok.colno,data)]))}else if(tok.type==lexer.TOKEN_BLOCK_START){var n=this.parseStatement();if(!n){break}buf.push(n)}else if(tok.type==lexer.TOKEN_VARIABLE_START){var e=this.parseExpression();this.advanceAfterVariableEnd();buf.push(new nodes.Output(tok.lineno,tok.colno,[e]))}else if(tok.type!=lexer.TOKEN_COMMENT){this.fail("Unexpected token at top-level: "+tok.type,tok.lineno,tok.colno)}}return buf},parse:function(){return new nodes.NodeList(0,0,this.parseNodes())},parseAsRoot:function(){return new nodes.Root(0,0,this.parseNodes())}});modules["parser"]={parse:function(src,extensions,opts){var p=new Parser(lexer.lex(src,opts));if(extensions!==undefined){p.extensions=extensions}return p.parseAsRoot()}}})();(function(){var nodes=modules["nodes"];var lib=modules["lib"];var sym=0;function gensym(){return"hole_"+sym++}function mapCOW(arr,func){var res=null;for(var i=0;i":">","<=":"<=",">=":">="};function binOpEmitter(str){return function(node,frame){this.compile(node.left,frame);this.emit(str);this.compile(node.right,frame)}}var Compiler=Object.extend({init:function(templateName){this.templateName=templateName;this.codebuf=[];this.lastId=0;this.buffer=null;this.bufferStack=[];this.isChild=false;this.scopeClosers=""},fail:function(msg,lineno,colno){if(lineno!==undefined)lineno+=1;if(colno!==undefined)colno+=1;throw new lib.TemplateError(msg,lineno,colno)},pushBufferId:function(id){this.bufferStack.push(this.buffer);this.buffer=id;this.emit("var "+this.buffer+' = "";')},popBufferId:function(){this.buffer=this.bufferStack.pop()},emit:function(code){this.codebuf.push(code)},emitLine:function(code){this.emit(code+"\n")},emitLines:function(){lib.each(lib.toArray(arguments),function(line){this.emitLine(line)},this)},emitFuncBegin:function(name){this.buffer="output";this.scopeClosers="";this.emitLine("function "+name+"(env, context, frame, runtime, cb) {");this.emitLine("var lineno = null;");this.emitLine("var colno = null;");this.emitLine("var "+this.buffer+' = "";');this.emitLine("try {")},emitFuncEnd:function(noReturn){if(!noReturn){this.emitLine("cb(null, "+this.buffer+");")}this.closeScopeLevels();this.emitLine("} catch (e) {");this.emitLine(" cb(runtime.handleError(e, lineno, colno));");this.emitLine("}");this.emitLine("}");this.buffer=null},addScopeLevel:function(){this.scopeClosers+="})"},closeScopeLevels:function(){this.emitLine(this.scopeClosers+";");this.scopeClosers=""},withScopedSyntax:function(func){var scopeClosers=this.scopeClosers;this.scopeClosers="";func.call(this);this.closeScopeLevels();this.scopeClosers=scopeClosers},makeCallback:function(res){var err=this.tmpid();return"function("+err+(res?","+res:"")+") {\n"+"if("+err+") { cb("+err+"); return; }"},tmpid:function(){this.lastId++;return"t_"+this.lastId},_bufferAppend:function(func){this.emit(this.buffer+" += runtime.suppressValue(");func.call(this);this.emit(", env.opts.autoescape);\n")},_compileChildren:function(node,frame){var children=node.children;for(var i=0,l=children.length;i0){this.emit(",")}this.compile(node.children[i],frame)}if(endChar){this.emit(endChar)}},_compileExpression:function(node,frame){this.assertType(node,nodes.Literal,nodes.Symbol,nodes.Group,nodes.Array,nodes.Dict,nodes.FunCall,nodes.Caller,nodes.Filter,nodes.LookupVal,nodes.Compare,nodes.InlineIf,nodes.In,nodes.And,nodes.Or,nodes.Not,nodes.Add,nodes.Sub,nodes.Mul,nodes.Div,nodes.FloorDiv,nodes.Mod,nodes.Pow,nodes.Neg,nodes.Pos,nodes.Compare,nodes.NodeList);this.compile(node,frame)},assertType:function(node){var types=lib.toArray(arguments).slice(1);var success=false;for(var i=0;i0){this.emit(",")}if(arg){var id=this.tmpid();this.emitLine("function(cb) {");this.emitLine("if(!cb) { cb = function(err) { if(err) { throw err; }}}");this.pushBufferId(id);this.withScopedSyntax(function(){this.compile(arg,frame);this.emitLine("cb(null, "+id+");")});this.popBufferId();this.emitLine("return "+id+";");this.emitLine("}")}else{this.emit("null")}},this)}if(async){var res=this.tmpid();this.emitLine(", "+this.makeCallback(res));this.emitLine(this.buffer+" += runtime.suppressValue("+res+", "+autoescape+" && env.opts.autoescape);");this.addScopeLevel()}else{this.emit(")");this.emit(", "+autoescape+" && env.opts.autoescape);\n")}},compileCallExtensionAsync:function(node,frame){this.compileCallExtension(node,frame,true)},compileNodeList:function(node,frame){this._compileChildren(node,frame)},compileLiteral:function(node,frame){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");this.emit('"'+val+'"')}else{this.emit(node.value.toString())}},compileSymbol:function(node,frame){var name=node.value;var v;if(v=frame.lookup(name)){this.emit(v)}else{this.emit("runtime.contextOrFrameLookup("+'context, frame, "'+name+'")')}},compileGroup:function(node,frame){this._compileAggregate(node,frame,"(",")")},compileArray:function(node,frame){this._compileAggregate(node,frame,"[","]")},compileDict:function(node,frame){this._compileAggregate(node,frame,"{","}")},compilePair:function(node,frame){var key=node.key;var val=node.value;if(key instanceof nodes.Symbol){key=new nodes.Literal(key.lineno,key.colno,key.value)}else if(!(key instanceof nodes.Literal&&typeof key.value=="string")){this.fail("compilePair: Dict keys must be strings or names",key.lineno,key.colno)}this.compile(key,frame);this.emit(": ");this._compileExpression(val,frame)},compileInlineIf:function(node,frame){this.emit("(");this.compile(node.cond,frame);this.emit("?");this.compile(node.body,frame);this.emit(":");if(node.else_!==null)this.compile(node.else_,frame);else this.emit('""');this.emit(")")},compileIn:function(node,frame){this.emit("(");this.compile(node.right,frame);this.emit(".indexOf(");this.compile(node.left,frame);this.emit(") !== -1)")},compileOr:binOpEmitter(" || "),compileAnd:binOpEmitter(" && "),compileAdd:binOpEmitter(" + "),compileSub:binOpEmitter(" - "),compileMul:binOpEmitter(" * "),compileDiv:binOpEmitter(" / "),compileMod:binOpEmitter(" % "),compileNot:function(node,frame){this.emit("!");this.compile(node.target,frame)},compileFloorDiv:function(node,frame){this.emit("Math.floor(");this.compile(node.left,frame);this.emit(" / ");this.compile(node.right,frame);this.emit(")")},compilePow:function(node,frame){this.emit("Math.pow(");this.compile(node.left,frame);this.emit(", ");this.compile(node.right,frame);this.emit(")")},compileNeg:function(node,frame){this.emit("-");this.compile(node.target,frame)},compilePos:function(node,frame){this.emit("+");this.compile(node.target,frame)},compileCompare:function(node,frame){this.compile(node.expr,frame);for(var i=0;i=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=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=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(xy){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"+possibleUrl.substr(0,length)+"";if(wwwRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";if(emailRE.test(possibleUrl))return''+possibleUrl+"";if(tldRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";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":">"};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>>0;fromIndex=+fromIndex||0;if(Math.abs(fromIndex)===Infinity){fromIndex=0}if(fromIndex<0){fromIndex+=length;if(fromIndex<0){fromIndex=0}}for(;fromIndex0||!inline){for(var j=0;jargNames.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=","//","**"];var curComplex=cur+this.current();var type;if(lib.indexOf(complexOps,curComplex)!==-1){this.forward();cur=curComplex}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;default:type=TOKEN_OPERATOR}return token(type,cur,lineno,colno)}else{tok=this._extractUntil(whitespaceChars+delimChars);if(tok.match(/^[-+]?[0-9]+$/)){if(this.current()==="."){this.forward();var dec=this._extract(intChars);return token(TOKEN_FLOAT,tok+"."+dec,lineno,colno)}else{return token(TOKEN_INT,tok,lineno,colno)}}else if(tok.match(/^(true|false)$/)){return token(TOKEN_BOOLEAN,tok,lineno,colno)}else if(tok){return token(TOKEN_SYMBOL,tok,lineno,colno)}else{throw new Error("Unexpected value while parsing: "+tok)}}}else{var beginChars=this.tags.BLOCK_START.charAt(0)+this.tags.VARIABLE_START.charAt(0)+this.tags.COMMENT_START.charAt(0)+this.tags.COMMENT_END.charAt(0);if(this.is_finished()){return null}else if((tok=this._extractString(this.tags.BLOCK_START+"-"))||(tok=this._extractString(this.tags.BLOCK_START))){this.in_code=true;return token(TOKEN_BLOCK_START,tok,lineno,colno)}else if(tok=this._extractString(this.tags.VARIABLE_START)){this.in_code=true;return token(TOKEN_VARIABLE_START,tok,lineno,colno)}else{tok="";var data;var in_comment=false;if(this._matches(this.tags.COMMENT_START)){in_comment=true;tok=this._extractString(this.tags.COMMENT_START)}while((data=this._extractUntil(beginChars))!==null){tok+=data;if((this._matches(this.tags.BLOCK_START)||this._matches(this.tags.VARIABLE_START)||this._matches(this.tags.COMMENT_START))&&!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)){tok=tok.slice(0,-this.colno);if(!tok.length){return this.nextToken()}}}break}else if(this._matches(this.tags.COMMENT_END)){if(!in_comment){throw new Error("unexpected end of comment")}tok+=this._extractString(this.tags.COMMENT_END);break}else{tok+=this.current();this.forward()}}if(data===null&&in_comment){throw new Error("expected end of comment, got end of file")}return token(in_comment?TOKEN_COMMENT:TOKEN_DATA,tok,lineno,colno)}}throw new Error("Could not parse text")};Tokenizer.prototype.parseString=function(delimiter){this.forward();var lineno=this.lineno;var colno=this.colno;var str="";while(!this.is_finished()&&this.current()!==delimiter){var cur=this.current();if(cur==="\\"){this.forward();switch(this.current()){case"n":str+="\n";break;case"t":str+=" ";break;case"r":str+="\r";break;default:str+=this.current()}this.forward()}else{str+=cur;this.forward()}}this.forward();return str};Tokenizer.prototype._matches=function(str){if(this.index+str.length>this.len){return null}var m=this.str.slice(this.index,this.index+str.length);return m===str};Tokenizer.prototype._extractString=function(str){if(this._matches(str)){this.index+=str.length;return str}return null};Tokenizer.prototype._extractUntil=function(charString){return this._extractMatching(true,charString||"")};Tokenizer.prototype._extract=function(charString){return this._extractMatching(false,charString)};Tokenizer.prototype._extractMatching=function(breakOnMatch,charString){if(this.is_finished()){return null}var first=charString.indexOf(this.current());if(breakOnMatch&&first===-1||!breakOnMatch&&first!==-1){var t=this.current();this.forward();var idx=charString.indexOf(this.current());while((breakOnMatch&&idx===-1||!breakOnMatch&&idx!==-1)&&!this.is_finished()){t+=this.current();this.forward();idx=charString.indexOf(this.current())}return t}return""};Tokenizer.prototype.is_finished=function(){return this.index>=this.len};Tokenizer.prototype.forwardN=function(n){for(var i=0;i0&&!this.skip(lexer.TOKEN_COMMA)){this.fail("parseFrom: expected comma",fromTok.lineno,fromTok.colno)}var name=this.parsePrimary();if(name.value.charAt(0)==="_"){this.fail("parseFrom: names starting with an underscore "+"cannot be imported",name.lineno,name.colno)}if(this.skipSymbol("as")){var alias=this.parsePrimary();names.addChild(new nodes.Pair(name.lineno,name.colno,name,alias))}else{names.addChild(name)}withContext=this.parseWithContext()}return new nodes.FromImport(fromTok.lineno,fromTok.colno,template,names,withContext)},parseBlock:function(){var tag=this.peekToken();if(!this.skipSymbol("block")){this.fail("parseBlock: expected block",tag.lineno,tag.colno)}var node=new nodes.Block(tag.lineno,tag.colno);node.name=this.parsePrimary();if(!(node.name instanceof nodes.Symbol)){this.fail("parseBlock: variable name expected",tag.lineno,tag.colno)}this.advanceAfterBlockEnd(tag.value);node.body=this.parseUntilBlocks("endblock");if(!this.peekToken()){this.fail("parseBlock: expected endblock, got end of file")}this.advanceAfterBlockEnd();return node},parseTemplateRef:function(tagName,nodeType){var tag=this.peekToken();if(!this.skipSymbol(tagName)){this.fail("parseTemplateRef: expected "+tagName)}var node=new nodeType(tag.lineno,tag.colno);node.template=this.parseExpression();this.advanceAfterBlockEnd(tag.value);return node},parseExtends:function(){return this.parseTemplateRef("extends",nodes.Extends)},parseInclude:function(){return this.parseTemplateRef("include",nodes.Include)},parseIf:function(){var tag=this.peekToken();var node;if(this.skipSymbol("if")||this.skipSymbol("elif")){node=new nodes.If(tag.lineno,tag.colno)}else if(this.skipSymbol("ifAsync")){node=new nodes.IfAsync(tag.lineno,tag.colno)}else{this.fail("parseIf: expected if or elif",tag.lineno,tag.colno)}node.cond=this.parseExpression();this.advanceAfterBlockEnd(tag.value);node.body=this.parseUntilBlocks("elif","else","endif");var tok=this.peekToken();switch(tok&&tok.value){case"elif":node.else_=this.parseIf();break;case"else":this.advanceAfterBlockEnd();node.else_=this.parseUntilBlocks("endif");this.advanceAfterBlockEnd();break;case"endif":node.else_=null;this.advanceAfterBlockEnd();break;default:this.fail("parseIf: expected endif, else, or endif, "+"got end of file")}return node},parseSet:function(){var tag=this.peekToken();if(!this.skipSymbol("set")){this.fail("parseSet: expected set",tag.lineno,tag.colno)}var node=new nodes.Set(tag.lineno,tag.colno,[]);var target; +while(target=this.parsePrimary()){node.targets.push(target);if(!this.skip(lexer.TOKEN_COMMA)){break}}if(!this.skipValue(lexer.TOKEN_OPERATOR,"=")){this.fail("parseSet: expected = in set tag",tag.lineno,tag.colno)}node.value=this.parseExpression();this.advanceAfterBlockEnd(tag.value);return node},parseStatement:function(){var tok=this.peekToken();var node;if(tok.type!==lexer.TOKEN_SYMBOL){this.fail("tag name expected",tok.lineno,tok.colno)}if(this.breakOnBlocks&&lib.indexOf(this.breakOnBlocks,tok.value)!==-1){return null}switch(tok.value){case"raw":return this.parseRaw();case"if":case"ifAsync":return this.parseIf();case"for":case"asyncEach":case"asyncAll":return this.parseFor();case"block":return this.parseBlock();case"extends":return this.parseExtends();case"include":return this.parseInclude();case"set":return this.parseSet();case"macro":return this.parseMacro();case"call":return this.parseCall();case"import":return this.parseImport();case"from":return this.parseFrom();default:if(this.extensions.length){for(var i=0;i1){this.fail("invalid index")}node=new nodes.LookupVal(tok.lineno,tok.colno,node,lookup.children[0])}else if(tok.type===lexer.TOKEN_OPERATOR&&tok.value==="."){this.nextToken();var val=this.nextToken();if(val.type!==lexer.TOKEN_SYMBOL){this.fail("expected name as lookup value, got "+val.value,val.lineno,val.colno)}var lookup=new nodes.Literal(val.lineno,val.colno,val.value);node=new nodes.LookupVal(tok.lineno,tok.colno,node,lookup)}else{break}tok=this.peekToken()}return node},parseExpression:function(){var node=this.parseInlineIf();return node},parseInlineIf:function(){var node=this.parseOr();if(this.skipSymbol("if")){var cond_node=this.parseOr();var body_node=node;node=new nodes.InlineIf(node.lineno,node.colno);node.body=body_node;node.cond=cond_node;if(this.skipSymbol("else")){node.else_=this.parseOr()}else{node.else_=null}}return node},parseOr:function(){var node=this.parseAnd();while(this.skipSymbol("or")){var node2=this.parseAnd();node=new nodes.Or(node.lineno,node.colno,node,node2)}return node},parseAnd:function(){var node=this.parseNot();while(this.skipSymbol("and")){var node2=this.parseNot();node=new nodes.And(node.lineno,node.colno,node,node2)}return node},parseNot:function(){var tok=this.peekToken();if(this.skipSymbol("not")){return new nodes.Not(tok.lineno,tok.colno,this.parseNot())}return this.parseIn()},parseIn:function(){var node=this.parseCompare();while(1){var tok=this.nextToken();if(!tok){break}var invert=tok.type===lexer.TOKEN_SYMBOL&&tok.value==="not";if(!invert){this.pushToken(tok)}if(this.skipSymbol("in")){var node2=this.parseCompare();node=new nodes.In(node.lineno,node.colno,node,node2);if(invert){node=new nodes.Not(node.lineno,node.colno,node)}}else{if(invert){this.pushToken(tok)}break}}return node},parseCompare:function(){var compareOps=["==","!=","<",">","<=",">="];var expr=this.parseAdd();var ops=[];while(1){var tok=this.nextToken();if(!tok){break}else if(lib.indexOf(compareOps,tok.value)!==-1){ops.push(new nodes.CompareOperand(tok.lineno,tok.colno,this.parseAdd(),tok.value))}else{this.pushToken(tok);break}}if(ops.length){return new nodes.Compare(ops[0].lineno,ops[0].colno,expr,ops)}else{return expr}},parseAdd:function(){var node=this.parseSub();while(this.skipValue(lexer.TOKEN_OPERATOR,"+")){var node2=this.parseSub();node=new nodes.Add(node.lineno,node.colno,node,node2)}return node},parseSub:function(){var node=this.parseMul();while(this.skipValue(lexer.TOKEN_OPERATOR,"-")){var node2=this.parseMul();node=new nodes.Sub(node.lineno,node.colno,node,node2)}return node},parseMul:function(){var node=this.parseDiv();while(this.skipValue(lexer.TOKEN_OPERATOR,"*")){var node2=this.parseDiv();node=new nodes.Mul(node.lineno,node.colno,node,node2)}return node},parseDiv:function(){var node=this.parseFloorDiv();while(this.skipValue(lexer.TOKEN_OPERATOR,"/")){var node2=this.parseFloorDiv();node=new nodes.Div(node.lineno,node.colno,node,node2)}return node},parseFloorDiv:function(){var node=this.parseMod();while(this.skipValue(lexer.TOKEN_OPERATOR,"//")){var node2=this.parseMod();node=new nodes.FloorDiv(node.lineno,node.colno,node,node2)}return node},parseMod:function(){var node=this.parsePow();while(this.skipValue(lexer.TOKEN_OPERATOR,"%")){var node2=this.parsePow();node=new nodes.Mod(node.lineno,node.colno,node,node2)}return node},parsePow:function(){var node=this.parseUnary();while(this.skipValue(lexer.TOKEN_OPERATOR,"**")){var node2=this.parseUnary();node=new nodes.Pow(node.lineno,node.colno,node,node2)}return node},parseUnary:function(noFilters){var tok=this.peekToken();var node;if(this.skipValue(lexer.TOKEN_OPERATOR,"-")){node=new nodes.Neg(tok.lineno,tok.colno,this.parseUnary(true))}else if(this.skipValue(lexer.TOKEN_OPERATOR,"+")){node=new nodes.Pos(tok.lineno,tok.colno,this.parseUnary(true))}else{node=this.parsePrimary()}if(!noFilters){node=this.parseFilter(node)}return node},parsePrimary:function(noPostfix){var tok=this.nextToken();var val=null;var node=null;if(!tok){this.fail("expected expression, got end of file")}else if(tok.type===lexer.TOKEN_STRING){val=tok.value}else if(tok.type===lexer.TOKEN_INT){val=parseInt(tok.value,10)}else if(tok.type===lexer.TOKEN_FLOAT){val=parseFloat(tok.value)}else if(tok.type===lexer.TOKEN_BOOLEAN){if(tok.value==="true"){val=true}else if(tok.value==="false"){val=false}else{this.fail("invalid boolean: "+tok.value,tok.lineno,tok.colno)}}else if(tok.type===lexer.TOKEN_REGEX){val=new RegExp(tok.value.body,tok.value.flags)}if(val!==null){node=new nodes.Literal(tok.lineno,tok.colno,val)}else if(tok.type===lexer.TOKEN_SYMBOL){node=new nodes.Symbol(tok.lineno,tok.colno,tok.value);if(!noPostfix){node=this.parsePostfix(node)}}else{this.pushToken(tok);node=this.parseAggregate()}if(node){return node}else{this.fail("unexpected token: "+tok.value,tok.lineno,tok.colno)}},parseFilter:function(node){while(this.skip(lexer.TOKEN_PIPE)){var tok=this.expect(lexer.TOKEN_SYMBOL);var name=tok.value;while(this.skipValue(lexer.TOKEN_OPERATOR,".")){name+="."+this.expect(lexer.TOKEN_SYMBOL).value}node=new nodes.Filter(tok.lineno,tok.colno,new nodes.Symbol(tok.lineno,tok.colno,name),new nodes.NodeList(tok.lineno,tok.colno,[node]));if(this.peekToken().type===lexer.TOKEN_LEFT_PAREN){var call=this.parsePostfix(node);node.args.children=node.args.children.concat(call.args.children)}}return node},parseAggregate:function(){var tok=this.nextToken();var node;switch(tok.type){case lexer.TOKEN_LEFT_PAREN:node=new nodes.Group(tok.lineno,tok.colno);break;case lexer.TOKEN_LEFT_BRACKET:node=new nodes.Array(tok.lineno,tok.colno);break;case lexer.TOKEN_LEFT_CURLY:node=new nodes.Dict(tok.lineno,tok.colno);break;default:return null}while(1){var type=this.peekToken().type;if(type===lexer.TOKEN_RIGHT_PAREN||type===lexer.TOKEN_RIGHT_BRACKET||type===lexer.TOKEN_RIGHT_CURLY){this.nextToken();break}if(node.children.length>0){if(!this.skip(lexer.TOKEN_COMMA)){this.fail("parseAggregate: expected comma after expression",tok.lineno,tok.colno)}}if(node instanceof nodes.Dict){var key=this.parsePrimary();if(!this.skip(lexer.TOKEN_COLON)){this.fail("parseAggregate: expected colon after dict key",tok.lineno,tok.colno)}var value=this.parseExpression();node.addChild(new nodes.Pair(key.lineno,key.colno,key,value))}else{var expr=this.parseExpression();node.addChild(expr)}}return node},parseSignature:function(tolerant,noParens){var tok=this.peekToken();if(!noParens&&tok.type!==lexer.TOKEN_LEFT_PAREN){if(tolerant){return null}else{this.fail("expected arguments",tok.lineno,tok.colno)}}if(tok.type===lexer.TOKEN_LEFT_PAREN){tok=this.nextToken()}var args=new nodes.NodeList(tok.lineno,tok.colno);var kwargs=new nodes.KeywordArgs(tok.lineno,tok.colno);var kwnames=[];var checkComma=false;while(1){tok=this.peekToken();if(!noParens&&tok.type===lexer.TOKEN_RIGHT_PAREN){this.nextToken();break}else if(noParens&&tok.type===lexer.TOKEN_BLOCK_END){break}if(checkComma&&!this.skip(lexer.TOKEN_COMMA)){this.fail("parseSignature: expected comma after expression",tok.lineno,tok.colno)}else{var arg=this.parseExpression();if(this.skipValue(lexer.TOKEN_OPERATOR,"=")){kwargs.addChild(new nodes.Pair(arg.lineno,arg.colno,arg,this.parseExpression()))}else{args.addChild(arg)}}checkComma=true}if(kwargs.children.length){args.addChild(kwargs)}return args},parseUntilBlocks:function(){var prev=this.breakOnBlocks;this.breakOnBlocks=lib.toArray(arguments);var ret=this.parse();this.breakOnBlocks=prev;return ret},parseNodes:function(){var tok;var buf=[];while(tok=this.nextToken()){if(tok.type===lexer.TOKEN_DATA){var data=tok.value;var nextToken=this.peekToken();var nextVal=nextToken&&nextToken.value;if(this.dropLeadingWhitespace){data=data.replace(/^\s*/,"");this.dropLeadingWhitespace=false}if(nextToken&&nextToken.type===lexer.TOKEN_BLOCK_START&&nextVal.charAt(nextVal.length-1)==="-"){data=data.replace(/\s*$/,"")}buf.push(new nodes.Output(tok.lineno,tok.colno,[new nodes.TemplateData(tok.lineno,tok.colno,data)]))}else if(tok.type===lexer.TOKEN_BLOCK_START){var n=this.parseStatement();if(!n){break}buf.push(n)}else if(tok.type===lexer.TOKEN_VARIABLE_START){var e=this.parseExpression();this.advanceAfterVariableEnd();buf.push(new nodes.Output(tok.lineno,tok.colno,[e]))}else if(tok.type!==lexer.TOKEN_COMMENT){this.fail("Unexpected token at top-level: "+tok.type,tok.lineno,tok.colno)}}return buf},parse:function(){return new nodes.NodeList(0,0,this.parseNodes())},parseAsRoot:function(){return new nodes.Root(0,0,this.parseNodes())}});modules["parser"]={parse:function(src,extensions,opts){var p=new Parser(lexer.lex(src,opts));if(extensions!==undefined){p.extensions=extensions}return p.parseAsRoot()}}})();(function(){"use strict";var nodes=modules["nodes"];var lib=modules["lib"];var sym=0;function gensym(){return"hole_"+sym++}function mapCOW(arr,func){var res=null;for(var i=0;i":">","<=":"<=",">=":">="};function binOpEmitter(str){return function(node,frame){this.compile(node.left,frame);this.emit(str);this.compile(node.right,frame)}}var Compiler=Object.extend({init:function(templateName){this.templateName=templateName;this.codebuf=[];this.lastId=0;this.buffer=null;this.bufferStack=[];this.isChild=false;this.scopeClosers=""},fail:function(msg,lineno,colno){if(lineno!==undefined)lineno+=1;if(colno!==undefined)colno+=1;throw new lib.TemplateError(msg,lineno,colno)},pushBufferId:function(id){this.bufferStack.push(this.buffer);this.buffer=id;this.emit("var "+this.buffer+' = "";')},popBufferId:function(){this.buffer=this.bufferStack.pop()},emit:function(code){this.codebuf.push(code)},emitLine:function(code){this.emit(code+"\n")},emitLines:function(){lib.each(lib.toArray(arguments),function(line){this.emitLine(line)},this)},emitFuncBegin:function(name){this.buffer="output";this.scopeClosers="";this.emitLine("function "+name+"(env, context, frame, runtime, cb) {");this.emitLine("var lineno = null;");this.emitLine("var colno = null;");this.emitLine("var "+this.buffer+' = "";');this.emitLine("try {")},emitFuncEnd:function(noReturn){if(!noReturn){this.emitLine("cb(null, "+this.buffer+");")}this.closeScopeLevels();this.emitLine("} catch (e) {");this.emitLine(" cb(runtime.handleError(e, lineno, colno));");this.emitLine("}");this.emitLine("}");this.buffer=null},addScopeLevel:function(){this.scopeClosers+="})"},closeScopeLevels:function(){this.emitLine(this.scopeClosers+";");this.scopeClosers=""},withScopedSyntax:function(func){var scopeClosers=this.scopeClosers;this.scopeClosers="";func.call(this);this.closeScopeLevels();this.scopeClosers=scopeClosers},makeCallback:function(res){var err=this.tmpid();return"function("+err+(res?","+res:"")+") {\n"+"if("+err+") { cb("+err+"); return; }"},tmpid:function(){this.lastId++;return"t_"+this.lastId},_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.opts.autoescape);\n")},_compileChildren:function(node,frame){var children=node.children;for(var i=0,l=children.length;i0){this.emit(",")}this.compile(node.children[i],frame)}if(endChar){this.emit(endChar)}},_compileExpression:function(node,frame){this.assertType(node,nodes.Literal,nodes.Symbol,nodes.Group,nodes.Array,nodes.Dict,nodes.FunCall,nodes.Caller,nodes.Filter,nodes.LookupVal,nodes.Compare,nodes.InlineIf,nodes.In,nodes.And,nodes.Or,nodes.Not,nodes.Add,nodes.Sub,nodes.Mul,nodes.Div,nodes.FloorDiv,nodes.Mod,nodes.Pow,nodes.Neg,nodes.Pos,nodes.Compare,nodes.NodeList);this.compile(node,frame)},assertType:function(node){var types=lib.toArray(arguments).slice(1);var success=false;for(var i=0;i0){this.emit(",")}if(arg){var id=this.tmpid();this.emitLine("function(cb) {");this.emitLine("if(!cb) { cb = function(err) { if(err) { throw err; }}}");this.pushBufferId(id);this.withScopedSyntax(function(){this.compile(arg,frame);this.emitLine("cb(null, "+id+");")});this.popBufferId();this.emitLine("return "+id+";");this.emitLine("}")}else{this.emit("null")}},this)}if(async){var res=this.tmpid();this.emitLine(", "+this.makeCallback(res));this.emitLine(this.buffer+" += runtime.suppressValue("+res+", "+autoescape+" && env.opts.autoescape);");this.addScopeLevel()}else{this.emit(")");this.emit(", "+autoescape+" && env.opts.autoescape);\n")}},compileCallExtensionAsync:function(node,frame){this.compileCallExtension(node,frame,true)},compileNodeList:function(node,frame){this._compileChildren(node,frame)},compileLiteral:function(node,frame){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");this.emit('"'+val+'"')}else{this.emit(node.value.toString())}},compileSymbol:function(node,frame){var name=node.value;var v;if(v=frame.lookup(name)){this.emit(v)}else{this.emit("runtime.contextOrFrameLookup("+'context, frame, "'+name+'")')}},compileGroup:function(node,frame){this._compileAggregate(node,frame,"(",")")},compileArray:function(node,frame){this._compileAggregate(node,frame,"[","]")},compileDict:function(node,frame){this._compileAggregate(node,frame,"{","}")},compilePair:function(node,frame){var key=node.key;var val=node.value;if(key instanceof nodes.Symbol){key=new nodes.Literal(key.lineno,key.colno,key.value)}else if(!(key instanceof nodes.Literal&&typeof key.value==="string")){this.fail("compilePair: Dict keys must be strings or names",key.lineno,key.colno)}this.compile(key,frame);this.emit(": ");this._compileExpression(val,frame)},compileInlineIf:function(node,frame){this.emit("(");this.compile(node.cond,frame);this.emit("?");this.compile(node.body,frame);this.emit(":");if(node.else_!==null)this.compile(node.else_,frame);else this.emit('""');this.emit(")")},compileIn:function(node,frame){this.emit("(");this.compile(node.right,frame);this.emit(".indexOf(");this.compile(node.left,frame);this.emit(") !== -1)")},compileOr:binOpEmitter(" || "),compileAnd:binOpEmitter(" && "),compileAdd:binOpEmitter(" + "),compileSub:binOpEmitter(" - "),compileMul:binOpEmitter(" * "),compileDiv:binOpEmitter(" / "),compileMod:binOpEmitter(" % "),compileNot:function(node,frame){this.emit("!");this.compile(node.target,frame)},compileFloorDiv:function(node,frame){this.emit("Math.floor(");this.compile(node.left,frame);this.emit(" / ");this.compile(node.right,frame);this.emit(")")},compilePow:function(node,frame){this.emit("Math.pow(");this.compile(node.left,frame);this.emit(", ");this.compile(node.right,frame);this.emit(")")},compileNeg:function(node,frame){this.emit("-");this.compile(node.target,frame)},compilePos:function(node,frame){this.emit("+");this.compile(node.target,frame)},compileCompare:function(node,frame){this.compile(node.expr,frame);for(var i=0;i=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=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=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(xy){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"+possibleUrl.substr(0,length)+"";if(wwwRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";if(emailRE.test(possibleUrl))return''+possibleUrl+"";if(tldRE.test(possibleUrl))return'"+possibleUrl.substr(0,length)+"";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", "dependencies": { "optimist": "*",