apostrophe
Version:
Apostrophe is a user-friendly content management system. This core module of Apostrophe provides rich content editing and essential facilities to integrate Apostrophe into your Express project. Apostrophe also includes simple facilities for storing your r
1,509 lines (1,365 loc) • 244 kB
JavaScript
/**
* @license
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash -o ./dist/lodash.compat.js`
* 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>
*/
;(function() {
/** Used as a safe reference for `undefined` in pre ES5 environments */
var undefined;
/** Used to pool arrays and objects used internally */
var arrayPool = [],
objectPool = [];
/** Used to generate unique IDs */
var idCounter = 0;
/** Used internally to indicate various things */
var indicatorObject = {};
/** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
var keyPrefix = +new Date + '';
/** Used as the size when optimizations are enabled for large arrays */
var largeArraySize = 75;
/** Used as the max size of the `arrayPool` and `objectPool` */
var maxPoolSize = 40;
/** Used to detect and test whitespace */
var whitespace = (
// whitespace
' \t\x0B\f\xA0\ufeff' +
// line terminators
'\n\r\u2028\u2029' +
// unicode category "Zs" space separators
'\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
);
/** 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 ES6 template delimiters
* http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
/** Used to detected named functions */
var reFuncName = /^\s*function[ \n\r\t]+\w/;
/** Used to match "interpolate" template delimiters */
var reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to match leading whitespace and zeros to be removed */
var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
/** Used to ensure capturing order of template delimiters */
var reNoMatch = /($^)/;
/** Used to detect functions containing a `this` reference */
var reThis = /\bthis\b/;
/** Used to match unescaped characters in compiled string literals */
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/** Used to assign default `context` object properties */
var contextProps = [
'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object',
'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
'parseInt', 'setTimeout'
];
/** Used to fix the JScript [[DontEnum]] bug */
var shadowedProps = [
'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
'toLocaleString', 'toString', 'valueOf'
];
/** Used to make template sourceURLs easier to identify */
var templateCounter = 0;
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
errorClass = '[object Error]',
funcClass = '[object Function]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
/** Used to identify object classifications that `_.clone` supports */
var cloneableClasses = {};
cloneableClasses[funcClass] = false;
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
/** Used as an internal `_.debounce` options object */
var debounceOptions = {
'leading': false,
'maxWait': 0,
'trailing': false
};
/** Used as the property descriptor for `__bindData__` */
var descriptor = {
'configurable': false,
'enumerable': false,
'value': null,
'writable': false
};
/** Used as the data object for `iteratorTemplate` */
var iteratorData = {
'args': '',
'array': null,
'bottom': '',
'firstArg': '',
'init': '',
'keys': null,
'loop': '',
'shadowedProps': null,
'support': null,
'top': '',
'useHas': false
};
/** Used to determine if values are of the language type Object */
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
/** Used to escape characters for inclusion in compiled string literals */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/** Used as a reference to the global object */
var root = (objectTypes[typeof window] && window) || this;
/** Detect free variable `exports` */
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/** Detect free variable `module` */
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/** Detect the popular CommonJS extension `module.exports` */
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
/** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
var freeGlobal = objectTypes[typeof global] && global;
if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
root = freeGlobal;
}
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.indexOf` without support for binary searches
* or `fromIndex` constraints.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* An implementation of `_.contains` for cache objects that mimics the return
* signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
*
* @private
* @param {Object} cache The cache object to inspect.
* @param {*} value The value to search for.
* @returns {number} Returns `0` if `value` is found, else `-1`.
*/
function cacheIndexOf(cache, value) {
var type = typeof value;
cache = cache.cache;
if (type == 'boolean' || value == null) {
return cache[value] ? 0 : -1;
}
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value;
cache = (cache = cache[type]) && cache[key];
return type == 'object'
? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
: (cache ? 0 : -1);
}
/**
* Adds a given value to the corresponding cache object.
*
* @private
* @param {*} value The value to add to the cache.
*/
function cachePush(value) {
var cache = this.cache,
type = typeof value;
if (type == 'boolean' || value == null) {
cache[value] = true;
} else {
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value,
typeCache = cache[type] || (cache[type] = {});
if (type == 'object') {
(typeCache[key] || (typeCache[key] = [])).push(value);
} else {
typeCache[key] = true;
}
}
}
/**
* Used by `_.max` and `_.min` as the default callback when a given
* collection is a string value.
*
* @private
* @param {string} value The character to inspect.
* @returns {number} Returns the code unit of given character.
*/
function charAtCallback(value) {
return value.charCodeAt(0);
}
/**
* Used by `sortBy` to compare transformed `collection` elements, stable sorting
* them in ascending order.
*
* @private
* @param {Object} a The object to compare to `b`.
* @param {Object} b The object to compare to `a`.
* @returns {number} Returns the sort order indicator of `1` or `-1`.
*/
function compareAscending(a, b) {
var ac = a.criteria,
bc = b.criteria,
index = -1,
length = ac.length;
while (++index < length) {
var value = ac[index],
other = bc[index];
if (value !== other) {
if (value > other || typeof value == 'undefined') {
return 1;
}
if (value < other || typeof other == 'undefined') {
return -1;
}
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to return the same value for
// `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
//
// This also ensures a stable sort in V8 and other engines.
// See http://code.google.com/p/v8/issues/detail?id=90
return a.index - b.index;
}
/**
* Creates a cache object to optimize linear searches of large arrays.
*
* @private
* @param {Array} [array=[]] The array to search.
* @returns {null|Object} Returns the cache object or `null` if caching should not be used.
*/
function createCache(array) {
var index = -1,
length = array.length,
first = array[0],
mid = array[(length / 2) | 0],
last = array[length - 1];
if (first && typeof first == 'object' &&
mid && typeof mid == 'object' && last && typeof last == 'object') {
return false;
}
var cache = getObject();
cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
var result = getObject();
result.array = array;
result.cache = cache;
result.push = cachePush;
while (++index < length) {
result.push(array[index]);
}
return result;
}
/**
* Used by `template` to escape characters for inclusion in compiled
* string literals.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeStringChar(match) {
return '\\' + stringEscapes[match];
}
/**
* Gets an array from the array pool or creates a new one if the pool is empty.
*
* @private
* @returns {Array} The array from the pool.
*/
function getArray() {
return arrayPool.pop() || [];
}
/**
* Gets an object from the object pool or creates a new one if the pool is empty.
*
* @private
* @returns {Object} The object from the pool.
*/
function getObject() {
return objectPool.pop() || {
'array': null,
'cache': null,
'criteria': null,
'false': false,
'index': 0,
'null': false,
'number': null,
'object': null,
'push': null,
'string': null,
'true': false,
'undefined': false,
'value': null
};
}
/**
* Checks if `value` is a DOM node in IE < 9.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`.
*/
function isNode(value) {
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
// methods that are `typeof` "string" and still can coerce nodes to strings
return typeof value.toString != 'function' && typeof (value + '') == 'string';
}
/**
* Releases the given array back to the array pool.
*
* @private
* @param {Array} [array] The array to release.
*/
function releaseArray(array) {
array.length = 0;
if (arrayPool.length < maxPoolSize) {
arrayPool.push(array);
}
}
/**
* Releases the given object back to the object pool.
*
* @private
* @param {Object} [object] The object to release.
*/
function releaseObject(object) {
var cache = object.cache;
if (cache) {
releaseObject(cache);
}
object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
if (objectPool.length < maxPoolSize) {
objectPool.push(object);
}
}
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
*
* Note: This function is used instead of `Array#slice` to support node lists
* in IE < 9 and to ensure dense arrays are returned.
*
* @private
* @param {Array|Object|string} collection The collection to slice.
* @param {number} start The start index.
* @param {number} end The end index.
* @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
start || (start = 0);
if (typeof end == 'undefined') {
end = array ? array.length : 0;
}
var index = -1,
length = end - start || 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = array[start + index];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Create a new `lodash` function using the given context object.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} [context=root] The context object.
* @returns {Function} Returns the `lodash` function.
*/
function runInContext(context) {
// Avoid issues with some ES3 environments that attempt to use values, named
// after built-in constructors like `Object`, for the creation of literals.
// ES5 clears this up by stating that literals must use built-in constructors.
// See http://es5.github.io/#x11.1.5.
context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
/** Native constructor references */
var Array = context.Array,
Boolean = context.Boolean,
Date = context.Date,
Error = context.Error,
Function = context.Function,
Math = context.Math,
Number = context.Number,
Object = context.Object,
RegExp = context.RegExp,
String = context.String,
TypeError = context.TypeError;
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Used for native method references */
var errorProto = Error.prototype,
objectProto = Object.prototype,
stringProto = String.prototype;
/** Used to restore the original `_` reference in `noConflict` */
var oldDash = context._;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Used to detect if a method is native */
var reNative = RegExp('^' +
String(toString)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/toString| for [^\]]+/g, '.*?') + '$'
);
/** Native method shortcuts */
var ceil = Math.ceil,
clearTimeout = context.clearTimeout,
floor = Math.floor,
fnToString = Function.prototype.toString,
getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
hasOwnProperty = objectProto.hasOwnProperty,
push = arrayRef.push,
propertyIsEnumerable = objectProto.propertyIsEnumerable,
setTimeout = context.setTimeout,
splice = arrayRef.splice,
unshift = arrayRef.unshift;
/** Used to set meta data on functions */
var defineProperty = (function() {
// IE 8 only accepts DOM elements
try {
var o = {},
func = isNative(func = Object.defineProperty) && func,
result = func(o, o, o) && func;
} catch(e) { }
return result;
}());
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
nativeIsFinite = context.isFinite,
nativeIsNaN = context.isNaN,
nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
nativeMax = Math.max,
nativeMin = Math.min,
nativeParseInt = context.parseInt,
nativeRandom = Math.random;
/** Used to lookup a built-in constructor by [[Class]] */
var ctorByClass = {};
ctorByClass[arrayClass] = Array;
ctorByClass[boolClass] = Boolean;
ctorByClass[dateClass] = Date;
ctorByClass[funcClass] = Function;
ctorByClass[objectClass] = Object;
ctorByClass[numberClass] = Number;
ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String;
/** Used to avoid iterating non-enumerable properties in IE < 9 */
var nonEnumProps = {};
nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true };
nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true };
nonEnumProps[objectClass] = { 'constructor': true };
(function() {
var length = shadowedProps.length;
while (length--) {
var key = shadowedProps[length];
for (var className in nonEnumProps) {
if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) {
nonEnumProps[className][key] = false;
}
}
}
}());
/*--------------------------------------------------------------------------*/
/**
* Creates a `lodash` object which wraps the given value to enable intuitive
* method chaining.
*
* In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
* Chaining is supported in custom builds as long as the `value` method is
* implicitly or explicitly included in the build.
*
* The chainable wrapper functions are:
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
* `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
* `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
* `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
* `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
* `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
* `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
* `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
* `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
* `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
* and `zip`
*
* The non-chainable wrapper functions are:
* `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
* `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
* `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
* `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
* `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
* `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
* `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
* `template`, `unescape`, `uniqueId`, and `value`
*
* The wrapper functions `first` and `last` return wrapped values when `n` is
* provided, otherwise they return unwrapped values.
*
* Explicit chaining can be enabled by using the `_.chain` method.
*
* @name _
* @constructor
* @category Chaining
* @param {*} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns a `lodash` instance.
* @example
*
* var wrapped = _([1, 2, 3]);
*
* // returns an unwrapped value
* wrapped.reduce(function(sum, num) {
* return sum + num;
* });
* // => 6
*
* // returns a wrapped value
* var squares = wrapped.map(function(num) {
* return num * num;
* });
*
* _.isArray(squares);
* // => false
*
* _.isArray(squares.value());
* // => true
*/
function lodash(value) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
? value
: new lodashWrapper(value);
}
/**
* A fast path for creating `lodash` wrapper objects.
*
* @private
* @param {*} value The value to wrap in a `lodash` instance.
* @param {boolean} chainAll A flag to enable chaining for all methods
* @returns {Object} Returns a `lodash` instance.
*/
function lodashWrapper(value, chainAll) {
this.__chain__ = !!chainAll;
this.__wrapped__ = value;
}
// ensure `new lodashWrapper` is an instance of `lodash`
lodashWrapper.prototype = lodash.prototype;
/**
* An object used to flag environments features.
*
* @static
* @memberOf _
* @type Object
*/
var support = lodash.support = {};
(function() {
var ctor = function() { this.x = 1; },
object = { '0': 1, 'length': 1 },
props = [];
ctor.prototype = { 'valueOf': 1, 'y': 1 };
for (var key in new ctor) { props.push(key); }
for (key in arguments) { }
/**
* Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9).
*
* @memberOf _.support
* @type boolean
*/
support.argsClass = toString.call(arguments) == argsClass;
/**
* Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5).
*
* @memberOf _.support
* @type boolean
*/
support.argsObject = arguments.constructor == Object && !(arguments instanceof Array);
/**
* Detect if `name` or `message` properties of `Error.prototype` are
* enumerable by default. (IE < 9, Safari < 5.1)
*
* @memberOf _.support
* @type boolean
*/
support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name');
/**
* Detect if `prototype` properties are enumerable by default.
*
* Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
* (if the prototype or a property on the prototype has been set)
* incorrectly sets a function's `prototype` property [[Enumerable]]
* value to `true`.
*
* @memberOf _.support
* @type boolean
*/
support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype');
/**
* Detect if functions can be decompiled by `Function#toString`
* (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
*
* @memberOf _.support
* @type boolean
*/
support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
/**
* Detect if `Function#name` is supported (all but IE).
*
* @memberOf _.support
* @type boolean
*/
support.funcNames = typeof Function.name == 'string';
/**
* Detect if `arguments` object indexes are non-enumerable
* (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1).
*
* @memberOf _.support
* @type boolean
*/
support.nonEnumArgs = key != 0;
/**
* Detect if properties shadowing those on `Object.prototype` are non-enumerable.
*
* In IE < 9 an objects own properties, shadowing non-enumerable ones, are
* made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).
*
* @memberOf _.support
* @type boolean
*/
support.nonEnumShadows = !/valueOf/.test(props);
/**
* Detect if own properties are iterated after inherited properties (all but IE < 9).
*
* @memberOf _.support
* @type boolean
*/
support.ownLast = props[0] != 'x';
/**
* Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.
*
* Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
* and `splice()` functions that fail to remove the last element, `value[0]`,
* of array-like objects even though the `length` property is set to `0`.
* The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
* is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
*
* @memberOf _.support
* @type boolean
*/
support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);
/**
* Detect lack of support for accessing string characters by index.
*
* IE < 8 can't access characters by index and IE 8 can only access
* characters by index on string literals.
*
* @memberOf _.support
* @type boolean
*/
support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
/**
* Detect if a DOM node's [[Class]] is resolvable (all but IE < 9)
* and that the JS engine errors when attempting to coerce an object to
* a string without a `toString` function.
*
* @memberOf _.support
* @type boolean
*/
try {
support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
} catch(e) {
support.nodeClass = true;
}
}(1));
/**
* By default, the template delimiters used by Lo-Dash are similar to those in
* embedded Ruby (ERB). Change the following template settings to use alternative
* delimiters.
*
* @static
* @memberOf _
* @type Object
*/
lodash.templateSettings = {
/**
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'escape': /<%-([\s\S]+?)%>/g,
/**
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'evaluate': /<%([\s\S]+?)%>/g,
/**
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'interpolate': reInterpolate,
/**
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
* @type string
*/
'variable': '',
/**
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
* @type Object
*/
'imports': {
/**
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
* @type Function
*/
'_': lodash
}
};
/*--------------------------------------------------------------------------*/
/**
* The template used to create iterator functions.
*
* @private
* @param {Object} data The data object used to populate the text.
* @returns {string} Returns the interpolated text.
*/
var iteratorTemplate = function(obj) {
var __p = 'var index, iterable = ' +
(obj.firstArg) +
', result = ' +
(obj.init) +
';\nif (!iterable) return result;\n' +
(obj.top) +
';';
if (obj.array) {
__p += '\nvar length = iterable.length; index = -1;\nif (' +
(obj.array) +
') { ';
if (support.unindexedChars) {
__p += '\n if (isString(iterable)) {\n iterable = iterable.split(\'\')\n } ';
}
__p += '\n while (++index < length) {\n ' +
(obj.loop) +
';\n }\n}\nelse { ';
} else if (support.nonEnumArgs) {
__p += '\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += \'\';\n ' +
(obj.loop) +
';\n }\n } else { ';
}
if (support.enumPrototypes) {
__p += '\n var skipProto = typeof iterable == \'function\';\n ';
}
if (support.enumErrorProps) {
__p += '\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ';
}
var conditions = []; if (support.enumPrototypes) { conditions.push('!(skipProto && index == "prototype")'); } if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (index == "message" || index == "name"))'); }
if (obj.useHas && obj.keys) {
__p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n';
if (conditions.length) {
__p += ' if (' +
(conditions.join(' && ')) +
') {\n ';
}
__p +=
(obj.loop) +
'; ';
if (conditions.length) {
__p += '\n }';
}
__p += '\n } ';
} else {
__p += '\n for (index in iterable) {\n';
if (obj.useHas) { conditions.push("hasOwnProperty.call(iterable, index)"); } if (conditions.length) {
__p += ' if (' +
(conditions.join(' && ')) +
') {\n ';
}
__p +=
(obj.loop) +
'; ';
if (conditions.length) {
__p += '\n }';
}
__p += '\n } ';
if (support.nonEnumShadows) {
__p += '\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ';
for (k = 0; k < 7; k++) {
__p += '\n index = \'' +
(obj.shadowedProps[k]) +
'\';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))';
if (!obj.useHas) {
__p += ' || (!nonEnum[index] && iterable[index] !== objectProto[index])';
}
__p += ') {\n ' +
(obj.loop) +
';\n } ';
}
__p += '\n } ';
}
}
if (obj.array || support.nonEnumArgs) {
__p += '\n}';
}
__p +=
(obj.bottom) +
';\nreturn result';
return __p
};
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.bind` that creates the bound function and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new bound function.
*/
function baseBind(bindData) {
var func = bindData[0],
partialArgs = bindData[2],
thisArg = bindData[4];
function bound() {
// `Function#bind` spec
// http://es5.github.io/#x15.3.4.5
if (partialArgs) {
// avoid `arguments` object deoptimizations by using `slice` instead
// of `Array.prototype.slice.call` and not assigning `arguments` to a
// variable as a ternary expression
var args = slice(partialArgs);
push.apply(args, arguments);
}
// mimic the constructor's `return` behavior
// http://es5.github.io/#x13.2.2
if (this instanceof bound) {
// ensure `new bound` is an instance of `func`
var thisBinding = baseCreate(func.prototype),
result = func.apply(thisBinding, args || arguments);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisArg, args || arguments);
}
setBindData(bound, bindData);
return bound;
}
/**
* The base implementation of `_.clone` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates clones with source counterparts.
* @returns {*} Returns the cloned value.
*/
function baseClone(value, isDeep, callback, stackA, stackB) {
if (callback) {
var result = callback(value);
if (typeof result != 'undefined') {
return result;
}
}
// inspect [[Class]]
var isObj = isObject(value);
if (isObj) {
var className = toString.call(value);
if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) {
return value;
}
var ctor = ctorByClass[className];
switch (className) {
case boolClass:
case dateClass:
return new ctor(+value);
case numberClass:
case stringClass:
return new ctor(value);
case regexpClass:
result = ctor(value.source, reFlags.exec(value));
result.lastIndex = value.lastIndex;
return result;
}
} else {
return value;
}
var isArr = isArray(value);
if (isDeep) {
// check for circular references and return corresponding clone
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == value) {
return stackB[length];
}
}
result = isArr ? ctor(value.length) : {};
}
else {
result = isArr ? slice(value) : assign({}, value);
}
// add array properties assigned by `RegExp#exec`
if (isArr) {
if (hasOwnProperty.call(value, 'index')) {
result.index = value.index;
}
if (hasOwnProperty.call(value, 'input')) {
result.input = value.input;
}
}
// exit for shallow clone
if (!isDeep) {
return result;
}
// add the source value to the stack of traversed objects
// and associate it with its clone
stackA.push(value);
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
(isArr ? baseEach : forOwn)(value, function(objValue, key) {
result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
});
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* The base implementation of `_.create` without support for assigning
* properties to the created object.
*
* @private
* @param {Object} prototype The object to inherit from.
* @returns {Object} Returns the new object.
*/
function baseCreate(prototype, properties) {
return isObject(prototype) ? nativeCreate(prototype) : {};
}
// fallback for browsers without `Object.create`
if (!nativeCreate) {
baseCreate = (function() {
function Object() {}
return function(prototype) {
if (isObject(prototype)) {
Object.prototype = prototype;
var result = new Object;
Object.prototype = null;
}
return result || context.Object();
};
}());
}
/**
* The base implementation of `_.createCallback` without support for creating
* "_.pluck" or "_.where" style callbacks.
*
* @private
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
*/
function baseCreateCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
return identity;
}
// exit early for no `thisArg` or already bound by `Function#bind`
if (typeof thisArg == 'undefined' || !('prototype' in func)) {
return func;
}
var bindData = func.__bindData__;
if (typeof bindData == 'undefined') {
if (support.funcNames) {
bindData = !func.name;
}
bindData = bindData || !support.funcDecomp;
if (!bindData) {
var source = fnToString.call(func);
if (!support.funcNames) {
bindData = !reFuncName.test(source);
}
if (!bindData) {
// checks if `func` references the `this` keyword and stores the result
bindData = reThis.test(source);
setBindData(func, bindData);
}
}
}
// exit early if there are no `this` references or `func` is bound
if (bindData === false || (bindData !== true && bindData[1] & 1)) {
return func;
}
switch (argCount) {
case 1: return function(value) {
return func.call(thisArg, value);
};
case 2: return function(a, b) {
return func.call(thisArg, a, b);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return bind(func, thisArg);
}
/**
* The base implementation of `createWrapper` that creates the wrapper and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new function.
*/
function baseCreateWrapper(bindData) {
var func = bindData[0],
bitmask = bindData[1],
partialArgs = bindData[2],
partialRightArgs = bindData[3],
thisArg = bindData[4],
arity = bindData[5];
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
key = func;
function bound() {
var thisBinding = isBind ? thisArg : this;
if (partialArgs) {
var args = slice(partialArgs);
push.apply(args, arguments);
}
if (partialRightArgs || isCurry) {
args || (args = slice(arguments));
if (partialRightArgs) {
push.apply(args, partialRightArgs);
}
if (isCurry && args.length < arity) {
bitmask |= 16 & ~32;
return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
}
}
args || (args = arguments);
if (isBindKey) {
func = thisBinding[key];
}
if (this instanceof bound) {
thisBinding = baseCreate(func.prototype);
var result = func.apply(thisBinding, args);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisBinding, args);
}
setBindData(bound, bindData);
return bound;
}
/**
* The base implementation of `_.difference` that accepts a single array
* of values to exclude.
*
* @private
* @param {Array} array The array to process.
* @param {Array} [values] The array of values to exclude.
* @returns {Array} Returns a new array of filtered values.
*/
function baseDifference(array, values) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
isLarge = length >= largeArraySize && indexOf === baseIndexOf,
result = [];
if (isLarge) {
var cache = createCache(values);
if (cache) {
indexOf = cacheIndexOf;
values = cache;
} else {
isLarge = false;
}
}
while (++index < length) {
var value = array[index];
if (indexOf(values, value) < 0) {
result.push(value);
}
}
if (isLarge) {
releaseObject(values);
}
return result;
}
/**
* The base implementation of `_.flatten` without support for callback
* shorthands or `thisArg` binding.
*
* @private
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
* @param {number} [fromIndex=0] The index to start from.
* @returns {Array} Returns a new flattened array.
*/
function baseFlatten(array, isShallow, isStrict, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value && typeof value == 'object' && typeof value.length == 'number'
&& (isArray(value) || isArguments(value))) {
// recursively flatten arrays (susceptible to call stack limits)
if (!isShallow) {
value = baseFlatten(value, isShallow, isStrict);
}
var valIndex = -1,
valLength = value.length,
resIndex = result.length;
result.length += valLength;
while (++valIndex < valLength) {
result[resIndex++] = value[valIndex];
}
} else if (!isStrict) {
result.push(value);
}
}
return result;
}
/**
* The base implementation of `_.isEqual`, without support for `thisArg` binding,
* that allows partial "_.where" style comparisons.
*
* @private
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
* @param {Array} [stackA=[]] Tracks traversed `a` objects.
* @param {Array} [stackB=[]] Tracks traversed `b` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
// used to indicate that when comparing objects, `a` has at least the properties of `b`
if (callback) {
var result = callback(a, b);
if (typeof result != 'undefined') {
return !!result;
}
}
// exit early for identical values
if (a === b) {
// treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b);
}
var type = typeof a,
otherType = typeof b;
// exit early for unlike primitive values
if (a === a &&
!(a && objectTypes[type]) &&
!(b && objectTypes[otherType])) {
return false;
}
// exit early for `null` and `undefined` avoiding ES3's Function#call behavior
// http://es5.github.io/#x15.3.4.4
if (a == null || b == null) {
return a === b;
}
// compare [[Class]] names
var className = toString.call(a),
otherClass = toString.call(b);
if (className == argsClass) {
className = objectClass;
}
if (otherClass == argsClass) {
otherClass = objectClass;
}
if (className != otherClass) {
return false;
}
switch (className) {
case boolClass:
case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal
return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
return (a != +a)
? b != +b
// but treat `+0` vs. `-0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
return a == String(b);
}
var isArr = className == arrayClass;
if (!isArr) {
// unwrap any `lodash` wrapped values
var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
bWrapped = hasOwnProperty.call(b, '__wrapped__');
if (aWrapped || bWrapped) {
return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
}
// exit for functions and DOM nodes
if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {
return false;
}
// in older versions of Opera, `arguments` objects have `Array` constructors
var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,
ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
// non `Object` object instances with different constructors are not equal
if (ctorA != ctorB &&
!(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
('constructor' in a && 'constructor' in b)
) {
return false;
}
}
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
// section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == a) {
return stackB[length] == b;
}
}
var size = 0;
result = true;
// add `a` and `b` to the stack of traversed objects
stackA.push(a);
stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
// compare lengths to determine if a deep comparison is necessary
length = a.length;
size = b.length;
result = size == length;
if (result || isWhere) {
// deep compare the contents, ignoring non-numeric properties
while (size--) {
var index = length,
value = b[size];
if (isWhere) {
while (index--) {
if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
break;
}
}
} else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
break;
}
}
}
}
else {
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
forIn(b, function(value, key, b) {
if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
}
});
if (result && !isWhere) {
// ensure both objects have the same number of properties
forIn(a, function(value, key, a) {
if (hasOwnProperty.call(a, key)) {
// `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
}
}
stackA.pop();
stackB.pop();
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* The base implementation of `_.merge` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @param {Function} [callback] The function to customize merging properties.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates values with source counterparts.
*/
function baseMerge(object, source, callback, stackA, stackB) {
(isArray(source) ? forEach : forOwn)(source, function(source, key) {
var found,
isArr,
result = source,
value = object[key];
if (source && ((isArr = isArray(sour