diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..2fbab11 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": [ "react", "es2015" ] +} diff --git a/.gitignore b/.gitignore index ea90594..71f9bbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .DS_Store build/ node_modules/ +example/main* +.publish diff --git a/README.md b/README.md index 9c660d2..8cc9696 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,35 @@ -# react-tinymce +# react-mce React TinyMCE component ## Installing ```bash -$ npm install react-tinymce +$ npm install react-mce ``` ## Demo -http://instructure-react.github.io/react-tinymce/ +http://janstuemmel.github.io/react-mce/ ## Example -```js -import React from 'react'; -import ReactDOM from 'react-dom'; -import TinyMCE from 'react-tinymce'; - -const App = React.createClass({ - handleEditorChange(e) { - console.log(e.target.getContent()); - }, - - render() { - return ( - - ); - } -}); - -ReactDOM.render(, document.getElementById('container')); -``` +see [example.js](example/example.js) ## Dependency This component depends on `tinymce` being globally accessible. ```html - + ``` ## Contributing -install your dependencies: - -`npm install` - -rackt-cli depends on a version of babel-eslint that will not run successfully with -the rest of this project. Until an upgrade is available, after installing, -edit "node_modules/rackt-cli/package.json" -and update it's babel-eslint to at least 4.1.7. Then `npm install` in the rackt -directory, and return to project root. From here on you need to use the -rackt version in node modules, so either alias "rackt" to it's bin, or -just path each command into node_modules/.bin like below. - -To make sure the linter is happy and the functional tests run, execute: - -`./node_modules/.bin/rackt test` - -To release, you'll need to be an npm owner for react-tinymce, and already -have your machine currently authed with `npm adduser` - -https://docs.npmjs.com/cli/adduser - -use `./node_modules/.bin/rackt release` +```sh +# runs the karma/mocha testsuite on phantomjs +npm test +``` ## License diff --git a/dist/react-tinymce.js b/dist/react-tinymce.js deleted file mode 100644 index 0c3ba3e..0000000 --- a/dist/react-tinymce.js +++ /dev/null @@ -1,1967 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("React"), require("ReactDOM")); - else if(typeof define === 'function' && define.amd) - define(["React", "ReactDOM"], factory); - else if(typeof exports === 'object') - exports["ReactTinymce"] = factory(require("React"), require("ReactDOM")); - else - root["ReactTinymce"] = factory(root["React"], root["ReactDOM"]); -})(this, function(__WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_3__) { -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'; - - module.exports = __webpack_require__(1); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - var _react = __webpack_require__(2); - - var _react2 = _interopRequireDefault(_react); - - var _reactDom = __webpack_require__(3); - - var _lodashLangIsEqual = __webpack_require__(4); - - var _lodashLangIsEqual2 = _interopRequireDefault(_lodashLangIsEqual); - - var _lodashLangClone = __webpack_require__(29); - - var _lodashLangClone2 = _interopRequireDefault(_lodashLangClone); - - var _helpersUuid = __webpack_require__(44); - - var _helpersUuid2 = _interopRequireDefault(_helpersUuid); - - var _helpersUcFirst = __webpack_require__(45); - - var _helpersUcFirst2 = _interopRequireDefault(_helpersUcFirst); - - // Include all of the Native DOM and custom events from: - // https://github.com/tinymce/tinymce/blob/master/tools/docs/tinymce.Editor.js#L5-L12 - var EVENTS = ['focusin', 'focusout', 'click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'beforepaste', 'paste', 'cut', 'copy', 'selectionchange', 'mouseout', 'mouseenter', 'mouseleave', 'keydown', 'keypress', 'keyup', 'contextmenu', 'dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag', 'BeforeRenderUI', 'SetAttrib', 'PreInit', 'PostRender', 'init', 'deactivate', 'activate', 'NodeChange', 'BeforeExecCommand', 'ExecCommand', 'show', 'hide', 'ProgressState', 'LoadContent', 'SaveContent', 'BeforeSetContent', 'SetContent', 'BeforeGetContent', 'GetContent', 'VisualAid', 'remove', 'submit', 'reset', 'BeforeAddUndo', 'AddUndo', 'change', 'undo', 'redo', 'ClearUndos', 'ObjectSelected', 'ObjectResizeStart', 'ObjectResized', 'PreProcess', 'PostProcess', 'focus', 'blur', 'dirty']; - - // Note: because the capitalization of the events is weird, we're going to get - // some inconsistently-named handlers, for example compare: - // 'onMouseleave' and 'onNodeChange' - var HANDLER_NAMES = EVENTS.map(function (event) { - return 'on' + (0, _helpersUcFirst2['default'])(event); - }); - - var TinyMCE = _react2['default'].createClass({ - displayName: 'TinyMCE', - - propTypes: { - config: _react2['default'].PropTypes.object, - content: _react2['default'].PropTypes.string, - id: _react2['default'].PropTypes.string, - className: _react2['default'].PropTypes.string - }, - - getDefaultProps: function getDefaultProps() { - return { - config: {}, - content: '' - }; - }, - - componentWillMount: function componentWillMount() { - this.id = this.id || this.props.id || (0, _helpersUuid2['default'])(); - }, - - componentDidMount: function componentDidMount() { - var config = (0, _lodashLangClone2['default'])(this.props.config); - this._init(config); - }, - - componentWillReceiveProps: function componentWillReceiveProps(nextProps) { - if (!(0, _lodashLangIsEqual2['default'])(this.props.config, nextProps.config)) { - this._init(nextProps.config, nextProps.content); - } - if (!(0, _lodashLangIsEqual2['default'])(this.props.id, nextProps.id)) { - this.id = nextProps.id; - } - }, - - shouldComponentUpdate: function shouldComponentUpdate(nextProps) { - return !(0, _lodashLangIsEqual2['default'])(this.props.content, nextProps.content) || !(0, _lodashLangIsEqual2['default'])(this.props.config, nextProps.config); - }, - - componentWillUnmount: function componentWillUnmount() { - this._remove(); - }, - - render: function render() { - return this.props.config.inline ? _react2['default'].createElement('div', { - id: this.id, - className: this.props.className, - dangerouslySetInnerHTML: { __html: this.props.content } - }) : _react2['default'].createElement('textarea', { - id: this.id, - className: this.props.className, - defaultValue: this.props.content - }); - }, - - _init: function _init(config, content) { - var _this = this; - - if (this._isInit) { - this._remove(); - } - - // hide the textarea that is me so that no one sees it - (0, _reactDom.findDOMNode)(this).style.hidden = 'hidden'; - - var setupCallback = config.setup; - var hasSetupCallback = typeof setupCallback === 'function'; - - config.selector = '#' + this.id; - config.setup = function (editor) { - EVENTS.forEach(function (event, index) { - var handler = _this.props[HANDLER_NAMES[index]]; - if (typeof handler !== 'function') return; - editor.on(event, function (e) { - // native DOM events don't have access to the editor so we pass it here - handler(e, editor); - }); - }); - // need to set content here because the textarea will still have the - // old `this.props.content` - if (content) { - editor.on('init', function () { - editor.setContent(content); - }); - } - if (hasSetupCallback) { - setupCallback(editor); - } - }; - - tinymce.init(config); - - (0, _reactDom.findDOMNode)(this).style.hidden = ''; - - this._isInit = true; - }, - - _remove: function _remove() { - tinymce.EditorManager.execCommand('mceRemoveEditor', true, this.id); - this._isInit = false; - } - }); - - // add handler propTypes - HANDLER_NAMES.forEach(function (name) { - TinyMCE.propTypes[name] = _react2['default'].PropTypes.func; - }); - - module.exports = TinyMCE; - -/***/ }, -/* 2 */ -/***/ function(module, exports) { - - module.exports = __WEBPACK_EXTERNAL_MODULE_2__; - -/***/ }, -/* 3 */ -/***/ function(module, exports) { - - module.exports = __WEBPACK_EXTERNAL_MODULE_3__; - -/***/ }, -/* 4 */ -/***/ function(module, exports, __webpack_require__) { - - var baseIsEqual = __webpack_require__(5), - bindCallback = __webpack_require__(27); - - /** - * Performs a deep comparison between two values to determine if they are - * equivalent. If `customizer` is provided it's invoked to compare values. - * If `customizer` returns `undefined` comparisons are handled by the method - * instead. The `customizer` is bound to `thisArg` and invoked with up to - * 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; - } - - module.exports = isEqual; - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - var baseIsEqualDeep = __webpack_require__(6), - isObject = __webpack_require__(15), - isObjectLike = __webpack_require__(16); - - /** - * 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); - } - - module.exports = baseIsEqual; - - -/***/ }, -/* 6 */ -/***/ function(module, exports, __webpack_require__) { - - var equalArrays = __webpack_require__(7), - equalByTag = __webpack_require__(9), - equalObjects = __webpack_require__(10), - isArray = __webpack_require__(23), - isTypedArray = __webpack_require__(26); - - /** `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`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ - 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} [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; - } - - module.exports = baseIsEqualDeep; - - -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { - - var arraySome = __webpack_require__(8); - - /** - * 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; - } - - module.exports = equalArrays; - - -/***/ }, -/* 8 */ -/***/ function(module, exports) { - - /** - * 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; - } - - module.exports = arraySome; - - -/***/ }, -/* 9 */ -/***/ 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} object 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; - } - - module.exports = equalByTag; - - -/***/ }, -/* 10 */ -/***/ function(module, exports, __webpack_require__) { - - var keys = __webpack_require__(11); - - /** 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} [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; - } - - module.exports = equalObjects; - - -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { - - var getNative = __webpack_require__(12), - isArrayLike = __webpack_require__(17), - isObject = __webpack_require__(15), - shimKeys = __webpack_require__(21); - - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeKeys = getNative(Object, 'keys'); - - /** - * Creates an array of the own enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/6.0/#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 ? undefined : object.constructor; - if ((typeof Ctor == 'function' && Ctor.prototype === object) || - (typeof object != 'function' && isArrayLike(object))) { - return shimKeys(object); - } - return isObject(object) ? nativeKeys(object) : []; - }; - - module.exports = keys; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - - var isNative = __webpack_require__(13); - - /** - * 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; - } - - module.exports = getNative; - - -/***/ }, -/* 13 */ -/***/ function(module, exports, __webpack_require__) { - - var isFunction = __webpack_require__(14), - isObjectLike = __webpack_require__(16); - - /** Used to detect host constructors (Safari > 5). */ - var reIsHostCtor = /^\[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 check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to detect if a method is native. */ - var reIsNative = RegExp('^' + - fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') - .replace(/hasOwnProperty|(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 (isFunction(value)) { - return reIsNative.test(fnToString.call(value)); - } - return isObjectLike(value) && reIsHostCtor.test(value); - } - - module.exports = isNative; - - -/***/ }, -/* 14 */ -/***/ function(module, exports, __webpack_require__) { - - var isObject = __webpack_require__(15); - - /** `Object#toString` result references. */ - var funcTag = '[object Function]'; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; - - /** - * 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 - */ - function isFunction(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 which returns 'object' for typed array constructors. - return isObject(value) && objToString.call(value) == funcTag; - } - - module.exports = isFunction; - - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - /** - * 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'); - } - - module.exports = isObject; - - -/***/ }, -/* 16 */ -/***/ 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'; - } - - module.exports = isObjectLike; - - -/***/ }, -/* 17 */ -/***/ function(module, exports, __webpack_require__) { - - var getLength = __webpack_require__(18), - isLength = __webpack_require__(20); - - /** - * 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)); - } - - module.exports = isArrayLike; - - -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { - - var baseProperty = __webpack_require__(19); - - /** - * 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'); - - module.exports = getLength; - - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - /** - * 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]; - }; - } - - module.exports = baseProperty; - - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - /** - * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) - * of an array-like value. - */ - var MAX_SAFE_INTEGER = 9007199254740991; - - /** - * Checks if `value` is a valid array-like length. - * - * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#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; - } - - module.exports = isLength; - - -/***/ }, -/* 21 */ -/***/ function(module, exports, __webpack_require__) { - - var isArguments = __webpack_require__(22), - isArray = __webpack_require__(23), - isIndex = __webpack_require__(24), - isLength = __webpack_require__(20), - keysIn = __webpack_require__(25); - - /** 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 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; - } - - module.exports = shimKeys; - - -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { - - var isArrayLike = __webpack_require__(17), - isObjectLike = __webpack_require__(16); - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Native method references. */ - var propertyIsEnumerable = objectProto.propertyIsEnumerable; - - /** - * 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) && - hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); - } - - module.exports = isArguments; - - -/***/ }, -/* 23 */ -/***/ function(module, exports, __webpack_require__) { - - var getNative = __webpack_require__(12), - isLength = __webpack_require__(20), - isObjectLike = __webpack_require__(16); - - /** `Object#toString` result references. */ - var arrayTag = '[object Array]'; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; - - /* Native method references for those with the same name as other `lodash` methods. */ - var nativeIsArray = getNative(Array, 'isArray'); - - /** - * 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; - }; - - module.exports = isArray; - - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - /** Used to detect unsigned integer values. */ - var reIsUint = /^\d+$/; - - /** - * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) - * of an array-like value. - */ - var MAX_SAFE_INTEGER = 9007199254740991; - - /** - * 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; - } - - module.exports = isIndex; - - -/***/ }, -/* 25 */ -/***/ function(module, exports, __webpack_require__) { - - var isArguments = __webpack_require__(22), - isArray = __webpack_require__(23), - isIndex = __webpack_require__(24), - isLength = __webpack_require__(20), - isObject = __webpack_require__(15); - - /** 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 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; - } - - module.exports = keysIn; - - -/***/ }, -/* 26 */ -/***/ function(module, exports, __webpack_require__) { - - var isLength = __webpack_require__(20), - isObjectLike = __webpack_require__(16); - - /** `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 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 for native method references. */ - var objectProto = Object.prototype; - - /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; - - /** - * 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)]; - } - - module.exports = isTypedArray; - - -/***/ }, -/* 27 */ -/***/ function(module, exports, __webpack_require__) { - - var identity = __webpack_require__(28); - - /** - * 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); - }; - } - - module.exports = bindCallback; - - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - /** - * 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; - } - - module.exports = identity; - - -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { - - var baseClone = __webpack_require__(30), - bindCallback = __webpack_require__(27), - isIterateeCall = __webpack_require__(43); - - /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, - * otherwise they are assigned by reference. If `customizer` is provided it's - * 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 up to three 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, 3)) - : baseClone(value, isDeep); - } - - module.exports = clone; - - -/***/ }, -/* 30 */ -/***/ function(module, exports, __webpack_require__) { - - var arrayCopy = __webpack_require__(31), - arrayEach = __webpack_require__(32), - baseAssign = __webpack_require__(33), - baseForOwn = __webpack_require__(35), - initCloneArray = __webpack_require__(39), - initCloneByTag = __webpack_require__(40), - initCloneObject = __webpack_require__(42), - isArray = __webpack_require__(23), - isObject = __webpack_require__(15); - - /** `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 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 for native method references. */ - var objectProto = Object.prototype; - - /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ - var objToString = objectProto.toString; - - /** - * 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 its 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; - } - - module.exports = baseClone; - - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - /** - * 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; - } - - module.exports = arrayCopy; - - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - /** - * 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; - } - - module.exports = arrayEach; - - -/***/ }, -/* 33 */ -/***/ function(module, exports, __webpack_require__) { - - var baseCopy = __webpack_require__(34), - keys = __webpack_require__(11); - - /** - * 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); - } - - module.exports = baseAssign; - - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - /** - * 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; - } - - module.exports = baseCopy; - - -/***/ }, -/* 35 */ -/***/ function(module, exports, __webpack_require__) { - - var baseFor = __webpack_require__(36), - keys = __webpack_require__(11); - - /** - * 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); - } - - module.exports = baseForOwn; - - -/***/ }, -/* 36 */ -/***/ function(module, exports, __webpack_require__) { - - var createBaseFor = __webpack_require__(37); - - /** - * 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(); - - module.exports = baseFor; - - -/***/ }, -/* 37 */ -/***/ function(module, exports, __webpack_require__) { - - var toObject = __webpack_require__(38); - - /** - * 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; - }; - } - - module.exports = createBaseFor; - - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - var isObject = __webpack_require__(15); - - /** - * 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); - } - - module.exports = toObject; - - -/***/ }, -/* 39 */ -/***/ function(module, exports) { - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * 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; - } - - module.exports = initCloneArray; - - -/***/ }, -/* 40 */ -/***/ function(module, exports, __webpack_require__) { - - var bufferClone = __webpack_require__(41); - - /** `Object#toString` result references. */ - var boolTag = '[object Boolean]', - dateTag = '[object Date]', - numberTag = '[object Number]', - regexpTag = '[object RegExp]', - stringTag = '[object String]'; - - 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 `RegExp` flags from their coerced string values. */ - var reFlags = /\w*$/; - - /** - * 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; - } - - module.exports = initCloneByTag; - - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - /* WEBPACK VAR INJECTION */(function(global) {/** Native method references. */ - var ArrayBuffer = global.ArrayBuffer, - Uint8Array = global.Uint8Array; - - /** - * 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) { - var result = new ArrayBuffer(buffer.byteLength), - view = new Uint8Array(result); - - view.set(new Uint8Array(buffer)); - return result; - } - - module.exports = bufferClone; - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - /** - * 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; - } - - module.exports = initCloneObject; - - -/***/ }, -/* 43 */ -/***/ function(module, exports, __webpack_require__) { - - var isArrayLike = __webpack_require__(17), - isIndex = __webpack_require__(24), - isObject = __webpack_require__(15); - - /** - * 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; - } - - module.exports = isIterateeCall; - - -/***/ }, -/* 44 */ -/***/ function(module, exports) { - - 'use strict'; - - var count = 0; - module.exports = function uuid() { - return 'react-tinymce-' + count++; - }; - -/***/ }, -/* 45 */ -/***/ function(module, exports) { - - "use strict"; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports["default"] = ucFirst; - - function ucFirst(str) { - return str[0].toUpperCase() + str.substring(1); - } - - module.exports = exports["default"]; - -/***/ } -/******/ ]) -}); -; -//# sourceMappingURL=react-tinymce.js.map \ No newline at end of file diff --git a/dist/react-tinymce.min.js b/dist/react-tinymce.min.js deleted file mode 100644 index 43adbc3..0000000 --- a/dist/react-tinymce.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("React"),require("ReactDOM")):"function"==typeof define&&define.amd?define(["React","ReactDOM"],e):"object"==typeof exports?exports.ReactTinymce=e(require("React"),require("ReactDOM")):t.ReactTinymce=e(t.React,t.ReactDOM)}(this,function(t,e){return function(t){function e(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return t[n].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){"use strict";t.exports=r(1)},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}var o=r(2),c=n(o),i=r(3),u=r(4),a=n(u),f=r(29),s=n(f),p=r(44),l=n(p),d=r(45),b=n(d),y=["focusin","focusout","click","dblclick","mousedown","mouseup","mousemove","mouseover","beforepaste","paste","cut","copy","selectionchange","mouseout","mouseenter","mouseleave","keydown","keypress","keyup","contextmenu","dragend","dragover","draggesture","dragdrop","drop","drag","BeforeRenderUI","SetAttrib","PreInit","PostRender","init","deactivate","activate","NodeChange","BeforeExecCommand","ExecCommand","show","hide","ProgressState","LoadContent","SaveContent","BeforeSetContent","SetContent","BeforeGetContent","GetContent","VisualAid","remove","submit","reset","BeforeAddUndo","AddUndo","change","undo","redo","ClearUndos","ObjectSelected","ObjectResizeStart","ObjectResized","PreProcess","PostProcess","focus","blur","dirty"],v=y.map(function(t){return"on"+b["default"](t)}),j=c["default"].createClass({displayName:"TinyMCE",propTypes:{config:c["default"].PropTypes.object,content:c["default"].PropTypes.string,id:c["default"].PropTypes.string,className:c["default"].PropTypes.string},getDefaultProps:function(){return{config:{},content:""}},componentWillMount:function(){this.id=this.id||this.props.id||l["default"]()},componentDidMount:function(){var t=s["default"](this.props.config);this._init(t)},componentWillReceiveProps:function(t){a["default"](this.props.config,t.config)||this._init(t.config,t.content),a["default"](this.props.id,t.id)||(this.id=t.id)},shouldComponentUpdate:function(t){return!a["default"](this.props.content,t.content)||!a["default"](this.props.config,t.config)},componentWillUnmount:function(){this._remove()},render:function(){return this.props.config.inline?c["default"].createElement("div",{id:this.id,className:this.props.className,dangerouslySetInnerHTML:{__html:this.props.content}}):c["default"].createElement("textarea",{id:this.id,className:this.props.className,defaultValue:this.props.content})},_init:function(t,e){var r=this;this._isInit&&this._remove(),i.findDOMNode(this).style.hidden="hidden";var n=t.setup,o="function"==typeof n;t.selector="#"+this.id,t.setup=function(t){y.forEach(function(e,n){var o=r.props[v[n]];"function"==typeof o&&t.on(e,function(e){o(e,t)})}),e&&t.on("init",function(){t.setContent(e)}),o&&n(t)},tinymce.init(t),i.findDOMNode(this).style.hidden="",this._isInit=!0},_remove:function(){tinymce.EditorManager.execCommand("mceRemoveEditor",!0,this.id),this._isInit=!1}});v.forEach(function(t){j.propTypes[t]=c["default"].PropTypes.func}),t.exports=j},function(e,r){e.exports=t},function(t,r){t.exports=e},function(t,e,r){function n(t,e,r,n){r="function"==typeof r?c(r,n,3):void 0;var i=r?r(t,e):void 0;return void 0===i?o(t,e,r):!!i}var o=r(5),c=r(27);t.exports=n},function(t,e,r){function n(t,e,r,u,a,f){return t===e?!0:null==t||null==e||!c(t)&&!i(e)?t!==t&&e!==e:o(t,e,n,r,u,a,f)}var o=r(6),c=r(15),i=r(16);t.exports=n},function(t,e,r){function n(t,e,r,n,l,y,v){var j=u(t),h=u(e),g=s,x=s;j||(g=b.call(t),g==f?g=p:g!=p&&(j=a(t))),h||(x=b.call(e),x==f?x=p:x!=p&&(h=a(e)));var m=g==p,A=x==p,O=g==x;if(O&&!j&&!m)return c(t,e,g);if(!l){var w=m&&d.call(t,"__wrapped__"),P=A&&d.call(e,"__wrapped__");if(w||P)return r(w?t.value():t,P?e.value():e,n,l,y,v)}if(!O)return!1;y||(y=[]),v||(v=[]);for(var _=y.length;_--;)if(y[_]==t)return v[_]==e;y.push(t),v.push(e);var R=(j?o:i)(t,e,r,n,l,y,v);return y.pop(),v.pop(),R}var o=r(7),c=r(9),i=r(10),u=r(23),a=r(26),f="[object Arguments]",s="[object Array]",p="[object Object]",l=Object.prototype,d=l.hasOwnProperty,b=l.toString;t.exports=n},function(t,e,r){function n(t,e,r,n,c,i,u){var a=-1,f=t.length,s=e.length;if(f!=s&&!(c&&s>f))return!1;for(;++a-1&&t%1==0&&n>=t}var n=9007199254740991;t.exports=r},function(t,e,r){function n(t){for(var e=a(t),r=e.length,n=r&&t.length,f=!!n&&u(n)&&(c(t)||o(t)),p=-1,l=[];++p-1&&t%1==0&&e>t}var n=/^\d+$/,o=9007199254740991;t.exports=r},function(t,e,r){function n(t){if(null==t)return[];a(t)||(t=Object(t));var e=t.length;e=e&&u(e)&&(c(t)||o(t))&&e||0;for(var r=t.constructor,n=-1,f="function"==typeof r&&r.prototype===t,p=Array(e),l=e>0;++n +
+

