Editing Handlebars VS TemplateEngine This edit will create a new revision. Your details (optional) Name Email (won’t be displayed; might be used for Gravatar) URL Test case details Title * Published (uncheck if you want to fiddle around before making the page public) Description (in case you feel further explanation is needed)(Markdown syntax is allowed) Libraries ========= > Handlebars.js (current) > vs > Mustache.js (current) > vs > TemplateEngine (current, 1.8) Notes ===== - **Handlebars** only supports Array iteration by default. In order to compare it with other templates, I have added a simple, fast {{#each}} block helper that works Objects. This would be required in order to use it in a real-world setting, so it is appropriate for the test. - This example specifically does not pre-compile the Handlebars template, because my primary use-case for the result of this test simply cannot accomodate this (it would require execution of code outside the scope of a sandbox). - **Mustache** just doesn't support the type of nested iteration needed for this demo. Not a good sign. It also doesn't support iteration over Objects, and the "." special field doesn't appear to work **at all**. I've attempted to make the result *look* like the other two templates, but the inability to do these basic operations means Mustache just isn't going to cut it. I've left it in the test purely for completeness. Are you a spammer? (just answer the question) Preparation code Preparation code HTML (this will be inserted in the <body> of a valid HTML5 document in standards mode) (useful when testing DOM operations or including libraries) <script src="http://jsonupload.services.jasonmillerdesign.com/file/4085966784759edf34d5ce919d935b90_16d7a767a3603d75eb65cd83ef111755/TemplateEngine-1.8.js"></script> <script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script> <script src="https://raw.github.com/boucher/mustache.js/master/lib/mustache.js"></script> <button onclick="var n=document.getElementById('o').style;n.display=n.display=='none'?'block':'none';">Toggle Output</button> <div id="o" style="display:none;"> <div class="output"> <h1>TemplateEngine</h1> <div id="output_engine"></div> </div> <div class="output"> <h1>Handlebars</h1> <div id="output_handlebars"></div> </div> <div class="output"> <h1>Mustache</h1> <div id="output_mustache"></div> </div> </div> <script id="template-handlebars" type="text/template"><![CDATA[ <div class="foo1"> <h2>{{title}}</h2> <h4>Iterating over an object:</h4> <ul> {{#each list}} <li>{{.}}</li> {{/each}} </ul> <h4>Iterating over an array:</h4> <ol> {{#arr}} <li>{{.}}</li> {{/arr}} </ol> <h4>Recursive nesting:</h4> <ul> {{#each nest1}} <li> <div>key={{__key__}}</div> <ol> {{#.}} <li>{{.}}</li> {{/.}} </ol> </li> {{/each}} </ul> </div> ]]></script> <script id="template-engine" type="text/template"><![CDATA[ <div class="foo1"> <h2>{{title}}</h2> <h4>Iterating over an object:</h4> <ul> {{#each list}} <li>{{.}}</li> {{/each}} </ul> <h4>Iterating over an array:</h4> <ol> {{#each arr}} <li>{{.}}</li> {{/each}} </ol> <h4>Recursive nesting:</h4> <ul> {{#each nest1}} <li> <div>key={{__key__}}</div> <ol> {{#each .}} <li>{{.}}</li> {{/each}} </ol> </li> {{/each}} </ul> </div> ]]></script> <script id="template-mustache" type="text/template"><![CDATA[ <div class="foo1"> <h2>{{title}}</h2> <h4>Iterating over an object:</h4> <ul> {{#arr}} <li>{{arr.0}}</li> {{/arr}} </ul> <h4>Iterating over an array:</h4> <ol> {{#arr}} <li>{{arr.0}}</li> {{/arr}} </ol> <h4>Recursive nesting:</h4> <ul> {{#arr}} <li> <div>key={{__key__}}</div> <ol> {{#nest1.foo}} <li>{{nest1.foo.0}}</li> {{/nest1.foo}} </ol> </li> {{/arr}} </ul> </div> ]]></script> <script> /** NOTE: Handlebars does not support #each for Objects by default. We have to re-implement the each block helper to get that functionality back. The code below is a slightly modified version of the example from the Handlebars website. */ Handlebars.registerHelper('each', function(context, options) { var ret = ""; for(var i in context) { if (context.hasOwnProperty(i)) { ret = ret + options.fn(context[i]); } } return new Handlebars.SafeString(ret); }); //---------------------------- // Collect Templates: var templates = {}; var tpls = document.querySelectorAll('script[type="text/template"]'); [].forEach.call(tpls, function(n) { var tpl = (n.textContent || n.nodeValue || ''); tpl = tpl.replace(/(^<\!\[CDATA\[|\]\]>$)/gm,''); templates[n.id.replace(/^template\-/gi,'')] = tpl; }); // Output Areas: var out = { engine : document.getElementById('output_engine'), handlebars : document.getElementById('output_handlebars'), mustache : document.getElementById('output_mustache') }; var output = {}; var context = { title : "Template Standoff", list : { test : "test value", test2 : "test 2 value", test3 : "test 3 value", }, arr : [ "array value 1", "array value 2", "array value 3", "array value 4" ], nest1 : { foo : [ "nested level 2, item 1, child 1", "nested level 2, item 1, child 2", "nested level 2, item 1, child 3" ], foo2 : [ "nested level 2, item 2, child 1", "nested level 2, item 2, child 2" ], foo3 : [ "nested level 2, item 3, child 1", "nested level 2, item 3, child 2", "nested level 2, item 3, child 3", "nested level 2, item 3, child 4" ] } }; </script> Include JavaScript libraries as follows: <script src="//cdn.ext/library.js"></script> Define setup for all tests (variables, functions, arrays or other objects that will be used in the tests) (runs before each clocked test loop, outside of the timed code region) (e.g. define local test variables, reset global variables, clear canvas, etc.) (see FAQ) var compiled; Define teardown for all tests (runs after each clocked test loop, outside of the timed code region) (see FAQ) out.engine.innerHTML = output.engine; out.handlebars.innerHTML = output.handlebars; out.mustache.innerHTML = output.mustache; Code snippets to compare Test 1 Title Async (check if this is an asynchronous test) Code compiled = Handlebars.compile(templates.handlebars); output.handlebars = compiled(context); Test 2 Title Async (check if this is an asynchronous test) Code output.mustache = Mustache.to_html(templates.mustache, context); Test 3 Title Async (check if this is an asynchronous test) Code output.engine = engine_1_8.template(templates.engine, context);