Javascript templating shootoff (extended)

JavaScript performance comparison

Revision 92 of this test case created by Mark Lee

Preparation code

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://coffeescript.org/extras/coffee-script.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script>
var underscore = _;
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.compat.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.js"></script>
<script src="http://cdn.kendostatic.com/2014.1.318/js/kendo.all.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hogan.js/3.0.0/hogan.js"></script>
<script src="https://rawgit.com/pure/pure/master/libs/pure.js"></script>
<script src="https://rawgit.com/linkedin/dustjs/master/dist/dust-full.js"></script>
<script src="https://sstephenson.github.io/eco/dist/eco.js"></script>
<script src="http://embeddedjs.com/javascripts/ejs_production.js"></script>
<script src="https://cdn.jsdelivr.net/mustache.js/0.8.1/mustache.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.jqote2/0.9.8/jquery.jqote2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jade/1.3.1/jade.min.js"></script>
<script src="http://terrainformatica.com/kite/kite.js"></script>
<script src="http://borismoore.github.com/jsrender/jsrender.js"></script>
<script src="http://satchmorun.github.com/mote/mote.js"></script>
<script src="https://rawgit.com/snoguchi/simple-template.js/master/simple-template.js"></script>
<script src="https://rawgit.com/nicolas-van/jiko/master/jiko.js"></script>
<script src="https://rawgit.com/kirbysayshi/vash/master/build/vash.min.js"></script>
<script src="https://rawgit.com/olado/doT/master/doT.min.js"></script>
<script src="https://rawgit.com/Trenker/Browser-UglifyJS/2f1c56681b5bfec706292294bff23a1136fcd659/build/uglifyjs.1.2.5.js"></script>

<!--------------------------->
<!-- DOM TEMPLATES         -->
<!--------------------------->
<div class="pure">
	<h1 class='header'></h1>
	<h2 class='header2'></h2>
	<h3 class='header3'></h3>
	<h4 class='header4'></h4>
	<h5 class='header5'></h5>
	<h6 class='header6'></h6>
</div>

<script>
/****************************************
 MASTER TEMPLATE DATA
 ****************************************/
window.tpl = {};
window.tpl.vars = {
   header: "Header",
   header2: "Header2",
   header3: "Header3",
   header4: "Header4",
   header5: "Header5",
   header6: "Header6",
   list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
};
window.tpl.vars2 = {
   header: "Header",
   header2: "Header2",
   header3: "Header3",
   header4: "Header4",
   header5: "Header5",
   header6: "Header6",
   list: [{i:'1'}, {i:'2'}, {i:'3'}, {i:'4'}, {i:'5'}, {i:'6'}, {i:'7'}, {i:'8'}, {i:'9'}, {i:'10'}]
};  

/****************************************
 TEMPLATE ENGINES NOT HOSTED BY A CDN (github)
 ****************************************/
//Please minify any hard included library and note the version.

