Permalink
Browse files

bump to 0.1.10

  • Loading branch information...
1 parent 0fc9622 commit acd1a7b49e0547ab86bb7e5596fd89f53974288f @jlongster committed Aug 9, 2013
Showing with 168 additions and 50 deletions.
  1. +11 −0 CHANGELOG.md
  2. +94 −35 browser/nunjucks-dev.js
  3. +1 −1 browser/nunjucks-min.js
  4. +61 −13 browser/nunjucks.js
  5. +1 −1 package.json
View
11 CHANGELOG.md
@@ -1,5 +1,16 @@
Changelog for versions previous to v0.1.9 are located at http://nunjucks.tumblr.com/.
+# v0.1.10 (August 9, 2013)
+
+This is a minor version update that includes several bugfixes.
+
+* fix hang when parsing an unclosed string that hits the end of file (fixes #85)
+* Adds IE8 support
+* `super()` calls are marked safe by default if using autoescaping
+* exposed a `markSafe` function in the runtime module for marking strings as safe inside filters
+* iterating over any "falsey" values will output nothing
+* make "this" be the context object in filters (fixes #109)
+
# v0.1.9 (May 31, 2013)
* autoescaping ([docs](http://nunjucks.jlongster.com/api#Autoescaping))
View
129 browser/nunjucks-dev.js
@@ -5,7 +5,11 @@ var modules = {};
// A simple class system, more documentation to come
function extend(cls, name, props) {
- var prototype = Object.create(cls.prototype);
+ // This does that same thing as Object.create, but with support for IE8
+ var F = function() {};
+ F.prototype = cls.prototype;
+ var prototype = new F();
+
var fnTest = /xyz/.test(function(){ xyz; }) ? /\bparent\b/ : /.*/;
props = props || {};
@@ -247,6 +251,38 @@ exports.map = function(obj, func) {
return results;
};
+
+if(!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function(array, searchElement /*, fromIndex */) {
+ if (array == null) {
+ throw new TypeError();
+ }
+ var t = Object(array);
+ var len = t.length >>> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 2) {
+ n = Number(arguments[2]);
+ if (n != n) { // shortcut for verifying if it's NaN
+ n = 0;
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ };
+}
})();
(function() {
var util = modules["util"];
@@ -677,7 +713,7 @@ function SafeString(val) {
];
for(var i=0; i<methods.length; i++) {
- this[methods[i]] = proxyStr(val[methods[i]]);
+ this[methods[i]] = markSafe(val[methods[i]]);
}
}
@@ -688,15 +724,26 @@ function copySafeness(dest, target) {
return target.toString();
}
-function proxyStr(func) {
- return function() {
- var ret = func.apply(this, arguments);
+function markSafe(val) {
+ var type = typeof val;
- if(typeof ret == 'string') {
- return new SafeString(ret);
- }
- return ret;
- };
+ if(type === 'string') {
+ return new SafeString(val);
+ }
+ else if(type !== 'function') {
+ return val;
+ }
+ else {
+ return function() {
+ var ret = val.apply(this, arguments);
+
+ if(typeof ret === 'string') {
+ return new SafeString(ret);
+ }
+
+ return ret;
+ };
+ }
}
function suppressValue(val, autoescape) {
@@ -760,10 +807,12 @@ modules['runtime'] = {
handleError: handleError,
isArray: lib.isArray,
SafeString: SafeString,
- copySafeness: copySafeness
+ copySafeness: copySafeness,
+ markSafe: markSafe
};
})();
(function() {
+var lib = modules["lib"];
var whitespaceChars = " \n\t\r";
var delimChars = "()[]{}%*-+/#,:|.<>=!";
@@ -863,7 +912,7 @@ Tokenizer.prototype.nextToken = function() {
var curComplex = cur + this.current();
var type;
- if(complexOps.indexOf(curComplex) != -1) {
+ if(complexOps.indexOf(curComplex) !== -1) {
this.forward();
cur = curComplex;
}
@@ -913,10 +962,10 @@ Tokenizer.prototype.nextToken = function() {
// Parse out the template text, breaking on tag
// delimiters because we need to look for block/variable start
// tags (don't use the full delimChars for optimization)
- var beginChars = (BLOCK_START[0] +
- VARIABLE_START[0] +
- COMMENT_START[0] +
- COMMENT_END[0]);
+ var beginChars = (BLOCK_START.charAt(0) +
+ VARIABLE_START.charAt(0) +
+ COMMENT_START.charAt(0) +
+ COMMENT_END.charAt(0));
var tok;
if(this.is_finished()) {
@@ -1130,13 +1179,13 @@ Tokenizer.prototype.back = function() {
Tokenizer.prototype.current = function() {
if(!this.is_finished()) {
- return this.str[this.index];
+ return this.str.charAt(this.index);
}
return "";
};
Tokenizer.prototype.previous = function() {
- return this.str[this.index-1];
+ return this.str.charAt(this.index-1);
};
modules['lexer'] = {
@@ -1594,7 +1643,7 @@ var Parser = Object.extend({
}
if(this.breakOnBlocks &&
- this.breakOnBlocks.indexOf(tok.value) != -1) {
+ this.breakOnBlocks.indexOf(tok.value) !== -1) {
return null;
}
@@ -1613,7 +1662,7 @@ var Parser = Object.extend({
if (this.extensions.length) {
for (var i = 0; i < this.extensions.length; i++) {
var ext = this.extensions[i];
- if ((ext.tags || []).indexOf(tok.value) > -1) {
+ if ((ext.tags || []).indexOf(tok.value) !== -1) {
return ext.parse(this, nodes, lexer);
}
}
@@ -1801,7 +1850,7 @@ var Parser = Object.extend({
if(!tok) {
break;
}
- else if(compareOps.indexOf(tok.value) != -1) {
+ else if(compareOps.indexOf(tok.value) !== -1) {
ops.push(new nodes.CompareOperand(tok.lineno,
tok.colno,
this.parseAdd(),
@@ -2372,7 +2421,9 @@ var Compiler = Object.extend({
},
_compileAggregate: function(node, frame, startChar, endChar) {
- this.emit(startChar);
+ if(startChar) {
+ this.emit(startChar);
+ }
for(var i=0; i<node.children.length; i++) {
if(i > 0) {
@@ -2382,7 +2433,9 @@ var Compiler = Object.extend({
this.compile(node.children[i], frame);
}
- this.emit(endChar);
+ if(endChar) {
+ this.emit(endChar);
+ }
},
_compileExpression: function(node, frame) {
@@ -2460,7 +2513,7 @@ var Compiler = Object.extend({
// object as the last argument, if they exist.
this._compileExpression(arg, frame);
- if(i != args.children.length || contentArgs) {
+ if(i != args.children.length - 1 || contentArgs) {
this.emit(',');
}
}, this);
@@ -2665,8 +2718,9 @@ var Compiler = Object.extend({
var name = node.name;
this.assertType(name, nodes.Symbol);
- this.emit('env.getFilter("' + name.value + '")');
- this._compileAggregate(node.args, frame, '(', ')');
+ this.emit('env.getFilter("' + name.value + '").call(context, ');
+ this._compileAggregate(node.args, frame);
+ this.emit(')');
},
compileKeywordArgs: function(node, frame) {
@@ -2761,7 +2815,7 @@ var Compiler = Object.extend({
});
});
- this.emit('if(' + arr + ' !== undefined) {');
+ this.emit('if(' + arr + ') {');
if(node.name instanceof nodes.Array) {
// key/value iteration. the user could have passed a dict
@@ -3114,11 +3168,12 @@ var Compiler = Object.extend({
var name = block.name.value;
this.emitFuncBegin('b_' + name);
- this.emitLine('var l_super = context.getSuper(env, ' +
+ this.emitLine('var l_super = runtime.markSafe(' +
+ 'context.getSuper(env, ' +
'"' + name + '", ' +
'b_' + name + ', ' +
'frame, ' +
- 'runtime);');
+ 'runtime));');
var tmpFrame = new Frame();
tmpFrame.set('super', 'l_super');
@@ -3155,7 +3210,7 @@ var Compiler = Object.extend({
// var fs = modules["fs"];
//var src = '{{ foo({a:1}) }} {% block content %}foo{% endblock %}';
// var c = new Compiler();
-// var src = '{% extends "b.html" %}{% block block1 %}{% block nested %}BAR{% endblock %}{% endblock %}';
+// var src = '{{ foo | poop(1, 2, 3) }}';
//var extensions = [new testExtension()];
// var ns = parser.parse(src);
@@ -3223,7 +3278,7 @@ var filters = {
capitalize: function(str) {
var ret = str.toLowerCase();
- return r.copySafeness(str, ret[0].toUpperCase() + ret.slice(1));
+ return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
},
center: function(str, width) {
@@ -3292,7 +3347,7 @@ var filters = {
},
safe: function(str) {
- return new r.SafeString(str);
+ return r.markSafe(str);
},
first: function(arr) {
@@ -3630,8 +3685,11 @@ var Object = modules["object"];
var HttpLoader = Object.extend({
init: function(baseURL, neverUpdate) {
- console.log("[nunjucks] Warning: only use HttpLoader in " +
- "development. Otherwise precompile your templates.");
+ if (typeof(console) !== "undefined" && console.log &&
+ typeof(nunjucks) == "object" && !nunjucks.testing) {
+ console.log("[nunjucks] Warning: only use HttpLoader in " +
+ "development. Otherwise precompile your templates.");
+ }
this.baseURL = baseURL || '';
this.neverUpdate = neverUpdate;
},
@@ -3660,7 +3718,8 @@ var HttpLoader = Object.extend({
}
};
- url += (url.indexOf('?') === -1 ? '?' : '&') + 's=' + Date.now();
+ url += (url.indexOf('?') === -1 ? '?' : '&') + 's=' +
+ (new Date().getTime());
// Synchronous because this API shouldn't be used in
// production (pre-load compiled templates instead)
View
2 browser/nunjucks-min.js
@@ -1 +1 @@
-(function(){var modules={};(function(){function extend(cls,name,props){var prototype=Object.create(cls.prototype);var fnTest=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;props=props||{};for(var k in props){var src=props[k];var parent=prototype[k];if(typeof parent=="function"&&typeof src=="function"&&fnTest.test(src)){prototype[k]=function(src,parent){return function(){var tmp=this.parent;this.parent=parent;var res=src.apply(this,arguments);this.parent=tmp;return res}}(src,parent)}else{prototype[k]=src}}prototype.typename=name;var new_cls=function(){if(prototype.init){prototype.init.apply(this,arguments)}};new_cls.prototype=prototype;new_cls.prototype.constructor=new_cls;new_cls.extend=function(name,props){if(typeof name=="object"){props=name;name="anonymous"}return extend(new_cls,name,props)};return new_cls}modules["object"]=extend(Object,"Object",{})})();(function(){var ArrayProto=Array.prototype;var ObjProto=Object.prototype;var escapeMap={"&":"&amp;",'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;"};var 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(/[&"'<>]/g,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 obj===Object(obj)};exports.groupBy=function(obj,val){var result={};var iterator=exports.isFunction(val)?val:function(obj){return obj[val]};for(var i=0;i<obj.length;i++){var value=obj[i];var key=iterator(value,i);(result[key]||(result[key]=[])).push(value)}return result};exports.toArray=function(obj){return Array.prototype.slice.call(obj)};exports.without=function(array){var result=[];if(!array){return result}var index=-1,length=array.length,contains=exports.toArray(arguments).slice(1);while(++index<length){if(contains.indexOf(array[index])===-1){result.push(array[index])}}return result};exports.extend=function(obj,obj2){for(var k in obj2){obj[k]=obj2[k]}return obj};exports.repeat=function(char_,n){var str="";for(var i=0;i<n;i++){str+=char_}return str};exports.each=function(obj,func,context){if(obj==null){return}if(ArrayProto.each&&obj.each==ArrayProto.each){obj.forEach(func,context)}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i<l;i++){func.call(context,obj[i],i,obj)}}};exports.map=function(obj,func){var results=[];if(obj==null){return results}if(ArrayProto.map&&obj.map===ArrayProto.map){return obj.map(func)}for(var i=0;i<obj.length;i++){results[results.length]=func(obj[i],i)}if(obj.length===+obj.length){results.length=obj.length}return results}})();(function(){var lib=modules["lib"];var Object=modules["object"];var Frame=Object.extend({init:function(parent){this.variables={};this.parent=parent},set:function(name,val){var parts=name.split(".");var obj=this.variables;for(var i=0;i<parts.length-1;i++){var id=parts[i];if(!obj[id]){obj[id]={}}obj=obj[id]}obj[parts[parts.length-1]]=val},get:function(name){var val=this.variables[name];if(val!==undefined&&val!==null){return val}return null},lookup:function(name){var p=this.parent;var val=this.variables[name];if(val!==undefined&&val!==null){return val}return p&&p.lookup(name)},push:function(){return new Frame(this)},pop:function(){return this.parent}});function makeMacro(argNames,kwargNames,func){return function(){var argCount=numArgs(arguments);var args;var kwargs=getKeywordArgs(arguments);if(argCount>argNames.length){args=Array.prototype.slice.call(arguments,0,argNames.length);var vals=Array.prototype.slice.call(arguments,args.length,argCount);for(var i=0;i<vals.length;i++){if(i<kwargNames.length){kwargs[kwargNames[i]]=vals[i]}}args.push(kwargs)}else if(argCount<argNames.length){args=Array.prototype.slice.call(arguments,0,argCount);for(var i=argCount;i<argNames.length;i++){var arg=argNames[i];args.push(kwargs[arg]);delete kwargs[arg]}args.push(kwargs)}else{args=arguments}return func.apply(this,args)}}function makeKeywordArgs(obj){obj.__keywords=true;return obj}function getKeywordArgs(args){var len=args.length;if(len){var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return lastArg}}return{}}function numArgs(args){var len=args.length;if(len===0){return 0}var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return len-1}else{return len}}function SafeString(val){if(typeof val!="string"){return val}this.toString=function(){return val};this.length=val.length;var methods=["charAt","charCodeAt","concat","contains","endsWith","fromCharCode","indexOf","lastIndexOf","length","localeCompare","match","quote","replace","search","slice","split","startsWith","substr","substring","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toUpperCase","trim","trimLeft","trimRight"];for(var i=0;i<methods.length;i++){this[methods[i]]=proxyStr(val[methods[i]])}}function copySafeness(dest,target){if(dest instanceof SafeString){return new SafeString(target)}return target.toString()}function proxyStr(func){return function(){var ret=func.apply(this,arguments);if(typeof ret=="string"){return new SafeString(ret)}return ret}}function suppressValue(val,autoescape){val=val!==undefined&&val!==null?val:"";if(autoescape&&typeof val==="string"){val=lib.escape(val)}return val}function memberLookup(obj,val){obj=obj||{};if(typeof obj[val]==="function"){return function(){return obj[val].apply(obj,arguments)}}return obj[val]}function callWrap(obj,name,args){if(!obj){throw new Error("Unable to call `"+name+"`, which is undefined or falsey")}else if(typeof obj!=="function"){throw new Error("Unable to call `"+name+"`, which is not a function")}return obj.apply(this,args)}function contextOrFrameLookup(context,frame,name){var val=context.lookup(name);return val!==undefined&&val!==null?val:frame.lookup(name)}function handleError(error,lineno,colno){if(error.lineno){throw error}else{throw new lib.TemplateError(error,lineno,colno)}}modules["runtime"]={Frame:Frame,makeMacro:makeMacro,makeKeywordArgs:makeKeywordArgs,numArgs:numArgs,suppressValue:suppressValue,memberLookup:memberLookup,contextOrFrameLookup:contextOrFrameLookup,callWrap:callWrap,handleError:handleError,isArray:lib.isArray,SafeString:SafeString,copySafeness:copySafeness}})();(function(){var lib=modules["lib"];var r=modules["runtime"];var filters={abs:function(n){return Math.abs(n)},batch:function(arr,linecount,fill_with){var res=[];var tmp=[];for(var i=0;i<arr.length;i++){if(i%linecount===0&&tmp.length){res.push(tmp);tmp=[]}tmp.push(arr[i])}if(tmp.length){if(fill_with){for(var i=tmp.length;i<linecount;i++){tmp.push(fill_with)}}res.push(tmp)}return res},capitalize:function(str){var ret=str.toLowerCase();return r.copySafeness(str,ret[0].toUpperCase()+ret.slice(1))},center:function(str,width){width=width||80;if(str.length>=width){return str}var spaces=width-str.length;var pre=lib.repeat(" ",spaces/2-spaces%2);var post=lib.repeat(" ",spaces/2);return r.copySafeness(str,pre+str+post)},"default":function(val,def){return val?val:def},dictsort:function(val,case_sensitive,by){if(!lib.isObject(val)){throw new lib.TemplateError("dictsort filter: val must be an object")}var array=[];for(var k in val){array.push([k,val[k]])}var si;if(by===undefined||by==="key"){si=0}else if(by==="value"){si=1}else{throw new lib.TemplateError("dictsort filter: You can only sort by either key or value")}array.sort(function(t1,t2){var a=t1[si];var b=t2[si];if(!case_sensitive){if(lib.isString(a)){a=a.toUpperCase()}if(lib.isString(b)){b=b.toUpperCase()}}return a>b?1:a==b?0:-1});return array},escape:function(str){if(typeof str=="string"||str instanceof r.SafeString){return lib.escape(str)}return str},safe:function(str){return new r.SafeString(str)},first:function(arr){return arr[0]},groupby:function(arr,attr){return lib.groupBy(arr,attr)},indent:function(str,width,indentfirst){width=width||4;var res="";var lines=str.split("\n");var sp=lib.repeat(" ",width);for(var i=0;i<lines.length;i++){if(i==0&&!indentfirst){res+=lines[i]+"\n"}else{res+=sp+lines[i]+"\n"}}return r.copySafeness(str,res)},join:function(arr,del,attr){del=del||"";if(attr){arr=lib.map(arr,function(v){return v[attr]})}return arr.join(del)},last:function(arr){return arr[arr.length-1]},length:function(arr){return arr.length},list:function(val){if(lib.isString(val)){return val.split("")}else if(lib.isObject(val)){var keys=[];if(Object.keys){keys=Object.keys(val)}else{for(var k in val){keys.push(k)}}return lib.map(keys,function(k){return{key:k,value:val[k]}})}else{throw new lib.TemplateError("list filter: type not iterable")}},lower:function(str){return str.toLowerCase()},random:function(arr){var i=Math.floor(Math.random()*arr.length);if(i==arr.length){i--}return arr[i]},replace:function(str,old,new_,maxCount){var res=str;var last=res;var count=1;res=res.replace(old,new_);while(last!=res){if(count>=maxCount){break}last=res;res=res.replace(old,new_);count++}return r.copySafeness(str,res)},reverse:function(val){var arr;if(lib.isString(val)){arr=filters.list(val)}else{arr=lib.map(val,function(v){return v})}arr.reverse();if(lib.isString(val)){return r.copySafeness(val,arr.join(""))}return arr},round:function(val,precision,method){precision=precision||0;var factor=Math.pow(10,precision);var rounder;if(method=="ceil"){rounder=Math.ceil}else if(method=="floor"){rounder=Math.floor}else{rounder=Math.round}return rounder(val*factor)/factor},slice:function(arr,slices,fillWith){var sliceLength=Math.floor(arr.length/slices);var extra=arr.length%slices;var offset=0;var res=[];for(var i=0;i<slices;i++){var start=offset+i*sliceLength;if(i<extra){offset++}var end=offset+(i+1)*sliceLength;var slice=arr.slice(start,end);if(fillWith&&i>=extra){slice.push(fillWith)}res.push(slice)}return res},sort:function(arr,reverse,caseSens,attr){arr=lib.map(arr,function(v){return v});arr.sort(function(a,b){var x,y;if(attr){x=a[attr];y=b[attr]}else{x=a;y=b}if(!caseSens&&lib.isString(x)&&lib.isString(y)){x=x.toLowerCase();y=y.toLowerCase()}if(x<y){return reverse?1:-1}else if(x>y){return reverse?-1:1}else{return 0}});return arr},string:function(obj){return r.copySafeness(obj,obj)},title:function(str){var words=str.split(" ");for(var i=0;i<words.length;i++){words[i]=filters.capitalize(words[i])}return r.copySafeness(str,words.join(" "))},trim:function(str){return r.copySafeness(str,str.replace(/^\s*|\s*$/g,""))},truncate:function(input,length,killwords,end){var orig=input;length=length||255;if(input.length<=length)return input;if(killwords){input=input.substring(0,length)}else{var idx=input.lastIndexOf(" ",length);if(idx===-1){idx=length}input=input.substring(0,idx)}input+=end!==undefined&&end!==null?end:"...";return r.copySafeness(orig,input)},upper:function(str){return str.toUpperCase()},wordcount:function(str){return str.match(/\w+/g).length},"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;var current=null;return{reset:function(){index=-1;current=null},next:function(){index++;if(index>=items.length){index=0}current=items[index];return current}}}function joiner(sep){sep=sep||",";var first=true;return function(){var val=first?"":sep;first=false;return val}}var globals={range:function(start,stop,step){if(!stop){stop=start;start=0;step=1}else if(!step){step=1}var arr=[];for(var i=start;i<stop;i+=step){arr.push(i)}return arr},cycler:function(){return cycler(Array.prototype.slice.call(arguments))},joiner:function(sep){return joiner(sep)}};modules["globals"]=globals})();(function(){var lib=modules["lib"];var Object=modules["object"];var lexer=modules["lexer"];var compiler=modules["compiler"];var builtin_filters=modules["filters"];var builtin_loaders=modules["loaders"];var runtime=modules["runtime"];var globals=modules["globals"];var Frame=runtime.Frame;var Environment=Object.extend({init:function(loaders,opts){opts=opts||{};this.dev=!!opts.dev;this.autoesc=!!opts.autoescape;if(!loaders){if(builtin_loaders.FileSystemLoader){this.loaders=[new builtin_loaders.FileSystemLoader]}else{this.loaders=[new builtin_loaders.HttpLoader("/views")]}}else{this.loaders=lib.isArray(loaders)?loaders:[loaders]}if(opts.tags){lexer.setTags(opts.tags)}this.filters=builtin_filters;this.cache={};this.extensions={};this.extensionsList=[]},addExtension:function(name,extension){extension._name=name;this.extensions[name]=extension;this.extensionsList.push(extension)},getExtension:function(name){return this.extensions[name]},addFilter:function(name,func){this.filters[name]=func},getFilter:function(name){if(!this.filters[name]){throw new Error("filter not found: "+name)}return this.filters[name]},getTemplate:function(name,eagerCompile){if(name&&name.raw){name=name.raw}var info=null;var tmpl=this.cache[name];var upToDate;if(typeof name!=="string"){throw new Error("template names must be a string: "+name)}if(!tmpl||!tmpl.isUpToDate()){for(var i=0;i<this.loaders.length;i++){if(info=this.loaders[i].getSource(name)){break}}if(!info){throw new Error("template not found: "+name)}this.cache[name]=new Template(info.src,this,info.path,info.upToDate,eagerCompile)}return this.cache[name]},registerPrecompiled:function(templates){for(var name in templates){this.cache[name]=new Template({type:"code",obj:templates[name]},this,name,function(){return true},true)}},express:function(app){var env=this;if(app.render){app.render=function(name,ctx,k){var context={};if(lib.isFunction(ctx)){k=ctx;ctx={}}context=lib.extend(context,this.locals);if(ctx._locals){context=lib.extend(context,ctx._locals)}context=lib.extend(context,ctx);var res=env.render(name,context);k(null,res)}}else{var http=modules["http"];var res=http.ServerResponse.prototype;res._render=function(name,ctx,k){var app=this.app;var context={};if(this._locals){context=lib.extend(context,this._locals)}if(ctx){context=lib.extend(context,ctx);if(ctx.locals){context=lib.extend(context,ctx.locals)}}context=lib.extend(context,app._locals);var str=env.render(name,context);if(k){k(null,str)}else{this.send(str)}}}},render:function(name,ctx){return this.getTemplate(name).render(ctx)}});var Context=Object.extend({init:function(ctx,blocks){this.ctx=ctx;this.blocks={};this.exported=[];for(var name in blocks){this.addBlock(name,blocks[name])}},lookup:function(name){if(name in globals&&!(name in this.ctx)){return globals[name]}else{return this.ctx[name]}},setVariable:function(name,val){this.ctx[name]=val},getVariables:function(){return this.ctx},addBlock:function(name,block){this.blocks[name]=this.blocks[name]||[];this.blocks[name].push(block)},getBlock:function(name){if(!this.blocks[name]){throw new Error('unknown block "'+name+'"')}return this.blocks[name][0]},getSuper:function(env,name,block,frame,runtime){var idx=(this.blocks[name]||[]).indexOf(block);var blk=this.blocks[name][idx+1];var context=this;return function(){if(idx==-1||!blk){throw new Error('no super block available for "'+name+'"')}return blk(env,context,frame,runtime)}},addExport:function(name){this.exported.push(name)},getExported:function(){var exported={};for(var i=0;i<this.exported.length;i++){var name=this.exported[i];exported[name]=this.ctx[name]}return exported}});var Template=Object.extend({init:function(src,env,path,upToDate,eagerCompile){this.env=env||new Environment;if(lib.isObject(src)){switch(src.type){case"code":this.tmplProps=src.obj;break;case"string":this.tmplStr=src.obj;break}}else if(lib.isString(src)){this.tmplStr=src}else{throw new Error("src must be a string or an object describing "+"the source")}this.path=path;this.upToDate=upToDate||function(){return false};if(eagerCompile){var _this=this;lib.withPrettyErrors(this.path,this.env.dev,function(){_this._compile()})}else{this.compiled=false}},render:function(ctx,frame){var self=this;var render=function(){if(!self.compiled){self._compile()}var context=new Context(ctx||{},self.blocks);return self.rootRenderFunc(self.env,context,frame||new Frame,runtime)};return lib.withPrettyErrors(this.path,this.env.dev,render)},isUpToDate:function(){return this.upToDate()},getExported:function(){if(!this.compiled){this._compile()}var context=new Context({},this.blocks);this.rootRenderFunc(this.env,context,new Frame,runtime);return context.getExported()},_compile:function(){var props;if(this.tmplProps){props=this.tmplProps}else{var source=compiler.compile(this.tmplStr,this.env.extensionsList,this.path);var func=new Function(source);props=func()}this.blocks=this._getBlocks(props);this.rootRenderFunc=props.root;this.compiled=true},_getBlocks:function(props){var blocks={};for(var k in props){if(k.slice(0,2)=="b_"){blocks[k.slice(2)]=props[k]}}return blocks}});modules["environment"]={Environment:Environment,Template:Template}})();var nunjucks;var env=modules["environment"];var compiler=modules["compiler"];var parser=modules["parser"];var lexer=modules["lexer"];var runtime=modules["runtime"];var loaders=modules["loaders"];nunjucks={};nunjucks.Environment=env.Environment;nunjucks.Template=env.Template;if(loaders){if(loaders.FileSystemLoader){nunjucks.FileSystemLoader=loaders.FileSystemLoader}else{nunjucks.HttpLoader=loaders.HttpLoader}}nunjucks.compiler=compiler;nunjucks.parser=parser;nunjucks.lexer=lexer;nunjucks.runtime=runtime;nunjucks.require=function(name){return modules[name]};if(typeof define==="function"&&define.amd){define(function(){return nunjucks})}else{window.nunjucks=nunjucks}})();
+(function(){var modules={};(function(){function extend(cls,name,props){var F=function(){};F.prototype=cls.prototype;var prototype=new F;var fnTest=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;props=props||{};for(var k in props){var src=props[k];var parent=prototype[k];if(typeof parent=="function"&&typeof src=="function"&&fnTest.test(src)){prototype[k]=function(src,parent){return function(){var tmp=this.parent;this.parent=parent;var res=src.apply(this,arguments);this.parent=tmp;return res}}(src,parent)}else{prototype[k]=src}}prototype.typename=name;var new_cls=function(){if(prototype.init){prototype.init.apply(this,arguments)}};new_cls.prototype=prototype;new_cls.prototype.constructor=new_cls;new_cls.extend=function(name,props){if(typeof name=="object"){props=name;name="anonymous"}return extend(new_cls,name,props)};return new_cls}modules["object"]=extend(Object,"Object",{})})();(function(){var ArrayProto=Array.prototype;var ObjProto=Object.prototype;var escapeMap={"&":"&amp;",'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;"};var 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(/[&"'<>]/g,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 obj===Object(obj)};exports.groupBy=function(obj,val){var result={};var iterator=exports.isFunction(val)?val:function(obj){return obj[val]};for(var i=0;i<obj.length;i++){var value=obj[i];var key=iterator(value,i);(result[key]||(result[key]=[])).push(value)}return result};exports.toArray=function(obj){return Array.prototype.slice.call(obj)};exports.without=function(array){var result=[];if(!array){return result}var index=-1,length=array.length,contains=exports.toArray(arguments).slice(1);while(++index<length){if(contains.indexOf(array[index])===-1){result.push(array[index])}}return result};exports.extend=function(obj,obj2){for(var k in obj2){obj[k]=obj2[k]}return obj};exports.repeat=function(char_,n){var str="";for(var i=0;i<n;i++){str+=char_}return str};exports.each=function(obj,func,context){if(obj==null){return}if(ArrayProto.each&&obj.each==ArrayProto.each){obj.forEach(func,context)}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i<l;i++){func.call(context,obj[i],i,obj)}}};exports.map=function(obj,func){var results=[];if(obj==null){return results}if(ArrayProto.map&&obj.map===ArrayProto.map){return obj.map(func)}for(var i=0;i<obj.length;i++){results[results.length]=func(obj[i],i)}if(obj.length===+obj.length){results.length=obj.length}return results};if(!Array.prototype.indexOf){Array.prototype.indexOf=function(array,searchElement){if(array==null){throw new TypeError}var t=Object(array);var len=t.length>>>0;if(len===0){return-1}var n=0;if(arguments.length>2){n=Number(arguments[2]);if(n!=n){n=0}else if(n!=0&&n!=Infinity&&n!=-Infinity){n=(n>0||-1)*Math.floor(Math.abs(n))}}if(n>=len){return-1}var k=n>=0?n:Math.max(len-Math.abs(n),0);for(;k<len;k++){if(k in t&&t[k]===searchElement){return k}}return-1}}})();(function(){var lib=modules["lib"];var Object=modules["object"];var Frame=Object.extend({init:function(parent){this.variables={};this.parent=parent},set:function(name,val){var parts=name.split(".");var obj=this.variables;for(var i=0;i<parts.length-1;i++){var id=parts[i];if(!obj[id]){obj[id]={}}obj=obj[id]}obj[parts[parts.length-1]]=val},get:function(name){var val=this.variables[name];if(val!==undefined&&val!==null){return val}return null},lookup:function(name){var p=this.parent;var val=this.variables[name];if(val!==undefined&&val!==null){return val}return p&&p.lookup(name)},push:function(){return new Frame(this)},pop:function(){return this.parent}});function makeMacro(argNames,kwargNames,func){return function(){var argCount=numArgs(arguments);var args;var kwargs=getKeywordArgs(arguments);if(argCount>argNames.length){args=Array.prototype.slice.call(arguments,0,argNames.length);var vals=Array.prototype.slice.call(arguments,args.length,argCount);for(var i=0;i<vals.length;i++){if(i<kwargNames.length){kwargs[kwargNames[i]]=vals[i]}}args.push(kwargs)}else if(argCount<argNames.length){args=Array.prototype.slice.call(arguments,0,argCount);for(var i=argCount;i<argNames.length;i++){var arg=argNames[i];args.push(kwargs[arg]);delete kwargs[arg]}args.push(kwargs)}else{args=arguments}return func.apply(this,args)}}function makeKeywordArgs(obj){obj.__keywords=true;return obj}function getKeywordArgs(args){var len=args.length;if(len){var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return lastArg}}return{}}function numArgs(args){var len=args.length;if(len===0){return 0}var lastArg=args[len-1];if(lastArg&&lastArg.hasOwnProperty("__keywords")){return len-1}else{return len}}function SafeString(val){if(typeof val!="string"){return val}this.toString=function(){return val};this.length=val.length;var methods=["charAt","charCodeAt","concat","contains","endsWith","fromCharCode","indexOf","lastIndexOf","length","localeCompare","match","quote","replace","search","slice","split","startsWith","substr","substring","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toUpperCase","trim","trimLeft","trimRight"];for(var i=0;i<methods.length;i++){this[methods[i]]=markSafe(val[methods[i]])}}function copySafeness(dest,target){if(dest instanceof SafeString){return new SafeString(target)}return target.toString()}function markSafe(val){var type=typeof val;if(type==="string"){return new SafeString(val)}else if(type!=="function"){return val}else{return function(){var ret=val.apply(this,arguments);if(typeof ret==="string"){return new SafeString(ret)}return ret}}}function suppressValue(val,autoescape){val=val!==undefined&&val!==null?val:"";if(autoescape&&typeof val==="string"){val=lib.escape(val)}return val}function memberLookup(obj,val){obj=obj||{};if(typeof obj[val]==="function"){return function(){return obj[val].apply(obj,arguments)}}return obj[val]}function callWrap(obj,name,args){if(!obj){throw new Error("Unable to call `"+name+"`, which is undefined or falsey")}else if(typeof obj!=="function"){throw new Error("Unable to call `"+name+"`, which is not a function")}return obj.apply(this,args)}function contextOrFrameLookup(context,frame,name){var val=context.lookup(name);return val!==undefined&&val!==null?val:frame.lookup(name)}function handleError(error,lineno,colno){if(error.lineno){throw error}else{throw new lib.TemplateError(error,lineno,colno)}}modules["runtime"]={Frame:Frame,makeMacro:makeMacro,makeKeywordArgs:makeKeywordArgs,numArgs:numArgs,suppressValue:suppressValue,memberLookup:memberLookup,contextOrFrameLookup:contextOrFrameLookup,callWrap:callWrap,handleError:handleError,isArray:lib.isArray,SafeString:SafeString,copySafeness:copySafeness,markSafe:markSafe}})();(function(){var lib=modules["lib"];var r=modules["runtime"];var filters={abs:function(n){return Math.abs(n)},batch:function(arr,linecount,fill_with){var res=[];var tmp=[];for(var i=0;i<arr.length;i++){if(i%linecount===0&&tmp.length){res.push(tmp);tmp=[]}tmp.push(arr[i])}if(tmp.length){if(fill_with){for(var i=tmp.length;i<linecount;i++){tmp.push(fill_with)}}res.push(tmp)}return res},capitalize:function(str){var ret=str.toLowerCase();return r.copySafeness(str,ret.charAt(0).toUpperCase()+ret.slice(1))},center:function(str,width){width=width||80;if(str.length>=width){return str}var spaces=width-str.length;var pre=lib.repeat(" ",spaces/2-spaces%2);var post=lib.repeat(" ",spaces/2);return r.copySafeness(str,pre+str+post)},"default":function(val,def){return val?val:def},dictsort:function(val,case_sensitive,by){if(!lib.isObject(val)){throw new lib.TemplateError("dictsort filter: val must be an object")}var array=[];for(var k in val){array.push([k,val[k]])}var si;if(by===undefined||by==="key"){si=0}else if(by==="value"){si=1}else{throw new lib.TemplateError("dictsort filter: You can only sort by either key or value")}array.sort(function(t1,t2){var a=t1[si];var b=t2[si];if(!case_sensitive){if(lib.isString(a)){a=a.toUpperCase()}if(lib.isString(b)){b=b.toUpperCase()}}return a>b?1:a==b?0:-1});return array},escape:function(str){if(typeof str=="string"||str instanceof r.SafeString){return lib.escape(str)}return str},safe:function(str){return r.markSafe(str)},first:function(arr){return arr[0]},groupby:function(arr,attr){return lib.groupBy(arr,attr)},indent:function(str,width,indentfirst){width=width||4;var res="";var lines=str.split("\n");var sp=lib.repeat(" ",width);for(var i=0;i<lines.length;i++){if(i==0&&!indentfirst){res+=lines[i]+"\n"}else{res+=sp+lines[i]+"\n"}}return r.copySafeness(str,res)},join:function(arr,del,attr){del=del||"";if(attr){arr=lib.map(arr,function(v){return v[attr]})}return arr.join(del)},last:function(arr){return arr[arr.length-1]},length:function(arr){return arr.length},list:function(val){if(lib.isString(val)){return val.split("")}else if(lib.isObject(val)){var keys=[];if(Object.keys){keys=Object.keys(val)}else{for(var k in val){keys.push(k)}}return lib.map(keys,function(k){return{key:k,value:val[k]}})}else{throw new lib.TemplateError("list filter: type not iterable")}},lower:function(str){return str.toLowerCase()},random:function(arr){var i=Math.floor(Math.random()*arr.length);if(i==arr.length){i--}return arr[i]},replace:function(str,old,new_,maxCount){var res=str;var last=res;var count=1;res=res.replace(old,new_);while(last!=res){if(count>=maxCount){break}last=res;res=res.replace(old,new_);count++}return r.copySafeness(str,res)},reverse:function(val){var arr;if(lib.isString(val)){arr=filters.list(val)}else{arr=lib.map(val,function(v){return v})}arr.reverse();if(lib.isString(val)){return r.copySafeness(val,arr.join(""))}return arr},round:function(val,precision,method){precision=precision||0;var factor=Math.pow(10,precision);var rounder;if(method=="ceil"){rounder=Math.ceil}else if(method=="floor"){rounder=Math.floor}else{rounder=Math.round}return rounder(val*factor)/factor},slice:function(arr,slices,fillWith){var sliceLength=Math.floor(arr.length/slices);var extra=arr.length%slices;var offset=0;var res=[];for(var i=0;i<slices;i++){var start=offset+i*sliceLength;if(i<extra){offset++}var end=offset+(i+1)*sliceLength;var slice=arr.slice(start,end);if(fillWith&&i>=extra){slice.push(fillWith)}res.push(slice)}return res},sort:function(arr,reverse,caseSens,attr){arr=lib.map(arr,function(v){return v});arr.sort(function(a,b){var x,y;if(attr){x=a[attr];y=b[attr]}else{x=a;y=b}if(!caseSens&&lib.isString(x)&&lib.isString(y)){x=x.toLowerCase();y=y.toLowerCase()}if(x<y){return reverse?1:-1}else if(x>y){return reverse?-1:1}else{return 0}});return arr},string:function(obj){return r.copySafeness(obj,obj)},title:function(str){var words=str.split(" ");for(var i=0;i<words.length;i++){words[i]=filters.capitalize(words[i])}return r.copySafeness(str,words.join(" "))},trim:function(str){return r.copySafeness(str,str.replace(/^\s*|\s*$/g,""))},truncate:function(input,length,killwords,end){var orig=input;length=length||255;if(input.length<=length)return input;if(killwords){input=input.substring(0,length)}else{var idx=input.lastIndexOf(" ",length);if(idx===-1){idx=length}input=input.substring(0,idx)}input+=end!==undefined&&end!==null?end:"...";return r.copySafeness(orig,input)},upper:function(str){return str.toUpperCase()},wordcount:function(str){return str.match(/\w+/g).length},"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;var current=null;return{reset:function(){index=-1;current=null},next:function(){index++;if(index>=items.length){index=0}current=items[index];return current}}}function joiner(sep){sep=sep||",";var first=true;return function(){var val=first?"":sep;first=false;return val}}var globals={range:function(start,stop,step){if(!stop){stop=start;start=0;step=1}else if(!step){step=1}var arr=[];for(var i=start;i<stop;i+=step){arr.push(i)}return arr},cycler:function(){return cycler(Array.prototype.slice.call(arguments))},joiner:function(sep){return joiner(sep)}};modules["globals"]=globals})();(function(){var lib=modules["lib"];var Object=modules["object"];var lexer=modules["lexer"];var compiler=modules["compiler"];var builtin_filters=modules["filters"];var builtin_loaders=modules["loaders"];var runtime=modules["runtime"];var globals=modules["globals"];var Frame=runtime.Frame;var Environment=Object.extend({init:function(loaders,opts){opts=opts||{};this.dev=!!opts.dev;this.autoesc=!!opts.autoescape;if(!loaders){if(builtin_loaders.FileSystemLoader){this.loaders=[new builtin_loaders.FileSystemLoader]}else{this.loaders=[new builtin_loaders.HttpLoader("/views")]}}else{this.loaders=lib.isArray(loaders)?loaders:[loaders]}if(opts.tags){lexer.setTags(opts.tags)}this.filters=builtin_filters;this.cache={};this.extensions={};this.extensionsList=[]},addExtension:function(name,extension){extension._name=name;this.extensions[name]=extension;this.extensionsList.push(extension)},getExtension:function(name){return this.extensions[name]},addFilter:function(name,func){this.filters[name]=func},getFilter:function(name){if(!this.filters[name]){throw new Error("filter not found: "+name)}return this.filters[name]},getTemplate:function(name,eagerCompile){if(name&&name.raw){name=name.raw}var info=null;var tmpl=this.cache[name];var upToDate;if(typeof name!=="string"){throw new Error("template names must be a string: "+name)}if(!tmpl||!tmpl.isUpToDate()){for(var i=0;i<this.loaders.length;i++){if(info=this.loaders[i].getSource(name)){break}}if(!info){throw new Error("template not found: "+name)}this.cache[name]=new Template(info.src,this,info.path,info.upToDate,eagerCompile)}return this.cache[name]},registerPrecompiled:function(templates){for(var name in templates){this.cache[name]=new Template({type:"code",obj:templates[name]},this,name,function(){return true},true)}},express:function(app){var env=this;if(app.render){app.render=function(name,ctx,k){var context={};if(lib.isFunction(ctx)){k=ctx;ctx={}}context=lib.extend(context,this.locals);if(ctx._locals){context=lib.extend(context,ctx._locals)}context=lib.extend(context,ctx);var res=env.render(name,context);k(null,res)}}else{var http=modules["http"];var res=http.ServerResponse.prototype;res._render=function(name,ctx,k){var app=this.app;var context={};if(this._locals){context=lib.extend(context,this._locals)}if(ctx){context=lib.extend(context,ctx);if(ctx.locals){context=lib.extend(context,ctx.locals)}}context=lib.extend(context,app._locals);var str=env.render(name,context);if(k){k(null,str)}else{this.send(str)}}}},render:function(name,ctx){return this.getTemplate(name).render(ctx)}});var Context=Object.extend({init:function(ctx,blocks){this.ctx=ctx;this.blocks={};this.exported=[];for(var name in blocks){this.addBlock(name,blocks[name])}},lookup:function(name){if(name in globals&&!(name in this.ctx)){return globals[name]}else{return this.ctx[name]}},setVariable:function(name,val){this.ctx[name]=val},getVariables:function(){return this.ctx},addBlock:function(name,block){this.blocks[name]=this.blocks[name]||[];this.blocks[name].push(block)},getBlock:function(name){if(!this.blocks[name]){throw new Error('unknown block "'+name+'"')}return this.blocks[name][0]},getSuper:function(env,name,block,frame,runtime){var idx=(this.blocks[name]||[]).indexOf(block);var blk=this.blocks[name][idx+1];var context=this;return function(){if(idx==-1||!blk){throw new Error('no super block available for "'+name+'"')}return blk(env,context,frame,runtime)}},addExport:function(name){this.exported.push(name)},getExported:function(){var exported={};for(var i=0;i<this.exported.length;i++){var name=this.exported[i];exported[name]=this.ctx[name]}return exported}});var Template=Object.extend({init:function(src,env,path,upToDate,eagerCompile){this.env=env||new Environment;if(lib.isObject(src)){switch(src.type){case"code":this.tmplProps=src.obj;break;case"string":this.tmplStr=src.obj;break}}else if(lib.isString(src)){this.tmplStr=src}else{throw new Error("src must be a string or an object describing "+"the source")}this.path=path;this.upToDate=upToDate||function(){return false};if(eagerCompile){var _this=this;lib.withPrettyErrors(this.path,this.env.dev,function(){_this._compile()})}else{this.compiled=false}},render:function(ctx,frame){var self=this;var render=function(){if(!self.compiled){self._compile()}var context=new Context(ctx||{},self.blocks);return self.rootRenderFunc(self.env,context,frame||new Frame,runtime)};return lib.withPrettyErrors(this.path,this.env.dev,render)},isUpToDate:function(){return this.upToDate()},getExported:function(){if(!this.compiled){this._compile()}var context=new Context({},this.blocks);this.rootRenderFunc(this.env,context,new Frame,runtime);return context.getExported()},_compile:function(){var props;if(this.tmplProps){props=this.tmplProps}else{var source=compiler.compile(this.tmplStr,this.env.extensionsList,this.path);var func=new Function(source);props=func()}this.blocks=this._getBlocks(props);this.rootRenderFunc=props.root;this.compiled=true},_getBlocks:function(props){var blocks={};for(var k in props){if(k.slice(0,2)=="b_"){blocks[k.slice(2)]=props[k]}}return blocks}});modules["environment"]={Environment:Environment,Template:Template}})();var nunjucks;var env=modules["environment"];var compiler=modules["compiler"];var parser=modules["parser"];var lexer=modules["lexer"];var runtime=modules["runtime"];var loaders=modules["loaders"];nunjucks={};nunjucks.Environment=env.Environment;nunjucks.Template=env.Template;if(loaders){if(loaders.FileSystemLoader){nunjucks.FileSystemLoader=loaders.FileSystemLoader}else{nunjucks.HttpLoader=loaders.HttpLoader}}nunjucks.compiler=compiler;nunjucks.parser=parser;nunjucks.lexer=lexer;nunjucks.runtime=runtime;nunjucks.require=function(name){return modules[name]};if(typeof define==="function"&&define.amd){define(function(){return nunjucks})}else{window.nunjucks=nunjucks}})();
View
74 browser/nunjucks.js
@@ -5,7 +5,11 @@ var modules = {};
// A simple class system, more documentation to come
function extend(cls, name, props) {
- var prototype = Object.create(cls.prototype);
+ // This does that same thing as Object.create, but with support for IE8
+ var F = function() {};
+ F.prototype = cls.prototype;
+ var prototype = new F();
+
var fnTest = /xyz/.test(function(){ xyz; }) ? /\bparent\b/ : /.*/;
props = props || {};
@@ -247,6 +251,38 @@ exports.map = function(obj, func) {
return results;
};
+
+if(!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function(array, searchElement /*, fromIndex */) {
+ if (array == null) {
+ throw new TypeError();
+ }
+ var t = Object(array);
+ var len = t.length >>> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 2) {
+ n = Number(arguments[2]);
+ if (n != n) { // shortcut for verifying if it's NaN
+ n = 0;
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ };
+}
})();
(function() {
@@ -404,7 +440,7 @@ function SafeString(val) {
];
for(var i=0; i<methods.length; i++) {
- this[methods[i]] = proxyStr(val[methods[i]]);
+ this[methods[i]] = markSafe(val[methods[i]]);
}
}
@@ -415,15 +451,26 @@ function copySafeness(dest, target) {
return target.toString();
}
-function proxyStr(func) {
- return function() {
- var ret = func.apply(this, arguments);
+function markSafe(val) {
+ var type = typeof val;
- if(typeof ret == 'string') {
- return new SafeString(ret);
- }
- return ret;
- };
+ if(type === 'string') {
+ return new SafeString(val);
+ }
+ else if(type !== 'function') {
+ return val;
+ }
+ else {
+ return function() {
+ var ret = val.apply(this, arguments);
+
+ if(typeof ret === 'string') {
+ return new SafeString(ret);
+ }
+
+ return ret;
+ };
+ }
}
function suppressValue(val, autoescape) {
@@ -487,7 +534,8 @@ modules['runtime'] = {
handleError: handleError,
isArray: lib.isArray,
SafeString: SafeString,
- copySafeness: copySafeness
+ copySafeness: copySafeness,
+ markSafe: markSafe
};
})();
(function() {
@@ -528,7 +576,7 @@ var filters = {
capitalize: function(str) {
var ret = str.toLowerCase();
- return r.copySafeness(str, ret[0].toUpperCase() + ret.slice(1));
+ return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
},
center: function(str, width) {
@@ -597,7 +645,7 @@ var filters = {
},
safe: function(str) {
- return new r.SafeString(str);
+ return r.markSafe(str);
},
first: function(arr) {
View
2 package.json
@@ -1,7 +1,7 @@
{
"name": "nunjucks",
"description": "A jinja inspired templating engine",
- "version": "0.1.9",
+ "version": "0.1.10",
"author": {
"name": "James Long",
"email": "longster@gmail.com"

0 comments on commit acd1a7b

Please sign in to comment.