/*! Quill Editor v0.20.1 * https://quilljs.com/ * Copyright (c) 2014, Jason Chen * Copyright (c) 2013, salesforce.com */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Quill = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o * Build: `lodash modern include="difference,intersection,last,all,each,find,invoke,map,reduce,partition,bind,defer,partial,clone,extend,defaults,omit,values,isElement,isEqual,isFunction,isNumber,isObject,isString,uniqueId" --development --output .build/lodash.js` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.8.3 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ ;(function() { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; /** Used as the semantic version number. */ var VERSION = '3.9.3'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; /** Used to detect when a function becomes hot. */ var HOT_COUNT = 150, HOT_SPAN = 16; /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; /** Used as the internal argument placeholder. */ var PLACEHOLDER = '__lodash_placeholder__'; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', boolTag = '[object Boolean]', dateTag = '[object Date]', errorTag = '[object Error]', funcTag = '[object Function]', mapTag = '[object Map]', numberTag = '[object Number]', objectTag = '[object Object]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', weakMapTag = '[object WeakMap]'; var arrayBufferTag = '[object ArrayBuffer]', float32Tag = '[object Float32Array]', float64Tag = '[object Float64Array]', int8Tag = '[object Int8Array]', int16Tag = '[object Int16Array]', int32Tag = '[object Int32Array]', uint8Tag = '[object Uint8Array]', uint8ClampedTag = '[object Uint8ClampedArray]', uint16Tag = '[object Uint16Array]', uint32Tag = '[object Uint32Array]'; /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; /** * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). * In addition to special characters the forward slash is escaped to allow for * easier `eval` use and `Function` compilation. */ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; /** Used to detect host constructors (Safari > 5). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used to detect unsigned integer values. */ var reIsUint = /^\d+$/; /** Used to identify `toStringTag` values of typed arrays. */ var typedArrayTags = {}; typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; /** Used to identify `toStringTag` values supported by `_.clone`. */ var cloneableTags = {}; cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; /** Used to determine if values are of the language type `Object`. */ var objectTypes = { 'function': true, 'object': true }; /** 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 free variable `global` from Node.js. */ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global; /** Detect free variable `self`. */ var freeSelf = objectTypes[typeof self] && self && self.Object && self; /** Detect free variable `window`. */ var freeWindow = objectTypes[typeof window] && window && window.Object && window; /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; /** * Used as a reference to the global object. * * The `this` value is used if it's the global object to avoid Greasemonkey's * restricted `window` object, otherwise the `window` object is used. */ var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this; /*--------------------------------------------------------------------------*/ /** * The base implementation of `_.findIndex` and `_.findLastIndex` without * support for callback shorthands and `this` binding. * * @private * @param {Array} array The array to search. * @param {Function} predicate The function invoked per iteration. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseFindIndex(array, predicate, fromRight) { var length = array.length, index = fromRight ? length : -1; while ((fromRight ? index-- : ++index < length)) { if (predicate(array[index], index, array)) { return index; } } return -1; } /** * The base implementation of `_.indexOf` without support for binary searches. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { if (value !== value) { return indexOfNaN(array, fromIndex); } var index = fromIndex - 1, length = array.length; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** * The base implementation of `_.isFunction` without support for environments * with incorrect `typeof` results. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. */ function baseIsFunction(value) { // Avoid a Chakra JIT bug in compatibility modes of IE 11. // See https://github.com/jashkenas/underscore/issues/1621 for more details. return typeof value == 'function' || false; } /** * Converts `value` to a string if it's not one. An empty string is returned * for `null` or `undefined` values. * * @private * @param {*} value The value to process. * @returns {string} Returns the string. */ function baseToString(value) { if (typeof value == 'string') { return value; } return value == null ? '' : (value + ''); } /** * Gets the index at which the first occurrence of `NaN` is found in `array`. * * @private * @param {Array} array The array to search. * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched `NaN`, else `-1`. */ function indexOfNaN(array, fromIndex, fromRight) { var length = array.length, index = fromIndex + (fromRight ? 0 : -1); while ((fromRight ? index-- : ++index < length)) { var other = array[index]; if (other !== other) { return index; } } return -1; } /** * Checks if `value` is object-like. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ function isObjectLike(value) { return !!value && typeof value == 'object'; } /** * Replaces all `placeholder` elements in `array` with an internal placeholder * and returns an array of their indexes. * * @private * @param {Array} array The array to modify. * @param {*} placeholder The placeholder to replace. * @returns {Array} Returns the new array of placeholder indexes. */ function replaceHolders(array, placeholder) { var index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; result[++resIndex] = index; } } return result; } /*--------------------------------------------------------------------------*/ /** Used for native method references. */ var objectProto = Object.prototype; /** Used to detect DOM support. */ var document = (document = root.window) ? document.document : null; /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** Used to generate unique IDs. */ var idCounter = 0; /** * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + escapeRegExp(fnToString.call(hasOwnProperty)) .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method references. */ var ArrayBuffer = getNative(root, 'ArrayBuffer'), bufferSlice = getNative(ArrayBuffer && new ArrayBuffer(0), 'slice'), floor = Math.floor, getPrototypeOf = getNative(Object, 'getPrototypeOf'), Set = getNative(root, 'Set'), Uint8Array = getNative(root, 'Uint8Array'), WeakMap = getNative(root, 'WeakMap'); /** Used to clone array buffers. */ var Float64Array = (function() { // Safari 5 errors when using an array buffer to initialize a typed array // where the array buffer's `byteLength` is not a multiple of the typed // array's `BYTES_PER_ELEMENT`. try { var func = getNative(root, 'Float64Array'), result = new func(new ArrayBuffer(10), 0, 1) && func; } catch(e) {} return result || null; }()); /* Native method references for those with the same name as other `lodash` methods. */ var nativeCreate = getNative(Object, 'create'), nativeIsArray = getNative(Array, 'isArray'), nativeKeys = getNative(Object, 'keys'), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, 'now'); /** Used as references for `-Infinity` and `Infinity`. */ var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; /** Used as the size, in bytes, of each `Float64Array` element. */ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; /** * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * of an array-like value. */ var MAX_SAFE_INTEGER = 9007199254740991; /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; /** Used to lookup unminified function names. */ var realNames = {}; /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps `value` to enable implicit chaining. * Methods that operate on and return arrays, collections, and functions can * be chained together. Methods that return a boolean or single value will * automatically end the chain returning the unwrapped value. Explicit chaining * may be enabled using `_.chain`. The execution of chained methods is lazy, * that is, execution is deferred until `_#value` is implicitly or explicitly * called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut * fusion is an optimization that merges iteratees to avoid creating intermediate * arrays and reduce the number of iteratee executions. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. * * In addition to lodash methods, wrappers have `Array` and `String` methods. * * The wrapper `Array` methods are: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, * `splice`, and `unshift` * * The wrapper `String` methods are: * `replace` and `split` * * The wrapper methods that support shortcut fusion are: * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`, * and `where` * * The chainable wrapper methods are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, * `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, * `memoize`, `merge`, `method`, `methodOf`, `mixin`, `negate`, `omit`, `once`, * `pairs`, `partial`, `partialRight`, `partition`, `pick`, `plant`, `pluck`, * `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `shuffle`, * `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`, `spread`, * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, * `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `where`, `without`, * `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `get`, * `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, * `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, * `isFinite` `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `lt`, `lte`, * `max`, `min`, `noConflict`, `noop`, `now`, `pad`, `padLeft`, `padRight`, * `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, * `runInContext`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, * `sortedLastIndex`, `startCase`, `startsWith`, `sum`, `template`, `trim`, * `trimLeft`, `trimRight`, `trunc`, `unescape`, `uniqueId`, `value`, and `words` * * The wrapper method `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. * * @name _ * @constructor * @category Chain * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value * wrapped.reduce(function(total, n) { * return total + n; * }); * // => 6 * * // returns a wrapped value * var squares = wrapped.map(function(n) { * return n * n; * }); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash() { // No operation performed. } /** * The function whose prototype all chaining wrappers inherit from. * * @private */ function baseLodash() { // No operation performed. } /** * An object environment feature flags. * * @static * @memberOf _ * @type Object */ var support = lodash.support = {}; (function(x) { var Ctor = function() { this.x = x; }, object = { '0': x, 'length': x }, props = []; Ctor.prototype = { 'valueOf': x, 'y': x }; for (var key in new Ctor) { props.push(key); } /** * Detect if the DOM is supported. * * @memberOf _.support * @type boolean */ try { support.dom = document.createDocumentFragment().nodeType === 11; } catch(e) { support.dom = false; } }(1, 0)); /*------------------------------------------------------------------------*/ /** * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. * * @private * @param {*} value The value to wrap. */ function LazyWrapper(value) { this.__wrapped__ = value; this.__actions__ = null; this.__dir__ = 1; this.__dropCount__ = 0; this.__filtered__ = false; this.__iteratees__ = null; this.__takeCount__ = POSITIVE_INFINITY; this.__views__ = null; } /*------------------------------------------------------------------------*/ /** * * Creates a cache object to store unique values. * * @private * @param {Array} [values] The values to cache. */ function SetCache(values) { var length = values ? values.length : 0; this.data = { 'hash': nativeCreate(null), 'set': new Set }; while (length--) { this.push(values[length]); } } /** * Checks if `value` is in `cache` mimicking the return signature of * `_.indexOf` by returning `0` if the value is found, else `-1`. * * @private * @param {Object} cache The cache to search. * @param {*} value The value to search for. * @returns {number} Returns `0` if `value` is found, else `-1`. */ function cacheIndexOf(cache, value) { var data = cache.data, result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value]; return result ? 0 : -1; } /** * Adds `value` to the cache. * * @private * @name push * @memberOf SetCache * @param {*} value The value to cache. */ function cachePush(value) { var data = this.data; if (typeof value == 'string' || isObject(value)) { data.set.add(value); } else { data.hash[value] = true; } } /*------------------------------------------------------------------------*/ /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ function arrayCopy(source, array) { var index = -1, length = source.length; array || (array = Array(length)); while (++index < length) { array[index] = source[index]; } return array; } /** * A specialized version of `_.forEach` for arrays without support for callback * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { if (iteratee(array[index], index, array) === false) { break; } } return array; } /** * A specialized version of `_.every` for arrays without support for callback * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. */ function arrayEvery(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (!predicate(array[index], index, array)) { return false; } } return true; } /** * A specialized version of `_.map` for arrays without support for callback * shorthands and `this` binding. * * @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; } /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray] Specify using the first element of `array` * as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; if (initFromArray && length) { accumulator = array[++index]; } while (++index < length) { accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } /** * A specialized version of `_.some` for arrays without support for callback * shorthands and `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function arraySome(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (predicate(array[index], index, array)) { return true; } } return false; } /** * Used by `_.defaults` to customize its `_.assign` use. * * @private * @param {*} objectValue The destination object property value. * @param {*} sourceValue The source object property value. * @returns {*} Returns the value to assign to the destination object. */ function assignDefaults(objectValue, sourceValue) { return objectValue === undefined ? sourceValue : objectValue; } /** * A specialized version of `_.assign` for customizing assigned values without * support for argument juggling, multiple sources, and `this` binding `customizer` * functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} customizer The function to customize assigned values. * @returns {Object} Returns `object`. */ function assignWith(object, source, customizer) { var index = -1, props = keys(source), length = props.length; while (++index < length) { var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); if ((result === result ? (result !== value) : (value === value)) || (value === undefined && !(key in object))) { object[key] = result; } } return object; } /** * The base implementation of `_.assign` without support for argument juggling, * multiple sources, and `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @returns {Object} Returns `object`. */ function baseAssign(object, source) { return source == null ? object : baseCopy(source, keys(source), object); } /** * Copies properties of `source` to `object`. * * @private * @param {Object} source The object to copy properties from. * @param {Array} props The property names to copy. * @param {Object} [object={}] The object to copy properties to. * @returns {Object} Returns `object`. */ function baseCopy(source, props, object) { object || (object = {}); var index = -1, length = props.length; while (++index < length) { var key = props[index]; object[key] = source[key]; } return object; } /** * The base implementation of `_.callback` which supports specifying the * number of arguments to provide to `func`. * * @private * @param {*} [func=_.identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of `func`. * @param {number} [argCount] The number of arguments to provide to `func`. * @returns {Function} Returns the callback. */ function baseCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function') { return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); } if (func == null) { return identity; } if (type == 'object') { return baseMatches(func); } return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); } /** * The base implementation of `_.clone` without support for argument juggling * and `this` binding `customizer` functions. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {string} [key] The key of `value`. * @param {Object} [object] The object `value` belongs to. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates clones with source counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { var result; if (customizer) { result = object ? customizer(value, key, object) : customizer(value); } if (result !== undefined) { return result; } if (!isObject(value)) { return value; } var isArr = isArray(value); if (isArr) { result = initCloneArray(value); if (!isDeep) { return arrayCopy(value, result); } } else { var tag = objToString.call(value), isFunc = tag == funcTag; if (tag == objectTag || tag == argsTag || (isFunc && !object)) { result = initCloneObject(isFunc ? {} : value); if (!isDeep) { return baseAssign(result, value); } } else { return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : (object ? value : {}); } } // Check for circular references and return corresponding clone. stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == value) { return stackB[length]; } } // 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 ? arrayEach : baseForOwn)(value, function(subValue, key) { result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, 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. */ var baseCreate = (function() { function object() {} return function(prototype) { if (isObject(prototype)) { object.prototype = prototype; var result = new object; object.prototype = null; } return result || {}; }; }()); /** * The base implementation of `_.delay` and `_.defer` which accepts an index * of where to slice the arguments to provide to `func`. * * @private * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {Object} args The arguments provide to `func`. * @returns {number} Returns the timer id. */ function baseDelay(func, wait, args) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return setTimeout(function() { func.apply(undefined, args); }, wait); } /** * The base implementation of `_.difference` which accepts a single array * of values to exclude. * * @private * @param {Array} array The array to inspect. * @param {Array} values The values to exclude. * @returns {Array} Returns the new array of filtered values. */ function baseDifference(array, values) { var length = array ? array.length : 0, result = []; if (!length) { return result; } var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, cache = (isCommon && values.length >= 200) ? createCache(values) : null, valuesLength = values.length; if (cache) { indexOf = cacheIndexOf; isCommon = false; values = cache; } outer: while (++index < length) { var value = array[index]; if (isCommon && value === value) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { continue outer; } } result.push(value); } else if (indexOf(values, value, 0) < 0) { result.push(value); } } return result; } /** * The base implementation of `_.forEach` without support for callback * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ var baseEach = createBaseEach(baseForOwn); /** * The base implementation of `_.every` without support for callback * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false` */ function baseEvery(collection, predicate) { var result = true; baseEach(collection, function(value, index, collection) { result = !!predicate(value, index, collection); return result; }); return result; } /** * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, * without support for callback shorthands and `this` binding, which iterates * over `collection` using the provided `eachFunc`. * * @private * @param {Array|Object|string} collection The collection to search. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey] Specify returning the key of the found element * instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ function baseFind(collection, predicate, eachFunc, retKey) { var result; eachFunc(collection, function(value, key, collection) { if (predicate(value, key, collection)) { result = retKey ? key : value; return false; } }); return result; } /** * The base implementation of `_.flatten` with added support for restricting * flattening and specifying the start index. * * @private * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects. * @returns {Array} Returns the new flattened array. */ function baseFlatten(array, isDeep, isStrict) { var index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, valLength = value.length; while (++valIndex < valLength) { result[++resIndex] = value[valIndex]; } } else if (!isStrict) { result[++resIndex] = value; } } return result; } /** * The base implementation of `baseForIn` and `baseForOwn` which iterates * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iteratee functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ var baseFor = createBaseFor(); /** * The base implementation of `_.forIn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { return baseFor(object, iteratee, keysIn); } /** * The base implementation of `_.forOwn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return baseFor(object, iteratee, keys); } /** * The base implementation of `get` without support for string paths * and default values. * * @private * @param {Object} object The object to query. * @param {Array} path The path of the property to get. * @param {string} [pathKey] The key representation of path. * @returns {*} Returns the resolved value. */ function baseGet(object, path, pathKey) { if (object == null) { return; } if (pathKey !== undefined && pathKey in toObject(object)) { path = [pathKey]; } var index = 0, length = path.length; while (object != null && index < length) { object = object[path[index++]]; } return (index && index == length) ? object : undefined; } /** * The base implementation of `_.isEqual` without support for `this` binding * `customizer` functions. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparing values. * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { if (value === other) { return true; } if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { return value !== value && other !== other; } return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); } /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular * references to be compared. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing objects. * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; if (!objIsArr) { objTag = objToString.call(object); if (objTag == argsTag) { objTag = objectTag; } else if (objTag != objectTag) { objIsArr = isTypedArray(object); } } if (!othIsArr) { othTag = objToString.call(other); if (othTag == argsTag) { othTag = objectTag; } else if (othTag != objectTag) { othIsArr = isTypedArray(other); } } var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; if (isSameTag && !(objIsArr || objIsObj)) { return equalByTag(object, other, objTag); } if (!isLoose) { var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (objIsWrapped || othIsWrapped) { return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); } } if (!isSameTag) { return false; } // Assume cyclic values are equal. // For more information on detecting circular references see https://es5.github.io/#JO. stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == object) { return stackB[length] == other; } } // Add `object` and `other` to the stack of traversed objects. stackA.push(object); stackB.push(other); var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); stackA.pop(); stackB.pop(); return result; } /** * The base implementation of `_.isMatch` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to inspect. * @param {Array} matchData The propery names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparing objects. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, matchData, customizer) { var index = matchData.length, length = index, noCustomizer = !customizer; if (object == null) { return !length; } object = toObject(object); while (index--) { var data = matchData[index]; if ((noCustomizer && data[2]) ? data[1] !== object[data[0]] : !(data[0] in object) ) { return false; } } while (++index < length) { data = matchData[index]; var key = data[0], objValue = object[key], srcValue = data[1]; if (noCustomizer && data[2]) { if (objValue === undefined && !(key in object)) { return false; } } else { var result = customizer ? customizer(objValue, srcValue, key) : undefined; if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { return false; } } } return true; } /** * The base implementation of `_.map` without support for callback shorthands * and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value, key, collection) { result[++index] = iteratee(value, key, collection); }); return result; } /** * The base implementation of `_.matches` which does not clone `source`. * * @private * @param {Object} source The object of property values to match. * @returns {Function} Returns the new function. */ function baseMatches(source) { var matchData = getMatchData(source); if (matchData.length == 1 && matchData[0][2]) { var key = matchData[0][0], value = matchData[0][1]; return function(object) { if (object == null) { return false; } return object[key] === value && (value !== undefined || (key in toObject(object))); }; } return function(object) { return baseIsMatch(object, matchData); }; } /** * The base implementation of `_.matchesProperty` which does not clone `srcValue`. * * @private * @param {string} path The path of the property to get. * @param {*} srcValue The value to compare. * @returns {Function} Returns the new function. */ function baseMatchesProperty(path, srcValue) { var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = (path + ''); path = toPath(path); return function(object) { if (object == null) { return false; } var key = pathKey; object = toObject(object); if ((isArr || !isCommon) && !(key in object)) { object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); if (object == null) { return false; } key = last(path); object = toObject(object); } return object[key] === srcValue ? (srcValue !== undefined || (key in object)) : baseIsEqual(srcValue, object[key], undefined, true); }; } /** * 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]; }; } /** * A specialized version of `baseProperty` which supports deep paths. * * @private * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new function. */ function basePropertyDeep(path) { var pathKey = (path + ''); path = toPath(path); return function(object) { return baseGet(object, path, pathKey); }; } /** * The base implementation of `_.reduce` and `_.reduceRight` without support * for callback shorthands and `this` binding, which iterates over `collection` * using the provided `eachFunc`. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); }); return accumulator; } /** * The base implementation of `setData` without support for hot loop detection. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var baseSetData = !metaMap ? identity : function(func, data) { metaMap.set(func, data); return func; }; /** * The base implementation of `_.slice` without an iteratee call guard. * * @private * @param {Array} array The array to slice. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the slice of `array`. */ function baseSlice(array, start, end) { var index = -1, length = array.length; start = start == null ? 0 : (+start || 0); if (start < 0) { start = -start > length ? 0 : (length + start); } end = (end === undefined || end > length) ? length : (+end || 0); if (end < 0) { end += length; } length = start > end ? 0 : ((end - start) >>> 0); start >>>= 0; var result = Array(length); while (++index < length) { result[index] = array[index + start]; } 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) { var index = -1, length = props.length, result = Array(length); while (++index < length) { result[index] = object[props[index]]; } return result; } /** * Performs a binary search of `array` to determine the index at which `value` * should be inserted into `array` in order to maintain its sort order. * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function binaryIndex(array, value, retHighest) { var low = 0, high = array ? array.length : low; if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { while (low < high) { var mid = (low + high) >>> 1, computed = array[mid]; if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) { low = mid + 1; } else { high = mid; } } return high; } return binaryIndexBy(array, value, identity, retHighest); } /** * This function is like `binaryIndex` except that it invokes `iteratee` for * `value` and each element of `array` to compute their sort ranking. The * iteratee is invoked with one argument; (value). * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function binaryIndexBy(array, value, iteratee, retHighest) { value = iteratee(value); var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; while (low < high) { var mid = floor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; if (valIsNaN) { var setLow = isReflexive || retHighest; } else if (valIsNull) { setLow = isReflexive && isDef && (retHighest || computed != null); } else if (valIsUndef) { setLow = isReflexive && (retHighest || isDef); } else if (computed == null) { setLow = false; } else { setLow = retHighest ? (computed <= value) : (computed < value); } if (setLow) { low = mid + 1; } else { high = mid; } } return nativeMin(high, MAX_ARRAY_INDEX); } /** * A specialized version of `baseCallback` which only supports `this` binding * and specifying the number of arguments to provide to `func`. * * @private * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. * @param {number} [argCount] The number of arguments to provide to `func`. * @returns {Function} Returns the callback. */ function bindCallback(func, thisArg, argCount) { if (typeof func != 'function') { return identity; } if (thisArg === undefined) { return func; } switch (argCount) { case 1: return function(value) { return func.call(thisArg, value); }; 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); }; case 5: return function(value, other, key, object, source) { return func.call(thisArg, value, other, key, object, source); }; } return function() { return func.apply(thisArg, arguments); }; } /** * Creates a clone of the given array buffer. * * @private * @param {ArrayBuffer} buffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ function bufferClone(buffer) { return bufferSlice.call(buffer, 0); } if (!bufferSlice) { // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { var byteLength = buffer.byteLength, floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, result = new ArrayBuffer(byteLength); if (floatLength) { var view = new Float64Array(result, 0, floatLength); view.set(new Float64Array(buffer, 0, floatLength)); } if (byteLength != offset) { view = new Uint8Array(result, offset); view.set(new Uint8Array(buffer, offset)); } return result; }; } /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private * @param {Array|Object} args The provided arguments. * @param {Array} partials The arguments to prepend to those provided. * @param {Array} holders The `partials` placeholder indexes. * @returns {Array} Returns the new array of composed arguments. */ function composeArgs(args, partials, holders) { var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(argsLength + leftLength); while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; } while (++argsIndex < holdersLength) { result[holders[argsIndex]] = args[argsIndex]; } while (argsLength--) { result[leftIndex++] = args[argsIndex++]; } return result; } /** * This function is like `composeArgs` except that the arguments composition * is tailored for `_.partialRight`. * * @private * @param {Array|Object} args The provided arguments. * @param {Array} partials The arguments to append to those provided. * @param {Array} holders The `partials` placeholder indexes. * @returns {Array} Returns the new array of composed arguments. */ function composeArgsRight(args, partials, holders) { var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); while (++argsIndex < argsLength) { result[argsIndex] = args[argsIndex]; } var offset = argsIndex; while (++rightIndex < rightLength) { result[offset + rightIndex] = partials[rightIndex]; } while (++holdersIndex < holdersLength) { result[offset + holders[holdersIndex]] = args[argsIndex++]; } return result; } /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection * through an iteratee. * * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`, * and `_.partition`. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. * @param {Function} [initializer] The function to initialize the accumulator object. * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { return function(collection, iteratee, thisArg) { var result = initializer ? initializer() : {}; iteratee = getCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { setter(result, value, iteratee(value, key, collection), collection); }); } return result; }; } /** * Creates a function that assigns properties of source object(s) to a given * destination object. * * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`. * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { return restParam(function(object, sources) { var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; if (typeof customizer == 'function') { customizer = bindCallback(customizer, thisArg, 5); length -= 2; } else { customizer = typeof thisArg == 'function' ? thisArg : undefined; length -= (customizer ? 1 : 0); } if (guard && isIterateeCall(sources[0], sources[1], guard)) { customizer = length < 3 ? undefined : customizer; length = 1; } while (++index < length) { var source = sources[index]; if (source) { assigner(object, source, customizer); } } return object; }); } /** * Creates a `baseEach` or `baseEachRight` function. * * @private * @param {Function} eachFunc The function to iterate over a collection. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseEach(eachFunc, fromRight) { return function(collection, iteratee) { var length = collection ? getLength(collection) : 0; if (!isLength(length)) { return eachFunc(collection, iteratee); } var index = fromRight ? length : -1, iterable = toObject(collection); while ((fromRight ? index-- : ++index < length)) { if (iteratee(iterable[index], index, iterable) === false) { break; } } return collection; }; } /** * Creates a base function for `_.forIn` or `_.forInRight`. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseFor(fromRight) { return function(object, iteratee, keysFunc) { var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; while ((fromRight ? index-- : ++index < length)) { var key = props[index]; if (iteratee(iterable[key], key, iterable) === false) { break; } } return object; }; } /** * Creates a function that wraps `func` and invokes it with the `this` * binding of `thisArg`. * * @private * @param {Function} func The function to bind. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new bound function. */ function createBindWrapper(func, thisArg) { var Ctor = createCtorWrapper(func); function wrapper() { var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; return fn.apply(thisArg, arguments); } return wrapper; } /** * Creates a `Set` cache object to optimize linear searches of large arrays. * * @private * @param {Array} [values] The values to cache. * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. */ var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { return new SetCache(values); }; /** * Creates a function that produces an instance of `Ctor` regardless of * whether it was invoked as part of a `new` expression or by `call` or `apply`. * * @private * @param {Function} Ctor The constructor to wrap. * @returns {Function} Returns the new wrapped function. */ function createCtorWrapper(Ctor) { return function() { // Use a `switch` statement to work with class constructors. // See https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { case 0: return new Ctor; case 1: return new Ctor(args[0]); case 2: return new Ctor(args[0], args[1]); case 3: return new Ctor(args[0], args[1], args[2]); case 4: return new Ctor(args[0], args[1], args[2], args[3]); case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); } var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior. // See https://es5.github.io/#x13.2.2 for more details. return isObject(result) ? result : thisBinding; }; } /** * Creates a `_.find` or `_.findLast` function. * * @private * @param {Function} eachFunc The function to iterate over a collection. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new find function. */ function createFind(eachFunc, fromRight) { return function(collection, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); if (isArray(collection)) { var index = baseFindIndex(collection, predicate, fromRight); return index > -1 ? collection[index] : undefined; } return baseFind(collection, predicate, eachFunc); }; } /** * Creates a function for `_.forEach` or `_.forEachRight`. * * @private * @param {Function} arrayFunc The function to iterate over an array. * @param {Function} eachFunc The function to iterate over a collection. * @returns {Function} Returns the new each function. */ function createForEach(arrayFunc, eachFunc) { return function(collection, iteratee, thisArg) { return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection)) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); }; } /** * Creates a `_.partial` or `_.partialRight` function. * * @private * @param {boolean} flag The partial bit flag. * @returns {Function} Returns the new partial function. */ function createPartial(flag) { var partialFunc = restParam(function(func, partials) { var holders = replaceHolders(partials, partialFunc.placeholder); return createWrapper(func, flag, null, partials, holders); }); return partialFunc; } /** * Creates a function for `_.reduce` or `_.reduceRight`. * * @private * @param {Function} arrayFunc The function to iterate over an array. * @param {Function} eachFunc The function to iterate over a collection. * @returns {Function} Returns the new each function. */ function createReduce(arrayFunc, eachFunc) { return function(collection, iteratee, accumulator, thisArg) { var initFromArray = arguments.length < 3; return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection)) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); }; } /** * Creates a function that wraps `func` and invokes it with optional `this` * binding of, partial application, and currying. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to prepend to those provided to the new function. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [partialsRight] The arguments to append to those provided to the new function. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? null : createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by // converting it to an array before providing it to other functions. var length = arguments.length, index = length, args = Array(length); while (index--) { args[index] = arguments[index]; } if (partials) { args = composeArgs(args, partials, holders); } if (partialsRight) { args = composeArgsRight(args, partialsRight, holdersRight); } if (isCurry || isCurryRight) { var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); length -= argsHolders.length; if (length < arity) { var newArgPos = argPos ? arrayCopy(argPos) : null, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : null, newHoldersRight = isCurry ? null : argsHolders, newPartials = isCurry ? args : null, newPartialsRight = isCurry ? null : args; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity], result = createHybridWrapper.apply(undefined, newData); if (isLaziable(func)) { setData(result, newData); } result.placeholder = placeholder; return result; } } var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; if (argPos) { args = reorder(args, argPos); } if (isAry && ary < args.length) { args.length = ary; } if (this && this !== root && this instanceof wrapper) { fn = Ctor || createCtorWrapper(func); } return fn.apply(thisBinding, args); } return wrapper; } /** * Creates a function that wraps `func` and invokes it with the optional `this` * binding of `thisArg` and the `partials` prepended to those provided to * the wrapper. * * @private * @param {Function} func The function to partially apply arguments to. * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {*} thisArg The `this` binding of `func`. * @param {Array} partials The arguments to prepend to those provided to the new function. * @returns {Function} Returns the new bound function. */ function createPartialWrapper(func, bitmask, thisArg, partials) { var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by // converting it to an array before providing it `func`. var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(argsLength + leftLength); while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; } while (argsLength--) { args[leftIndex++] = arguments[++argsIndex]; } var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; return fn.apply(isBind ? thisArg : this, args); } return wrapper; } /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` * 4 - `_.curry` or `_.curryRight` of a bound function * 8 - `_.curry` * 16 - `_.curryRight` * 32 - `_.partial` * 64 - `_.partialRight` * 128 - `_.rearg` * 256 - `_.ary` * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to be partially applied. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); partials = holders = null; } length -= (holders ? holders.length : 0); if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; partials = holders = null; } var data = isBindKey ? null : getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; if (data) { mergeData(newData, data); bitmask = newData[1]; arity = newData[9]; } newData[9] = arity == null ? (isBindKey ? 0 : func.length) : (nativeMax(arity - length, 0) || 0); if (bitmask == BIND_FLAG) { var result = createBindWrapper(newData[0], newData[2]); } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { result = createPartialWrapper.apply(undefined, newData); } else { result = createHybridWrapper.apply(undefined, newData); } var setter = data ? baseSetData : setData; return setter(result, newData); } /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. * * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing arrays. * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { var index = -1, arrLength = array.length, othLength = other.length; if (arrLength != othLength && !(isLoose && othLength > arrLength)) { return false; } // Ignore non-index properties. while (++index < arrLength) { var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; if (result !== undefined) { if (result) { continue; } return false; } // Recursively compare arrays (susceptible to call stack limits). if (isLoose) { if (!arraySome(other, function(othValue) { return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); })) { return false; } } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { return false; } } return true; } /** * A specialized version of `baseIsEqualDeep` for comparing objects of * the same `toStringTag`. * * **Note:** This function only supports comparing values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} value The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalByTag(object, other, tag) { switch (tag) { case boolTag: case dateTag: // 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 +object == +other; case errorTag: return object.name == other.name && object.message == other.message; case numberTag: // Treat `NaN` vs. `NaN` as equal. return (object != +object) ? other != +other : object == +other; case regexpTag: case stringTag: // Coerce regexes to strings and treat strings primitives and string // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. return object == (other + ''); } return false; } /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing values. * @param {boolean} [isLoose] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; if (objLength != othLength && !isLoose) { return false; } var index = objLength; while (index--) { var key = objProps[index]; if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { return false; } } var skipCtor = isLoose; while (++index < objLength) { key = objProps[index]; var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined; // Recursively compare objects (susceptible to call stack limits). if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { return false; } skipCtor || (skipCtor = key == 'constructor'); } if (!skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal. if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { return false; } } return true; } /** * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns * the `baseCallback` function. If arguments are provided the chosen function * is invoked with them and its result is returned. * * @private * @returns {Function} Returns the chosen function or its result. */ function getCallback(func, thisArg, argCount) { var result = lodash.callback || callback; result = result === callback ? baseCallback : result; return argCount ? result(func, thisArg, argCount) : result; } /** * Gets metadata for `func`. * * @private * @param {Function} func The function to query. * @returns {*} Returns the metadata for `func`. */ var getData = !metaMap ? noop : function(func) { return metaMap.get(func); }; /** * Gets the name of `func`. * * @private * @param {Function} func The function to query. * @returns {string} Returns the function name. */ function getFuncName(func) { var result = func.name, array = realNames[result], length = array ? array.length : 0; while (length--) { var data = array[length], otherFunc = data.func; if (otherFunc == null || otherFunc == func) { return data.name; } } return result; } /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. */ function getIndexOf(collection, target, fromIndex) { var result = lodash.indexOf || indexOf; result = result === indexOf ? baseIndexOf : result; return collection ? result(collection, target, fromIndex) : result; } /** * 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'); /** * Gets the propery names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { var result = pairs(object), length = result.length; while (length--) { result[length][2] = isStrictComparable(result[length][1]); } return result; } /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { var value = object == null ? undefined : object[key]; return isNative(value) ? value : undefined; } /** * Initializes an array clone. * * @private * @param {Array} array The array to clone. * @returns {Array} Returns the initialized clone. */ function initCloneArray(array) { var length = array.length, result = new array.constructor(length); // Add array properties assigned by `RegExp#exec`. if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { result.index = array.index; result.input = array.input; } return result; } /** * Initializes an object clone. * * @private * @param {Object} object The object to clone. * @returns {Object} Returns the initialized clone. */ function initCloneObject(object) { var Ctor = object.constructor; if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) { Ctor = Object; } return new Ctor; } /** * Initializes an object clone based on its `toStringTag`. * * **Note:** This function only supports cloning values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to clone. * @param {string} tag The `toStringTag` of the object to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the initialized clone. */ function initCloneByTag(object, tag, isDeep) { var Ctor = object.constructor; switch (tag) { case arrayBufferTag: return bufferClone(object); case boolTag: case dateTag: return new Ctor(+object); case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: var buffer = object.buffer; return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); case numberTag: case stringTag: return new Ctor(object); case regexpTag: var result = new Ctor(object.source, reFlags.exec(object)); result.lastIndex = object.lastIndex; } return result; } /** * Invokes the method at `path` on `object`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the method to invoke. * @param {Array} args The arguments to invoke the method with. * @returns {*} Returns the result of the invoked method. */ function invokePath(object, path, args) { if (object != null && !isKey(path, object)) { path = toPath(path); object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); path = last(path); } var func = object == null ? object : object[path]; return func == null ? undefined : func.apply(object, args); } /** * Checks if `value` is array-like. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. */ function isArrayLike(value) { return value != null && isLength(getLength(value)); } /** * 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; } /** * Checks if the provided 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)) { var other = object[index]; return value === value ? (value === other) : (other !== other); } return false; } /** * Checks if `value` is a property name and not a property path. * * @private * @param {*} value The value to check. * @param {Object} [object] The object to query keys on. * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { var type = typeof value; if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') { return true; } if (isArray(value)) { return false; } var result = !reIsDeepProp.test(value); return result || (object != null && value in toObject(object)); } /** * Checks if `func` has a lazy counterpart. * * @private * @param {Function} func The function to check. * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`. */ function isLaziable(func) { var funcName = getFuncName(func); if (!(funcName in LazyWrapper.prototype)) { return false; } var other = lodash[funcName]; if (func === other) { return true; } var data = getData(other); return !!data && func === data[0]; } /** * Checks if `value` is a valid array-like length. * * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength). * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. */ function isLength(value) { return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` if suitable for strict * equality comparisons, else `false`. */ function isStrictComparable(value) { return value === value && !isObject(value); } /** * Merges the function metadata of `source` into `data`. * * Merging metadata reduces the number of wrappers required to invoke a function. * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` * augment function arguments, making the order in which they are executed important, * preventing the merging of metadata. However, we make an exception for a safe * common case where curried functions have `_.ary` and or `_.rearg` applied. * * @private * @param {Array} data The destination metadata. * @param {Array} source The source metadata. * @returns {Array} Returns `data`. */ function mergeData(data, source) { var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; var isCombo = (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) || (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) || (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { return data; } // Use source `thisArg` if available. if (srcBitmask & BIND_FLAG) { data[2] = source[2]; // Set when currying a bound function. newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG; } // Compose partial arguments. var value = source[3]; if (value) { var partials = data[3]; data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); } // Compose partial right arguments. value = source[5]; if (value) { partials = data[5]; data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); } // Use source `argPos` if available. value = source[7]; if (value) { data[7] = arrayCopy(value); } // Use source `ary` if it's smaller. if (srcBitmask & ARY_FLAG) { data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); } // Use source `arity` if one is not provided. if (data[9] == null) { data[9] = source[9]; } // Use source `func` and merge bitmasks. data[0] = source[0]; data[1] = newBitmask; return data; } /** * A specialized version of `_.pick` which picks `object` properties specified * by `props`. * * @private * @param {Object} object The source object. * @param {string[]} props The property names to pick. * @returns {Object} Returns the new object. */ function pickByArray(object, props) { object = toObject(object); var index = -1, length = props.length, result = {}; while (++index < length) { var key = props[index]; if (key in object) { result[key] = object[key]; } } return result; } /** * A specialized version of `_.pick` which picks `object` properties `predicate` * returns truthy for. * * @private * @param {Object} object The source object. * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { var result = {}; baseForIn(object, function(value, key, object) { if (predicate(value, key, object)) { result[key] = value; } }); return result; } /** * Reorder `array` according to the specified indexes where the element at * the first index is assigned as the first element, the element at * the second index is assigned as the second element, and so on. * * @private * @param {Array} array The array to reorder. * @param {Array} indexes The arranged array indexes. * @returns {Array} Returns `array`. */ function reorder(array, indexes) { var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); while (length--) { var index = indexes[length]; array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; } return array; } /** * Sets metadata for `func`. * * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity function * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070) * for more details. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var setData = (function() { var count = 0, lastCalled = 0; return function(key, value) { var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { if (++count >= HOT_COUNT) { return key; } } else { count = 0; } return baseSetData(key, value); }; }()); /** * A fallback implementation of `_.isPlainObject` which checks if `value` * is an object created by the `Object` constructor or has a `[[Prototype]]` * of `null`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { var Ctor, support = lodash.support; // Exit early for non `Object` objects. if (!(isObjectLike(value) && objToString.call(value) == objectTag) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first // iterated property is an object's own property then there are no inherited // enumerable properties. var result; // In most environments an object's own properties are iterated before // its inherited properties. If the last iterated property is an object's // own property then there are no inherited enumerable properties. baseForIn(value, function(subValue, key) { result = key; }); return result === undefined || hasOwnProperty.call(value, result); } /** * A fallback implementation of `Object.keys` which creates an array of the * own enumerable property names of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function shimKeys(object) { var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); var index = -1, result = []; while (++index < propsLength) { var key = props[index]; if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { result.push(key); } } return result; } /** * Converts `value` to an object if it's not one. * * @private * @param {*} value The value to process. * @returns {Object} Returns the object. */ function toObject(value) { return isObject(value) ? value : Object(value); } /** * Converts `value` to property path array if it's not one. * * @private * @param {*} value The value to process. * @returns {Array} Returns the property path array. */ function toPath(value) { if (isArray(value)) { return value; } var result = []; baseToString(value).replace(rePropName, function(match, number, quote, string) { result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); }); return result; } /*------------------------------------------------------------------------*/ /** * Creates an array of unique `array` values not included in the other * provided arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for equality comparisons. * * @static * @memberOf _ * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example * * _.difference([1, 2, 3], [4, 2]); * // => [1, 3] */ var difference = restParam(function(array, values) { return isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; }); /** * Gets the index at which the first occurrence of `value` is found in `array` * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it is used as the offset * from the end of `array`. If `array` is sorted providing `true` for `fromIndex` * performs a faster binary search. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=0] The index to search from or `true` * to perform a binary search on a sorted array. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.indexOf([1, 2, 1, 2], 2); * // => 1 * * // using `fromIndex` * _.indexOf([1, 2, 1, 2], 2, 2); * // => 3 * * // performing a binary search * _.indexOf([1, 1, 2, 2], 2, true); * // => 2 */ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (!length) { return -1; } if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; } else if (fromIndex) { var index = binaryIndex(array, value), other = array[index]; if (value === value ? (value === other) : (other !== other)) { return index; } return -1; } return baseIndexOf(array, value, fromIndex || 0); } /** * Creates an array of unique values that are included in all of the provided * arrays using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for equality comparisons. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of shared values. * @example * _.intersection([1, 2], [4, 2], [2, 1]); * // => [2] */ var intersection = restParam(function(arrays) { var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, result = []; while (othIndex--) { var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null; } var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; outer: while (++index < length) { value = array[index]; if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { var othIndex = othLength; while (--othIndex) { var cache = caches[othIndex]; if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { continue outer; } } if (seen) { seen.push(value); } result.push(value); } } return result; }); /** * Gets the last element of `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to query. * @returns {*} Returns the last element of `array`. * @example * * _.last([1, 2, 3]); * // => 3 */ function last(array) { var length = array ? array.length : 0; return length ? array[length - 1] : undefined; } /*------------------------------------------------------------------------*/ /** * Checks if `predicate` returns truthy for **all** elements of `collection`. * The predicate is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * * If an object is provided for `predicate` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. * @example * * _.every([true, 1, null, 'yes'], Boolean); * // => false * * var users = [ * { 'user': 'barney', 'active': false }, * { 'user': 'fred', 'active': false } * ]; * * // using the `_.matches` callback shorthand * _.every(users, { 'user': 'barney', 'active': false }); * // => false * * // using the `_.matchesProperty` callback shorthand * _.every(users, 'active', false); * // => true * * // using the `_.property` callback shorthand * _.every(users, 'active'); * // => false */ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (thisArg && isIterateeCall(collection, predicate, thisArg)) { predicate = null; } if (typeof predicate != 'function' || thisArg !== undefined) { predicate = getCallback(predicate, thisArg, 3); } return func(collection, predicate); } /** * Iterates over elements of `collection`, returning the first element * `predicate` returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * * If an object is provided for `predicate` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': true }, * { 'user': 'fred', 'age': 40, 'active': false }, * { 'user': 'pebbles', 'age': 1, 'active': true } * ]; * * _.result(_.find(users, function(chr) { * return chr.age < 40; * }), 'user'); * // => 'barney' * * // using the `_.matches` callback shorthand * _.result(_.find(users, { 'age': 1, 'active': true }), 'user'); * // => 'pebbles' * * // using the `_.matchesProperty` callback shorthand * _.result(_.find(users, 'active', false), 'user'); * // => 'fred' * * // using the `_.property` callback shorthand * _.result(_.find(users, 'active'), 'user'); * // => 'barney' */ var find = createFind(baseEach); /** * Iterates over elements of `collection` invoking `iteratee` for each element. * The `iteratee` is bound to `thisArg` and invoked with three arguments: * (value, index|key, collection). Iteratee functions may exit iteration early * by explicitly returning `false`. * * **Note:** As with other "Collections" methods, objects with a "length" property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * * @static * @memberOf _ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2]).forEach(function(n) { * console.log(n); * }).value(); * // => logs each value from left to right and returns the array * * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) { * console.log(n, key); * }); * // => logs each value-key pair and returns the object (iteration order is not guaranteed) */ var forEach = createForEach(arrayEach, baseEach); /** * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments * are provided to each invoked method. If `methodName` is a function it is * invoked for, and `this` bound to, each element in `collection`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|string} path The path of the method to invoke or * the function invoked per iteration. * @param {...*} [args] The arguments to invoke the method with. * @returns {Array} Returns the array of results. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ var invoke = restParam(function(collection, path, args) { var index = -1, isFunc = typeof path == 'function', isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { var func = isFunc ? path : ((isProp && value != null) ? value[path] : null); result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); }); return result; }); /** * Creates an array of values by running each element in `collection` through * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments: (value, index|key, collection). * * If a property name is provided for `iteratee` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * * If an object is provided for `iteratee` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * Many lodash methods are guarded to work as iteratees for methods like * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. * * The guarded methods are: * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, * `sum`, `uniq`, and `words` * * @static * @memberOf _ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * * function timesThree(n) { * return n * 3; * } * * _.map([1, 2], timesThree); * // => [3, 6] * * _.map({ 'a': 1, 'b': 2 }, timesThree); * // => [3, 6] (iteration order is not guaranteed) * * var users = [ * { 'user': 'barney' }, * { 'user': 'fred' } * ]; * * // using the `_.property` callback shorthand * _.map(users, 'user'); * // => ['barney', 'fred'] */ function map(collection, iteratee, thisArg) { var func = isArray(collection) ? arrayMap : baseMap; iteratee = getCallback(iteratee, thisArg, 3); return func(collection, iteratee); } /** * Creates an array of elements split into two groups, the first of which * contains elements `predicate` returns truthy for, while the second of which * contains elements `predicate` returns falsey for. The predicate is bound * to `thisArg` and invoked with three arguments: (value, index|key, collection). * * If a property name is provided for `predicate` the created `_.property` * style callback returns the property value of the given element. * * If a value is also provided for `thisArg` the created `_.matchesProperty` * style callback returns `true` for elements that have a matching property * value, else `false`. * * If an object is provided for `predicate` the created `_.matches` style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the array of grouped elements. * @example * * _.partition([1, 2, 3], function(n) { * return n % 2; * }); * // => [[1, 3], [2]] * * _.partition([1.2, 2.3, 3.4], function(n) { * return this.floor(n) % 2; * }, Math); * // => [[1.2, 3.4], [2.3]] * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true }, * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * * var mapper = function(array) { * return _.pluck(array, 'user'); * }; * * // using the `_.matches` callback shorthand * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper); * // => [['pebbles'], ['barney', 'fred']] * * // using the `_.matchesProperty` callback shorthand * _.map(_.partition(users, 'active', false), mapper); * // => [['barney', 'pebbles'], ['fred']] * * // using the `_.property` callback shorthand * _.map(_.partition(users, 'active'), mapper); * // => [['fred'], ['barney', 'pebbles']] */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); }, function() { return [[], []]; }); /** * Reduces `collection` to a value which is the accumulated result of running * each element in `collection` through `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of `collection` is used as the initial * value. The `iteratee` is bound to `thisArg` and invoked with four arguments: * (accumulator, value, index|key, collection). * * Many lodash methods are guarded to work as iteratees for methods like * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder` * * @static * @memberOf _ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * _.reduce([1, 2], function(total, n) { * return total + n; * }); * // => 3 * * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) { * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed) */ var reduce = createReduce(arrayReduce, baseEach); /*------------------------------------------------------------------------*/ /** * Gets the number of milliseconds that have elapsed since the Unix epoch * (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ * @category Date * @example * * _.defer(function(stamp) { * console.log(_.now() - stamp); * }, _.now()); * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function() { return new Date().getTime(); }; /*------------------------------------------------------------------------*/ /** * Creates a function that invokes `func` with the `this` binding of `thisArg` * and prepends any additional `_.bind` arguments to those provided to the * bound function. * * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for partially applied arguments. * * **Note:** Unlike native `Function#bind` this method does not set the "length" * property of bound functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var greet = function(greeting, punctuation) { * return greeting + ' ' + this.user + punctuation; * }; * * var object = { 'user': 'fred' }; * * var bound = _.bind(greet, object, 'hi'); * bound('!'); * // => 'hi fred!' * * // using placeholders * var bound = _.bind(greet, object, _, '!'); * bound('hi'); * // => 'hi fred!' */ var bind = restParam(function(func, thisArg, partials) { var bitmask = BIND_FLAG; if (partials.length) { var holders = replaceHolders(partials, bind.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(func, bitmask, thisArg, partials, holders); }); /** * Defers invoking the `func` until the current call stack has cleared. Any * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to defer. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.defer(function(text) { * console.log(text); * }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ var defer = restParam(function(func, args) { return baseDelay(func, 1, args); }); /** * Creates a function that invokes `func` with `partial` arguments prepended * to those provided to the new function. This method is like `_.bind` except * it does **not** alter the `this` binding. * * The `_.partial.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * **Note:** This method does not set the "length" property of partially * applied functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { * return greeting + ' ' + name; * }; * * var sayHelloTo = _.partial(greet, 'hello'); * sayHelloTo('fred'); * // => 'hello fred' * * // using placeholders * var greetFred = _.partial(greet, _, 'fred'); * greetFred('hi'); * // => 'hi fred' */ var partial = createPartial(PARTIAL_FLAG); /** * Creates a function that invokes `func` with the `this` binding of the * created function and arguments from `start` and beyond provided as an array. * * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters). * * @static * @memberOf _ * @category Function * @param {Function} func The function to apply a rest parameter to. * @param {number} [start=func.length-1] The start position of the rest parameter. * @returns {Function} Returns the new function. * @example * * var say = _.restParam(function(what, names) { * return what + ' ' + _.initial(names).join(', ') + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); * }); * * say('hello', 'fred', 'barney', 'pebbles'); * // => 'hello fred, barney, & pebbles' */ function restParam(func, start) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0); return function() { var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); while (++index < length) { rest[index] = args[start + index]; } switch (start) { case 0: return func.call(this, rest); case 1: return func.call(this, args[0], rest); case 2: return func.call(this, args[0], args[1], rest); } var otherArgs = Array(start + 1); index = -1; while (++index < start) { otherArgs[index] = args[index]; } otherArgs[start] = rest; return func.apply(this, otherArgs); }; } /*------------------------------------------------------------------------*/ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value [, index|key, object]). * * **Note:** This method is loosely based on the * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, * Maps, Sets, and WeakMaps. * * @static * @memberOf _ * @category Lang * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {*} Returns the cloned value. * @example * * var users = [ * { 'user': 'barney' }, * { 'user': 'fred' } * ]; * * var shallow = _.clone(users); * shallow[0] === users[0]; * // => true * * var deep = _.clone(users, true); * deep[0] === users[0]; * // => false * * // using a customizer callback * var el = _.clone(document.body, function(value) { * if (_.isElement(value)) { * return value.cloneNode(false); * } * }); * * el === document.body * // => false * el.nodeName * // => BODY * el.childNodes.length; * // => 0 */ function clone(value, isDeep, customizer, thisArg) { if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) { isDeep = false; } else if (typeof isDeep == 'function') { thisArg = customizer; customizer = isDeep; isDeep = false; } return typeof customizer == 'function' ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1)) : baseClone(value, isDeep); } /** * Checks if `value` is classified as an `arguments` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isArguments(function() { return arguments; }()); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag; } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * _.isArray(function() { return arguments; }()); * // => false */ var isArray = nativeIsArray || function(value) { return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; }; /** * Checks if `value` is a DOM element. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true * * _.isElement(''); * // => false */ function isElement(value) { return !!value && value.nodeType === 1 && isObjectLike(value) && (objToString.call(value).indexOf('Element') > -1); } // Fallback for environments without DOM support. if (!support.dom) { isElement = function(value) { return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); }; } /** * Performs a deep comparison between two values to determine if they are * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments: (value, other [, index|key]). * * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Objects are compared by * their own, not inherited, enumerable properties. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. * * @static * @memberOf _ * @alias eq * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize value comparisons. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'user': 'fred' }; * var other = { 'user': 'fred' }; * * object == other; * // => false * * _.isEqual(object, other); * // => true * * // using a customizer callback * var array = ['hello', 'goodbye']; * var other = ['hi', 'goodbye']; * * _.isEqual(array, other, function(value, other) { * if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) { * return true; * } * }); * // => true */ function isEqual(value, other, customizer, thisArg) { customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined; var result = customizer ? customizer(value, other) : undefined; return result === undefined ? baseIsEqual(value, other, customizer) : !!result; } /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @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 */ var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. return objToString.call(value) == funcTag; }; /** * 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 _ * @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(1); * // => false */ function isObject(value) { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; return !!value && (type == 'object' || type == 'function'); } /** * Checks if `value` is a native function. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, else `false`. * @example * * _.isNative(Array.prototype.push); * // => true * * _.isNative(_); * // => false */ function isNative(value) { if (value == null) { return false; } if (objToString.call(value) == funcTag) { return reIsNative.test(fnToString.call(value)); } return isObjectLike(value) && reIsHostCtor.test(value); } /** * Checks if `value` is classified as a `Number` primitive or object. * * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isNumber(8.4); * // => true * * _.isNumber(NaN); * // => true * * _.isNumber('8.4'); * // => false */ function isNumber(value) { return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag); } /** * Checks if `value` is a plain object, that is, an object created by the * `Object` constructor or one with a `[[Prototype]]` of `null`. * * **Note:** This method assumes objects created by the `Object` constructor * have no inherited enumerable properties. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Foo() { * this.a = 1; * } * * _.isPlainObject(new Foo); * // => false * * _.isPlainObject([1, 2, 3]); * // => false * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true * * _.isPlainObject(Object.create(null)); * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && objToString.call(value) == objectTag)) { return false; } var valueOf = getNative(value, 'valueOf'), objProto = valueOf && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); return objProto ? (value == objProto || getPrototypeOf(value) == objProto) : shimIsPlainObject(value); }; /** * Checks if `value` is classified as a `String` primitive or object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isString('abc'); * // => true * * _.isString(1); * // => false */ function isString(value) { return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag); } /** * Checks if `value` is classified as a typed array. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isTypedArray(new Uint8Array); * // => true * * _.isTypedArray([]); * // => false */ function isTypedArray(value) { return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; } /*------------------------------------------------------------------------*/ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments: * (objectValue, sourceValue, key, object, source). * * **Note:** This method mutates `object` and is based on * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign). * * @static * @memberOf _ * @alias extend * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @param {Function} [customizer] The function to customize assigned values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {Object} Returns `object`. * @example * * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' }); * // => { 'user': 'fred', 'age': 40 } * * // using a customizer callback * var defaults = _.partialRight(_.assign, function(value, other) { * return _.isUndefined(value) ? other : value; * }); * * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ var assign = createAssigner(function(object, source, customizer) { return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); }); /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a * property is set, additional values of the same property are ignored. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @example * * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ var defaults = restParam(function(args) { var object = args[0]; if (object == null) { return object; } args.push(assignDefaults); return assign.apply(undefined, args); }); /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) * for more details. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keys(new Foo); * // => ['a', 'b'] (iteration order is not guaranteed) * * _.keys('hi'); * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { var Ctor = object == null ? null : object.constructor; if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) { return shimKeys(object); } return isObject(object) ? nativeKeys(object) : []; }; /** * Creates an array of the own and inherited enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { if (object == null) { return []; } if (!isObject(object)) { object = Object(object); } var length = object.length; length = (length && isLength(length) && (isArray(object) || isArguments(object)) && length) || 0; var Ctor = object.constructor, index = -1, isProto = typeof Ctor == 'function' && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; while (++index < length) { result[index] = (index + ''); } for (var key in object) { if (!(skipIndexes && isIndex(key, length)) && !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { result.push(key); } } return result; } /** * The opposite of `_.pick`; this method creates an object composed of the * own and inherited enumerable properties of `object` that are not omitted. * * @static * @memberOf _ * @category Object * @param {Object} object The source object. * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns the new object. * @example * * var object = { 'user': 'fred', 'age': 40 }; * * _.omit(object, 'age'); * // => { 'user': 'fred' } * * _.omit(object, _.isNumber); * // => { 'user': 'fred' } */ var omit = restParam(function(object, props) { if (object == null) { return {}; } if (typeof props[0] != 'function') { var props = arrayMap(baseFlatten(props), String); return pickByArray(object, baseDifference(keysIn(object), props)); } var predicate = bindCallback(props[0], props[1], 3); return pickByCallback(object, function(value, key, object) { return !predicate(value, key, object); }); }); /** * Creates a two dimensional array of the key-value pairs for `object`, * e.g. `[[key1, value1], [key2, value2]]`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the new array of key-value pairs. * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) */ function pairs(object) { object = toObject(object); var index = -1, props = keys(object), length = props.length, result = Array(length); while (++index < length) { var key = props[index]; result[index] = [key, object[key]]; } return result; } /** * Creates an array of the own enumerable property values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.values(new Foo); * // => [1, 2] (iteration order is not guaranteed) * * _.values('hi'); * // => ['h', 'i'] */ function values(object) { return baseValues(object, keys(object)); } /*------------------------------------------------------------------------*/ /** * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?", * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escapeRegExp('[lodash](https://lodash.com/)'); * // => '\[lodash\]\(https:\/\/lodash\.com\/\)' */ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) ? string.replace(reRegExpChars, '\\$&') : string; } /*------------------------------------------------------------------------*/ /** * Creates a function that invokes `func` with the `this` binding of `thisArg` * and arguments of the created function. If `func` is a property name the * created callback returns the property value for a given element. If `func` * is an object the created callback returns `true` for elements that contain * the equivalent object properties, otherwise it returns `false`. * * @static * @memberOf _ * @alias iteratee * @category Utility * @param {*} [func=_.identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of `func`. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Function} Returns the callback. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // wrap to create custom callback shorthands * _.callback = _.wrap(_.callback, function(callback, func, thisArg) { * var match = /^(.+?)__([gl]t)(.+)$/.exec(func); * if (!match) { * return callback(func, thisArg); * } * return function(object) { * return match[2] == 'gt' * ? object[match[1]] > match[3] * : object[match[1]] < match[3]; * }; * }); * * _.filter(users, 'age__gt36'); * // => [{ 'user': 'fred', 'age': 40 }] */ function callback(func, thisArg, guard) { if (guard && isIterateeCall(func, thisArg, guard)) { thisArg = null; } return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); } /** * Creates a function that returns `value`. * * @static * @memberOf _ * @category Utility * @param {*} value The value to return from the new function. * @returns {Function} Returns the new function. * @example * * var object = { 'user': 'fred' }; * var getter = _.constant(object); * * getter() === object; * // => true */ function constant(value) { return function() { return value; }; } /** * This method returns the first argument provided to it. * * @static * @memberOf _ * @category Utility * @param {*} value Any value. * @returns {*} Returns `value`. * @example * * var object = { 'user': 'fred' }; * * _.identity(object) === object; * // => true */ function identity(value) { return value; } /** * Creates a function that performs a deep comparison between a given object * and `source`, returning `true` if the given object has equivalent property * values, else `false`. * * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Objects are compared by * their own, not inherited, enumerable properties. For comparing a single * own or inherited property value see `_.matchesProperty`. * * @static * @memberOf _ * @category Utility * @param {Object} source The object of property values to match. * @returns {Function} Returns the new function. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': true }, * { 'user': 'fred', 'age': 40, 'active': false } * ]; * * _.filter(users, _.matches({ 'age': 40, 'active': false })); * // => [{ 'user': 'fred', 'age': 40, 'active': false }] */ function matches(source) { return baseMatches(baseClone(source, true)); } /** * A no-operation function that returns `undefined` regardless of the * arguments it receives. * * @static * @memberOf _ * @category Utility * @example * * var object = { 'user': 'fred' }; * * _.noop(object) === undefined; * // => true */ function noop() { // No operation performed. } /** * Creates a function that returns the property value at `path` on a * given object. * * @static * @memberOf _ * @category Utility * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new function. * @example * * var objects = [ * { 'a': { 'b': { 'c': 2 } } }, * { 'a': { 'b': { 'c': 1 } } } * ]; * * _.map(objects, _.property('a.b.c')); * // => [2, 1] * * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); * // => [1, 2] */ function property(path) { return isKey(path) ? baseProperty(path) : basePropertyDeep(path); } /** * Generates a unique ID. If `prefix` is provided the ID is appended to it. * * @static * @memberOf _ * @category Utility * @param {string} [prefix] The value to prefix the ID with. * @returns {string} Returns the unique ID. * @example * * _.uniqueId('contact_'); * // => 'contact_104' * * _.uniqueId(); * // => '105' */ function uniqueId(prefix) { var id = ++idCounter; return baseToString(prefix) + id; } /*------------------------------------------------------------------------*/ LazyWrapper.prototype = baseCreate(baseLodash.prototype); LazyWrapper.prototype.constructor = LazyWrapper; // Add functions to the `Set` cache. SetCache.prototype.push = cachePush; // Add functions that return wrapped values when chaining. lodash.assign = assign; lodash.bind = bind; lodash.callback = callback; lodash.constant = constant; lodash.defaults = defaults; lodash.defer = defer; lodash.difference = difference; lodash.forEach = forEach; lodash.intersection = intersection; lodash.invoke = invoke; lodash.keys = keys; lodash.keysIn = keysIn; lodash.map = map; lodash.matches = matches; lodash.omit = omit; lodash.pairs = pairs; lodash.partial = partial; lodash.partition = partition; lodash.property = property; lodash.restParam = restParam; lodash.values = values; // Add aliases. lodash.collect = map; lodash.each = forEach; lodash.extend = assign; lodash.iteratee = callback; /*------------------------------------------------------------------------*/ // Add functions that return unwrapped values when chaining. lodash.clone = clone; lodash.escapeRegExp = escapeRegExp; lodash.every = every; lodash.find = find; lodash.identity = identity; lodash.indexOf = indexOf; lodash.isArguments = isArguments; lodash.isArray = isArray; lodash.isElement = isElement; lodash.isEqual = isEqual; lodash.isFunction = isFunction; lodash.isNative = isNative; lodash.isNumber = isNumber; lodash.isObject = isObject; lodash.isPlainObject = isPlainObject; lodash.isString = isString; lodash.isTypedArray = isTypedArray; lodash.last = last; lodash.noop = noop; lodash.now = now; lodash.reduce = reduce; lodash.uniqueId = uniqueId; // Add aliases. lodash.all = every; lodash.eq = isEqual; lodash.detect = find; lodash.foldl = reduce; lodash.inject = reduce; /*------------------------------------------------------------------------*/ /** * The semantic version number. * * @static * @memberOf _ * @type string */ lodash.VERSION = VERSION; // Assign default placeholders. arrayEach(['bind', 'partial'], function(methodName) { lodash[methodName].placeholder = lodash; }); /*--------------------------------------------------------------------------*/ // Some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { // Expose lodash to the global object when an AMD loader is present to avoid // errors in cases where lodash is loaded by a script tag and not intended // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch for // more details. root._ = lodash; // Define as an anonymous module so, through path mapping, it can be // referenced as the "underscore" module. define(function() { return lodash; }); } // Check for `exports` after `define` in case a build optimizer adds an `exports` object. else if (freeExports && freeModule) { // Export for Node.js or RingoJS. if (moduleExports) { (freeModule.exports = lodash)._ = lodash; } // Export for Rhino with CommonJS support. else { freeExports._ = lodash; } } else { // Export for a browser or Rhino. root._ = lodash; } }.call(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],2:[function(_dereq_,module,exports){ /*! * EventEmitter2 * https://github.com/hij1nx/EventEmitter2 * * Copyright (c) 2013 hij1nx * Licensed under the MIT license. */ ;!function(undefined) { var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; }; var defaultMaxListeners = 10; function init() { this._events = {}; if (this._conf) { configure.call(this, this._conf); } } function configure(conf) { if (conf) { this._conf = conf; conf.delimiter && (this.delimiter = conf.delimiter); conf.maxListeners && (this._events.maxListeners = conf.maxListeners); conf.wildcard && (this.wildcard = conf.wildcard); conf.newListener && (this.newListener = conf.newListener); if (this.wildcard) { this.listenerTree = {}; } } } function EventEmitter(conf) { this._events = {}; this.newListener = false; configure.call(this, conf); } // // Attention, function return type now is array, always ! // It has zero elements if no any matches found and one or more // elements (leafs) if there are matches // function searchListenerTree(handlers, type, tree, i) { if (!tree) { return []; } var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached, typeLength = type.length, currentType = type[i], nextType = type[i+1]; if (i === typeLength && tree._listeners) { // // If at the end of the event(s) list and the tree has listeners // invoke those listeners. // if (typeof tree._listeners === 'function') { handlers && handlers.push(tree._listeners); return [tree]; } else { for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) { handlers && handlers.push(tree._listeners[leaf]); } return [tree]; } } if ((currentType === '*' || currentType === '**') || tree[currentType]) { // // If the event emitted is '*' at this part // or there is a concrete match at this patch // if (currentType === '*') { for (branch in tree) { if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1)); } } return listeners; } else if(currentType === '**') { endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*')); if(endReached && tree._listeners) { // The next element has a _listeners, add it to the handlers. listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength)); } for (branch in tree) { if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { if(branch === '*' || branch === '**') { if(tree[branch]._listeners && !endReached) { listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength)); } listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); } else if(branch === nextType) { listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2)); } else { // No match on this one, shift into the tree but not in the type array. listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); } } } return listeners; } listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1)); } xTree = tree['*']; if (xTree) { // // If the listener tree will allow any match for this part, // then recursively explore all branches of the tree // searchListenerTree(handlers, type, xTree, i+1); } xxTree = tree['**']; if(xxTree) { if(i < typeLength) { if(xxTree._listeners) { // If we have a listener on a '**', it will catch all, so add its handler. searchListenerTree(handlers, type, xxTree, typeLength); } // Build arrays of matching next branches and others. for(branch in xxTree) { if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) { if(branch === nextType) { // We know the next element will match, so jump twice. searchListenerTree(handlers, type, xxTree[branch], i+2); } else if(branch === currentType) { // Current node matches, move into the tree. searchListenerTree(handlers, type, xxTree[branch], i+1); } else { isolatedBranch = {}; isolatedBranch[branch] = xxTree[branch]; searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1); } } } } else if(xxTree._listeners) { // We have reached the end and still on a '**' searchListenerTree(handlers, type, xxTree, typeLength); } else if(xxTree['*'] && xxTree['*']._listeners) { searchListenerTree(handlers, type, xxTree['*'], typeLength); } } return listeners; } function growListenerTree(type, listener) { type = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); // // Looks for two consecutive '**', if so, don't add the event at all. // for(var i = 0, len = type.length; i+1 < len; i++) { if(type[i] === '**' && type[i+1] === '**') { return; } } var tree = this.listenerTree; var name = type.shift(); while (name) { if (!tree[name]) { tree[name] = {}; } tree = tree[name]; if (type.length === 0) { if (!tree._listeners) { tree._listeners = listener; } else if(typeof tree._listeners === 'function') { tree._listeners = [tree._listeners, listener]; } else if (isArray(tree._listeners)) { tree._listeners.push(listener); if (!tree._listeners.warned) { var m = defaultMaxListeners; if (typeof this._events.maxListeners !== 'undefined') { m = this._events.maxListeners; } if (m > 0 && tree._listeners.length > m) { tree._listeners.warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', tree._listeners.length); console.trace(); } } } return true; } name = type.shift(); } return true; } // By default EventEmitters will print a warning if more than // 10 listeners are added to it. This is a useful default which // helps finding memory leaks. // // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.delimiter = '.'; EventEmitter.prototype.setMaxListeners = function(n) { this._events || init.call(this); this._events.maxListeners = n; if (!this._conf) this._conf = {}; this._conf.maxListeners = n; }; EventEmitter.prototype.event = ''; EventEmitter.prototype.once = function(event, fn) { this.many(event, 1, fn); return this; }; EventEmitter.prototype.many = function(event, ttl, fn) { var self = this; if (typeof fn !== 'function') { throw new Error('many only accepts instances of Function'); } function listener() { if (--ttl === 0) { self.off(event, listener); } fn.apply(this, arguments); } listener._origin = fn; this.on(event, listener); return self; }; EventEmitter.prototype.emit = function() { this._events || init.call(this); var type = arguments[0]; if (type === 'newListener' && !this.newListener) { if (!this._events.newListener) { return false; } } // Loop through the *_all* functions and invoke them. if (this._all) { var l = arguments.length; var args = new Array(l - 1); for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; for (i = 0, l = this._all.length; i < l; i++) { this.event = type; this._all[i].apply(this, args); } } // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._all && !this._events.error && !(this.wildcard && this.listenerTree.error)) { if (arguments[1] instanceof Error) { throw arguments[1]; // Unhandled 'error' event } else { throw new Error("Uncaught, unspecified 'error' event."); } // not reachable: return false; } } var handler; if(this.wildcard) { handler = []; var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); searchListenerTree.call(this, handler, ns, this.listenerTree, 0); } else { handler = this._events[type]; } if (typeof handler === 'function') { this.event = type; if (arguments.length === 1) { handler.call(this); } else if (arguments.length > 1) switch (arguments.length) { case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: var l = arguments.length; var args = new Array(l - 1); for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } return true; } else if (handler) { var l = arguments.length; var args = new Array(l - 1); for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { this.event = type; listeners[i].apply(this, args); } return (listeners.length > 0) || !!this._all; } else { return !!this._all; } }; EventEmitter.prototype.on = function(type, listener) { if (typeof type === 'function') { this.onAny(type); return this; } if (typeof listener !== 'function') { throw new Error('on only accepts instances of Function'); } this._events || init.call(this); // To avoid recursion in the case that type == "newListeners"! Before // adding it to the listeners, first emit "newListeners". this.emit('newListener', type, listener); if(this.wildcard) { growListenerTree.call(this, type, listener); return this; } if (!this._events[type]) { // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; } else if(typeof this._events[type] === 'function') { // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; } else if (isArray(this._events[type])) { // If we've already got an array, just append. this._events[type].push(listener); // Check for listener leak if (!this._events[type].warned) { var m = defaultMaxListeners; if (typeof this._events.maxListeners !== 'undefined') { m = this._events.maxListeners; } if (m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); console.trace(); } } } return this; }; EventEmitter.prototype.onAny = function(fn) { if (typeof fn !== 'function') { throw new Error('onAny only accepts instances of Function'); } if(!this._all) { this._all = []; } // Add the function to the event listener collection. this._all.push(fn); return this; }; EventEmitter.prototype.addListener = EventEmitter.prototype.on; EventEmitter.prototype.off = function(type, listener) { if (typeof listener !== 'function') { throw new Error('removeListener only takes instances of Function'); } var handlers,leafs=[]; if(this.wildcard) { var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); } else { // does not use listeners(), so no side effect of creating _events[type] if (!this._events[type]) return this; handlers = this._events[type]; leafs.push({_listeners:handlers}); } for (var iLeaf=0; iLeaf 0) { fns = this._all; for(i = 0, l = fns.length; i < l; i++) { if(fn === fns[i]) { fns.splice(i, 1); return this; } } } else { this._all = []; } return this; }; EventEmitter.prototype.removeListener = EventEmitter.prototype.off; EventEmitter.prototype.removeAllListeners = function(type) { if (arguments.length === 0) { !this._events || init.call(this); return this; } if(this.wildcard) { var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); for (var iLeaf=0; iLeaf 0) newOp.attributes = attributes; return this.push(newOp); }; Delta.prototype['delete'] = function (length) { if (length <= 0) return this; return this.push({ 'delete': length }); }; Delta.prototype.retain = function (length, attributes) { if (length <= 0) return this; var newOp = { retain: length }; if (is.object(attributes) && Object.keys(attributes).length > 0) newOp.attributes = attributes; return this.push(newOp); }; Delta.prototype.push = function (newOp) { var index = this.ops.length; var lastOp = this.ops[index - 1]; newOp = op.clone(newOp); if (is.object(lastOp)) { if (is.number(newOp['delete']) && is.number(lastOp['delete'])) { this.ops[index - 1] = { 'delete': lastOp['delete'] + newOp['delete'] }; return this; } // Since it does not matter if we insert before or after deleting at the same index, // always prefer to insert first if (is.number(lastOp['delete']) && newOp.insert != null) { index -= 1; lastOp = this.ops[index - 1]; if (!is.object(lastOp)) { this.ops.unshift(newOp); return this; } } if (is.equal(newOp.attributes, lastOp.attributes)) { if (is.string(newOp.insert) && is.string(lastOp.insert)) { this.ops[index - 1] = { insert: lastOp.insert + newOp.insert }; if (is.object(newOp.attributes)) this.ops[index - 1].attributes = newOp.attributes return this; } else if (is.number(newOp.retain) && is.number(lastOp.retain)) { this.ops[index - 1] = { retain: lastOp.retain + newOp.retain }; if (is.object(newOp.attributes)) this.ops[index - 1].attributes = newOp.attributes return this; } } } if (index === this.ops.length) { this.ops.push(newOp); } else { this.ops.splice(index, 0, newOp); } return this; }; Delta.prototype.chop = function () { var lastOp = this.ops[this.ops.length - 1]; if (lastOp && lastOp.retain && !lastOp.attributes) { this.ops.pop(); } return this; }; Delta.prototype.length = function () { return this.ops.reduce(function (length, elem) { return length + op.length(elem); }, 0); }; Delta.prototype.slice = function (start, end) { start = start || 0; if (!is.number(end)) end = Infinity; var delta = new Delta(); var iter = op.iterator(this.ops); var index = 0; while (index < end && iter.hasNext()) { var nextOp; if (index < start) { nextOp = iter.next(start - index); } else { nextOp = iter.next(end - index); delta.push(nextOp); } index += op.length(nextOp); } return delta; }; Delta.prototype.compose = function (other) { var thisIter = op.iterator(this.ops); var otherIter = op.iterator(other.ops); var delta = new Delta(); while (thisIter.hasNext() || otherIter.hasNext()) { if (otherIter.peekType() === 'insert') { delta.push(otherIter.next()); } else if (thisIter.peekType() === 'delete') { delta.push(thisIter.next()); } else { var length = Math.min(thisIter.peekLength(), otherIter.peekLength()); var thisOp = thisIter.next(length); var otherOp = otherIter.next(length); if (is.number(otherOp.retain)) { var newOp = {}; if (is.number(thisOp.retain)) { newOp.retain = length; } else { newOp.insert = thisOp.insert; } // Preserve null when composing with a retain, otherwise remove it for inserts var attributes = op.attributes.compose(thisOp.attributes, otherOp.attributes, is.number(thisOp.retain)); if (attributes) newOp.attributes = attributes; delta.push(newOp); // Other op should be delete, we could be an insert or retain // Insert + delete cancels out } else if (is.number(otherOp['delete']) && is.number(thisOp.retain)) { delta.push(otherOp); } } } return delta.chop(); }; Delta.prototype.concat = function (other) { var delta = this.slice(); if (other.ops.length > 0) { delta.push(other.ops[0]); delta.ops = delta.ops.concat(other.ops.slice(1)); } return delta; }; Delta.prototype.diff = function (other) { var delta = new Delta(); if (this.ops === other.ops) { return delta; } var strings = [this.ops, other.ops].map(function (ops) { return ops.map(function (op) { if (op.insert != null) { return is.string(op.insert) ? op.insert : NULL_CHARACTER; } var prep = (ops === other.ops) ? 'on' : 'with'; throw new Error('diff() called ' + prep + ' non-document'); }).join(''); }); var diffResult = diff(strings[0], strings[1]); var thisIter = op.iterator(this.ops); var otherIter = op.iterator(other.ops); diffResult.forEach(function (component) { var length = component[1].length; while (length > 0) { var opLength = 0; switch (component[0]) { case diff.INSERT: opLength = Math.min(otherIter.peekLength(), length); delta.push(otherIter.next(opLength)); break; case diff.DELETE: opLength = Math.min(length, thisIter.peekLength()); thisIter.next(opLength); delta['delete'](opLength); break; case diff.EQUAL: opLength = Math.min(thisIter.peekLength(), otherIter.peekLength(), length); var thisOp = thisIter.next(opLength); var otherOp = otherIter.next(opLength); if (is.equal(thisOp.insert, otherOp.insert)) { delta.retain(opLength, op.attributes.diff(thisOp.attributes, otherOp.attributes)); } else { delta.push(otherOp)['delete'](opLength); } break; } length -= opLength; } }); return delta.chop(); }; Delta.prototype.transform = function (other, priority) { priority = !!priority; if (is.number(other)) { return this.transformPosition(other, priority); } var thisIter = op.iterator(this.ops); var otherIter = op.iterator(other.ops); var delta = new Delta(); while (thisIter.hasNext() || otherIter.hasNext()) { if (thisIter.peekType() === 'insert' && (priority || otherIter.peekType() !== 'insert')) { delta.retain(op.length(thisIter.next())); } else if (otherIter.peekType() === 'insert') { delta.push(otherIter.next()); } else { var length = Math.min(thisIter.peekLength(), otherIter.peekLength()); var thisOp = thisIter.next(length); var otherOp = otherIter.next(length); if (thisOp['delete']) { // Our delete either makes their delete redundant or removes their retain continue; } else if (otherOp['delete']) { delta.push(otherOp); } else { // We retain either their retain or insert delta.retain(length, op.attributes.transform(thisOp.attributes, otherOp.attributes, priority)); } } } return delta.chop(); }; Delta.prototype.transformPosition = function (index, priority) { priority = !!priority; var thisIter = op.iterator(this.ops); var offset = 0; while (thisIter.hasNext() && offset <= index) { var length = thisIter.peekLength(); var nextType = thisIter.peekType(); thisIter.next(); if (nextType === 'delete') { index -= Math.min(length, index - offset); continue; } else if (nextType === 'insert' && (offset < index || !priority)) { index += length; } offset += length; } return index; }; module.exports = Delta; },{"./is":4,"./op":5,"fast-diff":6}],4:[function(_dereq_,module,exports){ module.exports = { equal: function (a, b) { if (a === b) return true; if (a == null && b == null) return true; if (a == null || b == null) return false; if (!this.object(a) || !this.object(b)) return false; if (Object.keys(a).length != Object.keys(b).length) return false; for(var key in a) { // Only compare one level deep if (a[key] !== b[key]) return false; } return true; }, array: function (value) { return Array.isArray(value); }, number: function (value) { if (typeof value === 'number') return true; if (typeof value === 'object' && Object.prototype.toString.call(value) === '[object Number]') return true; return false; }, object: function (value) { if (!value) return false; return (typeof value === 'function' || typeof value === 'object'); }, string: function (value) { if (typeof value === 'string') return true; if (typeof value === 'object' && Object.prototype.toString.call(value) === '[object String]') return true; return false; } }; },{}],5:[function(_dereq_,module,exports){ var is = _dereq_('./is'); var lib = { attributes: { clone: function (attributes, keepNull) { if (!is.object(attributes)) return {}; return Object.keys(attributes).reduce(function (memo, key) { if (attributes[key] !== undefined && (attributes[key] !== null || keepNull)) { memo[key] = attributes[key]; } return memo; }, {}); }, compose: function (a, b, keepNull) { if (!is.object(a)) a = {}; if (!is.object(b)) b = {}; var attributes = this.clone(b, keepNull); for (var key in a) { if (a[key] !== undefined && b[key] === undefined) { attributes[key] = a[key]; } } return Object.keys(attributes).length > 0 ? attributes : undefined; }, diff: function(a, b) { if (!is.object(a)) a = {}; if (!is.object(b)) b = {}; var attributes = Object.keys(a).concat(Object.keys(b)).reduce(function (attributes, key) { if (a[key] !== b[key]) { attributes[key] = b[key] === undefined ? null : b[key]; } return attributes; }, {}); return Object.keys(attributes).length > 0 ? attributes : undefined; }, transform: function (a, b, priority) { if (!is.object(a)) return b; if (!is.object(b)) return undefined; if (!priority) return b; // b simply overwrites us without priority var attributes = Object.keys(b).reduce(function (attributes, key) { if (a[key] === undefined) attributes[key] = b[key]; // null is a valid value return attributes; }, {}); return Object.keys(attributes).length > 0 ? attributes : undefined; } }, clone: function (op) { var newOp = this.attributes.clone(op); if (is.object(newOp.attributes)) { newOp.attributes = this.attributes.clone(newOp.attributes, true); } return newOp; }, iterator: function (ops) { return new Iterator(ops); }, length: function (op) { if (is.number(op['delete'])) { return op['delete']; } else if (is.number(op.retain)) { return op.retain; } else { return is.string(op.insert) ? op.insert.length : 1; } } }; function Iterator(ops) { this.ops = ops; this.index = 0; this.offset = 0; }; Iterator.prototype.hasNext = function () { return this.peekLength() < Infinity; }; Iterator.prototype.next = function (length) { if (!length) length = Infinity; var nextOp = this.ops[this.index]; if (nextOp) { var offset = this.offset; var opLength = lib.length(nextOp) if (length >= opLength - offset) { length = opLength - offset; this.index += 1; this.offset = 0; } else { this.offset += length; } if (is.number(nextOp['delete'])) { return { 'delete': length }; } else { var retOp = {}; if (nextOp.attributes) { retOp.attributes = nextOp.attributes; } if (is.number(nextOp.retain)) { retOp.retain = length; } else if (is.string(nextOp.insert)) { retOp.insert = nextOp.insert.substr(offset, length); } else { // offset should === 0, length should === 1 retOp.insert = nextOp.insert; } return retOp; } } else { return { retain: Infinity }; } }; Iterator.prototype.peekLength = function () { if (this.ops[this.index]) { // Should never return 0 if our index is being managed correctly return lib.length(this.ops[this.index]) - this.offset; } else { return Infinity; } }; Iterator.prototype.peekType = function () { if (this.ops[this.index]) { if (is.number(this.ops[this.index]['delete'])) { return 'delete'; } else if (is.number(this.ops[this.index].retain)) { return 'retain'; } else { return 'insert'; } } return 'retain'; }; module.exports = lib; },{"./is":4}],6:[function(_dereq_,module,exports){ /** * This library modifies the diff-patch-match library by Neil Fraser * by removing the patch and match functionality and certain advanced * options in the diff function. The original license is as follows: * * === * * Diff Match and Patch * * Copyright 2006 Google Inc. * http://code.google.com/p/google-diff-match-patch/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * The data structure representing a diff is an array of tuples: * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] * which means: delete 'Hello', add 'Goodbye' and keep ' world.' */ var DIFF_DELETE = -1; var DIFF_INSERT = 1; var DIFF_EQUAL = 0; /** * Find the differences between two texts. Simplifies the problem by stripping * any common prefix or suffix off the texts before diffing. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @return {Array} Array of diff tuples. */ function diff_main(text1, text2) { // Check for equality (speedup). if (text1 == text2) { if (text1) { return [[DIFF_EQUAL, text1]]; } return []; } // Trim off common prefix (speedup). var commonlength = diff_commonPrefix(text1, text2); var commonprefix = text1.substring(0, commonlength); text1 = text1.substring(commonlength); text2 = text2.substring(commonlength); // Trim off common suffix (speedup). commonlength = diff_commonSuffix(text1, text2); var commonsuffix = text1.substring(text1.length - commonlength); text1 = text1.substring(0, text1.length - commonlength); text2 = text2.substring(0, text2.length - commonlength); // Compute the diff on the middle block. var diffs = diff_compute_(text1, text2); // Restore the prefix and suffix. if (commonprefix) { diffs.unshift([DIFF_EQUAL, commonprefix]); } if (commonsuffix) { diffs.push([DIFF_EQUAL, commonsuffix]); } diff_cleanupMerge(diffs); return diffs; }; /** * Find the differences between two texts. Assumes that the texts do not * have any common prefix or suffix. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @return {Array} Array of diff tuples. */ function diff_compute_(text1, text2) { var diffs; if (!text1) { // Just add some text (speedup). return [[DIFF_INSERT, text2]]; } if (!text2) { // Just delete some text (speedup). return [[DIFF_DELETE, text1]]; } var longtext = text1.length > text2.length ? text1 : text2; var shorttext = text1.length > text2.length ? text2 : text1; var i = longtext.indexOf(shorttext); if (i != -1) { // Shorter text is inside the longer text (speedup). diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]]; // Swap insertions for deletions if diff is reversed. if (text1.length > text2.length) { diffs[0][0] = diffs[2][0] = DIFF_DELETE; } return diffs; } if (shorttext.length == 1) { // Single character string. // After the previous speedup, the character can't be an equality. return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; } // Check to see if the problem can be split in two. var hm = diff_halfMatch_(text1, text2); if (hm) { // A half-match was found, sort out the return data. var text1_a = hm[0]; var text1_b = hm[1]; var text2_a = hm[2]; var text2_b = hm[3]; var mid_common = hm[4]; // Send both pairs off for separate processing. var diffs_a = diff_main(text1_a, text2_a); var diffs_b = diff_main(text1_b, text2_b); // Merge the results. return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b); } return diff_bisect_(text1, text2); }; /** * Find the 'middle snake' of a diff, split the problem in two * and return the recursively constructed diff. * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @return {Array} Array of diff tuples. * @private */ function diff_bisect_(text1, text2) { // Cache the text lengths to prevent multiple calls. var text1_length = text1.length; var text2_length = text2.length; var max_d = Math.ceil((text1_length + text2_length) / 2); var v_offset = max_d; var v_length = 2 * max_d; var v1 = new Array(v_length); var v2 = new Array(v_length); // Setting all elements to -1 is faster in Chrome & Firefox than mixing // integers and undefined. for (var x = 0; x < v_length; x++) { v1[x] = -1; v2[x] = -1; } v1[v_offset + 1] = 0; v2[v_offset + 1] = 0; var delta = text1_length - text2_length; // If the total number of characters is odd, then the front path will collide // with the reverse path. var front = (delta % 2 != 0); // Offsets for start and end of k loop. // Prevents mapping of space beyond the grid. var k1start = 0; var k1end = 0; var k2start = 0; var k2end = 0; for (var d = 0; d < max_d; d++) { // Walk the front path one step. for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { var k1_offset = v_offset + k1; var x1; if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) { x1 = v1[k1_offset + 1]; } else { x1 = v1[k1_offset - 1] + 1; } var y1 = x1 - k1; while (x1 < text1_length && y1 < text2_length && text1.charAt(x1) == text2.charAt(y1)) { x1++; y1++; } v1[k1_offset] = x1; if (x1 > text1_length) { // Ran off the right of the graph. k1end += 2; } else if (y1 > text2_length) { // Ran off the bottom of the graph. k1start += 2; } else if (front) { var k2_offset = v_offset + delta - k1; if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) { // Mirror x2 onto top-left coordinate system. var x2 = text1_length - v2[k2_offset]; if (x1 >= x2) { // Overlap detected. return diff_bisectSplit_(text1, text2, x1, y1); } } } } // Walk the reverse path one step. for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { var k2_offset = v_offset + k2; var x2; if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) { x2 = v2[k2_offset + 1]; } else { x2 = v2[k2_offset - 1] + 1; } var y2 = x2 - k2; while (x2 < text1_length && y2 < text2_length && text1.charAt(text1_length - x2 - 1) == text2.charAt(text2_length - y2 - 1)) { x2++; y2++; } v2[k2_offset] = x2; if (x2 > text1_length) { // Ran off the left of the graph. k2end += 2; } else if (y2 > text2_length) { // Ran off the top of the graph. k2start += 2; } else if (!front) { var k1_offset = v_offset + delta - k2; if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) { var x1 = v1[k1_offset]; var y1 = v_offset + x1 - k1_offset; // Mirror x2 onto top-left coordinate system. x2 = text1_length - x2; if (x1 >= x2) { // Overlap detected. return diff_bisectSplit_(text1, text2, x1, y1); } } } } } // Diff took too long and hit the deadline or // number of diffs equals number of characters, no commonality at all. return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; }; /** * Given the location of the 'middle snake', split the diff in two parts * and recurse. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @param {number} x Index of split point in text1. * @param {number} y Index of split point in text2. * @return {Array} Array of diff tuples. */ function diff_bisectSplit_(text1, text2, x, y) { var text1a = text1.substring(0, x); var text2a = text2.substring(0, y); var text1b = text1.substring(x); var text2b = text2.substring(y); // Compute both diffs serially. var diffs = diff_main(text1a, text2a); var diffsb = diff_main(text1b, text2b); return diffs.concat(diffsb); }; /** * Determine the common prefix of two strings. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {number} The number of characters common to the start of each * string. */ function diff_commonPrefix(text1, text2) { // Quick check for common null cases. if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) { return 0; } // Binary search. // Performance analysis: http://neil.fraser.name/news/2007/10/09/ var pointermin = 0; var pointermax = Math.min(text1.length, text2.length); var pointermid = pointermax; var pointerstart = 0; while (pointermin < pointermid) { if (text1.substring(pointerstart, pointermid) == text2.substring(pointerstart, pointermid)) { pointermin = pointermid; pointerstart = pointermin; } else { pointermax = pointermid; } pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); } return pointermid; }; /** * Determine the common suffix of two strings. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {number} The number of characters common to the end of each string. */ function diff_commonSuffix(text1, text2) { // Quick check for common null cases. if (!text1 || !text2 || text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) { return 0; } // Binary search. // Performance analysis: http://neil.fraser.name/news/2007/10/09/ var pointermin = 0; var pointermax = Math.min(text1.length, text2.length); var pointermid = pointermax; var pointerend = 0; while (pointermin < pointermid) { if (text1.substring(text1.length - pointermid, text1.length - pointerend) == text2.substring(text2.length - pointermid, text2.length - pointerend)) { pointermin = pointermid; pointerend = pointermin; } else { pointermax = pointermid; } pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); } return pointermid; }; /** * Do the two texts share a substring which is at least half the length of the * longer text? * This speedup can produce non-minimal diffs. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {Array.} Five element Array, containing the prefix of * text1, the suffix of text1, the prefix of text2, the suffix of * text2 and the common middle. Or null if there was no match. */ function diff_halfMatch_(text1, text2) { var longtext = text1.length > text2.length ? text1 : text2; var shorttext = text1.length > text2.length ? text2 : text1; if (longtext.length < 4 || shorttext.length * 2 < longtext.length) { return null; // Pointless. } /** * Does a substring of shorttext exist within longtext such that the substring * is at least half the length of longtext? * Closure, but does not reference any external variables. * @param {string} longtext Longer string. * @param {string} shorttext Shorter string. * @param {number} i Start index of quarter length substring within longtext. * @return {Array.} Five element Array, containing the prefix of * longtext, the suffix of longtext, the prefix of shorttext, the suffix * of shorttext and the common middle. Or null if there was no match. * @private */ function diff_halfMatchI_(longtext, shorttext, i) { // Start with a 1/4 length substring at position i as a seed. var seed = longtext.substring(i, i + Math.floor(longtext.length / 4)); var j = -1; var best_common = ''; var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b; while ((j = shorttext.indexOf(seed, j + 1)) != -1) { var prefixLength = diff_commonPrefix(longtext.substring(i), shorttext.substring(j)); var suffixLength = diff_commonSuffix(longtext.substring(0, i), shorttext.substring(0, j)); if (best_common.length < suffixLength + prefixLength) { best_common = shorttext.substring(j - suffixLength, j) + shorttext.substring(j, j + prefixLength); best_longtext_a = longtext.substring(0, i - suffixLength); best_longtext_b = longtext.substring(i + prefixLength); best_shorttext_a = shorttext.substring(0, j - suffixLength); best_shorttext_b = shorttext.substring(j + prefixLength); } } if (best_common.length * 2 >= longtext.length) { return [best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b, best_common]; } else { return null; } } // First check if the second quarter is the seed for a half-match. var hm1 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 4)); // Check again based on the third quarter. var hm2 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 2)); var hm; if (!hm1 && !hm2) { return null; } else if (!hm2) { hm = hm1; } else if (!hm1) { hm = hm2; } else { // Both matched. Select the longest. hm = hm1[4].length > hm2[4].length ? hm1 : hm2; } // A half-match was found, sort out the return data. var text1_a, text1_b, text2_a, text2_b; if (text1.length > text2.length) { text1_a = hm[0]; text1_b = hm[1]; text2_a = hm[2]; text2_b = hm[3]; } else { text2_a = hm[0]; text2_b = hm[1]; text1_a = hm[2]; text1_b = hm[3]; } var mid_common = hm[4]; return [text1_a, text1_b, text2_a, text2_b, mid_common]; }; /** * Reorder and merge like edit sections. Merge equalities. * Any edit section can move as long as it doesn't cross an equality. * @param {Array} diffs Array of diff tuples. */ function diff_cleanupMerge(diffs) { diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end. var pointer = 0; var count_delete = 0; var count_insert = 0; var text_delete = ''; var text_insert = ''; var commonlength; while (pointer < diffs.length) { switch (diffs[pointer][0]) { case DIFF_INSERT: count_insert++; text_insert += diffs[pointer][1]; pointer++; break; case DIFF_DELETE: count_delete++; text_delete += diffs[pointer][1]; pointer++; break; case DIFF_EQUAL: // Upon reaching an equality, check for prior redundancies. if (count_delete + count_insert > 1) { if (count_delete !== 0 && count_insert !== 0) { // Factor out any common prefixies. commonlength = diff_commonPrefix(text_insert, text_delete); if (commonlength !== 0) { if ((pointer - count_delete - count_insert) > 0 && diffs[pointer - count_delete - count_insert - 1][0] == DIFF_EQUAL) { diffs[pointer - count_delete - count_insert - 1][1] += text_insert.substring(0, commonlength); } else { diffs.splice(0, 0, [DIFF_EQUAL, text_insert.substring(0, commonlength)]); pointer++; } text_insert = text_insert.substring(commonlength); text_delete = text_delete.substring(commonlength); } // Factor out any common suffixies. commonlength = diff_commonSuffix(text_insert, text_delete); if (commonlength !== 0) { diffs[pointer][1] = text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1]; text_insert = text_insert.substring(0, text_insert.length - commonlength); text_delete = text_delete.substring(0, text_delete.length - commonlength); } } // Delete the offending records and add the merged ones. if (count_delete === 0) { diffs.splice(pointer - count_insert, count_delete + count_insert, [DIFF_INSERT, text_insert]); } else if (count_insert === 0) { diffs.splice(pointer - count_delete, count_delete + count_insert, [DIFF_DELETE, text_delete]); } else { diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert, [DIFF_DELETE, text_delete], [DIFF_INSERT, text_insert]); } pointer = pointer - count_delete - count_insert + (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1; } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) { // Merge this equality with the previous one. diffs[pointer - 1][1] += diffs[pointer][1]; diffs.splice(pointer, 1); } else { pointer++; } count_insert = 0; count_delete = 0; text_delete = ''; text_insert = ''; break; } } if (diffs[diffs.length - 1][1] === '') { diffs.pop(); // Remove the dummy entry at the end. } // Second pass: look for single edits surrounded on both sides by equalities // which can be shifted sideways to eliminate an equality. // e.g: ABAC -> ABAC var changes = false; pointer = 1; // Intentionally ignore the first and last element (don't need checking). while (pointer < diffs.length - 1) { if (diffs[pointer - 1][0] == DIFF_EQUAL && diffs[pointer + 1][0] == DIFF_EQUAL) { // This is a single edit surrounded by equalities. if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) { // Shift the edit over the previous equality. diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length); diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; diffs.splice(pointer - 1, 1); changes = true; } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == diffs[pointer + 1][1]) { // Shift the edit over the next equality. diffs[pointer - 1][1] += diffs[pointer + 1][1]; diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1]; diffs.splice(pointer + 1, 1); changes = true; } } pointer++; } // If shifts were made, the diff needs reordering and another shift sweep. if (changes) { diff_cleanupMerge(diffs); } }; var diff = diff_main; diff.INSERT = DIFF_INSERT; diff.DELETE = DIFF_DELETE; diff.EQUAL = DIFF_EQUAL; module.exports = diff; },{}],7:[function(_dereq_,module,exports){ module.exports={"version":"0.20.1"} },{}],8:[function(_dereq_,module,exports){ var Delta, Document, Format, Line, LinkedList, Normalizer, _, dom; _ = _dereq_('lodash'); Delta = _dereq_('rich-text/lib/delta'); dom = _dereq_('../lib/dom'); Format = _dereq_('./format'); Line = _dereq_('./line'); LinkedList = _dereq_('../lib/linked-list'); Normalizer = _dereq_('./normalizer'); Document = (function() { function Document(root, options) { this.root = root; if (options == null) { options = {}; } this.normalizer = new Normalizer(); this.formats = {}; _.each(options.formats, _.bind(this.addFormat, this)); this.setHTML(this.root.innerHTML); } Document.prototype.addFormat = function(name, config) { if (!_.isObject(config)) { config = Format.FORMATS[name]; } if (this.formats[name] != null) { console.warn('Overwriting format', name, this.formats[name]); } this.formats[name] = new Format(config); return this.normalizer.addFormat(config); }; Document.prototype.appendLine = function(lineNode) { return this.insertLineBefore(lineNode, null); }; Document.prototype.findLeafAt = function(index, inclusive) { var line, offset, ref; ref = this.findLineAt(index), line = ref[0], offset = ref[1]; if (line != null) { return line.findLeafAt(offset, inclusive); } else { return [void 0, offset]; } }; Document.prototype.findLine = function(node) { var line; while ((node != null) && (dom.BLOCK_TAGS[node.tagName] == null)) { node = node.parentNode; } line = node != null ? dom(node).data(Line.DATA_KEY) : void 0; if ((line != null ? line.node : void 0) === node) { return line; } else { return void 0; } }; Document.prototype.findLineAt = function(index) { var curLine, length; if (!(this.lines.length > 0)) { return [void 0, index]; } length = this.toDelta().length(); if (index === length) { return [this.lines.last, this.lines.last.length]; } if (index > length) { return [void 0, index - length]; } curLine = this.lines.first; while (curLine != null) { if (index < curLine.length) { return [curLine, index]; } index -= curLine.length; curLine = curLine.next; } return [void 0, index]; }; Document.prototype.getHTML = function() { return this.root.innerHTML.replace(/\>\s+\ <'); }; Document.prototype.insertLineBefore = function(newLineNode, refLine) { var line; line = new Line(this, newLineNode); if (refLine != null) { if (!dom(newLineNode.parentNode).isElement()) { this.root.insertBefore(newLineNode, refLine.node); } this.lines.insertAfter(refLine.prev, line); } else { if (!dom(newLineNode.parentNode).isElement()) { this.root.appendChild(newLineNode); } this.lines.append(line); } return line; }; Document.prototype.mergeLines = function(line, lineToMerge) { if (lineToMerge.length > 1) { if (line.length === 1) { dom(line.leaves.last.node).remove(); } _.each(dom(lineToMerge.node).childNodes(), function(child) { if (child.tagName !== dom.DEFAULT_BREAK_TAG) { return line.node.appendChild(child); } }); } this.removeLine(lineToMerge); return line.rebuild(); }; Document.prototype.optimizeLines = function() { return _.each(this.lines.toArray(), function(line, i) { line.optimize(); return true; }); }; Document.prototype.rebuild = function() { var lineNode, lines, results; lines = this.lines.toArray(); lineNode = this.root.firstChild; if ((lineNode != null) && (dom.LIST_TAGS[lineNode.tagName] != null)) { lineNode = lineNode.firstChild; } _.each(lines, (function(_this) { return function(line, index) { var newLine, ref; while (line.node !== lineNode) { if (line.node.parentNode === _this.root || ((ref = line.node.parentNode) != null ? ref.parentNode : void 0) === _this.root) { lineNode = _this.normalizer.normalizeLine(lineNode); newLine = _this.insertLineBefore(lineNode, line); lineNode = dom(lineNode).nextLineNode(_this.root); } else { return _this.removeLine(line); } } if (line.outerHTML !== lineNode.outerHTML) { line.node = _this.normalizer.normalizeLine(line.node); line.rebuild(); } return lineNode = dom(lineNode).nextLineNode(_this.root); }; })(this)); results = []; while (lineNode != null) { lineNode = this.normalizer.normalizeLine(lineNode); this.appendLine(lineNode); results.push(lineNode = dom(lineNode).nextLineNode(this.root)); } return results; }; Document.prototype.removeLine = function(line) { if (line.node.parentNode != null) { if (dom.LIST_TAGS[line.node.parentNode.tagName] && line.node.parentNode.childNodes.length === 1) { dom(line.node.parentNode).remove(); } else { dom(line.node).remove(); } } return this.lines.remove(line); }; Document.prototype.setHTML = function(html) { html = Normalizer.stripComments(html); html = Normalizer.stripWhitespace(html); this.root.innerHTML = html; this.lines = new LinkedList(); return this.rebuild(); }; Document.prototype.splitLine = function(line, offset) { var lineNode1, lineNode2, newLine, ref; offset = Math.min(offset, line.length - 1); ref = dom(line.node).split(offset, true), lineNode1 = ref[0], lineNode2 = ref[1]; line.node = lineNode1; line.rebuild(); newLine = this.insertLineBefore(lineNode2, line.next); newLine.formats = _.clone(line.formats); newLine.resetContent(); return newLine; }; Document.prototype.toDelta = function() { var delta, lines; lines = this.lines.toArray(); delta = new Delta(); _.each(lines, function(line) { return _.each(line.delta.ops, function(op) { return delta.push(op); }); }); return delta; }; return Document; })(); module.exports = Document; },{"../lib/dom":17,"../lib/linked-list":18,"./format":10,"./line":12,"./normalizer":13,"lodash":1,"rich-text/lib/delta":3}],9:[function(_dereq_,module,exports){ var Delta, Document, Editor, Line, Selection, _, dom; _ = _dereq_('lodash'); Delta = _dereq_('rich-text/lib/delta'); dom = _dereq_('../lib/dom'); Document = _dereq_('./document'); Line = _dereq_('./line'); Selection = _dereq_('./selection'); Editor = (function() { Editor.sources = { API: 'api', SILENT: 'silent', USER: 'user' }; function Editor(root, quill, options) { this.root = root; this.quill = quill; this.options = options != null ? options : {}; this.root.setAttribute('id', this.options.id); this.doc = new Document(this.root, this.options); this.delta = this.doc.toDelta(); this.length = this.delta.length(); this.selection = new Selection(this.doc, this.quill); this.timer = setInterval(_.bind(this.checkUpdate, this), this.options.pollInterval); this.savedRange = null; this.quill.on("selection-change", (function(_this) { return function(range) { return _this.savedRange = range; }; })(this)); if (!this.options.readOnly) { this.enable(); } } Editor.prototype.destroy = function() { return clearInterval(this.timer); }; Editor.prototype.disable = function() { return this.enable(false); }; Editor.prototype.enable = function(enabled) { if (enabled == null) { enabled = true; } return this.root.setAttribute('contenteditable', enabled); }; Editor.prototype.applyDelta = function(delta, source) { var localDelta; localDelta = this._update(); if (localDelta) { delta = localDelta.transform(delta, true); localDelta = delta.transform(localDelta, false); } if (delta.ops.length > 0) { delta = this._trackDelta((function(_this) { return function() { var index; index = 0; _.each(delta.ops, function(op) { if (_.isString(op.insert)) { _this._insertAt(index, op.insert, op.attributes); return index += op.insert.length; } else if (_.isNumber(op.insert)) { _this._insertEmbed(index, op.attributes); return index += 1; } else if (_.isNumber(op["delete"])) { return _this._deleteAt(index, op["delete"]); } else if (_.isNumber(op.retain)) { _.each(op.attributes, function(value, name) { return _this._formatAt(index, op.retain, name, value); }); return index += op.retain; } }); return _this.selection.shiftAfter(0, 0, _.bind(_this.doc.optimizeLines, _this.doc)); }; })(this)); this.delta = this.doc.toDelta(); this.length = this.delta.length(); this.innerHTML = this.root.innerHTML; if (delta && source !== Editor.sources.SILENT) { this.quill.emit(this.quill.constructor.events.TEXT_CHANGE, delta, source); } } if (localDelta && localDelta.ops.length > 0 && source !== Editor.sources.SILENT) { return this.quill.emit(this.quill.constructor.events.TEXT_CHANGE, localDelta, Editor.sources.USER); } }; Editor.prototype.checkUpdate = function(source) { var delta; if (source == null) { source = 'user'; } if (this.root.parentNode == null) { return clearInterval(this.timer); } delta = this._update(); if (delta) { this.delta = this.delta.compose(delta); this.length = this.delta.length(); this.quill.emit(this.quill.constructor.events.TEXT_CHANGE, delta, source); } if (delta) { source = Editor.sources.SILENT; } return this.selection.update(source); }; Editor.prototype.focus = function() { if (this.selection.range != null) { return this.selection.setRange(this.selection.range); } else { return this.root.focus(); } }; Editor.prototype.getBounds = function(index) { var bounds, containerBounds, leaf, offset, range, ref, side; this.checkUpdate(); ref = this.doc.findLeafAt(index, true), leaf = ref[0], offset = ref[1]; if (leaf == null) { return null; } containerBounds = this.root.parentNode.getBoundingClientRect(); side = 'left'; if (leaf.length === 0) { bounds = leaf.node.parentNode.getBoundingClientRect(); } else if (dom.VOID_TAGS[leaf.node.tagName]) { bounds = leaf.node.getBoundingClientRect(); if (offset === 1) { side = 'right'; } } else { range = document.createRange(); if (offset < leaf.length) { range.setStart(leaf.node, offset); range.setEnd(leaf.node, offset + 1); } else { range.setStart(leaf.node, offset - 1); range.setEnd(leaf.node, offset); side = 'right'; } bounds = range.getBoundingClientRect(); } return { height: bounds.height, left: bounds[side] - containerBounds.left, top: bounds.top - containerBounds.top }; }; Editor.prototype._deleteAt = function(index, length) { if (length <= 0) { return; } return this.selection.shiftAfter(index, -1 * length, (function(_this) { return function() { var curLine, deleteLength, firstLine, mergeFirstLine, nextLine, offset, ref; ref = _this.doc.findLineAt(index), firstLine = ref[0], offset = ref[1]; curLine = firstLine; mergeFirstLine = firstLine.length - offset <= length && offset > 0; while ((curLine != null) && length > 0) { nextLine = curLine.next; deleteLength = Math.min(curLine.length - offset, length); if (offset === 0 && length >= curLine.length) { _this.doc.removeLine(curLine); } else { curLine.deleteText(offset, deleteLength); } length -= deleteLength; curLine = nextLine; offset = 0; } if (mergeFirstLine && firstLine.next) { return _this.doc.mergeLines(firstLine, firstLine.next); } }; })(this)); }; Editor.prototype._formatAt = function(index, length, name, value) { return this.selection.shiftAfter(index, 0, (function(_this) { return function() { var formatLength, line, offset, ref, results; ref = _this.doc.findLineAt(index), line = ref[0], offset = ref[1]; results = []; while ((line != null) && length > 0) { formatLength = Math.min(length, line.length - offset - 1); line.formatText(offset, formatLength, name, value); length -= formatLength; if (length > 0) { line.format(name, value); } length -= 1; offset = 0; results.push(line = line.next); } return results; }; })(this)); }; Editor.prototype._insertEmbed = function(index, attributes) { return this.selection.shiftAfter(index, 1, (function(_this) { return function() { var line, offset, ref; ref = _this.doc.findLineAt(index), line = ref[0], offset = ref[1]; return line.insertEmbed(offset, attributes); }; })(this)); }; Editor.prototype._insertAt = function(index, text, formatting) { if (formatting == null) { formatting = {}; } return this.selection.shiftAfter(index, text.length, (function(_this) { return function() { var line, lineTexts, offset, ref; text = text.replace(/\r\n?/g, '\n'); lineTexts = text.split('\n'); ref = _this.doc.findLineAt(index), line = ref[0], offset = ref[1]; return _.each(lineTexts, function(lineText, i) { var nextLine; if ((line == null) || line.length <= offset) { if (i < lineTexts.length - 1 || lineText.length > 0) { line = _this.doc.appendLine(document.createElement(dom.DEFAULT_BLOCK_TAG)); offset = 0; line.insertText(offset, lineText, formatting); line.format(formatting); nextLine = null; } } else { line.insertText(offset, lineText, formatting); if (i < lineTexts.length - 1) { nextLine = _this.doc.splitLine(line, offset + lineText.length); _.each(_.defaults({}, formatting, line.formats), function(value, format) { return line.format(format, formatting[format]); }); offset = 0; } } return line = nextLine; }); }; })(this)); }; Editor.prototype._trackDelta = function(fn) { var ignored, newDelta, newIndex, newLeftDelta, newRightDelta, oldIndex, oldLeftDelta, oldRightDelta, ref, ref1; oldIndex = (ref = this.savedRange) != null ? ref.start : void 0; fn(); newDelta = this.doc.toDelta(); this.savedRange = this.selection.getRange(); newIndex = (ref1 = this.savedRange) != null ? ref1.start : void 0; try { if ((oldIndex != null) && (newIndex != null) && oldIndex <= this.delta.length() && newIndex <= newDelta.length()) { oldRightDelta = this.delta.slice(oldIndex); newRightDelta = newDelta.slice(newIndex); if (_.isEqual(oldRightDelta.ops, newRightDelta.ops)) { oldLeftDelta = this.delta.slice(0, oldIndex); newLeftDelta = newDelta.slice(0, newIndex); return oldLeftDelta.diff(newLeftDelta); } } } catch (_error) { ignored = _error; } return this.delta.diff(newDelta); }; Editor.prototype._update = function() { var delta; if (this.innerHTML === this.root.innerHTML) { return false; } delta = this._trackDelta((function(_this) { return function() { _this.selection.preserve(_.bind(_this.doc.rebuild, _this.doc)); return _this.selection.shiftAfter(0, 0, _.bind(_this.doc.optimizeLines, _this.doc)); }; })(this)); this.innerHTML = this.root.innerHTML; if (delta.ops.length > 0) { return delta; } else { return false; } }; return Editor; })(); module.exports = Editor; },{"../lib/dom":17,"./document":8,"./line":12,"./selection":14,"lodash":1,"rich-text/lib/delta":3}],10:[function(_dereq_,module,exports){ var Format, _, dom; _ = _dereq_('lodash'); dom = _dereq_('../lib/dom'); Format = (function() { Format.types = { LINE: 'line', EMBED: 'embed' }; Format.FORMATS = { bold: { tag: 'B', prepare: 'bold' }, italic: { tag: 'I', prepare: 'italic' }, underline: { tag: 'U', prepare: 'underline' }, strike: { tag: 'S', prepare: 'strikeThrough' }, color: { style: 'color', "default": 'rgb(0, 0, 0)', prepare: 'foreColor' }, background: { style: 'backgroundColor', "default": 'rgb(255, 255, 255)', prepare: 'backColor' }, font: { style: 'fontFamily', "default": "'Helvetica', 'Arial', sans-serif", prepare: 'fontName' }, size: { style: 'fontSize', "default": '13px', prepare: function(value) { return document.execCommand('fontSize', false, dom.convertFontSize(value)); } }, link: { tag: 'A', add: function(node, value) { node.setAttribute('href', value); return node; }, remove: function(node) { node.removeAttribute('href'); return node; }, value: function(node) { return node.getAttribute('href'); } }, image: { type: Format.types.EMBED, tag: 'IMG', attribute: 'src' }, align: { type: Format.types.LINE, style: 'textAlign', "default": 'left' }, bullet: { type: Format.types.LINE, exclude: 'list', parentTag: 'UL', tag: 'LI' }, list: { type: Format.types.LINE, exclude: 'bullet', parentTag: 'OL', tag: 'LI' } }; function Format(config) { this.config = config; } Format.prototype.add = function(node, value) { var formatNode, inline, parentNode, ref, ref1; if (!value) { return this.remove(node); } if (this.value(node) === value) { return node; } if (_.isString(this.config.parentTag)) { parentNode = node.parentNode; if (parentNode.tagName !== this.config.parentTag) { parentNode = document.createElement(this.config.parentTag); dom(node).wrap(parentNode); } if (node.parentNode.tagName === ((ref = node.parentNode.previousSibling) != null ? ref.tagName : void 0)) { dom(node.parentNode.previousSibling).merge(node.parentNode); } if (node.parentNode.tagName === ((ref1 = node.parentNode.nextSibling) != null ? ref1.tagName : void 0)) { dom(node.parentNode).merge(node.parentNode.nextSibling); } } if (_.isString(this.config.tag) && node.tagName !== this.config.tag) { formatNode = document.createElement(this.config.tag); if (dom.VOID_TAGS[formatNode.tagName] != null) { if (node.parentNode != null) { dom(node).replace(formatNode); } node = formatNode; } else if (this.isType(Format.types.LINE)) { node = dom(node).switchTag(this.config.tag).get(); } else { dom(node).wrap(formatNode); node = formatNode; } } if (_.isString(this.config.style) || _.isString(this.config.attribute) || _.isString(this.config["class"])) { if (_.isString(this.config["class"])) { node = this.remove(node); } if (dom(node).isTextNode()) { inline = document.createElement(dom.DEFAULT_INLINE_TAG); dom(node).wrap(inline); node = inline; } if (_.isString(this.config.style)) { if (value !== this.config["default"]) { node.style[this.config.style] = value; } } if (_.isString(this.config.attribute)) { node.setAttribute(this.config.attribute, value); } if (_.isString(this.config["class"])) { dom(node).addClass(this.config["class"] + value); } } if (_.isFunction(this.config.add)) { node = this.config.add(node, value); } return node; }; Format.prototype.isType = function(type) { return type === this.config.type; }; Format.prototype.match = function(node) { var c, i, len, ref, ref1; if (!dom(node).isElement()) { return false; } if (_.isString(this.config.parentTag) && ((ref = node.parentNode) != null ? ref.tagName : void 0) !== this.config.parentTag) { return false; } if (_.isString(this.config.tag) && node.tagName !== this.config.tag) { return false; } if (_.isString(this.config.style) && (!node.style[this.config.style] || node.style[this.config.style] === this.config["default"])) { return false; } if (_.isString(this.config.attribute) && !node.hasAttribute(this.config.attribute)) { return false; } if (_.isString(this.config["class"])) { ref1 = dom(node).classes(); for (i = 0, len = ref1.length; i < len; i++) { c = ref1[i]; if (c.indexOf(this.config["class"]) === 0) { return true; } } return false; } return true; }; Format.prototype.prepare = function(value) { if (_.isString(this.config.prepare)) { return document.execCommand(this.config.prepare, false, value); } else if (_.isFunction(this.config.prepare)) { return this.config.prepare(value); } }; Format.prototype.remove = function(node) { var c, i, len, ref; if (!this.match(node)) { return node; } if (_.isString(this.config.style)) { node.style[this.config.style] = ''; if (!node.getAttribute('style')) { node.removeAttribute('style'); } } if (_.isString(this.config.attribute)) { node.removeAttribute(this.config.attribute); } if (_.isString(this.config["class"])) { ref = dom(node).classes(); for (i = 0, len = ref.length; i < len; i++) { c = ref[i]; if (c.indexOf(this.config["class"]) === 0) { dom(node).removeClass(c); } } } if (_.isString(this.config.tag)) { if (this.isType(Format.types.LINE)) { if (_.isString(this.config.parentTag)) { if (node.previousSibling != null) { dom(node).splitBefore(node.parentNode.parentNode); } if (node.nextSibling != null) { dom(node.nextSibling).splitBefore(node.parentNode.parentNode); } } node = dom(node).switchTag(dom.DEFAULT_BLOCK_TAG).get(); } else if (this.isType(Format.types.EMBED)) { dom(node).remove(); return void 0; } else { node = dom(node).switchTag(dom.DEFAULT_INLINE_TAG).get(); } } if (_.isString(this.config.parentTag)) { dom(node.parentNode).unwrap(); } if (_.isFunction(this.config.remove)) { node = this.config.remove(node); } if (node.tagName === dom.DEFAULT_INLINE_TAG && !node.hasAttributes()) { node = dom(node).unwrap(); } return node; }; Format.prototype.value = function(node) { var c, i, len, ref; if (!this.match(node)) { return void 0; } if (this.config.value) { return this.config.value(node); } if (_.isString(this.config.attribute)) { return node.getAttribute(this.config.attribute) || void 0; } else if (_.isString(this.config.style)) { return node.style[this.config.style] || void 0; } else if (_.isString(this.config["class"])) { ref = dom(node).classes(); for (i = 0, len = ref.length; i < len; i++) { c = ref[i]; if (c.indexOf(this.config["class"]) === 0) { return c.slice(this.config["class"].length); } } } else if (_.isString(this.config.tag)) { return true; } return void 0; }; return Format; })(); module.exports = Format; },{"../lib/dom":17,"lodash":1}],11:[function(_dereq_,module,exports){ var Format, Leaf, LinkedList, _, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; _ = _dereq_('lodash'); dom = _dereq_('../lib/dom'); Format = _dereq_('./format'); LinkedList = _dereq_('../lib/linked-list'); Leaf = (function(superClass) { extend(Leaf, superClass); Leaf.DATA_KEY = 'leaf'; Leaf.isLeafNode = function(node) { return dom(node).isTextNode() || (node.firstChild == null); }; function Leaf(node1, formats) { this.node = node1; this.formats = _.clone(formats); this.text = dom(this.node).text(); this.length = this.text.length; dom(this.node).data(Leaf.DATA_KEY, this); } Leaf.prototype.deleteText = function(offset, length) { var textNode; if (!(length > 0)) { return; } this.text = this.text.slice(0, offset) + this.text.slice(offset + length); this.length = this.text.length; if (dom.EMBED_TAGS[this.node.tagName] != null) { textNode = document.createTextNode(this.text); dom(textNode).data(Leaf.DATA_KEY, this); return this.node = dom(this.node).replace(textNode).get(); } else { return dom(this.node).text(this.text); } }; Leaf.prototype.insertText = function(offset, text) { var textNode; this.text = this.text.slice(0, offset) + text + this.text.slice(offset); if (dom(this.node).isTextNode()) { dom(this.node).text(this.text); } else { textNode = document.createTextNode(text); dom(textNode).data(Leaf.DATA_KEY, this); if (this.node.tagName === dom.DEFAULT_BREAK_TAG) { this.node = dom(this.node).replace(textNode).get(); } else { this.node.appendChild(textNode); this.node = textNode; } } return this.length = this.text.length; }; return Leaf; })(LinkedList.Node); module.exports = Leaf; },{"../lib/dom":17,"../lib/linked-list":18,"./format":10,"lodash":1}],12:[function(_dereq_,module,exports){ var Delta, Format, Leaf, Line, LinkedList, Normalizer, _, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; _ = _dereq_('lodash'); Delta = _dereq_('rich-text/lib/delta'); dom = _dereq_('../lib/dom'); Format = _dereq_('./format'); Leaf = _dereq_('./leaf'); Line = _dereq_('./line'); LinkedList = _dereq_('../lib/linked-list'); Normalizer = _dereq_('./normalizer'); Line = (function(superClass) { extend(Line, superClass); Line.DATA_KEY = 'line'; function Line(doc, node1) { this.doc = doc; this.node = node1; this.formats = {}; this.rebuild(); Line.__super__.constructor.call(this, this.node); } Line.prototype.buildLeaves = function(node, formats) { return _.each(dom(node).childNodes(), (function(_this) { return function(node) { var nodeFormats; node = _this.doc.normalizer.normalizeNode(node); nodeFormats = _.clone(formats); _.each(_this.doc.formats, function(format, name) { if (!format.isType(Format.types.LINE) && format.match(node)) { return nodeFormats[name] = format.value(node); } }); if (Leaf.isLeafNode(node)) { return _this.leaves.append(new Leaf(node, nodeFormats)); } else { return _this.buildLeaves(node, nodeFormats); } }; })(this)); }; Line.prototype.deleteText = function(offset, length) { var deleteLength, leaf, ref; if (!(length > 0)) { return; } ref = this.findLeafAt(offset), leaf = ref[0], offset = ref[1]; while ((leaf != null) && length > 0) { deleteLength = Math.min(length, leaf.length - offset); leaf.deleteText(offset, deleteLength); length -= deleteLength; leaf = leaf.next; offset = 0; } return this.rebuild(); }; Line.prototype.findLeaf = function(leafNode) { if (leafNode != null) { return dom(leafNode).data(Leaf.DATA_KEY); } else { return void 0; } }; Line.prototype.findLeafAt = function(offset, inclusive) { var leaf; if (inclusive == null) { inclusive = false; } if (offset >= this.length - 1) { return [this.leaves.last, this.leaves.last.length]; } leaf = this.leaves.first; while (leaf != null) { if (offset < leaf.length || (offset === leaf.length && inclusive)) { return [leaf, offset]; } offset -= leaf.length; leaf = leaf.next; } return [this.leaves.last, offset - this.leaves.last.length]; }; Line.prototype.format = function(name, value) { var formats; if (_.isObject(name)) { formats = name; } else { formats = {}; formats[name] = value; } _.each(formats, (function(_this) { return function(value, name) { var excludeFormat, format; format = _this.doc.formats[name]; if (format == null) { return; } if (format.isType(Format.types.LINE)) { if (format.config.exclude && _this.formats[format.config.exclude]) { excludeFormat = _this.doc.formats[format.config.exclude]; if (excludeFormat != null) { _this.node = excludeFormat.remove(_this.node); delete _this.formats[format.config.exclude]; } } _this.node = format.add(_this.node, value); } if (value) { return _this.formats[name] = value; } else { return delete _this.formats[name]; } }; })(this)); return this.resetContent(); }; Line.prototype.formatText = function(offset, length, name, value) { var format, leaf, leafOffset, leftNode, nextLeaf, ref, ref1, ref2, rightNode, targetNode; ref = this.findLeafAt(offset), leaf = ref[0], leafOffset = ref[1]; format = this.doc.formats[name]; if (!((format != null) && format.config.type !== Format.types.LINE)) { return; } while ((leaf != null) && length > 0) { nextLeaf = leaf.next; if ((value && leaf.formats[name] !== value) || (!value && (leaf.formats[name] != null))) { targetNode = leaf.node; if (leaf.formats[name] != null) { dom(targetNode).splitBefore(this.node); while (!format.match(targetNode)) { targetNode = targetNode.parentNode; } dom(targetNode).split(leaf.length); } if (leafOffset > 0) { ref1 = dom(targetNode).split(leafOffset), leftNode = ref1[0], targetNode = ref1[1]; } if (leaf.length > leafOffset + length) { ref2 = dom(targetNode).split(length), targetNode = ref2[0], rightNode = ref2[1]; } format.add(targetNode, value); } length -= leaf.length - leafOffset; leafOffset = 0; leaf = nextLeaf; } return this.rebuild(); }; Line.prototype._insert = function(offset, node, formats) { var leaf, leafOffset, nextNode, prevNode, ref, ref1; ref = this.findLeafAt(offset), leaf = ref[0], leafOffset = ref[1]; node = _.reduce(formats, (function(_this) { return function(node, value, name) { var format; format = _this.doc.formats[name]; if ((format != null) && !format.isType(Format.types.LINE)) { node = format.add(node, value); } return node; }; })(this), node); ref1 = dom(leaf.node).split(leafOffset), prevNode = ref1[0], nextNode = ref1[1]; if (nextNode) { nextNode = dom(nextNode).splitBefore(this.node).get(); } this.node.insertBefore(node, nextNode); return this.rebuild(); }; Line.prototype.insertEmbed = function(offset, attributes) { var formatName, leaf, leafOffset, nextNode, node, prevNode, ref, ref1; ref = this.findLeafAt(offset), leaf = ref[0], leafOffset = ref[1]; ref1 = dom(leaf.node).split(leafOffset), prevNode = ref1[0], nextNode = ref1[1]; formatName = _.find(Object.keys(attributes), (function(_this) { return function(name) { return _this.doc.formats[name].isType(Format.types.EMBED); }; })(this)); node = this.doc.formats[formatName].add({}, attributes[formatName]); attributes = _.clone(attributes); delete attributes[formatName]; return this._insert(offset, node, attributes); }; Line.prototype.insertText = function(offset, text, formats) { var leaf, leafOffset, ref; if (formats == null) { formats = {}; } if (!(text.length > 0)) { return; } ref = this.findLeafAt(offset), leaf = ref[0], leafOffset = ref[1]; if (_.isEqual(leaf.formats, formats)) { leaf.insertText(leafOffset, text); return this.resetContent(); } else { return this._insert(offset, document.createTextNode(text), formats); } }; Line.prototype.optimize = function() { Normalizer.optimizeLine(this.node); return this.rebuild(); }; Line.prototype.rebuild = function(force) { if (force == null) { force = false; } if (!force && (this.outerHTML != null) && this.outerHTML === this.node.outerHTML) { if (_.all(this.leaves.toArray(), (function(_this) { return function(leaf) { return dom(leaf.node).isAncestor(_this.node); }; })(this))) { return false; } } this.node = this.doc.normalizer.normalizeNode(this.node); if (dom(this.node).length() === 0 && !this.node.querySelector(dom.DEFAULT_BREAK_TAG)) { this.node.appendChild(document.createElement(dom.DEFAULT_BREAK_TAG)); } this.leaves = new LinkedList(); this.formats = _.reduce(this.doc.formats, (function(_this) { return function(formats, format, name) { if (format.isType(Format.types.LINE)) { if (format.match(_this.node)) { formats[name] = format.value(_this.node); } else { delete formats[name]; } } return formats; }; })(this), this.formats); this.buildLeaves(this.node, {}); this.resetContent(); return true; }; Line.prototype.resetContent = function() { dom(this.node).data(Line.DATA_KEY, this); this.outerHTML = this.node.outerHTML; this.length = 1; this.delta = new Delta(); _.each(this.leaves.toArray(), (function(_this) { return function(leaf) { _this.length += leaf.length; if (dom.EMBED_TAGS[leaf.node.tagName] != null) { return _this.delta.insert(1, leaf.formats); } else { return _this.delta.insert(leaf.text, leaf.formats); } }; })(this)); return this.delta.insert('\n', this.formats); }; return Line; })(LinkedList.Node); module.exports = Line; },{"../lib/dom":17,"../lib/linked-list":18,"./format":10,"./leaf":11,"./line":12,"./normalizer":13,"lodash":1,"rich-text/lib/delta":3}],13:[function(_dereq_,module,exports){ var Normalizer, _, camelize, dom; _ = _dereq_('lodash'); dom = _dereq_('../lib/dom'); camelize = function(str) { str = str.replace(/(?:^|[-_])(\w)/g, function(i, c) { if (c) { return c.toUpperCase(); } else { return ''; } }); return str.charAt(0).toLowerCase() + str.slice(1); }; Normalizer = (function() { Normalizer.ALIASES = { 'STRONG': 'B', 'EM': 'I', 'DEL': 'S', 'STRIKE': 'S' }; Normalizer.ATTRIBUTES = { 'color': 'color', 'face': 'fontFamily', 'size': 'fontSize' }; function Normalizer() { this.whitelist = { styles: {}, tags: {} }; this.whitelist.tags[dom.DEFAULT_BREAK_TAG] = true; this.whitelist.tags[dom.DEFAULT_BLOCK_TAG] = true; this.whitelist.tags[dom.DEFAULT_INLINE_TAG] = true; } Normalizer.prototype.addFormat = function(config) { if (config.tag != null) { this.whitelist.tags[config.tag] = true; } if (config.parentTag != null) { this.whitelist.tags[config.parentTag] = true; } if (config.style != null) { return this.whitelist.styles[config.style] = true; } }; Normalizer.prototype.normalizeLine = function(lineNode) { lineNode = Normalizer.wrapInline(lineNode); lineNode = Normalizer.handleBreaks(lineNode); if (lineNode.tagName === 'LI') { Normalizer.flattenList(lineNode); } lineNode = Normalizer.pullBlocks(lineNode); lineNode = this.normalizeNode(lineNode); Normalizer.unwrapText(lineNode); if ((lineNode != null) && (dom.LIST_TAGS[lineNode.tagName] != null)) { lineNode = lineNode.firstChild; } return lineNode; }; Normalizer.prototype.normalizeNode = function(node) { if (dom(node).isTextNode()) { return node; } _.each(Normalizer.ATTRIBUTES, function(style, attribute) { var value; if (node.hasAttribute(attribute)) { value = node.getAttribute(attribute); if (attribute === 'size') { value = dom.convertFontSize(value); } node.style[style] = value; return node.removeAttribute(attribute); } }); if (node.style.fontWeight === 'bold' || node.style.fontWeight > 500) { node.style.fontWeight = ''; dom(node).wrap(document.createElement('b')); node = node.parentNode; } this.whitelistStyles(node); return this.whitelistTags(node); }; Normalizer.prototype.whitelistStyles = function(node) { var original, styles; original = dom(node).styles(); styles = _.omit(original, (function(_this) { return function(value, key) { return _this.whitelist.styles[camelize(key)] == null; }; })(this)); if (Object.keys(styles).length < Object.keys(original).length) { if (Object.keys(styles).length > 0) { return dom(node).styles(styles, true); } else { return node.removeAttribute('style'); } } }; Normalizer.prototype.whitelistTags = function(node) { if (!dom(node).isElement()) { return node; } if (Normalizer.ALIASES[node.tagName] != null) { node = dom(node).switchTag(Normalizer.ALIASES[node.tagName]).get(); } else if (this.whitelist.tags[node.tagName] == null) { if (dom.BLOCK_TAGS[node.tagName] != null) { node = dom(node).switchTag(dom.DEFAULT_BLOCK_TAG).get(); } else if (!node.hasAttributes() && (node.firstChild != null)) { node = dom(node).unwrap(); } else { node = dom(node).switchTag(dom.DEFAULT_INLINE_TAG).get(); } } return node; }; Normalizer.flattenList = function(listNode) { var innerItems, innerLists, ref; ref = listNode.nextSibling; innerItems = _.map(listNode.querySelectorAll('li')); innerItems.forEach(function(item) { listNode.parentNode.insertBefore(item, ref); return ref = item.nextSibling; }); innerLists = _.map(listNode.querySelectorAll(Object.keys(dom.LIST_TAGS).join(','))); return innerLists.forEach(function(list) { return dom(list).remove(); }); }; Normalizer.handleBreaks = function(lineNode) { var breaks; breaks = _.map(lineNode.querySelectorAll(dom.DEFAULT_BREAK_TAG)); _.each(breaks, (function(_this) { return function(br) { if ((br.nextSibling != null) && (!dom.isIE(10) || (br.previousSibling != null))) { return dom(br.nextSibling).splitBefore(lineNode.parentNode); } }; })(this)); return lineNode; }; Normalizer.optimizeLine = function(lineNode) { var lineNodeLength, node, nodes, results; lineNode.normalize(); lineNodeLength = dom(lineNode).length(); nodes = dom(lineNode).descendants(); results = []; while (nodes.length > 0) { node = nodes.pop(); if ((node != null ? node.parentNode : void 0) == null) { continue; } if (dom.EMBED_TAGS[node.tagName] != null) { continue; } if (node.tagName === dom.DEFAULT_BREAK_TAG) { if (lineNodeLength !== 0) { results.push(dom(node).remove()); } else { results.push(void 0); } } else if (dom(node).length() === 0) { nodes.push(node.nextSibling); results.push(dom(node).unwrap()); } else if ((node.previousSibling != null) && node.tagName === node.previousSibling.tagName) { if (_.isEqual(dom(node).attributes(), dom(node.previousSibling).attributes())) { nodes.push(node.firstChild); results.push(dom(node.previousSibling).merge(node)); } else { results.push(void 0); } } else { results.push(void 0); } } return results; }; Normalizer.pullBlocks = function(lineNode) { var curNode; curNode = lineNode.firstChild; while (curNode != null) { if ((dom.BLOCK_TAGS[curNode.tagName] != null) && curNode.tagName !== 'LI') { dom(curNode).isolate(lineNode.parentNode); if ((dom.LIST_TAGS[curNode.tagName] == null) || !curNode.firstChild) { dom(curNode).unwrap(); Normalizer.pullBlocks(lineNode); } else { dom(curNode.parentNode).unwrap(); if (lineNode.parentNode == null) { lineNode = curNode; } } break; } curNode = curNode.nextSibling; } return lineNode; }; Normalizer.stripComments = function(html) { return html.replace(//g, ''); }; Normalizer.stripWhitespace = function(html) { html = html.trim(); html = html.replace(/(\r?\n|\r)+/g, ' '); html = html.replace(/\>\s+\<'); return html; }; Normalizer.wrapInline = function(lineNode) { var blockNode, nextNode; if (dom.BLOCK_TAGS[lineNode.tagName] != null) { return lineNode; } blockNode = document.createElement(dom.DEFAULT_BLOCK_TAG); lineNode.parentNode.insertBefore(blockNode, lineNode); while ((lineNode != null) && (dom.BLOCK_TAGS[lineNode.tagName] == null)) { nextNode = lineNode.nextSibling; blockNode.appendChild(lineNode); lineNode = nextNode; } return blockNode; }; Normalizer.unwrapText = function(lineNode) { var spans; spans = _.map(lineNode.querySelectorAll(dom.DEFAULT_INLINE_TAG)); return _.each(spans, function(span) { if (!span.hasAttributes()) { return dom(span).unwrap(); } }); }; return Normalizer; })(); module.exports = Normalizer; },{"../lib/dom":17,"lodash":1}],14:[function(_dereq_,module,exports){ var Leaf, Normalizer, Range, Selection, _, dom; _ = _dereq_('lodash'); dom = _dereq_('../lib/dom'); Leaf = _dereq_('./leaf'); Normalizer = _dereq_('./normalizer'); Range = _dereq_('../lib/range'); Selection = (function() { function Selection(doc, emitter) { this.doc = doc; this.emitter = emitter; this.focus = false; this.range = new Range(0, 0); this.nullDelay = false; this.update('silent'); } Selection.prototype.checkFocus = function() { return document.activeElement === this.doc.root; }; Selection.prototype.getRange = function(ignoreFocus) { var end, nativeRange, start; if (ignoreFocus == null) { ignoreFocus = false; } if (this.checkFocus()) { nativeRange = this._getNativeRange(); if (nativeRange == null) { return null; } start = this._positionToIndex(nativeRange.startContainer, nativeRange.startOffset); if (nativeRange.startContainer === nativeRange.endContainer && nativeRange.startOffset === nativeRange.endOffset) { end = start; } else { end = this._positionToIndex(nativeRange.endContainer, nativeRange.endOffset); } return new Range(Math.min(start, end), Math.max(start, end)); } else if (ignoreFocus) { return this.range; } else { return null; } }; Selection.prototype.preserve = function(fn) { var endNode, endOffset, nativeRange, ref, ref1, ref2, ref3, startNode, startOffset; nativeRange = this._getNativeRange(); if ((nativeRange != null) && this.checkFocus()) { ref = this._encodePosition(nativeRange.startContainer, nativeRange.startOffset), startNode = ref[0], startOffset = ref[1]; ref1 = this._encodePosition(nativeRange.endContainer, nativeRange.endOffset), endNode = ref1[0], endOffset = ref1[1]; fn(); ref2 = this._decodePosition(startNode, startOffset), startNode = ref2[0], startOffset = ref2[1]; ref3 = this._decodePosition(endNode, endOffset), endNode = ref3[0], endOffset = ref3[1]; return this._setNativeRange(startNode, startOffset, endNode, endOffset); } else { return fn(); } }; Selection.prototype.scrollIntoView = function() { var containerBounds, containerHeight, editor, endBounds, line, offset, ref, ref1, startBounds; if (!this.range) { return; } editor = this.emitter.editor; startBounds = editor.getBounds(this.range.start); endBounds = this.range.isCollapsed() ? startBounds : editor.getBounds(this.range.end); containerBounds = editor.root.parentNode.getBoundingClientRect(); containerHeight = containerBounds.bottom - containerBounds.top; if (containerHeight < endBounds.top + endBounds.height) { ref = editor.doc.findLineAt(this.range.end), line = ref[0], offset = ref[1]; return line.node.scrollIntoView(false); } else if (startBounds.top < 0) { ref1 = editor.doc.findLineAt(this.range.start), line = ref1[0], offset = ref1[1]; return line.node.scrollIntoView(); } }; Selection.prototype.setRange = function(range, source) { var endNode, endOffset, ref, ref1, ref2, startNode, startOffset; if (range != null) { ref = this._indexToPosition(range.start), startNode = ref[0], startOffset = ref[1]; if (range.isCollapsed()) { ref1 = [startNode, startOffset], endNode = ref1[0], endOffset = ref1[1]; } else { ref2 = this._indexToPosition(range.end), endNode = ref2[0], endOffset = ref2[1]; } this._setNativeRange(startNode, startOffset, endNode, endOffset); } else { this._setNativeRange(null); } return this.update(source); }; Selection.prototype.shiftAfter = function(index, length, fn) { var range; range = this.getRange(); fn(); if (range != null) { range.shift(index, length); return this.setRange(range, 'silent'); } }; Selection.prototype.update = function(source) { var emit, focus, range, toEmit; focus = this.checkFocus(); range = this.getRange(true); emit = source !== 'silent' && (!Range.compare(range, this.range) || focus !== this.focus); toEmit = focus ? range : null; if (toEmit === null && source === 'user' && !this.nullDelay) { return this.nullDelay = true; } else { this.nullDelay = false; this.range = range; this.focus = focus; if (emit) { return this.emitter.emit(this.emitter.constructor.events.SELECTION_CHANGE, toEmit, source); } } }; Selection.prototype._decodePosition = function(node, offset) { var childIndex; if (dom(node).isElement()) { childIndex = dom(node.parentNode).childNodes().indexOf(node); offset += childIndex; node = node.parentNode; } return [node, offset]; }; Selection.prototype._encodePosition = function(node, offset) { var text; while (true) { if (dom(node).isTextNode() || node.tagName === dom.DEFAULT_BREAK_TAG || (dom.EMBED_TAGS[node.tagName] != null)) { return [node, offset]; } else if (offset < node.childNodes.length) { node = node.childNodes[offset]; offset = 0; } else if (node.childNodes.length === 0) { if (this.doc.normalizer.whitelist.tags[node.tagName] == null) { text = document.createTextNode(''); node.appendChild(text); node = text; } return [node, 0]; } else { node = node.lastChild; if (dom(node).isElement()) { if (node.tagName === dom.DEFAULT_BREAK_TAG || (dom.EMBED_TAGS[node.tagName] != null)) { return [node, 1]; } else { offset = node.childNodes.length; } } else { return [node, dom(node).length()]; } } } }; Selection.prototype._getNativeRange = function() { var range, selection; selection = document.getSelection(); if ((selection != null ? selection.rangeCount : void 0) > 0) { range = selection.getRangeAt(0); if (dom(range.startContainer).isAncestor(this.doc.root, true)) { if (range.startContainer === range.endContainer || dom(range.endContainer).isAncestor(this.doc.root, true)) { return range; } } } return null; }; Selection.prototype._indexToPosition = function(index) { var leaf, offset, ref; if (this.doc.lines.length === 0) { return [this.doc.root, 0]; } ref = this.doc.findLeafAt(index, true), leaf = ref[0], offset = ref[1]; return this._decodePosition(leaf.node, offset); }; Selection.prototype._positionToIndex = function(node, offset) { var leaf, leafNode, leafOffset, line, lineOffset, ref; if (dom.isIE(10) && node.tagName === 'BR' && offset === 1) { offset = 0; } ref = this._encodePosition(node, offset), leafNode = ref[0], offset = ref[1]; line = this.doc.findLine(leafNode); if (line == null) { return 0; } leaf = line.findLeaf(leafNode); lineOffset = 0; while (line.prev != null) { line = line.prev; lineOffset += line.length; } if (leaf == null) { return lineOffset; } leafOffset = 0; while (leaf.prev != null) { leaf = leaf.prev; leafOffset += leaf.length; } return lineOffset + leafOffset + offset; }; Selection.prototype._setNativeRange = function(startNode, startOffset, endNode, endOffset) { var nativeRange, selection; selection = document.getSelection(); if (!selection) { return; } if (startNode != null) { if (!this.checkFocus()) { this.doc.root.focus(); } nativeRange = this._getNativeRange(); if ((nativeRange == null) || startNode !== nativeRange.startContainer || startOffset !== nativeRange.startOffset || endNode !== nativeRange.endContainer || endOffset !== nativeRange.endOffset) { selection.removeAllRanges(); nativeRange = document.createRange(); nativeRange.setStart(startNode, startOffset); nativeRange.setEnd(endNode, endOffset); return selection.addRange(nativeRange); } } else { selection.removeAllRanges(); this.doc.root.blur(); if (dom.isIE(11) && !dom.isIE(9)) { return document.body.focus(); } } }; return Selection; })(); module.exports = Selection; },{"../lib/dom":17,"../lib/range":20,"./leaf":11,"./normalizer":13,"lodash":1}],15:[function(_dereq_,module,exports){ _dereq_('./modules/authorship'); _dereq_('./modules/image-tooltip'); _dereq_('./modules/keyboard'); _dereq_('./modules/link-tooltip'); _dereq_('./modules/multi-cursor'); _dereq_('./modules/paste-manager'); _dereq_('./modules/toolbar'); _dereq_('./modules/tooltip'); _dereq_('./modules/undo-manager'); module.exports = _dereq_('./quill'); },{"./modules/authorship":21,"./modules/image-tooltip":22,"./modules/keyboard":23,"./modules/link-tooltip":24,"./modules/multi-cursor":25,"./modules/paste-manager":26,"./modules/toolbar":27,"./modules/tooltip":28,"./modules/undo-manager":29,"./quill":30}],16:[function(_dereq_,module,exports){ var ColorPicker, Picker, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; dom = _dereq_('./dom'); Picker = _dereq_('./picker'); ColorPicker = (function(superClass) { extend(ColorPicker, superClass); function ColorPicker() { ColorPicker.__super__.constructor.apply(this, arguments); dom(this.container).addClass('ql-color-picker'); } ColorPicker.prototype.buildItem = function(picker, option, index) { var item; item = ColorPicker.__super__.buildItem.call(this, picker, option, index); item.style.backgroundColor = option.value; return item; }; return ColorPicker; })(Picker); module.exports = ColorPicker; },{"./dom":17,"./picker":19}],17:[function(_dereq_,module,exports){ var SelectWrapper, Wrapper, _, dom, lastKeyEvent, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; _ = _dereq_('lodash'); lastKeyEvent = null; Wrapper = (function() { function Wrapper(node1) { this.node = node1; this.trigger = bind(this.trigger, this); } Wrapper.prototype.addClass = function(cssClass) { if (this.hasClass(cssClass)) { return; } if (this.node.classList != null) { this.node.classList.add(cssClass); } else if (this.node.className != null) { this.node.className = (this.node.className + ' ' + cssClass).trim(); } return this; }; Wrapper.prototype.attributes = function(attributes) { var attr, i, j, len, ref, value; if (attributes) { _.each(attributes, (function(_this) { return function(value, name) { return _this.node.setAttribute(name, value); }; })(this)); return this; } else { if (this.node.attributes == null) { return {}; } attributes = {}; ref = this.node.attributes; for (i = j = 0, len = ref.length; j < len; i = ++j) { value = ref[i]; attr = this.node.attributes[i]; attributes[attr.name] = attr.value; } return attributes; } }; Wrapper.prototype.child = function(offset) { var child, length; child = this.node.firstChild; length = dom(child).length(); while (child != null) { if (offset < length) { break; } offset -= length; child = child.nextSibling; length = dom(child).length(); } if (child == null) { child = this.node.lastChild; offset = dom(child).length(); } return [child, offset]; }; Wrapper.prototype.childNodes = function() { return _.map(this.node.childNodes); }; Wrapper.prototype.classes = function() { return this.node.className.split(/\s+/); }; Wrapper.prototype.data = function(key, value) { var ref; if (value != null) { if (this.node['ql-data'] == null) { this.node['ql-data'] = {}; } this.node['ql-data'][key] = value; return this; } else { return (ref = this.node['ql-data']) != null ? ref[key] : void 0; } }; Wrapper.prototype.descendants = function() { return _.map(this.node.getElementsByTagName('*')); }; Wrapper.prototype.get = function() { return this.node; }; Wrapper.prototype.hasClass = function(cssClass) { if (this.node.classList != null) { return this.node.classList.contains(cssClass); } else if (this.node.className != null) { return this.classes().indexOf(cssClass) > -1; } return false; }; Wrapper.prototype.isAncestor = function(ancestor, inclusive) { var node; if (inclusive == null) { inclusive = false; } if (ancestor === this.node) { return inclusive; } node = this.node; while (node) { if (node === ancestor) { return true; } node = node.parentNode; } return false; }; Wrapper.prototype.isElement = function() { var ref; return ((ref = this.node) != null ? ref.nodeType : void 0) === dom.ELEMENT_NODE; }; Wrapper.prototype.isTextNode = function() { var ref; return ((ref = this.node) != null ? ref.nodeType : void 0) === dom.TEXT_NODE; }; Wrapper.prototype.isolate = function(root) { if (this.node.nextSibling != null) { dom(this.node.nextSibling).splitBefore(root); } this.splitBefore(root); return this; }; Wrapper.prototype.length = function() { var length; if (this.node == null) { return 0; } length = this.text().length; if (this.isElement()) { length += this.node.querySelectorAll(Object.keys(dom.EMBED_TAGS).join(',')).length; } return length; }; Wrapper.prototype.merge = function(node) { var $node; $node = dom(node); if (this.isElement()) { $node.moveChildren(this.node); this.normalize(); } else { this.text(this.text() + $node.text()); } $node.remove(); return this; }; Wrapper.prototype.moveChildren = function(newParent) { _.each(this.childNodes(), function(child) { return newParent.appendChild(child); }); return this; }; Wrapper.prototype.nextLineNode = function(root) { var nextNode; nextNode = this.node.nextSibling; if ((nextNode == null) && this.node.parentNode !== root) { nextNode = this.node.parentNode.nextSibling; } if ((nextNode != null) && (dom.LIST_TAGS[nextNode.tagName] != null)) { nextNode = nextNode.firstChild; } return nextNode; }; Wrapper.prototype.normalize = function() { var $node, curNode, followingNode, nextNode; curNode = this.node.firstChild; while (curNode != null) { nextNode = curNode.nextSibling; $node = dom(curNode); if ((nextNode != null) && dom(nextNode).isTextNode()) { if ($node.text().length === 0) { $node.remove(); } else if ($node.isTextNode()) { followingNode = nextNode.nextSibling; $node.merge(nextNode); nextNode = followingNode; } } curNode = nextNode; } return this; }; Wrapper.prototype.on = function(eventName, listener) { this.node.addEventListener(eventName, (function(_this) { return function(event) { var arg, propagate; arg = lastKeyEvent && (eventName === 'keydown' || eventName === 'keyup') ? lastKeyEvent : event; propagate = listener.call(_this.node, arg); if (!propagate) { event.preventDefault(); event.stopPropagation(); } return propagate; }; })(this)); return this; }; Wrapper.prototype.remove = function() { var ref; if ((ref = this.node.parentNode) != null) { ref.removeChild(this.node); } this.node = null; return null; }; Wrapper.prototype.removeClass = function(cssClass) { var classArray; if (!this.hasClass(cssClass)) { return; } if (this.node.classList != null) { this.node.classList.remove(cssClass); } else if (this.node.className != null) { classArray = this.classes(); classArray.splice(classArray.indexOf(cssClass), 1); this.node.className = classArray.join(' '); } if (!this.node.getAttribute('class')) { this.node.removeAttribute('class'); } return this; }; Wrapper.prototype.replace = function(newNode) { this.node.parentNode.replaceChild(newNode, this.node); this.node = newNode; return this; }; Wrapper.prototype.splitBefore = function(root, force) { var nextNode, parentClone, parentNode, refNode; if (force == null) { force = false; } if (this.node === root || this.node.parentNode === root) { return this; } if ((this.node.previousSibling != null) || force) { parentNode = this.node.parentNode; parentClone = parentNode.cloneNode(false); parentNode.parentNode.insertBefore(parentClone, parentNode.nextSibling); refNode = this.node; while (refNode != null) { nextNode = refNode.nextSibling; parentClone.appendChild(refNode); refNode = nextNode; } return dom(parentClone).splitBefore(root); } else { return dom(this.node.parentNode).splitBefore(root); } }; Wrapper.prototype.split = function(offset, force) { var after, child, childLeft, childRight, left, nextRight, nodeLength, ref, ref1, right; if (force == null) { force = false; } nodeLength = this.length(); offset = Math.max(0, offset); offset = Math.min(offset, nodeLength); if (!(force || offset !== 0)) { return [this.node.previousSibling, this.node, false]; } if (!(force || offset !== nodeLength)) { return [this.node, this.node.nextSibling, false]; } if (this.node.nodeType === dom.TEXT_NODE) { after = this.node.splitText(offset); return [this.node, after, true]; } else { left = this.node; right = this.node.cloneNode(false); this.node.parentNode.insertBefore(right, left.nextSibling); ref = this.child(offset), child = ref[0], offset = ref[1]; ref1 = dom(child).split(offset), childLeft = ref1[0], childRight = ref1[1]; while (childRight !== null) { nextRight = childRight.nextSibling; right.appendChild(childRight); childRight = nextRight; } return [left, right, true]; } }; Wrapper.prototype.styles = function(styles, overwrite) { var obj, styleString; if (overwrite == null) { overwrite = false; } if (styles) { if (!overwrite) { styles = _.defaults(styles, this.styles()); } styleString = _.map(styles, function(style, name) { return name + ": " + style; }).join('; ') + ';'; this.node.setAttribute('style', styleString); return this; } else { styleString = this.node.getAttribute('style') || ''; obj = _.reduce(styleString.split(';'), function(styles, str) { var name, ref, value; ref = str.split(':'), name = ref[0], value = ref[1]; if (name && value) { name = name.trim(); value = value.trim(); styles[name.toLowerCase()] = value; } return styles; }, {}); return obj; } }; Wrapper.prototype.switchTag = function(newTag) { var attributes, newNode; newTag = newTag.toUpperCase(); if (this.node.tagName === newTag) { return this; } newNode = document.createElement(newTag); attributes = this.attributes(); if (dom.VOID_TAGS[newTag] == null) { this.moveChildren(newNode); } this.replace(newNode); this.node = newNode; return this.attributes(attributes); }; Wrapper.prototype.text = function(text) { if (text != null) { switch (this.node.nodeType) { case dom.ELEMENT_NODE: this.node.textContent = text; break; case dom.TEXT_NODE: this.node.data = text; } return this; } else { switch (this.node.nodeType) { case dom.ELEMENT_NODE: if (this.node.tagName === dom.DEFAULT_BREAK_TAG) { return ""; } if (dom.EMBED_TAGS[this.node.tagName] != null) { return dom.EMBED_TEXT; } if (this.node.textContent != null) { return this.node.textContent; } return ""; case dom.TEXT_NODE: return this.node.data || ""; default: return ""; } } }; Wrapper.prototype.textNodes = function() { var textNode, textNodes, walker; walker = document.createTreeWalker(this.node, NodeFilter.SHOW_TEXT, null, false); textNodes = []; while (textNode = walker.nextNode()) { textNodes.push(textNode); } return textNodes; }; Wrapper.prototype.toggleClass = function(className, state) { if (state == null) { state = !this.hasClass(className); } if (state) { this.addClass(className); } else { this.removeClass(className); } return this; }; Wrapper.prototype.trigger = function(eventName, options) { var event, initFn, modifiers; if (options == null) { options = {}; } if (['keypress', 'keydown', 'keyup'].indexOf(eventName) < 0) { event = document.createEvent('Event'); event.initEvent(eventName, options.bubbles, options.cancelable); } else { event = document.createEvent('KeyboardEvent'); lastKeyEvent = _.clone(options); if (_.isNumber(options.key)) { lastKeyEvent.which = options.key; } else if (_.isString(options.key)) { lastKeyEvent.which = options.key.toUpperCase().charCodeAt(0); } else { lastKeyEvent.which = 0; } if (dom.isIE(10)) { modifiers = []; if (options.altKey) { modifiers.push('Alt'); } if (options.ctrlKey) { modifiers.push('Control'); } if (options.metaKey) { modifiers.push('Meta'); } if (options.shiftKey) { modifiers.push('Shift'); } event.initKeyboardEvent(eventName, options.bubbles, options.cancelable, window, 0, 0, modifiers.join(' '), null, null); } else { initFn = _.isFunction(event.initKeyboardEvent) ? 'initKeyboardEvent' : 'initKeyEvent'; event[initFn](eventName, options.bubbles, options.cancelable, window, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, 0); } } this.node.dispatchEvent(event); lastKeyEvent = null; return this; }; Wrapper.prototype.unwrap = function() { var next, ret; ret = this.node.firstChild; next = this.node.nextSibling; _.each(this.childNodes(), (function(_this) { return function(child) { return _this.node.parentNode.insertBefore(child, next); }; })(this)); this.remove(); return ret; }; Wrapper.prototype.wrap = function(wrapper) { var parent; if (this.node.parentNode != null) { this.node.parentNode.insertBefore(wrapper, this.node); } parent = wrapper; while (parent.firstChild != null) { parent = wrapper.firstChild; } parent.appendChild(this.node); return this; }; return Wrapper; })(); SelectWrapper = (function(superClass) { extend(SelectWrapper, superClass); function SelectWrapper() { return SelectWrapper.__super__.constructor.apply(this, arguments); } SelectWrapper.prototype["default"] = function() { return this.node.querySelector('option[selected]'); }; SelectWrapper.prototype.option = function(option, trigger) { var child, i, j, len, ref, value; if (trigger == null) { trigger = true; } value = _.isElement(option) ? option.value : option; if (value) { value = value.replace(/[^\w]+/g, ''); ref = this.node.children; for (i = j = 0, len = ref.length; j < len; i = ++j) { child = ref[i]; if (child.value.replace(/[^\w]+/g, '') === value) { this.node.selectedIndex = i; break; } } } else { this.node.selectedIndex = -1; } if (trigger) { this.trigger('change'); } return this; }; SelectWrapper.prototype.reset = function(trigger) { var option; if (trigger == null) { trigger = true; } option = this["default"](); if (option != null) { option.selected = true; } else { this.node.selectedIndex = 0; } if (trigger) { this.trigger('change'); } return this; }; SelectWrapper.prototype.value = function() { if (this.node.selectedIndex > -1) { return this.node.options[this.node.selectedIndex].value; } else { return ''; } }; return SelectWrapper; })(Wrapper); dom = function(node) { if ((node != null ? node.tagName : void 0) === 'SELECT') { return new SelectWrapper(node); } else { return new Wrapper(node); } }; dom = _.extend(dom, { ELEMENT_NODE: 1, NOBREAK_SPACE: " ", TEXT_NODE: 3, ZERO_WIDTH_NOBREAK_SPACE: "\uFEFF", DEFAULT_BLOCK_TAG: 'DIV', DEFAULT_BREAK_TAG: 'BR', DEFAULT_INLINE_TAG: 'SPAN', EMBED_TEXT: '!', FONT_SIZES: { '10px': 1, '13px': 2, '16px': 3, '18px': 4, '24px': 5, '32px': 6, '48px': 7 }, KEYS: { BACKSPACE: 8, TAB: 9, ENTER: 13, ESCAPE: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, DELETE: 46 }, BLOCK_TAGS: { 'ADDRESS': 'ADDRESS', 'ARTICLE': 'ARTICLE', 'ASIDE': 'ASIDE', 'AUDIO': 'AUDIO', 'BLOCKQUOTE': 'BLOCKQUOTE', 'CANVAS': 'CANVAS', 'DD': 'DD', 'DIV': 'DIV', 'DL': 'DL', 'FIGCAPTION': 'FIGCAPTION', 'FIGURE': 'FIGURE', 'FOOTER': 'FOOTER', 'FORM': 'FORM', 'H1': 'H1', 'H2': 'H2', 'H3': 'H3', 'H4': 'H4', 'H5': 'H5', 'H6': 'H6', 'HEADER': 'HEADER', 'HGROUP': 'HGROUP', 'LI': 'LI', 'OL': 'OL', 'OUTPUT': 'OUTPUT', 'P': 'P', 'PRE': 'PRE', 'SECTION': 'SECTION', 'TABLE': 'TABLE', 'TBODY': 'TBODY', 'TD': 'TD', 'TFOOT': 'TFOOT', 'TH': 'TH', 'THEAD': 'THEAD', 'TR': 'TR', 'UL': 'UL', 'VIDEO': 'VIDEO' }, EMBED_TAGS: { 'IMG': 'IMG' }, LINE_TAGS: { 'DIV': 'DIV', 'LI': 'LI' }, LIST_TAGS: { 'OL': 'OL', 'UL': 'UL' }, VOID_TAGS: { 'AREA': 'AREA', 'BASE': 'BASE', 'BR': 'BR', 'COL': 'COL', 'COMMAND': 'COMMAND', 'EMBED': 'EMBED', 'HR': 'HR', 'IMG': 'IMG', 'INPUT': 'INPUT', 'KEYGEN': 'KEYGEN', 'LINK': 'LINK', 'META': 'META', 'PARAM': 'PARAM', 'SOURCE': 'SOURCE', 'TRACK': 'TRACK', 'WBR': 'WBR' }, convertFontSize: function(size) { var i, s, sources, targets; if (_.isString(size) && size.indexOf('px') > -1) { sources = Object.keys(dom.FONT_SIZES); targets = _.values(dom.FONT_SIZES); } else { targets = Object.keys(dom.FONT_SIZES); sources = _.values(dom.FONT_SIZES); } for (i in sources) { s = sources[i]; if (parseInt(size) <= parseInt(s)) { return targets[i]; } } return _.last(targets); }, isIE: function(maxVersion) { var version; version = document.documentMode; return version && maxVersion >= version; }, isIOS: function() { return /iPhone|iPad/i.test(navigator.userAgent); }, isMac: function() { return /Mac/i.test(navigator.platform); } }); module.exports = dom; },{"lodash":1}],18:[function(_dereq_,module,exports){ var LinkedList, Node; Node = (function() { function Node(data) { this.data = data; this.prev = this.next = null; } return Node; })(); LinkedList = (function() { LinkedList.Node = Node; function LinkedList() { this.length = 0; this.first = this.last = null; } LinkedList.prototype.append = function(node) { if (this.first != null) { node.next = null; this.last.next = node; } else { this.first = node; } node.prev = this.last; this.last = node; return this.length += 1; }; LinkedList.prototype.insertAfter = function(refNode, newNode) { newNode.prev = refNode; if (refNode != null) { newNode.next = refNode.next; if (refNode.next != null) { refNode.next.prev = newNode; } refNode.next = newNode; if (refNode === this.last) { this.last = newNode; } } else { newNode.next = this.first; this.first.prev = newNode; this.first = newNode; } return this.length += 1; }; LinkedList.prototype.remove = function(node) { if (this.length > 1) { if (node.prev != null) { node.prev.next = node.next; } if (node.next != null) { node.next.prev = node.prev; } if (node === this.first) { this.first = node.next; } if (node === this.last) { this.last = node.prev; } } else { this.first = this.last = null; } node.prev = node.next = null; return this.length -= 1; }; LinkedList.prototype.toArray = function() { var arr, cur; arr = []; cur = this.first; while (cur != null) { arr.push(cur); cur = cur.next; } return arr; }; return LinkedList; })(); module.exports = LinkedList; },{}],19:[function(_dereq_,module,exports){ var Picker, _, dom; _ = _dereq_('lodash'); dom = _dereq_('./dom'); Picker = (function() { Picker.TEMPLATE = ''; function Picker(select) { this.select = select; this.container = document.createElement('span'); this.buildPicker(); dom(this.container).addClass('ql-picker'); this.select.style.display = 'none'; this.select.parentNode.insertBefore(this.container, this.select); dom(document).on('click', (function(_this) { return function() { _this.close(); return true; }; })(this)); dom(this.label).on('click', (function(_this) { return function() { _.defer(function() { return dom(_this.container).toggleClass('ql-expanded'); }); return false; }; })(this)); dom(this.select).on('change', (function(_this) { return function() { var item, option; if (_this.select.selectedIndex > -1) { item = _this.container.querySelectorAll('.ql-picker-item')[_this.select.selectedIndex]; option = _this.select.options[_this.select.selectedIndex]; } _this.selectItem(item, false); return dom(_this.label).toggleClass('ql-active', option !== dom(_this.select)["default"]()); }; })(this)); } Picker.prototype.buildItem = function(picker, option, index) { var item; item = document.createElement('span'); item.setAttribute('data-value', option.getAttribute('value')); dom(item).addClass('ql-picker-item').text(dom(option).text()).on('click', (function(_this) { return function() { _this.selectItem(item, true); return _this.close(); }; })(this)); if (this.select.selectedIndex === index) { this.selectItem(item, false); } return item; }; Picker.prototype.buildPicker = function() { var picker; _.each(dom(this.select).attributes(), (function(_this) { return function(value, name) { return _this.container.setAttribute(name, value); }; })(this)); this.container.innerHTML = Picker.TEMPLATE; this.label = this.container.querySelector('.ql-picker-label'); picker = this.container.querySelector('.ql-picker-options'); return _.each(this.select.options, (function(_this) { return function(option, i) { var item; item = _this.buildItem(picker, option, i); return picker.appendChild(item); }; })(this)); }; Picker.prototype.close = function() { return dom(this.container).removeClass('ql-expanded'); }; Picker.prototype.selectItem = function(item, trigger) { var selected, value; selected = this.container.querySelector('.ql-selected'); if (selected != null) { dom(selected).removeClass('ql-selected'); } if (item != null) { value = item.getAttribute('data-value'); dom(item).addClass('ql-selected'); dom(this.label).text(dom(item).text()); dom(this.select).option(value, trigger); return this.label.setAttribute('data-value', value); } else { this.label.innerHTML = ' '; return this.label.removeAttribute('data-value'); } }; return Picker; })(); module.exports = Picker; },{"./dom":17,"lodash":1}],20:[function(_dereq_,module,exports){ var Range, _; _ = _dereq_('lodash'); Range = (function() { Range.compare = function(r1, r2) { if (r1 === r2) { return true; } if (!((r1 != null) && (r2 != null))) { return false; } return r1.equals(r2); }; function Range(start, end) { this.start = start; this.end = end; } Range.prototype.equals = function(range) { if (range == null) { return false; } return this.start === range.start && this.end === range.end; }; Range.prototype.shift = function(index, length) { var ref; return ref = _.map([this.start, this.end], function(pos) { if (index > pos) { return pos; } if (length >= 0) { return pos + length; } else { return Math.max(index, pos + length); } }), this.start = ref[0], this.end = ref[1], ref; }; Range.prototype.isCollapsed = function() { return this.start === this.end; }; return Range; })(); module.exports = Range; },{"lodash":1}],21:[function(_dereq_,module,exports){ var Authorship, Delta, Quill, _, dom; Quill = _dereq_('../quill'); _ = Quill.require('lodash'); dom = Quill.require('dom'); Delta = Quill.require('delta'); Authorship = (function() { Authorship.DEFAULTS = { authorId: null, color: 'transparent', enabled: false }; function Authorship(quill, options) { this.quill = quill; this.options = options; if (this.options.button != null) { this.attachButton(this.options.button); } if (this.options.enabled) { this.enable(); } this.quill.addFormat('author', { "class": 'author-' }); if (this.options.authorId == null) { return; } this.quill.on(this.quill.constructor.events.PRE_EVENT, (function(_this) { return function(eventName, delta, origin) { var authorDelta, authorFormat; if (eventName === _this.quill.constructor.events.TEXT_CHANGE && origin === 'user') { authorDelta = new Delta(); authorFormat = { author: _this.options.authorId }; _.each(delta.ops, function(op) { if (op["delete"] != null) { return; } if ((op.insert != null) || ((op.retain != null) && (op.attributes != null))) { op.attributes || (op.attributes = {}); op.attributes.author = _this.options.authorId; return authorDelta.retain(op.retain || op.insert.length || 1, authorFormat); } else { return authorDelta.retain(op.retain); } }); return _this.quill.updateContents(authorDelta, Quill.sources.SILENT); } }; })(this)); this.addAuthor(this.options.authorId, this.options.color); } Authorship.prototype.addAuthor = function(id, color) { var styles; styles = {}; styles[".authorship .author-" + id] = { "background-color": "" + color }; return this.quill.theme.addStyles(styles); }; Authorship.prototype.attachButton = function(button) { var $button; $button = dom(button); return $button.on('click', (function(_this) { return function() { $button.toggleClass('ql-on'); return _this.enable($dom.hasClass('ql-on')); }; })(this)); }; Authorship.prototype.enable = function(enabled) { if (enabled == null) { enabled = true; } return dom(this.quill.root).toggleClass('authorship', enabled); }; Authorship.prototype.disable = function() { return this.enable(false); }; return Authorship; })(); Quill.registerModule('authorship', Authorship); module.exports = Authorship; },{"../quill":30}],22:[function(_dereq_,module,exports){ var Delta, ImageTooltip, Quill, Range, Tooltip, _, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Quill = _dereq_('../quill'); Tooltip = _dereq_('./tooltip'); _ = Quill.require('lodash'); dom = Quill.require('dom'); Delta = Quill.require('delta'); Range = Quill.require('range'); ImageTooltip = (function(superClass) { extend(ImageTooltip, superClass); ImageTooltip.DEFAULTS = { template: '
Preview
Cancel Insert' }; function ImageTooltip(quill, options) { this.quill = quill; this.options = options; this.options = _.defaults(this.options, Tooltip.DEFAULTS); ImageTooltip.__super__.constructor.call(this, this.quill, this.options); this.preview = this.container.querySelector('.preview'); this.textbox = this.container.querySelector('.input'); dom(this.container).addClass('ql-image-tooltip'); this.initListeners(); } ImageTooltip.prototype.initListeners = function() { dom(this.quill.root).on('focus', _.bind(this.hide, this)); dom(this.container.querySelector('.insert')).on('click', _.bind(this.insertImage, this)); dom(this.container.querySelector('.cancel')).on('click', _.bind(this.hide, this)); dom(this.textbox).on('input', _.bind(this._preview, this)); this.initTextbox(this.textbox, this.insertImage, this.hide); return this.quill.onModuleLoad('toolbar', (function(_this) { return function(toolbar) { _this.toolbar = toolbar; return toolbar.initFormat('image', _.bind(_this._onToolbar, _this)); }; })(this)); }; ImageTooltip.prototype.insertImage = function() { var index, url; url = this._normalizeURL(this.textbox.value); if (this.range == null) { this.range = new Range(0, 0); } if (this.range) { this.preview.innerHTML = 'Preview'; this.textbox.value = ''; index = this.range.end; this.quill.insertEmbed(index, 'image', url, 'user'); this.quill.setSelection(index + 1, index + 1); } return this.hide(); }; ImageTooltip.prototype._onToolbar = function(range, value) { if (value) { if (!this.textbox.value) { this.textbox.value = 'http://'; } this.show(); this.textbox.focus(); return _.defer((function(_this) { return function() { return _this.textbox.setSelectionRange(_this.textbox.value.length, _this.textbox.value.length); }; })(this)); } else { this.quill.deleteText(range, 'user'); return this.toolbar.setActive('image', false); } }; ImageTooltip.prototype._preview = function() { var img; if (!this._matchImageURL(this.textbox.value)) { return; } if (this.preview.firstChild.tagName === 'IMG') { return this.preview.firstChild.setAttribute('src', this.textbox.value); } else { img = document.createElement('img'); img.setAttribute('src', this.textbox.value); return this.preview.replaceChild(img, this.preview.firstChild); } }; ImageTooltip.prototype._matchImageURL = function(url) { return /^https?:\/\/.+\.(jpe?g|gif|png)$/.test(url); }; ImageTooltip.prototype._normalizeURL = function(url) { if (!/^https?:\/\//.test(url)) { url = 'http://' + url; } return url; }; return ImageTooltip; })(Tooltip); Quill.registerModule('image-tooltip', ImageTooltip); module.exports = ImageTooltip; },{"../quill":30,"./tooltip":28}],23:[function(_dereq_,module,exports){ var Delta, Keyboard, Quill, _, dom; Quill = _dereq_('../quill'); _ = Quill.require('lodash'); dom = Quill.require('dom'); Delta = Quill.require('delta'); Keyboard = (function() { Keyboard.hotkeys = { BOLD: { key: 'B', metaKey: true }, INDENT: { key: dom.KEYS.TAB }, ITALIC: { key: 'I', metaKey: true }, OUTDENT: { key: dom.KEYS.TAB, shiftKey: true }, UNDERLINE: { key: 'U', metaKey: true } }; function Keyboard(quill, options) { this.quill = quill; this.hotkeys = {}; this._initListeners(); this._initHotkeys(); this.quill.onModuleLoad('toolbar', (function(_this) { return function(toolbar) { return _this.toolbar = toolbar; }; })(this)); } Keyboard.prototype.addHotkey = function(hotkeys, callback) { if (!Array.isArray(hotkeys)) { hotkeys = [hotkeys]; } return _.each(hotkeys, (function(_this) { return function(hotkey) { var base, which; hotkey = _.isObject(hotkey) ? _.clone(hotkey) : { key: hotkey }; hotkey.callback = callback; which = _.isNumber(hotkey.key) ? hotkey.key : hotkey.key.toUpperCase().charCodeAt(0); if ((base = _this.hotkeys)[which] == null) { base[which] = []; } return _this.hotkeys[which].push(hotkey); }; })(this)); }; Keyboard.prototype.removeHotkeys = function(hotkey, callback) { var base, kept, ref, removed, which; hotkey = _.isString(hotkey) ? hotkey.toUpperCase() : hotkey; hotkey = Keyboard.hotkeys[hotkey] ? Keyboard.hotkeys[hotkey] : hotkey; hotkey = _.isObject(hotkey) ? hotkey : { key: hotkey }; which = _.isNumber(hotkey.key) ? hotkey.key : hotkey.key.charCodeAt(0); if ((base = this.hotkeys)[which] == null) { base[which] = []; } ref = _.partition(this.hotkeys[which], function(handler) { return _.isEqual(hotkey, _.omit(handler, 'callback')) && (!callback || callback === handler.callback); }), removed = ref[0], kept = ref[1]; this.hotkeys[which] = kept; return _.map(removed, 'callback'); }; Keyboard.prototype.toggleFormat = function(range, format) { var delta, value; if (range.isCollapsed()) { delta = this.quill.getContents(Math.max(0, range.start - 1), range.end); } else { delta = this.quill.getContents(range); } value = delta.ops.length === 0 || !_.all(delta.ops, function(op) { var ref; return (ref = op.attributes) != null ? ref[format] : void 0; }); if (range.isCollapsed()) { this.quill.prepareFormat(format, value, Quill.sources.USER); } else { this.quill.formatText(range, format, value, Quill.sources.USER); } if (this.toolbar != null) { return this.toolbar.setActive(format, value); } }; Keyboard.prototype._initEnter = function() { var keys; keys = [ { key: dom.KEYS.ENTER }, { key: dom.KEYS.ENTER, shiftKey: true } ]; return this.addHotkey(keys, (function(_this) { return function(range, hotkey) { var delta, leaf, line, offset, ref, ref1; if (range == null) { return true; } ref = _this.quill.editor.doc.findLineAt(range.start), line = ref[0], offset = ref[1]; ref1 = line.findLeafAt(offset), leaf = ref1[0], offset = ref1[1]; delta = new Delta().retain(range.start).insert('\n', line.formats)["delete"](range.end - range.start); _this.quill.updateContents(delta, Quill.sources.USER); _.each(leaf.formats, function(value, format) { _this.quill.prepareFormat(format, value); if (_this.toolbar != null) { _this.toolbar.setActive(format, value); } }); _this.quill.editor.selection.scrollIntoView(); return false; }; })(this)); }; Keyboard.prototype._initDeletes = function() { return this.addHotkey([dom.KEYS.DELETE, dom.KEYS.BACKSPACE], (function(_this) { return function(range, hotkey) { var format, line, offset, ref; if ((range != null) && _this.quill.getLength() > 0) { if (range.start !== range.end) { _this.quill.deleteText(range.start, range.end, Quill.sources.USER); } else { if (hotkey.key === dom.KEYS.BACKSPACE) { ref = _this.quill.editor.doc.findLineAt(range.start), line = ref[0], offset = ref[1]; if (offset === 0 && (line.formats.bullet || line.formats.list)) { format = line.formats.bullet ? 'bullet' : 'list'; _this.quill.formatLine(range.start, range.start, format, false, Quill.sources.USER); } else if (range.start > 0) { _this.quill.deleteText(range.start - 1, range.start, Quill.sources.USER); } } else if (range.start < _this.quill.getLength() - 1) { _this.quill.deleteText(range.start, range.start + 1, Quill.sources.USER); } } } _this.quill.editor.selection.scrollIntoView(); return false; }; })(this)); }; Keyboard.prototype._initHotkeys = function() { this.addHotkey(Keyboard.hotkeys.INDENT, (function(_this) { return function(range) { _this._onTab(range, false); return false; }; })(this)); this.addHotkey(Keyboard.hotkeys.OUTDENT, (function(_this) { return function(range) { return false; }; })(this)); _.each(['bold', 'italic', 'underline'], (function(_this) { return function(format) { return _this.addHotkey(Keyboard.hotkeys[format.toUpperCase()], function(range) { if (_this.quill.editor.doc.formats[format]) { _this.toggleFormat(range, format); } return false; }); }; })(this)); this._initDeletes(); return this._initEnter(); }; Keyboard.prototype._initListeners = function() { return dom(this.quill.root).on('keydown', (function(_this) { return function(event) { var prevent; prevent = false; _.each(_this.hotkeys[event.which], function(hotkey) { var metaKey; metaKey = dom.isMac() ? event.metaKey : event.metaKey || event.ctrlKey; if (!!hotkey.metaKey !== !!metaKey) { return; } if (!!hotkey.shiftKey !== !!event.shiftKey) { return; } if (!!hotkey.altKey !== !!event.altKey) { return; } prevent = hotkey.callback(_this.quill.getSelection(), hotkey, event) === false || prevent; return true; }); return !prevent; }; })(this)); }; Keyboard.prototype._onTab = function(range, shift) { var delta; if (shift == null) { shift = false; } delta = new Delta().retain(range.start).insert("\t")["delete"](range.end - range.start).retain(this.quill.getLength() - range.end); this.quill.updateContents(delta, Quill.sources.USER); return this.quill.setSelection(range.start + 1, range.start + 1); }; return Keyboard; })(); Quill.registerModule('keyboard', Keyboard); module.exports = Keyboard; },{"../quill":30}],24:[function(_dereq_,module,exports){ var LinkTooltip, Quill, Tooltip, _, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Quill = _dereq_('../quill'); Tooltip = _dereq_('./tooltip'); _ = Quill.require('lodash'); dom = Quill.require('dom'); LinkTooltip = (function(superClass) { extend(LinkTooltip, superClass); LinkTooltip.DEFAULTS = { maxLength: 50, template: 'Visit URL:   -  Change Remove Done' }; LinkTooltip.hotkeys = { LINK: { key: 'K', metaKey: true } }; function LinkTooltip(quill, options) { this.quill = quill; this.options = options; this.options = _.defaults(this.options, Tooltip.DEFAULTS); LinkTooltip.__super__.constructor.call(this, this.quill, this.options); dom(this.container).addClass('ql-link-tooltip'); this.textbox = this.container.querySelector('.input'); this.link = this.container.querySelector('.url'); this.initListeners(); } LinkTooltip.prototype.initListeners = function() { this.quill.on(this.quill.constructor.events.SELECTION_CHANGE, (function(_this) { return function(range) { var anchor; if (!((range != null) && range.isCollapsed())) { return; } anchor = _this._findAnchor(range); if (anchor) { _this.setMode(anchor.href, false); return _this.show(anchor); } else if (_this.container.style.left !== Tooltip.HIDE_MARGIN) { _this.range = null; return _this.hide(); } }; })(this)); dom(this.container.querySelector('.done')).on('click', _.bind(this.saveLink, this)); dom(this.container.querySelector('.remove')).on('click', (function(_this) { return function() { return _this.removeLink(_this.range); }; })(this)); dom(this.container.querySelector('.change')).on('click', (function(_this) { return function() { return _this.setMode(_this.link.href, true); }; })(this)); this.initTextbox(this.textbox, this.saveLink, this.hide); this.quill.onModuleLoad('toolbar', (function(_this) { return function(toolbar) { _this.toolbar = toolbar; return toolbar.initFormat('link', _.bind(_this._onToolbar, _this)); }; })(this)); return this.quill.onModuleLoad('keyboard', (function(_this) { return function(keyboard) { return keyboard.addHotkey(LinkTooltip.hotkeys.LINK, _.bind(_this._onKeyboard, _this)); }; })(this)); }; LinkTooltip.prototype.saveLink = function() { var anchor, end, url; url = this._normalizeURL(this.textbox.value); if (this.range != null) { end = this.range.end; if (this.range.isCollapsed()) { anchor = this._findAnchor(this.range); if (anchor != null) { anchor.href = url; } } else { this.quill.formatText(this.range, 'link', url, 'user'); } this.quill.setSelection(end, end); } return this.setMode(url, false); }; LinkTooltip.prototype.removeLink = function(range) { if (range.isCollapsed()) { range = this._expandRange(range); } this.hide(); this.quill.formatText(range, 'link', false, 'user'); if (this.toolbar != null) { return this.toolbar.setActive('link', false); } }; LinkTooltip.prototype.setMode = function(url, edit) { var text; if (edit == null) { edit = false; } if (edit) { this.textbox.value = url; _.defer((function(_this) { return function() { _this.textbox.focus(); return _this.textbox.setSelectionRange(0, url.length); }; })(this)); } else { this.link.href = url; url = this.link.href; text = url.length > this.options.maxLength ? url.slice(0, this.options.maxLength) + '...' : url; dom(this.link).text(text); } return dom(this.container).toggleClass('editing', edit); }; LinkTooltip.prototype._findAnchor = function(range) { var leaf, node, offset, ref; ref = this.quill.editor.doc.findLeafAt(range.start, true), leaf = ref[0], offset = ref[1]; if (leaf != null) { node = leaf.node; } while ((node != null) && node !== this.quill.root) { if (node.tagName === 'A') { return node; } node = node.parentNode; } return null; }; LinkTooltip.prototype._expandRange = function(range) { var end, leaf, offset, ref, start; ref = this.quill.editor.doc.findLeafAt(range.start, true), leaf = ref[0], offset = ref[1]; start = range.start - offset; end = start + leaf.length; return { start: start, end: end }; }; LinkTooltip.prototype._onToolbar = function(range, value) { return this._toggle(range, value); }; LinkTooltip.prototype._onKeyboard = function() { var range; range = this.quill.getSelection(); return this._toggle(range, !this._findAnchor(range)); }; LinkTooltip.prototype._toggle = function(range, value) { var nativeRange; if (!range) { return; } if (!value) { return this.removeLink(range); } else if (!range.isCollapsed()) { this.setMode(this._suggestURL(range), true); nativeRange = this.quill.editor.selection._getNativeRange(); return this.show(nativeRange); } }; LinkTooltip.prototype._normalizeURL = function(url) { if (!/^(https?:\/\/|mailto:)/.test(url)) { url = 'http://' + url; } return url; }; LinkTooltip.prototype._suggestURL = function(range) { var text; text = this.quill.getText(range); return this._normalizeURL(text); }; return LinkTooltip; })(Tooltip); Quill.registerModule('link-tooltip', LinkTooltip); module.exports = LinkTooltip; },{"../quill":30,"./tooltip":28}],25:[function(_dereq_,module,exports){ var EventEmitter2, MultiCursor, Quill, _, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Quill = _dereq_('../quill'); EventEmitter2 = _dereq_('eventemitter2').EventEmitter2; _ = Quill.require('lodash'); dom = Quill.require('dom'); MultiCursor = (function(superClass) { extend(MultiCursor, superClass); MultiCursor.DEFAULTS = { template: ' ', timeout: 2500 }; MultiCursor.events = { CURSOR_ADDED: 'cursor-addded', CURSOR_MOVED: 'cursor-moved', CURSOR_REMOVED: 'cursor-removed' }; function MultiCursor(quill, options) { this.quill = quill; this.options = options; this.cursors = {}; this.container = this.quill.addContainer('ql-multi-cursor', true); this.quill.on(this.quill.constructor.events.TEXT_CHANGE, _.bind(this._applyDelta, this)); } MultiCursor.prototype.clearCursors = function() { _.each(Object.keys(this.cursors), _.bind(this.removeCursor, this)); return this.cursors = {}; }; MultiCursor.prototype.moveCursor = function(userId, index) { var cursor; cursor = this.cursors[userId]; if (cursor == null) { return; } cursor.index = index; dom(cursor.elem).removeClass('hidden'); clearTimeout(cursor.timer); cursor.timer = setTimeout((function(_this) { return function() { dom(cursor.elem).addClass('hidden'); return cursor.timer = null; }; })(this), this.options.timeout); this._updateCursor(cursor); return cursor; }; MultiCursor.prototype.removeCursor = function(userId) { var cursor; cursor = this.cursors[userId]; this.emit(MultiCursor.events.CURSOR_REMOVED, cursor); if (cursor != null) { cursor.elem.parentNode.removeChild(cursor.elem); } return delete this.cursors[userId]; }; MultiCursor.prototype.setCursor = function(userId, index, name, color) { var cursor; if (this.cursors[userId] == null) { this.cursors[userId] = cursor = { userId: userId, index: index, color: color, elem: this._buildCursor(name, color) }; this.emit(MultiCursor.events.CURSOR_ADDED, cursor); } _.defer((function(_this) { return function() { return _this.moveCursor(userId, index); }; })(this)); return this.cursors[userId]; }; MultiCursor.prototype.shiftCursors = function(index, length, authorId) { if (authorId == null) { authorId = null; } return _.each(this.cursors, (function(_this) { return function(cursor, id) { var shift; if (!cursor) { return; } shift = Math.max(length, index - cursor.index); if (cursor.userId === authorId) { return _this.moveCursor(authorId, cursor.index + shift); } else if (cursor.index > index) { return cursor.index += shift; } }; })(this)); }; MultiCursor.prototype.update = function() { return _.each(this.cursors, (function(_this) { return function(cursor, id) { if (cursor == null) { return; } _this._updateCursor(cursor); return true; }; })(this)); }; MultiCursor.prototype._applyDelta = function(delta) { var index; index = 0; _.each(delta.ops, (function(_this) { return function(op) { var length, ref; length = 0; if (op.insert != null) { length = op.insert.length || 1; _this.shiftCursors(index, length, (ref = op.attributes) != null ? ref['author'] : void 0); } else if (op["delete"] != null) { _this.shiftCursors(index, -1 * op["delete"], null); } else if (op.retain != null) { _this.shiftCursors(index, 0, null); length = op.retain; } return index += length; }; })(this)); return this.update(); }; MultiCursor.prototype._buildCursor = function(name, color) { var cursor, cursorCaret, cursorFlag, cursorName; cursor = document.createElement('span'); dom(cursor).addClass('cursor'); cursor.innerHTML = this.options.template; cursorFlag = cursor.querySelector('.cursor-flag'); cursorName = cursor.querySelector('.cursor-name'); dom(cursorName).text(name); cursorCaret = cursor.querySelector('.cursor-caret'); cursorCaret.style.backgroundColor = cursorName.style.backgroundColor = color; this.container.appendChild(cursor); return cursor; }; MultiCursor.prototype._updateCursor = function(cursor) { var bounds, flag; bounds = this.quill.getBounds(cursor.index); if (bounds == null) { return this.removeCursor(cursor.userId); } cursor.elem.style.top = (bounds.top + this.quill.container.scrollTop) + 'px'; cursor.elem.style.left = bounds.left + 'px'; cursor.elem.style.height = bounds.height + 'px'; flag = cursor.elem.querySelector('.cursor-flag'); dom(cursor.elem).toggleClass('top', parseInt(cursor.elem.style.top) <= flag.offsetHeight).toggleClass('left', parseInt(cursor.elem.style.left) <= flag.offsetWidth).toggleClass('right', this.quill.root.offsetWidth - parseInt(cursor.elem.style.left) <= flag.offsetWidth); return this.emit(MultiCursor.events.CURSOR_MOVED, cursor); }; return MultiCursor; })(EventEmitter2); Quill.registerModule('multi-cursor', MultiCursor); module.exports = MultiCursor; },{"../quill":30,"eventemitter2":2}],26:[function(_dereq_,module,exports){ var Delta, Document, PasteManager, Quill, _, dom, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Quill = _dereq_('../quill'); Document = _dereq_('../core/document'); _ = Quill.require('lodash'); dom = Quill.require('dom'); Delta = Quill.require('delta'); PasteManager = (function() { PasteManager.DEFAULTS = { onConvert: null }; function PasteManager(quill, options) { var base; this.quill = quill; this._onConvert = bind(this._onConvert, this); this.container = this.quill.addContainer('ql-paste-manager'); this.container.setAttribute('contenteditable', true); this.container.setAttribute('tabindex', '-1'); dom(this.quill.root).on('paste', _.bind(this._paste, this)); this.options = _.defaults(options, PasteManager.DEFAULTS); if ((base = this.options).onConvert == null) { base.onConvert = this._onConvert; } } PasteManager.prototype._onConvert = function(container) { var delta, doc, lengthAdded; doc = new Document(container, this.quill.options); delta = doc.toDelta(); lengthAdded = delta.length(); if (lengthAdded === 0) { return delta; } return delta.compose(new Delta().retain(lengthAdded - 1)["delete"](1)); }; PasteManager.prototype._paste = function() { var oldDocLength, range; oldDocLength = this.quill.getLength(); range = this.quill.getSelection(); if (range == null) { return; } this.container.focus(); return _.defer((function(_this) { return function() { var delta, lengthAdded; delta = _this.options.onConvert(_this.container); lengthAdded = delta.length(); if (lengthAdded > 0) { if (range.start > 0) { delta.ops.unshift({ retain: range.start }); } delta["delete"](range.end - range.start); _this.quill.updateContents(delta, 'user'); } _this.quill.setSelection(range.start + lengthAdded, range.start + lengthAdded); _this.quill.editor.selection.scrollIntoView(); return _this.container.innerHTML = ""; }; })(this)); }; return PasteManager; })(); Quill.registerModule('paste-manager', PasteManager); module.exports = PasteManager; },{"../core/document":8,"../quill":30}],27:[function(_dereq_,module,exports){ var Quill, Toolbar, _, dom; Quill = _dereq_('../quill'); _ = Quill.require('lodash'); dom = Quill.require('dom'); Toolbar = (function() { Toolbar.DEFAULTS = { container: null }; Toolbar.formats = { LINE: { 'align': 'align', 'bullet': 'bullet', 'list': 'list' }, SELECT: { 'align': 'align', 'background': 'background', 'color': 'color', 'font': 'font', 'size': 'size' }, TOGGLE: { 'bold': 'bold', 'bullet': 'bullet', 'image': 'image', 'italic': 'italic', 'link': 'link', 'list': 'list', 'strike': 'strike', 'underline': 'underline' }, TOOLTIP: { 'image': 'image', 'link': 'link' } }; function Toolbar(quill, options) { this.quill = quill; this.options = options; if (_.isString(this.options) || _.isElement(this.options)) { this.options = { container: this.options }; } if (this.options.container == null) { throw new Error('container required for toolbar', this.options); } this.container = _.isString(this.options.container) ? document.querySelector(this.options.container) : this.options.container; this.inputs = {}; this.preventUpdate = false; this.triggering = false; _.each(this.quill.options.formats, (function(_this) { return function(name) { if (Toolbar.formats.TOOLTIP[name] != null) { return; } return _this.initFormat(name, _.bind(_this._applyFormat, _this, name)); }; })(this)); this.quill.on(Quill.events.FORMAT_INIT, (function(_this) { return function(name) { if (Toolbar.formats.TOOLTIP[name] != null) { return; } return _this.initFormat(name, _.bind(_this._applyFormat, _this, name)); }; })(this)); this.quill.on(Quill.events.SELECTION_CHANGE, (function(_this) { return function(range) { if (range != null) { return _this.updateActive(range); } }; })(this)); this.quill.on(Quill.events.TEXT_CHANGE, (function(_this) { return function() { return _this.updateActive(); }; })(this)); this.quill.onModuleLoad('keyboard', (function(_this) { return function(keyboard) { return keyboard.addHotkey([dom.KEYS.BACKSPACE, dom.KEYS.DELETE], function() { return _.defer(_.bind(_this.updateActive, _this)); }); }; })(this)); dom(this.container).addClass('ql-toolbar'); if (dom.isIOS()) { dom(this.container).addClass('ios'); } } Toolbar.prototype.initFormat = function(format, callback) { var eventName, input, selector; selector = ".ql-" + format; if (Toolbar.formats.SELECT[format] != null) { selector = "select" + selector; eventName = 'change'; } else { eventName = 'click'; } input = this.container.querySelector(selector); if (input == null) { return; } this.inputs[format] = input; return dom(input).on(eventName, (function(_this) { return function() { var range, value; value = eventName === 'change' ? dom(input).value() : !dom(input).hasClass('ql-active'); _this.preventUpdate = true; _this.quill.focus(); range = _this.quill.getSelection(); if (range != null) { callback(range, value); } if (dom.isIE(11)) { _this.quill.editor.selection.scrollIntoView(); } _this.preventUpdate = false; return false; }; })(this)); }; Toolbar.prototype.setActive = function(format, value) { var $input, input, ref, selectValue; if (format === 'image') { value = false; } input = this.inputs[format]; if (input == null) { return; } $input = dom(input); if (input.tagName === 'SELECT') { this.triggering = true; selectValue = $input.value(input); if (value == null) { value = (ref = $input["default"]()) != null ? ref.value : void 0; } if (Array.isArray(value)) { value = ''; } if (value !== selectValue) { if (value != null) { $input.option(value); } else { $input.reset(); } } return this.triggering = false; } else { return $input.toggleClass('ql-active', value || false); } }; Toolbar.prototype.updateActive = function(range, formats) { var activeFormats; if (formats == null) { formats = null; } range || (range = this.quill.getSelection()); if (!((range != null) && !this.preventUpdate)) { return; } activeFormats = this._getActive(range); return _.each(this.inputs, (function(_this) { return function(input, format) { if (!Array.isArray(formats) || formats.indexOf(format) > -1) { _this.setActive(format, activeFormats[format]); } return true; }; })(this)); }; Toolbar.prototype._applyFormat = function(format, range, value) { if (this.triggering) { return; } if (range.isCollapsed()) { this.quill.prepareFormat(format, value, 'user'); } else if (Toolbar.formats.LINE[format] != null) { this.quill.formatLine(range, format, value, 'user'); } else { this.quill.formatText(range, format, value, 'user'); } return _.defer((function(_this) { return function() { _this.updateActive(range, ['bullet', 'list']); return _this.setActive(format, value); }; })(this)); }; Toolbar.prototype._getActive = function(range) { var leafFormats, lineFormats; leafFormats = this._getLeafActive(range); lineFormats = this._getLineActive(range); return _.defaults({}, leafFormats, lineFormats); }; Toolbar.prototype._getLeafActive = function(range) { var contents, formatsArr, line, offset, ref; if (range.isCollapsed()) { ref = this.quill.editor.doc.findLineAt(range.start), line = ref[0], offset = ref[1]; if (offset === 0) { contents = this.quill.getContents(range.start, range.end + 1); } else { contents = this.quill.getContents(range.start - 1, range.end); } } else { contents = this.quill.getContents(range); } formatsArr = _.map(contents.ops, 'attributes'); return this._intersectFormats(formatsArr); }; Toolbar.prototype._getLineActive = function(range) { var firstLine, formatsArr, lastLine, offset, ref, ref1; formatsArr = []; ref = this.quill.editor.doc.findLineAt(range.start), firstLine = ref[0], offset = ref[1]; ref1 = this.quill.editor.doc.findLineAt(range.end), lastLine = ref1[0], offset = ref1[1]; if ((lastLine != null) && lastLine === firstLine) { lastLine = lastLine.next; } while ((firstLine != null) && firstLine !== lastLine) { formatsArr.push(_.clone(firstLine.formats)); firstLine = firstLine.next; } return this._intersectFormats(formatsArr); }; Toolbar.prototype._intersectFormats = function(formatsArr) { return _.reduce(formatsArr.slice(1), function(activeFormats, formats) { var activeKeys, added, formatKeys, intersection, missing; if (formats == null) { formats = {}; } activeKeys = Object.keys(activeFormats); formatKeys = formats != null ? Object.keys(formats) : {}; intersection = _.intersection(activeKeys, formatKeys); missing = _.difference(activeKeys, formatKeys); added = _.difference(formatKeys, activeKeys); _.each(intersection, function(name) { if (Toolbar.formats.SELECT[name] != null) { if (Array.isArray(activeFormats[name])) { if (activeFormats[name].indexOf(formats[name]) < 0) { return activeFormats[name].push(formats[name]); } } else if (activeFormats[name] !== formats[name]) { return activeFormats[name] = [activeFormats[name], formats[name]]; } } }); _.each(missing, function(name) { if (Toolbar.formats.TOGGLE[name] != null) { return delete activeFormats[name]; } else if ((Toolbar.formats.SELECT[name] != null) && !Array.isArray(activeFormats[name])) { return activeFormats[name] = [activeFormats[name]]; } }); _.each(added, function(name) { if (Toolbar.formats.SELECT[name] != null) { return activeFormats[name] = [formats[name]]; } }); return activeFormats; }, formatsArr[0] || {}); }; return Toolbar; })(); Quill.registerModule('toolbar', Toolbar); module.exports = Toolbar; },{"../quill":30}],28:[function(_dereq_,module,exports){ var Quill, Tooltip, _, dom; Quill = _dereq_('../quill'); _ = Quill.require('lodash'); dom = Quill.require('dom'); Tooltip = (function() { Tooltip.DEFAULTS = { offset: 10, template: '' }; Tooltip.HIDE_MARGIN = '-10000px'; function Tooltip(quill, options) { this.quill = quill; this.options = options; this.container = this.quill.addContainer('ql-tooltip'); this.container.innerHTML = this.options.template; this.hide(); this.quill.on(this.quill.constructor.events.TEXT_CHANGE, (function(_this) { return function(delta, source) { if (_this.container.style.left !== Tooltip.HIDE_MARGIN) { _this.range = null; return _this.hide(); } }; })(this)); } Tooltip.prototype.initTextbox = function(textbox, enterCallback, escapeCallback) { return dom(textbox).on('keydown', (function(_this) { return function(event) { switch (event.which) { case dom.KEYS.ENTER: event.preventDefault(); return enterCallback.call(_this); case dom.KEYS.ESCAPE: event.preventDefault(); return escapeCallback.call(_this); default: return true; } }; })(this)); }; Tooltip.prototype.hide = function() { this.container.style.left = Tooltip.HIDE_MARGIN; if (this.range) { this.quill.setSelection(this.range); } return this.range = null; }; Tooltip.prototype.position = function(reference) { var left, offsetBottom, offsetLeft, offsetTop, parentBounds, referenceBounds, top; if (reference != null) { referenceBounds = reference.getBoundingClientRect(); parentBounds = this.quill.container.getBoundingClientRect(); offsetLeft = referenceBounds.left - parentBounds.left; offsetTop = referenceBounds.top - parentBounds.top; offsetBottom = referenceBounds.bottom - parentBounds.bottom; left = offsetLeft + referenceBounds.width / 2 - this.container.offsetWidth / 2; top = offsetTop + referenceBounds.height + this.options.offset; if (top + this.container.offsetHeight > this.quill.container.offsetHeight) { top = offsetTop - this.container.offsetHeight - this.options.offset; } left = Math.max(0, Math.min(left, this.quill.container.offsetWidth - this.container.offsetWidth)); top = Math.max(0, Math.min(top, this.quill.container.offsetHeight - this.container.offsetHeight)); } else { left = this.quill.container.offsetWidth / 2 - this.container.offsetWidth / 2; top = this.quill.container.offsetHeight / 2 - this.container.offsetHeight / 2; } top += this.quill.container.scrollTop; return [left, top]; }; Tooltip.prototype.show = function(reference) { var left, ref, top; this.range = this.quill.getSelection(); ref = this.position(reference), left = ref[0], top = ref[1]; this.container.style.left = left + "px"; this.container.style.top = top + "px"; return this.container.focus(); }; return Tooltip; })(); Quill.registerModule('tooltip', Tooltip); module.exports = Tooltip; },{"../quill":30}],29:[function(_dereq_,module,exports){ var Delta, Quill, UndoManager, _; Quill = _dereq_('../quill'); _ = Quill.require('lodash'); Delta = Quill.require('delta'); UndoManager = (function() { UndoManager.DEFAULTS = { delay: 1000, maxStack: 100, userOnly: false }; UndoManager.hotkeys = { UNDO: { key: 'Z', metaKey: true }, REDO: { key: 'Z', metaKey: true, shiftKey: true } }; function UndoManager(quill, options) { this.quill = quill; this.options = options != null ? options : {}; this.lastRecorded = 0; this.ignoreChange = false; this.clear(); this.initListeners(); } UndoManager.prototype.initListeners = function() { this.quill.onModuleLoad('keyboard', (function(_this) { return function(keyboard) { var redoKey; keyboard.addHotkey(UndoManager.hotkeys.UNDO, function() { _this.quill.editor.checkUpdate(); _this.undo(); return false; }); redoKey = [UndoManager.hotkeys.REDO]; if (navigator.platform.indexOf('Win') > -1) { redoKey.push({ key: 'Y', metaKey: true }); } return keyboard.addHotkey(redoKey, function() { _this.quill.editor.checkUpdate(); _this.redo(); return false; }); }; })(this)); return this.quill.on(this.quill.constructor.events.TEXT_CHANGE, (function(_this) { return function(delta, source) { if (_this.ignoreChange) { return; } if (!_this.options.userOnly || source === Quill.sources.USER) { _this.record(delta, _this.oldDelta); } else { _this._transform(delta); } return _this.oldDelta = _this.quill.getContents(); }; })(this)); }; UndoManager.prototype.clear = function() { this.stack = { undo: [], redo: [] }; return this.oldDelta = this.quill.getContents(); }; UndoManager.prototype.record = function(changeDelta, oldDelta) { var change, ignored, timestamp, undoDelta; if (!(changeDelta.ops.length > 0)) { return; } this.stack.redo = []; try { undoDelta = this.quill.getContents().diff(this.oldDelta); timestamp = new Date().getTime(); if (this.lastRecorded + this.options.delay > timestamp && this.stack.undo.length > 0) { change = this.stack.undo.pop(); undoDelta = undoDelta.compose(change.undo); changeDelta = change.redo.compose(changeDelta); } else { this.lastRecorded = timestamp; } this.stack.undo.push({ redo: changeDelta, undo: undoDelta }); if (this.stack.undo.length > this.options.maxStack) { return this.stack.undo.unshift(); } } catch (_error) { ignored = _error; console.warn('Could not record change... clearing undo stack.'); return this.clear(); } }; UndoManager.prototype.redo = function() { return this._change('redo', 'undo'); }; UndoManager.prototype.undo = function() { return this._change('undo', 'redo'); }; UndoManager.prototype._getLastChangeIndex = function(delta) { var index, lastIndex; lastIndex = 0; index = 0; _.each(delta.ops, function(op) { if (op.insert != null) { return lastIndex = Math.max(index + (op.insert.length || 1), lastIndex); } else if (op["delete"] != null) { return lastIndex = Math.max(index, lastIndex); } else if (op.retain != null) { if (op.attributes != null) { lastIndex = Math.max(index + op.retain, lastIndex); } return index += op.retain; } }); return lastIndex; }; UndoManager.prototype._change = function(source, dest) { var change, index; if (this.stack[source].length > 0) { change = this.stack[source].pop(); this.lastRecorded = 0; this.ignoreChange = true; this.quill.updateContents(change[source], Quill.sources.USER); this.ignoreChange = false; index = this._getLastChangeIndex(change[source]); this.quill.setSelection(index, index); this.oldDelta = this.quill.getContents(); return this.stack[dest].push(change); } }; UndoManager.prototype._transform = function(delta) { var change, i, j, len, len1, ref, ref1, results; this.oldDelta = delta.transform(this.oldDelta, true); ref = this.stack.undo; for (i = 0, len = ref.length; i < len; i++) { change = ref[i]; change.undo = delta.transform(change.undo, true); change.redo = delta.transform(change.redo, true); } ref1 = this.stack.redo; results = []; for (j = 0, len1 = ref1.length; j < len1; j++) { change = ref1[j]; change.undo = delta.transform(change.undo, true); results.push(change.redo = delta.transform(change.redo, true)); } return results; }; return UndoManager; })(); Quill.registerModule('undo-manager', UndoManager); module.exports = UndoManager; },{"../quill":30}],30:[function(_dereq_,module,exports){ var Delta, Document, Editor, EventEmitter2, Format, Normalizer, Quill, Range, _, dom, pkg, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, slice = [].slice; _ = _dereq_('lodash'); pkg = _dereq_('../package.json'); Delta = _dereq_('rich-text/lib/delta'); EventEmitter2 = _dereq_('eventemitter2').EventEmitter2; dom = _dereq_('./lib/dom'); Document = _dereq_('./core/document'); Editor = _dereq_('./core/editor'); Format = _dereq_('./core/format'); Normalizer = _dereq_('./core/normalizer'); Range = _dereq_('./lib/range'); Quill = (function(superClass) { extend(Quill, superClass); Quill.version = pkg.version; Quill.editors = []; Quill.modules = []; Quill.themes = []; Quill.DEFAULTS = { formats: ['align', 'bold', 'italic', 'strike', 'underline', 'color', 'background', 'font', 'size', 'link', 'image', 'bullet', 'list'], modules: { 'keyboard': true, 'paste-manager': true, 'undo-manager': true }, pollInterval: 100, readOnly: false, styles: {}, theme: 'base' }; Quill.events = { FORMAT_INIT: 'format-init', MODULE_INIT: 'module-init', POST_EVENT: 'post-event', PRE_EVENT: 'pre-event', SELECTION_CHANGE: 'selection-change', TEXT_CHANGE: 'text-change' }; Quill.sources = Editor.sources; Quill.registerModule = function(name, module) { if (Quill.modules[name] != null) { console.warn("Overwriting " + name + " module"); } return Quill.modules[name] = module; }; Quill.registerTheme = function(name, theme) { if (Quill.themes[name] != null) { console.warn("Overwriting " + name + " theme"); } return Quill.themes[name] = theme; }; Quill.require = function(name) { switch (name) { case 'lodash': return _; case 'delta': return Delta; case 'format': return Format; case 'normalizer': return Normalizer; case 'dom': return dom; case 'document': return Document; case 'range': return Range; default: return null; } }; function Quill(container1, options) { var html, moduleOptions, themeClass; this.container = container1; if (options == null) { options = {}; } if (_.isString(this.container)) { this.container = document.querySelector(this.container); } if (this.container == null) { throw new Error('Invalid Quill container'); } moduleOptions = _.defaults(options.modules || {}, Quill.DEFAULTS.modules); html = this.container.innerHTML; this.container.innerHTML = ''; this.options = _.defaults(options, Quill.DEFAULTS); this.options.modules = moduleOptions; this.options.id = this.id = "ql-editor-" + (Quill.editors.length + 1); this.modules = {}; this.root = this.addContainer('ql-editor'); this.editor = new Editor(this.root, this, this.options); Quill.editors.push(this); this.setHTML(html, Quill.sources.SILENT); themeClass = Quill.themes[this.options.theme]; if (themeClass == null) { throw new Error("Cannot load " + this.options.theme + " theme. Are you sure you registered it?"); } this.theme = new themeClass(this, this.options); _.each(this.options.modules, (function(_this) { return function(option, name) { return _this.addModule(name, option); }; })(this)); } Quill.prototype.destroy = function() { var html; html = this.getHTML(); _.each(this.modules, function(module, name) { if (_.isFunction(module.destroy)) { return module.destroy(); } }); this.editor.destroy(); this.removeAllListeners(); Quill.editors.splice(_.indexOf(Quill.editors, this), 1); return this.container.innerHTML = html; }; Quill.prototype.addContainer = function(className, before) { var container, refNode; if (before == null) { before = false; } refNode = before ? this.root : null; container = document.createElement('div'); dom(container).addClass(className); this.container.insertBefore(container, refNode); return container; }; Quill.prototype.addFormat = function(name, config) { this.editor.doc.addFormat(name, config); return this.emit(Quill.events.FORMAT_INIT, name); }; Quill.prototype.addModule = function(name, options) { var moduleClass; moduleClass = Quill.modules[name]; if (moduleClass == null) { throw new Error("Cannot load " + name + " module. Are you sure you registered it?"); } if (options === true) { options = {}; } options = _.defaults(options, this.theme.constructor.OPTIONS[name] || {}, moduleClass.DEFAULTS || {}); this.modules[name] = new moduleClass(this, options); this.emit(Quill.events.MODULE_INIT, name, this.modules[name]); return this.modules[name]; }; Quill.prototype.deleteText = function(start, end, source) { var delta, formats, ref; if (source == null) { source = Quill.sources.API; } ref = this._buildParams(start, end, {}, source), start = ref[0], end = ref[1], formats = ref[2], source = ref[3]; if (!(end > start)) { return; } delta = new Delta().retain(start)["delete"](end - start); return this.editor.applyDelta(delta, source); }; Quill.prototype.emit = function() { var args, eventName; eventName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; Quill.__super__.emit.apply(this, [Quill.events.PRE_EVENT, eventName].concat(slice.call(args))); Quill.__super__.emit.apply(this, [eventName].concat(slice.call(args))); return Quill.__super__.emit.apply(this, [Quill.events.POST_EVENT, eventName].concat(slice.call(args))); }; Quill.prototype.focus = function() { return this.editor.focus(); }; Quill.prototype.formatLine = function(start, end, name, value, source) { var formats, line, offset, ref, ref1; ref = this._buildParams(start, end, name, value, source), start = ref[0], end = ref[1], formats = ref[2], source = ref[3]; ref1 = this.editor.doc.findLineAt(end), line = ref1[0], offset = ref1[1]; if (line != null) { end += line.length - offset; } return this.formatText(start, end, formats, source); }; Quill.prototype.formatText = function(start, end, name, value, source) { var delta, formats, ref; ref = this._buildParams(start, end, name, value, source), start = ref[0], end = ref[1], formats = ref[2], source = ref[3]; formats = _.reduce(formats, (function(_this) { return function(formats, value, name) { var format; format = _this.editor.doc.formats[name]; if (!(value && value !== format.config["default"])) { formats[name] = null; } return formats; }; })(this), formats); delta = new Delta().retain(start).retain(end - start, formats); return this.editor.applyDelta(delta, source); }; Quill.prototype.getBounds = function(index) { return this.editor.getBounds(index); }; Quill.prototype.getContents = function(start, end) { if (start == null) { start = 0; } if (end == null) { end = null; } if (_.isObject(start)) { end = start.end; start = start.start; } return this.editor.delta.slice(start, end); }; Quill.prototype.getHTML = function() { return this.editor.doc.getHTML(); }; Quill.prototype.getLength = function() { return this.editor.length; }; Quill.prototype.getModule = function(name) { return this.modules[name]; }; Quill.prototype.getSelection = function() { this.editor.checkUpdate(); return this.editor.selection.getRange(); }; Quill.prototype.getText = function(start, end) { if (start == null) { start = 0; } if (end == null) { end = null; } return _.map(this.getContents(start, end).ops, function(op) { if (_.isString(op.insert)) { return op.insert; } else { return ''; } }).join(''); }; Quill.prototype.insertEmbed = function(index, type, url, source) { var delta, end, formats, ref; ref = this._buildParams(index, 0, type, url, source), index = ref[0], end = ref[1], formats = ref[2], source = ref[3]; delta = new Delta().retain(index).insert(1, formats); return this.editor.applyDelta(delta, source); }; Quill.prototype.insertText = function(index, text, name, value, source) { var delta, end, formats, ref; ref = this._buildParams(index, 0, name, value, source), index = ref[0], end = ref[1], formats = ref[2], source = ref[3]; if (!(text.length > 0)) { return; } delta = new Delta().retain(index).insert(text, formats); return this.editor.applyDelta(delta, source); }; Quill.prototype.onModuleLoad = function(name, callback) { if (this.modules[name]) { return callback(this.modules[name]); } return this.on(Quill.events.MODULE_INIT, function(moduleName, module) { if (moduleName === name) { return callback(module); } }); }; Quill.prototype.prepareFormat = function(name, value, source) { var format, range; if (source == null) { source = Quill.sources.API; } format = this.editor.doc.formats[name]; if (format == null) { return; } range = this.getSelection(); if (!(range != null ? range.isCollapsed() : void 0)) { return; } if (format.isType(Format.types.LINE)) { return this.formatLine(range, name, value, source); } else { return format.prepare(value); } }; Quill.prototype.setContents = function(delta, source) { var lastOp; if (source == null) { source = Quill.sources.API; } if (Array.isArray(delta)) { delta = new Delta(delta.slice()); } else { delta = new Delta(delta.ops.slice()); } lastOp = _.last(delta.slice(delta.length() - 1).ops); delta["delete"](this.getLength() - 1); if ((lastOp != null) && _.isString(lastOp.insert) && _.last(lastOp.insert) === '\n') { delta["delete"](1); } return this.updateContents(delta, source); }; Quill.prototype.setHTML = function(html, source) { if (source == null) { source = Quill.sources.API; } if (!html.trim()) { html = "<" + dom.DEFAULT_BLOCK_TAG + "><" + dom.DEFAULT_BREAK_TAG + ">"; } this.editor.doc.setHTML(html); return this.editor.checkUpdate(source); }; Quill.prototype.setSelection = function(start, end, source) { var range; if (source == null) { source = Quill.sources.API; } if (_.isNumber(start) && _.isNumber(end)) { range = new Range(start, end); } else { range = start; source = end || source; } return this.editor.selection.setRange(range, source); }; Quill.prototype.setText = function(text, source) { var delta; if (source == null) { source = Quill.sources.API; } delta = new Delta().insert(text); return this.setContents(delta, source); }; Quill.prototype.updateContents = function(delta, source) { if (source == null) { source = Quill.sources.API; } if (Array.isArray(delta)) { delta = { ops: delta }; } return this.editor.applyDelta(delta, source); }; Quill.prototype._buildParams = function() { var formats, params; params = 1 <= arguments.length ? slice.call(arguments, 0) : []; if (_.isObject(params[0])) { params.splice(0, 1, params[0].start, params[0].end); } if (_.isString(params[2])) { formats = {}; formats[params[2]] = params[3]; params.splice(2, 2, formats); } if (params[3] == null) { params[3] = Quill.sources.API; } return params; }; return Quill; })(EventEmitter2); Quill.registerTheme('base', _dereq_('./themes/base')); Quill.registerTheme('snow', _dereq_('./themes/snow')); module.exports = Quill; },{"../package.json":7,"./core/document":8,"./core/editor":9,"./core/format":10,"./core/normalizer":13,"./lib/dom":17,"./lib/range":20,"./themes/base":32,"./themes/snow":33,"eventemitter2":2,"lodash":1,"rich-text/lib/delta":3}],31:[function(_dereq_,module,exports){ module.exports = ".ql-image-tooltip{padding:10px;width:300px}.ql-image-tooltip:after{clear:both;content:\"\";display:table}.ql-image-tooltip a{border:1px solid #000;box-sizing:border-box;display:inline-block;float:left;padding:5px;text-align:center;width:50%}.ql-image-tooltip img{bottom:0;left:0;margin:auto;max-height:100%;max-width:100%;position:absolute;right:0;top:0}.ql-image-tooltip .input{box-sizing:border-box;width:100%}.ql-image-tooltip .preview{margin:10px 0;position:relative;border:1px dashed #000;height:200px}.ql-image-tooltip .preview span{display:inline-block;position:absolute;text-align:center;top:40%;width:100%}.ql-link-tooltip{padding:5px 10px}.ql-link-tooltip input.input{width:170px}.ql-link-tooltip a.done,.ql-link-tooltip input.input{display:none}.ql-link-tooltip a.change{margin-right:4px}.ql-link-tooltip.editing a.done,.ql-link-tooltip.editing input.input{display:inline-block}.ql-link-tooltip.editing a.change,.ql-link-tooltip.editing a.remove,.ql-link-tooltip.editing a.url{display:none}.ql-multi-cursor{position:absolute;left:0;top:0;z-index:1000}.ql-multi-cursor .cursor{margin-left:-1px;position:absolute}.ql-multi-cursor .cursor-flag{bottom:100%;position:absolute;white-space:nowrap}.ql-multi-cursor .cursor-name{display:inline-block;color:#fff;padding:2px 8px}.ql-multi-cursor .cursor-caret{height:100%;position:absolute;width:2px}.ql-multi-cursor .cursor.hidden .cursor-flag{display:none}.ql-multi-cursor .cursor.top .cursor-flag{bottom:auto;top:100%}.ql-multi-cursor .cursor.right .cursor-flag{right:-2px}.ql-paste-manager{left:-100000px;position:absolute;top:50%}.ql-toolbar{box-sizing:border-box}.ql-tooltip{background-color:#fff;border:1px solid #000;box-sizing:border-box;position:absolute;top:0;white-space:nowrap;z-index:2000}.ql-tooltip a{cursor:pointer;text-decoration:none}.ql-container{box-sizing:border-box;cursor:text;font-family:Helvetica,Arial,sans-serif;height:100%;line-height:1.42;margin:0;overflow-x:hidden;overflow-y:auto;padding:12px 15px;position:relative}.ql-editor{box-sizing:border-box;min-height:100%;outline:0;tab-size:4;white-space:pre-wrap}.ql-editor div{margin:0;padding:0}.ql-editor a{text-decoration:underline}.ql-editor b{font-weight:700;font-style:bold}.ql-editor i{font-style:italic}.ql-editor s{text-decoration:line-through}.ql-editor u{text-decoration:underline}.ql-editor a,.ql-editor b,.ql-editor i,.ql-editor s,.ql-editor span,.ql-editor u{background-color:inherit}.ql-editor img{max-width:100%}.ql-editor blockquote,.ql-editor ol,.ql-editor ul{margin:0 0 0 2em;padding:0}.ql-editor ol{list-style-type:decimal}.ql-editor ul{list-style-type:disc}.ql-editor.ql-ie-10 br,.ql-editor.ql-ie-9 br{display:none}"; },{}],32:[function(_dereq_,module,exports){ var BaseTheme, _, baseStyles, dom; _ = _dereq_('lodash'); dom = _dereq_('../../lib/dom'); baseStyles = _dereq_('./base.styl'); BaseTheme = (function() { BaseTheme.OPTIONS = {}; BaseTheme.objToCss = function(obj) { return _.map(obj, function(value, key) { var innerStr; innerStr = _.map(value, function(innerValue, innerKey) { return innerKey + ": " + innerValue + ";"; }).join(' '); return key + " { " + innerStr + " }"; }).join("\n"); }; function BaseTheme(quill, options) { var version; this.quill = quill; this.options = options; dom(this.quill.container).addClass('ql-container'); if (this.options.styles) { this.addStyles(baseStyles + BaseTheme.objToCss(this.options.styles)); } if (dom.isIE(10)) { version = dom.isIE(9) ? '9' : '10'; dom(this.quill.root).addClass('ql-ie-' + version); } } BaseTheme.prototype.addStyles = function(css) { var style; if (_.isObject(css)) { css = BaseTheme.objToCss(css); } style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(css)); return document.head.appendChild(style); }; return BaseTheme; })(); module.exports = BaseTheme; },{"../../lib/dom":17,"./base.styl":31,"lodash":1}],33:[function(_dereq_,module,exports){ var BaseTheme, ColorPicker, Picker, SnowTheme, _, dom, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; _ = _dereq_('lodash'); ColorPicker = _dereq_('../../lib/color-picker'); BaseTheme = _dereq_('../base'); dom = _dereq_('../../lib/dom'); Picker = _dereq_('../../lib/picker'); SnowTheme = (function(superClass) { extend(SnowTheme, superClass); SnowTheme.COLORS = ["#000000", "#e60000", "#ff9900", "#ffff00", "#008A00", "#0066cc", "#9933ff", "#ffffff", "#facccc", "#ffebcc", "#ffffcc", "#cce8cc", "#cce0f5", "#ebd6ff", "#bbbbbb", "#f06666", "#ffc266", "#ffff66", "#66b966", "#66a3e0", "#c285ff", "#888888", "#a10000", "#b26b00", "#b2b200", "#006100", "#0047b2", "#6b24b2", "#444444", "#5c0000", "#663d00", "#666600", "#003700", "#002966", "#3d1466"]; SnowTheme.OPTIONS = { 'multi-cursor': { template: ' ' } }; function SnowTheme(quill, options) { this.quill = quill; this.options = options; SnowTheme.__super__.constructor.apply(this, arguments); dom(this.quill.container).addClass('ql-snow'); this.pickers = []; this.quill.on(this.quill.constructor.events.SELECTION_CHANGE, (function(_this) { return function(range) { if (range != null) { return _.invoke(_this.pickers, 'close'); } }; })(this)); this.quill.onModuleLoad('multi-cursor', _.bind(this.extendMultiCursor, this)); this.quill.onModuleLoad('toolbar', _.bind(this.extendToolbar, this)); } SnowTheme.prototype.extendMultiCursor = function(module) { return module.on(module.constructor.events.CURSOR_ADDED, function(cursor) { var bottomTriangle, topTriangle; bottomTriangle = cursor.elem.querySelector('.cursor-triangle.bottom'); topTriangle = cursor.elem.querySelector('.cursor-triangle.top'); return bottomTriangle.style.borderTopColor = topTriangle.style.borderBottomColor = cursor.color; }); }; SnowTheme.prototype.extendToolbar = function(module) { dom(module.container).addClass('ql-snow'); _.each(['color', 'background', 'font', 'size', 'align'], (function(_this) { return function(format) { var picker, select; select = module.container.querySelector(".ql-" + format); if (select == null) { return; } switch (format) { case 'font': case 'size': case 'align': picker = new Picker(select); break; case 'color': case 'background': picker = new ColorPicker(select); _.each(picker.container.querySelectorAll('.ql-picker-item'), function(item, i) { if (i < 7) { return dom(item).addClass('ql-primary-color'); } }); } if (picker != null) { return _this.pickers.push(picker); } }; })(this)); return _.each(dom(module.container).textNodes(), function(node) { if (dom(node).text().trim().length === 0) { return dom(node).remove(); } }); }; return SnowTheme; })(BaseTheme); module.exports = SnowTheme; },{"../../lib/color-picker":16,"../../lib/dom":17,"../../lib/picker":19,"../base":32,"lodash":1}]},{},[15])(15) });