From 414fafb1f4e5daf4d22bfaa1f4e50ee190cf24c4 Mon Sep 17 00:00:00 2001 From: Brad Dunbar Date: Sun, 11 Mar 2012 12:39:13 -0400 Subject: [PATCH] Allow natural multi-line code evaluation in templates. By escaping `\r`, `\n`, and `\t` earlier, we can unescape them along with backslashes and single quotes allowing for the inclusion of single line comments and code without a terminating semicolon. --- test/test.html | 2 ++ test/utility.js | 10 +++++++++- underscore.js | 28 ++++++++++++++++++---------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/test/test.html b/test/test.html index f8609aa26..86e7300a6 100644 --- a/test/test.html +++ b/test/test.html @@ -18,6 +18,7 @@

Underscore Test Suite

+

    @@ -34,6 +35,7 @@ diff --git a/test/utility.js b/test/utility.js index 6207d3be3..4a59faf1f 100644 --- a/test/utility.js +++ b/test/utility.js @@ -1,6 +1,14 @@ $(document).ready(function() { - module("Utility"); + var templateSettings = _.templateSettings; + + module("Utility", { + + teardown: function() { + _.templateSettings = templateSettings; + } + + }); test("utility: noConflict", function() { var underscore = _.noConflict(); diff --git a/underscore.js b/underscore.js index 88da6e1d8..c0b4a84e2 100644 --- a/underscore.js +++ b/underscore.js @@ -905,7 +905,15 @@ // Within an interpolation, evaluation, or escaping, remove HTML escaping // that had been previously added. var unescape = function(code) { - return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'"); + return code.replace(/\\(\\|'|r|n|t)/g, function(match, char) { + switch (char) { + case '\\': return '\\'; + case "'": return "'"; + case 'r': return '\r'; + case 'n': return '\n'; + case 't': return '\t'; + } + }); }; // JavaScript micro-templating, similar to John Resig's implementation. @@ -917,18 +925,18 @@ 'with(obj||{}){__p.push(\'' + str.replace(/\\/g, '\\\\') .replace(/'/g, "\\'") - .replace(c.escape || noMatch, function(match, code) { - return "',_.escape(" + unescape(code) + "),'"; - }) - .replace(c.interpolate || noMatch, function(match, code) { - return "'," + unescape(code) + ",'"; - }) - .replace(c.evaluate || noMatch, function(match, code) { - return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('"; - }) .replace(/\r/g, '\\r') .replace(/\n/g, '\\n') .replace(/\t/g, '\\t') + .replace(c.escape || noMatch, function(match, code) { + return "',_.escape(" + unescape(code) + "),\n'"; + }) + .replace(c.interpolate || noMatch, function(match, code) { + return "'," + unescape(code) + ",\n'"; + }) + .replace(c.evaluate || noMatch, function(match, code) { + return "');" + unescape(code) + ";\n__p.push('"; + }) + "');}return __p.join('');"; var func = new Function('obj', '_', tmpl); if (data) return func(data, _);