react-substance
Version:
A React implementation of the Substance editor library.
1,819 lines (1,527 loc) • 599 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react"));
else if(typeof define === 'function' && define.amd)
define(["react"], factory);
else if(typeof exports === 'object')
exports["ReactSubstance"] = factory(require("react"));
else
root["ReactSubstance"] = factory(root["React"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_19__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _interopRequireDefault = __webpack_require__(1)['default'];
exports.__esModule = true;
var _SubstanceEditor2 = __webpack_require__(2);
var _SubstanceEditor3 = _interopRequireDefault(_SubstanceEditor2);
exports.SubstanceEditor = _SubstanceEditor3['default'];
/***/ },
/* 1 */
/***/ function(module, exports) {
"use strict";
exports["default"] = function (obj) {
return obj && obj.__esModule ? obj : {
"default": obj
};
};
exports.__esModule = true;
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _inherits = __webpack_require__(3)['default'];
var _classCallCheck = __webpack_require__(18)['default'];
var _interopRequireDefault = __webpack_require__(1)['default'];
exports.__esModule = true;
var _react = __webpack_require__(19);
var _react2 = _interopRequireDefault(_react);
var _substanceUiEditor = __webpack_require__(20);
var _substanceUiEditor2 = _interopRequireDefault(_substanceUiEditor);
var _substanceUiComponent = __webpack_require__(143);
var _substanceUiComponent2 = _interopRequireDefault(_substanceUiComponent);
var $$ = _substanceUiComponent2['default'].$$;
var SubstanceEditor = (function (_React$Component) {
_inherits(SubstanceEditor, _React$Component);
function SubstanceEditor(props) {
_classCallCheck(this, SubstanceEditor);
_React$Component.call(this, props);
this.state = {
contentEditor: undefined
};
}
SubstanceEditor.prototype.componentDidMount = function componentDidMount() {
var container = this.refs.substance_editor;
this.setState({ contentEditor: _substanceUiComponent2['default'].mount($$(_substanceUiEditor2['default'], {
content: this.props.initialValue || ''
}), container) });
};
SubstanceEditor.prototype.render = function render() {
return _react2['default'].createElement(
'div',
{ className: 'substance-editor', ref: 'substance_editor' },
'Loading editor...'
);
};
return SubstanceEditor;
})(_react2['default'].Component);
exports['default'] = SubstanceEditor;
module.exports = exports['default'];
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var _Object$create = __webpack_require__(4)["default"];
var _Object$setPrototypeOf = __webpack_require__(7)["default"];
exports["default"] = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = _Object$create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) _Object$setPrototypeOf ? _Object$setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
exports.__esModule = true;
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
module.exports = { "default": __webpack_require__(5), __esModule: true };
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {
var $ = __webpack_require__(6);
module.exports = function create(P, D){
return $.create(P, D);
};
/***/ },
/* 6 */
/***/ function(module, exports) {
var $Object = Object;
module.exports = {
create: $Object.create,
getProto: $Object.getPrototypeOf,
isEnum: {}.propertyIsEnumerable,
getDesc: $Object.getOwnPropertyDescriptor,
setDesc: $Object.defineProperty,
setDescs: $Object.defineProperties,
getKeys: $Object.keys,
getNames: $Object.getOwnPropertyNames,
getSymbols: $Object.getOwnPropertySymbols,
each: [].forEach
};
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
module.exports = { "default": __webpack_require__(8), __esModule: true };
/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {
__webpack_require__(9);
module.exports = __webpack_require__(12).Object.setPrototypeOf;
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
// 19.1.3.19 Object.setPrototypeOf(O, proto)
var $def = __webpack_require__(10);
$def($def.S, 'Object', {setPrototypeOf: __webpack_require__(13).set});
/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {
var global = __webpack_require__(11)
, core = __webpack_require__(12)
, PROTOTYPE = 'prototype';
var ctx = function(fn, that){
return function(){
return fn.apply(that, arguments);
};
};
var $def = function(type, name, source){
var key, own, out, exp
, isGlobal = type & $def.G
, isProto = type & $def.P
, target = isGlobal ? global : type & $def.S
? global[name] : (global[name] || {})[PROTOTYPE]
, exports = isGlobal ? core : core[name] || (core[name] = {});
if(isGlobal)source = name;
for(key in source){
// contains in native
own = !(type & $def.F) && target && key in target;
if(own && key in exports)continue;
// export native or passed
out = own ? target[key] : source[key];
// prevent global pollution for namespaces
if(isGlobal && typeof target[key] != 'function')exp = source[key];
// bind timers to global for call from export context
else if(type & $def.B && own)exp = ctx(out, global);
// wrap global constructors for prevent change them in library
else if(type & $def.W && target[key] == out)!function(C){
exp = function(param){
return this instanceof C ? new C(param) : C(param);
};
exp[PROTOTYPE] = C[PROTOTYPE];
}(out);
else exp = isProto && typeof out == 'function' ? ctx(Function.call, out) : out;
// export
exports[key] = exp;
if(isProto)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
}
};
// type bitmap
$def.F = 1; // forced
$def.G = 2; // global
$def.S = 4; // static
$def.P = 8; // proto
$def.B = 16; // bind
$def.W = 32; // wrap
module.exports = $def;
/***/ },
/* 11 */
/***/ function(module, exports) {
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var UNDEFINED = 'undefined';
var global = module.exports = typeof window != UNDEFINED && window.Math == Math
? window : typeof self != UNDEFINED && self.Math == Math ? self : Function('return this')();
if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
/***/ },
/* 12 */
/***/ function(module, exports) {
var core = module.exports = {};
if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {
// Works with __proto__ only. Old v8 can't work with null proto objects.
/* eslint-disable no-proto */
var getDesc = __webpack_require__(6).getDesc
, isObject = __webpack_require__(14)
, anObject = __webpack_require__(15);
var check = function(O, proto){
anObject(O);
if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!");
};
module.exports = {
set: Object.setPrototypeOf || ('__proto__' in {} // eslint-disable-line
? function(buggy, set){
try {
set = __webpack_require__(16)(Function.call, getDesc(Object.prototype, '__proto__').set, 2);
set({}, []);
} catch(e){ buggy = true; }
return function setPrototypeOf(O, proto){
check(O, proto);
if(buggy)O.__proto__ = proto;
else set(O, proto);
return O;
};
}()
: undefined),
check: check
};
/***/ },
/* 14 */
/***/ function(module, exports) {
// http://jsperf.com/core-js-isobject
module.exports = function(it){
return it !== null && (typeof it == 'object' || typeof it == 'function');
};
/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {
var isObject = __webpack_require__(14);
module.exports = function(it){
if(!isObject(it))throw TypeError(it + ' is not an object!');
return it;
};
/***/ },
/* 16 */
/***/ function(module, exports, __webpack_require__) {
// optional / simple context binding
var aFunction = __webpack_require__(17);
module.exports = function(fn, that, length){
aFunction(fn);
if(that === undefined)return fn;
switch(length){
case 1: return function(a){
return fn.call(that, a);
};
case 2: return function(a, b){
return fn.call(that, a, b);
};
case 3: return function(a, b, c){
return fn.call(that, a, b, c);
};
} return function(/* ...args */){
return fn.apply(that, arguments);
};
};
/***/ },
/* 17 */
/***/ function(module, exports) {
module.exports = function(it){
if(typeof it != 'function')throw TypeError(it + ' is not a function!');
return it;
};
/***/ },
/* 18 */
/***/ function(module, exports) {
"use strict";
exports["default"] = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
exports.__esModule = true;
/***/ },
/* 19 */
/***/ function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_19__;
/***/ },
/* 20 */
/***/ function(module, exports, __webpack_require__) {
var Editor = __webpack_require__(21);
module.exports = Editor;
/***/ },
/* 21 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _ = __webpack_require__(22);
var Component = __webpack_require__(143);
var Surface = __webpack_require__(145);
var Registry = __webpack_require__(151);
var ContainerComponent = __webpack_require__(246);
var SubstanceArticle = __webpack_require__(248);
var DefaultToolbar = __webpack_require__(249);
var ListEditing = __webpack_require__(254);
var $$ = Component.$$;
var Clipboard = Surface.Clipboard;
var SurfaceManager = Surface.SurfaceManager;
var ContainerEditor = Surface.ContainerEditor;
var defaultComponents = {
"paragraph": __webpack_require__(255),
"heading": __webpack_require__(258),
"blockquote": __webpack_require__(259),
"codeblock": __webpack_require__(260),
"list": __webpack_require__(261),
"link": __webpack_require__(262)
};
var defaultTools = Surface.Tools;
// TODO: discuss how to organize editor extensions
var editingBehavior = [ new ListEditing() ];
// Editor
// ----------------
//
// A simple rich text editor implementation based on Substance
var Editor = Component.extend({
displayName: "Editor",
didInitialize: function() {
if (!this.config) this.config = {};
var ArticleClass = this.config.article || SubstanceArticle;
var components = this.config.components || defaultComponents;
var tools = this.config.tools || defaultTools;
this.doc = new ArticleClass();
this.doc.loadHtml(this.props.content);
// Editing Surface
this.surfaceManager = new SurfaceManager(this.doc);
this.clipboard = new Clipboard(this.surfaceManager, this.doc.getClipboardImporter(), this.doc.getClipboardExporter());
this.editor = new ContainerEditor('body');
// Editing behavior
_.each(editingBehavior, function(behavior) {
this.editor.extendBehavior(behavior);
}, this);
// Component registry
this.componentRegistry = new Registry();
_.each(components, function(ComponentClass, name) {
this.componentRegistry.add(name, ComponentClass);
}, this);
// Tool registry
this.toolRegistry = new Registry();
_.each(tools, function(ToolClass) {
this.toolRegistry.add(ToolClass.static.name, new ToolClass());
}, this);
// Dependency Injection
this.childContext = {
componentRegistry: this.componentRegistry,
toolRegistry: this.toolRegistry,
surfaceManager: this.surfaceManager
};
},
render: function() {
var el = $$('div').addClass('editor-component');
// Toolbar
var ToolbarClass = this.config.toolbar || DefaultToolbar;
var toolbar = $$(ToolbarClass);
toolbar.key('toolbar');
el.append(toolbar);
// Content Container
el.append($$(ContainerComponent)
.key('bodyContainer')
.attr({ contentEditable: true })
.addProps({
doc: this.doc,
node: this.doc.get('body'),
editor: this.editor
})
);
return el;
},
didReceiveProps: function() {
if (this.doc.toHtml() !== this.props.content) {
this.doc.loadHtml(this.props.content);
}
},
didMount: function() {
this.surfaceManager.on('selection:changed', this.onSelectionChanged, this);
this.clipboard.attach(this.$el[0]);
},
willUnmount: function() {
this.dispose();
},
dispose: function() {
var clipboard = this.clipboard;
var surfaceManager = this.surfaceManager;
if (clipboard) clipboard.detach(this.$el[0]);
if (surfaceManager) surfaceManager.dispose();
},
getContent: function() {
return this.doc.toHtml();
},
getDocument: function() {
return this.doc;
},
onSelectionChanged: function(sel, surface) {
this.toolRegistry.each(function(tool) {
tool.update(surface, sel);
}, this);
}
});
module.exports = Editor;
/***/ },
/* 22 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
/**
* Mostly taken from lodash.
*
* @class Helpers
* @static
* @module Basics
*/
var Helpers = {};
// Lang helpers
/**
* See https://lodash.com/docs#isEqual
* @method isEqual
*/
Helpers.isEqual = __webpack_require__(23);
/**
* See https://lodash.com/docs#isObject
* @method isObject
*/
Helpers.isObject = __webpack_require__(35);
/**
* See https://lodash.com/docs#isArray
* @method isArray
*/
Helpers.isArray = __webpack_require__(38);
/**
* See https://lodash.com/docs#isString
* @method isString
*/
Helpers.isString = __webpack_require__(46);
/**
* See https://lodash.com/docs#isNumber
* @method isNumber
*/
Helpers.isNumber = __webpack_require__(47);
/**
* See https://lodash.com/docs#isBoolean
* @method isBoolean
*/
Helpers.isBoolean = __webpack_require__(48);
/**
* See https://lodash.com/docs#isFunction
* @method isFunction
*/
Helpers.isFunction = __webpack_require__(49);
/**
* See https://lodash.com/docs#cloneDeep
* @method cloneDeep
*/
Helpers.cloneDeep = __webpack_require__(51);
/**
* See https://lodash.com/docs#clone
* @method clone
*/
Helpers.clone = __webpack_require__(64);
/**
* See https://lodash.com/docs#isEmpty
* @method isEmpty
*/
Helpers.isEmpty = __webpack_require__(66);
// Function helpers
/**
* See https://lodash.com/docs#bind
* @method bind
*/
Helpers.bind = __webpack_require__(67);
/**
* See https://lodash.com/docs#delay
* @method delay
*/
Helpers.delay = __webpack_require__(86);
/**
* See https://lodash.com/docs#debounce
* @method debounce
*/
Helpers.debounce = __webpack_require__(88);
// Object helpers
/**
* See https://lodash.com/docs#extend
* @method extend
*/
Helpers.extend = __webpack_require__(89);
/**
* See https://lodash.com/docs#omit
* @method omit
*/
Helpers.omit = __webpack_require__(93);
// Array helpers
/**
* See https://lodash.com/docs#last
* @method last
*/
Helpers.last = __webpack_require__(106);
/**
* See https://lodash.com/docs#first
* @method first
*/
Helpers.first = __webpack_require__(107);
/**
* See https://lodash.com/docs#compact
* @method compact
*/
Helpers.compact = __webpack_require__(108);
/**
* See https://lodash.com/docs#uniq
* @method uniq
*/
Helpers.uniq = __webpack_require__(109);
/**
* See https://lodash.com/docs#intersection
* @method intersection
*/
Helpers.intersection = __webpack_require__(118);
/**
* See https://lodash.com/docs#union
* @method union
*/
Helpers.union = __webpack_require__(119);
/**
* See https://lodash.com/docs#without
* @method without
*/
Helpers.without = __webpack_require__(120);
// Collection helpers
/**
* See https://lodash.com/docs#each
* @method each
*/
Helpers.each = __webpack_require__(121);
/**
* See https://lodash.com/docs#filter
* @method filter
*/
Helpers.filter = __webpack_require__(123);
/**
* See https://lodash.com/docs#includes
* @method includes
*/
Helpers.includes = __webpack_require__(126);
/**
* See https://lodash.com/docs#find
* @method find
*/
Helpers.find = __webpack_require__(129);
/**
* See https://lodash.com/docs#map
* @method map
*/
Helpers.map = __webpack_require__(132);
/**
* See https://lodash.com/docs#pluck
* @method pluck
*/
Helpers.pluck = __webpack_require__(134);
/**
* See https://lodash.com/docs#indexBy
* @method indexBy
*/
Helpers.indexBy = __webpack_require__(135);
/**
* See https://lodash.com/docs#sortBy
* @method sortBy
*/
Helpers.sortBy = __webpack_require__(137);
// String helpers
/**
* See https://lodash.com/docs#capitalize
* @method capitalize
*/
Helpers.capitalize = __webpack_require__(141);
/**
* Check if two arrays are equal.
*
* @method isArrayEqual
* @param {Array} a
* @param {Array} b
* @deprecated use `Helpers.isEqual` instead.
*/
Helpers.isArrayEqual = function(a, b) {
if (a === b) return true;
if (a === null || b === null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
};
/**
* Removes all occurrence of value in array using Array.splice
* I.e., this changes the array instead of creating a new one
* as _.without() does.
*
* @method deleteFromArray
* @param {Array} array
* @param value
*/
Helpers.deleteFromArray = function(array, value) {
for (var i = 0; i < array.length; i++) {
if (array[i] === value) {
array.splice(i, 1);
i--;
}
}
};
/**
* Clones a given object.
* Uses obj.clone() if available, otherwise delegates to _.cloneDeep().
*
* @method clone
* @param {Object} obj
* @return The cloned object.
*/
Helpers.deepclone = function(obj) {
if (obj === null || obj === undefined) {
return obj;
}
if (Helpers.isFunction(obj.clone)) {
return obj.clone();
}
return Helpers.deepclone(obj);
};
/**
* Alias for {{#crossLink "Helpers/cloneDeep:method"}}{{/crossLink}}.
* @method deepClone
*/
Helpers.deepclone = Helpers.cloneDeep;
/**
* Web helper to compute the relative offset of an element to an ancestor element.
*
* @method getRelativeOffset
* @param {jQuery.Selector} $element
* @param {jQuery.Selector} $ancestor
* @return An object with properties
* - top: Number
* - left: Number
*/
Helpers.getRelativeOffset = function ( $element, $ancestor ) {
var pos = $element.offset();
var ancestorPos = $ancestor.offset();
pos.left -= ancestorPos.left;
pos.top -= ancestorPos.top;
return pos;
};
Helpers.uuid = __webpack_require__(142);
module.exports = Helpers;
/***/ },
/* 23 */
/***/ function(module, exports, __webpack_require__) {
var baseIsEqual = __webpack_require__(24),
bindCallback = __webpack_require__(43),
isStrictComparable = __webpack_require__(45);
/**
* 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 _
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize comparing values.
* @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);
if (!customizer && isStrictComparable(value) && isStrictComparable(other)) {
return value === other;
}
var result = customizer ? customizer(value, other) : undefined;
return typeof result == 'undefined' ? baseIsEqual(value, other, customizer) : !!result;
}
module.exports = isEqual;
/***/ },
/* 24 */
/***/ function(module, exports, __webpack_require__) {
var baseIsEqualDeep = __webpack_require__(25);
/**
* 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} [isWhere] 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, isWhere, stackA, stackB) {
// Exit early for identical values.
if (value === other) {
// Treat `+0` vs. `-0` as not equal.
return value !== 0 || (1 / value == 1 / other);
}
var valType = typeof value,
othType = typeof other;
// Exit early for unlike primitive values.
if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') ||
value == null || other == null) {
// Return `false` unless both values are `NaN`.
return value !== value && other !== other;
}
return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB);
}
module.exports = baseIsEqual;
/***/ },
/* 25 */
/***/ function(module, exports, __webpack_require__) {
var equalArrays = __webpack_require__(26),
equalByTag = __webpack_require__(27),
equalObjects = __webpack_require__(28),
isArray = __webpack_require__(38),
isTypedArray = __webpack_require__(42);
/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
arrayTag = '[object Array]',
objectTag = '[object Object]';
/** Used for native method references. */
var objectProto = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Used to resolve the `toStringTag` of values.
* See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
* for more details.
*/
var objToString = objectProto.toString;
/**
* 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} [isWhere] 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, isWhere, 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);
}
var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
if (valWrapped || othWrapped) {
return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, 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, isWhere, stackA, stackB);
stackA.pop();
stackB.pop();
return result;
}
module.exports = baseIsEqualDeep;
/***/ },
/* 26 */
/***/ function(module, exports) {
/**
* 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} [isWhere] 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, isWhere, stackA, stackB) {
var index = -1,
arrLength = array.length,
othLength = other.length,
result = true;
if (arrLength != othLength && !(isWhere && othLength > arrLength)) {
return false;
}
// Deep compare the contents, ignoring non-numeric properties.
while (result && ++index < arrLength) {
var arrValue = array[index],
othValue = other[index];
result = undefined;
if (customizer) {
result = isWhere
? customizer(othValue, arrValue, index)
: customizer(arrValue, othValue, index);
}
if (typeof result == 'undefined') {
// Recursively compare arrays (susceptible to call stack limits).
if (isWhere) {
var othIndex = othLength;
while (othIndex--) {
othValue = other[othIndex];
result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB);
if (result) {
break;
}
}
} else {
result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB);
}
}
}
return !!result;
}
module.exports = equalArrays;
/***/ },
/* 27 */
/***/ function(module, exports) {
/** `Object#toString` result references. */
var boolTag = '[object Boolean]',
dateTag = '[object Date]',
errorTag = '[object Error]',
numberTag = '[object Number]',
regexpTag = '[object RegExp]',
stringTag = '[object String]';
/**
* 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
// But, treat `-0` vs. `+0` as not equal.
: (object == 0 ? ((1 / object) == (1 / 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;
}
module.exports = equalByTag;
/***/ },
/* 28 */
/***/ function(module, exports, __webpack_require__) {
var keys = __webpack_require__(29);
/** Used for native method references. */
var objectProto = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* 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} [isWhere] 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, isWhere, stackA, stackB) {
var objProps = keys(object),
objLength = objProps.length,
othProps = keys(other),
othLength = othProps.length;
if (objLength != othLength && !isWhere) {
return false;
}
var hasCtor,
index = -1;
while (++index < objLength) {
var key = objProps[index],
result = hasOwnProperty.call(other, key);
if (result) {
var objValue = object[key],
othValue = other[key];
result = undefined;
if (customizer) {
result = isWhere
? customizer(othValue, objValue, key)
: customizer(objValue, othValue, key);
}
if (typeof result == 'undefined') {
// Recursively compare objects (susceptible to call stack limits).
result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB);
}
}
if (!result) {
return false;
}
hasCtor || (hasCtor = key == 'constructor');
}
if (!hasCtor) {
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;
}
module.exports = equalObjects;
/***/ },
/* 29 */
/***/ function(module, exports, __webpack_require__) {
var isLength = __webpack_require__(30),
isNative = __webpack_require__(31),
isObject = __webpack_require__(35),
shimKeys = __webpack_require__(36);
/* Native method references for those with the same name as other `lodash` methods. */
var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys;
/**
* 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 inspect.
* @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) {
if (object) {
var Ctor = object.constructor,
length = object.length;
}
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
(typeof object != 'function' && (length && isLength(length)))) {
return shimKeys(object);
}
return isObject(object) ? nativeKeys(object) : [];
};
module.exports = keys;
/***/ },
/* 30 */
/***/ function(module, exports) {
/**
* Used as the maximum length of an array-like value.
* See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
* for more details.
*/
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
/**
* Checks if `value` is a valid array-like length.
*
* **Note:** This function is based on ES `ToLength`. See the
* [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
* for more details.
*
* @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;
}
module.exports = isLength;
/***/ },
/* 31 */
/***/ function(module, exports, __webpack_require__) {
var escapeRegExp = __webpack_require__(32),
isObjectLike = __webpack_require__(34);
/** `Object#toString` result references. */
var funcTag = '[object Function]';
/** Used to detect host constructors (Safari > 5). */
var reHostCtor = /^\[object .+?Constructor\]$/;
/** Used for native method references. */
var objectProto = Object.prototype;
/** Used to resolve the decompiled source of functions. */
var fnToString = Function.prototype.toString;
/**
* Used to resolve the `toStringTag` of values.
* See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
* for more details.
*/
var objToString = objectProto.toString;
/** Used to detect if a method is native. */
var reNative = RegExp('^' +
escapeRegExp(objToString)
.replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
/**
* 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 reNative.test(fnToString.call(value));
}
return (isObjectLike(value) && reHostCtor.test(value)) || false;
}
module.exports = isNative;
/***/ },
/* 32 */
/***/ function(module, exports, __webpack_require__) {
var baseToString = __webpack_require__(33);
/**
* Used to match `RegExp` special characters.
* See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special)
* for more details.
*/
var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
reHasRegExpChars = RegExp(reRegExpChars.source);
/**
* 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;
}
module.exports = escapeRegExp;
/***/ },
/* 33 */
/***/ function(module, exports) {
/**
* Converts `value` to a string if it is 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 + '');
}
module.exports = baseToString;
/***/ },
/* 34 */
/***/ function(module, exports) {
/**
* 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') || false;
}
module.exports = isObjectLike;
/***/ },
/* 35 */
/***/ function(module, exports) {
/**
* Checks if `value` is the language type of `Object`.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* **Note:** See the [ES5 spec](https://es5.github.io/#x8) for more details.
*
* @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 type == 'function' || (value && type == 'object') || false;
}
module.exports = isObject;
/***/ },
/* 36 */
/***/ function(module, exports, __webpack_require__) {
var isArguments = __webpack_require__(37),
isArray = __webpack_require__(38),
isIndex = __webpack_require__(39),
isLength = __webpack_require__(30),
keysIn = __webpack_require__(40),
support = __webpack_require__(41);
/** Used for native method references. */
var objectProto = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* 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 inspect.
* @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) || (support.nonEnumArgs && 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;
}
module.exports = shimKeys;
/***/ },
/* 37 */
/***/ function(module, exports, __webpack_require__) {
var isLength = __webpack_require__(30),
isObjectLike = __webpack_require__(34);
/** `Object#toString` result references. */
var argsTag = '[object Arguments]';
/** Used for native method references. */
var objectProto = Object.prototype;
/**
* Used to resolve the `toStringTag` of values.
* See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
* for more details.
*/
var objToString = objectProto.toString;
/**
* 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) {
var length = isObjectLike(value) ? value.length : undefined;
return (isLength(length) && objToString.call(value) == argsTag) || false;
}
module.exports = isArguments;
/***/ },
/* 38 */
/***/ function(module, exports, __webpack_require__) {
var isLength = __webpack_require__(30),
isNative = __webpack_require__(31),
isObjectLike = __webpack_require__(34);
/** `Object#toString` result references. */
var arrayTag = '[object Array]';
/** Used for native method references. */
var objectProto = Object.prototype;
/**
* Used to resolve the `toStringTag` of values.
* See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
* for more details.
*/
var objToString = objectProto.toString;
/* Native method references for those with the same name as other `lodash` methods. */
var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray;
/**
* 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) || false;
};
module.exports = isArray;
/***/ },
/* 39 */
/***/ function(module, exports) {
/**
* Used as the maximum length of an array-like value.
* See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
* for more details.
*/
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
/**
* 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 = +value;
length = length == null ? MAX_SAFE_INTEGER : length;
return value > -1 && value % 1 == 0 && value < length;
}
module.exports = isIndex;
/***/ },
/* 40 */
/***/ function(module, exports, __webpack_require__) {
var isArguments = __webpack_require__(37),
isArray = __webpack_require__(38),
isIndex = __webpack_require__(39),
isLength = __webpack_require__(30),
isObject = __webpack_require__(35),
support = __webpack_require__(41);
/** Used for native method references. */
var objectProto = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* 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 inspect.
* @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) || (support.nonEnumArgs && 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;
}
module.exports = keysIn;
/***/ },
/* 41 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {var isNative = __webpack_require__(31);
/** Used to detect functions containing a `this` reference. */
var reThis = /\bthis\b/;
/** Used for native method references. */
var objectProto = Object.prototype;
/** Used to detect DOM support. */
var document = (document = global.window) && document.document;
/** Native method references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;
/**
* An object environment feature flags.
*
* @static
* @memberOf _
* @type Object
*/
var support = {};
(function(x) {
/**
* Detect if functions can be decompiled by `Function#toString`
* (all but Firefox OS certified apps, older Opera mobile browsers, and
* the PlayStation 3; forced `false` for Windows 8 apps).
*
* @memberOf _.support
* @type boolean
*/
support.funcDecomp = !isNative(global.WinRTError) && reThis.test(function() { return this; });
/**
* Detect if `Function#name` is supported (all but IE).
*
* @memberOf _.support
* @type boolean
*/
support.funcNames = typeof Function.name == 'string';
/**
* Detect if the DOM is supported.
*
* @memberOf _.support
* @type boolean
*/
try {
support.dom = document.createDocumentFragment().nodeType === 11;
} catch(e) {
support.dom = false;
}
/**
* Detect if `arguments` object indexes are non-enumerable.
*
* In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object
* indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat
* `arguments` object indexes as non-enumerable and fail `hasOwnProperty`
* checks for indexes that exceed their function's formal parameters with
* associated values of `0`.
*
* @memberOf _.support
* @type boolean
*/
try {
support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1);
} catch(e) {
support.nonEnumArgs = true;
}
}(0, 0));
module.exports = support;
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
/***/ },
/* 42 */
/***/ function(module, exports, __webpack_require__) {
var isLength = __webpack_require__(30),
isObjectLike = __webpack_require__(34);
/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
arrayTag = '[object Array]',
boolTag = '[object Boolean]',
dateTag = '[object Date]',
errorTag = '[object Error]',
funcTag = '[object Fu