/**1* lodash 3.6.1 (Custom Build) <https://lodash.com/>2* Build: `lodash modern modularize exports="npm" -o ./`3* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>4* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>5* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors6* Available under MIT license <https://lodash.com/license>7*/8var baseCopy = require('lodash._basecopy'),9baseToString = require('lodash._basetostring'),10baseValues = require('lodash._basevalues'),11isIterateeCall = require('lodash._isiterateecall'),12reInterpolate = require('lodash._reinterpolate'),13keys = require('lodash.keys'),14restParam = require('lodash.restparam'),15templateSettings = require('lodash.templatesettings');1617/** `Object#toString` result references. */18var errorTag = '[object Error]';1920/** Used to match empty string literals in compiled template source. */21var reEmptyStringLeading = /\b__p \+= '';/g,22reEmptyStringMiddle = /\b(__p \+=) '' \+/g,23reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;2425/** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */26var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;2728/** Used to ensure capturing order of template delimiters. */29var reNoMatch = /($^)/;3031/** Used to match unescaped characters in compiled string literals. */32var reUnescapedString = /['\n\r\u2028\u2029\\]/g;3334/** Used to escape characters for inclusion in compiled string literals. */35var stringEscapes = {36'\\': '\\',37"'": "'",38'\n': 'n',39'\r': 'r',40'\u2028': 'u2028',41'\u2029': 'u2029'42};4344/**45* Used by `_.template` to escape characters for inclusion in compiled46* string literals.47*48* @private49* @param {string} chr The matched character to escape.50* @returns {string} Returns the escaped character.51*/52function escapeStringChar(chr) {53return '\\' + stringEscapes[chr];54}5556/**57* Checks if `value` is object-like.58*59* @private60* @param {*} value The value to check.61* @returns {boolean} Returns `true` if `value` is object-like, else `false`.62*/63function isObjectLike(value) {64return !!value && typeof value == 'object';65}6667/** Used for native method references. */68var objectProto = Object.prototype;6970/** Used to check objects for own properties. */71var hasOwnProperty = objectProto.hasOwnProperty;7273/**74* Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)75* of values.76*/77var objToString = objectProto.toString;7879/**80* Used by `_.template` to customize its `_.assign` use.81*82* **Note:** This function is like `assignDefaults` except that it ignores83* inherited property values when checking if a property is `undefined`.84*85* @private86* @param {*} objectValue The destination object property value.87* @param {*} sourceValue The source object property value.88* @param {string} key The key associated with the object and source values.89* @param {Object} object The destination object.90* @returns {*} Returns the value to assign to the destination object.91*/92function assignOwnDefaults(objectValue, sourceValue, key, object) {93return (objectValue === undefined || !hasOwnProperty.call(object, key))94? sourceValue95: objectValue;96}9798/**99* A specialized version of `_.assign` for customizing assigned values without100* support for argument juggling, multiple sources, and `this` binding `customizer`101* functions.102*103* @private104* @param {Object} object The destination object.105* @param {Object} source The source object.106* @param {Function} customizer The function to customize assigned values.107* @returns {Object} Returns `object`.108*/109function assignWith(object, source, customizer) {110var index = -1,111props = keys(source),112length = props.length;113114while (++index < length) {115var key = props[index],116value = object[key],117result = customizer(value, source[key], key, object, source);118119if ((result === result ? (result !== value) : (value === value)) ||120(value === undefined && !(key in object))) {121object[key] = result;122}123}124return object;125}126127/**128* The base implementation of `_.assign` without support for argument juggling,129* multiple sources, and `customizer` functions.130*131* @private132* @param {Object} object The destination object.133* @param {Object} source The source object.134* @returns {Object} Returns `object`.135*/136function baseAssign(object, source) {137return source == null138? object139: baseCopy(source, keys(source), object);140}141142/**143* Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,144* `SyntaxError`, `TypeError`, or `URIError` object.145*146* @static147* @memberOf _148* @category Lang149* @param {*} value The value to check.150* @returns {boolean} Returns `true` if `value` is an error object, else `false`.151* @example152*153* _.isError(new Error);154* // => true155*156* _.isError(Error);157* // => false158*/159function isError(value) {160return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;161}162163/**164* Creates a compiled template function that can interpolate data properties165* in "interpolate" delimiters, HTML-escape interpolated data properties in166* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data167* properties may be accessed as free variables in the template. If a setting168* object is provided it takes precedence over `_.templateSettings` values.169*170* **Note:** In the development build `_.template` utilizes171* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)172* for easier debugging.173*174* For more information on precompiling templates see175* [lodash's custom builds documentation](https://lodash.com/custom-builds).176*177* For more information on Chrome extension sandboxes see178* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).179*180* @static181* @memberOf _182* @category String183* @param {string} [string=''] The template string.184* @param {Object} [options] The options object.185* @param {RegExp} [options.escape] The HTML "escape" delimiter.186* @param {RegExp} [options.evaluate] The "evaluate" delimiter.187* @param {Object} [options.imports] An object to import into the template as free variables.188* @param {RegExp} [options.interpolate] The "interpolate" delimiter.189* @param {string} [options.sourceURL] The sourceURL of the template's compiled source.190* @param {string} [options.variable] The data object variable name.191* @param- {Object} [otherOptions] Enables the legacy `options` param signature.192* @returns {Function} Returns the compiled template function.193* @example194*195* // using the "interpolate" delimiter to create a compiled template196* var compiled = _.template('hello <%= user %>!');197* compiled({ 'user': 'fred' });198* // => 'hello fred!'199*200* // using the HTML "escape" delimiter to escape data property values201* var compiled = _.template('<b><%- value %></b>');202* compiled({ 'value': '<script>' });203* // => '<b><script></b>'204*205* // using the "evaluate" delimiter to execute JavaScript and generate HTML206* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');207* compiled({ 'users': ['fred', 'barney'] });208* // => '<li>fred</li><li>barney</li>'209*210* // using the internal `print` function in "evaluate" delimiters211* var compiled = _.template('<% print("hello " + user); %>!');212* compiled({ 'user': 'barney' });213* // => 'hello barney!'214*215* // using the ES delimiter as an alternative to the default "interpolate" delimiter216* var compiled = _.template('hello ${ user }!');217* compiled({ 'user': 'pebbles' });218* // => 'hello pebbles!'219*220* // using custom template delimiters221* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;222* var compiled = _.template('hello {{ user }}!');223* compiled({ 'user': 'mustache' });224* // => 'hello mustache!'225*226* // using backslashes to treat delimiters as plain text227* var compiled = _.template('<%= "\\<%- value %\\>" %>');228* compiled({ 'value': 'ignored' });229* // => '<%- value %>'230*231* // using the `imports` option to import `jQuery` as `jq`232* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';233* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });234* compiled({ 'users': ['fred', 'barney'] });235* // => '<li>fred</li><li>barney</li>'236*237* // using the `sourceURL` option to specify a custom sourceURL for the template238* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });239* compiled(data);240* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector241*242* // using the `variable` option to ensure a with-statement isn't used in the compiled template243* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });244* compiled.source;245* // => function(data) {246* // var __t, __p = '';247* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';248* // return __p;249* // }250*251* // using the `source` property to inline compiled templates for meaningful252* // line numbers in error messages and a stack trace253* fs.writeFileSync(path.join(cwd, 'jst.js'), '\254* var JST = {\255* "main": ' + _.template(mainText).source + '\256* };\257* ');258*/259function template(string, options, otherOptions) {260// Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)261// and Laura Doktorova's doT.js (https://github.com/olado/doT).262var settings = templateSettings.imports._.templateSettings || templateSettings;263264if (otherOptions && isIterateeCall(string, options, otherOptions)) {265options = otherOptions = null;266}267string = baseToString(string);268options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);269270var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),271importsKeys = keys(imports),272importsValues = baseValues(imports, importsKeys);273274var isEscaping,275isEvaluating,276index = 0,277interpolate = options.interpolate || reNoMatch,278source = "__p += '";279280// Compile the regexp to match each delimiter.281var reDelimiters = RegExp(282(options.escape || reNoMatch).source + '|' +283interpolate.source + '|' +284(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +285(options.evaluate || reNoMatch).source + '|$'286, 'g');287288// Use a sourceURL for easier debugging.289var sourceURL = 'sourceURL' in options ? '//# sourceURL=' + options.sourceURL + '\n' : '';290291string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {292interpolateValue || (interpolateValue = esTemplateValue);293294// Escape characters that can't be included in string literals.295source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);296297// Replace delimiters with snippets.298if (escapeValue) {299isEscaping = true;300source += "' +\n__e(" + escapeValue + ") +\n'";301}302if (evaluateValue) {303isEvaluating = true;304source += "';\n" + evaluateValue + ";\n__p += '";305}306if (interpolateValue) {307source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";308}309index = offset + match.length;310311// The JS engine embedded in Adobe products requires returning the `match`312// string in order to produce the correct `offset` value.313return match;314});315316source += "';\n";317318// If `variable` is not specified wrap a with-statement around the generated319// code to add the data object to the top of the scope chain.320var variable = options.variable;321if (!variable) {322source = 'with (obj) {\n' + source + '\n}\n';323}324// Cleanup code by stripping empty strings.325source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)326.replace(reEmptyStringMiddle, '$1')327.replace(reEmptyStringTrailing, '$1;');328329// Frame code as the function body.330source = 'function(' + (variable || 'obj') + ') {\n' +331(variable332? ''333: 'obj || (obj = {});\n'334) +335"var __t, __p = ''" +336(isEscaping337? ', __e = _.escape'338: ''339) +340(isEvaluating341? ', __j = Array.prototype.join;\n' +342"function print() { __p += __j.call(arguments, '') }\n"343: ';\n'344) +345source +346'return __p\n}';347348var result = attempt(function() {349return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);350});351352// Provide the compiled function's source by its `toString` method or353// the `source` property as a convenience for inlining compiled templates.354result.source = source;355if (isError(result)) {356throw result;357}358return result;359}360361/**362* Attempts to invoke `func`, returning either the result or the caught error363* object. Any additional arguments are provided to `func` when it is invoked.364*365* @static366* @memberOf _367* @category Utility368* @param {Function} func The function to attempt.369* @returns {*} Returns the `func` result or error object.370* @example371*372* // avoid throwing errors for invalid selectors373* var elements = _.attempt(function(selector) {374* return document.querySelectorAll(selector);375* }, '>_>');376*377* if (_.isError(elements)) {378* elements = [];379* }380*/381var attempt = restParam(function(func, args) {382try {383return func.apply(undefined, args);384} catch(e) {385return isError(e) ? e : new Error(e);386}387});388389module.exports = template;390391392