Comparing version 0.5.15-1896 to 0.6.0-2085
/** | ||
* Vash - JavaScript Template Parser, v0.5.15-1896 | ||
* Vash - JavaScript Template Parser, v0.6.0-2085 | ||
* | ||
@@ -44,3 +44,4 @@ * https://github.com/kirbysayshi/vash | ||
helpers.toString = helpers.toHtmlString = function(){ | ||
return this.buffer.toString(); | ||
// not calling buffer.toString() results in 2x speedup | ||
return this.buffer._vo.join('');//.toString(); | ||
} | ||
@@ -62,3 +63,3 @@ | ||
helpers.raw = function( val ) { | ||
helpers['raw'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -74,3 +75,3 @@ | ||
helpers.escape = function( val ) { | ||
helpers['escape'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -144,2 +145,6 @@ | ||
Buffer.prototype.push = function( buffer ) { | ||
return this._vo.push( buffer ); | ||
}; | ||
Buffer.prototype.pushConcat = function( buffer ){ | ||
if( buffer instanceof Array ) { | ||
@@ -152,4 +157,6 @@ this._vo.push.apply( this._vo, buffer ); | ||
} | ||
}; | ||
return this.__vo; | ||
} | ||
Buffer.prototype.indexOf = function( str ){ | ||
@@ -268,3 +275,3 @@ | ||
helpers.reportError = function() { | ||
helpers['reportError'] = function() { | ||
this.constructor.reportError.apply( this, arguments ); | ||
@@ -278,52 +285,118 @@ }; | ||
// VASH.LINK | ||
// Reconstitute precompiled functions | ||
// Take a compiled string or function and "link" it to the current vash | ||
// runtime. This is necessary to allow instantiation of `Helpers` and | ||
// proper decompilation via `toClientString`. | ||
// | ||
// If `options.asHelper` and `options.args` are defined, the `cmpFunc` is | ||
// interpreted as a compiled helper, and is attached to `vash.helpers` at | ||
// a property name equal to `options.asHelper`. | ||
vash['link'] = function( cmpFunc, modelName, helpersName ){ | ||
vash['link'] = function( cmpFunc, options ){ | ||
var joined; | ||
// TODO: allow options.filename to be used as sourceUrl? | ||
var originalFunc | ||
,cmpOpts; | ||
if( !options.args ){ | ||
// every template has these arguments | ||
options.args = [options.modelName, options.helpersName, '__vopts', 'vash']; | ||
} | ||
if( typeof cmpFunc === 'string' ){ | ||
joined = cmpFunc; | ||
originalFunc = cmpFunc; | ||
try { | ||
cmpFunc = new Function(modelName, helpersName, '__vopts', 'vash', joined); | ||
} catch(e){ | ||
helpers.reportError(e, 0, 0, joined, /\n/); | ||
// do not pollute the args array for later attachment to the compiled | ||
// function for later decompilation/linking | ||
cmpOpts = options.args.slice(); | ||
cmpOpts.push(cmpFunc); | ||
cmpFunc = Function.apply(null, cmpOpts); | ||
} catch(e) { | ||
// TODO: add flag to reportError to know if it's at compile time or runtime | ||
helpers.reportError(e, 0, 0, originalFunc, /\n/); | ||
} | ||
} | ||
// need this to enable `vash.batch` to reconstitute | ||
cmpFunc.options = { modelName: modelName, helpersName: helpersName }; | ||
// need this to enable decompilation / relinking | ||
cmpFunc.options = { | ||
simple: options.simple | ||
,modelName: options.modelName | ||
,helpersName: options.helpersName | ||
} | ||
var linked = function( model, opts ){ | ||
var linked; | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
if( options.asHelper ){ | ||
opts = opts || {}; | ||
cmpFunc.options.args = options.args; | ||
cmpFunc.options.asHelper = options.asHelper; | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd && opts && !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
linked = function(){ | ||
return cmpFunc.apply(this, slice.call(arguments)); | ||
} | ||
if( model && model.onRenderEnd ){ | ||
delete model.onRenderEnd; | ||
helpers[options.asHelper] = linked; | ||
} else { | ||
linked = function( model, opts ){ | ||
if( options.simple ){ | ||
var ctx = { | ||
buffer: [] | ||
,escape: Helpers.prototype.escape | ||
,raw: Helpers.prototype.raw | ||
} | ||
return cmpFunc( model, ctx, opts, vash ); | ||
} | ||
opts = divineRuntimeTplOptions( model, opts ); | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
} | ||
} | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
}; | ||
// show the template-specific code, instead of the generic linked function | ||
linked['toString'] = function(){ return cmpFunc.toString(); } | ||
linked.toString = function(){ | ||
return cmpFunc.toString(); | ||
}; | ||
// shortcut to show the actual linked function | ||
linked['_toString'] = function(){ return Function.prototype.toString.call(linked) } | ||
linked.toClientString = function(){ | ||
return 'vash.link( ' + cmpFunc.toString() + ', "' + modelName + '", "' + helpersName + '" )'; | ||
}; | ||
linked['toClientString'] = function(){ | ||
return 'vash.link( ' | ||
+ cmpFunc.toString() + ', ' | ||
+ JSON.stringify( cmpFunc.options ) + ' )'; | ||
} | ||
return linked; | ||
}; | ||
} | ||
// given a model and options, allow for various tpl signatures and options: | ||
// ( model, {} ) | ||
// ( model, function onRenderEnd(){} ) | ||
// ( model ) | ||
// and model.onRenderEnd | ||
function divineRuntimeTplOptions( model, opts ){ | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd ){ | ||
opts = opts || {}; | ||
if( !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
} | ||
delete model.onRenderEnd; | ||
} | ||
return opts; | ||
} | ||
// shortcut for compiled helpers | ||
var slice = Array.prototype.slice; | ||
// VASH.LINK | ||
@@ -335,3 +408,3 @@ /////////////////////////////////////////////////////////////////////////// | ||
vash.lookup = function( path, model ){ | ||
vash['lookup'] = function( path, model ){ | ||
var tpl = vash.helpers.tplcache[path]; | ||
@@ -343,3 +416,3 @@ if( !tpl ){ throw new Error('Could not find template: ' + path); } | ||
vash.install = function( path, tpl ){ | ||
vash['install'] = function( path, tpl ){ | ||
var cache = vash.helpers.tplcache; | ||
@@ -349,2 +422,8 @@ if( typeof tpl === 'string' ){ | ||
tpl = vash.compile(tpl); | ||
} else if( typeof path === 'object' ){ | ||
tpl = path; | ||
Object.keys(tpl).forEach(function(path){ | ||
cache[path] = tpl[path]; | ||
}); | ||
return cache; | ||
} | ||
@@ -354,3 +433,3 @@ return cache[path] = tpl; | ||
vash.uninstall = function( path ){ | ||
vash['uninstall'] = function( path ){ | ||
var cache = vash.helpers.tplcache | ||
@@ -530,3 +609,3 @@ ,deleted = false; | ||
prepends && prepends.forEach(function(p){ self.buffer.push( p ); }); | ||
prepends && prepends.forEach(function(p){ self.buffer.pushConcat( p ); }); | ||
@@ -536,5 +615,5 @@ // a block might never have a callback defined, e.g. is optional | ||
block = blocks.pop(); | ||
block && this.buffer.push( block ); | ||
block && this.buffer.pushConcat( block ); | ||
appends && appends.forEach(function(a){ self.buffer.push( a ); }); | ||
appends && appends.forEach(function(a){ self.buffer.pushConcat( a ); }); | ||
@@ -541,0 +620,0 @@ // grab rendered content |
/** | ||
* Vash - JavaScript Template Parser, v0.5.15-1896 | ||
* Vash - JavaScript Template Parser, v0.6.0-2085 | ||
* | ||
@@ -10,2 +10,2 @@ * https://github.com/kirbysayshi/vash | ||
(function(){vash=typeof vash=="undefined"?{}:vash,vash.compile||(typeof define=="function"&&define.amd?define(function(){return vash}):typeof module=="object"&&module.exports?module.exports=vash:window.vash=vash);var a=vash.helpers,b=function(a){this.buffer=new f,this.model=a,this.vl=0,this.vc=0};vash.helpers=a=b.prototype={constructor:b,config:{},tplcache:{}},a.toString=a.toHtmlString=function(){return this.buffer.toString()};var c=/[&<>"'`]/g,d=function(a){return e[a]},e={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};a.raw=function(a){var b=function(){return a};a=a!=null?a:"";return{toHtmlString:b,toString:b}},a.escape=function(a){var b=function(){return a};a=a!=null?a:"";if(typeof a.toHtmlString!="function"){a=a.toString().replace(c,d);return{toHtmlString:b,toString:b}}return a};var f=function(){this._vo=[]};f.prototype.mark=function(a){var b=new g(this,a);b.markedIndex=this._vo.length,this._vo.push(b.uid);return b},f.prototype.fromMark=function(a){var b=a.findInBuffer();if(b>-1){a.destroy();return this._vo.splice(b,this._vo.length)}return[]},f.prototype.spliceMark=function(a,b,c){var d=a.findInBuffer();if(d>-1){a.destroy(),arguments[0]=d;return this._vo.splice.apply(this._vo,arguments)}return[]},f.prototype.empty=function(){return this._vo.splice(0,this._vo.length)},f.prototype.push=function(a){a instanceof Array?this._vo.push.apply(this._vo,a):arguments.length>1?this._vo.push.apply(this._vo,Array.prototype.slice.call(arguments)):this._vo.push(a)},f.prototype.indexOf=function(a){for(var b=0;b<this._vo.length;b++)if(this._vo[b]==a)return b;return-1},f.prototype.splice=function(){return this._vo.splice.apply(this._vo,arguments)},f.prototype.index=function(a){return this._vo[a]},f.prototype.flush=function(){return this.empty().join("")},f.prototype.toString=f.prototype.toHtmlString=function(){return this._vo.join("")};var g=vash.Mark=function(a,b){this.uid="[VASHMARK-"+~~(Math.random()*1e7)+(b?":"+b:"")+"]",this.markedIndex=0,this.buffer=a,this.destroyed=!1},h=/\[VASHMARK\-\d{1,8}(?::[\s\S]+?)?]/g;g.uidLike=function(a){return(a||"").search(h)>-1},g.prototype.destroy=function(){var a=this.findInBuffer();a>-1&&(this.buffer.splice(a,1),this.markedIndex=-1),this.destroyed=!0},g.prototype.findInBuffer=function(){return this.destroyed?-1:this.markedIndex&&this.buffer.index(this.markedIndex)===this.uid?this.markedIndex:this.markedIndex=this.buffer.indexOf(this.uid)},a.constructor.reportError=function(a,b,c,d,e){e=e||"!LB!";var f=d.split(e),g=b===0&&c===0?f.length-1:3,h=Math.max(0,b-g),i=Math.min(f.length,b+g),j=f.slice(h,i).map(function(a,c,d){var e=c+h+1;return(e===b?" > ":" ")+(e<10?" ":"")+e+" | "+a}).join("\n");a.message="Problem while rendering template at line "+b+", character "+c+".\nOriginal message: "+a.message+"."+"\nContext: \n\n"+j+"\n\n";throw a},a.reportError=function(){this.constructor.reportError.apply(this,arguments)},vash.link=function(c,d,e){var f;if(typeof c=="string"){f=c;try{c=new Function(d,e,"__vopts","vash",f)}catch(g){a.reportError(g,0,0,f,/\n/)}}c.options={modelName:d,helpersName:e};var h=function(a,d){typeof d=="function"&&(d={onRenderEnd:d}),d=d||{},a&&a.onRenderEnd&&d&&!d.onRenderEnd&&(d.onRenderEnd=a.onRenderEnd),a&&a.onRenderEnd&&delete a.onRenderEnd;return c(a,d&&d.context||new b(a),d,vash)};h.toString=function(){return c.toString()},h.toClientString=function(){return"vash.link( "+c.toString()+', "'+d+'", "'+e+'" )'};return h},vash.lookup=function(a,b){var c=vash.helpers.tplcache[a];if(!c)throw new Error("Could not find template: "+a);return b?c(b):c},vash.install=function(a,b){var c=vash.helpers.tplcache;if(typeof b=="string"){if(!vash.compile)throw new Error("vash.install(path, [string]) is not available in the standalone runtime.");b=vash.compile(b)}return c[a]=b},vash.uninstall=function(a){var b=vash.helpers.tplcache,c=!1;if(typeof a=="string")return delete b[a];Object.keys(b).forEach(function(d){b[d]===a&&(c=delete b[d])});return c}})(),function(){var a=vash.helpers;a.config.highlighter=null,a.highlight=function(b,c){var d=this.buffer.mark();c();var e=this.buffer.fromMark(d);this.buffer.push("<pre><code>"),a.config.highlighter?this.buffer.push(a.config.highlighter(b,e.join("")).value):this.buffer.push(e),this.buffer.push("</code></pre>")}}(),function(){if(typeof window=="undefined")var a=require("fs"),b=require("path");var c=vash.helpers;c.config.browser=!1,vash.loadFile=function(d,e,f){e=vQuery.extend({},vash.config,e||{});var g=c.config.browser,h;!g&&e.settings&&e.settings.views&&(d=b.normalize(d),d.indexOf(b.normalize(e.settings.views))===-1&&(d=b.join(e.settings.views,d)),b.extname(d)||(d+="."+(e.settings["view engine"]||"vash")));try{h=e.cache||g?c.tplcache[d]||(c.tplcache[d]=vash.compile(a.readFileSync(d,"utf8"))):vash.compile(a.readFileSync(d,"utf8")),f&&f(null,h)}catch(i){f&&f(i,null)}},vash.renderFile=function(a,b,c){vash.loadFile(a,b,function(a,d){var e=b.onRenderEnd;c(a,d(b,function(a,b){b.finishLayout(),e&&e(a,b)}))})},c._ensureLayoutProps=function(){this.appends=this.appends||{},this.prepends=this.prepends||{},this.blocks=this.blocks||{},this.blockMarks=this.blockMarks||{}},c.finishLayout=function(){this._ensureLayoutProps();var a=this,b,c,d,e,f,g,h,i;for(b in this.blockMarks)c=this.blockMarks[b],e=this.prepends[b],d=this.blocks[b],f=this.appends[b],g=c.pop(),h=this.buffer.mark(),e&&e.forEach(function(b){a.buffer.push(b)}),block=d.pop(),block&&this.buffer.push(block),f&&f.forEach(function(b){a.buffer.push(b)}),i=this.buffer.fromMark(h),i.unshift(g,0),this.buffer.spliceMark.apply(this.buffer,i);for(b in this.blockMarks)this.blockMarks[b].forEach(function(a){a.destroy()});delete this.blockMarks,delete this.prepends,delete this.blocks,delete this.appends;return this.toString()},c.extend=function(a,b){var c=this,d=this.buffer,e=this.model,f;this._ensureLayoutProps(),vash.loadFile(a,this.model,function(a,d){var e=c.buffer.mark();b(c.model);var f=c.buffer.fromMark(e);c.isExtending=!0,d(c.model,{context:c}),c.isExtending=!1}),this.model=e},c.include=function(a,b){var c=this,d=this.buffer,e=this.model;vash.loadFile(a,this.model,function(a,d){d(b||c.model,{context:c})}),this.model=e},c.block=function(a,b){this._ensureLayoutProps();var c=this,d=this.blockMarks[a]||(this.blockMarks[a]=[]),e=this.blocks[a]||(this.blocks[a]=[]),f,g;b&&(f=this.buffer.mark(),b(this.model),g=this.buffer.fromMark(f),g.length&&!this.isExtending&&e.push(g),g.length&&this.isExtending&&e.unshift(g)),d.push(this.buffer.mark("block-"+a))},c._handlePrependAppend=function(a,b,c){this._ensureLayoutProps();var d=this.buffer.mark(),e,f=this[a],g=f[b]||(f[b]=[]);c(this.model),e=this.buffer.fromMark(d),g.push(e)},c.append=function(a,b){this._handlePrependAppend("appends",a,b)},c.prepend=function(a,b){this._handlePrependAppend("prepends",a,b)}}() | ||
(function(){function i(a,b){typeof b=="function"&&(b={onRenderEnd:b}),a&&a.onRenderEnd&&(b=b||{},b.onRenderEnd||(b.onRenderEnd=a.onRenderEnd),delete a.onRenderEnd);return b}vash=typeof vash=="undefined"?{}:vash,vash.compile||(typeof define=="function"&&define.amd?define(function(){return vash}):typeof module=="object"&&module.exports?module.exports=vash:window.vash=vash);var a=vash.helpers,b=function(a){this.buffer=new f,this.model=a,this.vl=0,this.vc=0};vash.helpers=a=b.prototype={constructor:b,config:{},tplcache:{}},a.toString=a.toHtmlString=function(){return this.buffer._vo.join("")};var c=/[&<>"'`]/g,d=function(a){return e[a]},e={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};a.raw=function(a){var b=function(){return a};a=a!=null?a:"";return{toHtmlString:b,toString:b}},a.escape=function(a){var b=function(){return a};a=a!=null?a:"";if(typeof a.toHtmlString!="function"){a=a.toString().replace(c,d);return{toHtmlString:b,toString:b}}return a};var f=function(){this._vo=[]};f.prototype.mark=function(a){var b=new g(this,a);b.markedIndex=this._vo.length,this._vo.push(b.uid);return b},f.prototype.fromMark=function(a){var b=a.findInBuffer();if(b>-1){a.destroy();return this._vo.splice(b,this._vo.length)}return[]},f.prototype.spliceMark=function(a,b,c){var d=a.findInBuffer();if(d>-1){a.destroy(),arguments[0]=d;return this._vo.splice.apply(this._vo,arguments)}return[]},f.prototype.empty=function(){return this._vo.splice(0,this._vo.length)},f.prototype.push=function(a){return this._vo.push(a)},f.prototype.pushConcat=function(a){a instanceof Array?this._vo.push.apply(this._vo,a):arguments.length>1?this._vo.push.apply(this._vo,Array.prototype.slice.call(arguments)):this._vo.push(a);return this.__vo},f.prototype.indexOf=function(a){for(var b=0;b<this._vo.length;b++)if(this._vo[b]==a)return b;return-1},f.prototype.splice=function(){return this._vo.splice.apply(this._vo,arguments)},f.prototype.index=function(a){return this._vo[a]},f.prototype.flush=function(){return this.empty().join("")},f.prototype.toString=f.prototype.toHtmlString=function(){return this._vo.join("")};var g=vash.Mark=function(a,b){this.uid="[VASHMARK-"+~~(Math.random()*1e7)+(b?":"+b:"")+"]",this.markedIndex=0,this.buffer=a,this.destroyed=!1},h=/\[VASHMARK\-\d{1,8}(?::[\s\S]+?)?]/g;g.uidLike=function(a){return(a||"").search(h)>-1},g.prototype.destroy=function(){var a=this.findInBuffer();a>-1&&(this.buffer.splice(a,1),this.markedIndex=-1),this.destroyed=!0},g.prototype.findInBuffer=function(){return this.destroyed?-1:this.markedIndex&&this.buffer.index(this.markedIndex)===this.uid?this.markedIndex:this.markedIndex=this.buffer.indexOf(this.uid)},a.constructor.reportError=function(a,b,c,d,e){e=e||"!LB!";var f=d.split(e),g=b===0&&c===0?f.length-1:3,h=Math.max(0,b-g),i=Math.min(f.length,b+g),j=f.slice(h,i).map(function(a,c,d){var e=c+h+1;return(e===b?" > ":" ")+(e<10?" ":"")+e+" | "+a}).join("\n");a.message="Problem while rendering template at line "+b+", character "+c+".\nOriginal message: "+a.message+"."+"\nContext: \n\n"+j+"\n\n";throw a},a.reportError=function(){this.constructor.reportError.apply(this,arguments)},vash.link=function(c,d){var e,f;d.args||(d.args=[d.modelName,d.helpersName,"__vopts","vash"]);if(typeof c=="string"){e=c;try{f=d.args.slice(),f.push(c),c=Function.apply(null,f)}catch(g){a.reportError(g,0,0,e,/\n/)}}c.options={simple:d.simple,modelName:d.modelName,helpersName:d.helpersName};var h;d.asHelper?(c.options.args=d.args,c.options.asHelper=d.asHelper,h=function(){return c.apply(this,j.call(arguments))},a[d.asHelper]=h):h=function(a,e){if(d.simple){var f={buffer:[],escape:b.prototype.escape,raw:b.prototype.raw};return c(a,f,e,vash)}e=i(a,e);return c(a,e&&e.context||new b(a),e,vash)},h.toString=function(){return c.toString()},h._toString=function(){return Function.prototype.toString.call(h)},h.toClientString=function(){return"vash.link( "+c.toString()+", "+JSON.stringify(c.options)+" )"};return h};var j=Array.prototype.slice;vash.lookup=function(a,b){var c=vash.helpers.tplcache[a];if(!c)throw new Error("Could not find template: "+a);return b?c(b):c},vash.install=function(a,b){var c=vash.helpers.tplcache;if(typeof b=="string"){if(!vash.compile)throw new Error("vash.install(path, [string]) is not available in the standalone runtime.");b=vash.compile(b)}else if(typeof a=="object"){b=a,Object.keys(b).forEach(function(a){c[a]=b[a]});return c}return c[a]=b},vash.uninstall=function(a){var b=vash.helpers.tplcache,c=!1;if(typeof a=="string")return delete b[a];Object.keys(b).forEach(function(d){b[d]===a&&(c=delete b[d])});return c}})(),function(){var a=vash.helpers;a.config.highlighter=null,a.highlight=function(b,c){var d=this.buffer.mark();c();var e=this.buffer.fromMark(d);this.buffer.push("<pre><code>"),a.config.highlighter?this.buffer.push(a.config.highlighter(b,e.join("")).value):this.buffer.push(e),this.buffer.push("</code></pre>")}}(),function(){if(typeof window=="undefined")var a=require("fs"),b=require("path");var c=vash.helpers;c.config.browser=!1,vash.loadFile=function(d,e,f){e=vQuery.extend({},vash.config,e||{});var g=c.config.browser,h;!g&&e.settings&&e.settings.views&&(d=b.normalize(d),d.indexOf(b.normalize(e.settings.views))===-1&&(d=b.join(e.settings.views,d)),b.extname(d)||(d+="."+(e.settings["view engine"]||"vash")));try{h=e.cache||g?c.tplcache[d]||(c.tplcache[d]=vash.compile(a.readFileSync(d,"utf8"))):vash.compile(a.readFileSync(d,"utf8")),f&&f(null,h)}catch(i){f&&f(i,null)}},vash.renderFile=function(a,b,c){vash.loadFile(a,b,function(a,d){var e=b.onRenderEnd;c(a,d(b,function(a,b){b.finishLayout(),e&&e(a,b)}))})},c._ensureLayoutProps=function(){this.appends=this.appends||{},this.prepends=this.prepends||{},this.blocks=this.blocks||{},this.blockMarks=this.blockMarks||{}},c.finishLayout=function(){this._ensureLayoutProps();var a=this,b,c,d,e,f,g,h,i;for(b in this.blockMarks)c=this.blockMarks[b],e=this.prepends[b],d=this.blocks[b],f=this.appends[b],g=c.pop(),h=this.buffer.mark(),e&&e.forEach(function(b){a.buffer.pushConcat(b)}),block=d.pop(),block&&this.buffer.pushConcat(block),f&&f.forEach(function(b){a.buffer.pushConcat(b)}),i=this.buffer.fromMark(h),i.unshift(g,0),this.buffer.spliceMark.apply(this.buffer,i);for(b in this.blockMarks)this.blockMarks[b].forEach(function(a){a.destroy()});delete this.blockMarks,delete this.prepends,delete this.blocks,delete this.appends;return this.toString()},c.extend=function(a,b){var c=this,d=this.buffer,e=this.model,f;this._ensureLayoutProps(),vash.loadFile(a,this.model,function(a,d){var e=c.buffer.mark();b(c.model);var f=c.buffer.fromMark(e);c.isExtending=!0,d(c.model,{context:c}),c.isExtending=!1}),this.model=e},c.include=function(a,b){var c=this,d=this.buffer,e=this.model;vash.loadFile(a,this.model,function(a,d){d(b||c.model,{context:c})}),this.model=e},c.block=function(a,b){this._ensureLayoutProps();var c=this,d=this.blockMarks[a]||(this.blockMarks[a]=[]),e=this.blocks[a]||(this.blocks[a]=[]),f,g;b&&(f=this.buffer.mark(),b(this.model),g=this.buffer.fromMark(f),g.length&&!this.isExtending&&e.push(g),g.length&&this.isExtending&&e.unshift(g)),d.push(this.buffer.mark("block-"+a))},c._handlePrependAppend=function(a,b,c){this._ensureLayoutProps();var d=this.buffer.mark(),e,f=this[a],g=f[b]||(f[b]=[]);c(this.model),e=this.buffer.fromMark(d),g.push(e)},c.append=function(a,b){this._handlePrependAppend("appends",a,b)},c.prepend=function(a,b){this._handlePrependAppend("prepends",a,b)}}() |
/** | ||
* Vash - JavaScript Template Parser, v0.5.15-1896 | ||
* Vash - JavaScript Template Parser, v0.6.0-2085 | ||
* | ||
@@ -44,3 +44,4 @@ * https://github.com/kirbysayshi/vash | ||
helpers.toString = helpers.toHtmlString = function(){ | ||
return this.buffer.toString(); | ||
// not calling buffer.toString() results in 2x speedup | ||
return this.buffer._vo.join('');//.toString(); | ||
} | ||
@@ -62,3 +63,3 @@ | ||
helpers.raw = function( val ) { | ||
helpers['raw'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -74,3 +75,3 @@ | ||
helpers.escape = function( val ) { | ||
helpers['escape'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -144,2 +145,6 @@ | ||
Buffer.prototype.push = function( buffer ) { | ||
return this._vo.push( buffer ); | ||
}; | ||
Buffer.prototype.pushConcat = function( buffer ){ | ||
if( buffer instanceof Array ) { | ||
@@ -152,4 +157,6 @@ this._vo.push.apply( this._vo, buffer ); | ||
} | ||
}; | ||
return this.__vo; | ||
} | ||
Buffer.prototype.indexOf = function( str ){ | ||
@@ -268,3 +275,3 @@ | ||
helpers.reportError = function() { | ||
helpers['reportError'] = function() { | ||
this.constructor.reportError.apply( this, arguments ); | ||
@@ -278,52 +285,118 @@ }; | ||
// VASH.LINK | ||
// Reconstitute precompiled functions | ||
// Take a compiled string or function and "link" it to the current vash | ||
// runtime. This is necessary to allow instantiation of `Helpers` and | ||
// proper decompilation via `toClientString`. | ||
// | ||
// If `options.asHelper` and `options.args` are defined, the `cmpFunc` is | ||
// interpreted as a compiled helper, and is attached to `vash.helpers` at | ||
// a property name equal to `options.asHelper`. | ||
vash['link'] = function( cmpFunc, modelName, helpersName ){ | ||
vash['link'] = function( cmpFunc, options ){ | ||
var joined; | ||
// TODO: allow options.filename to be used as sourceUrl? | ||
var originalFunc | ||
,cmpOpts; | ||
if( !options.args ){ | ||
// every template has these arguments | ||
options.args = [options.modelName, options.helpersName, '__vopts', 'vash']; | ||
} | ||
if( typeof cmpFunc === 'string' ){ | ||
joined = cmpFunc; | ||
originalFunc = cmpFunc; | ||
try { | ||
cmpFunc = new Function(modelName, helpersName, '__vopts', 'vash', joined); | ||
} catch(e){ | ||
helpers.reportError(e, 0, 0, joined, /\n/); | ||
// do not pollute the args array for later attachment to the compiled | ||
// function for later decompilation/linking | ||
cmpOpts = options.args.slice(); | ||
cmpOpts.push(cmpFunc); | ||
cmpFunc = Function.apply(null, cmpOpts); | ||
} catch(e) { | ||
// TODO: add flag to reportError to know if it's at compile time or runtime | ||
helpers.reportError(e, 0, 0, originalFunc, /\n/); | ||
} | ||
} | ||
// need this to enable `vash.batch` to reconstitute | ||
cmpFunc.options = { modelName: modelName, helpersName: helpersName }; | ||
// need this to enable decompilation / relinking | ||
cmpFunc.options = { | ||
simple: options.simple | ||
,modelName: options.modelName | ||
,helpersName: options.helpersName | ||
} | ||
var linked = function( model, opts ){ | ||
var linked; | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
if( options.asHelper ){ | ||
opts = opts || {}; | ||
cmpFunc.options.args = options.args; | ||
cmpFunc.options.asHelper = options.asHelper; | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd && opts && !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
linked = function(){ | ||
return cmpFunc.apply(this, slice.call(arguments)); | ||
} | ||
if( model && model.onRenderEnd ){ | ||
delete model.onRenderEnd; | ||
helpers[options.asHelper] = linked; | ||
} else { | ||
linked = function( model, opts ){ | ||
if( options.simple ){ | ||
var ctx = { | ||
buffer: [] | ||
,escape: Helpers.prototype.escape | ||
,raw: Helpers.prototype.raw | ||
} | ||
return cmpFunc( model, ctx, opts, vash ); | ||
} | ||
opts = divineRuntimeTplOptions( model, opts ); | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
} | ||
} | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
}; | ||
// show the template-specific code, instead of the generic linked function | ||
linked['toString'] = function(){ return cmpFunc.toString(); } | ||
linked.toString = function(){ | ||
return cmpFunc.toString(); | ||
}; | ||
// shortcut to show the actual linked function | ||
linked['_toString'] = function(){ return Function.prototype.toString.call(linked) } | ||
linked.toClientString = function(){ | ||
return 'vash.link( ' + cmpFunc.toString() + ', "' + modelName + '", "' + helpersName + '" )'; | ||
}; | ||
linked['toClientString'] = function(){ | ||
return 'vash.link( ' | ||
+ cmpFunc.toString() + ', ' | ||
+ JSON.stringify( cmpFunc.options ) + ' )'; | ||
} | ||
return linked; | ||
}; | ||
} | ||
// given a model and options, allow for various tpl signatures and options: | ||
// ( model, {} ) | ||
// ( model, function onRenderEnd(){} ) | ||
// ( model ) | ||
// and model.onRenderEnd | ||
function divineRuntimeTplOptions( model, opts ){ | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd ){ | ||
opts = opts || {}; | ||
if( !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
} | ||
delete model.onRenderEnd; | ||
} | ||
return opts; | ||
} | ||
// shortcut for compiled helpers | ||
var slice = Array.prototype.slice; | ||
// VASH.LINK | ||
@@ -335,3 +408,3 @@ /////////////////////////////////////////////////////////////////////////// | ||
vash.lookup = function( path, model ){ | ||
vash['lookup'] = function( path, model ){ | ||
var tpl = vash.helpers.tplcache[path]; | ||
@@ -343,3 +416,3 @@ if( !tpl ){ throw new Error('Could not find template: ' + path); } | ||
vash.install = function( path, tpl ){ | ||
vash['install'] = function( path, tpl ){ | ||
var cache = vash.helpers.tplcache; | ||
@@ -349,2 +422,8 @@ if( typeof tpl === 'string' ){ | ||
tpl = vash.compile(tpl); | ||
} else if( typeof path === 'object' ){ | ||
tpl = path; | ||
Object.keys(tpl).forEach(function(path){ | ||
cache[path] = tpl[path]; | ||
}); | ||
return cache; | ||
} | ||
@@ -354,3 +433,3 @@ return cache[path] = tpl; | ||
vash.uninstall = function( path ){ | ||
vash['uninstall'] = function( path ){ | ||
var cache = vash.helpers.tplcache | ||
@@ -357,0 +436,0 @@ ,deleted = false; |
/** | ||
* Vash - JavaScript Template Parser, v0.5.15-1896 | ||
* Vash - JavaScript Template Parser, v0.6.0-2085 | ||
* | ||
@@ -10,2 +10,2 @@ * https://github.com/kirbysayshi/vash | ||
(function(){vash=typeof vash=="undefined"?{}:vash,vash.compile||(typeof define=="function"&&define.amd?define(function(){return vash}):typeof module=="object"&&module.exports?module.exports=vash:window.vash=vash);var a=vash.helpers,b=function(a){this.buffer=new f,this.model=a,this.vl=0,this.vc=0};vash.helpers=a=b.prototype={constructor:b,config:{},tplcache:{}},a.toString=a.toHtmlString=function(){return this.buffer.toString()};var c=/[&<>"'`]/g,d=function(a){return e[a]},e={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};a.raw=function(a){var b=function(){return a};a=a!=null?a:"";return{toHtmlString:b,toString:b}},a.escape=function(a){var b=function(){return a};a=a!=null?a:"";if(typeof a.toHtmlString!="function"){a=a.toString().replace(c,d);return{toHtmlString:b,toString:b}}return a};var f=function(){this._vo=[]};f.prototype.mark=function(a){var b=new g(this,a);b.markedIndex=this._vo.length,this._vo.push(b.uid);return b},f.prototype.fromMark=function(a){var b=a.findInBuffer();if(b>-1){a.destroy();return this._vo.splice(b,this._vo.length)}return[]},f.prototype.spliceMark=function(a,b,c){var d=a.findInBuffer();if(d>-1){a.destroy(),arguments[0]=d;return this._vo.splice.apply(this._vo,arguments)}return[]},f.prototype.empty=function(){return this._vo.splice(0,this._vo.length)},f.prototype.push=function(a){a instanceof Array?this._vo.push.apply(this._vo,a):arguments.length>1?this._vo.push.apply(this._vo,Array.prototype.slice.call(arguments)):this._vo.push(a)},f.prototype.indexOf=function(a){for(var b=0;b<this._vo.length;b++)if(this._vo[b]==a)return b;return-1},f.prototype.splice=function(){return this._vo.splice.apply(this._vo,arguments)},f.prototype.index=function(a){return this._vo[a]},f.prototype.flush=function(){return this.empty().join("")},f.prototype.toString=f.prototype.toHtmlString=function(){return this._vo.join("")};var g=vash.Mark=function(a,b){this.uid="[VASHMARK-"+~~(Math.random()*1e7)+(b?":"+b:"")+"]",this.markedIndex=0,this.buffer=a,this.destroyed=!1},h=/\[VASHMARK\-\d{1,8}(?::[\s\S]+?)?]/g;g.uidLike=function(a){return(a||"").search(h)>-1},g.prototype.destroy=function(){var a=this.findInBuffer();a>-1&&(this.buffer.splice(a,1),this.markedIndex=-1),this.destroyed=!0},g.prototype.findInBuffer=function(){return this.destroyed?-1:this.markedIndex&&this.buffer.index(this.markedIndex)===this.uid?this.markedIndex:this.markedIndex=this.buffer.indexOf(this.uid)},a.constructor.reportError=function(a,b,c,d,e){e=e||"!LB!";var f=d.split(e),g=b===0&&c===0?f.length-1:3,h=Math.max(0,b-g),i=Math.min(f.length,b+g),j=f.slice(h,i).map(function(a,c,d){var e=c+h+1;return(e===b?" > ":" ")+(e<10?" ":"")+e+" | "+a}).join("\n");a.message="Problem while rendering template at line "+b+", character "+c+".\nOriginal message: "+a.message+"."+"\nContext: \n\n"+j+"\n\n";throw a},a.reportError=function(){this.constructor.reportError.apply(this,arguments)},vash.link=function(c,d,e){var f;if(typeof c=="string"){f=c;try{c=new Function(d,e,"__vopts","vash",f)}catch(g){a.reportError(g,0,0,f,/\n/)}}c.options={modelName:d,helpersName:e};var h=function(a,d){typeof d=="function"&&(d={onRenderEnd:d}),d=d||{},a&&a.onRenderEnd&&d&&!d.onRenderEnd&&(d.onRenderEnd=a.onRenderEnd),a&&a.onRenderEnd&&delete a.onRenderEnd;return c(a,d&&d.context||new b(a),d,vash)};h.toString=function(){return c.toString()},h.toClientString=function(){return"vash.link( "+c.toString()+', "'+d+'", "'+e+'" )'};return h},vash.lookup=function(a,b){var c=vash.helpers.tplcache[a];if(!c)throw new Error("Could not find template: "+a);return b?c(b):c},vash.install=function(a,b){var c=vash.helpers.tplcache;if(typeof b=="string"){if(!vash.compile)throw new Error("vash.install(path, [string]) is not available in the standalone runtime.");b=vash.compile(b)}return c[a]=b},vash.uninstall=function(a){var b=vash.helpers.tplcache,c=!1;if(typeof a=="string")return delete b[a];Object.keys(b).forEach(function(d){b[d]===a&&(c=delete b[d])});return c}})() | ||
(function(){function i(a,b){typeof b=="function"&&(b={onRenderEnd:b}),a&&a.onRenderEnd&&(b=b||{},b.onRenderEnd||(b.onRenderEnd=a.onRenderEnd),delete a.onRenderEnd);return b}vash=typeof vash=="undefined"?{}:vash,vash.compile||(typeof define=="function"&&define.amd?define(function(){return vash}):typeof module=="object"&&module.exports?module.exports=vash:window.vash=vash);var a=vash.helpers,b=function(a){this.buffer=new f,this.model=a,this.vl=0,this.vc=0};vash.helpers=a=b.prototype={constructor:b,config:{},tplcache:{}},a.toString=a.toHtmlString=function(){return this.buffer._vo.join("")};var c=/[&<>"'`]/g,d=function(a){return e[a]},e={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};a.raw=function(a){var b=function(){return a};a=a!=null?a:"";return{toHtmlString:b,toString:b}},a.escape=function(a){var b=function(){return a};a=a!=null?a:"";if(typeof a.toHtmlString!="function"){a=a.toString().replace(c,d);return{toHtmlString:b,toString:b}}return a};var f=function(){this._vo=[]};f.prototype.mark=function(a){var b=new g(this,a);b.markedIndex=this._vo.length,this._vo.push(b.uid);return b},f.prototype.fromMark=function(a){var b=a.findInBuffer();if(b>-1){a.destroy();return this._vo.splice(b,this._vo.length)}return[]},f.prototype.spliceMark=function(a,b,c){var d=a.findInBuffer();if(d>-1){a.destroy(),arguments[0]=d;return this._vo.splice.apply(this._vo,arguments)}return[]},f.prototype.empty=function(){return this._vo.splice(0,this._vo.length)},f.prototype.push=function(a){return this._vo.push(a)},f.prototype.pushConcat=function(a){a instanceof Array?this._vo.push.apply(this._vo,a):arguments.length>1?this._vo.push.apply(this._vo,Array.prototype.slice.call(arguments)):this._vo.push(a);return this.__vo},f.prototype.indexOf=function(a){for(var b=0;b<this._vo.length;b++)if(this._vo[b]==a)return b;return-1},f.prototype.splice=function(){return this._vo.splice.apply(this._vo,arguments)},f.prototype.index=function(a){return this._vo[a]},f.prototype.flush=function(){return this.empty().join("")},f.prototype.toString=f.prototype.toHtmlString=function(){return this._vo.join("")};var g=vash.Mark=function(a,b){this.uid="[VASHMARK-"+~~(Math.random()*1e7)+(b?":"+b:"")+"]",this.markedIndex=0,this.buffer=a,this.destroyed=!1},h=/\[VASHMARK\-\d{1,8}(?::[\s\S]+?)?]/g;g.uidLike=function(a){return(a||"").search(h)>-1},g.prototype.destroy=function(){var a=this.findInBuffer();a>-1&&(this.buffer.splice(a,1),this.markedIndex=-1),this.destroyed=!0},g.prototype.findInBuffer=function(){return this.destroyed?-1:this.markedIndex&&this.buffer.index(this.markedIndex)===this.uid?this.markedIndex:this.markedIndex=this.buffer.indexOf(this.uid)},a.constructor.reportError=function(a,b,c,d,e){e=e||"!LB!";var f=d.split(e),g=b===0&&c===0?f.length-1:3,h=Math.max(0,b-g),i=Math.min(f.length,b+g),j=f.slice(h,i).map(function(a,c,d){var e=c+h+1;return(e===b?" > ":" ")+(e<10?" ":"")+e+" | "+a}).join("\n");a.message="Problem while rendering template at line "+b+", character "+c+".\nOriginal message: "+a.message+"."+"\nContext: \n\n"+j+"\n\n";throw a},a.reportError=function(){this.constructor.reportError.apply(this,arguments)},vash.link=function(c,d){var e,f;d.args||(d.args=[d.modelName,d.helpersName,"__vopts","vash"]);if(typeof c=="string"){e=c;try{f=d.args.slice(),f.push(c),c=Function.apply(null,f)}catch(g){a.reportError(g,0,0,e,/\n/)}}c.options={simple:d.simple,modelName:d.modelName,helpersName:d.helpersName};var h;d.asHelper?(c.options.args=d.args,c.options.asHelper=d.asHelper,h=function(){return c.apply(this,j.call(arguments))},a[d.asHelper]=h):h=function(a,e){if(d.simple){var f={buffer:[],escape:b.prototype.escape,raw:b.prototype.raw};return c(a,f,e,vash)}e=i(a,e);return c(a,e&&e.context||new b(a),e,vash)},h.toString=function(){return c.toString()},h._toString=function(){return Function.prototype.toString.call(h)},h.toClientString=function(){return"vash.link( "+c.toString()+", "+JSON.stringify(c.options)+" )"};return h};var j=Array.prototype.slice;vash.lookup=function(a,b){var c=vash.helpers.tplcache[a];if(!c)throw new Error("Could not find template: "+a);return b?c(b):c},vash.install=function(a,b){var c=vash.helpers.tplcache;if(typeof b=="string"){if(!vash.compile)throw new Error("vash.install(path, [string]) is not available in the standalone runtime.");b=vash.compile(b)}else if(typeof a=="object"){b=a,Object.keys(b).forEach(function(a){c[a]=b[a]});return c}return c[a]=b},vash.uninstall=function(a){var b=vash.helpers.tplcache,c=!1;if(typeof a=="string")return delete b[a];Object.keys(b).forEach(function(d){b[d]===a&&(c=delete b[d])});return c}})() |
/** | ||
* Vash - JavaScript Template Parser, v0.5.15-1896 | ||
* Vash - JavaScript Template Parser, v0.6.0-2085 | ||
* | ||
@@ -29,3 +29,3 @@ * https://github.com/kirbysayshi/vash | ||
exports["version"] = "0.5.15-1896"; | ||
exports["version"] = "0.6.0-2085"; | ||
exports["config"] = { | ||
@@ -39,2 +39,3 @@ "useWith": false | ||
,"debugCompiler": false | ||
,"simple": false | ||
@@ -76,31 +77,104 @@ ,"favorText": false | ||
exports['batch'] = function batch(path, cb){ | ||
/////////////////////////////////////////////////////////////////////////// | ||
// VASH.BATCH | ||
// | ||
// Allow multiple templates to be contained within the same string. | ||
// Templates are separated via a sourceURL-esque string: | ||
// | ||
// //@batch = tplname/or/path | ||
// | ||
// The separator is forgiving in terms of whitespace: | ||
// | ||
// // @ batch=tplname/or/path | ||
// | ||
// Is just as valid. | ||
// | ||
// Returns the compiled templates as named properties of an object. | ||
var caller = batch.caller; | ||
exports['batch'] = function(markup, options){ | ||
function _batch(path, cb){ | ||
var tpls = splitByNamedTpl(markup).batch; | ||
var reFuncHead = /^function\s*\([^)]*?\)\s*{/ | ||
,reFuncTail = /\}$/ | ||
if(tpls){ | ||
Object.keys(tpls).forEach(function(path){ | ||
tpls[path] = vash.compile(tpls[path], options); | ||
}); | ||
} | ||
,str = cb.toString() | ||
.replace(reFuncHead, '') | ||
.replace(reFuncTail, '') | ||
return tpls; | ||
} | ||
,callOpts = caller.options | ||
// do the actual work of splitting the string via the batch separator | ||
var splitByNamedTpl = function(markup){ | ||
var cmp = new VCompiler([], '', callOpts); | ||
var reSourceMap = /^\/\/\s*@\s*(batch|helper)\s*=\s*(.*?)$/ | ||
,lines = markup.split(/[\n\r]/g) | ||
,tpls = { | ||
batch: {} | ||
,helper: {} | ||
} | ||
,paths = [] | ||
,currentPath = '' | ||
,typePointer = tpls.batch; | ||
str = cmp.wrapBody( str ); | ||
vash.install( path, vash.link( str, callOpts.modelName, callOpts.helpersName ) ); | ||
} | ||
lines.forEach(function(line, idx, arr){ | ||
var pathResult = reSourceMap.exec(line) | ||
,atEnd = idx === arr.length - 1; | ||
if( vash.compile ) { | ||
exports['batch'] = _batch; | ||
return exports['batch'](path, cb); | ||
} else { | ||
throw new Error('vash.batch is not available in the standalone runtime.'); | ||
} | ||
}; | ||
if(!pathResult || atEnd){ | ||
tpls[typePointer][currentPath].push(line); | ||
} | ||
if((pathResult || atEnd) && currentPath){ | ||
tpls[typePointer][currentPath] = tpls[typePointer][currentPath].join('\n'); | ||
} | ||
if(pathResult){ | ||
typePointer = pathResult[1]; | ||
currentPath = pathResult[2].replace(/^\s+|\s+$/, ''); | ||
tpls[typePointer][currentPath] = []; | ||
} | ||
}); | ||
return tpls; | ||
} | ||
// VASH.BATCH | ||
/////////////////////////////////////////////////////////////////////////// | ||
/////////////////////////////////////////////////////////////////////////// | ||
// HELPER INSTALLATION | ||
var slice = Array.prototype.slice | ||
,reFuncHead = /^vash\.helpers\.([^= ]+?)\s*=\s*function([^(]*?)\(([^)]*?)\)\s*{/ | ||
,reFuncTail = /\}$/ | ||
exports['compileHelper'] = function reg(str, options){ | ||
options = options || {}; | ||
// replace leading/trailing spaces, and parse the function head | ||
var def = str.replace(/^\s+|\s+$/, '').match(reFuncHead) | ||
// split the function arguments, kill all whitespace | ||
,args = def[3].split(',').map(function(arg){ return arg.replace(' ', '') }) | ||
,name = def[1] | ||
,body = str | ||
.replace( reFuncHead, '' ) | ||
.replace( reFuncTail, '' ) | ||
// Wrap body in @{} to simulate it actually being inside a function | ||
// definition, since we manually stripped it. Without this, statements | ||
// such as `this.what = "what";` that are at the beginning of the body | ||
// will be interpreted as markup. | ||
body = '@{' + body + '}'; | ||
// `args` and `asHelper` inform `vash.compile/link` that this is a helper | ||
options.args = args; | ||
options.asHelper = name; | ||
vash.compile(body, options); | ||
} | ||
// HELPER INSTALLATION | ||
/////////////////////////////////////////////////////////////////////////// | ||
/************** Begin injected code from build script */ | ||
@@ -141,3 +215,4 @@ /*jshint strict:false, asi: false, laxcomma:true, laxbreak:true, boss:true, curly:true, node:true, browser:true, devel:true */ | ||
helpers.toString = helpers.toHtmlString = function(){ | ||
return this.buffer.toString(); | ||
// not calling buffer.toString() results in 2x speedup | ||
return this.buffer._vo.join('');//.toString(); | ||
} | ||
@@ -159,3 +234,3 @@ | ||
helpers.raw = function( val ) { | ||
helpers['raw'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -171,3 +246,3 @@ | ||
helpers.escape = function( val ) { | ||
helpers['escape'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -241,2 +316,6 @@ | ||
Buffer.prototype.push = function( buffer ) { | ||
return this._vo.push( buffer ); | ||
}; | ||
Buffer.prototype.pushConcat = function( buffer ){ | ||
if( buffer instanceof Array ) { | ||
@@ -249,4 +328,6 @@ this._vo.push.apply( this._vo, buffer ); | ||
} | ||
}; | ||
return this.__vo; | ||
} | ||
Buffer.prototype.indexOf = function( str ){ | ||
@@ -365,3 +446,3 @@ | ||
helpers.reportError = function() { | ||
helpers['reportError'] = function() { | ||
this.constructor.reportError.apply( this, arguments ); | ||
@@ -375,52 +456,118 @@ }; | ||
// VASH.LINK | ||
// Reconstitute precompiled functions | ||
// Take a compiled string or function and "link" it to the current vash | ||
// runtime. This is necessary to allow instantiation of `Helpers` and | ||
// proper decompilation via `toClientString`. | ||
// | ||
// If `options.asHelper` and `options.args` are defined, the `cmpFunc` is | ||
// interpreted as a compiled helper, and is attached to `vash.helpers` at | ||
// a property name equal to `options.asHelper`. | ||
vash['link'] = function( cmpFunc, modelName, helpersName ){ | ||
vash['link'] = function( cmpFunc, options ){ | ||
var joined; | ||
// TODO: allow options.filename to be used as sourceUrl? | ||
var originalFunc | ||
,cmpOpts; | ||
if( !options.args ){ | ||
// every template has these arguments | ||
options.args = [options.modelName, options.helpersName, '__vopts', 'vash']; | ||
} | ||
if( typeof cmpFunc === 'string' ){ | ||
joined = cmpFunc; | ||
originalFunc = cmpFunc; | ||
try { | ||
cmpFunc = new Function(modelName, helpersName, '__vopts', 'vash', joined); | ||
} catch(e){ | ||
helpers.reportError(e, 0, 0, joined, /\n/); | ||
// do not pollute the args array for later attachment to the compiled | ||
// function for later decompilation/linking | ||
cmpOpts = options.args.slice(); | ||
cmpOpts.push(cmpFunc); | ||
cmpFunc = Function.apply(null, cmpOpts); | ||
} catch(e) { | ||
// TODO: add flag to reportError to know if it's at compile time or runtime | ||
helpers.reportError(e, 0, 0, originalFunc, /\n/); | ||
} | ||
} | ||
// need this to enable `vash.batch` to reconstitute | ||
cmpFunc.options = { modelName: modelName, helpersName: helpersName }; | ||
// need this to enable decompilation / relinking | ||
cmpFunc.options = { | ||
simple: options.simple | ||
,modelName: options.modelName | ||
,helpersName: options.helpersName | ||
} | ||
var linked = function( model, opts ){ | ||
var linked; | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
if( options.asHelper ){ | ||
opts = opts || {}; | ||
cmpFunc.options.args = options.args; | ||
cmpFunc.options.asHelper = options.asHelper; | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd && opts && !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
linked = function(){ | ||
return cmpFunc.apply(this, slice.call(arguments)); | ||
} | ||
if( model && model.onRenderEnd ){ | ||
delete model.onRenderEnd; | ||
helpers[options.asHelper] = linked; | ||
} else { | ||
linked = function( model, opts ){ | ||
if( options.simple ){ | ||
var ctx = { | ||
buffer: [] | ||
,escape: Helpers.prototype.escape | ||
,raw: Helpers.prototype.raw | ||
} | ||
return cmpFunc( model, ctx, opts, vash ); | ||
} | ||
opts = divineRuntimeTplOptions( model, opts ); | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
} | ||
} | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
}; | ||
// show the template-specific code, instead of the generic linked function | ||
linked['toString'] = function(){ return cmpFunc.toString(); } | ||
linked.toString = function(){ | ||
return cmpFunc.toString(); | ||
}; | ||
// shortcut to show the actual linked function | ||
linked['_toString'] = function(){ return Function.prototype.toString.call(linked) } | ||
linked.toClientString = function(){ | ||
return 'vash.link( ' + cmpFunc.toString() + ', "' + modelName + '", "' + helpersName + '" )'; | ||
}; | ||
linked['toClientString'] = function(){ | ||
return 'vash.link( ' | ||
+ cmpFunc.toString() + ', ' | ||
+ JSON.stringify( cmpFunc.options ) + ' )'; | ||
} | ||
return linked; | ||
}; | ||
} | ||
// given a model and options, allow for various tpl signatures and options: | ||
// ( model, {} ) | ||
// ( model, function onRenderEnd(){} ) | ||
// ( model ) | ||
// and model.onRenderEnd | ||
function divineRuntimeTplOptions( model, opts ){ | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd ){ | ||
opts = opts || {}; | ||
if( !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
} | ||
delete model.onRenderEnd; | ||
} | ||
return opts; | ||
} | ||
// shortcut for compiled helpers | ||
var slice = Array.prototype.slice; | ||
// VASH.LINK | ||
@@ -432,3 +579,3 @@ /////////////////////////////////////////////////////////////////////////// | ||
vash.lookup = function( path, model ){ | ||
vash['lookup'] = function( path, model ){ | ||
var tpl = vash.helpers.tplcache[path]; | ||
@@ -440,3 +587,3 @@ if( !tpl ){ throw new Error('Could not find template: ' + path); } | ||
vash.install = function( path, tpl ){ | ||
vash['install'] = function( path, tpl ){ | ||
var cache = vash.helpers.tplcache; | ||
@@ -446,2 +593,8 @@ if( typeof tpl === 'string' ){ | ||
tpl = vash.compile(tpl); | ||
} else if( typeof path === 'object' ){ | ||
tpl = path; | ||
Object.keys(tpl).forEach(function(path){ | ||
cache[path] = tpl[path]; | ||
}); | ||
return cache; | ||
} | ||
@@ -451,3 +604,3 @@ return cache[path] = tpl; | ||
vash.uninstall = function( path ){ | ||
vash['uninstall'] = function( path ){ | ||
var cache = vash.helpers.tplcache | ||
@@ -627,3 +780,3 @@ ,deleted = false; | ||
prepends && prepends.forEach(function(p){ self.buffer.push( p ); }); | ||
prepends && prepends.forEach(function(p){ self.buffer.pushConcat( p ); }); | ||
@@ -633,5 +786,5 @@ // a block might never have a callback defined, e.g. is optional | ||
block = blocks.pop(); | ||
block && this.buffer.push( block ); | ||
block && this.buffer.pushConcat( block ); | ||
appends && appends.forEach(function(a){ self.buffer.push( a ); }); | ||
appends && appends.forEach(function(a){ self.buffer.pushConcat( a ); }); | ||
@@ -1877,3 +2030,3 @@ // grab rendered content | ||
VCP.wrapBody = function(body){ | ||
VCP.addHead = function(body){ | ||
@@ -1888,19 +2041,57 @@ var options = this.options; | ||
head = this.replaceDevTokens( head ); | ||
return head + body; | ||
} | ||
VCP.addHelperHead = function(body){ | ||
var options = this.options; | ||
var head = '' | ||
+ (options.debug ? 'try { \n' : '') | ||
+ 'var __vbuffer = this.buffer; \n' | ||
+ 'var MODELNAME = this.model; \n' | ||
+ 'var HELPERSNAME = this; \n'; | ||
head = this.replaceDevTokens( head ); | ||
return head + body; | ||
} | ||
VCP.addFoot = function(body){ | ||
var options = this.options; | ||
var foot = '' | ||
+ '(__vopts && __vopts.onRenderEnd && __vopts.onRenderEnd(null, HELPERSNAME)); \n' | ||
+ 'return (__vopts && __vopts.asContext) \n' | ||
+ ' ? HELPERSNAME \n' | ||
+ ' : HELPERSNAME.toString(); \n' | ||
+ (options.simple | ||
? 'return HELPERSNAME.buffer.join(""); \n' | ||
: '(__vopts && __vopts.onRenderEnd && __vopts.onRenderEnd(null, HELPERSNAME)); \n' | ||
+ 'return (__vopts && __vopts.asContext) \n' | ||
+ ' ? HELPERSNAME \n' | ||
+ ' : HELPERSNAME.toString(); \n' ) | ||
+ (options.useWith ? '} \n' : '') | ||
+ (options.debug ? '} catch( e ){ \n' | ||
+ ' HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n' | ||
+ '} \n' : '') | ||
+ (options.useWith ? '} \n' : ''); | ||
+ '} \n' : ''); | ||
head = this.replaceDevTokens( head ); | ||
foot = this.replaceDevTokens( foot ) | ||
.replace( this.reOriginalMarkup, this.escapeForDebug( this.originalMarkup ) ); | ||
return head + body + foot; | ||
return body + foot; | ||
} | ||
VCP.addHelperFoot = function(body){ | ||
var options = this.options; | ||
var foot = '' | ||
+ (options.debug ? '} catch( e ){ \n' | ||
+ ' HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n' | ||
+ '} \n' : ''); | ||
foot = this.replaceDevTokens( foot ) | ||
.replace( this.reOriginalMarkup, this.escapeForDebug( this.originalMarkup ) ); | ||
return body + foot; | ||
} | ||
VCP.generate = function(){ | ||
@@ -1921,9 +2112,16 @@ var options = this.options; | ||
joined = this.wrapBody( joined ); | ||
if(!options.asHelper){ | ||
joined = this.addHead( joined ); | ||
joined = this.addFoot( joined ); | ||
} else { | ||
joined = this.addHelperHead( joined ); | ||
joined = this.addHelperFoot( joined ); | ||
} | ||
if(options.debugCompiler){ | ||
console.log(joined); | ||
console.log(options); | ||
} | ||
this.cmpFunc = vash.link( joined, options.modelName, options.helpersName ); | ||
this.cmpFunc = vash.link( joined, options ); | ||
return this.cmpFunc; | ||
@@ -1930,0 +2128,0 @@ } |
/** | ||
* Vash - JavaScript Template Parser, v0.5.15-1896 | ||
* Vash - JavaScript Template Parser, v0.6.0-2085 | ||
* | ||
@@ -10,2 +10,2 @@ * https://github.com/kirbysayshi/vash | ||
(function(a){typeof define=="function"&&define.amd?define(function(){return a}):typeof module=="object"&&module.exports?module.exports=a:window.vash=a})(function(a){function Q(a,b,c){this.ast=a,this.originalMarkup=b||"",this.options=c||{},this.reQuote=/(["'])/gi,this.reEscapedQuote=/\\+(["'])/gi,this.reLineBreak=/[\n\r]/gi,this.reHelpersName=/HELPERSNAME/g,this.reModelName=/MODELNAME/g,this.reOriginalMarkup=/ORIGINALMARKUP/g,this.buffer=[]}function L(a,b){this.options=b||{},this.tokens=a,this.ast=K(M),this.prevTokens=[]}function J(a){this.input=this.originalInput=a.replace(/\r\n|\r/g,"\n"),this.lineno=1,this.charno=0}var b=a;a.version="0.5.15-1896",a.config={useWith:!1,modelName:"model",helpersName:"html",htmlEscape:!0,debug:!0,debugParser:!1,debugCompiler:!1,favorText:!1,saveTextTag:!1,saveAT:!1},a.compile=function(b,c){if(b===""||typeof b!="string")throw new Error("Empty or non-string cannot be compiled");var d,e,f=[],g,h,i,j;c=K.extend({},a.config,c||{}),d=new J(b);while(e=d.advance())f.push(e);f.reverse(),g=new L(f,c),g.parse(),h=new Q(g.ast,b,c),i=h.generate();return i},a.batch=function T(c,d){function f(a,c){var d=/^function\s*\([^)]*?\)\s*{/,f=/\}$/,g=c.toString().replace(d,"").replace(f,""),h=e.options,i=new Q([],"",h);g=i.wrapBody(g),b.install(a,b.link(g,h.modelName,h.helpersName))}var e=T.caller;if(b.compile){a.batch=f;return a.batch(c,d)}throw new Error("vash.batch is not available in the standalone runtime.")},function(){b=typeof b=="undefined"?{}:b,b.compile||(typeof define=="function"&&define.amd?define(function(){return b}):typeof module=="object"&&module.exports?module.exports=b:window.vash=b);var a=b.helpers,c=function(a){this.buffer=new g,this.model=a,this.vl=0,this.vc=0};b.helpers=a=c.prototype={constructor:c,config:{},tplcache:{}},a.toString=a.toHtmlString=function(){return this.buffer.toString()};var d=/[&<>"'`]/g,e=function(a){return f[a]},f={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};a.raw=function(a){var b=function(){return a};a=a!=null?a:"";return{toHtmlString:b,toString:b}},a.escape=function(a){var b=function(){return a};a=a!=null?a:"";if(typeof a.toHtmlString!="function"){a=a.toString().replace(d,e);return{toHtmlString:b,toString:b}}return a};var g=function(){this._vo=[]};g.prototype.mark=function(a){var b=new h(this,a);b.markedIndex=this._vo.length,this._vo.push(b.uid);return b},g.prototype.fromMark=function(a){var b=a.findInBuffer();if(b>-1){a.destroy();return this._vo.splice(b,this._vo.length)}return[]},g.prototype.spliceMark=function(a,b,c){var d=a.findInBuffer();if(d>-1){a.destroy(),arguments[0]=d;return this._vo.splice.apply(this._vo,arguments)}return[]},g.prototype.empty=function(){return this._vo.splice(0,this._vo.length)},g.prototype.push=function(a){a instanceof Array?this._vo.push.apply(this._vo,a):arguments.length>1?this._vo.push.apply(this._vo,Array.prototype.slice.call(arguments)):this._vo.push(a)},g.prototype.indexOf=function(a){for(var b=0;b<this._vo.length;b++)if(this._vo[b]==a)return b;return-1},g.prototype.splice=function(){return this._vo.splice.apply(this._vo,arguments)},g.prototype.index=function(a){return this._vo[a]},g.prototype.flush=function(){return this.empty().join("")},g.prototype.toString=g.prototype.toHtmlString=function(){return this._vo.join("")};var h=b.Mark=function(a,b){this.uid="[VASHMARK-"+~~(Math.random()*1e7)+(b?":"+b:"")+"]",this.markedIndex=0,this.buffer=a,this.destroyed=!1},i=/\[VASHMARK\-\d{1,8}(?::[\s\S]+?)?]/g;h.uidLike=function(a){return(a||"").search(i)>-1},h.prototype.destroy=function(){var a=this.findInBuffer();a>-1&&(this.buffer.splice(a,1),this.markedIndex=-1),this.destroyed=!0},h.prototype.findInBuffer=function(){return this.destroyed?-1:this.markedIndex&&this.buffer.index(this.markedIndex)===this.uid?this.markedIndex:this.markedIndex=this.buffer.indexOf(this.uid)},a.constructor.reportError=function(a,b,c,d,e){e=e||"!LB!";var f=d.split(e),g=b===0&&c===0?f.length-1:3,h=Math.max(0,b-g),i=Math.min(f.length,b+g),j=f.slice(h,i).map(function(a,c,d){var e=c+h+1;return(e===b?" > ":" ")+(e<10?" ":"")+e+" | "+a}).join("\n");a.message="Problem while rendering template at line "+b+", character "+c+".\nOriginal message: "+a.message+"."+"\nContext: \n\n"+j+"\n\n";throw a},a.reportError=function(){this.constructor.reportError.apply(this,arguments)},b.link=function(d,e,f){var g;if(typeof d=="string"){g=d;try{d=new Function(e,f,"__vopts","vash",g)}catch(h){a.reportError(h,0,0,g,/\n/)}}d.options={modelName:e,helpersName:f};var i=function(a,e){typeof e=="function"&&(e={onRenderEnd:e}),e=e||{},a&&a.onRenderEnd&&e&&!e.onRenderEnd&&(e.onRenderEnd=a.onRenderEnd),a&&a.onRenderEnd&&delete a.onRenderEnd;return d(a,e&&e.context||new c(a),e,b)};i.toString=function(){return d.toString()},i.toClientString=function(){return"vash.link( "+d.toString()+', "'+e+'", "'+f+'" )'};return i},b.lookup=function(a,c){var d=b.helpers.tplcache[a];if(!d)throw new Error("Could not find template: "+a);return c?d(c):d},b.install=function(a,c){var d=b.helpers.tplcache;if(typeof c=="string"){if(!b.compile)throw new Error("vash.install(path, [string]) is not available in the standalone runtime.");c=b.compile(c)}return d[a]=c},b.uninstall=function(a){var c=b.helpers.tplcache,d=!1;if(typeof a=="string")return delete c[a];Object.keys(c).forEach(function(b){c[b]===a&&(d=delete c[b])});return d}}(),function(){var a=b.helpers;a.config.highlighter=null,a.highlight=function(b,c){var d=this.buffer.mark();c();var e=this.buffer.fromMark(d);this.buffer.push("<pre><code>"),a.config.highlighter?this.buffer.push(a.config.highlighter(b,e.join("")).value):this.buffer.push(e),this.buffer.push("</code></pre>")}}(),function(){if(typeof window=="undefined")var a=require("fs"),c=require("path");var d=b.helpers;d.config.browser=!1,b.loadFile=function(e,f,g){f=K.extend({},b.config,f||{});var h=d.config.browser,i;!h&&f.settings&&f.settings.views&&(e=c.normalize(e),e.indexOf(c.normalize(f.settings.views))===-1&&(e=c.join(f.settings.views,e)),c.extname(e)||(e+="."+(f.settings["view engine"]||"vash")));try{i=f.cache||h?d.tplcache[e]||(d.tplcache[e]=b.compile(a.readFileSync(e,"utf8"))):b.compile(a.readFileSync(e,"utf8")),g&&g(null,i)}catch(j){g&&g(j,null)}},b.renderFile=function(a,c,d){b.loadFile(a,c,function(a,b){var e=c.onRenderEnd;d(a,b(c,function(a,b){b.finishLayout(),e&&e(a,b)}))})},d._ensureLayoutProps=function(){this.appends=this.appends||{},this.prepends=this.prepends||{},this.blocks=this.blocks||{},this.blockMarks=this.blockMarks||{}},d.finishLayout=function(){this._ensureLayoutProps();var a=this,b,c,d,e,f,g,h,i;for(b in this.blockMarks)c=this.blockMarks[b],e=this.prepends[b],d=this.blocks[b],f=this.appends[b],g=c.pop(),h=this.buffer.mark(),e&&e.forEach(function(b){a.buffer.push(b)}),block=d.pop(),block&&this.buffer.push(block),f&&f.forEach(function(b){a.buffer.push(b)}),i=this.buffer.fromMark(h),i.unshift(g,0),this.buffer.spliceMark.apply(this.buffer,i);for(b in this.blockMarks)this.blockMarks[b].forEach(function(a){a.destroy()});delete this.blockMarks,delete this.prepends,delete this.blocks,delete this.appends;return this.toString()},d.extend=function(a,c){var d=this,e=this.buffer,f=this.model,g;this._ensureLayoutProps(),b.loadFile(a,this.model,function(a,b){var e=d.buffer.mark();c(d.model);var f=d.buffer.fromMark(e);d.isExtending=!0,b(d.model,{context:d}),d.isExtending=!1}),this.model=f},d.include=function(a,c){var d=this,e=this.buffer,f=this.model;b.loadFile(a,this.model,function(a,b){b(c||d.model,{context:d})}),this.model=f},d.block=function(a,b){this._ensureLayoutProps();var c=this,d=this.blockMarks[a]||(this.blockMarks[a]=[]),e=this.blocks[a]||(this.blocks[a]=[]),f,g;b&&(f=this.buffer.mark(),b(this.model),g=this.buffer.fromMark(f),g.length&&!this.isExtending&&e.push(g),g.length&&this.isExtending&&e.unshift(g)),d.push(this.buffer.mark("block-"+a))},d._handlePrependAppend=function(a,b,c){this._ensureLayoutProps();var d=this.buffer.mark(),e,f=this[a],g=f[b]||(f[b]=[]);c(this.model),e=this.buffer.fromMark(d),g.push(e)},d.append=function(a,b){this._handlePrependAppend("appends",a,b)},d.prepend=function(a,b){this._handlePrependAppend("prepends",a,b)}}(),a.__express=a.renderFile;var c="AT",d="ASSIGN_OPERATOR",e="AT_COLON",f="AT_STAR_CLOSE",g="AT_STAR_OPEN",h="BACKSLASH",i="BRACE_CLOSE",j="BRACE_OPEN",k="CONTENT",l="DOUBLE_QUOTE",m="EMAIL",n="FAT_ARROW",o="FUNCTION",p="HARD_PAREN_CLOSE",q="HARD_PAREN_OPEN",r="HTML_TAG_CLOSE",s="HTML_TAG_OPEN",t="HTML_TAG_SELFCLOSE",u="IDENTIFIER",v="KEYWORD",w="LOGICAL",x="NEWLINE",y="NUMERIC_CONTENT",z="OPERATOR",A="PAREN_CLOSE",B="PAREN_OPEN",C="PERIOD",D="SINGLE_QUOTE",E="TEXT_TAG_CLOSE",F="TEXT_TAG_OPEN",G="WHITESPACE",H={};H[g]=f,H[j]=i,H[l]=l,H[q]=p,H[B]=A,H[D]=D,H[e]=x;var I=[m,/^([a-zA-Z0-9.%]+@[a-zA-Z0-9.\-]+\.(?:ca|co\.uk|com|edu|net|org))\b/,g,/^(@\*)/,f,/^(\*@)/,e,/^(@\:)/,c,/^(@)/,n,/^(\(.*?\)?\s*?=>)/,B,/^(\()/,A,/^(\))/,q,/^(\[)/,p,/^(\])/,j,/^(\{)/,i,/^(\})/,F,/^(<text>)/,E,/^(<\/text>)/,t,/^(<[^@>]+?\/>)/,s,function(){var a=/^(<[^\/=+< >]+?[^>]*?>)/,b=/([a-zA-Z0-9.%]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,4})\b/,c=this.scan(a,s);c&&(this.spewIf(c,b),this.spewIf(c,/(@)/));return c},r,/^(<\/[^>@\b]+?>)/,C,/^(\.)/,x,function(){var a=this.scan(/^(\n)/,x);a&&(this.lineno++,this.charno=0);return a},G,/^(\s)/,o,/^(function)(?![\d\w])/,v,/^(case|catch|do|else|finally|for|function|goto|if|instanceof|return|switch|try|typeof|var|while|with)(?![\d\w])/,u,/^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)/,z,/^(===|!==|==|!==|>>>|<<|>>|>=|<=|>|<|\+|-|\/|\*|\^|%|\:|\?)/,d,/^(\|=|\^=|&=|>>>=|>>=|<<=|-=|\+=|%=|\/=|\*=|=)/,w,/^(&&|\|\||&|\||\^)/,h,/^(\\)/,l,/^(\")/,D,/^(\')/,y,/^([0-9]+)/,k,/^([^\s})@.]+?)/];J.prototype={scan:function(a,b){var c,d;if(c=a.exec(this.input)){this.input=this.input.substr(c[1].length),d={type:b,line:this.lineno,chr:this.charno,val:c[1]||"",toString:function(){return"["+this.type+" ("+this.line+","+this.chr+"): "+this.val+"]"}},this.charno+=c[0].length;return d}},spewIf:function(a,b){var c,d,e;a&&(c=b.exec(a.val),c&&(d=a.val.indexOf(c[1]),e=a.val.substring(d),this.input=e+this.input,this.charno-=e.length,a.val=a.val.substring(0,d)));return a},advance:function(){var a,b,c,d;for(a=0;a<I.length;a+=2){c=I[a+1],c.displayName=I[a],typeof c=="function"&&(d=c.call(this)),typeof c.exec=="function"&&(d=this.scan(c,I[a]));if(d)return d}}};var K=function(a){return new K.fn.init(a)};K.prototype.init=function(a){typeof a=="string"&&(this.mode=a),this.maxCheck()},K.fn=K.prototype.init.prototype=K.prototype,K.fn.vquery="yep",K.fn.constructor=K,K.fn.length=0,K.fn.parent=null,K.fn.mode=null,K.fn.tagName=null,K.fn.beget=function(a,b){var c=K(a);c.parent=this,this.push(c),b&&(c.tagName=b),this.maxCheck();return c},K.fn.closest=function(a,b){var c=this;while(c)if(c.tagName!==b&&c.parent)c=c.parent;else break;return c},K.fn.pushFlatten=function(a){var b=a,c,d;while(b.length===1&&b[0].vquery)b=b[0];if(b.mode!==M)this.push(b);else for(c=0;c<b.length;c++)this.push(b[c]);this.maxCheck();return this},K.fn.push=function(a){K.isArray(a)?(a.vquery&&a.forEach(function(a){a.parent=this},this),Array.prototype.push.apply(this,a)):(a.vquery&&(a.parent=this),Array.prototype.push.call(this,a)),this.maxCheck();return this.length},K.fn.root=function(){var a=this;while(a&&a.parent&&(a=a.parent));return a},K.fn.toTreeString=function(){function c(d){var e,f;a.push(Array(b).join(" |")+" +"+d.mode+" "+(d.tagName||"")),b+=1,e=d.slice();while(f=e.shift())f.vquery===K.fn.vquery?c(f):a.push(Array(b).join(" |")+" "+(f?f.toString().replace(/(\r|\n)/g,""):"[empty]"));b-=1,a.push(Array(b).join(" |")+" -"+d.mode+" "+(d.tagName||""))}var a=[],b=1;c(this);return a.join("\n")},K.fn.maxCheck=function(a){if(this.length>=K.maxSize){var b=new Error;b.message="Maximum number of elements exceeded.\nThis is typically caused by an unmatched character or tag. Parse tree follows:\n"+this.toTreeString(),b.name="vQueryDepthException";throw b}},K.maxSize=1e3,K.fn.flatten=function(){var a;return this.reduce(function b(c,d,e,f){if(d.vquery){c.push({type:"META",val:"START"+d.mode,tagName:d.tagName}),a=d.reduce(b,c),a.push({type:"META",val:"END"+d.mode,tagName:d.tagName});return a}d.mode=f.mode,c.push(d);return c},[])},K.reconstitute=function(a){return a.reduce(function b(a,b,c,d){b.type==="META"?a=a.parent:(b.mode!==a.mode&&(a=a.beget(b.mode,b.tagName)),a.push(b));return a},K(M))},K.isArray=function(a){return Object.prototype.toString.call(a)=="[object Array]"},K.extend=function(a){var b,c,d;for(c=1;c<arguments.length;c++){b=arguments[c];for(d in b)a[d]=b[d]}return a},K.takeMethodsFromArray=function(){var a=["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"],b=[],c;for(var d=0;d<a.length;d++){c=a[d];if(typeof b[c]=="function")K.fn[c]||function(a){K.fn[a]=function(){return b[a].apply(this,Array.prototype.slice.call(arguments,0))}}(c);else throw new Error("Vash requires ES5 array iteration methods, missing: "+c)}},K.takeMethodsFromArray();var M="PROGRAM",N="MARKUP",O="BLOCK",P="EXPRESSION";L.prototype={parse:function(){var a,b,c,d;while(this.prevTokens.push(a),a=this.tokens.pop()){this.options.debugParser&&console.log(this.ast&&this.ast.mode,a.type,a.toString(),a.val);if(this.ast.mode===M||this.ast.mode===null)this.ast=this.ast.beget(this.options.initialMode||N),this.options.initialMode===P&&(this.ast=this.ast.beget(P));if(this.ast.mode===N){this.handleMKP(a);continue}if(this.ast.mode===O){this.handleBLK(a);continue}if(this.ast.mode===P){this.handleEXP(a);continue}}this.ast=this.ast.root(),this.options.debugParser&&!this.options.initialMode&&(console.log(this.ast.toString()),console.log(this.ast.toTreeString()));return this.ast},exceptionFactory:function(a,b,c){b=="UNMATCHED"&&(a.name="UnmatchedCharacterError",this.ast=this.ast.root(),c&&(a.message="Unmatched "+c.type+" at line "+c.line+", character "+c.chr+". Value: "+c.val+"\n "+this.ast.toTreeString(),a.lineNumber=c.line));return a},advanceUntilNot:function(a){var b,c,d=[];while(c=this.tokens[this.tokens.length-1])if(c.type===a)b=this.tokens.pop(),d.push(b);else break;return d},advanceUntilMatched:function(a,b,c,d,e){var f=a,g=null,h=0,i=0,j=[];while(f){f.type===b?g&&g.type!==d&&b!==c||!g?h++:b===c&&g.type!==d&&i++:f.type===c&&(i++,g&&g.type===e&&i--),j.push(f);if(h===i)break;g=f,f=this.tokens.pop();if(!f)throw this.exceptionFactory(new Error,"UNMATCHED",a)}return j.reverse()},subParse:function(a,b,d){var e,f,g,h=K.extend({},this.options);h.initialMode=b,e=this.advanceUntilMatched(a,a.type,H[a.type],null,c),e.pop(),f=e.shift(),d||this.ast.push(a),g=new L(e,h),g.parse(),d&&(g.ast[0].unshift(a),g.ast[0].push(f)),this.ast.pushFlatten(g.ast),d||this.ast.push(f)},handleMKP:function(a){var b=this.tokens[this.tokens.length-1],d=this.tokens[this.tokens.length-2],e=null,h;switch(a.type){case g:this.advanceUntilMatched(a,g,f,c,c);break;case c:if(b){this.options.saveAT&&this.ast.push(a);switch(b.type){case B:case u:this.ast.length===0&&(this.ast=this.ast.parent,this.ast.pop()),this.ast=this.ast.beget(P);break;case v:case o:case j:this.ast.length===0&&(this.ast=this.ast.parent,this.ast.pop()),this.ast=this.ast.beget(O);break;case c:b.type="CONTENT",this.ast.push(this.tokens.pop());break;default:this.ast.push(this.tokens.pop())}}break;case F:case s:e=a.val.match(/^<([^\/ >]+)/i),e===null&&b&&b.type===c&&d&&(e=d.val.match(/(.*)/)),this.ast.tagName?this.ast=this.ast.beget(N,e[1]):this.ast.tagName=e[1],(s===a.type||this.options.saveTextTag)&&this.ast.push(a);break;case E:case r:e=a.val.match(/^<\/([^>]+)/i),e===null&&b&&b.type===c&&d&&(e=d.val.match(/(.*)/)),h=this.ast.closest(N,e[1]),h!==null&&h.tagName===e[1]&&(this.ast=h),(r===a.type||this.options.saveTextTag)&&this.ast.push(a),this.ast.parent&&this.ast.parent.mode===O&&(this.ast=this.ast.parent);break;case t:this.ast.push(a),this.ast.parent&&this.ast.parent.mode===O&&(this.ast=this.ast.parent);break;default:this.ast.push(a)}},handleBLK:function(a){var b=this.tokens[this.tokens.length-1],d,h,i,k,l,m,n;switch(a.type){case c:b.type!==c&&(this.tokens.push(a),this.ast=this.ast.beget(N));break;case g:this.advanceUntilMatched(a,g,f,c,c);break;case e:this.subParse(a,N,!0);break;case F:case E:case t:case s:case r:this.ast=this.ast.beget(N),this.tokens.push(a);break;case j:case B:d=this.options.favorText&&a.type===j?N:O,this.subParse(a,d),k=this.advanceUntilNot(G),b=this.tokens[this.tokens.length-1],b&&b.type!==v&&b.type!==o&&b.type!==j&&a.type!==B?(this.tokens.push.apply(this.tokens,k.reverse()),this.ast=this.ast.parent):this.ast.push(k);break;case G:this.ast.push(a),this.advanceUntilNot(G);break;default:this.ast.push(a)}},handleEXP:function(a){var b=null,e,f,g,i,k,m,r;switch(a.type){case v:case o:this.ast=this.ast.beget(O),this.tokens.push(a);break;case G:case w:case d:case z:case y:this.ast.parent&&this.ast.parent.mode===P?this.ast.push(a):(this.ast=this.ast.parent,this.tokens.push(a));break;case u:this.ast.push(a);break;case D:case l:this.ast.parent&&this.ast.parent.mode===P?(k=this.advanceUntilMatched(a,a.type,H[a.type],h,h),this.ast.pushFlatten(k.reverse())):(this.ast=this.ast.parent,this.tokens.push(a));break;case q:case B:m=this.prevTokens[this.prevTokens.length-1],b=this.tokens[this.tokens.length-1];if(a.type===q&&b.type===p){this.tokens.push(a),this.ast=this.ast.parent;break}this.subParse(a,P),b=this.tokens[this.tokens.length-1];if(m&&m.type===c||b&&b.type===u)this.ast=this.ast.parent;break;case j:this.tokens.push(a),this.ast=this.ast.beget(O);break;case n:this.tokens.push(a),this.ast=this.ast.beget(O);break;case C:b=this.tokens[this.tokens.length-1],b&&(b.type===u||b.type===v||b.type===o||b.type===C||this.ast.parent&&this.ast.parent.mode===P)?this.ast.push(a):(this.ast=this.ast.parent,this.tokens.push(a));break;default:this.ast.parent&&this.ast.parent.mode!==P?(this.ast=this.ast.parent,this.tokens.push(a)):this.ast.push(a)}}};var R=Q.prototype;R.insertDebugVars=function(a){this.options.debug&&this.buffer.push(this.options.helpersName+".vl = "+a.line+", ",this.options.helpersName+".vc = "+a.chr+"; \n")},R.visitMarkupTok=function(a,b,c){this.insertDebugVars(a),this.buffer.push("MKP('"+a.val.replace(this.reQuote,"\\$1").replace(this.reLineBreak,"\\n")+"')MKP")},R.visitBlockTok=function(a,b,c){this.buffer.push(a.val)},R.visitExpressionTok=function(a,b,c,d){var e="",f="",g=b.parent&&b.parent.mode!==P;this.options.htmlEscape!==!1&&(g&&c===0&&d&&(e+=this.options.helpersName+".escape("),g&&c===b.length-1&&d&&(f+=").toHtmlString()")),g&&c===0&&(this.insertDebugVars(a),e="__vbuffer.push("+e),g&&c===b.length-1&&(f+="); \n"),this.buffer.push(e+a.val+f),g&&c===b.length-1&&this.insertDebugVars(a)},R.visitNode=function(a){var b,d=a.slice(0),f,g,h;a.mode===P&&a.parent&&a.parent.mode!==P&&(f=a.filter(Q.findNonExp).length);for(g=0;g<d.length;g++){h=d[g];if(h.type&&h.type===c||h.type===e)continue;h.vquery?this.visitNode(h):a.mode===N?this.visitMarkupTok(h,a,g):a.mode===O?this.visitBlockTok(h,a,g):a.mode===P&&this.visitExpressionTok(h,a,g,f>0?!1:!0)}},R.escapeForDebug=function(a){return a.replace(this.reLineBreak,"!LB!").replace(this.reQuote,"\\$1").replace(this.reEscapedQuote,"\\$1")},R.replaceDevTokens=function(a){return a.replace(this.reHelpersName,this.options.helpersName).replace(this.reModelName,this.options.modelName)},R.wrapBody=function(a){var b=this.options,c=""+(b.debug?"try { \n":"")+"var __vbuffer = HELPERSNAME.buffer; \n"+"MODELNAME = MODELNAME || {}; \n"+(b.useWith?"with( MODELNAME ){ \n":""),d="(__vopts && __vopts.onRenderEnd && __vopts.onRenderEnd(null, HELPERSNAME)); \nreturn (__vopts && __vopts.asContext) \n ? HELPERSNAME \n : HELPERSNAME.toString(); \n"+(b.debug?'} catch( e ){ \n HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n} \n':"")+(b.useWith?"} \n":"");c=this.replaceDevTokens(c),d=this.replaceDevTokens(d).replace(this.reOriginalMarkup,this.escapeForDebug(this.originalMarkup));return c+a+d},R.generate=function(){var a=this.options;this.buffer.length=0,this.visitNode(this.ast);var c=this.buffer.join("").split("')MKPMKP('").join("").split("MKP(").join("__vbuffer.push(").split(")MKP").join("); \n");c=this.wrapBody(c),a.debugCompiler&&console.log(c),this.cmpFunc=b.link(c,a.modelName,a.helpersName);return this.cmpFunc},Q.noop=function(){},Q.findNonExp=function(a){return a.vquery&&a.mode===P?a.filter(Q.findNonExp).length>0:a.vquery&&a.mode!==P?!0:!1},a.VLexer=J,a.VParser=L,a.VCompiler=Q,a.vQuery=K;return a}({})) | ||
(function(a){typeof define=="function"&&define.amd?define(function(){return a}):typeof module=="object"&&module.exports?module.exports=a:window.vash=a})(function(a){function U(a,b,c){this.ast=a,this.originalMarkup=b||"",this.options=c||{},this.reQuote=/(["'])/gi,this.reEscapedQuote=/\\+(["'])/gi,this.reLineBreak=/[\n\r]/gi,this.reHelpersName=/HELPERSNAME/g,this.reModelName=/MODELNAME/g,this.reOriginalMarkup=/ORIGINALMARKUP/g,this.buffer=[]}function P(a,b){this.options=b||{},this.tokens=a,this.ast=O(Q),this.prevTokens=[]}function N(a){this.input=this.originalInput=a.replace(/\r\n|\r/g,"\n"),this.lineno=1,this.charno=0}var b=a;a.version="0.6.0-2085",a.config={useWith:!1,modelName:"model",helpersName:"html",htmlEscape:!0,debug:!0,debugParser:!1,debugCompiler:!1,simple:!1,favorText:!1,saveTextTag:!1,saveAT:!1},a.compile=function(b,c){if(b===""||typeof b!="string")throw new Error("Empty or non-string cannot be compiled");var d,e,f=[],g,h,i,j;c=O.extend({},a.config,c||{}),d=new N(b);while(e=d.advance())f.push(e);f.reverse(),g=new P(f,c),g.parse(),h=new U(g.ast,b,c),i=h.generate();return i},a.batch=function(a,d){var e=c(a).batch;e&&Object.keys(e).forEach(function(a){e[a]=b.compile(e[a],d)});return e};var c=function(a){var b=/^\/\/\s*@\s*(batch|helper)\s*=\s*(.*?)$/,c=a.split(/[\n\r]/g),d={batch:{},helper:{}},e=[],f="",g=d.batch;c.forEach(function(a,c,e){var h=b.exec(a),i=c===e.length-1;(!h||i)&&d[g][f].push(a),(h||i)&&f&&(d[g][f]=d[g][f].join("\n")),h&&(g=h[1],f=h[2].replace(/^\s+|\s+$/,""),d[g][f]=[])});return d},d=Array.prototype.slice,e=/^vash\.helpers\.([^= ]+?)\s*=\s*function([^(]*?)\(([^)]*?)\)\s*{/,f=/\}$/;a.compileHelper=function(a,c){c=c||{};var d=a.replace(/^\s+|\s+$/,"").match(e),g=d[3].split(",").map(function(a){return a.replace(" ","")}),h=d[1],i=a.replace(e,"").replace(f,"");i="@{"+i+"}",c.args=g,c.asHelper=h,b.compile(i,c)},function(){function j(a,b){typeof b=="function"&&(b={onRenderEnd:b}),a&&a.onRenderEnd&&(b=b||{},b.onRenderEnd||(b.onRenderEnd=a.onRenderEnd),delete a.onRenderEnd);return b}b=typeof b=="undefined"?{}:b,b.compile||(typeof define=="function"&&define.amd?define(function(){return b}):typeof module=="object"&&module.exports?module.exports=b:window.vash=b);var a=b.helpers,c=function(a){this.buffer=new g,this.model=a,this.vl=0,this.vc=0};b.helpers=a=c.prototype={constructor:c,config:{},tplcache:{}},a.toString=a.toHtmlString=function(){return this.buffer._vo.join("")};var d=/[&<>"'`]/g,e=function(a){return f[a]},f={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};a.raw=function(a){var b=function(){return a};a=a!=null?a:"";return{toHtmlString:b,toString:b}},a.escape=function(a){var b=function(){return a};a=a!=null?a:"";if(typeof a.toHtmlString!="function"){a=a.toString().replace(d,e);return{toHtmlString:b,toString:b}}return a};var g=function(){this._vo=[]};g.prototype.mark=function(a){var b=new h(this,a);b.markedIndex=this._vo.length,this._vo.push(b.uid);return b},g.prototype.fromMark=function(a){var b=a.findInBuffer();if(b>-1){a.destroy();return this._vo.splice(b,this._vo.length)}return[]},g.prototype.spliceMark=function(a,b,c){var d=a.findInBuffer();if(d>-1){a.destroy(),arguments[0]=d;return this._vo.splice.apply(this._vo,arguments)}return[]},g.prototype.empty=function(){return this._vo.splice(0,this._vo.length)},g.prototype.push=function(a){return this._vo.push(a)},g.prototype.pushConcat=function(a){a instanceof Array?this._vo.push.apply(this._vo,a):arguments.length>1?this._vo.push.apply(this._vo,Array.prototype.slice.call(arguments)):this._vo.push(a);return this.__vo},g.prototype.indexOf=function(a){for(var b=0;b<this._vo.length;b++)if(this._vo[b]==a)return b;return-1},g.prototype.splice=function(){return this._vo.splice.apply(this._vo,arguments)},g.prototype.index=function(a){return this._vo[a]},g.prototype.flush=function(){return this.empty().join("")},g.prototype.toString=g.prototype.toHtmlString=function(){return this._vo.join("")};var h=b.Mark=function(a,b){this.uid="[VASHMARK-"+~~(Math.random()*1e7)+(b?":"+b:"")+"]",this.markedIndex=0,this.buffer=a,this.destroyed=!1},i=/\[VASHMARK\-\d{1,8}(?::[\s\S]+?)?]/g;h.uidLike=function(a){return(a||"").search(i)>-1},h.prototype.destroy=function(){var a=this.findInBuffer();a>-1&&(this.buffer.splice(a,1),this.markedIndex=-1),this.destroyed=!0},h.prototype.findInBuffer=function(){return this.destroyed?-1:this.markedIndex&&this.buffer.index(this.markedIndex)===this.uid?this.markedIndex:this.markedIndex=this.buffer.indexOf(this.uid)},a.constructor.reportError=function(a,b,c,d,e){e=e||"!LB!";var f=d.split(e),g=b===0&&c===0?f.length-1:3,h=Math.max(0,b-g),i=Math.min(f.length,b+g),j=f.slice(h,i).map(function(a,c,d){var e=c+h+1;return(e===b?" > ":" ")+(e<10?" ":"")+e+" | "+a}).join("\n");a.message="Problem while rendering template at line "+b+", character "+c+".\nOriginal message: "+a.message+"."+"\nContext: \n\n"+j+"\n\n";throw a},a.reportError=function(){this.constructor.reportError.apply(this,arguments)},b.link=function(d,e){var f,g;e.args||(e.args=[e.modelName,e.helpersName,"__vopts","vash"]);if(typeof d=="string"){f=d;try{g=e.args.slice(),g.push(d),d=Function.apply(null,g)}catch(h){a.reportError(h,0,0,f,/\n/)}}d.options={simple:e.simple,modelName:e.modelName,helpersName:e.helpersName};var i;e.asHelper?(d.options.args=e.args,d.options.asHelper=e.asHelper,i=function(){return d.apply(this,k.call(arguments))},a[e.asHelper]=i):i=function(a,f){if(e.simple){var g={buffer:[],escape:c.prototype.escape,raw:c.prototype.raw};return d(a,g,f,b)}f=j(a,f);return d(a,f&&f.context||new c(a),f,b)},i.toString=function(){return d.toString()},i._toString=function(){return Function.prototype.toString.call(i)},i.toClientString=function(){return"vash.link( "+d.toString()+", "+JSON.stringify(d.options)+" )"};return i};var k=Array.prototype.slice;b.lookup=function(a,c){var d=b.helpers.tplcache[a];if(!d)throw new Error("Could not find template: "+a);return c?d(c):d},b.install=function(a,c){var d=b.helpers.tplcache;if(typeof c=="string"){if(!b.compile)throw new Error("vash.install(path, [string]) is not available in the standalone runtime.");c=b.compile(c)}else if(typeof a=="object"){c=a,Object.keys(c).forEach(function(a){d[a]=c[a]});return d}return d[a]=c},b.uninstall=function(a){var c=b.helpers.tplcache,d=!1;if(typeof a=="string")return delete c[a];Object.keys(c).forEach(function(b){c[b]===a&&(d=delete c[b])});return d}}(),function(){var a=b.helpers;a.config.highlighter=null,a.highlight=function(b,c){var d=this.buffer.mark();c();var e=this.buffer.fromMark(d);this.buffer.push("<pre><code>"),a.config.highlighter?this.buffer.push(a.config.highlighter(b,e.join("")).value):this.buffer.push(e),this.buffer.push("</code></pre>")}}(),function(){if(typeof window=="undefined")var a=require("fs"),c=require("path");var d=b.helpers;d.config.browser=!1,b.loadFile=function(e,f,g){f=O.extend({},b.config,f||{});var h=d.config.browser,i;!h&&f.settings&&f.settings.views&&(e=c.normalize(e),e.indexOf(c.normalize(f.settings.views))===-1&&(e=c.join(f.settings.views,e)),c.extname(e)||(e+="."+(f.settings["view engine"]||"vash")));try{i=f.cache||h?d.tplcache[e]||(d.tplcache[e]=b.compile(a.readFileSync(e,"utf8"))):b.compile(a.readFileSync(e,"utf8")),g&&g(null,i)}catch(j){g&&g(j,null)}},b.renderFile=function(a,c,d){b.loadFile(a,c,function(a,b){var e=c.onRenderEnd;d(a,b(c,function(a,b){b.finishLayout(),e&&e(a,b)}))})},d._ensureLayoutProps=function(){this.appends=this.appends||{},this.prepends=this.prepends||{},this.blocks=this.blocks||{},this.blockMarks=this.blockMarks||{}},d.finishLayout=function(){this._ensureLayoutProps();var a=this,b,c,d,e,f,g,h,i;for(b in this.blockMarks)c=this.blockMarks[b],e=this.prepends[b],d=this.blocks[b],f=this.appends[b],g=c.pop(),h=this.buffer.mark(),e&&e.forEach(function(b){a.buffer.pushConcat(b)}),block=d.pop(),block&&this.buffer.pushConcat(block),f&&f.forEach(function(b){a.buffer.pushConcat(b)}),i=this.buffer.fromMark(h),i.unshift(g,0),this.buffer.spliceMark.apply(this.buffer,i);for(b in this.blockMarks)this.blockMarks[b].forEach(function(a){a.destroy()});delete this.blockMarks,delete this.prepends,delete this.blocks,delete this.appends;return this.toString()},d.extend=function(a,c){var d=this,e=this.buffer,f=this.model,g;this._ensureLayoutProps(),b.loadFile(a,this.model,function(a,b){var e=d.buffer.mark();c(d.model);var f=d.buffer.fromMark(e);d.isExtending=!0,b(d.model,{context:d}),d.isExtending=!1}),this.model=f},d.include=function(a,c){var d=this,e=this.buffer,f=this.model;b.loadFile(a,this.model,function(a,b){b(c||d.model,{context:d})}),this.model=f},d.block=function(a,b){this._ensureLayoutProps();var c=this,d=this.blockMarks[a]||(this.blockMarks[a]=[]),e=this.blocks[a]||(this.blocks[a]=[]),f,g;b&&(f=this.buffer.mark(),b(this.model),g=this.buffer.fromMark(f),g.length&&!this.isExtending&&e.push(g),g.length&&this.isExtending&&e.unshift(g)),d.push(this.buffer.mark("block-"+a))},d._handlePrependAppend=function(a,b,c){this._ensureLayoutProps();var d=this.buffer.mark(),e,f=this[a],g=f[b]||(f[b]=[]);c(this.model),e=this.buffer.fromMark(d),g.push(e)},d.append=function(a,b){this._handlePrependAppend("appends",a,b)},d.prepend=function(a,b){this._handlePrependAppend("prepends",a,b)}}(),a.__express=a.renderFile;var g="AT",h="ASSIGN_OPERATOR",i="AT_COLON",j="AT_STAR_CLOSE",k="AT_STAR_OPEN",l="BACKSLASH",m="BRACE_CLOSE",n="BRACE_OPEN",o="CONTENT",p="DOUBLE_QUOTE",q="EMAIL",r="FAT_ARROW",s="FUNCTION",t="HARD_PAREN_CLOSE",u="HARD_PAREN_OPEN",v="HTML_TAG_CLOSE",w="HTML_TAG_OPEN",x="HTML_TAG_SELFCLOSE",y="IDENTIFIER",z="KEYWORD",A="LOGICAL",B="NEWLINE",C="NUMERIC_CONTENT",D="OPERATOR",E="PAREN_CLOSE",F="PAREN_OPEN",G="PERIOD",H="SINGLE_QUOTE",I="TEXT_TAG_CLOSE",J="TEXT_TAG_OPEN",K="WHITESPACE",L={};L[k]=j,L[n]=m,L[p]=p,L[u]=t,L[F]=E,L[H]=H,L[i]=B;var M=[q,/^([a-zA-Z0-9.%]+@[a-zA-Z0-9.\-]+\.(?:ca|co\.uk|com|edu|net|org))\b/,k,/^(@\*)/,j,/^(\*@)/,i,/^(@\:)/,g,/^(@)/,r,/^(\(.*?\)?\s*?=>)/,F,/^(\()/,E,/^(\))/,u,/^(\[)/,t,/^(\])/,n,/^(\{)/,m,/^(\})/,J,/^(<text>)/,I,/^(<\/text>)/,x,/^(<[^@>]+?\/>)/,w,function(){var a=/^(<[^\/=+< >]+?[^>]*?>)/,b=/([a-zA-Z0-9.%]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,4})\b/,c=this.scan(a,w);c&&(this.spewIf(c,b),this.spewIf(c,/(@)/));return c},v,/^(<\/[^>@\b]+?>)/,G,/^(\.)/,B,function(){var a=this.scan(/^(\n)/,B);a&&(this.lineno++,this.charno=0);return a},K,/^(\s)/,s,/^(function)(?![\d\w])/,z,/^(case|catch|do|else|finally|for|function|goto|if|instanceof|return|switch|try|typeof|var|while|with)(?![\d\w])/,y,/^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)/,D,/^(===|!==|==|!==|>>>|<<|>>|>=|<=|>|<|\+|-|\/|\*|\^|%|\:|\?)/,h,/^(\|=|\^=|&=|>>>=|>>=|<<=|-=|\+=|%=|\/=|\*=|=)/,A,/^(&&|\|\||&|\||\^)/,l,/^(\\)/,p,/^(\")/,H,/^(\')/,C,/^([0-9]+)/,o,/^([^\s})@.]+?)/];N.prototype={scan:function(a,b){var c,d;if(c=a.exec(this.input)){this.input=this.input.substr(c[1].length),d={type:b,line:this.lineno,chr:this.charno,val:c[1]||"",toString:function(){return"["+this.type+" ("+this.line+","+this.chr+"): "+this.val+"]"}},this.charno+=c[0].length;return d}},spewIf:function(a,b){var c,d,e;a&&(c=b.exec(a.val),c&&(d=a.val.indexOf(c[1]),e=a.val.substring(d),this.input=e+this.input,this.charno-=e.length,a.val=a.val.substring(0,d)));return a},advance:function(){var a,b,c,d;for(a=0;a<M.length;a+=2){c=M[a+1],c.displayName=M[a],typeof c=="function"&&(d=c.call(this)),typeof c.exec=="function"&&(d=this.scan(c,M[a]));if(d)return d}}};var O=function(a){return new O.fn.init(a)};O.prototype.init=function(a){typeof a=="string"&&(this.mode=a),this.maxCheck()},O.fn=O.prototype.init.prototype=O.prototype,O.fn.vquery="yep",O.fn.constructor=O,O.fn.length=0,O.fn.parent=null,O.fn.mode=null,O.fn.tagName=null,O.fn.beget=function(a,b){var c=O(a);c.parent=this,this.push(c),b&&(c.tagName=b),this.maxCheck();return c},O.fn.closest=function(a,b){var c=this;while(c)if(c.tagName!==b&&c.parent)c=c.parent;else break;return c},O.fn.pushFlatten=function(a){var b=a,c,d;while(b.length===1&&b[0].vquery)b=b[0];if(b.mode!==Q)this.push(b);else for(c=0;c<b.length;c++)this.push(b[c]);this.maxCheck();return this},O.fn.push=function(a){O.isArray(a)?(a.vquery&&a.forEach(function(a){a.parent=this},this),Array.prototype.push.apply(this,a)):(a.vquery&&(a.parent=this),Array.prototype.push.call(this,a)),this.maxCheck();return this.length},O.fn.root=function(){var a=this;while(a&&a.parent&&(a=a.parent));return a},O.fn.toTreeString=function(){function c(d){var e,f;a.push(Array(b).join(" |")+" +"+d.mode+" "+(d.tagName||"")),b+=1,e=d.slice();while(f=e.shift())f.vquery===O.fn.vquery?c(f):a.push(Array(b).join(" |")+" "+(f?f.toString().replace(/(\r|\n)/g,""):"[empty]"));b-=1,a.push(Array(b).join(" |")+" -"+d.mode+" "+(d.tagName||""))}var a=[],b=1;c(this);return a.join("\n")},O.fn.maxCheck=function(a){if(this.length>=O.maxSize){var b=new Error;b.message="Maximum number of elements exceeded.\nThis is typically caused by an unmatched character or tag. Parse tree follows:\n"+this.toTreeString(),b.name="vQueryDepthException";throw b}},O.maxSize=1e3,O.fn.flatten=function(){var a;return this.reduce(function b(c,d,e,f){if(d.vquery){c.push({type:"META",val:"START"+d.mode,tagName:d.tagName}),a=d.reduce(b,c),a.push({type:"META",val:"END"+d.mode,tagName:d.tagName});return a}d.mode=f.mode,c.push(d);return c},[])},O.reconstitute=function(a){return a.reduce(function b(a,b,c,d){b.type==="META"?a=a.parent:(b.mode!==a.mode&&(a=a.beget(b.mode,b.tagName)),a.push(b));return a},O(Q))},O.isArray=function(a){return Object.prototype.toString.call(a)=="[object Array]"},O.extend=function(a){var b,c,d;for(c=1;c<arguments.length;c++){b=arguments[c];for(d in b)a[d]=b[d]}return a},O.takeMethodsFromArray=function(){var a=["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"],b=[],c;for(var d=0;d<a.length;d++){c=a[d];if(typeof b[c]=="function")O.fn[c]||function(a){O.fn[a]=function(){return b[a].apply(this,Array.prototype.slice.call(arguments,0))}}(c);else throw new Error("Vash requires ES5 array iteration methods, missing: "+c)}},O.takeMethodsFromArray();var Q="PROGRAM",R="MARKUP",S="BLOCK",T="EXPRESSION";P.prototype={parse:function(){var a,b,c,d;while(this.prevTokens.push(a),a=this.tokens.pop()){this.options.debugParser&&console.log(this.ast&&this.ast.mode,a.type,a.toString(),a.val);if(this.ast.mode===Q||this.ast.mode===null)this.ast=this.ast.beget(this.options.initialMode||R),this.options.initialMode===T&&(this.ast=this.ast.beget(T));if(this.ast.mode===R){this.handleMKP(a);continue}if(this.ast.mode===S){this.handleBLK(a);continue}if(this.ast.mode===T){this.handleEXP(a);continue}}this.ast=this.ast.root(),this.options.debugParser&&!this.options.initialMode&&(console.log(this.ast.toString()),console.log(this.ast.toTreeString()));return this.ast},exceptionFactory:function(a,b,c){b=="UNMATCHED"&&(a.name="UnmatchedCharacterError",this.ast=this.ast.root(),c&&(a.message="Unmatched "+c.type+" at line "+c.line+", character "+c.chr+". Value: "+c.val+"\n "+this.ast.toTreeString(),a.lineNumber=c.line));return a},advanceUntilNot:function(a){var b,c,d=[];while(c=this.tokens[this.tokens.length-1])if(c.type===a)b=this.tokens.pop(),d.push(b);else break;return d},advanceUntilMatched:function(a,b,c,d,e){var f=a,g=null,h=0,i=0,j=[];while(f){f.type===b?g&&g.type!==d&&b!==c||!g?h++:b===c&&g.type!==d&&i++:f.type===c&&(i++,g&&g.type===e&&i--),j.push(f);if(h===i)break;g=f,f=this.tokens.pop();if(!f)throw this.exceptionFactory(new Error,"UNMATCHED",a)}return j.reverse()},subParse:function(a,b,c){var d,e,f,h=O.extend({},this.options);h.initialMode=b,d=this.advanceUntilMatched(a,a.type,L[a.type],null,g),d.pop(),e=d.shift(),c||this.ast.push(a),f=new P(d,h),f.parse(),c&&(f.ast[0].unshift(a),f.ast[0].push(e)),this.ast.pushFlatten(f.ast),c||this.ast.push(e)},handleMKP:function(a){var b=this.tokens[this.tokens.length-1],c=this.tokens[this.tokens.length-2],d=null,e;switch(a.type){case k:this.advanceUntilMatched(a,k,j,g,g);break;case g:if(b){this.options.saveAT&&this.ast.push(a);switch(b.type){case F:case y:this.ast.length===0&&(this.ast=this.ast.parent,this.ast.pop()),this.ast=this.ast.beget(T);break;case z:case s:case n:this.ast.length===0&&(this.ast=this.ast.parent,this.ast.pop()),this.ast=this.ast.beget(S);break;case g:b.type="CONTENT",this.ast.push(this.tokens.pop());break;default:this.ast.push(this.tokens.pop())}}break;case J:case w:d=a.val.match(/^<([^\/ >]+)/i),d===null&&b&&b.type===g&&c&&(d=c.val.match(/(.*)/)),this.ast.tagName?this.ast=this.ast.beget(R,d[1]):this.ast.tagName=d[1],(w===a.type||this.options.saveTextTag)&&this.ast.push(a);break;case I:case v:d=a.val.match(/^<\/([^>]+)/i),d===null&&b&&b.type===g&&c&&(d=c.val.match(/(.*)/)),e=this.ast.closest(R,d[1]),e!==null&&e.tagName===d[1]&&(this.ast=e),(v===a.type||this.options.saveTextTag)&&this.ast.push(a),this.ast.parent&&this.ast.parent.mode===S&&(this.ast=this.ast.parent);break;case x:this.ast.push(a),this.ast.parent&&this.ast.parent.mode===S&&(this.ast=this.ast.parent);break;default:this.ast.push(a)}},handleBLK:function(a){var b=this.tokens[this.tokens.length-1],c,d,e,f,h,l,m;switch(a.type){case g:b.type!==g&&(this.tokens.push(a),this.ast=this.ast.beget(R));break;case k:this.advanceUntilMatched(a,k,j,g,g);break;case i:this.subParse(a,R,!0);break;case J:case I:case x:case w:case v:this.ast=this.ast.beget(R),this.tokens.push(a);break;case n:case F:c=this.options.favorText&&a.type===n?R:S,this.subParse(a,c),f=this.advanceUntilNot(K),b=this.tokens[this.tokens.length-1],b&&b.type!==z&&b.type!==s&&b.type!==n&&a.type!==F?(this.tokens.push.apply(this.tokens,f.reverse()),this.ast=this.ast.parent):this.ast.push(f);break;case K:this.ast.push(a),this.advanceUntilNot(K);break;default:this.ast.push(a)}},handleEXP:function(a){var b=null,c,d,e,f,i,j,k;switch(a.type){case z:case s:this.ast=this.ast.beget(S),this.tokens.push(a);break;case K:case A:case h:case D:case C:this.ast.parent&&this.ast.parent.mode===T?this.ast.push(a):(this.ast=this.ast.parent,this.tokens.push(a));break;case y:this.ast.push(a);break;case H:case p:this.ast.parent&&this.ast.parent.mode===T?(i=this.advanceUntilMatched(a,a.type,L[a.type],l,l),this.ast.pushFlatten(i.reverse())):(this.ast=this.ast.parent,this.tokens.push(a));break;case u:case F:j=this.prevTokens[this.prevTokens.length-1],b=this.tokens[this.tokens.length-1];if(a.type===u&&b.type===t){this.tokens.push(a),this.ast=this.ast.parent;break}this.subParse(a,T),b=this.tokens[this.tokens.length-1];if(j&&j.type===g||b&&b.type===y)this.ast=this.ast.parent;break;case n:this.tokens.push(a),this.ast=this.ast.beget(S);break;case r:this.tokens.push(a),this.ast=this.ast.beget(S);break;case G:b=this.tokens[this.tokens.length-1],b&&(b.type===y||b.type===z||b.type===s||b.type===G||this.ast.parent&&this.ast.parent.mode===T)?this.ast.push(a):(this.ast=this.ast.parent,this.tokens.push(a));break;default:this.ast.parent&&this.ast.parent.mode!==T?(this.ast=this.ast.parent,this.tokens.push(a)):this.ast.push(a)}}};var V=U.prototype;V.insertDebugVars=function(a){this.options.debug&&this.buffer.push(this.options.helpersName+".vl = "+a.line+", ",this.options.helpersName+".vc = "+a.chr+"; \n")},V.visitMarkupTok=function(a,b,c){this.insertDebugVars(a),this.buffer.push("MKP('"+a.val.replace(this.reQuote,"\\$1").replace(this.reLineBreak,"\\n")+"')MKP")},V.visitBlockTok=function(a,b,c){this.buffer.push(a.val)},V.visitExpressionTok=function(a,b,c,d){var e="",f="",g=b.parent&&b.parent.mode!==T;this.options.htmlEscape!==!1&&(g&&c===0&&d&&(e+=this.options.helpersName+".escape("),g&&c===b.length-1&&d&&(f+=").toHtmlString()")),g&&c===0&&(this.insertDebugVars(a),e="__vbuffer.push("+e),g&&c===b.length-1&&(f+="); \n"),this.buffer.push(e+a.val+f),g&&c===b.length-1&&this.insertDebugVars(a)},V.visitNode=function(a){var b,c=a.slice(0),d,e,f;a.mode===T&&a.parent&&a.parent.mode!==T&&(d=a.filter(U.findNonExp).length);for(e=0;e<c.length;e++){f=c[e];if(f.type&&f.type===g||f.type===i)continue;f.vquery?this.visitNode(f):a.mode===R?this.visitMarkupTok(f,a,e):a.mode===S?this.visitBlockTok(f,a,e):a.mode===T&&this.visitExpressionTok(f,a,e,d>0?!1:!0)}},V.escapeForDebug=function(a){return a.replace(this.reLineBreak,"!LB!").replace(this.reQuote,"\\$1").replace(this.reEscapedQuote,"\\$1")},V.replaceDevTokens=function(a){return a.replace(this.reHelpersName,this.options.helpersName).replace(this.reModelName,this.options.modelName)},V.addHead=function(a){var b=this.options,c=""+(b.debug?"try { \n":"")+"var __vbuffer = HELPERSNAME.buffer; \n"+"MODELNAME = MODELNAME || {}; \n"+(b.useWith?"with( MODELNAME ){ \n":"");c=this.replaceDevTokens(c);return c+a},V.addHelperHead=function(a){var b=this.options,c=""+(b.debug?"try { \n":"")+"var __vbuffer = this.buffer; \n"+"var MODELNAME = this.model; \n"+"var HELPERSNAME = this; \n";c=this.replaceDevTokens(c);return c+a},V.addFoot=function(a){var b=this.options,c=""+(b.simple?'return HELPERSNAME.buffer.join(""); \n':"(__vopts && __vopts.onRenderEnd && __vopts.onRenderEnd(null, HELPERSNAME)); \nreturn (__vopts && __vopts.asContext) \n ? HELPERSNAME \n : HELPERSNAME.toString(); \n")+(b.useWith?"} \n":"")+(b.debug?'} catch( e ){ \n HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n} \n':"");c=this.replaceDevTokens(c).replace(this.reOriginalMarkup,this.escapeForDebug(this.originalMarkup));return a+c},V.addHelperFoot=function(a){var b=this.options,c=""+(b.debug?'} catch( e ){ \n HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n} \n':"");c=this.replaceDevTokens(c).replace(this.reOriginalMarkup,this.escapeForDebug(this.originalMarkup));return a+c},V.generate=function(){var a=this.options;this.buffer.length=0,this.visitNode(this.ast);var c=this.buffer.join("").split("')MKPMKP('").join("").split("MKP(").join("__vbuffer.push(").split(")MKP").join("); \n");a.asHelper?(c=this.addHelperHead(c),c=this.addHelperFoot(c)):(c=this.addHead(c),c=this.addFoot(c)),a.debugCompiler&&(console.log(c),console.log(a)),this.cmpFunc=b.link(c,a);return this.cmpFunc},U.noop=function(){},U.findNonExp=function(a){return a.vquery&&a.mode===T?a.filter(U.findNonExp).length>0:a.vquery&&a.mode!==T?!0:!1},a.VLexer=N,a.VParser=P,a.VCompiler=U,a.vQuery=O;return a}({})) |
{ | ||
"name": "vash", | ||
"description": "Razor syntax for JS templating", | ||
"version": "0.5.15-1896", | ||
"version": "0.6.0-2085", | ||
"author": "Andrew Petersen <senofpeter@gmail.com>", | ||
@@ -29,7 +29,3 @@ "homepage": "https://github.com/kirbysayshi/vash", | ||
"devDependencies": { | ||
"benchmark": ">=0.2.2", | ||
"dot": ">=0.1.7", | ||
"express": "3.0.0rc4", | ||
"vows": "~0.6.4", | ||
"jshtml": ">=0.2.2", | ||
"semver": ">=1.0.0", | ||
@@ -36,0 +32,0 @@ "underscore": ">=v1.3.3", |
@@ -29,2 +29,3 @@ /*jshint strict:false, laxcomma:true, laxbreak:true, boss:true, curly:true, node:true, browser:true, devel:true */ | ||
,"debugCompiler": false | ||
,"simple": false | ||
@@ -66,31 +67,104 @@ ,"favorText": false | ||
exports['batch'] = function batch(path, cb){ | ||
/////////////////////////////////////////////////////////////////////////// | ||
// VASH.BATCH | ||
// | ||
// Allow multiple templates to be contained within the same string. | ||
// Templates are separated via a sourceURL-esque string: | ||
// | ||
// //@batch = tplname/or/path | ||
// | ||
// The separator is forgiving in terms of whitespace: | ||
// | ||
// // @ batch=tplname/or/path | ||
// | ||
// Is just as valid. | ||
// | ||
// Returns the compiled templates as named properties of an object. | ||
var caller = batch.caller; | ||
exports['batch'] = function(markup, options){ | ||
function _batch(path, cb){ | ||
var tpls = splitByNamedTpl(markup).batch; | ||
var reFuncHead = /^function\s*\([^)]*?\)\s*{/ | ||
,reFuncTail = /\}$/ | ||
if(tpls){ | ||
Object.keys(tpls).forEach(function(path){ | ||
tpls[path] = vash.compile(tpls[path], options); | ||
}); | ||
} | ||
,str = cb.toString() | ||
.replace(reFuncHead, '') | ||
.replace(reFuncTail, '') | ||
return tpls; | ||
} | ||
,callOpts = caller.options | ||
// do the actual work of splitting the string via the batch separator | ||
var splitByNamedTpl = function(markup){ | ||
var cmp = new VCompiler([], '', callOpts); | ||
var reSourceMap = /^\/\/\s*@\s*(batch|helper)\s*=\s*(.*?)$/ | ||
,lines = markup.split(/[\n\r]/g) | ||
,tpls = { | ||
batch: {} | ||
,helper: {} | ||
} | ||
,paths = [] | ||
,currentPath = '' | ||
,typePointer = tpls.batch; | ||
str = cmp.wrapBody( str ); | ||
vash.install( path, vash.link( str, callOpts.modelName, callOpts.helpersName ) ); | ||
} | ||
lines.forEach(function(line, idx, arr){ | ||
var pathResult = reSourceMap.exec(line) | ||
,atEnd = idx === arr.length - 1; | ||
if( vash.compile ) { | ||
exports['batch'] = _batch; | ||
return exports['batch'](path, cb); | ||
} else { | ||
throw new Error('vash.batch is not available in the standalone runtime.'); | ||
} | ||
}; | ||
if(!pathResult || atEnd){ | ||
tpls[typePointer][currentPath].push(line); | ||
} | ||
if((pathResult || atEnd) && currentPath){ | ||
tpls[typePointer][currentPath] = tpls[typePointer][currentPath].join('\n'); | ||
} | ||
if(pathResult){ | ||
typePointer = pathResult[1]; | ||
currentPath = pathResult[2].replace(/^\s+|\s+$/, ''); | ||
tpls[typePointer][currentPath] = []; | ||
} | ||
}); | ||
return tpls; | ||
} | ||
// VASH.BATCH | ||
/////////////////////////////////////////////////////////////////////////// | ||
/////////////////////////////////////////////////////////////////////////// | ||
// HELPER INSTALLATION | ||
var slice = Array.prototype.slice | ||
,reFuncHead = /^vash\.helpers\.([^= ]+?)\s*=\s*function([^(]*?)\(([^)]*?)\)\s*{/ | ||
,reFuncTail = /\}$/ | ||
exports['compileHelper'] = function reg(str, options){ | ||
options = options || {}; | ||
// replace leading/trailing spaces, and parse the function head | ||
var def = str.replace(/^\s+|\s+$/, '').match(reFuncHead) | ||
// split the function arguments, kill all whitespace | ||
,args = def[3].split(',').map(function(arg){ return arg.replace(' ', '') }) | ||
,name = def[1] | ||
,body = str | ||
.replace( reFuncHead, '' ) | ||
.replace( reFuncTail, '' ) | ||
// Wrap body in @{} to simulate it actually being inside a function | ||
// definition, since we manually stripped it. Without this, statements | ||
// such as `this.what = "what";` that are at the beginning of the body | ||
// will be interpreted as markup. | ||
body = '@{' + body + '}'; | ||
// `args` and `asHelper` inform `vash.compile/link` that this is a helper | ||
options.args = args; | ||
options.asHelper = name; | ||
vash.compile(body, options); | ||
} | ||
// HELPER INSTALLATION | ||
/////////////////////////////////////////////////////////////////////////// | ||
/************** Begin injected code from build script */ | ||
@@ -97,0 +171,0 @@ /*?CODE?*/ |
@@ -127,3 +127,3 @@ /*jshint strict:false, asi:true, laxcomma:true, laxbreak:true, boss:true, curly:true, node:true, browser:true, devel:true */ | ||
VCP.wrapBody = function(body){ | ||
VCP.addHead = function(body){ | ||
@@ -138,19 +138,57 @@ var options = this.options; | ||
head = this.replaceDevTokens( head ); | ||
return head + body; | ||
} | ||
VCP.addHelperHead = function(body){ | ||
var options = this.options; | ||
var head = '' | ||
+ (options.debug ? 'try { \n' : '') | ||
+ 'var __vbuffer = this.buffer; \n' | ||
+ 'var MODELNAME = this.model; \n' | ||
+ 'var HELPERSNAME = this; \n'; | ||
head = this.replaceDevTokens( head ); | ||
return head + body; | ||
} | ||
VCP.addFoot = function(body){ | ||
var options = this.options; | ||
var foot = '' | ||
+ '(__vopts && __vopts.onRenderEnd && __vopts.onRenderEnd(null, HELPERSNAME)); \n' | ||
+ 'return (__vopts && __vopts.asContext) \n' | ||
+ ' ? HELPERSNAME \n' | ||
+ ' : HELPERSNAME.toString(); \n' | ||
+ (options.simple | ||
? 'return HELPERSNAME.buffer.join(""); \n' | ||
: '(__vopts && __vopts.onRenderEnd && __vopts.onRenderEnd(null, HELPERSNAME)); \n' | ||
+ 'return (__vopts && __vopts.asContext) \n' | ||
+ ' ? HELPERSNAME \n' | ||
+ ' : HELPERSNAME.toString(); \n' ) | ||
+ (options.useWith ? '} \n' : '') | ||
+ (options.debug ? '} catch( e ){ \n' | ||
+ ' HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n' | ||
+ '} \n' : '') | ||
+ (options.useWith ? '} \n' : ''); | ||
+ '} \n' : ''); | ||
head = this.replaceDevTokens( head ); | ||
foot = this.replaceDevTokens( foot ) | ||
.replace( this.reOriginalMarkup, this.escapeForDebug( this.originalMarkup ) ); | ||
return head + body + foot; | ||
return body + foot; | ||
} | ||
VCP.addHelperFoot = function(body){ | ||
var options = this.options; | ||
var foot = '' | ||
+ (options.debug ? '} catch( e ){ \n' | ||
+ ' HELPERSNAME.reportError( e, HELPERSNAME.vl, HELPERSNAME.vc, "ORIGINALMARKUP" ); \n' | ||
+ '} \n' : ''); | ||
foot = this.replaceDevTokens( foot ) | ||
.replace( this.reOriginalMarkup, this.escapeForDebug( this.originalMarkup ) ); | ||
return body + foot; | ||
} | ||
VCP.generate = function(){ | ||
@@ -171,9 +209,16 @@ var options = this.options; | ||
joined = this.wrapBody( joined ); | ||
if(!options.asHelper){ | ||
joined = this.addHead( joined ); | ||
joined = this.addFoot( joined ); | ||
} else { | ||
joined = this.addHelperHead( joined ); | ||
joined = this.addHelperFoot( joined ); | ||
} | ||
if(options.debugCompiler){ | ||
console.log(joined); | ||
console.log(options); | ||
} | ||
this.cmpFunc = vash.link( joined, options.modelName, options.helpersName ); | ||
this.cmpFunc = vash.link( joined, options ); | ||
return this.cmpFunc; | ||
@@ -180,0 +225,0 @@ } |
@@ -116,3 +116,3 @@ ;(function(){ | ||
prepends && prepends.forEach(function(p){ self.buffer.push( p ); }); | ||
prepends && prepends.forEach(function(p){ self.buffer.pushConcat( p ); }); | ||
@@ -122,5 +122,5 @@ // a block might never have a callback defined, e.g. is optional | ||
block = blocks.pop(); | ||
block && this.buffer.push( block ); | ||
block && this.buffer.pushConcat( block ); | ||
appends && appends.forEach(function(a){ self.buffer.push( a ); }); | ||
appends && appends.forEach(function(a){ self.buffer.pushConcat( a ); }); | ||
@@ -127,0 +127,0 @@ // grab rendered content |
@@ -35,3 +35,4 @@ /*jshint strict:false, asi: false, laxcomma:true, laxbreak:true, boss:true, curly:true, node:true, browser:true, devel:true */ | ||
helpers.toString = helpers.toHtmlString = function(){ | ||
return this.buffer.toString(); | ||
// not calling buffer.toString() results in 2x speedup | ||
return this.buffer._vo.join('');//.toString(); | ||
} | ||
@@ -53,3 +54,3 @@ | ||
helpers.raw = function( val ) { | ||
helpers['raw'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -65,3 +66,3 @@ | ||
helpers.escape = function( val ) { | ||
helpers['escape'] = function( val ) { | ||
var func = function() { return val; }; | ||
@@ -135,2 +136,6 @@ | ||
Buffer.prototype.push = function( buffer ) { | ||
return this._vo.push( buffer ); | ||
}; | ||
Buffer.prototype.pushConcat = function( buffer ){ | ||
if( buffer instanceof Array ) { | ||
@@ -143,4 +148,6 @@ this._vo.push.apply( this._vo, buffer ); | ||
} | ||
}; | ||
return this.__vo; | ||
} | ||
Buffer.prototype.indexOf = function( str ){ | ||
@@ -259,3 +266,3 @@ | ||
helpers.reportError = function() { | ||
helpers['reportError'] = function() { | ||
this.constructor.reportError.apply( this, arguments ); | ||
@@ -269,52 +276,118 @@ }; | ||
// VASH.LINK | ||
// Reconstitute precompiled functions | ||
// Take a compiled string or function and "link" it to the current vash | ||
// runtime. This is necessary to allow instantiation of `Helpers` and | ||
// proper decompilation via `toClientString`. | ||
// | ||
// If `options.asHelper` and `options.args` are defined, the `cmpFunc` is | ||
// interpreted as a compiled helper, and is attached to `vash.helpers` at | ||
// a property name equal to `options.asHelper`. | ||
vash['link'] = function( cmpFunc, modelName, helpersName ){ | ||
vash['link'] = function( cmpFunc, options ){ | ||
var joined; | ||
// TODO: allow options.filename to be used as sourceUrl? | ||
var originalFunc | ||
,cmpOpts; | ||
if( !options.args ){ | ||
// every template has these arguments | ||
options.args = [options.modelName, options.helpersName, '__vopts', 'vash']; | ||
} | ||
if( typeof cmpFunc === 'string' ){ | ||
joined = cmpFunc; | ||
originalFunc = cmpFunc; | ||
try { | ||
cmpFunc = new Function(modelName, helpersName, '__vopts', 'vash', joined); | ||
} catch(e){ | ||
helpers.reportError(e, 0, 0, joined, /\n/); | ||
// do not pollute the args array for later attachment to the compiled | ||
// function for later decompilation/linking | ||
cmpOpts = options.args.slice(); | ||
cmpOpts.push(cmpFunc); | ||
cmpFunc = Function.apply(null, cmpOpts); | ||
} catch(e) { | ||
// TODO: add flag to reportError to know if it's at compile time or runtime | ||
helpers.reportError(e, 0, 0, originalFunc, /\n/); | ||
} | ||
} | ||
// need this to enable `vash.batch` to reconstitute | ||
cmpFunc.options = { modelName: modelName, helpersName: helpersName }; | ||
// need this to enable decompilation / relinking | ||
cmpFunc.options = { | ||
simple: options.simple | ||
,modelName: options.modelName | ||
,helpersName: options.helpersName | ||
} | ||
var linked = function( model, opts ){ | ||
var linked; | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
if( options.asHelper ){ | ||
opts = opts || {}; | ||
cmpFunc.options.args = options.args; | ||
cmpFunc.options.asHelper = options.asHelper; | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd && opts && !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
linked = function(){ | ||
return cmpFunc.apply(this, slice.call(arguments)); | ||
} | ||
if( model && model.onRenderEnd ){ | ||
delete model.onRenderEnd; | ||
helpers[options.asHelper] = linked; | ||
} else { | ||
linked = function( model, opts ){ | ||
if( options.simple ){ | ||
var ctx = { | ||
buffer: [] | ||
,escape: Helpers.prototype.escape | ||
,raw: Helpers.prototype.raw | ||
} | ||
return cmpFunc( model, ctx, opts, vash ); | ||
} | ||
opts = divineRuntimeTplOptions( model, opts ); | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
} | ||
} | ||
return cmpFunc( model, (opts && opts.context) || new Helpers( model ), opts, vash ); | ||
}; | ||
// show the template-specific code, instead of the generic linked function | ||
linked['toString'] = function(){ return cmpFunc.toString(); } | ||
linked.toString = function(){ | ||
return cmpFunc.toString(); | ||
}; | ||
// shortcut to show the actual linked function | ||
linked['_toString'] = function(){ return Function.prototype.toString.call(linked) } | ||
linked.toClientString = function(){ | ||
return 'vash.link( ' + cmpFunc.toString() + ', "' + modelName + '", "' + helpersName + '" )'; | ||
}; | ||
linked['toClientString'] = function(){ | ||
return 'vash.link( ' | ||
+ cmpFunc.toString() + ', ' | ||
+ JSON.stringify( cmpFunc.options ) + ' )'; | ||
} | ||
return linked; | ||
}; | ||
} | ||
// given a model and options, allow for various tpl signatures and options: | ||
// ( model, {} ) | ||
// ( model, function onRenderEnd(){} ) | ||
// ( model ) | ||
// and model.onRenderEnd | ||
function divineRuntimeTplOptions( model, opts ){ | ||
// allow for signature: model, callback | ||
if( typeof opts === 'function' ) { | ||
opts = { onRenderEnd: opts }; | ||
} | ||
// allow for passing in onRenderEnd via model | ||
if( model && model.onRenderEnd ){ | ||
opts = opts || {}; | ||
if( !opts.onRenderEnd ){ | ||
opts.onRenderEnd = model.onRenderEnd; | ||
} | ||
delete model.onRenderEnd; | ||
} | ||
return opts; | ||
} | ||
// shortcut for compiled helpers | ||
var slice = Array.prototype.slice; | ||
// VASH.LINK | ||
@@ -326,3 +399,3 @@ /////////////////////////////////////////////////////////////////////////// | ||
vash.lookup = function( path, model ){ | ||
vash['lookup'] = function( path, model ){ | ||
var tpl = vash.helpers.tplcache[path]; | ||
@@ -334,3 +407,3 @@ if( !tpl ){ throw new Error('Could not find template: ' + path); } | ||
vash.install = function( path, tpl ){ | ||
vash['install'] = function( path, tpl ){ | ||
var cache = vash.helpers.tplcache; | ||
@@ -340,2 +413,8 @@ if( typeof tpl === 'string' ){ | ||
tpl = vash.compile(tpl); | ||
} else if( typeof path === 'object' ){ | ||
tpl = path; | ||
Object.keys(tpl).forEach(function(path){ | ||
cache[path] = tpl[path]; | ||
}); | ||
return cache; | ||
} | ||
@@ -345,3 +424,3 @@ return cache[path] = tpl; | ||
vash.uninstall = function( path ){ | ||
vash['uninstall'] = function( path ){ | ||
var cache = vash.helpers.tplcache | ||
@@ -348,0 +427,0 @@ ,deleted = false; |
@@ -951,2 +951,8 @@ var vows = require('vows') | ||
} | ||
,'self closing html tag with expression': { | ||
topic: '<img src="@model.a" />' | ||
,'allows expression': function(topic){ | ||
assert.equal( vash.compile(topic)({ a: 'a' }), '<img src="a" />' ); | ||
} | ||
} | ||
,'nested self closing html tag inside block': { | ||
@@ -1500,2 +1506,90 @@ topic: function(){ | ||
,'simple': { | ||
topic: function(){ | ||
return '<p>@model</p>' | ||
} | ||
,'renders': function( topic ){ | ||
var tpl = vash.compile(topic, { simple: true }); | ||
assert.equal( tpl('YES'), '<p>YES</p>' ); | ||
} | ||
,'html escaping': { | ||
topic: '' | ||
,'is ignored via `raw`': function(){ | ||
var str = '<p>@html.raw(model)</p>' | ||
,tpl = vash.compile( str, { simple: true, htmlEscape: true } ) | ||
assert.equal( tpl('<br />'), '<p><br /></p>'); | ||
} | ||
,'works': function(){ | ||
var str = '<p>@model</p>' | ||
,tpl = vash.compile( str, { simple: true, htmlEscape: true } ) | ||
assert.equal( tpl('<br />'), '<p><br /></p>'); | ||
} | ||
} | ||
} | ||
,'batched': { | ||
topic: '//@batch = div \n<div>@model</div>\n' | ||
+'// @batch = a \n<a>@model</a>' | ||
,'installs each tpl': function(topic){ | ||
var tpls = vash.batch(topic) | ||
,model = 'm'; | ||
vash.install(tpls); | ||
assert.equal( vash.lookup('div')(model), '<div>m</div>' ); | ||
assert.equal( vash.lookup('a')(model), '<a>m</a>' ); | ||
vash.uninstall('div'); | ||
vash.uninstall('a'); | ||
} | ||
} | ||
,'compiled helpers': { | ||
topic: 'vash.helpers.fn = function(id, ctn){' | ||
+ 'this.fnCounter = this.fnCounter || 0;' | ||
+ 'this.fnIds = this.fnIds || {};' | ||
+ 'this.fnCtn = this.fnCtn || {};' | ||
+ ' if(ctn){' | ||
+ ' <li id="fn:@id">' | ||
+ ' @ctn()' | ||
+ ' <a rev="footnote" href="#fnref:@id">↩</a>' | ||
+ ' </li>' | ||
+ ' } else {' | ||
+ ' this.fnIds[id] = ++this.fnCounter;' | ||
+ ' <sup id="fnref:@id">' | ||
+ ' <a rel="footnote" href="#fn:@id">@html.raw(this.fnCounter)</a>' | ||
+ ' </sup>' | ||
+ ' }' | ||
+ '}' | ||
,'can be defined': function(topic){ | ||
vash.compileHelper(topic); | ||
assert.ok( vash.helpers.fn ); | ||
var str = '@html.fn("one") @html.fn("two")' | ||
,tpl = vash.compile(str); | ||
var ctx = tpl({}, { asContext: true }) | ||
,rendered = ctx.toString(); | ||
assert.equal( ctx.fnCounter, 2 ); | ||
assert.equal( ctx.fnIds.one, 1 ); | ||
assert.equal( ctx.fnIds.two, 2 ); | ||
assert.ok( rendered.indexOf('fnref:one') > -1, 'expect indexOf fnref:one to be > -1' ); | ||
assert.ok( rendered.indexOf('fnref:two') > -1, 'expect indexOf fnref:two to be > -1' ); | ||
delete vash.helpers.fn; | ||
} | ||
} | ||
/*,'implicit compilation': { | ||
@@ -1502,0 +1596,0 @@ |
@@ -22,3 +22,3 @@ var vows = require('vows') | ||
'default helpers': { | ||
'default runtime helpers': { | ||
@@ -74,22 +74,2 @@ 'highlight': { | ||
,'batched': function(){ | ||
var str = | ||
'@vash.batch("div", function(){<div>@model</div>})' | ||
+'@vash.batch("a", function(){<a>@model</a>})' | ||
var tpl = vash.compile(str) | ||
,model = 'm'; | ||
assert.equal( tpl(), '' ); | ||
assert.equal( vash.lookup('div')(model), '<div>m</div>' ); | ||
assert.equal( vash.lookup('a')(model), '<a>m</a>' ); | ||
} | ||
,'vash.batch throws in standalone runtime': function(){ | ||
assert.throws(function(){ | ||
vm.runInNewContext( 'vash.batch()', { vash: vruntime } ); | ||
}, (/has no method ['"]batch['"]/g)); | ||
} | ||
,'uninstalling removes': function(){ | ||
@@ -115,2 +95,18 @@ var str = '<p></p>' | ||
,'installing with object installs each separately': function(){ | ||
var p = '<p></p>' | ||
,li = '<li></li>' | ||
,obj = { | ||
p: vash.compile(p) | ||
,li: vash.compile(li) | ||
} | ||
,tpl = vash.install(obj); | ||
assert.equal( vash.lookup('p')(), p ); | ||
assert.equal( vash.lookup('li')(), li ); | ||
vash.uninstall('p'); | ||
vash.uninstall('li'); | ||
} | ||
,'installing with string throws if only runtime': function(){ | ||
@@ -134,2 +130,36 @@ var str = 'vash.install("testpath", "<p></p>")' | ||
,'compiled helpers': { | ||
topic: 'vash.helpers.fn = function(id, ctn){' | ||
+ 'this.fnCounter = this.fnCounter || 0;' | ||
+ 'this.fnIds = this.fnIds || {};' | ||
+ 'this.fnCtn = this.fnCtn || {};' | ||
+ ' if(ctn){' | ||
+ ' <li id="fn:@id">' | ||
+ ' @ctn()' | ||
+ ' <a rev="footnote" href="#fnref:@id">↩</a>' | ||
+ ' </li>' | ||
+ ' } else {' | ||
+ ' this.fnIds[id] = ++this.fnCounter;' | ||
+ ' <sup id="fnref:@id">' | ||
+ ' <a rel="footnote" href="#fn:@id">@html.raw(this.fnCounter)</a>' | ||
+ ' </sup>' | ||
+ ' }' | ||
+ '}' | ||
,'can be decompiled and relinked': function(topic){ | ||
vash.compileHelper(topic); | ||
assert.ok( vash.helpers.fn ); | ||
var str = vash.compile('@html.fn("one") @html.fn("two")').toClientString() + '()' | ||
,client = vash.helpers.fn.toClientString() + '; \n' + str | ||
var actual = vm.runInNewContext( client, { vash: vruntime } ); | ||
assert.ok( actual.indexOf('fnref:one') > -1, 'expect indexOf fnref:one to be > -1' ); | ||
assert.ok( actual.indexOf('fnref:two') > -1, 'expect indexOf fnref:two to be > -1' ); | ||
} | ||
} | ||
}).export(module) |
Sorry, the diff of this file is not supported yet
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
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
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
5
0
405
280033
35
6138