Mustache vs micro templating

Benchmark created on


Preparation HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Test runner

Ready to run.

Testing in
TestOps/sec
Mustache
var Mustache=function(){var a={};var b=function(){};b.prototype={otag:"{{",ctag:"}}",pragmas:{},buffer:[],pragmas_implemented:{"IMPLICIT-ITERATOR":true},context:{},render:function(f,e,d,g){if(!g){this.context=e;this.buffer=[]}if(!this.includes("",f)){if(g){return f}else{this.send(f);return}}f=this.render_pragmas(f);var c=this.render_section(f,e,d);if(c===false){c=this.render_tags(f,e,d,g)}if(g){return c}else{this.sendLines(c)}},send:function(c){if(c!==""){this.buffer.push(c)}},sendLines:function(e){if(e){var c=e.split("\n");for(var d=0;d<c.length;d++){this.send(c[d])}}},render_pragmas:function(c){if(!this.includes("%",c)){return c}var e=this;var d=this.getCachedRegex("render_pragmas",function(g,f){return new RegExp(g+"%([\\w-]+) ?([\\w]+=[\\w]+)?"+f,"g")});return c.replace(d,function(h,f,g){if(!e.pragmas_implemented[f]){throw ({message:"This implementation of mustache doesn't understand the '"+f+"' pragma"})}e.pragmas[f]={};if(g){var i=g.split("=");e.pragmas[f][i[0]]=i[1]}return""})},render_partial:function(c,e,d){c=this.trim(c);if(!d||d[c]===undefined){throw ({message:"unknown_partial '"+c+"'"})}if(typeof(e[c])!="object"){return this.render(d[c],e,d,true)}return this.render(d[c],e[c],d,true)},render_section:function(e,d,c){if(!this.includes("#",e)&&!this.includes("^",e)){return false}var g=this;var f=this.getCachedRegex("render_section",function(i,h){return new RegExp("^([\\s\\S]*?)"+i+"(\\^|\\#)\\s*(.+)\\s*"+h+"\n*([\\s\\S]*?)"+i+"\\/\\s*\\3\\s*"+h+"\\s*([\\s\\S]*)$","g")});return e.replace(f,function(k,o,n,j,l,i){var q=o?g.render_tags(o,d,c,true):"",m=i?g.render(i,d,c,true):"",h,p=g.find(j,d);if(n==="^"){if(!p||g.is_array(p)&&p.length===0){h=g.render(l,d,c,true)}else{h=""}}else{if(n==="#"){if(g.is_array(p)){h=g.map(p,function(r){return g.render(l,g.create_context(r),c,true)}).join("")}else{if(g.is_object(p)){h=g.render(l,g.create_context(p),c,true)}else{if(typeof p==="function"){h=p.call(d,l,function(r){return g.render(r,d,c,true)})}else{if(p){h=g.render(l,d,c,true)}else{h=""}}}}}}return q+h+m})},render_tags:function(l,c,e,g){var f=this;var k=function(){return f.getCachedRegex("render_tags",function(n,i){return new RegExp(n+"(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?"+i+"+","g")})};var h=k();var j=function(o,i,n){switch(i){case"!":return"";case"=":f.set_delimiters(n);h=k();return"";case">":return f.render_partial(n,c,e);case"{":return f.find(n,c);default:return f.escape(f.find(n,c))}};var m=l.split("\n");for(var d=0;d<m.length;d++){m[d]=m[d].replace(h,j,this);if(!g){this.send(m[d])}}if(g){return m.join("\n")}},set_delimiters:function(d){var c=d.split(" ");this.otag=this.escape_regex(c[0]);this.ctag=this.escape_regex(c[1])},escape_regex:function(d){if(!arguments.callee.sRE){var c=["/",".","*","+","?","|","(",")","[","]","{","}","\\"];arguments.callee.sRE=new RegExp("(\\"+c.join("|\\")+")","g")}return d.replace(arguments.callee.sRE,"\\$1")},find:function(d,e){d=this.trim(d);function c(g){return g===false||g===0||g}var f;if(d.match(/([a-z_]+)\./ig)){f=c(this.walk_context(d,e))}else{if(c(e[d])){f=e[d]}else{if(c(this.context[d])){f=this.context[d]}}}if(typeof f==="function"){return f.apply(e)}if(f!==undefined){return f}return""},walk_context:function(c,d){var g=c.split(".");var f=(d[g[0]]!=undefined)?d:this.context;var e=f[g.shift()];while(e!=undefined&&g.length>0){f=e;e=e[g.shift()]}if(typeof e==="function"){return e.apply(f)}return e},includes:function(d,c){return c.indexOf(this.otag+d)!=-1},escape:function(c){c=String(c===null?"":c);return c.replace(/&(?!\w+;)|["'<>\\]/g,function(d){switch(d){case"&":return"&amp;";case'"':return"&quot;";case"'":return"&#39;";case"<":return"&lt;";case">":return"&gt;";default:return d}})},create_context:function(d){if(this.is_object(d)){return d}else{var e=".";if(this.pragmas["IMPLICIT-ITERATOR"]){e=this.pragmas["IMPLICIT-ITERATOR"].iterator}var c={};c[e]=d;return c}},is_object:function(c){return c&&typeof c=="object"},is_array:function(c){return Object.prototype.toString.call(c)==="[object Array]"},trim:function(c){return c.replace(/^\s*|\s*$/g,"")},map:function(g,e){if(typeof g.map=="function"){return g.map(e)}else{var f=[];var c=g.length;for(var d=0;d<c;d++){f.push(e(g[d]))}return f}},getCachedRegex:function(d,g){var f=a[this.otag];if(!f){f=a[this.otag]={}}var c=f[this.ctag];if(!c){c=f[this.ctag]={}}var e=c[d];if(!e){e=c[d]=g(this.otag,this.ctag)}return e}};return({name:"mustache.js",version:"0.4.0-dev",to_html:function(e,c,d,g){var f=new b();if(g){f.send=g}f.render(e,c||{},d);if(!g){return f.buffer.join("\n")}}})}();

var template = 
'My skills:' + 
    '{{#skills}}' + 
    '<a href="#">{{.}}</a>' +
    '{{/skills}}';
console.log(Mustache.to_html(template, {
    skills: ["js", "html", "css"]
}));
ready
Micro templating
var App = App || {};
App.render = function(html, options) {
    var re = /<%([^%>]+)?%>/g, reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g, code = 'var r=[];\n', cursor = 0;
    var add = function(line, js) {
        js? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
            (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
        return add;
    }
    while(match = re.exec(html)) {
        add(html.slice(cursor, match.index))(match[1], true);
        cursor = match.index + match[0].length;
    }
    add(html.substr(cursor, html.length - cursor));
    code += 'return r.join("");';
    return new Function(code.replace(/[\r\t\n]/g, '')).apply(options);
}
var template = 
'My skills:' + 
    '<%for(var index in this.skills) {%>' + 
    '<a href="#"><%this.skills[index]%></a>' +
    '<%}%>';
console.log(App.render(template, {
    skills: ["js", "html", "css"]
}));
ready

Revisions

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