123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- /**
- * lodash 4.2.4 (Custom Build) <https://lodash.com/>
- * Build: `lodash modularize exports="npm" -o ./`
- * Copyright jQuery Foundation and other contributors <https://jquery.org/>
- * Released under MIT license <https://lodash.com/license>
- * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
- * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- */
- var assignInWith = require('lodash.assigninwith'),
- keys = require('lodash.keys'),
- reInterpolate = require('lodash._reinterpolate'),
- rest = require('lodash.rest'),
- templateSettings = require('lodash.templatesettings'),
- toString = require('lodash.tostring');
- /** Used as references for various `Number` constants. */
- var MAX_SAFE_INTEGER = 9007199254740991;
- /** `Object#toString` result references. */
- var errorTag = '[object Error]',
- funcTag = '[object Function]',
- genTag = '[object GeneratorFunction]';
- /** Used to match empty string literals in compiled template source. */
- var reEmptyStringLeading = /\b__p \+= '';/g,
- reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
- reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
- /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */
- var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
- /** Used to detect unsigned integer values. */
- var reIsUint = /^(?:0|[1-9]\d*)$/;
- /** Used to ensure capturing order of template delimiters. */
- var reNoMatch = /($^)/;
- /** Used to match unescaped characters in compiled string literals. */
- var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
- /** Used to escape characters for inclusion in compiled string literals. */
- var stringEscapes = {
- '\\': '\\',
- "'": "'",
- '\n': 'n',
- '\r': 'r',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
- /**
- * A faster alternative to `Function#apply`, this function invokes `func`
- * with the `this` binding of `thisArg` and the arguments of `args`.
- *
- * @private
- * @param {Function} func The function to invoke.
- * @param {*} thisArg The `this` binding of `func`.
- * @param {...*} args The arguments to invoke `func` with.
- * @returns {*} Returns the result of `func`.
- */
- function apply(func, thisArg, args) {
- var length = args.length;
- switch (length) {
- case 0: return func.call(thisArg);
- case 1: return func.call(thisArg, args[0]);
- case 2: return func.call(thisArg, args[0], args[1]);
- case 3: return func.call(thisArg, args[0], args[1], args[2]);
- }
- return func.apply(thisArg, args);
- }
- /**
- * A specialized version of `_.map` for arrays without support for iteratee
- * shorthands.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
- */
- function arrayMap(array, iteratee) {
- var index = -1,
- length = array.length,
- result = Array(length);
- while (++index < length) {
- result[index] = iteratee(array[index], index, array);
- }
- return result;
- }
- /**
- * The base implementation of `_.values` and `_.valuesIn` which creates an
- * array of `object` property values corresponding to the property names
- * of `props`.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {Array} props The property names to get values for.
- * @returns {Object} Returns the array of property values.
- */
- function baseValues(object, props) {
- return arrayMap(props, function(key) {
- return object[key];
- });
- }
- /**
- * Used by `_.template` to escape characters for inclusion in compiled string literals.
- *
- * @private
- * @param {string} chr The matched character to escape.
- * @returns {string} Returns the escaped character.
- */
- function escapeStringChar(chr) {
- return '\\' + stringEscapes[chr];
- }
- /**
- * Checks if `value` is a valid array-like index.
- *
- * @private
- * @param {*} value The value to check.
- * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
- * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
- */
- function isIndex(value, length) {
- value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
- length = length == null ? MAX_SAFE_INTEGER : length;
- return value > -1 && value % 1 == 0 && value < length;
- }
- /** Used for built-in method references. */
- var objectProto = Object.prototype;
- /** Used to check objects for own properties. */
- var hasOwnProperty = objectProto.hasOwnProperty;
- /**
- * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
- * of values.
- */
- var objectToString = objectProto.toString;
- /**
- * Used by `_.defaults` to customize its `_.assignIn` use.
- *
- * @private
- * @param {*} objValue The destination value.
- * @param {*} srcValue The source value.
- * @param {string} key The key of the property to assign.
- * @param {Object} object The parent object of `objValue`.
- * @returns {*} Returns the value to assign.
- */
- function assignInDefaults(objValue, srcValue, key, object) {
- if (objValue === undefined ||
- (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
- return srcValue;
- }
- return objValue;
- }
- /**
- * The base implementation of `_.property` without support for deep paths.
- *
- * @private
- * @param {string} key The key of the property to get.
- * @returns {Function} Returns the new function.
- */
- function baseProperty(key) {
- return function(object) {
- return object == null ? undefined : object[key];
- };
- }
- /**
- * Gets the "length" property value of `object`.
- *
- * **Note:** This function is used to avoid a
- * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects
- * Safari on at least iOS 8.1-8.3 ARM64.
- *
- * @private
- * @param {Object} object The object to query.
- * @returns {*} Returns the "length" value.
- */
- var getLength = baseProperty('length');
- /**
- * Checks if the given arguments are from an iteratee call.
- *
- * @private
- * @param {*} value The potential iteratee value argument.
- * @param {*} index The potential iteratee index or key argument.
- * @param {*} object The potential iteratee object argument.
- * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
- * else `false`.
- */
- function isIterateeCall(value, index, object) {
- if (!isObject(object)) {
- return false;
- }
- var type = typeof index;
- if (type == 'number'
- ? (isArrayLike(object) && isIndex(index, object.length))
- : (type == 'string' && index in object)
- ) {
- return eq(object[index], value);
- }
- return false;
- }
- /**
- * Performs a
- * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
- * comparison between two values to determine if they are equivalent.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'user': 'fred' };
- * var other = { 'user': 'fred' };
- *
- * _.eq(object, object);
- * // => true
- *
- * _.eq(object, other);
- * // => false
- *
- * _.eq('a', 'a');
- * // => true
- *
- * _.eq('a', Object('a'));
- * // => false
- *
- * _.eq(NaN, NaN);
- * // => true
- */
- function eq(value, other) {
- return value === other || (value !== value && other !== other);
- }
- /**
- * Checks if `value` is array-like. A value is considered array-like if it's
- * not a function and has a `value.length` that's an integer greater than or
- * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
- * @example
- *
- * _.isArrayLike([1, 2, 3]);
- * // => true
- *
- * _.isArrayLike(document.body.children);
- * // => true
- *
- * _.isArrayLike('abc');
- * // => true
- *
- * _.isArrayLike(_.noop);
- * // => false
- */
- function isArrayLike(value) {
- return value != null && isLength(getLength(value)) && !isFunction(value);
- }
- /**
- * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
- * `SyntaxError`, `TypeError`, or `URIError` object.
- *
- * @static
- * @memberOf _
- * @since 3.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an error object,
- * else `false`.
- * @example
- *
- * _.isError(new Error);
- * // => true
- *
- * _.isError(Error);
- * // => false
- */
- function isError(value) {
- if (!isObjectLike(value)) {
- return false;
- }
- return (objectToString.call(value) == errorTag) ||
- (typeof value.message == 'string' && typeof value.name == 'string');
- }
- /**
- * Checks if `value` is classified as a `Function` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is correctly classified,
- * else `false`.
- * @example
- *
- * _.isFunction(_);
- * // => true
- *
- * _.isFunction(/abc/);
- * // => false
- */
- function isFunction(value) {
- // The use of `Object#toString` avoids issues with the `typeof` operator
- // in Safari 8 which returns 'object' for typed array and weak map constructors,
- // and PhantomJS 1.9 which returns 'function' for `NodeList` instances.
- var tag = isObject(value) ? objectToString.call(value) : '';
- return tag == funcTag || tag == genTag;
- }
- /**
- * Checks if `value` is a valid array-like length.
- *
- * **Note:** This function is loosely based on
- * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a valid length,
- * else `false`.
- * @example
- *
- * _.isLength(3);
- * // => true
- *
- * _.isLength(Number.MIN_VALUE);
- * // => false
- *
- * _.isLength(Infinity);
- * // => false
- *
- * _.isLength('3');
- * // => false
- */
- function isLength(value) {
- return typeof value == 'number' &&
- value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
- }
- /**
- * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
- * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an object, else `false`.
- * @example
- *
- * _.isObject({});
- * // => true
- *
- * _.isObject([1, 2, 3]);
- * // => true
- *
- * _.isObject(_.noop);
- * // => true
- *
- * _.isObject(null);
- * // => false
- */
- function isObject(value) {
- var type = typeof value;
- return !!value && (type == 'object' || type == 'function');
- }
- /**
- * Checks if `value` is object-like. A value is object-like if it's not `null`
- * and has a `typeof` result of "object".
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
- * @example
- *
- * _.isObjectLike({});
- * // => true
- *
- * _.isObjectLike([1, 2, 3]);
- * // => true
- *
- * _.isObjectLike(_.noop);
- * // => false
- *
- * _.isObjectLike(null);
- * // => false
- */
- function isObjectLike(value) {
- return !!value && typeof value == 'object';
- }
- /**
- * Creates a compiled template function that can interpolate data properties
- * in "interpolate" delimiters, HTML-escape interpolated data properties in
- * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
- * properties may be accessed as free variables in the template. If a setting
- * object is given it takes precedence over `_.templateSettings` values.
- *
- * **Note:** In the development build `_.template` utilizes
- * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
- * for easier debugging.
- *
- * For more information on precompiling templates see
- * [lodash's custom builds documentation](https://lodash.com/custom-builds).
- *
- * For more information on Chrome extension sandboxes see
- * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
- *
- * @static
- * @since 0.1.0
- * @memberOf _
- * @category String
- * @param {string} [string=''] The template string.
- * @param {Object} [options={}] The options object.
- * @param {RegExp} [options.escape=_.templateSettings.escape]
- * The HTML "escape" delimiter.
- * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
- * The "evaluate" delimiter.
- * @param {Object} [options.imports=_.templateSettings.imports]
- * An object to import into the template as free variables.
- * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
- * The "interpolate" delimiter.
- * @param {string} [options.sourceURL='templateSources[n]']
- * The sourceURL of the compiled template.
- * @param {string} [options.variable='obj']
- * The data object variable name.
- * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
- * @returns {Function} Returns the compiled template function.
- * @example
- *
- * // Use the "interpolate" delimiter to create a compiled template.
- * var compiled = _.template('hello <%= user %>!');
- * compiled({ 'user': 'fred' });
- * // => 'hello fred!'
- *
- * // Use the HTML "escape" delimiter to escape data property values.
- * var compiled = _.template('<b><%- value %></b>');
- * compiled({ 'value': '<script>' });
- * // => '<b><script></b>'
- *
- * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
- * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
- * compiled({ 'users': ['fred', 'barney'] });
- * // => '<li>fred</li><li>barney</li>'
- *
- * // Use the internal `print` function in "evaluate" delimiters.
- * var compiled = _.template('<% print("hello " + user); %>!');
- * compiled({ 'user': 'barney' });
- * // => 'hello barney!'
- *
- * // Use the ES delimiter as an alternative to the default "interpolate" delimiter.
- * var compiled = _.template('hello ${ user }!');
- * compiled({ 'user': 'pebbles' });
- * // => 'hello pebbles!'
- *
- * // Use custom template delimiters.
- * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
- * var compiled = _.template('hello {{ user }}!');
- * compiled({ 'user': 'mustache' });
- * // => 'hello mustache!'
- *
- * // Use backslashes to treat delimiters as plain text.
- * var compiled = _.template('<%= "\\<%- value %\\>" %>');
- * compiled({ 'value': 'ignored' });
- * // => '<%- value %>'
- *
- * // Use the `imports` option to import `jQuery` as `jq`.
- * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
- * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
- * compiled({ 'users': ['fred', 'barney'] });
- * // => '<li>fred</li><li>barney</li>'
- *
- * // Use the `sourceURL` option to specify a custom sourceURL for the template.
- * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
- * compiled(data);
- * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
- *
- * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
- * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
- * compiled.source;
- * // => function(data) {
- * // var __t, __p = '';
- * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
- * // return __p;
- * // }
- *
- * // Use the `source` property to inline compiled templates for meaningful
- * // line numbers in error messages and stack traces.
- * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
- * var JST = {\
- * "main": ' + _.template(mainText).source + '\
- * };\
- * ');
- */
- function template(string, options, guard) {
- // Based on John Resig's `tmpl` implementation
- // (http://ejohn.org/blog/javascript-micro-templating/)
- // and Laura Doktorova's doT.js (https://github.com/olado/doT).
- var settings = templateSettings.imports._.templateSettings || templateSettings;
- if (guard && isIterateeCall(string, options, guard)) {
- options = undefined;
- }
- string = toString(string);
- options = assignInWith({}, options, settings, assignInDefaults);
- var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
- importsKeys = keys(imports),
- importsValues = baseValues(imports, importsKeys);
- var isEscaping,
- isEvaluating,
- index = 0,
- interpolate = options.interpolate || reNoMatch,
- source = "__p += '";
- // Compile the regexp to match each delimiter.
- var reDelimiters = RegExp(
- (options.escape || reNoMatch).source + '|' +
- interpolate.source + '|' +
- (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
- (options.evaluate || reNoMatch).source + '|$'
- , 'g');
- // Use a sourceURL for easier debugging.
- var sourceURL = 'sourceURL' in options ? '//# sourceURL=' + options.sourceURL + '\n' : '';
- string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
- interpolateValue || (interpolateValue = esTemplateValue);
- // Escape characters that can't be included in string literals.
- source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
- // Replace delimiters with snippets.
- if (escapeValue) {
- isEscaping = true;
- source += "' +\n__e(" + escapeValue + ") +\n'";
- }
- if (evaluateValue) {
- isEvaluating = true;
- source += "';\n" + evaluateValue + ";\n__p += '";
- }
- if (interpolateValue) {
- source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
- }
- index = offset + match.length;
- // The JS engine embedded in Adobe products needs `match` returned in
- // order to produce the correct `offset` value.
- return match;
- });
- source += "';\n";
- // If `variable` is not specified wrap a with-statement around the generated
- // code to add the data object to the top of the scope chain.
- var variable = options.variable;
- if (!variable) {
- source = 'with (obj) {\n' + source + '\n}\n';
- }
- // Cleanup code by stripping empty strings.
- source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
- .replace(reEmptyStringMiddle, '$1')
- .replace(reEmptyStringTrailing, '$1;');
- // Frame code as the function body.
- source = 'function(' + (variable || 'obj') + ') {\n' +
- (variable
- ? ''
- : 'obj || (obj = {});\n'
- ) +
- "var __t, __p = ''" +
- (isEscaping
- ? ', __e = _.escape'
- : ''
- ) +
- (isEvaluating
- ? ', __j = Array.prototype.join;\n' +
- "function print() { __p += __j.call(arguments, '') }\n"
- : ';\n'
- ) +
- source +
- 'return __p\n}';
- var result = attempt(function() {
- return Function(importsKeys, sourceURL + 'return ' + source)
- .apply(undefined, importsValues);
- });
- // Provide the compiled function's source by its `toString` method or
- // the `source` property as a convenience for inlining compiled templates.
- result.source = source;
- if (isError(result)) {
- throw result;
- }
- return result;
- }
- /**
- * Attempts to invoke `func`, returning either the result or the caught error
- * object. Any additional arguments are provided to `func` when it's invoked.
- *
- * @static
- * @memberOf _
- * @since 3.0.0
- * @category Util
- * @param {Function} func The function to attempt.
- * @param {...*} [args] The arguments to invoke `func` with.
- * @returns {*} Returns the `func` result or error object.
- * @example
- *
- * // Avoid throwing errors for invalid selectors.
- * var elements = _.attempt(function(selector) {
- * return document.querySelectorAll(selector);
- * }, '>_>');
- *
- * if (_.isError(elements)) {
- * elements = [];
- * }
- */
- var attempt = rest(function(func, args) {
- try {
- return apply(func, undefined, args);
- } catch (e) {
- return isError(e) ? e : new Error(e);
- }
- });
- module.exports = template;
|