Skip to content

Instantly share code, notes, and snippets.

@boxxxie
Created April 25, 2012 21:08
Show Gist options
  • Save boxxxie/2493404 to your computer and use it in GitHub Desktop.
Save boxxxie/2493404 to your computer and use it in GitHub Desktop.
extracted template engine from underscore
var _ = {};
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate: /<%([\s\S]+?)%>/g,
interpolate: /<%=([\s\S]+?)%>/g,
escape: /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// 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(unescaper, function(match, escape) {
return escapes[escape];
});
};
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) {
settings = settings || _.templateSettings;
// Compile the template source, taking care to escape characters that
// cannot be included in a string literal and then unescape them in code
// blocks.
var source = "__p+='" + text.replace(escaper, function(match) {
return '\\' + escapes[match];
}).replace(settings.escape || noMatch, function(match, code) {
return "'+\n_.escape(" + unescape(code) + ")+\n'";
}).replace(settings.interpolate || noMatch, function(match, code) {
return "'+\n(" + unescape(code) + ")+\n'";
}).replace(settings.evaluate || noMatch, function(match, code) {
return "';\n" + unescape(code) + "\n;__p+='";
}) + "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __p='';" + "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" + source + "return __p;\n";
var render = new Function(settings.variable || 'obj', '_', source);
if (data) return render(data, _);
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled function source as a convenience for build time
// precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
return template;
};
document.write(_.template("<%=name%>", {
name: "bob"
}));
console.log(_.template("<%=name%>", {
name: "bob"
}))​
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment