From f5eb4b09157384c69f28e5cda38c620af8200c41 Mon Sep 17 00:00:00 2001 From: Brad Dunbar Date: Wed, 14 Mar 2012 08:25:01 -0400 Subject: [PATCH] Clean up _.template. * Cache regexes. * Use object properties for lookup instead of switch. --- underscore.js | 59 ++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/underscore.js b/underscore.js index b956e21ce..4470eab44 100644 --- a/underscore.js +++ b/underscore.js @@ -902,19 +902,27 @@ // guaranteed not to match. var noMatch = /.^/; + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + '\\': '\\', + "'": "'", + 'r': '\r', + 'n': '\n', + 't': '\t', + 'u2028': '\u2028', + 'u2029': '\u2029' + }; + + for (var p in escapes) escapes[escapes[p]] = p; + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g; + // Within an interpolation, evaluation, or escaping, remove HTML escaping // that had been previously added. var unescape = function(code) { - return code.replace(/\\(\\|'|r|n|t|u2028|u2029)/g, function(match, char) { - switch (char) { - case '\\': return '\\'; - case "'": return "'"; - case 'r': return '\r'; - case 'n': return '\n'; - case 't': return '\t'; - case 'u2028': return '\u2028'; - case 'u2029': return '\u2029'; - } + return code.replace(unescaper, function(match, escape) { + return escapes[escape]; }); }; @@ -925,23 +933,20 @@ var c = _.templateSettings; var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + 'with(obj||{}){__p.push(\'' + - str.replace(/\\/g, '\\\\') - .replace(/'/g, "\\'") - .replace(/\r/g, '\\r') - .replace(/\n/g, '\\n') - .replace(/\t/g, '\\t') - .replace(/\u2028/g, '\\u2028') - .replace(/\u2029/g, '\\u2029') - .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('');"; + str + .replace(escaper, function(match) { + return '\\' + escapes[match]; + }) + .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, _); return function(data) {