TinyMCE Textarea

+ + + +
+
+

TinyMCE Inline

+ + + +
+ + ); + } +} + +ReactDOM.render(, document.getElementById('root')); diff --git a/example/index.html b/example/index.html new file mode 100644 index 0000000..d589de7 --- /dev/null +++ b/example/index.html @@ -0,0 +1,13 @@ + + + + + + React TinyMCE Example + + +
+ + + + diff --git a/examples/basic/app.js b/examples/basic/app.js deleted file mode 100644 index 08318be..0000000 --- a/examples/basic/app.js +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import TinyMCE from '../../lib/main'; - -const STYLES = { - container: { - fontFamily: 'Helvetica Neue, sans-serif', - padding: '0 25px' - }, - output: { - border: '1px solid #999', - borderRadius: 5, - fontFamily: 'Courier New, monospace', - padding: 10, - height: 250, - overflow: 'auto' - } -}; - -const App = React.createClass({ - getInitialState() { - return { - content: '

Welcome to react-tinymce

' - }; - }, - - handleEditorChange(e) { - this.setState({ - content: e.target.getContent() - }); - }, - - render() { - return ( -
-

react-tinymce

- -
- Output -
{this.state.content}
-
- ); - } -}); - -ReactDOM.render(, document.getElementById('example')); diff --git a/examples/basic/index.html b/examples/basic/index.html deleted file mode 100644 index 0b930e9..0000000 --- a/examples/basic/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - -React TinyMCE component - -
- - - diff --git a/examples/index.html b/examples/index.html deleted file mode 100644 index 6b9d0e2..0000000 --- a/examples/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..c11df62 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,52 @@ +const gulp = require('gulp'); +const gulpif = require('gulp-if'); +const babel = require('gulp-babel'); +const browserify = require('browserify'); +const source = require('vinyl-source-stream'); +const buffer = require('vinyl-buffer'); +const gutil = require('gulp-util'); +const uglify = require('gulp-uglify'); +const sourcemaps = require('gulp-sourcemaps'); +const babelify = require('babelify'); +var ghPages = require('gulp-gh-pages'); + +gulp.task('build:meta', () => { + return gulp.src([ 'README.md', 'package.json' ]) + .pipe(gulp.dest('build')); +}); + +gulp.task('build', [ 'build:meta' ], () => { + return gulp.src('lib/**/*.js') + .pipe(babel()) + .pipe(gulp.dest('build/lib')); +}); + +gulp.task('example', () => { + return bundle('./example/example.js', 'main.js', './example', true); +}); + +gulp.task('pages', [ 'example' ], function() { + return gulp.src('./example/**/*') + .pipe(ghPages()); +}); + +gulp.task('npm-release', [ 'build', 'pages' ]); + +function bundle(src, name, outDir, min) { + process.env.NODE_ENV = min ? 'production' : 'development'; + var b = browserify({ + entries: src, + debug: true, + transform: [ babelify ], + }); + return b.bundle() + .pipe(source(name)) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(gulpif(min, uglify({ + output: { ascii_only: true, max_line_len: 100000 } + }))) + .on('error', gutil.log) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(outDir)); +} diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..bcd332c --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,53 @@ +module.exports = function(config) { + config.set({ + + basePath: '', + + frameworks: [ + 'mocha', + 'browserify', + 'chai' + ], + + files: [ + + // tinymce + 'node_modules/tinymce/tinymce.min.js', + 'node_modules/tinymce/plugins/**/*.min.js', + 'node_modules/tinymce/themes/**/*.min.js', + { pattern: 'node_modules/tinymce/skins/**', watched: false, included: false }, + + // tests + 'test/**/*Spec.js', + ], + + exclude: [ + ], + + preprocessors: { + 'test/**/*Spec.js': [ 'browserify' ] + }, + + reporters: ['spec'], + + port: 9876, + + colors: true, + + logLevel: config.LOG_INFO, + + autoWatch: true, + + browsers: ['PhantomJS'], + + singleRun: false, + + concurrency: Infinity, + + // browserify configuration + browserify: { + debug: true, + transform: [ [ 'babelify' ] ] + } + }) +} diff --git a/lib/components/TinyMCE.js b/lib/components/TinyMCE.js index eb778e9..9b49f1c 100644 --- a/lib/components/TinyMCE.js +++ b/lib/components/TinyMCE.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; import isEqual from 'lodash/lang/isEqual'; import clone from 'lodash/lang/clone'; @@ -29,31 +30,24 @@ const HANDLER_NAMES = EVENTS.map((event) => { return 'on' + ucFirst(event); }); -const TinyMCE = React.createClass({ - displayName: 'TinyMCE', +class TinyMCE extends React.Component { - propTypes: { - config: React.PropTypes.object, - content: React.PropTypes.string, - id: React.PropTypes.string, - className: React.PropTypes.string - }, - - getDefaultProps() { - return { + constructor() { + super(); + this.state = { config: {}, content: '' }; - }, + } componentWillMount() { this.id = this.id || this.props.id || uuid(); - }, + } componentDidMount() { const config = clone(this.props.config); this._init(config); - }, + } componentWillReceiveProps(nextProps) { if (!isEqual(this.props.config, nextProps.config)) { @@ -62,18 +56,18 @@ const TinyMCE = React.createClass({ if (!isEqual(this.props.id, nextProps.id)) { this.id = nextProps.id; } - }, + } shouldComponentUpdate(nextProps) { return ( !isEqual(this.props.content, nextProps.content) || !isEqual(this.props.config, nextProps.config) ); - }, + } componentWillUnmount() { this._remove(); - }, + } render() { return this.props.config.inline ? ( @@ -89,7 +83,7 @@ const TinyMCE = React.createClass({ defaultValue={this.props.content} /> ); - }, + } _init(config, content) { if (this._isInit) { @@ -129,17 +123,26 @@ const TinyMCE = React.createClass({ findDOMNode(this).style.hidden = ''; this._isInit = true; - }, + } _remove() { tinymce.EditorManager.execCommand('mceRemoveEditor', true, this.id); this._isInit = false; } -}); +} + +TinyMCE.displayName = 'TinyMCE', + +TinyMCE.propTypes = { + config: PropTypes.object, + content: PropTypes.string, + id: PropTypes.string, + className: PropTypes.string +}, // add handler propTypes HANDLER_NAMES.forEach((name) => { - TinyMCE.propTypes[name] = React.PropTypes.func; + TinyMCE.propTypes[name] = PropTypes.func; }); module.exports = TinyMCE; diff --git a/lib/components/__tests__/TinyMCE-test.js b/lib/components/__tests__/TinyMCE-test.js deleted file mode 100644 index c717ead..0000000 --- a/lib/components/__tests__/TinyMCE-test.js +++ /dev/null @@ -1,11 +0,0 @@ -// import React 'react'; -// import TestUtils from 'react-addons-test-utils'; -// import TinyMCE from '../..//main'; -import { equal } from 'assert'; - -/* eslint func-names:0 */ -describe('react-tinymce', function() { - it('should render', function() { - equal(true, true); - }); -}); diff --git a/package.json b/package.json index 54c5510..b64bed6 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,66 @@ { - "name": "react-tinymce", + "name": "react-mce", "version": "0.5.1", "description": "React TinyMCE component", "main": "lib/main.js", "scripts": { - "test": "node_modules/.bin/rackt test --single-run --browsers Firefox", - "start": "node_modules/.bin/rackt server" + "test": "karma start --single-run", + "test-watch": "karma start", + "release": "gulp npm-release && npm version $1" }, "repository": { "type": "git", - "url": "https://github.com/instructure-react/react-tinymce.git" + "url": "https://github.com/janstuemmel/react-mce.git" }, - "homepage": "https://github.com/instructure-react/react-tinymce", + "homepage": "https://github.com/janstuemmel/react-mce", "keywords": [ "tinymce", "react-component" ], "author": "Matt Zabriskie", + "contributors": [ + "Jan Stümmel" + ], "license": "MIT", "peerDependencies": { "react": "^0.14.0 || ^15.0.0", "react-dom": "^0.14.0 || ^15.0.0" }, "devDependencies": { + "babel-preset-es2015": "^6.24.1", + "babel-preset-react": "^6.24.1", + "babelify": "^7.3.0", + "browserify": "^14.4.0", + "chai": "^4.0.2", + "domify": "^1.4.0", + "gulp": "^3.9.1", + "gulp-babel": "^6.1.2", + "gulp-gh-pages": "^0.5.4", + "gulp-if": "^2.0.2", + "gulp-sourcemaps": "^2.6.0", + "gulp-uglify": "^3.0.0", + "gulp-util": "^3.0.8", + "karma": "^1.7.0", + "karma-browserify": "^5.1.1", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "^2.1.1", + "karma-firefox-launcher": "^1.0.1", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.4", + "karma-spec-reporter": "0.0.31", + "mocha": "^3.4.2", + "mocha-test-container-support": "^0.2.0", "rackt-cli": "^0.5.3", - "react": "^15.0.0", - "react-dom": "^15.0.0" + "react": "^15.6.0", + "react-dom": "^15.6.0", + "sinon": "^2.3.4", + "tinymce": "^4.6.4", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0", + "watchify": "^3.9.0" }, "dependencies": { - "lodash": "^3.9.3" + "lodash": "^3.9.3", + "prop-types": "^15.5.10" } -} \ No newline at end of file +} diff --git a/test/TinyMCESpec.js b/test/TinyMCESpec.js new file mode 100644 index 0000000..a107a88 --- /dev/null +++ b/test/TinyMCESpec.js @@ -0,0 +1,36 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import domify from 'domify'; +import TestContainer from 'mocha-test-container-support'; + +import TinyMCE from '../'; + +describe('TinyMCE component tests', () => { + + var testContainer; + + beforeEach( function () { + testContainer = TestContainer.get(this); + }); + + + it('should render TinyMCE Component', () => { + + ReactDOM.render(, testContainer); + }); + + + it('should render TinyMCE Component inline', () => { + + var div = document.createElement('div'); + testContainer.appendChild(div); + + ReactDOM.render( + , + div + ); + }); + + +}); diff --git a/test/basicSpec.js b/test/basicSpec.js new file mode 100644 index 0000000..5504daf --- /dev/null +++ b/test/basicSpec.js @@ -0,0 +1,50 @@ +const domify = require('domify'); +const TestContainer = require('mocha-test-container-support'); + +describe('basic test with global tinymce', () => { + + var testContainer; + + beforeEach( function () { + testContainer = TestContainer.get(this); + }); + + + it('should be defined', () => { + + // when + var tm = global.tinymce + + // then + expect(tm).to.be.not.undefined + }); + + + it('should tinymceify textarea', () => { + + // given + testContainer.appendChild(document.createElement('textarea')); + + // when + tinymce.init({ selector: 'textarea' }); + + // then + expect(testContainer.childNodes[0].className).to.include('mce-tinymce'); + }); + + + it('should tinymceify textarea inline', () => { + + // given + const div = domify('
Hello World
') + testContainer.appendChild(div); + + // when + tinymce.init({ selector: '#inline', inline: true }); + + // then + expect(div.contentEditable).to.equal('true'); + expect(div.innerHTML).to.equal('

Hello World

'); + }); + +}); diff --git a/test/fixtures/badCreateClass.js b/test/fixtures/badCreateClass.js new file mode 100644 index 0000000..26a2711 --- /dev/null +++ b/test/fixtures/badCreateClass.js @@ -0,0 +1,5 @@ +const React = require('react'); +var test = React.createClass({ + render: function(){ return null; } +}); +module.exports = Test; diff --git a/test/fixtures/badPropTypes.js b/test/fixtures/badPropTypes.js new file mode 100644 index 0000000..802ff07 --- /dev/null +++ b/test/fixtures/badPropTypes.js @@ -0,0 +1,6 @@ +const React = require('react'); +class Test extends React.Component { + render() { return null; } +} +Test.propTypes = { foo: React.PropTypes.string }; +module.exports = Test; diff --git a/test/reactWarningSpec.js b/test/reactWarningSpec.js new file mode 100644 index 0000000..51c55a5 --- /dev/null +++ b/test/reactWarningSpec.js @@ -0,0 +1,55 @@ + +describe('createClass/PropTypes Error', () => { + + var warn; + + before(() => { + // let console.warn throw an error + warn = console.warn; + console.warn = (msg) => { throw new Error(msg); + }}); + + after(() => console.warn = warn); + + + it('should throw PropTypes Warning', () => { + + expect(() => { + + // when + var BadPropTypesTest = require('./fixtures/badPropTypes'); + }) + + // then + .to.throw(/^Warning: Accessing PropTypes via the main React/); + + }); + + + it('should throw createClass Warning', () => { + + expect(() => { + + // when + var BadPropTypesTest = require('./fixtures/badCreateClass'); + }) + + // then + .to.throw(/^Warning: Accessing createClass via the main React/); + + }); + + + it('should should not throw creatClass or PropTypes Warning', () => { + + expect(() => { + + // when + var TinyMCE = require('../') + }) + + // then + .to.not.throw(); + }); + +});