react / wstein / node_modules / jest-cli / node_modules / istanbul / node_modules / js-yaml / node_modules / argparse / node_modules / lodash / string / template.js
80742 viewsvar assignOwnDefaults = require('../internal/assignOwnDefaults'),1assignWith = require('../internal/assignWith'),2attempt = require('../utility/attempt'),3baseAssign = require('../internal/baseAssign'),4baseToString = require('../internal/baseToString'),5baseValues = require('../internal/baseValues'),6escapeStringChar = require('../internal/escapeStringChar'),7isError = require('../lang/isError'),8isIterateeCall = require('../internal/isIterateeCall'),9keys = require('../object/keys'),10reInterpolate = require('../internal/reInterpolate'),11templateSettings = require('./templateSettings');1213/** Used to match empty string literals in compiled template source. */14var reEmptyStringLeading = /\b__p \+= '';/g,15reEmptyStringMiddle = /\b(__p \+=) '' \+/g,16reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;1718/** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */19var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;2021/** Used to ensure capturing order of template delimiters. */22var reNoMatch = /($^)/;2324/** Used to match unescaped characters in compiled string literals. */25var reUnescapedString = /['\n\r\u2028\u2029\\]/g;2627/**28* Creates a compiled template function that can interpolate data properties29* in "interpolate" delimiters, HTML-escape interpolated data properties in30* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data31* properties may be accessed as free variables in the template. If a setting32* object is provided it takes precedence over `_.templateSettings` values.33*34* **Note:** In the development build `_.template` utilizes35* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)36* for easier debugging.37*38* For more information on precompiling templates see39* [lodash's custom builds documentation](https://lodash.com/custom-builds).40*41* For more information on Chrome extension sandboxes see42* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).43*44* @static45* @memberOf _46* @category String47* @param {string} [string=''] The template string.48* @param {Object} [options] The options object.49* @param {RegExp} [options.escape] The HTML "escape" delimiter.50* @param {RegExp} [options.evaluate] The "evaluate" delimiter.51* @param {Object} [options.imports] An object to import into the template as free variables.52* @param {RegExp} [options.interpolate] The "interpolate" delimiter.53* @param {string} [options.sourceURL] The sourceURL of the template's compiled source.54* @param {string} [options.variable] The data object variable name.55* @param- {Object} [otherOptions] Enables the legacy `options` param signature.56* @returns {Function} Returns the compiled template function.57* @example58*59* // using the "interpolate" delimiter to create a compiled template60* var compiled = _.template('hello <%= user %>!');61* compiled({ 'user': 'fred' });62* // => 'hello fred!'63*64* // using the HTML "escape" delimiter to escape data property values65* var compiled = _.template('<b><%- value %></b>');66* compiled({ 'value': '<script>' });67* // => '<b><script></b>'68*69* // using the "evaluate" delimiter to execute JavaScript and generate HTML70* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');71* compiled({ 'users': ['fred', 'barney'] });72* // => '<li>fred</li><li>barney</li>'73*74* // using the internal `print` function in "evaluate" delimiters75* var compiled = _.template('<% print("hello " + user); %>!');76* compiled({ 'user': 'barney' });77* // => 'hello barney!'78*79* // using the ES delimiter as an alternative to the default "interpolate" delimiter80* var compiled = _.template('hello ${ user }!');81* compiled({ 'user': 'pebbles' });82* // => 'hello pebbles!'83*84* // using custom template delimiters85* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;86* var compiled = _.template('hello {{ user }}!');87* compiled({ 'user': 'mustache' });88* // => 'hello mustache!'89*90* // using backslashes to treat delimiters as plain text91* var compiled = _.template('<%= "\\<%- value %\\>" %>');92* compiled({ 'value': 'ignored' });93* // => '<%- value %>'94*95* // using the `imports` option to import `jQuery` as `jq`96* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';97* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });98* compiled({ 'users': ['fred', 'barney'] });99* // => '<li>fred</li><li>barney</li>'100*101* // using the `sourceURL` option to specify a custom sourceURL for the template102* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });103* compiled(data);104* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector105*106* // using the `variable` option to ensure a with-statement isn't used in the compiled template107* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });108* compiled.source;109* // => function(data) {110* // var __t, __p = '';111* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';112* // return __p;113* // }114*115* // using the `source` property to inline compiled templates for meaningful116* // line numbers in error messages and a stack trace117* fs.writeFileSync(path.join(cwd, 'jst.js'), '\118* var JST = {\119* "main": ' + _.template(mainText).source + '\120* };\121* ');122*/123function template(string, options, otherOptions) {124// Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)125// and Laura Doktorova's doT.js (https://github.com/olado/doT).126var settings = templateSettings.imports._.templateSettings || templateSettings;127128if (otherOptions && isIterateeCall(string, options, otherOptions)) {129options = otherOptions = null;130}131string = baseToString(string);132options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);133134var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),135importsKeys = keys(imports),136importsValues = baseValues(imports, importsKeys);137138var isEscaping,139isEvaluating,140index = 0,141interpolate = options.interpolate || reNoMatch,142source = "__p += '";143144// Compile the regexp to match each delimiter.145var reDelimiters = RegExp(146(options.escape || reNoMatch).source + '|' +147interpolate.source + '|' +148(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +149(options.evaluate || reNoMatch).source + '|$'150, 'g');151152// Use a sourceURL for easier debugging.153var sourceURL = 'sourceURL' in options ? '//# sourceURL=' + options.sourceURL + '\n' : '';154155string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {156interpolateValue || (interpolateValue = esTemplateValue);157158// Escape characters that can't be included in string literals.159source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);160161// Replace delimiters with snippets.162if (escapeValue) {163isEscaping = true;164source += "' +\n__e(" + escapeValue + ") +\n'";165}166if (evaluateValue) {167isEvaluating = true;168source += "';\n" + evaluateValue + ";\n__p += '";169}170if (interpolateValue) {171source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";172}173index = offset + match.length;174175// The JS engine embedded in Adobe products requires returning the `match`176// string in order to produce the correct `offset` value.177return match;178});179180source += "';\n";181182// If `variable` is not specified wrap a with-statement around the generated183// code to add the data object to the top of the scope chain.184var variable = options.variable;185if (!variable) {186source = 'with (obj) {\n' + source + '\n}\n';187}188// Cleanup code by stripping empty strings.189source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)190.replace(reEmptyStringMiddle, '$1')191.replace(reEmptyStringTrailing, '$1;');192193// Frame code as the function body.194source = 'function(' + (variable || 'obj') + ') {\n' +195(variable196? ''197: 'obj || (obj = {});\n'198) +199"var __t, __p = ''" +200(isEscaping201? ', __e = _.escape'202: ''203) +204(isEvaluating205? ', __j = Array.prototype.join;\n' +206"function print() { __p += __j.call(arguments, '') }\n"207: ';\n'208) +209source +210'return __p\n}';211212var result = attempt(function() {213return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);214});215216// Provide the compiled function's source by its `toString` method or217// the `source` property as a convenience for inlining compiled templates.218result.source = source;219if (isError(result)) {220throw result;221}222return result;223}224225module.exports = template;226227228