//Resig Template Function (modified to support ')
function rtmpl(a){var b="var p=[];"+"with(obj){p.push('"+a.replace(/[\r\t\n]/g," ").replace(/'(?=[^#]*#>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<#=(.+?)#>/g,"',$1,'").split("<#").join("');").split("#>").join("p.push('")+"');}return p.join('');";return new Function("obj",b)}

//Resig modified template function (no "with" block)
function rtmpl2(a){var b="var p=[];"+"p.push('"+a.replace(/[\r\t\n]/g," ").replace(/'(?=[^#]*#>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<#=(.+?)#>/g,"',$1,'").split("<#").join("');").split("#>").join("p.push('")+"');return p.join('');";return new Function("data",b)}

//doT 2
(function(){var a={version:"0.1.2"};typeof module!="undefined"&&module.exports?module.exports=a:this.doU=a,a.templateSettings={begin:"{{",end:"}}",varname:"it"},a.template=function(b,c){c=c||a.templateSettings;var d="",e=c.begin,f=c.end,g,h,i=b.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g,"").split(e).join(f+"").split(f);for(g=0,h=i.length;g<h;g++)d+=i[g].charAt(0)!==""?"out+='"+i[g].replace(/(\\|["'])/g,"\\$1")+"'":i[g].charAt(1)==="="?";out+=("+i[g].substr(2)+");":i[g].charAt(1)==="!"?";out+=("+i[g].substr(2)+").toString().replace(/&(?!\\w+;)/g, '&#38;').split('<').join('&#60;').split('>').join('&#62;').split('"+'"'+"').join('&#34;').split("+'"'+"'"+'"'+").join('&#39;').split('/').join('&#x2F;');":";"+i[g].substr(1);d=('var out="";'+d+";return out;").split("out+='';").join("").split('var out="";out+=').join("var out=");try{return new Function(c.varname,d)}catch(j){throw typeof console!="undefined"&&console.log("Could not create a template function: "+d),j}}})();


//Haml (July 16 2011)
var Haml;(function(){var matchers,self_close_tags,embedder,forceXML,escaperName,escapeHtmlByDefault;function html_escape(text){return(text+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;")}function render_attribs(attribs){var key,value,result=[];for(key in attribs){if(key!=="_content"&&attribs.hasOwnProperty(key)){switch(attribs[key]){case"undefined":case"false":case"null":case'""':break;default:try{value=JSON.parse("["+attribs[key]+"]")[0];if(value===true){value=key}else{if(typeof value==="string"&&embedder.test(value)){value='" +\n'+parse_interpol(html_escape(value))+' +\n"'}else{value=html_escape(value)}}result.push(" "+key+'=\\"'+value+'\\"')}catch(e){result.push(" "+key+'=\\"" + '+escaperName+"("+attribs[key]+') + "\\"')}}}}return result.join("")}function parse_attribs(line){var attributes={},l=line.length,i,c,count=1,quote=false,skip=false,open,close,joiner,seperator,pair={start:1,middle:null,end:null};if(!(l>0&&(line.charAt(0)==="{"||line.charAt(0)==="("))){return{_content:line[0]===" "?line.substr(1,l):line}}open=line.charAt(0);close=(open==="{")?"}":")";joiner=(open==="{")?":":"=";seperator=(open==="{")?",":" ";function process_pair(){if(typeof pair.start==="number"&&typeof pair.middle==="number"&&typeof pair.end==="number"){var key=line.substr(pair.start,pair.middle-pair.start).trim(),value=line.substr(pair.middle+1,pair.end-pair.middle-1).trim();attributes[key]=value}pair={start:null,middle:null,end:null}}for(i=1;count>0;i+=1){if(i>l){throw"Malformed attribute block"}c=line.charAt(i);if(skip){skip=false}else{if(quote){if(c==="\\"){skip=true}if(c===quote){quote=false}}else{if(c==='"'||c==="'"){quote=c}if(count===1){if(c===joiner){pair.middle=i}if(c===seperator||c===close){pair.end=i;process_pair();if(c===seperator){pair.start=i+1}}}if(c===open||c==="("){count+=1}if(c===close||(count>1&&c===")")){count-=1}}}}attributes._content=line.substr(i,line.length);return attributes}function parse_interpol(value){var items=[],pos=0,next=0,match;while(true){next=value.substr(pos).search(embedder);if(next<0){if(pos<value.length){items.push(JSON.stringify(value.substr(pos)))}break}items.push(JSON.stringify(value.substr(pos,next)));pos+=next;match=value.substr(pos).match(embedder);next=match[0].length;if(next<0){break}if(match[1]==="#"){items.push(escaperName+"("+(match[2]||match[3])+")")}else{items.push(match[2]||match[3])}pos+=next}return items.filter(function(part){return part&&part.length>0}).join(" +\n")}embedder=/([#!])\{([^}]*)\}/;self_close_tags=["meta","img","link","br","hr","input","area","base"];matchers=[{name:"html tags",regexp:/^(\s*)((?:[.#%][a-z_\-][a-z0-9_:\-]*)+)(.*)$/i,process:function(){var line_beginning,tag,classes,ids,attribs,content,whitespaceSpecifier,whitespace={},output;line_beginning=this.matches[2];classes=line_beginning.match(/\.([a-z_\-][a-z0-9_\-]*)/gi);ids=line_beginning.match(/\#([a-z_\-][a-z0-9_\-]*)/gi);tag=line_beginning.match(/\%([a-z_\-][a-z0-9_:\-]*)/gi);tag=tag?tag[0].substr(1,tag[0].length):"div";attribs=this.matches[3];if(attribs){attribs=parse_attribs(attribs);if(attribs._content){var leader0=attribs._content.charAt(0),leader1=attribs._content.charAt(1),leaderLength=0;if(leader0=="<"){leaderLength++;whitespace.inside=true;if(leader1==">"){leaderLength++;whitespace.around=true}}else{if(leader0==">"){leaderLength++;whitespace.around=true;if(leader1=="<"){leaderLength++;whitespace.inside=true}}}attribs._content=attribs._content.substr(leaderLength);this.contents.unshift(attribs._content.trim());delete (attribs._content)}}else{attribs={}}if(classes){classes=classes.map(function(klass){return klass.substr(1,klass.length)}).join(" ");if(attribs["class"]){try{attribs["class"]=JSON.stringify(classes+" "+JSON.parse(attribs["class"]))}catch(e){attribs["class"]=JSON.stringify(classes+" ")+" + "+attribs["class"]}}else{attribs["class"]=JSON.stringify(classes)}}if(ids){ids=ids.map(function(id){return id.substr(1,id.length)}).join(" ");if(attribs.id){attribs.id=JSON.stringify(ids+" ")+attribs.id}else{attribs.id=JSON.stringify(ids)}}attribs=render_attribs(attribs);content=this.render_contents();if(content==='""'){content=""}if(whitespace.inside){if(content.length==0){content='"  "'}else{try{content='" '+JSON.parse(content)+' "'}catch(e){content='" "+\n'+content+'+\n" "'}}}if(forceXML?content.length>0:self_close_tags.indexOf(tag)==-1){output='"<'+tag+attribs+'>"'+(content.length>0?" + \n"+content:"")+' + \n"</'+tag+'>"'}else{output='"<'+tag+attribs+' />"'}if(whitespace.around){output='" '+output.substr(1,output.length-2)+' "'}return output}},{name:"each loop",regexp:/^(\s*)(?::for|:each)\s+(?:([a-z_][a-z_\-]*),\s*)?([a-z_][a-z_\-]*)\s+in\s+(.*)(\s*)$/i,process:function(){var ivar=this.matches[2]||"__key__",vvar=this.matches[3],avar=this.matches[4],rvar="__result__";if(this.matches[5]){this.contents.unshift(this.matches[5])}return"(function () { var "+rvar+" = [], "+ivar+", "+vvar+"; for ("+ivar+" in "+avar+") { if ("+avar+".hasOwnProperty("+ivar+")) { "+vvar+" = "+avar+"["+ivar+"]; "+rvar+".push(\n"+(this.render_contents()||"''")+"\n); } } return "+rvar+'.join(""); }).call(this)'}},{name:"if",regexp:/^(\s*):if\s+(.*)\s*$/i,process:function(){var condition=this.matches[2];return"(function () { if ("+condition+") { return (\n"+(this.render_contents()||"")+'\n);} else { return ""; } }).call(this)'}},{name:"silent-comments",regexp:/^(\s*)-#\s*(.*)\s*$/i,process:function(){return'""'}},{name:"silent-comments",regexp:/^(\s*)\/\s*(.*)\s*$/i,process:function(){this.contents.unshift(this.matches[2]);return'"<!--'+this.contents.join("\\n")+'-->"'}},{name:"rawjs",regexp:/^(\s*)-\s*(.*)\s*$/i,process:function(){this.contents.unshift(this.matches[2]);return'"";'+this.contents.join("\n")+"; _$output = _$output "}},{name:"pre",regexp:/^(\s*):pre(\s+(.*)|$)/i,process:function(){this.contents.unshift(this.matches[2]);return'"<pre>"+\n'+JSON.stringify(this.contents.join("\n"))+'+\n"</pre>"'}},{name:"doctype",regexp:/^()!!!(?:\s*(.*))\s*$/,process:function(){var line="";switch((this.matches[2]||"").toLowerCase()){case"":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';break;case"strict":case"1.0":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';break;case"frameset":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';break;case"5":line="<!DOCTYPE html>";break;case"1.1":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';break;case"basic":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">';break;case"mobile":line='<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">';break;case"xml":line="<?xml version='1.0' encoding='utf-8' ?>";break;case"xml iso-8859-1":line="<?xml version='1.0' encoding='iso-8859-1' ?>";break}return JSON.stringify(line+"\n")}},{name:"markdown",regexp:/^(\s*):markdown\s*$/i,process:function(){return parse_interpol(exports.Markdown.encode(this.contents.join("\n")))}},{name:"script",regexp:/^(\s*):(?:java)?script\s*$/,process:function(){return parse_interpol('\n<script>\n//<![CDATA[\n'+this.contents.join("\n")+"\n//]]>\n<\/script>\n")}},{name:"css",regexp:/^(\s*):css\s*$/,process:function(){return JSON.stringify('<style type="text/css">\n'+this.contents.join("\n")+"\n</style>")}}];function compile(lines){var block=false,output=[];if(typeof lines==="string"){lines=lines.trim().replace(/\n\r|\r/g,"\n").split("\n")}lines.forEach(function(line){var match,found=false;if(block){match=block.check_indent.exec(line);if(match){block.contents.push(match[1]||"");return}else{output.push(block.process());block=false}}matchers.forEach(function(matcher){if(!found){match=matcher.regexp.exec(line);if(match){block={contents:[],indent_level:(match[1]),matches:match,check_indent:new RegExp("^(?:\\s*|"+match[1]+"  (.*))$"),process:matcher.process,render_contents:function(){return compile(this.contents)}};found=true}}});if(!found){output.push(function(){if(line[0]==="\\"){return parse_interpol(line.substr(1,line.length))}function escapedLine(){try{return escaperName+"("+JSON.stringify(JSON.parse(line))+")"}catch(e2){return escaperName+"("+line+")"}}function unescapedLine(){try{return parse_interpol(JSON.parse(line))}catch(e){return line}}if((line.substr(0,2)==="&=")){line=line.substr(2,line.length).trim();return escapedLine()}if((line.substr(0,2)==="!=")){line=line.substr(2,line.length).trim();return unescapedLine()}if((line[0]==="=")){line=line.substr(1,line.length).trim();if(escapeHtmlByDefault){return escapedLine()}else{return unescapedLine()}}return parse_interpol(line)}())}});if(block){output.push(block.process())}var txt=output.filter(function(part){return part&&part.length>0}).join(" +\n");if(txt.length==0){txt='""'}return txt}function optimize(js){var new_js=[],buffer=[],part,end;function flush(){if(buffer.length>0){new_js.push(JSON.stringify(buffer.join(""))+end);buffer=[]}}js.replace(/\n\r|\r/g,"\n").split("\n").forEach(function(line){part=line.match(/^(\".*\")(\s*\+\s*)?$/);if(!part){flush();new_js.push(line);return}end=part[2]||"";part=part[1];try{buffer.push(JSON.parse(part))}catch(e){flush();new_js.push(line)}});flush();return new_js.join("\n")}function render(text,options){options=options||{};text=text||"";var js=compile(text,options);if(options.optimize){js=Haml.optimize(js)}return execute(js,options.context||Haml,options.locals)}function execute(js,self,locals){return(function(){with(locals||{}){try{var _$output;eval("_$output ="+js);return _$output}catch(e){return"\n<pre class='error'>"+html_escape(e.stack)+"</pre>\n"}}}).call(self)}Haml=function Haml(haml,config){if(typeof(config)!="object"){forceXML=config;config={}}var escaper;if(config.customEscape){escaper="";escaperName=config.customEscape}else{escaper=html_escape.toString()+"\n";escaperName="html_escape"}escapeHtmlByDefault=(config.escapeHtmlByDefault||config.escapeHTML||config.escape_html);var js=optimize(compile(haml));var str="with(locals || {}) {\n  try {\n   var _$output="+js+";\n return _$output;  } catch (e) {\n    return \"\\n<pre class='error'>\" + "+escaperName+'(e.stack) + "</pre>\\n";\n  }\n}';try{var f=new Function("locals",escaper+str);return f}catch(e){console.error(str);throw e}};Haml.compile=compile;Haml.optimize=optimize;Haml.render=render;Haml.execute=execute;Haml.html_escape=html_escape}());if(typeof module!=="undefined"){module.exports=Haml};

//blueimp 1.0.2
(function(e){var a=function(b,d){var c=!/[^\-\w]/.test(b)?a.cache[b]=a.cache[b]||a(a.load(b)):new Function(a.arg,("var _s=''"+a.helper+";_s+='"+b.replace(a.regexp,a.func)+"';return _s;").split("_s+='';").join(""));c.tmpl=c.tmpl||a;return d?c(d):c};a.cache={};a.load=function(a){return document.getElementById(a).innerHTML};a.regexp=/(\s+)|('|\\)(?![^%]*%\})|(?:\{%(=|#)(.+?)%\})|(\{%)|(%\})/g;a.func=function(a,d,c,f,g,e,i,h,j){if(d)return h&&h+a.length!==j.length?" ":"";if(c)return"\\"+a;if(f)return"="===
f?"'+_e("+g+")+'":"'+("+g+"||'')+'";if(e)return"';";if(i)return"_s+='"};a.encReg=/[<>&"\x00]/g;a.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","\x00":""};a.encode=function(b){return(""+(b||"")).replace(a.encReg,function(b){return a.encMap[b]})};a.arg="o";a.helper=",_t=arguments.callee.tmpl,_e=_t.encode,print=function(s,e){_s+=e&&(s||'')||_e(s);},include=function(s,d){_s+=_t(s,d);}";"function"===typeof define&&define.amd?define("tmpl",function(){return a}):e.tmpl=a})(this);

/********************************
  PRE-COMPILED TEMPLATES
 ********************************/
// Underscore
window.tpl.underscore = underscore.template("<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%= list[i] %></li><% } %></ul></div>");

// Underscore - no with
window.tpl.underscoreNoWith = underscore.template("<div><h1 class='header'><%= data.header %></h1><h2 class='header2'><%= data.header2 %></h2><h3 class='header3'><%= data.header3 %></h3><h4 class='header4'><%= data.header4 %></h4><h5 class='header5'><%= data.header5 %></h5><h6 class='header6'><%= data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%= data.list[i] %></li><% } %></ul></div>", null, {variable: 'data'});

// Lodash
window.tpl.lodash = _.template("<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%= list[i] %></li><% } %></ul></div>");

// Lodash - no with
window.tpl.lodashNoWith = _.template("<div><h1 class='header'><%= data.header %></h1><h2 class='header2'><%= data.header2 %></h2><h3 class='header3'><%= data.header3 %></h3><h4 class='header4'><%= data.header4 %></h4><h5 class='header5'><%= data.header5 %></h5><h6 class='header6'><%= data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%= data.list[i] %></li><% } %></ul></div>", null, {variable: 'data'});

// Mustache
window.tpl.mustache = "<div><h1 class='header'>{{{header}}}</h1><h2 class='header2'>{{{header2}}}</h2><h3 class='header3'>{{{header3}}}</h3><h4 class='header4'>{{{header4}}}</h4><h5 class='header5'>{{{header5}}}</h5><h6 class='header6'>{{{header6}}}</h6><ul class='list'>{{#list}}<li class='item'>{{{.}}}</li>{{/list}}</ul></div>";
Mustache.parse(window.tpl.mustache);

// Handlebars
window.tpl.handlebars = Handlebars.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#each list}}<li class='item'>{{this}}</li>{{/each}}</ul></div>");

// Kendo
window.tpl.kendo = kendo.template("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>", {useWithBlock:true});
  
window.tpl.kendo2 = kendo.template("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>", {useWithBlock:false});

//John Resig's approach
window.tpl.resig = rtmpl("<div><h1 class='header'><#= header #></h1><h2 class='header2'><#= header2 #></h2><h3 class='header3'><#= header3 #></h3><h4 class='header4'><#= header4 #></h4><h5 class='header5'><#= header5 #></h5><h6 class='header6'><#= header6 #></h6><ul class='list'><# for (var i = 0, l = list.length; i < l; i++) { #><li class='item'><#= list[i] #></li><# } #></ul></div>");

window.tpl.resig2 = rtmpl2("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>");

//jqote2
window.tpl.jqote = $.jqotec("<div><h1 class='header'><%= this.header %></h1><h2 class='header2'><%= this.header2 %></h2><h3 class='header3'><%= this.header3 %></h3><h4 class='header4'><%= this.header4 %></h4><h5 class='header5'><%= this.header5 %></h5><h6 class='header6'><%= this.header6 %></h6><ul class='list'><% for (var n = 0, l = this.list.length; n < l; n++) { %><li class='item'><%= this.list[n] %></li><% } %></ul></div>");

//Dot
window.tpl.dot = doT.template("<div><h1 class='header'>{{= it.header }}</h1><h2 class='header2'>{{= it.header2 }}</h2><h3 class='header3'>{{= it.header3 }}</h3><h4 class='header4'>{{= it.header4 }}</h4><h5 class='header5'>{{= it.header5 }}</h5><h6 class='header6'>{{= it.header6 }}</h6><ul class='list'>{{ for (var i = 0, l = it.list.length; i < l; i++) { }}<li class='item'>{{= it.list[i] }}</li>{{ } }}</ul></div>");

//doU
window.tpl.doU = doU.template("<div><h1 class='header'>{{= it.header }}</h1><h2 class='header2'>{{= it.header2 }}</h2><h3 class='header3'>{{= it.header3 }}</h3><h4 class='header4'>{{= it.header4 }}</h4><h5 class='header5'>{{= it.header5 }}</h5><h6 class='header6'>{{= it.header6 }}</h6><ul class='list'>{{ for (var i = 0, l = it.list.length; i < l; i++) { }}<li class='item'>{{= it.list[i] }}</li>{{ } }}</ul></div>");


//hogan
window.tpl.hogan = Hogan.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{.}}</li>{{/list}}</ul></div>");

//haml
try {
window.tpl.haml = Haml("%div\n  %h1.header= header\n  %h2.header2= header2\n  %h3.header3= header3\n  %h4.header4= header4\n  %h5.header5= header5\n  %h6.header6= header6\n");
} catch(ex) {
$(".user-output").append("WARNING: HAML could not be compiled on this browser!<br/>");
}

//pure
window.tpl.pure = $p('div.pure').compile({
  h1: 'header',
  h2: 'header2',
  h3: 'header3',
  h4: 'header4',
  h5: 'header5',
  h6: 'header6'
});

//dust
(function(){dust.register("dusttmp",body_0);function body_0(chk,ctx){return chk.write("<h1 class='header'>").reference(ctx.get("header"),ctx,"h").write("</h1><h2 class='header2'>").reference(ctx.get("header2"),ctx,"h").write("</h2><h3 class='header3'>").reference(ctx.get("header3"),ctx,"h").write("</h3><h4 class='header4'>").reference(ctx.get("header4"),ctx,"h").write("</h4><h5 class='header5'>").reference(ctx.get("header5"),ctx,"h").write("</h5><h6 class='header6'>").reference(ctx.get("header6"),ctx,"h").write("</h6>");}return body_0;})();

//blueimp
window.tpl.blueimp = tmpl("<div><h1 class='header'>{%=o.header%}</h1><h2 class='header2'>{%=o.header2%}</h2><h3 class='header3'>{%=o.header3%}</h3><h4 class='header4'>{%=o.header4%}</h4><h5 class='header5'>{%=o.header5%}</h5><h6 class='header6'>{%=o.header6%}</h6></div>");

//eco
window.tpl.eco = eco("<div><h1 class='header'><%- @header %></h1><h2 class='header2'><%- @header2 %></h2><h3 class='header3'><%- @header3 %></h3><h4 class='header4'><%- @header4 %></h4><h5 class='header5'><%- @header5 %></h5><h6 class='header6'><%- @header6 %></h6></div>");

//Ejs
window.tpl.ejs = new EJS({text: "<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6></div>"});

//Jade
window.tpl.jadeCompiled = window.tpl.jade_compiled = jade.compile('div\n  h1(class="header")= header\n  h2(class="header2")= header2\n  h3(class="header3")= header3\n  h4(class="header4")= header4\n  h5(class="header5")= header5\n  h6(class="header6")= header6\nul(class="list")\n  each item in list\n    li=item');

//KiTe
window.tpl.kite = kite("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{.}}</li>{{/list}}</ul></div>");

//jsRender
$.templates({ jsr: "<div><h1 class='header'>{{:header}}</h1><h2 class='header'>{{:header2}}</h2><h3 class='header'>{{:header3}}</h3><h4 class='header'>{{:header4}}</h4><h5 class='header'>{{:header5}}</h5><h6 class='header'>{{:header6}}</h6><ul class='list'>{{for list}}<li class='item'>{{:#data}}</li>{{/for}}</ul></div>" });

// Mote
window.tpl.mote = mote.compile("<div><h1 class='header'>{{{header}}}</h1><h2 class='header2'>{{{header2}}}</h2><h3 class='header3'>{{{header3}}}</h3><h4 class='header4'>{{{header4}}}</h4><h5 class='header5'>{{{header5}}}</h5><h6 class='header6'>{{{header6}}}</h6><ul class='list'>{{#list}}<li class='item'>{{{.}}}</li>{{/list}}</ul></div>");

// vash 
window.tpl.vash1 = vash.compile("<div><h1 class='header'>@model.header</h1><h2 class='header2'>@model.header2</h2><h3 class='header3'>@model.header3</h3><h4 class='header4'>@model.header4</h4><h5 class='header5'>@model.header5</h5><h6 class='header6'>@model.header6</h6><ul class='list'>@for (var i = 0, l = model.list.length; i < l; i++) { <li class='item'>@model.list[i]</li> } </ul></div>");

// vash without html escaping
window.tpl.vash2 = vash.compile("<div><h1 class='header'>@model.header</h1><h2 class='header2'>@model.header2</h2><h3 class='header3'>@model.header3</h3><h4 class='header4'>@model.header4</h4><h5 class='header5'>@model.header5</h5><h6 class='header6'>@model.header6</h6><ul class='list'>@for (var i = 0, l = model.list.length; i < l; i++) { <li class='item'>@model.list[i]</li> } </ul></div>", { htmlEscape: false });

// simple-template.js
window.tpl.simpleTemplate = compileTemplate("<div><h1 class='header'><%= data.header %></h1><h2 class='header2'><%= data.header2 %></h2><h3 class='header3'><%= data.header3 %></h3><h4 class='header4'><%= data.header4 %></h4><h5 class='header5'><%= data.header5 %></h5><h6 class='header6'><%= data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%= data.list[i] %></li><% } %></ul></div>");

// Jiko
// Jiko is designed to be pre-compiled server side then minified
// and concatenated with the rest of the javascript files of the
// application. Here, I minify the compiled template manually.
// It has no consequences on performances compared to including
// the minified version directly like that's the case for some
// other template engines. I just think it's cleaner and easier
// to verify this way.
var compiledjiko = jiko.compile("<div><h1 class='header'>%{a.header}</h1><h2 class='header2'>%{a.header2}</h2><h3 class='header3'>%{a.header3}</h3><h4 class='header4'>%{a.header4}</h4><h5 class='header5'>%{a.header5}</h5><h6 class='header6'>%{a.header6}</h6><ul class='list'><% for (var i = 0, l = a.list.length; i < l; i++) { %><li class='item'>%{a.list[i]}</li><% } %></ul></div>");
window.tpl.jiko = new Function("return " + uglify(compiledjiko) + ";")();

</script>
    

Preparation code output

<script src="http://coffeescript.org/extras/coffee-script.js"></script> <script src="http://underscorejs.org/underscore-min.js"></script> <script> var underscore = _; </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.compat.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.js"></script> <script src="http://cdn.kendostatic.com/2014.1.318/js/kendo.all.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/hogan.js/3.0.0/hogan.js"></script> <script src="https://rawgit.com/pure/pure/master/libs/pure.js"></script> <script src="https://rawgit.com/linkedin/dustjs/master/dist/dust-full.js"></script> <script src="https://sstephenson.github.io/eco/dist/eco.js"></script> <script src="http://embeddedjs.com/javascripts/ejs_production.js"></script> <script src="https://cdn.jsdelivr.net/mustache.js/0.8.1/mustache.min.js"></script> <script src="https://cdn.jsdelivr.net/jquery.jqote2/0.9.8/jquery.jqote2.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jade/1.3.1/jade.min.js"></script> <script src="http://terrainformatica.com/kite/kite.js"></script> <script src="http://borismoore.github.com/jsrender/jsrender.js"></script> <script src="http://satchmorun.github.com/mote/mote.js"></script> <script src="https://rawgit.com/snoguchi/simple-template.js/master/simple-template.js"></script> <script src="https://rawgit.com/nicolas-van/jiko/master/jiko.js"></script> <script src="https://rawgit.com/kirbysayshi/vash/master/build/vash.min.js"></script> <script src="https://rawgit.com/olado/doT/master/doT.min.js"></script> <script src="https://rawgit.com/Trenker/Browser-UglifyJS/2f1c56681b5bfec706292294bff23a1136fcd659/build/uglifyjs.1.2.5.js"></script> <!---------------------------> <!-- DOM TEMPLATES --> <!---------------------------> <div class="pure"> <h1 class='header'></h1> <h2 class='header2'></h2> <h3 class='header3'></h3> <h4 class='header4'></h4> <h5 class='header5'></h5> <h6 class='header6'></h6> </div> <script> /**************************************** MASTER TEMPLATE DATA ****************************************/ window.tpl = {}; window.tpl.vars = { header: "Header", header2: "Header2", header3: "Header3", header4: "Header4", header5: "Header5", header6: "Header6", list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] }; window.tpl.vars2 = { header: "Header", header2: "Header2", header3: "Header3", header4: "Header4", header5: "Header5", header6: "Header6", list: [{i:'1'}, {i:'2'}, {i:'3'}, {i:'4'}, {i:'5'}, {i:'6'}, {i:'7'}, {i:'8'}, {i:'9'}, {i:'10'}] }; /**************************************** TEMPLATE ENGINES NOT HOSTED BY A CDN (github) ****************************************/ //Please minify any hard included library and note the version. //Resig Template Function (modified to support ') function rtmpl(a){var b="var p=[];"+"with(obj){p.push('"+a.replace(/[\r\t\n]/g," ").replace(/'(?=[^#]*#>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<#=(.+?)#>/g,"',$1,'").split("<#").join("');").split("#>").join("p.push('")+"');}return p.join('');";return new Function("obj",b)} //Resig modified template function (no "with" block) function rtmpl2(a){var b="var p=[];"+"p.push('"+a.replace(/[\r\t\n]/g," ").replace(/'(?=[^#]*#>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<#=(.+?)#>/g,"',$1,'").split("<#").join("');").split("#>").join("p.push('")+"');return p.join('');";return new Function("data",b)} //doT 2 (function(){var a={version:"0.1.2"};typeof module!="undefined"&&module.exports?module.exports=a:this.doU=a,a.templateSettings={begin:"{{",end:"}}",varname:"it"},a.template=function(b,c){c=c||a.templateSettings;var d="",e=c.begin,f=c.end,g,h,i=b.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g,"").split(e).join(f+"").split(f);for(g=0,h=i.length;g<h;g++)d+=i[g].charAt(0)!==""?"out+='"+i[g].replace(/(\\|["'])/g,"\\$1")+"'":i[g].charAt(1)==="="?";out+=("+i[g].substr(2)+");":i[g].charAt(1)==="!"?";out+=("+i[g].substr(2)+").toString().replace(/&(?!\\w+;)/g, '&#38;').split('<').join('&#60;').split('>').join('&#62;').split('"+'"'+"').join('&#34;').split("+'"'+"'"+'"'+").join('&#39;').split('/').join('&#x2F;');":";"+i[g].substr(1);d=('var out="";'+d+";return out;").split("out+='';").join("").split('var out="";out+=').join("var out=");try{return new Function(c.varname,d)}catch(j){throw typeof console!="undefined"&&console.log("Could not create a template function: "+d),j}}})(); //Haml (July 16 2011) var Haml;(function(){var matchers,self_close_tags,embedder,forceXML,escaperName,escapeHtmlByDefault;function html_escape(text){return(text+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;")}function render_attribs(attribs){var key,value,result=[];for(key in attribs){if(key!=="_content"&&attribs.hasOwnProperty(key)){switch(attribs[key]){case"undefined":case"false":case"null":case'""':break;default:try{value=JSON.parse("["+attribs[key]+"]")[0];if(value===true){value=key}else{if(typeof value==="string"&&embedder.test(value)){value='" +\n'+parse_interpol(html_escape(value))+' +\n"'}else{value=html_escape(value)}}result.push(" "+key+'=\\"'+value+'\\"')}catch(e){result.push(" "+key+'=\\"" + '+escaperName+"("+attribs[key]+') + "\\"')}}}}return result.join("")}function parse_attribs(line){var attributes={},l=line.length,i,c,count=1,quote=false,skip=false,open,close,joiner,seperator,pair={start:1,middle:null,end:null};if(!(l>0&&(line.charAt(0)==="{"||line.charAt(0)==="("))){return{_content:line[0]===" "?line.substr(1,l):line}}open=line.charAt(0);close=(open==="{")?"}":")";joiner=(open==="{")?":":"=";seperator=(open==="{")?",":" ";function process_pair(){if(typeof pair.start==="number"&&typeof pair.middle==="number"&&typeof pair.end==="number"){var key=line.substr(pair.start,pair.middle-pair.start).trim(),value=line.substr(pair.middle+1,pair.end-pair.middle-1).trim();attributes[key]=value}pair={start:null,middle:null,end:null}}for(i=1;count>0;i+=1){if(i>l){throw"Malformed attribute block"}c=line.charAt(i);if(skip){skip=false}else{if(quote){if(c==="\\"){skip=true}if(c===quote){quote=false}}else{if(c==='"'||c==="'"){quote=c}if(count===1){if(c===joiner){pair.middle=i}if(c===seperator||c===close){pair.end=i;process_pair();if(c===seperator){pair.start=i+1}}}if(c===open||c==="("){count+=1}if(c===close||(count>1&&c===")")){count-=1}}}}attributes._content=line.substr(i,line.length);return attributes}function parse_interpol(value){var items=[],pos=0,next=0,match;while(true){next=value.substr(pos).search(embedder);if(next<0){if(pos<value.length){items.push(JSON.stringify(value.substr(pos)))}break}items.push(JSON.stringify(value.substr(pos,next)));pos+=next;match=value.substr(pos).match(embedder);next=match[0].length;if(next<0){break}if(match[1]==="#"){items.push(escaperName+"("+(match[2]||match[3])+")")}else{items.push(match[2]||match[3])}pos+=next}return items.filter(function(part){return part&&part.length>0}).join(" +\n")}embedder=/([#!])\{([^}]*)\}/;self_close_tags=["meta","img","link","br","hr","input","area","base"];matchers=[{name:"html tags",regexp:/^(\s*)((?:[.#%][a-z_\-][a-z0-9_:\-]*)+)(.*)$/i,process:function(){var line_beginning,tag,classes,ids,attribs,content,whitespaceSpecifier,whitespace={},output;line_beginning=this.matches[2];classes=line_beginning.match(/\.([a-z_\-][a-z0-9_\-]*)/gi);ids=line_beginning.match(/\#([a-z_\-][a-z0-9_\-]*)/gi);tag=line_beginning.match(/\%([a-z_\-][a-z0-9_:\-]*)/gi);tag=tag?tag[0].substr(1,tag[0].length):"div";attribs=this.matches[3];if(attribs){attribs=parse_attribs(attribs);if(attribs._content){var leader0=attribs._content.charAt(0),leader1=attribs._content.charAt(1),leaderLength=0;if(leader0=="<"){leaderLength++;whitespace.inside=true;if(leader1==">"){leaderLength++;whitespace.around=true}}else{if(leader0==">"){leaderLength++;whitespace.around=true;if(leader1=="<"){leaderLength++;whitespace.inside=true}}}attribs._content=attribs._content.substr(leaderLength);this.contents.unshift(attribs._content.trim());delete (attribs._content)}}else{attribs={}}if(classes){classes=classes.map(function(klass){return klass.substr(1,klass.length)}).join(" ");if(attribs["class"]){try{attribs["class"]=JSON.stringify(classes+" "+JSON.parse(attribs["class"]))}catch(e){attribs["class"]=JSON.stringify(classes+" ")+" + "+attribs["class"]}}else{attribs["class"]=JSON.stringify(classes)}}if(ids){ids=ids.map(function(id){return id.substr(1,id.length)}).join(" ");if(attribs.id){attribs.id=JSON.stringify(ids+" ")+attribs.id}else{attribs.id=JSON.stringify(ids)}}attribs=render_attribs(attribs);content=this.render_contents();if(content==='""'){content=""}if(whitespace.inside){if(content.length==0){content='" "'}else{try{content='" '+JSON.parse(content)+' "'}catch(e){content='" "+\n'+content+'+\n" "'}}}if(forceXML?content.length>0:self_close_tags.indexOf(tag)==-1){output='"<'+tag+attribs+'>"'+(content.length>0?" + \n"+content:"")+' + \n"</'+tag+'>"'}else{output='"<'+tag+attribs+' />"'}if(whitespace.around){output='" '+output.substr(1,output.length-2)+' "'}return output}},{name:"each loop",regexp:/^(\s*)(?::for|:each)\s+(?:([a-z_][a-z_\-]*),\s*)?([a-z_][a-z_\-]*)\s+in\s+(.*)(\s*)$/i,process:function(){var ivar=this.matches[2]||"__key__",vvar=this.matches[3],avar=this.matches[4],rvar="__result__";if(this.matches[5]){this.contents.unshift(this.matches[5])}return"(function () { var "+rvar+" = [], "+ivar+", "+vvar+"; for ("+ivar+" in "+avar+") { if ("+avar+".hasOwnProperty("+ivar+")) { "+vvar+" = "+avar+"["+ivar+"]; "+rvar+".push(\n"+(this.render_contents()||"''")+"\n); } } return "+rvar+'.join(""); }).call(this)'}},{name:"if",regexp:/^(\s*):if\s+(.*)\s*$/i,process:function(){var condition=this.matches[2];return"(function () { if ("+condition+") { return (\n"+(this.render_contents()||"")+'\n);} else { return ""; } }).call(this)'}},{name:"silent-comments",regexp:/^(\s*)-#\s*(.*)\s*$/i,process:function(){return'""'}},{name:"silent-comments",regexp:/^(\s*)\/\s*(.*)\s*$/i,process:function(){this.contents.unshift(this.matches[2]);return'"<!--'+this.contents.join("\\n")+'-->"'}},{name:"rawjs",regexp:/^(\s*)-\s*(.*)\s*$/i,process:function(){this.contents.unshift(this.matches[2]);return'"";'+this.contents.join("\n")+"; _$output = _$output "}},{name:"pre",regexp:/^(\s*):pre(\s+(.*)|$)/i,process:function(){this.contents.unshift(this.matches[2]);return'"<pre>"+\n'+JSON.stringify(this.contents.join("\n"))+'+\n"</pre>"'}},{name:"doctype",regexp:/^()!!!(?:\s*(.*))\s*$/,process:function(){var line="";switch((this.matches[2]||"").toLowerCase()){case"":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';break;case"strict":case"1.0":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';break;case"frameset":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';break;case"5":line="<!DOCTYPE html>";break;case"1.1":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';break;case"basic":line='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">';break;case"mobile":line='<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">';break;case"xml":line="<?xml version='1.0' encoding='utf-8' ?>";break;case"xml iso-8859-1":line="<?xml version='1.0' encoding='iso-8859-1' ?>";break}return JSON.stringify(line+"\n")}},{name:"markdown",regexp:/^(\s*):markdown\s*$/i,process:function(){return parse_interpol(exports.Markdown.encode(this.contents.join("\n")))}},{name:"script",regexp:/^(\s*):(?:java)?script\s*$/,process:function(){return parse_interpol('\n<script>\n//<![CDATA[\n'+this.contents.join("\n")+"\n//]]>\n<\/script>\n")}},{name:"css",regexp:/^(\s*):css\s*$/,process:function(){return JSON.stringify('<style type="text/css">\n'+this.contents.join("\n")+"\n</style>")}}];function compile(lines){var block=false,output=[];if(typeof lines==="string"){lines=lines.trim().replace(/\n\r|\r/g,"\n").split("\n")}lines.forEach(function(line){var match,found=false;if(block){match=block.check_indent.exec(line);if(match){block.contents.push(match[1]||"");return}else{output.push(block.process());block=false}}matchers.forEach(function(matcher){if(!found){match=matcher.regexp.exec(line);if(match){block={contents:[],indent_level:(match[1]),matches:match,check_indent:new RegExp("^(?:\\s*|"+match[1]+" (.*))$"),process:matcher.process,render_contents:function(){return compile(this.contents)}};found=true}}});if(!found){output.push(function(){if(line[0]==="\\"){return parse_interpol(line.substr(1,line.length))}function escapedLine(){try{return escaperName+"("+JSON.stringify(JSON.parse(line))+")"}catch(e2){return escaperName+"("+line+")"}}function unescapedLine(){try{return parse_interpol(JSON.parse(line))}catch(e){return line}}if((line.substr(0,2)==="&=")){line=line.substr(2,line.length).trim();return escapedLine()}if((line.substr(0,2)==="!=")){line=line.substr(2,line.length).trim();return unescapedLine()}if((line[0]==="=")){line=line.substr(1,line.length).trim();if(escapeHtmlByDefault){return escapedLine()}else{return unescapedLine()}}return parse_interpol(line)}())}});if(block){output.push(block.process())}var txt=output.filter(function(part){return part&&part.length>0}).join(" +\n");if(txt.length==0){txt='""'}return txt}function optimize(js){var new_js=[],buffer=[],part,end;function flush(){if(buffer.length>0){new_js.push(JSON.stringify(buffer.join(""))+end);buffer=[]}}js.replace(/\n\r|\r/g,"\n").split("\n").forEach(function(line){part=line.match(/^(\".*\")(\s*\+\s*)?$/);if(!part){flush();new_js.push(line);return}end=part[2]||"";part=part[1];try{buffer.push(JSON.parse(part))}catch(e){flush();new_js.push(line)}});flush();return new_js.join("\n")}function render(text,options){options=options||{};text=text||"";var js=compile(text,options);if(options.optimize){js=Haml.optimize(js)}return execute(js,options.context||Haml,options.locals)}function execute(js,self,locals){return(function(){with(locals||{}){try{var _$output;eval("_$output ="+js);return _$output}catch(e){return"\n<pre class='error'>"+html_escape(e.stack)+"</pre>\n"}}}).call(self)}Haml=function Haml(haml,config){if(typeof(config)!="object"){forceXML=config;config={}}var escaper;if(config.customEscape){escaper="";escaperName=config.customEscape}else{escaper=html_escape.toString()+"\n";escaperName="html_escape"}escapeHtmlByDefault=(config.escapeHtmlByDefault||config.escapeHTML||config.escape_html);var js=optimize(compile(haml));var str="with(locals || {}) {\n try {\n var _$output="+js+";\n return _$output; } catch (e) {\n return \"\\n<pre class='error'>\" + "+escaperName+'(e.stack) + "</pre>\\n";\n }\n}';try{var f=new Function("locals",escaper+str);return f}catch(e){console.error(str);throw e}};Haml.compile=compile;Haml.optimize=optimize;Haml.render=render;Haml.execute=execute;Haml.html_escape=html_escape}());if(typeof module!=="undefined"){module.exports=Haml}; //blueimp 1.0.2 (function(e){var a=function(b,d){var c=!/[^\-\w]/.test(b)?a.cache[b]=a.cache[b]||a(a.load(b)):new Function(a.arg,("var _s=''"+a.helper+";_s+='"+b.replace(a.regexp,a.func)+"';return _s;").split("_s+='';").join(""));c.tmpl=c.tmpl||a;return d?c(d):c};a.cache={};a.load=function(a){return document.getElementById(a).innerHTML};a.regexp=/(\s+)|('|\\)(?![^%]*%\})|(?:\{%(=|#)(.+?)%\})|(\{%)|(%\})/g;a.func=function(a,d,c,f,g,e,i,h,j){if(d)return h&&h+a.length!==j.length?" ":"";if(c)return"\\"+a;if(f)return"="=== f?"'+_e("+g+")+'":"'+("+g+"||'')+'";if(e)return"';";if(i)return"_s+='"};a.encReg=/[<>&"\x00]/g;a.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","\x00":""};a.encode=function(b){return(""+(b||"")).replace(a.encReg,function(b){return a.encMap[b]})};a.arg="o";a.helper=",_t=arguments.callee.tmpl,_e=_t.encode,print=function(s,e){_s+=e&&(s||'')||_e(s);},include=function(s,d){_s+=_t(s,d);}";"function"===typeof define&&define.amd?define("tmpl",function(){return a}):e.tmpl=a})(this); /******************************** PRE-COMPILED TEMPLATES ********************************/ // Underscore window.tpl.underscore = underscore.template("<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%= list[i] %></li><% } %></ul></div>"); // Underscore - no with window.tpl.underscoreNoWith = underscore.template("<div><h1 class='header'><%= data.header %></h1><h2 class='header2'><%= data.header2 %></h2><h3 class='header3'><%= data.header3 %></h3><h4 class='header4'><%= data.header4 %></h4><h5 class='header5'><%= data.header5 %></h5><h6 class='header6'><%= data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%= data.list[i] %></li><% } %></ul></div>", null, {variable: 'data'}); // Lodash window.tpl.lodash = _.template("<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%= list[i] %></li><% } %></ul></div>"); // Lodash - no with window.tpl.lodashNoWith = _.template("<div><h1 class='header'><%= data.header %></h1><h2 class='header2'><%= data.header2 %></h2><h3 class='header3'><%= data.header3 %></h3><h4 class='header4'><%= data.header4 %></h4><h5 class='header5'><%= data.header5 %></h5><h6 class='header6'><%= data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%= data.list[i] %></li><% } %></ul></div>", null, {variable: 'data'}); // Mustache window.tpl.mustache = "<div><h1 class='header'>{{{header}}}</h1><h2 class='header2'>{{{header2}}}</h2><h3 class='header3'>{{{header3}}}</h3><h4 class='header4'>{{{header4}}}</h4><h5 class='header5'>{{{header5}}}</h5><h6 class='header6'>{{{header6}}}</h6><ul class='list'>{{#list}}<li class='item'>{{{.}}}</li>{{/list}}</ul></div>"; Mustache.parse(window.tpl.mustache); // Handlebars window.tpl.handlebars = Handlebars.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#each list}}<li class='item'>{{this}}</li>{{/each}}</ul></div>"); // Kendo window.tpl.kendo = kendo.template("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>", {useWithBlock:true}); window.tpl.kendo2 = kendo.template("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>", {useWithBlock:false}); //John Resig's approach window.tpl.resig = rtmpl("<div><h1 class='header'><#= header #></h1><h2 class='header2'><#= header2 #></h2><h3 class='header3'><#= header3 #></h3><h4 class='header4'><#= header4 #></h4><h5 class='header5'><#= header5 #></h5><h6 class='header6'><#= header6 #></h6><ul class='list'><# for (var i = 0, l = list.length; i < l; i++) { #><li class='item'><#= list[i] #></li><# } #></ul></div>"); window.tpl.resig2 = rtmpl2("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>"); //jqote2 window.tpl.jqote = $.jqotec("<div><h1 class='header'><%= this.header %></h1><h2 class='header2'><%= this.header2 %></h2><h3 class='header3'><%= this.header3 %></h3><h4 class='header4'><%= this.header4 %></h4><h5 class='header5'><%= this.header5 %></h5><h6 class='header6'><%= this.header6 %></h6><ul class='list'><% for (var n = 0, l = this.list.length; n < l; n++) { %><li class='item'><%= this.list[n] %></li><% } %></ul></div>"); //Dot window.tpl.dot = doT.template("<div><h1 class='header'>{{= it.header }}</h1><h2 class='header2'>{{= it.header2 }}</h2><h3 class='header3'>{{= it.header3 }}</h3><h4 class='header4'>{{= it.header4 }}</h4><h5 class='header5'>{{= it.header5 }}</h5><h6 class='header6'>{{= it.header6 }}</h6><ul class='list'>{{ for (var i = 0, l = it.list.length; i < l; i++) { }}<li class='item'>{{= it.list[i] }}</li>{{ } }}</ul></div>"); //doU window.tpl.doU = doU.template("<div><h1 class='header'>{{= it.header }}</h1><h2 class='header2'>{{= it.header2 }}</h2><h3 class='header3'>{{= it.header3 }}</h3><h4 class='header4'>{{= it.header4 }}</h4><h5 class='header5'>{{= it.header5 }}</h5><h6 class='header6'>{{= it.header6 }}</h6><ul class='list'>{{ for (var i = 0, l = it.list.length; i < l; i++) { }}<li class='item'>{{= it.list[i] }}</li>{{ } }}</ul></div>"); //hogan window.tpl.hogan = Hogan.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{.}}</li>{{/list}}</ul></div>"); //haml try { window.tpl.haml = Haml("%div\n %h1.header= header\n %h2.header2= header2\n %h3.header3= header3\n %h4.header4= header4\n %h5.header5= header5\n %h6.header6= header6\n"); } catch(ex) { $(".user-output").append("WARNING: HAML could not be compiled on this browser!<br/>"); } //pure window.tpl.pure = $p('div.pure').compile({ h1: 'header', h2: 'header2', h3: 'header3', h4: 'header4', h5: 'header5', h6: 'header6' }); //dust (function(){dust.register("dusttmp",body_0);function body_0(chk,ctx){return chk.write("<h1 class='header'>").reference(ctx.get("header"),ctx,"h").write("</h1><h2 class='header2'>").reference(ctx.get("header2"),ctx,"h").write("</h2><h3 class='header3'>").reference(ctx.get("header3"),ctx,"h").write("</h3><h4 class='header4'>").reference(ctx.get("header4"),ctx,"h").write("</h4><h5 class='header5'>").reference(ctx.get("header5"),ctx,"h").write("</h5><h6 class='header6'>").reference(ctx.get("header6"),ctx,"h").write("</h6>");}return body_0;})(); //blueimp window.tpl.blueimp = tmpl("<div><h1 class='header'>{%=o.header%}</h1><h2 class='header2'>{%=o.header2%}</h2><h3 class='header3'>{%=o.header3%}</h3><h4 class='header4'>{%=o.header4%}</h4><h5 class='header5'>{%=o.header5%}</h5><h6 class='header6'>{%=o.header6%}</h6></div>"); //eco window.tpl.eco = eco("<div><h1 class='header'><%- @header %></h1><h2 class='header2'><%- @header2 %></h2><h3 class='header3'><%- @header3 %></h3><h4 class='header4'><%- @header4 %></h4><h5 class='header5'><%- @header5 %></h5><h6 class='header6'><%- @header6 %></h6></div>"); //Ejs window.tpl.ejs = new EJS({text: "<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6></div>"}); //Jade window.tpl.jadeCompiled = window.tpl.jade_compiled = jade.compile('div\n h1(class="header")= header\n h2(class="header2")= header2\n h3(class="header3")= header3\n h4(class="header4")= header4\n h5(class="header5")= header5\n h6(class="header6")= header6\nul(class="list")\n each item in list\n li=item'); //KiTe window.tpl.kite = kite("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{.}}</li>{{/list}}</ul></div>"); //jsRender $.templates({ jsr: "<div><h1 class='header'>{{:header}}</h1><h2 class='header'>{{:header2}}</h2><h3 class='header'>{{:header3}}</h3><h4 class='header'>{{:header4}}</h4><h5 class='header'>{{:header5}}</h5><h6 class='header'>{{:header6}}</h6><ul class='list'>{{for list}}<li class='item'>{{:#data}}</li>{{/for}}</ul></div>" }); // Mote window.tpl.mote = mote.compile("<div><h1 class='header'>{{{header}}}</h1><h2 class='header2'>{{{header2}}}</h2><h3 class='header3'>{{{header3}}}</h3><h4 class='header4'>{{{header4}}}</h4><h5 class='header5'>{{{header5}}}</h5><h6 class='header6'>{{{header6}}}</h6><ul class='list'>{{#list}}<li class='item'>{{{.}}}</li>{{/list}}</ul></div>"); // vash window.tpl.vash1 = vash.compile("<div><h1 class='header'>@model.header</h1><h2 class='header2'>@model.header2</h2><h3 class='header3'>@model.header3</h3><h4 class='header4'>@model.header4</h4><h5 class='header5'>@model.header5</h5><h6 class='header6'>@model.header6</h6><ul class='list'>@for (var i = 0, l = model.list.length; i < l; i++) { <li class='item'>@model.list[i]</li> } </ul></div>"); // vash without html escaping window.tpl.vash2 = vash.compile("<div><h1 class='header'>@model.header</h1><h2 class='header2'>@model.header2</h2><h3 class='header3'>@model.header3</h3><h4 class='header4'>@model.header4</h4><h5 class='header5'>@model.header5</h5><h6 class='header6'>@model.header6</h6><ul class='list'>@for (var i = 0, l = model.list.length; i < l; i++) { <li class='item'>@model.list[i]</li> } </ul></div>", { htmlEscape: false }); // simple-template.js window.tpl.simpleTemplate = compileTemplate("<div><h1 class='header'><%= data.header %></h1><h2 class='header2'><%= data.header2 %></h2><h3 class='header3'><%= data.header3 %></h3><h4 class='header4'><%= data.header4 %></h4><h5 class='header5'><%= data.header5 %></h5><h6 class='header6'><%= data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%= data.list[i] %></li><% } %></ul></div>"); // Jiko // Jiko is designed to be pre-compiled server side then minified // and concatenated with the rest of the javascript files of the // application. Here, I minify the compiled template manually. // It has no consequences on performances compared to including // the minified version directly like that's the case for some // other template engines. I just think it's cleaner and easier // to verify this way. var compiledjiko = jiko.compile("<div><h1 class='header'>%{a.header}</h1><h2 class='header2'>%{a.header2}</h2><h3 class='header3'>%{a.header3}</h3><h4 class='header4'>%{a.header4}</h4><h5 class='header5'>%{a.header5}</h5><h6 class='header6'>%{a.header6}</h6><ul class='list'><% for (var i = 0, l = a.list.length; i < l; i++) { %><li class='item'>%{a.list[i]}</li><% } %></ul></div>"); window.tpl.jiko = new Function("return " + uglify(compiledjiko) + ";")(); </script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Mustache (compiled)
Mustache.render(tpl.mustache, tpl.vars);
pending…
Kendo UI
tpl.kendo(tpl.vars);
pending…
Handlebars
tpl.handlebars(tpl.vars)
pending…
Underscore
tpl.underscore(tpl.vars);
pending…
Resig Micro Templates
tpl.resig(tpl.vars)
pending…
Resig Micro Templates (No "with" block)
tpl.resig2(tpl.vars)
pending…
jqote2
$.jqote(tpl.jqote, tpl.vars);
pending…
DoT
tpl.dot(tpl.vars);
pending…
Hogan
tpl.hogan.render(tpl.vars)
pending…
Haml (7/16/11) (DOT2)
//WARNING: Compilation of the template fails in IE7!
tpl.haml(tpl.vars);
pending…
Pure
tpl.pure(tpl.vars);
pending…
Linked-in Dust
dust.render('dusttmp', tpl.vars, function() {});
pending…
Blueimp 1.0.2
window.tpl.blueimp(tpl.vars);
pending…
eco
tpl.eco(tpl.vars);
pending…
ejs
tpl.ejs.render(tpl.vars);
pending…
Jade
tpl.jadeCompiled(tpl.vars);
pending…
jsRender (jQuery Templates)
$.render.jsr(tpl.vars);
pending…
Underscore - (no "with" block)
tpl.underscoreNoWith(tpl.vars);
pending…
simple-template.js
tpl.simpleTemplate(tpl.vars);
pending…
Lo-Dash
tpl.lodash(tpl.vars);
pending…
Lo-Dash - (no "with" block)
tpl.lodashNoWith(tpl.vars);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments