From 8053051cb6c9326876da30bb339116e27f5fddf2 Mon Sep 17 00:00:00 2001 From: thegrandpoobah Date: Thu, 17 Jun 2010 11:38:55 -0400 Subject: [PATCH] Turn interpreter into a recursive descent parser. --- mustache.js | 151 ++++++++++++++++++++++++++++----------------------- test/unit.js | 2 +- 2 files changed, 84 insertions(+), 69 deletions(-) diff --git a/mustache.js b/mustache.js index 797c7e7..0fa970b 100644 --- a/mustache.js +++ b/mustache.js @@ -13,45 +13,27 @@ var Mustache = function() { escaped_otag: "\{\{", escaped_ctag: "\}\}", pragmas: {}, - buffer: [], pragmas_implemented: { "IMPLICIT-ITERATOR": true }, context: {}, - render: function(template, context, partials, in_recursion) { - // reset buffer & set context - if(!in_recursion) { - this.context = context; - this.buffer = []; // TODO: make this non-lazy - } + render: function(template, context, partials) { + // reset context + this.context = context; // fail fast if(!this.includes("", template)) { - if(in_recursion) { - return template; - } else { - this.send(template); - return; - } + return template; } template = this.render_pragmas(template); - template = this.render_delimiter(template, context, partials); - - var html = this.render_section(template, context, partials); - if(in_recursion) { - return this.render_tags(html, context, partials, in_recursion); - } - - this.render_tags(html, context, partials, in_recursion); + + return this.render_recursive(template, context, partials); }, - - /* - Sends parsed lines - */ - send: function(line) { - this.buffer.push(line); + + render_recursive: function(template, context, partials) { + return this.render_delimiter(template, context, partials); }, /* @@ -84,24 +66,38 @@ var Mustache = function() { render_delimiter: function(template, context, partials) { if(!this.includes("=", template)) { - return template; + return this.render_section(template, context, partials); } var that = this; - var regex = new RegExp(this.escaped_otag + "=(\\S+)\\s+(\\S+)=" + this.escaped_ctag + "\n?([\\s\\S]*)", "mg"); + var regex = new RegExp("(" + this.escaped_otag + "=(?:\\S+)\\s+(?:\\S+)=" + this.escaped_ctag + "\\n*)", "mg"); + var fragments = template.split(regex); - return template.replace(regex, function(match, newOpen, newClose, content) { - var old_otag = that.otag; - var old_ctag = that.ctag; - - that.set_delimiters(newOpen, newClose); - - var html = that.render(content, context, partials, true); - - that.set_delimiters(old_otag, old_ctag); - - return html; - }); + var i, n; + var r = new RegExp(this.escaped_otag + "=(\\S+)\\s+(\\S+)=" + this.escaped_ctag); + var matches; + + for (i=0, n=fragments.length; i": // render partial return that.render_partial(name, context, partials); case "{": // the triple mustache is unescaped - case "&": // the ampersand is also unescaped + case "&": // the ampersand is also unescaped return that.find(name, context); default: // escape the value return that.escape(that.find(name, context)); @@ -195,16 +222,10 @@ var Mustache = function() { var lines = template.split("\n"); var oldContent; for(var i = 0; i < lines.length; i++) { - oldContent = lines[i]; lines[i] = lines[i].replace(regex, tag_replace_callback, this); - if(!in_recursion && (oldContent === "" || lines[i] !== "")) { - this.send(lines[i]); - } } - if(in_recursion) { - return lines.join("\n"); - } + return lines.join("\n"); }, set_delimiters: function(open, close) { @@ -351,15 +372,9 @@ var Mustache = function() { /* Turns a template and view into HTML */ - to_html: function(template, view, partials, send_fun) { + to_html: function(template, view, partials) { var renderer = new Renderer(); - if(send_fun) { - renderer.send = send_fun; - } - renderer.render(template, view, partials); - if(!send_fun) { - return renderer.buffer.join("\n"); - } + return renderer.render(template, view, partials); } }); }(); diff --git a/test/unit.js b/test/unit.js index fc030c2..a3ae7fb 100644 --- a/test/unit.js +++ b/test/unit.js @@ -550,7 +550,7 @@ test("Regression Suite", function() { { enumerate: [ { text: 'A' }, { text: 'B' } ] }, { partial: '{{=[[ ]]=}}\n{{text}}\n[[={{ }}=]]' } ), - '{{text}}\n{{text}}\n', + '{{text}}\n\n{{text}}\n\n', 'Issue 44' );