| /** |
| * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> |
| * Build: `lodash modularize underscore exports="node" -o ./underscore/` |
| * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> |
| * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> |
| * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors |
| * Available under MIT license <http://lodash.com/license> |
| */ |
| var defaults = require('../objects/defaults'), |
| escape = require('./escape'), |
| escapeStringChar = require('../internals/escapeStringChar'), |
| reInterpolate = require('../internals/reInterpolate'), |
| templateSettings = require('./templateSettings'); |
| |
| /** Used to ensure capturing order of template delimiters */ |
| var reNoMatch = /($^)/; |
| |
| /** Used to match unescaped characters in compiled string literals */ |
| var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; |
| |
| /** |
| * A micro-templating method that handles arbitrary delimiters, preserves |
| * whitespace, and correctly escapes quotes within interpolated code. |
| * |
| * Note: In the development build, `_.template` utilizes sourceURLs for easier |
| * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl |
| * |
| * For more information on precompiling templates see: |
| * http://lodash.com/custom-builds |
| * |
| * For more information on Chrome extension sandboxes see: |
| * http://developer.chrome.com/stable/extensions/sandboxingEval.html |
| * |
| * @static |
| * @memberOf _ |
| * @category Utilities |
| * @param {string} text The template text. |
| * @param {Object} data The data object used to populate the text. |
| * @param {Object} [options] The options object. |
| * @param {RegExp} [options.escape] The "escape" delimiter. |
| * @param {RegExp} [options.evaluate] The "evaluate" delimiter. |
| * @param {Object} [options.imports] An object to import into the template as local variables. |
| * @param {RegExp} [options.interpolate] The "interpolate" delimiter. |
| * @param {string} [sourceURL] The sourceURL of the template's compiled source. |
| * @param {string} [variable] The data object variable name. |
| * @returns {Function|string} Returns a compiled function when no `data` object |
| * is given, else it returns the interpolated text. |
| * @example |
| * |
| * // using the "interpolate" delimiter to create a compiled template |
| * var compiled = _.template('hello <%= name %>'); |
| * compiled({ 'name': 'fred' }); |
| * // => 'hello fred' |
| * |
| * // using the "escape" delimiter to escape HTML in data property values |
| * _.template('<b><%- value %></b>', { 'value': '<script>' }); |
| * // => '<b><script></b>' |
| * |
| * // using the "evaluate" delimiter to generate HTML |
| * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>'; |
| * _.template(list, { 'people': ['fred', 'barney'] }); |
| * // => '<li>fred</li><li>barney</li>' |
| * |
| * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter |
| * _.template('hello ${ name }', { 'name': 'pebbles' }); |
| * // => 'hello pebbles' |
| * |
| * // using the internal `print` function in "evaluate" delimiters |
| * _.template('<% print("hello " + name); %>!', { 'name': 'barney' }); |
| * // => 'hello barney!' |
| * |
| * // using a custom template delimiters |
| * _.templateSettings = { |
| * 'interpolate': /{{([\s\S]+?)}}/g |
| * }; |
| * |
| * _.template('hello {{ name }}!', { 'name': 'mustache' }); |
| * // => 'hello mustache!' |
| * |
| * // using the `imports` option to import jQuery |
| * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>'; |
| * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } }); |
| * // => '<li>fred</li><li>barney</li>' |
| * |
| * // using the `sourceURL` option to specify a custom sourceURL for the template |
| * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' }); |
| * compiled(data); |
| * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector |
| * |
| * // using the `variable` option to ensure a with-statement isn't used in the compiled template |
| * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' }); |
| * compiled.source; |
| * // => function(data) { |
| * var __t, __p = '', __e = _.escape; |
| * __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!'; |
| * return __p; |
| * } |
| * |
| * // using the `source` property to inline compiled templates for meaningful |
| * // line numbers in error messages and a stack trace |
| * fs.writeFileSync(path.join(cwd, 'jst.js'), '\ |
| * var JST = {\ |
| * "main": ' + _.template(mainText).source + '\ |
| * };\ |
| * '); |
| */ |
| function template(text, data, options) { |
| var _ = templateSettings.imports._, |
| settings = _.templateSettings || templateSettings; |
| |
| text = String(text || ''); |
| options = defaults({}, options, settings); |
| |
| var index = 0, |
| source = "__p += '", |
| variable = options.variable; |
| |
| var reDelimiters = RegExp( |
| (options.escape || reNoMatch).source + '|' + |
| (options.interpolate || reNoMatch).source + '|' + |
| (options.evaluate || reNoMatch).source + '|$' |
| , 'g'); |
| |
| text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) { |
| source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar); |
| if (escapeValue) { |
| source += "' +\n_.escape(" + escapeValue + ") +\n'"; |
| } |
| if (evaluateValue) { |
| source += "';\n" + evaluateValue + ";\n__p += '"; |
| } |
| if (interpolateValue) { |
| source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; |
| } |
| index = offset + match.length; |
| return match; |
| }); |
| |
| source += "';\n"; |
| if (!variable) { |
| variable = 'obj'; |
| source = 'with (' + variable + ' || {}) {\n' + source + '\n}\n'; |
| } |
| source = 'function(' + variable + ') {\n' + |
| "var __t, __p = '', __j = Array.prototype.join;\n" + |
| "function print() { __p += __j.call(arguments, '') }\n" + |
| source + |
| 'return __p\n}'; |
| |
| try { |
| var result = Function('_', 'return ' + source)(_); |
| } catch(e) { |
| e.source = source; |
| throw e; |
| } |
| if (data) { |
| return result(data); |
| } |
| result.source = source; |
| return result; |
| } |
| |
| module.exports = template; |