UNPKG

todomvc

Version:

> Helping you select an MV\* framework

123 lines (104 loc) 3.81 kB
// Simple JavaScript Templating // Paul Miller (http://paulmillr.com) // http://underscorejs.org // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors (function(globals) { // By default, Underscore uses ERB-style template delimiters, change the // following template settings to use alternative delimiters. var settings = { 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' }; var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; // List of HTML entities for escaping. var htmlEntities = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#x27;' }; var entityRe = new RegExp('[&<>"\']', 'g'); var escapeExpr = function(string) { if (string == null) return ''; return ('' + string).replace(entityRe, function(match) { return htmlEntities[match]; }); }; var counter = 0; // JavaScript micro-templating, similar to John Resig's implementation. // Underscore templating handles arbitrary delimiters, preserves whitespace, // and correctly escapes quotes within interpolated code. var tmpl = function(text, data) { var render; // Combine delimiters into one regular expression via alternation. var matcher = new RegExp([ (settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source ].join('|') + '|$', 'g'); // Compile the template source, escaping string literals appropriately. var index = 0; var source = "__p+='"; text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { source += text.slice(index, offset) .replace(escaper, function(match) { return '\\' + escapes[match]; }); if (escape) { source += "'+\n((__t=(" + escape + "))==null?'':escapeExpr(__t))+\n'"; } if (interpolate) { source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; } if (evaluate) { source += "';\n" + evaluate + "\n__p+='"; } index = offset + match.length; return match; }); source += "';\n"; // If a variable is not specified, place data values in local scope. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n//# sourceURL=/microtemplates/source[" + counter++ + "]"; try { render = new Function(settings.variable || 'obj', 'escapeExpr', source); } catch (e) { e.source = source; throw e; } if (data) return render(data, escapeExpr); var template = function(data) { return render.call(this, data, escapeExpr); }; // Provide the compiled function source as a convenience for precompilation. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; return template; }; tmpl.settings = settings; if (typeof define !== 'undefined' && define.amd) { define([], function () { return tmpl; }); // RequireJS } else if (typeof module !== 'undefined' && module.exports) { module.exports = tmpl; // CommonJS } else { globals.microtemplate = tmpl; // <script> } })(this);