Comparing version 0.1.7 to 0.1.8
@@ -1,1 +0,1 @@ | ||
(function(){var a={};(function(){function b(a,c,d){var e=Object.create(a.prototype),f=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;d=d||{};for(var g in d){var h=d[g],i=e[g];typeof i=="function"&&typeof h=="function"&&f.test(h)?e[g]=function(a,b){return function(){var c=this.parent;this.parent=b;var d=a.apply(this,arguments);return this.parent=c,d}}(h,i):e[g]=h}e.typename=c;var j=function(){e.init&&e.init.apply(this,arguments)};return j.prototype=e,j.prototype.constructor=j,j.extend=function(a,c){return typeof a=="object"&&(c=a,a="anonymous"),b(j,a,c)},j}a.object=b(Object,"Object",{})})(),function(){var b=Array.prototype,c=Object.prototype,d=a.lib={};d.isFunction=function(a){return c.toString.call(a)=="[object Function]"},d.isArray=Array.isArray||function(a){return c.toString.call(a)=="[object Array]"},d.isString=function(a){return c.toString.call(a)=="[object String]"},d.isObject=function(a){return a===Object(a)},d.groupBy=function(a,b){var c={},e=d.isFunction(b)?b:function(a){return a[b]};for(var f=0;f<a.length;f++){var g=a[f],h=e(g,f);(c[h]||(c[h]=[])).push(g)}return c},d.toArray=function(a){return Array.prototype.slice.call(a)},d.without=function(a){var b=[];if(!a)return b;var c=-1,e=a.length,f=d.toArray(arguments).slice(1);while(++c<e)f.indexOf(a[c])===-1&&b.push(a[c]);return b},d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.repeat=function(a,b){var c="";for(var d=0;d<b;d++)c+=a;return c},d.each=function(a,c,d){if(a==null)return;if(b.each&&a.each==b.each)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++)c.call(d,a[e],e,a)},d.map=function(a,c){var d=[];if(a==null)return d;if(b.map&&a.map===b.map)return a.map(c);for(var e=0;e<a.length;e++)d[d.length]=c(a[e],e);return a.length===+a.length&&(d.length=a.length),d}}(),function(){var b=a.lib,c={abs:function(a){return Math.abs(a)},batch:function(a,b,c){var d=[],e=[];for(var f=0;f<a.length;f++)f%b===0&&e.length&&(d.push(e),e=[]),e.push(a[f]);if(e.length){if(c)for(var f=e.length;f<b;f++)e.push(c);d.push(e)}return d},capitalize:function(a){return a=a.toLowerCase(),a[0].toUpperCase()+a.slice(1)},center:function(a,c){c=c||80;if(a.length>=c)return a;var d=c-a.length,e=b.repeat(" ",d/2-d%2),f=b.repeat(" ",d/2);return e+a+f},"default":function(a,b){return a?a:b},escape:function(a){return a.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")},first:function(a){return a[0]},groupby:function(a,c){return b.groupBy(a,c)},indent:function(a,c,d){c=c||4;var e="",f=a.split("\n"),g=b.repeat(" ",c);for(var h=0;h<f.length;h++)h==0&&!d?e+=f[h]+"\n":e+=g+f[h]+"\n";return e},join:function(a,c,d){return c=c||"",d&&(a=b.map(a,function(a){return a[d]})),a.join(c)},last:function(a){return a[a.length-1]},length:function(a){return a.length},list:function(a){if(b.isString(a))return a.split("");if(b.isObject(a)){var c=[];if(Object.keys)c=Object.keys(a);else for(var d in a)c.push(d);return b.map(c,function(b){return{key:b,value:a[b]}})}throw new Error("list: type not iterable")},lower:function(a){return a.toLowerCase()},random:function(a){var b=Math.floor(Math.random()*a.length);return b==a.length&&b--,a[b]},replace:function(a,b,c,d){var e=a,f=e,g=1;e=e.replace(b,c);while(f!=e){if(g>=d)break;f=e,e=e.replace(b,c),g++}return e},reverse:function(a){var d;return b.isString(a)?d=c.list(a):d=b.map(a,function(a){return a}),d.reverse(),b.isString(a)?d.join(""):d},round:function(a,b,c){b=b||0;var d=Math.pow(10,b),e;return c=="ceil"?e=Math.ceil:c=="floor"?e=Math.floor:e=Math.round,e(a*d)/d},slice:function(a,b,c){var d=Math.floor(a.length/b),e=a.length%b,f=0,g=[];for(var h=0;h<b;h++){var i=f+h*d;h<e&&f++;var j=f+(h+1)*d,k=a.slice(i,j);c&&h>=e&&k.push(c),g.push(k)}return g},sort:function(a,c,d,e){return a=b.map(a,function(a){return a}),a.sort(function(a,f){var g,h;return e?(g=a[e],h=f[e]):(g=a,h=f),!d&&b.isString(g)&&b.isString(h)&&(g=g.toLowerCase(),h=h.toLowerCase()),g<h?c?1:-1:g>h?c?-1:1:0}),a},string:function(a){return a.toString()},title:function(a){return a.toUpperCase()},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},upper:function(a){return a.toUpperCase()},wordcount:function(a){return a.match(/\w+/g).length},"float":function(a,b){return parseFloat(a)||b},"int":function(a,b){return parseInt(a)||b}};c.d=c.default,c.e=c.escape,a.filters=c}(),function(){function d(a,b,c){return function(){var d=g(arguments),e,h=f(arguments);if(d>a.length){e=Array.prototype.slice.call(arguments,0,a.length);var i=Array.prototype.slice.call(arguments,e.length,d);for(var j=0;j<i.length;j++)j<b.length&&(h[b[j]]=i[j]);e.push(h)}else if(d<a.length){e=Array.prototype.slice.call(arguments,0,d);for(var j=d;j<a.length;j++){var k=a[j];e.push(h[k]),delete h[k]}e.push(h)}else e=arguments;return c.apply(this,e)}}function e(a){return a.__keywords=!0,a}function f(a){return a.length&&a[a.length-1].__keywords?a[a.length-1]:{}}function g(a){return a.length===0?0:a[a.length-1].__keywords?a.length-1:a.length}var b=a.object,c=b.extend({init:function(a){this.variables={},this.parent=a},set:function(a,b){var c=a.split("."),d=this.variables;for(var e=0;e<c.length-1;e++){var f=c[e];d[f]||(d[f]={}),d=d[f]}d[c[c.length-1]]=b},lookup:function(a){var b=this.parent;return this.variables[a]||b&&b.lookup(a)},push:function(){return new c(this)},pop:function(){return this.parent}});a.runtime={Frame:c,makeMacro:d,makeKeywordArgs:e,numArgs:g}}(),function(){var b=a.lib,c=a.object,d=a.lexer,e=a.compiler,f=a.filters,g=a.loaders,h=a.runtime,i=h.Frame,j=c.extend({init:function(a,c){a?this.loaders=b.isArray(a)?a:[a]:g.FileSystemLoader?this.loaders=[new g.FileSystemLoader]:this.loaders=[new g.HttpLoader("/views")],c&&d.setTags(c),this.filters=f,this.cache={}},addFilter:function(a,b){this.filters[a]=b},getFilter:function(a){return this.filters[a]},getTemplate:function(a,b){var c=null,d=this.cache[a],e;if(!d||!d.isUpToDate()){for(var f=0;f<this.loaders.length;f++)if(c=this.loaders[f].getSource(a))break;if(!c)throw new Error("template not found: "+a);this.cache[a]=new l(c.src,this,c.path,c.upToDate,b)}return this.cache[a]},registerPrecompiled:function(a){for(var b in a)this.cache[b]=new l({type:"code",obj:a[b]},this,b,function(){return!0},!0)},express:function(a){var c=this;a.render=function(d,e,f){var g={};b.isFunction(e)&&(f=e,e={}),g=b.extend(g,a.locals),e._locals&&(g=b.extend(g,e._locals)),g=b.extend(g,e);var h=c.render(d,g);f(null,h)}},render:function(a,b){return this.getTemplate(a).render(b)}}),k=c.extend({init:function(a,b){this.ctx=a,this.blocks={},this.exported=[];for(var c in b)this.addBlock(c,b[c])},lookup:function(a){return this.ctx[a]},setVariable:function(a,b){this.ctx[a]=b},getVariables:function(){return this.ctx},addBlock:function(a,b){this.blocks[a]=this.blocks[a]||[],this.blocks[a].push(b)},getBlock:function(a){if(!this.blocks[a])throw new Error('unknown block "'+a+'"');return this.blocks[a][0]},getSuper:function(a,b,c){var d=(this.blocks[b]||[]).indexOf(c),e=this.blocks[b][d+1],f=this;return function(){if(d==-1||!e)throw new Error('no super block available for "'+b+'"');return e(a,f)}},addExport:function(a){this.exported.push(a)},getExported:function(){var a={};for(var b=0;b<this.exported.length;b++){var c=this.exported[b];a[c]=this.ctx[c]}return a}}),l=c.extend({init:function(a,c,d,e,f){this.env=c||new j;if(b.isObject(a))switch(a.type){case"code":this.tmplProps=a.obj;break;case"string":this.tmplStr=a.obj}else{if(!b.isString(a))throw new Error("src must be a string or an object describing the source");this.tmplStr=a}this.path=d,this.upToDate=e||function(){return!1},f?this._compile():this.compiled=!1},render:function(a,b){this.compiled||this._compile();var c=new k(a||{},this.blocks);return this.rootRenderFunc(this.env,c,b||new i,h)},isUpToDate:function(){return this.upToDate()},getExported:function(){this.compiled||this._compile();var a=new k({},this.blocks);return this.rootRenderFunc(this.env,a,new i,h),a.getExported()},_compile:function(){var a;if(this.tmplProps)a=this.tmplProps;else{var b=new Function(e.compile(this.tmplStr,this.env));a=b()}this.blocks=this._getBlocks(a),this.rootRenderFunc=a.root,this.compiled=!0},_getBlocks:function(a){var b={};for(var c in a)c.slice(0,2)=="b_"&&(b[c.slice(2)]=a[c]);return b}});a.environment={Environment:j,Template:l}}();var b=a.environment,c=a.compiler,d=a.parser,e=a.lexer,f=a.loaders;window.nunjucks={},window.nunjucks.Environment=b.Environment,window.nunjucks.Template=b.Template,f.FileSystemLoader?window.nunjucks.FileSystemLoader=f.FileSystemLoader:window.nunjucks.HttpLoader=f.HttpLoader,window.nunjucks.compiler=c,window.nunjucks.parser=d,window.nunjucks.lexer=e,window.nunjucks.require=function(b){return a[b]}})(); | ||
(function(){var a={};(function(){function b(a,c,d){var e=Object.create(a.prototype),f=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;d=d||{};for(var g in d){var h=d[g],i=e[g];typeof i=="function"&&typeof h=="function"&&f.test(h)?e[g]=function(a,b){return function(){var c=this.parent;this.parent=b;var d=a.apply(this,arguments);return this.parent=c,d}}(h,i):e[g]=h}e.typename=c;var j=function(){e.init&&e.init.apply(this,arguments)};return j.prototype=e,j.prototype.constructor=j,j.extend=function(a,c){return typeof a=="object"&&(c=a,a="anonymous"),b(j,a,c)},j}a.object=b(Object,"Object",{})})(),function(){var b=Array.prototype,c=Object.prototype,d=a.lib={};d.TemplateError=function(a,b,c){var d=this;return a instanceof Error?(d=a,a=a.name+": "+a.message):Error.captureStackTrace(d),d.name="Template render error",d.message=a,d.lineno=b,d.colno=c,d.firstUpdate=!0,d.Update=function(a){var b="("+(a||"unknown path")+")";return this.firstUpdate&&this.lineno&&this.colno&&(b+=" [Line "+this.lineno+", Column "+this.colno+"]"),b+="\n ",this.firstUpdate&&(b+=" "),this.message=b+(this.message||""),this.firstUpdate=!1,this},d},d.TemplateError.prototype=Error.prototype,d.isFunction=function(a){return c.toString.call(a)=="[object Function]"},d.isArray=Array.isArray||function(a){return c.toString.call(a)=="[object Array]"},d.isString=function(a){return c.toString.call(a)=="[object String]"},d.isObject=function(a){return a===Object(a)},d.groupBy=function(a,b){var c={},e=d.isFunction(b)?b:function(a){return a[b]};for(var f=0;f<a.length;f++){var g=a[f],h=e(g,f);(c[h]||(c[h]=[])).push(g)}return c},d.toArray=function(a){return Array.prototype.slice.call(a)},d.without=function(a){var b=[];if(!a)return b;var c=-1,e=a.length,f=d.toArray(arguments).slice(1);while(++c<e)f.indexOf(a[c])===-1&&b.push(a[c]);return b},d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.repeat=function(a,b){var c="";for(var d=0;d<b;d++)c+=a;return c},d.each=function(a,c,d){if(a==null)return;if(b.each&&a.each==b.each)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++)c.call(d,a[e],e,a)},d.map=function(a,c){var d=[];if(a==null)return d;if(b.map&&a.map===b.map)return a.map(c);for(var e=0;e<a.length;e++)d[d.length]=c(a[e],e);return a.length===+a.length&&(d.length=a.length),d}}(),function(){var b=a.lib,c={abs:function(a){return Math.abs(a)},batch:function(a,b,c){var d=[],e=[];for(var f=0;f<a.length;f++)f%b===0&&e.length&&(d.push(e),e=[]),e.push(a[f]);if(e.length){if(c)for(var f=e.length;f<b;f++)e.push(c);d.push(e)}return d},capitalize:function(a){return a=a.toLowerCase(),a[0].toUpperCase()+a.slice(1)},center:function(a,c){c=c||80;if(a.length>=c)return a;var d=c-a.length,e=b.repeat(" ",d/2-d%2),f=b.repeat(" ",d/2);return e+a+f},"default":function(a,b){return a?a:b},escape:function(a){return a.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")},first:function(a){return a[0]},groupby:function(a,c){return b.groupBy(a,c)},indent:function(a,c,d){c=c||4;var e="",f=a.split("\n"),g=b.repeat(" ",c);for(var h=0;h<f.length;h++)h==0&&!d?e+=f[h]+"\n":e+=g+f[h]+"\n";return e},join:function(a,c,d){return c=c||"",d&&(a=b.map(a,function(a){return a[d]})),a.join(c)},last:function(a){return a[a.length-1]},length:function(a){return a.length},list:function(a){if(b.isString(a))return a.split("");if(b.isObject(a)){var c=[];if(Object.keys)c=Object.keys(a);else for(var d in a)c.push(d);return b.map(c,function(b){return{key:b,value:a[b]}})}throw new b.TemplateError("list filter: type not iterable")},lower:function(a){return a.toLowerCase()},random:function(a){var b=Math.floor(Math.random()*a.length);return b==a.length&&b--,a[b]},replace:function(a,b,c,d){var e=a,f=e,g=1;e=e.replace(b,c);while(f!=e){if(g>=d)break;f=e,e=e.replace(b,c),g++}return e},reverse:function(a){var d;return b.isString(a)?d=c.list(a):d=b.map(a,function(a){return a}),d.reverse(),b.isString(a)?d.join(""):d},round:function(a,b,c){b=b||0;var d=Math.pow(10,b),e;return c=="ceil"?e=Math.ceil:c=="floor"?e=Math.floor:e=Math.round,e(a*d)/d},slice:function(a,b,c){var d=Math.floor(a.length/b),e=a.length%b,f=0,g=[];for(var h=0;h<b;h++){var i=f+h*d;h<e&&f++;var j=f+(h+1)*d,k=a.slice(i,j);c&&h>=e&&k.push(c),g.push(k)}return g},sort:function(a,c,d,e){return a=b.map(a,function(a){return a}),a.sort(function(a,f){var g,h;return e?(g=a[e],h=f[e]):(g=a,h=f),!d&&b.isString(g)&&b.isString(h)&&(g=g.toLowerCase(),h=h.toLowerCase()),g<h?c?1:-1:g>h?c?-1:1:0}),a},string:function(a){return a.toString()},title:function(a){return a.toUpperCase()},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},upper:function(a){return a.toUpperCase()},wordcount:function(a){return a.match(/\w+/g).length},"float":function(a,b){return parseFloat(a)||b},"int":function(a,b){return parseInt(a)||b}};c.d=c.default,c.e=c.escape,a.filters=c}(),function(){function d(a,b,c){return function(){var d=g(arguments),e,h=f(arguments);if(d>a.length){e=Array.prototype.slice.call(arguments,0,a.length);var i=Array.prototype.slice.call(arguments,e.length,d);for(var j=0;j<i.length;j++)j<b.length&&(h[b[j]]=i[j]);e.push(h)}else if(d<a.length){e=Array.prototype.slice.call(arguments,0,d);for(var j=d;j<a.length;j++){var k=a[j];e.push(h[k]),delete h[k]}e.push(h)}else e=arguments;return c.apply(this,e)}}function e(a){return a.__keywords=!0,a}function f(a){return a.length&&a[a.length-1].__keywords?a[a.length-1]:{}}function g(a){return a.length===0?0:a[a.length-1].__keywords?a.length-1:a.length}function h(a){return a!==undefined&&a!==null?a:""}function i(a,b){return a=a||{},b=a[b],typeof b=="function"?function(){return h(b.apply(a,arguments))}:h(b)}function j(a,b,c){var d=a.lookup(c);return d!==undefined&&d!==null?d:b.lookup(c)}var b=a.object,c=b.extend({init:function(a){this.variables={},this.parent=a},set:function(a,b){var c=a.split("."),d=this.variables;for(var e=0;e<c.length-1;e++){var f=c[e];d[f]||(d[f]={}),d=d[f]}d[c[c.length-1]]=b},lookup:function(a){var b=this.parent,c=this.variables[a];return c!==undefined&&c!==null?c:b&&b.lookup(a)},push:function(){return new c(this)},pop:function(){return this.parent}});a.runtime={Frame:c,makeMacro:d,makeKeywordArgs:e,numArgs:g,suppressValue:h,suppressLookupValue:i,contextOrFrameLookup:j}}(),function(){var b=a.lib,c=a.object,d=a.lexer,e=a.compiler,f=a.filters,g=a.loaders,h=a.runtime,i=h.Frame,j=c.extend({init:function(a,c,e){this.dev=e,a?this.loaders=b.isArray(a)?a:[a]:g.FileSystemLoader?this.loaders=[new g.FileSystemLoader]:this.loaders=[new g.HttpLoader("/views")],c&&d.setTags(c),this.filters=f,this.cache={}},tryTemplate:function(a,c){try{return c()}catch(d){d.Update||(d=b.TemplateError(d)),d.Update(a);if(!this.dev){var e=d;d=new Error(e.message),d.name=e.name}throw d}},addFilter:function(a,b){this.filters[a]=b},getFilter:function(a){if(!this.filters[a])throw new Error("filter not found: "+a);return this.filters[a]},getTemplate:function(a,b){var c=null,d=this.cache[a],e;if(typeof a!="string")throw new Error("template names must be a string: "+a);if(!d||!d.isUpToDate()){for(var f=0;f<this.loaders.length;f++)if(c=this.loaders[f].getSource(a))break;if(!c)throw new Error("template not found: "+a);this.cache[a]=new l(c.src,this,c.path,c.upToDate,b)}return this.cache[a]},registerPrecompiled:function(a){for(var b in a)this.cache[b]=new l({type:"code",obj:a[b]},this,b,function(){return!0},!0)},express:function(c){var d=this;if(c.render)c.render=function(a,c,e){var f={};b.isFunction(c)&&(e=c,c={}),f=b.extend(f,this.locals),c._locals&&(f=b.extend(f,c._locals)),f=b.extend(f,c);var g=d.render(a,f);e(null,g)};else{var e=a.http,f=e.ServerResponse.prototype;f._render=function(a,c,e){var f=this.app,g={};this._locals&&(g=b.extend(g,this._locals)),c&&(g=b.extend(g,c),c.locals&&(g=b.extend(g,c.locals))),g=b.extend(g,f._locals);var h=d.render(a,g);e?e(null,h):this.send(h)}}},render:function(a,b){return this.getTemplate(a).render(b)}}),k=c.extend({init:function(a,b){this.ctx=a,this.blocks={},this.exported=[];for(var c in b)this.addBlock(c,b[c])},lookup:function(a){return this.ctx[a]},setVariable:function(a,b){this.ctx[a]=b},getVariables:function(){return this.ctx},addBlock:function(a,b){this.blocks[a]=this.blocks[a]||[],this.blocks[a].push(b)},getBlock:function(a){if(!this.blocks[a])throw new Error('unknown block "'+a+'"');return this.blocks[a][0]},getSuper:function(a,b,c){var d=(this.blocks[b]||[]).indexOf(c),e=this.blocks[b][d+1],f=this;return function(){if(d==-1||!e)throw new Error('no super block available for "'+b+'"');return e(a,f)}},addExport:function(a){this.exported.push(a)},getExported:function(){var a={};for(var b=0;b<this.exported.length;b++){var c=this.exported[b];a[c]=this.ctx[c]}return a}}),l=c.extend({init:function(a,c,d,e,f){this.env=c||new j;if(b.isObject(a))switch(a.type){case"code":this.tmplProps=a.obj;break;case"string":this.tmplStr=a.obj}else{if(!b.isString(a))throw new Error("src must be a string or an object describing the source");this.tmplStr=a}this.path=d,this.upToDate=e||function(){return!1};if(f){var g=this;this.env.tryTemplate(this.path,function(){g._compile()}),g=null}else this.compiled=!1},render:function(a,b){var c=this,d=function(){c.compiled||c._compile();var d=new k(a||{},c.blocks);return c.rootRenderFunc(c.env,d,b||new i,h)};return this.env.tryTemplate(this.path,d)},isUpToDate:function(){return this.upToDate()},getExported:function(){this.compiled||this._compile();var a=new k({},this.blocks);return this.rootRenderFunc(this.env,a,new i,h),a.getExported()},_compile:function(){var a;if(this.tmplProps)a=this.tmplProps;else{var b=new Function(e.compile(this.tmplStr,this.env));a=b()}this.blocks=this._getBlocks(a),this.rootRenderFunc=a.root,this.compiled=!0},_getBlocks:function(a){var b={};for(var c in a)c.slice(0,2)=="b_"&&(b[c.slice(2)]=a[c]);return b}});a.environment={Environment:j,Template:l}}();var b=a.environment,c=a.compiler,d=a.parser,e=a.lexer,f=a.loaders;window.nunjucks={},window.nunjucks.Environment=b.Environment,window.nunjucks.Template=b.Template,f&&(f.FileSystemLoader?window.nunjucks.FileSystemLoader=f.FileSystemLoader:window.nunjucks.HttpLoader=f.HttpLoader),window.nunjucks.compiler=c,window.nunjucks.parser=d,window.nunjucks.lexer=e,window.nunjucks.require=function(b){return a[b]}})(); |
@@ -68,2 +68,41 @@ (function() { | ||
exports.TemplateError = function(message, lineno, colno) { | ||
var self = this; | ||
if (message instanceof Error) { // for casting regular js errors | ||
self = message; | ||
message = message.name + ": " + message.message; | ||
} else { | ||
Error.captureStackTrace(self); | ||
} | ||
self.name = "Template render error"; | ||
self.message = message; | ||
self.lineno = lineno; | ||
self.colno = colno; | ||
self.firstUpdate = true; | ||
self.Update = function(path) { | ||
var message = "(" + (path || "unknown path") + ")"; | ||
// only show lineno + colno next to path of template | ||
// where error occurred | ||
if (this.firstUpdate && this.lineno && this.colno) { | ||
message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']'; | ||
} | ||
message += '\n '; | ||
if (this.firstUpdate) { | ||
message += ' '; | ||
} | ||
this.message = message + (this.message || ''); | ||
this.firstUpdate = false; | ||
return this; | ||
}; | ||
return self; | ||
}; | ||
exports.TemplateError.prototype = Error.prototype; | ||
exports.isFunction = function(obj) { | ||
@@ -301,3 +340,3 @@ return ObjProto.toString.call(obj) == '[object Function]'; | ||
else { | ||
throw new Error("list: type not iterable"); | ||
throw new lib.TemplateError("list filter: type not iterable"); | ||
} | ||
@@ -458,3 +497,3 @@ }, | ||
return parseInt(val) || def; | ||
}, | ||
} | ||
}; | ||
@@ -501,3 +540,7 @@ | ||
var p = this.parent; | ||
return this.variables[name] || (p && p.lookup(name)); | ||
var val = this.variables[name]; | ||
if(val !== undefined && val !== null) { | ||
return val; | ||
} | ||
return p && p.lookup(name); | ||
}, | ||
@@ -581,2 +624,27 @@ | ||
function suppressValue(val) { | ||
return (val !== undefined && val !== null) ? val : ""; | ||
} | ||
function suppressLookupValue(obj, val) { | ||
obj = obj || {}; | ||
val = obj[val]; | ||
if(typeof val === 'function') { | ||
return function() { | ||
return suppressValue(val.apply(obj, arguments)); | ||
}; | ||
} | ||
else { | ||
return suppressValue(val); | ||
} | ||
} | ||
function contextOrFrameLookup(context, frame, name) { | ||
var val = context.lookup(name); | ||
return (val !== undefined && val !== null) ? | ||
val : | ||
frame.lookup(name); | ||
} | ||
modules['runtime'] = { | ||
@@ -586,3 +654,6 @@ Frame: Frame, | ||
makeKeywordArgs: makeKeywordArgs, | ||
numArgs: numArgs | ||
numArgs: numArgs, | ||
suppressValue: suppressValue, | ||
suppressLookupValue: suppressLookupValue, | ||
contextOrFrameLookup: contextOrFrameLookup | ||
}; | ||
@@ -601,3 +672,10 @@ })(); | ||
var Environment = Object.extend({ | ||
init: function(loaders, tags) { | ||
init: function(loaders, tags, dev) { | ||
// The dev flag determines the trace that'll be shown on errors. | ||
// If set to true, returns the full trace from the error point, | ||
// otherwise will return trace starting from Template.render | ||
// (the full trace from within nunjucks may confuse developers using | ||
// the library) | ||
this.dev = dev; | ||
if(!loaders) { | ||
@@ -624,2 +702,23 @@ // The filesystem loader is only available client-side | ||
tryTemplate: function(path, func) { | ||
try { | ||
return func(); | ||
} catch (e) { | ||
if (!e.Update) { | ||
// not one of ours, cast it | ||
e = lib.TemplateError(e); | ||
} | ||
e.Update(path); | ||
// Unless they marked the dev flag, show them a trace from here | ||
if (!this.dev) { | ||
var old = e; | ||
e = new Error(old.message); | ||
e.name = old.name; | ||
} | ||
throw e; | ||
} | ||
}, | ||
addFilter: function(name, func) { | ||
@@ -630,2 +729,5 @@ this.filters[name] = func; | ||
getFilter: function(name) { | ||
if(!this.filters[name]) { | ||
throw new Error('filter not found: ' + name); | ||
} | ||
return this.filters[name]; | ||
@@ -639,2 +741,6 @@ }, | ||
if(typeof name !== 'string') { | ||
throw new Error('template names must be a string: ' + name); | ||
} | ||
if(!tmpl || !tmpl.isUpToDate()) { | ||
@@ -675,21 +781,56 @@ for(var i=0; i<this.loaders.length; i++) { | ||
app.render = function(name, ctx, k) { | ||
var context = {}; | ||
if(app.render) { | ||
// Express >2.5.11 | ||
app.render = function(name, ctx, k) { | ||
var context = {}; | ||
if(lib.isFunction(ctx)) { | ||
k = ctx; | ||
ctx = {}; | ||
} | ||
if(lib.isFunction(ctx)) { | ||
k = ctx; | ||
ctx = {}; | ||
} | ||
context = lib.extend(context, app.locals); | ||
context = lib.extend(context, this.locals); | ||
if(ctx._locals) { | ||
context = lib.extend(context, ctx._locals); | ||
} | ||
if(ctx._locals) { | ||
context = lib.extend(context, ctx._locals); | ||
} | ||
context = lib.extend(context, ctx); | ||
context = lib.extend(context, ctx); | ||
var res = env.render(name, context); | ||
k(null, res); | ||
}; | ||
var res = env.render(name, context); | ||
k(null, res); | ||
}; | ||
} | ||
else { | ||
// Express <2.5.11 | ||
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); | ||
} | ||
}; | ||
} | ||
}, | ||
@@ -788,3 +929,5 @@ | ||
if(eagerCompile) { | ||
this._compile(); | ||
var self = this; | ||
this.env.tryTemplate(this.path, function() { self._compile(); }); | ||
self = null; | ||
} | ||
@@ -797,11 +940,17 @@ else { | ||
render: function(ctx, frame) { | ||
if(!this.compiled) { | ||
this._compile(); | ||
} | ||
var self = this; | ||
var context = new Context(ctx || {}, this.blocks); | ||
return this.rootRenderFunc(this.env, | ||
context, | ||
frame || new Frame(), | ||
runtime); | ||
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 this.env.tryTemplate(this.path, render); | ||
}, | ||
@@ -884,8 +1033,11 @@ | ||
if(loaders.FileSystemLoader) { | ||
window.nunjucks.FileSystemLoader = loaders.FileSystemLoader; | ||
// loaders is not available when using precompiled templates | ||
if(loaders) { | ||
if(loaders.FileSystemLoader) { | ||
window.nunjucks.FileSystemLoader = loaders.FileSystemLoader; | ||
} | ||
else { | ||
window.nunjucks.HttpLoader = loaders.HttpLoader; | ||
} | ||
} | ||
else { | ||
window.nunjucks.HttpLoader = loaders.HttpLoader; | ||
} | ||
@@ -892,0 +1044,0 @@ window.nunjucks.compiler = compiler; |
13
index.js
@@ -12,8 +12,11 @@ | ||
if(loaders.FileSystemLoader) { | ||
module.exports.FileSystemLoader = loaders.FileSystemLoader; | ||
// loaders is not available when using precompiled templates | ||
if(loaders) { | ||
if(loaders.FileSystemLoader) { | ||
module.exports.FileSystemLoader = loaders.FileSystemLoader; | ||
} | ||
else { | ||
module.exports.HttpLoader = loaders.HttpLoader; | ||
} | ||
} | ||
else { | ||
module.exports.HttpLoader = loaders.HttpLoader; | ||
} | ||
@@ -20,0 +23,0 @@ module.exports.compiler = compiler; |
{ | ||
"name": "nunjucks", | ||
"description": "A jinja inspired templating engine", | ||
"version": "0.1.7", | ||
"version": "0.1.8", | ||
"author": { | ||
@@ -6,0 +6,0 @@ "name": "James Long", |
@@ -23,3 +23,3 @@ | ||
The current version is v0.1.6 ([changelog](http://nunjucks.tumblr.com/post/35641526923/v0-1-6-undefined-handling-bugfixes)). | ||
The current version is v0.1.7 ([changelog](http://nunjucks.tumblr.com/post/37795552313/v0-1-7-helpful-errors-many-bug-fixes)). | ||
@@ -26,0 +26,0 @@ ## Documentation |
@@ -30,3 +30,3 @@ | ||
function quotedArray(arr) { | ||
return '[' + | ||
return '[' + | ||
lib.map(arr, function(x) { return '"' + x + '"'; }) + | ||
@@ -67,3 +67,6 @@ ']'; | ||
this.emitLine('function ' + name + '(env, context, frame, runtime) {'); | ||
this.emitLine('var lineno = null;'); | ||
this.emitLine('var colno = null;'); | ||
this.emitLine('var ' + this.buffer + ' = "";'); | ||
this.emitLine('try {'); | ||
}, | ||
@@ -76,3 +79,6 @@ | ||
this.emitLine('} catch (e) {'); | ||
this.emitLine(' runtime.handleError(e, lineno, colno);'); | ||
this.emitLine('}'); | ||
this.emitLine('}'); | ||
this.buffer = null; | ||
@@ -180,5 +186,4 @@ }, | ||
else { | ||
this.emit('runtime.suppressValue(' + | ||
'runtime.contextOrFrameLookup(' + | ||
'context, frame, "' + name + '"))'); | ||
this.emit('runtime.contextOrFrameLookup(' + | ||
'context, frame, "' + name + '")'); | ||
} | ||
@@ -276,6 +281,16 @@ }, | ||
compileFunCall: function(node, frame) { | ||
// Keep track of line/col info at runtime by settings | ||
// variables within an expression. An expression in javascript | ||
// like (x, y, z) returns the last value, and x and y can be | ||
// anything | ||
this.emit('(lineno = ' + node.lineno + | ||
', colno = ' + node.colno + ', '); | ||
this.emit('('); | ||
this._compileExpression(node.name, frame); | ||
this.emit(')'); | ||
this._compileAggregate(node.args, frame, '(', ')'); | ||
this.emit(')'); | ||
}, | ||
@@ -351,3 +366,41 @@ | ||
if(node.name instanceof nodes.Array) { | ||
// key/value iteration | ||
// key/value iteration. the user could have passed a dict | ||
// amd two elements to be unpacked - "for k,v in { a: b }" | ||
// or they could have passed an array of arrays - | ||
// for a,b,c in [[a,b,c],[c,d,e]] where the number of | ||
// elements to be unpacked is variable. | ||
// | ||
// we cant known in advance which has been passed so we | ||
// have to emit code that handles both cases | ||
this.emitLine('var ' + i + ';'); | ||
// did they pass an array of tuples or a dict? | ||
this.emitLine('if (runtime.isArray(' + arr + ')) {'); | ||
// array of tuples | ||
this.emitLine('for (' + i + '=0; ' + i + ' < ' + arr + '.length; ' | ||
+ i + '++) {'); | ||
// create one frame var for each element in the unpacking expr | ||
for (var u=0; u < node.name.children.length; u++) { | ||
var tid = this.tmpid(); | ||
this.emitLine('var ' + tid + ' = ' + arr + '[' + i + '][' + u + ']'); | ||
this.emitLine('frame.set("' + node.name.children[u].value | ||
+ '", ' + arr + '[' + i + '][' + u + ']' + ');'); | ||
frame.set(node.name.children[u].value, tid); | ||
} | ||
this.emitLine('frame.set("loop.index", ' + i + ' + 1);'); | ||
this.emitLine('frame.set("loop.index0", ' + i + ');'); | ||
this.emitLine('frame.set("loop.first", ' + i + ' === 0);'); | ||
this.compile(node.body, frame); | ||
this.emitLine('}'); // end for | ||
this.emitLine('} else {'); | ||
// caller passed a dict | ||
this.emitLine(i + ' = -1;'); | ||
var key = node.name.children[0]; | ||
@@ -361,3 +414,2 @@ var val = node.name.children[1]; | ||
this.emitLine('var ' + i + ' = -1;'); | ||
this.emitLine('for(var ' + k + ' in ' + arr + ') {'); | ||
@@ -371,2 +423,7 @@ this.emitLine(i + '++;'); | ||
this.emitLine('frame.set("loop.first", ' + i + ' === 0);'); | ||
this.compile(node.body, frame); | ||
this.emitLine('}'); // end for | ||
this.emitLine('}'); // end if | ||
} | ||
@@ -390,6 +447,8 @@ else { | ||
this.emitLine('frame.set("loop.length", ' + arr + '.length);'); | ||
this.compile(node.body, frame); | ||
this.emitLine('}'); | ||
} | ||
this.compile(node.body, frame); | ||
this.emitLine('}'); | ||
@@ -445,3 +504,3 @@ this.emitLine('frame = frame.pop();'); | ||
}, this); | ||
// Expose the keyword arguments | ||
@@ -454,3 +513,3 @@ if(kwargs) { | ||
'kwargs["' + name + '"] : '); | ||
this._compileExpression(pair.value); | ||
this._compileExpression(pair.value, frame); | ||
this.emitLine(');'); | ||
@@ -593,5 +652,5 @@ }, this); | ||
compileOutput: function(node, frame) { | ||
this.emit(this.buffer + ' += '); | ||
this.emit(this.buffer + ' += runtime.suppressValue('); | ||
this._compileChildren(node, frame); | ||
this.emit(';\n'); | ||
this.emit(');\n'); | ||
}, | ||
@@ -623,2 +682,3 @@ | ||
'b_' + name + ', ' + | ||
'frame, ' + | ||
'runtime);'); | ||
@@ -629,3 +689,2 @@ | ||
this.compile(block.body, tmpFrame); | ||
this.emitFuncEnd(); | ||
@@ -656,3 +715,3 @@ } | ||
getCode: function() { | ||
return this.codebuf.join(""); | ||
return this.codebuf.join(''); | ||
} | ||
@@ -663,3 +722,5 @@ }); | ||
// var c = new Compiler(); | ||
// var src = '{{ foo }}'; | ||
// //var src = '{{ foo({a:1}) }}'; | ||
// var src = '{% extends "base.html" %}' + | ||
// '{% block block1 %}{{ super() }}BAR{% endblock %}'; | ||
@@ -666,0 +727,0 @@ // var ns = parser.parse(src); |
@@ -40,23 +40,2 @@ var lib = require('./lib'); | ||
tryTemplate: function(path, func) { | ||
try { | ||
return func(); | ||
} catch (e) { | ||
if (!e.Update) { | ||
// not one of ours, cast it | ||
e = lib.TemplateError(e); | ||
} | ||
e.Update(path); | ||
// Unless they marked the dev flag, show them a trace from here | ||
if (!this.dev) { | ||
var old = e; | ||
e = new Error(old.message); | ||
e.name = old.name; | ||
} | ||
throw e; | ||
} | ||
}, | ||
addFilter: function(name, func) { | ||
@@ -214,3 +193,3 @@ this.filters[name] = func; | ||
getSuper: function(env, name, block) { | ||
getSuper: function(env, name, block, frame, runtime) { | ||
var idx = (this.blocks[name] || []).indexOf(block); | ||
@@ -225,3 +204,3 @@ var blk = this.blocks[name][idx + 1]; | ||
return blk(env, context); | ||
return blk(env, context, frame, runtime); | ||
}; | ||
@@ -266,5 +245,6 @@ }, | ||
if(eagerCompile) { | ||
var self = this; | ||
this.env.tryTemplate(this.path, function() { self._compile(); }); | ||
self = null; | ||
var _this = this; | ||
lib.withPrettyErrors(this.path, | ||
this.env.dev, | ||
function() { _this._compile(); }); | ||
} | ||
@@ -291,3 +271,4 @@ else { | ||
}; | ||
return this.env.tryTemplate(this.path, render); | ||
return lib.withPrettyErrors(this.path, this.env.dev, render); | ||
}, | ||
@@ -294,0 +275,0 @@ |
@@ -53,6 +53,46 @@ | ||
default: function(val, def) { | ||
'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) { | ||
// deliberately include properties from the object's prototype | ||
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) { | ||
@@ -284,8 +324,10 @@ return str.replace(/&/g, '&') | ||
float: function(val, def) { | ||
return parseFloat(val) || def; | ||
'float': function(val, def) { | ||
var res = parseFloat(val); | ||
return isNaN(res) ? def : res; | ||
}, | ||
int: function(val, def) { | ||
return parseInt(val) || def; | ||
'int': function(val, def) { | ||
var res = parseInt(val, 10); | ||
return isNaN(res) ? def : res; | ||
} | ||
@@ -295,5 +337,5 @@ }; | ||
// Aliases | ||
filters.d = filters.default; | ||
filters.d = filters['default']; | ||
filters.e = filters.escape; | ||
module.exports = filters; |
@@ -77,3 +77,4 @@ | ||
} | ||
else if((tok = this._extractString(BLOCK_END))) { | ||
else if((tok = this._extractString(BLOCK_END)) || | ||
(tok = this._extractString('-' + BLOCK_END))) { | ||
// Special check for the block end tag | ||
@@ -159,3 +160,4 @@ // | ||
} | ||
else if((tok = this._extractString(BLOCK_START))) { | ||
else if((tok = this._extractString(BLOCK_START + '-')) || | ||
(tok = this._extractString(BLOCK_START))) { | ||
this.in_code = true; | ||
@@ -162,0 +164,0 @@ return token(TOKEN_BLOCK_START, tok, lineno, colno); |
@@ -6,19 +6,40 @@ var ArrayProto = Array.prototype; | ||
exports.withPrettyErrors = function(path, withInternals, func) { | ||
try { | ||
return func(); | ||
} catch (e) { | ||
if (!e.Update) { | ||
// not one of ours, cast it | ||
e = new exports.TemplateError(e); | ||
} | ||
e.Update(path); | ||
// Unless they marked the dev flag, show them a trace from here | ||
if (!withInternals) { | ||
var old = e; | ||
e = new Error(old.message); | ||
e.name = old.name; | ||
} | ||
throw e; | ||
} | ||
} | ||
exports.TemplateError = function(message, lineno, colno) { | ||
var self = this; | ||
var err = this; | ||
if (message instanceof Error) { // for casting regular js errors | ||
self = message; | ||
err = message; | ||
message = message.name + ": " + message.message; | ||
} else { | ||
Error.captureStackTrace(self); | ||
Error.captureStackTrace(err); | ||
} | ||
self.name = "Template render error"; | ||
self.message = message; | ||
self.lineno = lineno; | ||
self.colno = colno; | ||
self.firstUpdate = true; | ||
err.name = "Template render error"; | ||
err.message = message; | ||
err.lineno = lineno; | ||
err.colno = colno; | ||
err.firstUpdate = true; | ||
self.Update = function(path) { | ||
err.Update = function(path) { | ||
var message = "(" + (path || "unknown path") + ")"; | ||
@@ -28,4 +49,9 @@ | ||
// where error occurred | ||
if (this.firstUpdate && this.lineno && this.colno) { | ||
message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']'; | ||
if (this.firstUpdate) { | ||
if(this.lineno && this.colno) { | ||
message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']'; | ||
} | ||
else if(this.lineno) { | ||
message += ' [Line ' + this.lineno + ']'; | ||
} | ||
} | ||
@@ -42,7 +68,8 @@ | ||
}; | ||
return self; | ||
return err; | ||
}; | ||
exports.TemplateError.prototype = Error.prototype; | ||
exports.isFunction = function(obj) { | ||
@@ -49,0 +76,0 @@ return ObjProto.toString.call(obj) == '[object Function]'; |
@@ -12,3 +12,5 @@ var fs = require('fs'); | ||
if(searchPaths) { | ||
this.searchPaths = lib.isArray(searchPaths) ? searchPaths : [searchPaths]; | ||
searchPaths = lib.isArray(searchPaths) ? searchPaths : [searchPaths]; | ||
// For windows, convert to forward slashes | ||
this.searchPaths = searchPaths.map(path.normalize); | ||
} | ||
@@ -18,2 +20,3 @@ else { | ||
} | ||
}, | ||
@@ -24,3 +27,2 @@ | ||
var paths = this.searchPaths.concat(['', __dirname]); | ||
for(var i=0; i<paths.length; i++) { | ||
@@ -27,0 +29,0 @@ var p = path.join(paths[i], name); |
@@ -12,2 +12,3 @@ | ||
this.breakOnBlocks = null; | ||
this.dropLeadingWhitespace = false; | ||
}, | ||
@@ -116,3 +117,10 @@ | ||
if(!this.skip(lexer.TOKEN_BLOCK_END)) { | ||
var tok = this.nextToken(); | ||
if(tok.type == lexer.TOKEN_BLOCK_END) { | ||
if(tok.value.charAt(0) === '-') { | ||
this.dropLeadingWhitespace = true; | ||
} | ||
} | ||
else { | ||
this.fail("expected block end in " + name + " statement"); | ||
@@ -142,3 +150,4 @@ } | ||
if(this.skip(lexer.TOKEN_COMMA)) { | ||
var type = this.peekToken().type; | ||
if(type == lexer.TOKEN_COMMA) { | ||
// key/value iteration | ||
@@ -148,3 +157,7 @@ var key = node.name; | ||
node.name.addChild(key); | ||
node.name.addChild(this.parsePrimary()); | ||
while(this.skip(lexer.TOKEN_COMMA)) { | ||
var prim = this.parsePrimary(); | ||
node.name.addChild(prim); | ||
} | ||
} | ||
@@ -234,4 +247,4 @@ | ||
while(1) { | ||
var type = this.peekToken().type; | ||
if(type == lexer.TOKEN_BLOCK_END) { | ||
var nextTok = this.peekToken(); | ||
if(nextTok.type == lexer.TOKEN_BLOCK_END) { | ||
if(!names.children.length) { | ||
@@ -243,2 +256,9 @@ this.fail('parseFrom: Expected at least one import name', | ||
// 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) == '-') { | ||
this.dropLeadingWhitespace = true; | ||
} | ||
this.nextToken(); | ||
@@ -466,3 +486,10 @@ break; | ||
return new nodes.TemplateData(begun.lineno, begun.colno, str); | ||
var output = new nodes.Output( | ||
begun.lineno, | ||
begun.colno, | ||
[new nodes.TemplateData(begun.lineno, begun.colno, str)] | ||
); | ||
return output; | ||
}, | ||
@@ -928,2 +955,23 @@ | ||
if(tok.type == lexer.TOKEN_DATA) { | ||
var data = tok.value; | ||
var nextToken = this.peekToken(); | ||
var nextVal = nextToken && nextToken.value; | ||
// If the last token has "-" we need to trim the | ||
// leading whitespace of the data. This is marked with | ||
// the `dropLeadingWhitespace` variable. | ||
if(this.dropLeadingWhitespace) { | ||
// TODO: this could be optimized (don't use regex) | ||
data = data.replace(/^\s*/, ''); | ||
this.dropLeadingWhitespace = false; | ||
} | ||
// Same for the succeding block start token | ||
if(nextToken && | ||
nextToken.type == lexer.TOKEN_BLOCK_START && | ||
nextVal.charAt(nextVal.length - 1) == '-') { | ||
// TODO: this could be optimized (don't use regex) | ||
data = data.replace(/\s*$/, ''); | ||
} | ||
buf.push(new nodes.Output(tok.lineno, | ||
@@ -933,3 +981,3 @@ tok.colno, | ||
tok.colno, | ||
tok.value)])); | ||
data)])); | ||
} | ||
@@ -967,5 +1015,5 @@ else if(tok.type == lexer.TOKEN_BLOCK_START) { | ||
var util = require('util'); | ||
// var util = require('util'); | ||
// var l = lexer.lex('{% set x = 3 %}'); | ||
// var l = lexer.lex('{%- if x -%}\n hello {% endif %}'); | ||
// var t; | ||
@@ -976,3 +1024,3 @@ // while((t = l.nextToken())) { | ||
// var p = new Parser(lexer.lex('{{ foo(1, 2, 3, foo=3) }}')); | ||
// var p = new Parser(lexer.lex('{% from x import y -%}\n hi \n')); | ||
// var n = p.parse(); | ||
@@ -979,0 +1027,0 @@ // nodes.printNodes(n); |
@@ -1,2 +0,2 @@ | ||
var lib = require('./lib'); | ||
var Object = require('./object'); | ||
@@ -33,3 +33,7 @@ | ||
var p = this.parent; | ||
return this.variables[name] || (p && p.lookup(name)); | ||
var val = this.variables[name]; | ||
if(val !== undefined && val !== null) { | ||
return val; | ||
} | ||
return p && p.lookup(name); | ||
}, | ||
@@ -138,2 +142,11 @@ | ||
function handleError(error, lineno, colno) { | ||
if(error.lineno) { | ||
throw error; | ||
} | ||
else { | ||
throw new lib.TemplateError(error, lineno, colno); | ||
} | ||
} | ||
module.exports = { | ||
@@ -146,3 +159,5 @@ Frame: Frame, | ||
suppressLookupValue: suppressLookupValue, | ||
contextOrFrameLookup: contextOrFrameLookup | ||
contextOrFrameLookup: contextOrFrameLookup, | ||
handleError: handleError, | ||
isArray: lib.isArray | ||
}; |
@@ -104,2 +104,7 @@ var should = require('should'); | ||
s = render('{% for a, b, c in arr %}' + | ||
'{{ a }},{{ b }},{{ c }}.{% endfor %}', | ||
{ arr: [['x', 'y', 'z'], ['1', '2', '3']] }); | ||
s.should.equal('x,y,z.1,2,3.'); | ||
s = render('{% for item in arr | batch(2) %}{{ item[0] }}{% endfor %}', | ||
@@ -166,3 +171,3 @@ { arr: ['a', 'b', 'c', 'd'] }); | ||
'{{ foo(1) }}'); | ||
s.should.equal('undefined'); | ||
s.should.equal(''); | ||
@@ -169,0 +174,0 @@ s = render('{% macro foo(x, y) %}{{ y }}{% endmacro %}' + |
@@ -8,3 +8,3 @@ | ||
var e = new env.Environment(new loaders.FileSystemLoader('views')); | ||
var e = new env.Environment(new loaders.FileSystemLoader('views'), null, true); | ||
e.express(app); | ||
@@ -11,0 +11,0 @@ |
@@ -1,1 +0,1 @@ | ||
(function(){var a={};(function(){function b(a,c,d){var e=Object.create(a.prototype),f=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;d=d||{};for(var g in d){var h=d[g],i=e[g];typeof i=="function"&&typeof h=="function"&&f.test(h)?e[g]=function(a,b){return function(){var c=this.parent;this.parent=b;var d=a.apply(this,arguments);return this.parent=c,d}}(h,i):e[g]=h}e.typename=c;var j=function(){e.init&&e.init.apply(this,arguments)};return j.prototype=e,j.prototype.constructor=j,j.extend=function(a,c){return typeof a=="object"&&(c=a,a="anonymous"),b(j,a,c)},j}a.object=b(Object,"Object",{})})(),function(){var b=Array.prototype,c=Object.prototype,d=a.lib={};d.isFunction=function(a){return c.toString.call(a)=="[object Function]"},d.isArray=Array.isArray||function(a){return c.toString.call(a)=="[object Array]"},d.isString=function(a){return c.toString.call(a)=="[object String]"},d.isObject=function(a){return a===Object(a)},d.groupBy=function(a,b){var c={},e=d.isFunction(b)?b:function(a){return a[b]};for(var f=0;f<a.length;f++){var g=a[f],h=e(g,f);(c[h]||(c[h]=[])).push(g)}return c},d.toArray=function(a){return Array.prototype.slice.call(a)},d.without=function(a){var b=[];if(!a)return b;var c=-1,e=a.length,f=d.toArray(arguments).slice(1);while(++c<e)f.indexOf(a[c])===-1&&b.push(a[c]);return b},d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.repeat=function(a,b){var c="";for(var d=0;d<b;d++)c+=a;return c},d.each=function(a,c,d){if(a==null)return;if(b.each&&a.each==b.each)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++)c.call(d,a[e],e,a)},d.map=function(a,c){var d=[];if(a==null)return d;if(b.map&&a.map===b.map)return a.map(c);for(var e=0;e<a.length;e++)d[d.length]=c(a[e],e);return a.length===+a.length&&(d.length=a.length),d}}(),function(){var b=a.lib,c={abs:function(a){return Math.abs(a)},batch:function(a,b,c){var d=[],e=[];for(var f=0;f<a.length;f++)f%b===0&&e.length&&(d.push(e),e=[]),e.push(a[f]);if(e.length){if(c)for(var f=e.length;f<b;f++)e.push(c);d.push(e)}return d},capitalize:function(a){return a=a.toLowerCase(),a[0].toUpperCase()+a.slice(1)},center:function(a,c){c=c||80;if(a.length>=c)return a;var d=c-a.length,e=b.repeat(" ",d/2-d%2),f=b.repeat(" ",d/2);return e+a+f},"default":function(a,b){return a?a:b},escape:function(a){return a.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")},first:function(a){return a[0]},groupby:function(a,c){return b.groupBy(a,c)},indent:function(a,c,d){c=c||4;var e="",f=a.split("\n"),g=b.repeat(" ",c);for(var h=0;h<f.length;h++)h==0&&!d?e+=f[h]+"\n":e+=g+f[h]+"\n";return e},join:function(a,c,d){return c=c||"",d&&(a=b.map(a,function(a){return a[d]})),a.join(c)},last:function(a){return a[a.length-1]},length:function(a){return a.length},list:function(a){if(b.isString(a))return a.split("");if(b.isObject(a)){var c=[];if(Object.keys)c=Object.keys(a);else for(var d in a)c.push(d);return b.map(c,function(b){return{key:b,value:a[b]}})}throw new Error("list: type not iterable")},lower:function(a){return a.toLowerCase()},random:function(a){var b=Math.floor(Math.random()*a.length);return b==a.length&&b--,a[b]},replace:function(a,b,c,d){var e=a,f=e,g=1;e=e.replace(b,c);while(f!=e){if(g>=d)break;f=e,e=e.replace(b,c),g++}return e},reverse:function(a){var d;return b.isString(a)?d=c.list(a):d=b.map(a,function(a){return a}),d.reverse(),b.isString(a)?d.join(""):d},round:function(a,b,c){b=b||0;var d=Math.pow(10,b),e;return c=="ceil"?e=Math.ceil:c=="floor"?e=Math.floor:e=Math.round,e(a*d)/d},slice:function(a,b,c){var d=Math.floor(a.length/b),e=a.length%b,f=0,g=[];for(var h=0;h<b;h++){var i=f+h*d;h<e&&f++;var j=f+(h+1)*d,k=a.slice(i,j);c&&h>=e&&k.push(c),g.push(k)}return g},sort:function(a,c,d,e){return a=b.map(a,function(a){return a}),a.sort(function(a,f){var g,h;return e?(g=a[e],h=f[e]):(g=a,h=f),!d&&b.isString(g)&&b.isString(h)&&(g=g.toLowerCase(),h=h.toLowerCase()),g<h?c?1:-1:g>h?c?-1:1:0}),a},string:function(a){return a.toString()},title:function(a){return a.toUpperCase()},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},upper:function(a){return a.toUpperCase()},wordcount:function(a){return a.match(/\w+/g).length},"float":function(a,b){return parseFloat(a)||b},"int":function(a,b){return parseInt(a)||b}};c.d=c.default,c.e=c.escape,a.filters=c}(),function(){function d(a,b,c){return function(){var d=g(arguments),e,h=f(arguments);if(d>a.length){e=Array.prototype.slice.call(arguments,0,a.length);var i=Array.prototype.slice.call(arguments,e.length,d);for(var j=0;j<i.length;j++)j<b.length&&(h[b[j]]=i[j]);e.push(h)}else if(d<a.length){e=Array.prototype.slice.call(arguments,0,d);for(var j=d;j<a.length;j++){var k=a[j];e.push(h[k]),delete h[k]}e.push(h)}else e=arguments;return c.apply(this,e)}}function e(a){return a.__keywords=!0,a}function f(a){return a.length&&a[a.length-1].__keywords?a[a.length-1]:{}}function g(a){return a.length===0?0:a[a.length-1].__keywords?a.length-1:a.length}var b=a.object,c=b.extend({init:function(a){this.variables={},this.parent=a},set:function(a,b){var c=a.split("."),d=this.variables;for(var e=0;e<c.length-1;e++){var f=c[e];d[f]||(d[f]={}),d=d[f]}d[c[c.length-1]]=b},lookup:function(a){var b=this.parent;return this.variables[a]||b&&b.lookup(a)},push:function(){return new c(this)},pop:function(){return this.parent}});a.runtime={Frame:c,makeMacro:d,makeKeywordArgs:e,numArgs:g}}(),function(){var b=a.lib,c=a.object,d=a.lexer,e=a.compiler,f=a.filters,g=a.loaders,h=a.runtime,i=h.Frame,j=c.extend({init:function(a,c){a?this.loaders=b.isArray(a)?a:[a]:g.FileSystemLoader?this.loaders=[new g.FileSystemLoader]:this.loaders=[new g.HttpLoader("/views")],c&&d.setTags(c),this.filters=f,this.cache={}},addFilter:function(a,b){this.filters[a]=b},getFilter:function(a){return this.filters[a]},getTemplate:function(a,b){var c=null,d=this.cache[a],e;if(!d||!d.isUpToDate()){for(var f=0;f<this.loaders.length;f++)if(c=this.loaders[f].getSource(a))break;if(!c)throw new Error("template not found: "+a);this.cache[a]=new l(c.src,this,c.path,c.upToDate,b)}return this.cache[a]},registerPrecompiled:function(a){for(var b in a)this.cache[b]=new l({type:"code",obj:a[b]},this,b,function(){return!0},!0)},express:function(a){var c=this;a.render=function(d,e,f){var g={};b.isFunction(e)&&(f=e,e={}),g=b.extend(g,a.locals),e._locals&&(g=b.extend(g,e._locals)),g=b.extend(g,e);var h=c.render(d,g);f(null,h)}},render:function(a,b){return this.getTemplate(a).render(b)}}),k=c.extend({init:function(a,b){this.ctx=a,this.blocks={},this.exported=[];for(var c in b)this.addBlock(c,b[c])},lookup:function(a){return this.ctx[a]},setVariable:function(a,b){this.ctx[a]=b},getVariables:function(){return this.ctx},addBlock:function(a,b){this.blocks[a]=this.blocks[a]||[],this.blocks[a].push(b)},getBlock:function(a){if(!this.blocks[a])throw new Error('unknown block "'+a+'"');return this.blocks[a][0]},getSuper:function(a,b,c){var d=(this.blocks[b]||[]).indexOf(c),e=this.blocks[b][d+1],f=this;return function(){if(d==-1||!e)throw new Error('no super block available for "'+b+'"');return e(a,f)}},addExport:function(a){this.exported.push(a)},getExported:function(){var a={};for(var b=0;b<this.exported.length;b++){var c=this.exported[b];a[c]=this.ctx[c]}return a}}),l=c.extend({init:function(a,c,d,e,f){this.env=c||new j;if(b.isObject(a))switch(a.type){case"code":this.tmplProps=a.obj;break;case"string":this.tmplStr=a.obj}else{if(!b.isString(a))throw new Error("src must be a string or an object describing the source");this.tmplStr=a}this.path=d,this.upToDate=e||function(){return!1},f?this._compile():this.compiled=!1},render:function(a,b){this.compiled||this._compile();var c=new k(a||{},this.blocks);return this.rootRenderFunc(this.env,c,b||new i,h)},isUpToDate:function(){return this.upToDate()},getExported:function(){this.compiled||this._compile();var a=new k({},this.blocks);return this.rootRenderFunc(this.env,a,new i,h),a.getExported()},_compile:function(){var a;if(this.tmplProps)a=this.tmplProps;else{var b=new Function(e.compile(this.tmplStr,this.env));a=b()}this.blocks=this._getBlocks(a),this.rootRenderFunc=a.root,this.compiled=!0},_getBlocks:function(a){var b={};for(var c in a)c.slice(0,2)=="b_"&&(b[c.slice(2)]=a[c]);return b}});a.environment={Environment:j,Template:l}}();var b=a.environment,c=a.compiler,d=a.parser,e=a.lexer,f=a.loaders;window.nunjucks={},window.nunjucks.Environment=b.Environment,window.nunjucks.Template=b.Template,f.FileSystemLoader?window.nunjucks.FileSystemLoader=f.FileSystemLoader:window.nunjucks.HttpLoader=f.HttpLoader,window.nunjucks.compiler=c,window.nunjucks.parser=d,window.nunjucks.lexer=e,window.nunjucks.require=function(b){return a[b]}})(); | ||
(function(){var a={};(function(){function b(a,c,d){var e=Object.create(a.prototype),f=/xyz/.test(function(){xyz})?/\bparent\b/:/.*/;d=d||{};for(var g in d){var h=d[g],i=e[g];typeof i=="function"&&typeof h=="function"&&f.test(h)?e[g]=function(a,b){return function(){var c=this.parent;this.parent=b;var d=a.apply(this,arguments);return this.parent=c,d}}(h,i):e[g]=h}e.typename=c;var j=function(){e.init&&e.init.apply(this,arguments)};return j.prototype=e,j.prototype.constructor=j,j.extend=function(a,c){return typeof a=="object"&&(c=a,a="anonymous"),b(j,a,c)},j}a.object=b(Object,"Object",{})})(),function(){var b=Array.prototype,c=Object.prototype,d={"&":"&",'"':""","'":"'","<":"<",">":">"},e=function(a){return d[a]},f=a.lib={};f.TemplateError=function(a,b,c){var d=this;return a instanceof Error?(d=a,a=a.name+": "+a.message):Error.captureStackTrace(d),d.name="Template render error",d.message=a,d.lineno=b,d.colno=c,d.firstUpdate=!0,d.Update=function(a){var b="("+(a||"unknown path")+")";return this.firstUpdate&&this.lineno&&this.colno&&(b+=" [Line "+this.lineno+", Column "+this.colno+"]"),b+="\n ",this.firstUpdate&&(b+=" "),this.message=b+(this.message||""),this.firstUpdate=!1,this},d},f.TemplateError.prototype=Error.prototype,f.escape=function(a){return a.replace(/[&"'<>]/g,e)},f.isFunction=function(a){return c.toString.call(a)=="[object Function]"},f.isArray=Array.isArray||function(a){return c.toString.call(a)=="[object Array]"},f.isString=function(a){return c.toString.call(a)=="[object String]"},f.isObject=function(a){return a===Object(a)},f.groupBy=function(a,b){var c={},d=f.isFunction(b)?b:function(a){return a[b]};for(var e=0;e<a.length;e++){var g=a[e],h=d(g,e);(c[h]||(c[h]=[])).push(g)}return c},f.toArray=function(a){return Array.prototype.slice.call(a)},f.without=function(a){var b=[];if(!a)return b;var c=-1,d=a.length,e=f.toArray(arguments).slice(1);while(++c<d)e.indexOf(a[c])===-1&&b.push(a[c]);return b},f.extend=function(a,b){for(var c in b)a[c]=b[c];return a},f.repeat=function(a,b){var c="";for(var d=0;d<b;d++)c+=a;return c},f.each=function(a,c,d){if(a==null)return;if(b.each&&a.each==b.each)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++)c.call(d,a[e],e,a)},f.map=function(a,c){var d=[];if(a==null)return d;if(b.map&&a.map===b.map)return a.map(c);for(var e=0;e<a.length;e++)d[d.length]=c(a[e],e);return a.length===+a.length&&(d.length=a.length),d}}(),function(){var b=a.lib,c={abs:function(a){return Math.abs(a)},batch:function(a,b,c){var d=[],e=[];for(var f=0;f<a.length;f++)f%b===0&&e.length&&(d.push(e),e=[]),e.push(a[f]);if(e.length){if(c)for(var f=e.length;f<b;f++)e.push(c);d.push(e)}return d},capitalize:function(a){return a=a.toLowerCase(),a[0].toUpperCase()+a.slice(1)},center:function(a,c){c=c||80;if(a.length>=c)return a;var d=c-a.length,e=b.repeat(" ",d/2-d%2),f=b.repeat(" ",d/2);return e+a+f},"default":function(a,b){return a?a:b},escape:b.escape,safe:function(a){return a&&a.raw?a.raw:a},first:function(a){return a[0]},groupby:function(a,c){return b.groupBy(a,c)},indent:function(a,c,d){c=c||4;var e="",f=a.split("\n"),g=b.repeat(" ",c);for(var h=0;h<f.length;h++)h==0&&!d?e+=f[h]+"\n":e+=g+f[h]+"\n";return e},join:function(a,c,d){return c=c||"",d&&(a=b.map(a,function(a){return a[d]})),a.join(c)},last:function(a){return a[a.length-1]},length:function(a){return a.length},list:function(a){if(b.isString(a))return a.split("");if(b.isObject(a)){var c=[];if(Object.keys)c=Object.keys(a);else for(var d in a)c.push(d);return b.map(c,function(b){return{key:b,value:a[b]}})}throw new b.TemplateError("list filter: type not iterable")},lower:function(a){return a.toLowerCase()},random:function(a){var b=Math.floor(Math.random()*a.length);return b==a.length&&b--,a[b]},replace:function(a,b,c,d){var e=a,f=e,g=1;e=e.replace(b,c);while(f!=e){if(g>=d)break;f=e,e=e.replace(b,c),g++}return e},reverse:function(a){var d;return b.isString(a)?d=c.list(a):d=b.map(a,function(a){return a}),d.reverse(),b.isString(a)?d.join(""):d},round:function(a,b,c){b=b||0;var d=Math.pow(10,b),e;return c=="ceil"?e=Math.ceil:c=="floor"?e=Math.floor:e=Math.round,e(a*d)/d},slice:function(a,b,c){var d=Math.floor(a.length/b),e=a.length%b,f=0,g=[];for(var h=0;h<b;h++){var i=f+h*d;h<e&&f++;var j=f+(h+1)*d,k=a.slice(i,j);c&&h>=e&&k.push(c),g.push(k)}return g},sort:function(a,c,d,e){return a=b.map(a,function(a){return a}),a.sort(function(a,f){var g,h;return e?(g=a[e],h=f[e]):(g=a,h=f),!d&&b.isString(g)&&b.isString(h)&&(g=g.toLowerCase(),h=h.toLowerCase()),g<h?c?1:-1:g>h?c?-1:1:0}),a},string:function(a){return a.toString()},title:function(a){return a.toUpperCase()},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},upper:function(a){return a.toUpperCase()},wordcount:function(a){return a.match(/\w+/g).length},"float":function(a,b){return parseFloat(a)||b},"int":function(a,b){return parseInt(a)||b}};c.d=c.default,c.e=c.escape,a.filters=c}(),function(){function e(a,b,c){return function(){var d=h(arguments),e,f=g(arguments);if(d>a.length){e=Array.prototype.slice.call(arguments,0,a.length);var i=Array.prototype.slice.call(arguments,e.length,d);for(var j=0;j<i.length;j++)j<b.length&&(f[b[j]]=i[j]);e.push(f)}else if(d<a.length){e=Array.prototype.slice.call(arguments,0,d);for(var j=d;j<a.length;j++){var k=a[j];e.push(f[k]),delete f[k]}e.push(f)}else e=arguments;return c.apply(this,e)}}function f(a){return a.__keywords=!0,a}function g(a){return a.length&&a[a.length-1].__keywords?a[a.length-1]:{}}function h(a){return a.length===0?0:a[a.length-1].__keywords?a.length-1:a.length}function j(a,b){return a=a!==undefined&&a!==null?a:"",b&&typeof a=="string"&&(a=new i(a)),a}function k(a,b,c){var d=a.lookup(c);return d!==undefined&&d!==null?d:b.lookup(c)}var b=a.object,c=a.lib,d=b.extend({init:function(a){this.variables={},this.parent=a},set:function(a,b){var c=a.split("."),d=this.variables;for(var e=0;e<c.length-1;e++){var f=c[e];d[f]||(d[f]={}),d=d[f]}d[c[c.length-1]]=b},lookup:function(a){var b=this.parent;return this.variables[a]||b&&b.lookup(a)},push:function(){return new d(this)},pop:function(){return this.parent}}),i=b.extend({init:function(a){this.raw=a},toString:function(){return c.escape(this.raw)},replace:function(){return this.raw.replace.apply(this.raw,arguments)},toUpperCase:function(){return this.raw.toUpperCase()}});a.runtime={Frame:d,makeMacro:e,makeKeywordArgs:f,numArgs:h,suppressValue:j,contextOrFrameLookup:k}}(),function(){var b=a.lib,c=a.object,d=a.lexer,e=a.compiler,f=a.filters,g=a.loaders,h=a.runtime,i=h.Frame,j=c.extend({init:function(a,c,e){e=e||{},this.dev=!!e.dev,this.autoesc=!!e.autoescape,a?this.loaders=b.isArray(a)?a:[a]:g.FileSystemLoader?this.loaders=[new g.FileSystemLoader]:this.loaders=[new g.HttpLoader("/views")],c&&d.setTags(c),this.filters=f,this.cache={}},tryTemplate:function(a,c){try{return c()}catch(d){d.Update||(d=b.TemplateError(d)),d.Update(a);if(!this.dev){var e=d;d=new Error(e.message),d.name=e.name}throw d}},addFilter:function(a,b){this.filters[a]=b},getFilter:function(a){if(!this.filters[a])throw new Error("filter not found: "+a);return this.filters[a]},getTemplate:function(a,b){a&&a.raw&&(a=a.raw);var c=null,d=this.cache[a],e;if(typeof a!="string")throw new Error("template names must be a string: "+a);if(!d||!d.isUpToDate()){for(var f=0;f<this.loaders.length;f++)if(c=this.loaders[f].getSource(a))break;if(!c)throw new Error("template not found: "+a);this.cache[a]=new l(c.src,this,c.path,c.upToDate,b)}return this.cache[a]},registerPrecompiled:function(a){for(var b in a)this.cache[b]=new l({type:"code",obj:a[b]},this,b,function(){return!0},!0)},express:function(c){var d=this;if(c.render)c.render=function(a,c,e){var f={};b.isFunction(c)&&(e=c,c={}),f=b.extend(f,this.locals),c._locals&&(f=b.extend(f,c._locals)),f=b.extend(f,c);var g=d.render(a,f);e(null,g)};else{var e=a.http,f=e.ServerResponse.prototype;f._render=function(a,c,e){var f=this.app,g={};this._locals&&(g=b.extend(g,this._locals)),c&&(g=b.extend(g,c),c.locals&&(g=b.extend(g,c.locals))),g=b.extend(g,f._locals);var h=d.render(a,g);e?e(null,h):this.send(h)}}},render:function(a,b){return this.getTemplate(a).render(b)}}),k=c.extend({init:function(a,b){this.ctx=a,this.blocks={},this.exported=[];for(var c in b)this.addBlock(c,b[c])},lookup:function(a){return this.ctx[a]},setVariable:function(a,b){this.ctx[a]=b},getVariables:function(){return this.ctx},addBlock:function(a,b){this.blocks[a]=this.blocks[a]||[],this.blocks[a].push(b)},getBlock:function(a){if(!this.blocks[a])throw new Error('unknown block "'+a+'"');return this.blocks[a][0]},getSuper:function(a,b,c){var d=(this.blocks[b]||[]).indexOf(c),e=this.blocks[b][d+1],f=this;return function(){if(d==-1||!e)throw new Error('no super block available for "'+b+'"');return e(a,f)}},addExport:function(a){this.exported.push(a)},getExported:function(){var a={};for(var b=0;b<this.exported.length;b++){var c=this.exported[b];a[c]=this.ctx[c]}return a}}),l=c.extend({init:function(a,c,d,e,f){this.env=c||new j;if(b.isObject(a))switch(a.type){case"code":this.tmplProps=a.obj;break;case"string":this.tmplStr=a.obj}else{if(!b.isString(a))throw new Error("src must be a string or an object describing the source");this.tmplStr=a}this.path=d,this.upToDate=e||function(){return!1};if(f){var g=this;this.env.tryTemplate(this.path,function(){g._compile()}),g=null}else this.compiled=!1},render:function(a,b){var c=this,d=function(){c.compiled||c._compile();var d=new k(a||{},c.blocks);return c.rootRenderFunc(c.env,d,b||new i,h)};return this.env.tryTemplate(this.path,d)},isUpToDate:function(){return this.upToDate()},getExported:function(){this.compiled||this._compile();var a=new k({},this.blocks);return this.rootRenderFunc(this.env,a,new i,h),a.getExported()},_compile:function(){var a;if(this.tmplProps)a=this.tmplProps;else{var b=new Function(e.compile(this.tmplStr,this.env));a=b()}this.blocks=this._getBlocks(a),this.rootRenderFunc=a.root,this.compiled=!0},_getBlocks:function(a){var b={};for(var c in a)c.slice(0,2)=="b_"&&(b[c.slice(2)]=a[c]);return b}});a.environment={Environment:j,Template:l}}();var b=a.environment,c=a.compiler,d=a.parser,e=a.lexer,f=a.loaders;window.nunjucks={},window.nunjucks.Environment=b.Environment,window.nunjucks.Template=b.Template,f&&(f.FileSystemLoader?window.nunjucks.FileSystemLoader=f.FileSystemLoader:window.nunjucks.HttpLoader=f.HttpLoader),window.nunjucks.compiler=c,window.nunjucks.parser=d,window.nunjucks.lexer=e,window.nunjucks.require=function(b){return a[b]}})(); |
@@ -66,4 +66,58 @@ (function() { | ||
var escapeMap = { | ||
'&': '&', | ||
'"': '"', | ||
"'": ''', | ||
"<": '<', | ||
">": '>' | ||
}; | ||
var lookupEscape = function(ch) { | ||
return escapeMap[ch]; | ||
}; | ||
var exports = modules['lib'] = {}; | ||
exports.TemplateError = function(message, lineno, colno) { | ||
var self = this; | ||
if (message instanceof Error) { // for casting regular js errors | ||
self = message; | ||
message = message.name + ": " + message.message; | ||
} else { | ||
Error.captureStackTrace(self); | ||
} | ||
self.name = "Template render error"; | ||
self.message = message; | ||
self.lineno = lineno; | ||
self.colno = colno; | ||
self.firstUpdate = true; | ||
self.Update = function(path) { | ||
var message = "(" + (path || "unknown path") + ")"; | ||
// only show lineno + colno next to path of template | ||
// where error occurred | ||
if (this.firstUpdate && this.lineno && this.colno) { | ||
message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']'; | ||
} | ||
message += '\n '; | ||
if (this.firstUpdate) { | ||
message += ' '; | ||
} | ||
this.message = message + (this.message || ''); | ||
this.firstUpdate = false; | ||
return this; | ||
}; | ||
return self; | ||
}; | ||
exports.TemplateError.prototype = Error.prototype; | ||
exports.escape = function(val) { | ||
return val.replace(/[&"'<>]/g, lookupEscape); | ||
}; | ||
exports.isFunction = function(obj) { | ||
@@ -225,8 +279,6 @@ return ObjProto.toString.call(obj) == '[object Function]'; | ||
escape: function(str) { | ||
return str.replace(/&/g, '&') | ||
.replace(/"/g, '"') | ||
.replace(/'/g, ''') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>'); | ||
escape: lib.escape, | ||
safe: function(str) { | ||
return (str && str.raw) ? str.raw : str; | ||
}, | ||
@@ -302,3 +354,3 @@ | ||
else { | ||
throw new Error("list: type not iterable"); | ||
throw new lib.TemplateError("list filter: type not iterable"); | ||
} | ||
@@ -459,3 +511,3 @@ }, | ||
return parseInt(val) || def; | ||
}, | ||
} | ||
}; | ||
@@ -472,2 +524,3 @@ | ||
var Object = modules["object"]; | ||
var lib = modules["lib"]; | ||
@@ -582,2 +635,30 @@ // Frames keep track of scoping both at compile-time and run-time so | ||
var FakeString = Object.extend({ | ||
init: function(val) { | ||
this.raw = val; | ||
}, | ||
toString: function() { | ||
return lib.escape(this.raw); | ||
}, | ||
replace: function() { | ||
return this.raw.replace.apply(this.raw, arguments); | ||
}, | ||
toUpperCase: function() { | ||
return this.raw.toUpperCase(); | ||
} | ||
}); | ||
function suppressValue(val, autoescape) { | ||
val = (val !== undefined && val !== null) ? val : ""; | ||
if (autoescape && typeof val === "string") val = new FakeString(val); | ||
return val; | ||
} | ||
function contextOrFrameLookup(context, frame, name) { | ||
var val = context.lookup(name); | ||
return (val !== undefined && val !== null) ? | ||
val : | ||
frame.lookup(name); | ||
} | ||
modules['runtime'] = { | ||
@@ -587,3 +668,5 @@ Frame: Frame, | ||
makeKeywordArgs: makeKeywordArgs, | ||
numArgs: numArgs | ||
numArgs: numArgs, | ||
suppressValue: suppressValue, | ||
contextOrFrameLookup: contextOrFrameLookup | ||
}; | ||
@@ -602,3 +685,18 @@ })(); | ||
var Environment = Object.extend({ | ||
init: function(loaders, tags) { | ||
init: function(loaders, tags, opts) { | ||
// The dev flag determines the trace that'll be shown on errors. | ||
// If set to true, returns the full trace from the error point, | ||
// otherwise will return trace starting from Template.render | ||
// (the full trace from within nunjucks may confuse developers using | ||
// the library) | ||
// defaults to false | ||
opts = opts || {}; | ||
this.dev = !!opts.dev; | ||
// The autoescape flag sets global autoescaping. If true, | ||
// every string variable will be escaped by default. | ||
// If false, strings can be manually escaped using the `escape` filter. | ||
// defaults to false | ||
this.autoesc = !!opts.autoescape; | ||
if(!loaders) { | ||
@@ -625,2 +723,23 @@ // The filesystem loader is only available client-side | ||
tryTemplate: function(path, func) { | ||
try { | ||
return func(); | ||
} catch (e) { | ||
if (!e.Update) { | ||
// not one of ours, cast it | ||
e = lib.TemplateError(e); | ||
} | ||
e.Update(path); | ||
// Unless they marked the dev flag, show them a trace from here | ||
if (!this.dev) { | ||
var old = e; | ||
e = new Error(old.message); | ||
e.name = old.name; | ||
} | ||
throw e; | ||
} | ||
}, | ||
addFilter: function(name, func) { | ||
@@ -631,2 +750,5 @@ this.filters[name] = func; | ||
getFilter: function(name) { | ||
if(!this.filters[name]) { | ||
throw new Error('filter not found: ' + name); | ||
} | ||
return this.filters[name]; | ||
@@ -636,2 +758,6 @@ }, | ||
getTemplate: function(name, eagerCompile) { | ||
if (name && name.raw) { | ||
// this fixes autoescape for templates referenced in symbols | ||
name = name.raw; | ||
} | ||
var info = null; | ||
@@ -641,2 +767,6 @@ var tmpl = this.cache[name]; | ||
if(typeof name !== 'string') { | ||
throw new Error('template names must be a string: ' + name); | ||
} | ||
if(!tmpl || !tmpl.isUpToDate()) { | ||
@@ -677,21 +807,56 @@ for(var i=0; i<this.loaders.length; i++) { | ||
app.render = function(name, ctx, k) { | ||
var context = {}; | ||
if(app.render) { | ||
// Express >2.5.11 | ||
app.render = function(name, ctx, k) { | ||
var context = {}; | ||
if(lib.isFunction(ctx)) { | ||
k = ctx; | ||
ctx = {}; | ||
} | ||
if(lib.isFunction(ctx)) { | ||
k = ctx; | ||
ctx = {}; | ||
} | ||
context = lib.extend(context, app.locals); | ||
context = lib.extend(context, this.locals); | ||
if(ctx._locals) { | ||
context = lib.extend(context, ctx._locals); | ||
} | ||
if(ctx._locals) { | ||
context = lib.extend(context, ctx._locals); | ||
} | ||
context = lib.extend(context, ctx); | ||
context = lib.extend(context, ctx); | ||
var res = env.render(name, context); | ||
k(null, res); | ||
}; | ||
var res = env.render(name, context); | ||
k(null, res); | ||
}; | ||
} | ||
else { | ||
// Express <2.5.11 | ||
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); | ||
} | ||
}; | ||
} | ||
}, | ||
@@ -790,3 +955,5 @@ | ||
if(eagerCompile) { | ||
this._compile(); | ||
var self = this; | ||
this.env.tryTemplate(this.path, function() { self._compile(); }); | ||
self = null; | ||
} | ||
@@ -799,11 +966,17 @@ else { | ||
render: function(ctx, frame) { | ||
if(!this.compiled) { | ||
this._compile(); | ||
} | ||
var self = this; | ||
var context = new Context(ctx || {}, this.blocks); | ||
return this.rootRenderFunc(this.env, | ||
context, | ||
frame || new Frame(), | ||
runtime); | ||
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 this.env.tryTemplate(this.path, render); | ||
}, | ||
@@ -886,8 +1059,11 @@ | ||
if(loaders.FileSystemLoader) { | ||
window.nunjucks.FileSystemLoader = loaders.FileSystemLoader; | ||
// loaders is not available when using precompiled templates | ||
if(loaders) { | ||
if(loaders.FileSystemLoader) { | ||
window.nunjucks.FileSystemLoader = loaders.FileSystemLoader; | ||
} | ||
else { | ||
window.nunjucks.HttpLoader = loaders.HttpLoader; | ||
} | ||
} | ||
else { | ||
window.nunjucks.HttpLoader = loaders.HttpLoader; | ||
} | ||
@@ -894,0 +1070,0 @@ window.nunjucks.compiler = compiler; |
(function() { | ||
var templates = {}; | ||
templates["about.html"] = (function() { | ||
function root(env, context) { | ||
var t_1 = ""; | ||
function root(env, context, frame, runtime) { | ||
var output = ""; | ||
var parentTemplate = env.getTemplate("base.html", true); | ||
for(var t_2 in parentTemplate.blocks) { | ||
context.addBlock(t_2, parentTemplate.blocks[t_2]); | ||
for(var t_1 in parentTemplate.blocks) { | ||
context.addBlock(t_1, parentTemplate.blocks[t_1]); | ||
} | ||
t_1 += "\n\n"; | ||
t_1 += context.getBlock("content")(env, context); | ||
t_1 += "\n\n"; | ||
t_1 += context.getBlock("footer")(env, context); | ||
t_1 += "\n"; | ||
return parentTemplate.rootRenderFunc(env, context); | ||
output += "\n\n"; | ||
output += context.getBlock("content")(env, context, frame, runtime); | ||
output += "\n\n"; | ||
output += context.getBlock("footer")(env, context, frame, runtime); | ||
output += "\n"; | ||
return parentTemplate.rootRenderFunc(env, context, frame, runtime); | ||
} | ||
function b_content(env, context) { | ||
var t_3 = ""; | ||
var l_super = context.getSuper(env, "content", b_content); | ||
t_3 += "\nThis is just the about page\n"; | ||
return t_3; | ||
function b_content(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "content", b_content, runtime); | ||
output += "\nThis is just the about page\n"; | ||
return output; | ||
} | ||
function b_footer(env, context) { | ||
var t_4 = ""; | ||
var l_super = context.getSuper(env, "footer", b_footer); | ||
t_4 += "\n"; | ||
t_4 += l_super(); | ||
t_4 += "\nYou really should read this!\n"; | ||
return t_4; | ||
function b_footer(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "footer", b_footer, runtime); | ||
output += "\n"; | ||
output += (l_super)(); | ||
output += "\nYou really should read this!\n"; | ||
return output; | ||
} | ||
@@ -39,21 +39,21 @@ return { | ||
templates["base.html"] = (function() { | ||
function root(env, context) { | ||
var t_1 = ""; | ||
t_1 += "<!DOCTYPE html>\n<html>\n <head>\n <title>A quick app</title>\n\n <style>\n body {\n background-color: #ccccff;\n }\n\n .footer {\n margin-top: 5em;\n font-size: .75em;\n }\n </style>\n\n <script src=\"/nunjucks.js\"></script>\n </head>\n <body>\n "; | ||
t_1 += context.getBlock("content")(env, context); | ||
t_1 += "\n\n <div class=\"footer\">\n "; | ||
t_1 += context.getBlock("footer")(env, context); | ||
t_1 += "\n </div>\n </body>\n</html>\n"; | ||
return t_1; | ||
function root(env, context, frame, runtime) { | ||
var output = ""; | ||
output += "<!DOCTYPE html>\n<html>\n <head>\n <title>A quick app</title>\n\n <style>\n body {\n background-color: #ccccff;\n }\n\n .footer {\n margin-top: 5em;\n font-size: .75em;\n }\n </style>\n\n <script src=\"/nunjucks-dev.js\"></script>\n <!-- <script src=\"/templates.js\"></script> -->\n </head>\n <body>\n "; | ||
output += context.getBlock("content")(env, context, frame, runtime); | ||
output += "\n\n <div class=\"footer\">\n "; | ||
output += context.getBlock("footer")(env, context, frame, runtime); | ||
output += "\n </div>\n </body>\n</html>\n"; | ||
return output; | ||
} | ||
function b_content(env, context) { | ||
var t_2 = ""; | ||
var l_super = context.getSuper(env, "content", b_content); | ||
return t_2; | ||
function b_content(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "content", b_content, runtime); | ||
return output; | ||
} | ||
function b_footer(env, context) { | ||
var t_3 = ""; | ||
var l_super = context.getSuper(env, "footer", b_footer); | ||
t_3 += "(c) James Long 2012"; | ||
return t_3; | ||
function b_footer(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "footer", b_footer, runtime); | ||
output += "(c) James Long 2012"; | ||
return output; | ||
} | ||
@@ -68,20 +68,47 @@ return { | ||
templates["index.html"] = (function() { | ||
function root(env, context) { | ||
var t_1 = ""; | ||
function root(env, context, frame, runtime) { | ||
var output = ""; | ||
var parentTemplate = env.getTemplate("base.html", true); | ||
for(var t_2 in parentTemplate.blocks) { | ||
context.addBlock(t_2, parentTemplate.blocks[t_2]); | ||
for(var t_1 in parentTemplate.blocks) { | ||
context.addBlock(t_1, parentTemplate.blocks[t_1]); | ||
} | ||
t_1 += "\n\n"; | ||
t_1 += context.getBlock("content")(env, context); | ||
t_1 += "\n\n\n"; | ||
return parentTemplate.rootRenderFunc(env, context); | ||
output += "\n\n"; | ||
var macro_t_2 = runtime.makeMacro( | ||
["x", "y"], | ||
["z"], | ||
function (l_x, l_y, kwargs) { | ||
frame = frame.push(); | ||
kwargs = kwargs || {}; | ||
frame.set("x", l_x); | ||
frame.set("y", l_y); | ||
frame.set("z", kwargs.hasOwnProperty("z") ? kwargs["z"] : 10); | ||
var output= ""; | ||
output += "\n"; | ||
output += l_x; | ||
output += " is better than "; | ||
output += l_y; | ||
output += "!\n\nAND "; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "z"), env.autoesc); | ||
output += "\n"; | ||
frame = frame.pop(); | ||
return output; | ||
}); | ||
context.addExport("foo"); | ||
context.setVariable("foo", macro_t_2); | ||
output += "\n\n"; | ||
output += context.getBlock("content")(env, context, frame, runtime); | ||
output += "\n"; | ||
return parentTemplate.rootRenderFunc(env, context, frame, runtime); | ||
} | ||
function b_content(env, context) { | ||
var t_3 = ""; | ||
var l_super = context.getSuper(env, "content", b_content); | ||
t_3 += "\nHello, "; | ||
t_3 += context.lookup("username"); | ||
t_3 += "! This is just some content\n"; | ||
return t_3; | ||
function b_content(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "content", b_content, runtime); | ||
output += "\nHello, "; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "username"), env.autoesc); | ||
output += "! This is just some content\n\n"; | ||
output += (runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "foo"), env.autoesc))(1,2,3); | ||
output += "\n\n"; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "user"), env.autoesc); | ||
output += "\n"; | ||
return output; | ||
} | ||
@@ -95,18 +122,18 @@ return { | ||
templates["item-base.html"] = (function() { | ||
function root(env, context) { | ||
var t_1 = ""; | ||
t_1 += "\nEditing item: "; | ||
t_1 += context.lookup("name"); | ||
t_1 += "\n\n"; | ||
t_1 += context.getBlock("description")(env, context); | ||
t_1 += "\n"; | ||
return t_1; | ||
function root(env, context, frame, runtime) { | ||
var output = ""; | ||
output += "\nEditing item: "; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "name"), env.autoesc); | ||
output += "\n\n"; | ||
output += context.getBlock("description")(env, context, frame, runtime); | ||
output += "\n"; | ||
return output; | ||
} | ||
function b_description(env, context) { | ||
var t_2 = ""; | ||
var l_super = context.getSuper(env, "description", b_description); | ||
t_2 += "\nA basic description is: "; | ||
t_2 += context.lookup("desc"); | ||
t_2 += "\n"; | ||
return t_2; | ||
function b_description(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "description", b_description, runtime); | ||
output += "\nA basic description is: "; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "desc"), env.autoesc); | ||
output += "\n"; | ||
return output; | ||
} | ||
@@ -120,22 +147,22 @@ return { | ||
templates["item.html"] = (function() { | ||
function root(env, context) { | ||
var t_1 = ""; | ||
function root(env, context, frame, runtime) { | ||
var output = ""; | ||
var parentTemplate = env.getTemplate("item-base.html", true); | ||
for(var t_2 in parentTemplate.blocks) { | ||
context.addBlock(t_2, parentTemplate.blocks[t_2]); | ||
for(var t_1 in parentTemplate.blocks) { | ||
context.addBlock(t_1, parentTemplate.blocks[t_1]); | ||
} | ||
t_1 += "\n\n"; | ||
t_1 += context.getBlock("description")(env, context); | ||
t_1 += "\n"; | ||
return parentTemplate.rootRenderFunc(env, context); | ||
output += "\n\n"; | ||
output += context.getBlock("description")(env, context, frame, runtime); | ||
output += "\n"; | ||
return parentTemplate.rootRenderFunc(env, context, frame, runtime); | ||
} | ||
function b_description(env, context) { | ||
var t_3 = ""; | ||
var l_super = context.getSuper(env, "description", b_description); | ||
t_3 += "\nI told you, it's name is "; | ||
t_3 += context.lookup("name"); | ||
t_3 += ".\n\nIt also has the description: "; | ||
t_3 += context.lookup("desc"); | ||
t_3 += ".\n"; | ||
return t_3; | ||
function b_description(env, context, frame, runtime) { | ||
var output = ""; | ||
var l_super = context.getSuper(env, "description", b_description, runtime); | ||
output += "\nI told you, it's name is "; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "name"), env.autoesc); | ||
output += ".\n\nIt also has the description: "; | ||
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "desc"), env.autoesc); | ||
output += ".\n"; | ||
return output; | ||
} | ||
@@ -142,0 +169,0 @@ return { |
@@ -49,2 +49,49 @@ | ||
it("dictsort", function() { | ||
// no real foolproof way to test that a js obj has been transformed | ||
// from unsorted -> sorted, as its enumeration ordering is undefined | ||
// and might fluke being sorted originally .. lets just init with some jumbled | ||
// keys | ||
// no params - should be case insensitive, by key | ||
var s = render('{% for item in items | dictsort %}' + | ||
'{{ item[0] }}{% endfor %}', { | ||
items: { | ||
"e": 1, | ||
"d": 2, | ||
"c": 3, | ||
"a": 4, | ||
"f": 5, | ||
"b": 6 | ||
} | ||
}); | ||
s.should.equal("abcdef"); | ||
// case sensitive = true | ||
var s = render('{% for item in items | dictsort(true) %}' + | ||
'{{ item[0] }},{% endfor %}', { | ||
items: { | ||
"ABC": 6, | ||
"ABc": 5, | ||
"Abc": 1, | ||
"abc": 2 | ||
} | ||
}); | ||
s.should.equal("ABC,ABc,Abc,abc,"); | ||
// use values for sort | ||
var s = render('{% for item in items | dictsort(false, "value") %}' + | ||
'{{ item[0] }}{% endfor %}', { | ||
items: { | ||
"a": 6, | ||
"b": 5, | ||
"c": 1, | ||
"d": 2 | ||
} | ||
}); | ||
s.should.equal("cdba"); | ||
}); | ||
it('first', function() { | ||
@@ -59,4 +106,16 @@ var s = render('{{ [1,2,3] | first }}'); | ||
var s = render('{{ "3.5" | int }}'); | ||
s = render('{{ "3.5" | int }}'); | ||
s.should.equal('3'); | ||
s = render('{{ "0" | int }}'); | ||
s.should.equal('0'); | ||
s = render('{{ "0" | float }}'); | ||
s.should.equal('0'); | ||
s = render('{{ "bob" | int("cat") }}'); | ||
s.should.equal('cat'); | ||
s = render('{{ "bob" | float("cat") }}'); | ||
s.should.equal('cat'); | ||
}); | ||
@@ -63,0 +122,0 @@ |
@@ -226,2 +226,9 @@ var should = require('should'); | ||
it('should parse raw', function() { | ||
isAST(parser.parse('{% raw %}hello {{ {% %} }}{% endraw %}'), | ||
[nodes.Root, | ||
[nodes.Output, | ||
[nodes.TemplateData, 'hello {{ {% %} }}']]]); | ||
}); | ||
it('should parse keyword and non-keyword arguments', function() { | ||
@@ -261,2 +268,69 @@ isAST(parser.parse('{{ foo("bar", falalalala, baz="foobar") }}'), | ||
it('should parse whitespace control', function() { | ||
// Every start/end tag with "-" should trim the whitespace | ||
// before or after it | ||
isAST(parser.parse('{% if x %}\n hi \n{% endif %}'), | ||
[nodes.Root, | ||
[nodes.If, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Output, | ||
[nodes.TemplateData, '\n hi \n']]]]]); | ||
isAST(parser.parse('{% if x -%}\n hi \n{% endif %}'), | ||
[nodes.Root, | ||
[nodes.If, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Output, | ||
[nodes.TemplateData, 'hi \n']]]]]); | ||
isAST(parser.parse('{% if x %}\n hi \n{%- endif %}'), | ||
[nodes.Root, | ||
[nodes.If, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Output, | ||
[nodes.TemplateData, '\n hi']]]]]); | ||
isAST(parser.parse('{% if x -%}\n hi \n{%- endif %}'), | ||
[nodes.Root, | ||
[nodes.If, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Output, | ||
[nodes.TemplateData, 'hi']]]]]); | ||
isAST(parser.parse('poop \n{%- if x -%}\n hi \n{%- endif %}'), | ||
[nodes.Root, | ||
[nodes.Output, | ||
[nodes.TemplateData, 'poop']], | ||
[nodes.If, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Output, | ||
[nodes.TemplateData, 'hi']]]]]); | ||
// The from statement required a special case so make sure to | ||
// test it | ||
isAST(parser.parse('{% from x import y %}\n hi \n'), | ||
[nodes.Root, | ||
[nodes.FromImport, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Symbol, 'y']]], | ||
[nodes.Output, | ||
[nodes.TemplateData, '\n hi \n']]]); | ||
isAST(parser.parse('{% from x import y -%}\n hi \n'), | ||
[nodes.Root, | ||
[nodes.FromImport, | ||
[nodes.Symbol, 'x'], | ||
[nodes.NodeList, | ||
[nodes.Symbol, 'y']]], | ||
[nodes.Output, | ||
[nodes.TemplateData, 'hi \n']]]); | ||
}); | ||
it('should throw errors', function() { | ||
@@ -263,0 +337,0 @@ (function() { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
426715
11676