Merge pull request #521 from braddunbar/template-source

Attach template source to returned function.
This commit is contained in:
Jeremy Ashkenas
2012-03-26 10:48:26 -07:00
2 changed files with 28 additions and 14 deletions

View File

@@ -1327,7 +1327,7 @@ _.result(object, 'stuff');
<br /> <br />
Compiles JavaScript templates into functions that can be evaluated Compiles JavaScript templates into functions that can be evaluated
for rendering. Useful for rendering complicated bits of HTML from JSON for rendering. Useful for rendering complicated bits of HTML from JSON
data sources. Template functions can both interpolate variables, using<br /> data sources. Template functions can both interpolate variables, using
<tt>&lt;%= &hellip; %&gt;</tt>, as well as execute arbitrary JavaScript code, with <tt>&lt;%= &hellip; %&gt;</tt>, as well as execute arbitrary JavaScript code, with
<tt>&lt;% &hellip; %&gt;</tt>. If you wish to interpolate a value, and have <tt>&lt;% &hellip; %&gt;</tt>. If you wish to interpolate a value, and have
it be HTML-escaped, use <tt>&lt;%- &hellip; %&gt;</tt> When you evaluate a template function, pass in a it be HTML-escaped, use <tt>&lt;%- &hellip; %&gt;</tt> When you evaluate a template function, pass in a
@@ -1381,6 +1381,18 @@ var template = _.template("Hello {{ name }}!");
template({name : "Mustache"}); template({name : "Mustache"});
=&gt; "Hello Mustache!"</pre> =&gt; "Hello Mustache!"</pre>
<p>
Precompiling your templates can be a big help when debugging errors you can't
reproduce. This is because precompiled templates can provide line numbers and
a stack trace, something that is not possible when compiling templates on the client.
<b>template</b> provides the <b>source</b> property on the compiled template
function for easy precompilation.
</p>
<pre>&lt;script&gt;
JST.project = <%= _.template(jstText).source %>;
&lt;/script&gt;</pre>
<h2 id="chaining">Chaining</h2> <h2 id="chaining">Chaining</h2>

View File

@@ -938,28 +938,30 @@
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(str, data) { _.template = function(str, data) {
var c = _.templateSettings; var settings = _.templateSettings;
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + var source = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
'with(obj||{}){__p.push(\'' + 'with(obj||{}){__p.push(\'' +
str str
.replace(escaper, function(match) { .replace(escaper, function(match) {
return '\\' + escapes[match]; return '\\' + escapes[match];
}) })
.replace(c.escape || noMatch, function(match, code) { .replace(settings.escape || noMatch, function(match, code) {
return "',_.escape(" + unescape(code) + "),\n'"; return "',\n_.escape(" + unescape(code) + "),\n'";
}) })
.replace(c.interpolate || noMatch, function(match, code) { .replace(settings.interpolate || noMatch, function(match, code) {
return "'," + unescape(code) + ",\n'"; return "',\n" + unescape(code) + ",\n'";
}) })
.replace(c.evaluate || noMatch, function(match, code) { .replace(settings.evaluate || noMatch, function(match, code) {
return "');" + unescape(code) + ";\n__p.push('"; return "');\n" + unescape(code) + "\n;__p.push('";
}) })
+ "');}return __p.join('');"; + "');\n}\nreturn __p.join('');";
var func = new Function('obj', '_', tmpl); var render = new Function('obj', '_', source);
if (data) return func(data, _); if (data) return render(data, _);
return function(data) { var template = function(data) {
return func.call(this, data, _); return render.call(this, data, _);
}; };
template.source = 'function(obj){\n' + source + '\n}';
return template;
}; };
// Add a "chain" function, which will delegate to the wrapper. // Add a "chain" function, which will delegate to the wrapper.