diff --git a/build/codex-editor.js b/build/codex-editor.js index b85744ea..47dbe631 100644 --- a/build/codex-editor.js +++ b/build/codex-editor.js @@ -244,6 +244,20 @@ var Util = function () { return Array.prototype.slice.call(collection); } + + /** + * Checks if object is empty + * + * @param {Object} object + * @return {boolean} + */ + + }, { + key: "isEmpty", + value: function isEmpty(object) { + + return Object.keys(object).length === 0 && object.constructor === Object; + } }]); return Util; @@ -471,7 +485,7 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var modules = ["blockManager.js","events.js","renderer.js","toolbar.js","tools.js","ui.js"].map(function (module) { +var modules = ["blockManager.js","events.js","renderer.js","sanitizer.js","toolbar.js","tools.js","ui.js"].map(function (module) { return __webpack_require__(4)("./" + module); }); @@ -813,11 +827,12 @@ module.exports = function () { var map = { "./blockManager.js": 5, - "./events.js": 7, - "./renderer.js": 8, - "./toolbar.js": 9, - "./tools.js": 10, - "./ui.js": 11 + "./events.js": 6, + "./renderer.js": 7, + "./sanitizer.js": 8, + "./toolbar.js": 10, + "./tools.js": 11, + "./ui.js": 12 }; function webpackContext(req) { return __webpack_require__(webpackContextResolve(req)); @@ -847,7 +862,7 @@ var _createClass = function () { function defineProperties(target, props) { for * @classdesc Manage editor`s blocks storage and appearance */ -var _block = __webpack_require__(6); +var _block = __webpack_require__(15); var _block2 = _interopRequireDefault(_block); @@ -1294,94 +1309,6 @@ module.exports = BlockManager; /* 6 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; -/* WEBPACK VAR INJECTION */(function($) { - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * - * @class Block - * @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool - * - * @property {Tool} tool — current block tool (Paragraph, for example) - * @property {Object} CSS — block`s css classes - * - */ - -var Block = function () { - - /** - * @constructor - * - * @param {Object} tool — current block plugin`s instance - */ - function Block(tool) { - _classCallCheck(this, Block); - - this.tool = tool; - - this.CSS = { - wrapper: 'ce-block', - content: 'ce-block__content' - }; - - this._html = this.compose(); - } - - /** - * Make default block wrappers and put tool`s content there - * - * @returns {HTMLDivElement} - * @private - */ - - - _createClass(Block, [{ - key: 'compose', - value: function compose() { - - var wrapper = $.make('div', this.CSS.wrapper), - content = $.make('div', this.CSS.content); - - content.appendChild(this.tool.html); - wrapper.appendChild(content); - - return wrapper; - } - - /** - * Get block`s HTML - * - * @returns {HTMLDivElement} - */ - - }, { - key: 'html', - get: function get() { - - return this._html; - } - }]); - - return Block; -}(); - -Block.displayName = 'Block'; -exports.default = Block; -module.exports = exports['default']; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - "use strict"; /* WEBPACK VAR INJECTION */(function(Module) { @@ -1483,7 +1410,7 @@ module.exports = exports["default"]; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) /***/ }), -/* 8 */ +/* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -1787,10 +1714,376 @@ module.exports = Renderer; // })({}); /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1))) +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(Module, _) { + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(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; } + +/** + * Codex Sanitizer + * + * @module Sanitizer module + * Clears HTML from taint tags + * + * @version 2.0.0 + * + * @usage + * Module can be used within two ways: + * 1) When you have an instance + * - this.moduleInstance['Sanitizer'].clean(yourDirtyString); + * 2) As static method + * - CodexEditor.Sanitizer.clean(yourDirtyString, yourCustomConfiguration); + * + * + * Look up the SanitizerConfig object as example to make your custom restrictions + */ + +/** + * @typedef {Object} SanitizerConfig + * @property {Object} tags - define tags restrictions + * + * @example + * + * tags : { + * p: true, + * a: { + * href: true, + * rel: "nofollow", + * target: "_blank" + * } + * } + */ +var Sanitizer = function (_Module) { + _inherits(Sanitizer, _Module); + + /** + * Initializes Sanitizer module + * Sets default configuration if custom not exists + * + * @property {HTMLJanitor} this.janitor - Sanitizer library + * + * @param {SanitizerConfig} config + */ + function Sanitizer(config) { + _classCallCheck(this, Sanitizer); + + // default config + var _this = _possibleConstructorReturn(this, (Sanitizer.__proto__ || Object.getPrototypeOf(Sanitizer)).call(this, config)); + + _this.instantConfig = {}; + _this.janitorInstance = null; + + /** Custom configuration */ + _this.sanitizerConfig = config.settings ? config.settings.sanitizer : {}; + + /** HTML Janitor library */ + _this.sanitizerInstance = __webpack_require__(9); + + return _this; + } + + /** + * If developer uses editor's API, then he can customize sanitize restrictions. + * Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere + * At least, if there is no config overrides, that API uses Default configuration + * + * @uses https://www.npmjs.com/package/html-janitor + * + * @param {HTMLJanitor} library - sanitizer extension + */ + + + _createClass(Sanitizer, [{ + key: 'clean', + + + /** + * Cleans string from unwanted tags + * @param {String} taintString - HTML string + * + * @return {String} clean HTML + */ + value: function clean(taintString) { + + return this.janitorInstance.clean(taintString); + } + + /** + * Cleans string from unwanted tags + * @static + * + * Method allows to use default config + * + * @param {String} taintString - taint string + * @param {SanitizerConfig} customConfig - allowed tags + * + * @return {String} clean HTML + */ + + }, { + key: 'sanitizerInstance', + set: function set(library) { + + this.janitorInstance = new library(this.instanceConfig); + } + + /** + * Sets sanitizer configuration. Uses default config if user didn't pass the restriction + * @param {SanitizerConfig} config + */ + + }, { + key: 'sanitizerConfig', + set: function set(config) { + + if (_.isEmpty(config)) { + + this.instanceConfig = { + tags: { + p: {}, + a: { + href: true, + target: '_blank', + rel: 'nofollow' + } + } + }; + } else { + + this.instanceConfig = config; + } + } + }], [{ + key: 'clean', + value: function clean(taintString, customConfig) { + + var newInstance = Sanitizer(customConfig); + + return newInstance.clean(taintString); + } + }]); + + return Sanitizer; +}(Module); + +Sanitizer.displayName = 'Sanitizer'; +exports.default = Sanitizer; +module.exports = exports['default']; +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1))) + /***/ }), /* 9 */ /***/ (function(module, exports, __webpack_require__) { +var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory) { + if (true) { + !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : + __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.HTMLJanitor = factory(); + } +}(this, function () { + + /** + * @param {Object} config.tags Dictionary of allowed tags. + * @param {boolean} config.keepNestedBlockElements Default false. + */ + function HTMLJanitor(config) { + + var tagDefinitions = config['tags']; + var tags = Object.keys(tagDefinitions); + + var validConfigValues = tags + .map(function(k) { return typeof tagDefinitions[k]; }) + .every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; }); + + if(!validConfigValues) { + throw new Error("The configuration was invalid"); + } + + this.config = config; + } + + // TODO: not exhaustive? + var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE']; + function isBlockElement(node) { + return blockElementNames.indexOf(node.nodeName) !== -1; + } + + var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE']; + function isInlineElement(node) { + return inlineElementNames.indexOf(node.nodeName) !== -1; + } + + HTMLJanitor.prototype.clean = function (html) { + var sandbox = document.createElement('div'); + sandbox.innerHTML = html; + + this._sanitize(sandbox); + + return sandbox.innerHTML; + }; + + HTMLJanitor.prototype._sanitize = function (parentNode) { + var treeWalker = createTreeWalker(parentNode); + var node = treeWalker.firstChild(); + if (!node) { return; } + + do { + // Ignore nodes that have already been sanitized + if (node._sanitized) { + continue; + } + + if (node.nodeType === Node.TEXT_NODE) { + // If this text node is just whitespace and the previous or next element + // sibling is a block element, remove it + // N.B.: This heuristic could change. Very specific to a bug with + // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output + // FIXME: make this an option? + if (node.data.trim() === '' + && ((node.previousElementSibling && isBlockElement(node.previousElementSibling)) + || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) { + parentNode.removeChild(node); + this._sanitize(parentNode); + break; + } else { + continue; + } + } + + // Remove all comments + if (node.nodeType === Node.COMMENT_NODE) { + parentNode.removeChild(node); + this._sanitize(parentNode); + break; + } + + var isInline = isInlineElement(node); + var containsBlockElement; + if (isInline) { + containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement); + } + + // Block elements should not be nested (e.g.
  • ...); if + // they are, we want to unwrap the inner block element. + var isNotTopContainer = !! parentNode.parentNode; + var isNestedBlockElement = + isBlockElement(parentNode) && + isBlockElement(node) && + isNotTopContainer; + + var nodeName = node.nodeName.toLowerCase(); + + var allowedAttrs = getAllowedAttrs(this.config, nodeName, node); + + var isInvalid = isInline && containsBlockElement; + + // Drop tag entirely according to the whitelist *and* if the markup + // is invalid. + if (isInvalid || shouldRejectNode(node, allowedAttrs) + || (!this.config.keepNestedBlockElements && isNestedBlockElement)) { + // Do not keep the inner text of SCRIPT/STYLE elements. + if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) { + while (node.childNodes.length > 0) { + parentNode.insertBefore(node.childNodes[0], node); + } + } + parentNode.removeChild(node); + + this._sanitize(parentNode); + break; + } + + // Sanitize attributes + for (var a = 0; a < node.attributes.length; a += 1) { + var attr = node.attributes[a]; + + if (shouldRejectAttr(attr, allowedAttrs, node)) { + node.removeAttribute(attr.name); + // Shift the array to continue looping. + a = a - 1; + } + } + + // Sanitize children + this._sanitize(node); + + // Mark node as sanitized so it's ignored in future runs + node._sanitized = true; + } while ((node = treeWalker.nextSibling())); + }; + + function createTreeWalker(node) { + return document.createTreeWalker(node, + NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, + null, false); + } + + function getAllowedAttrs(config, nodeName, node){ + if (typeof config.tags[nodeName] === 'function') { + return config.tags[nodeName](node); + } else { + return config.tags[nodeName]; + } + } + + function shouldRejectNode(node, allowedAttrs){ + if (typeof allowedAttrs === 'undefined') { + return true; + } else if (typeof allowedAttrs === 'boolean') { + return !allowedAttrs; + } + + return false; + } + + function shouldRejectAttr(attr, allowedAttrs, node){ + var attrName = attr.name.toLowerCase(); + + if (allowedAttrs === true){ + return false; + } else if (typeof allowedAttrs[attrName] === 'function'){ + return !allowedAttrs[attrName](attr.value, node); + } else if (typeof allowedAttrs[attrName] === 'undefined'){ + return true; + } else if (allowedAttrs[attrName] === false) { + return true; + } else if (typeof allowedAttrs[attrName] === 'string') { + return (allowedAttrs[attrName] !== attr.value); + } + + return false; + } + + return HTMLJanitor; + +})); + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + "use strict"; /* WEBPACK VAR INJECTION */(function(Module, $) { @@ -2008,7 +2301,7 @@ module.exports = exports['default']; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(2))) /***/ }), -/* 10 */ +/* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -2271,7 +2564,7 @@ module.exports = exports['default']; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1))) /***/ }), -/* 11 */ +/* 12 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -2446,7 +2739,7 @@ var UI = function (_Module) { /** * Load CSS */ - var styles = __webpack_require__(12); + var styles = __webpack_require__(13); /** * Make tag @@ -2735,10 +3028,10 @@ module.exports = exports['default']; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(2))) /***/ }), -/* 12 */ +/* 13 */ /***/ (function(module, exports, __webpack_require__) { -exports = module.exports = __webpack_require__(13)(undefined); +exports = module.exports = __webpack_require__(14)(undefined); // imports @@ -2749,7 +3042,7 @@ exports.push([module.i, ":root {\n\n /**\n * Toolbar buttons\n */\n\n /***/ }), -/* 13 */ +/* 14 */ /***/ (function(module, exports) { /* @@ -2830,6 +3123,94 @@ function toComment(sourceMap) { } +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function($) { + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * + * @class Block + * @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool + * + * @property {Tool} tool — current block tool (Paragraph, for example) + * @property {Object} CSS — block`s css classes + * + */ + +var Block = function () { + + /** + * @constructor + * + * @param {Object} tool — current block plugin`s instance + */ + function Block(tool) { + _classCallCheck(this, Block); + + this.tool = tool; + + this.CSS = { + wrapper: 'ce-block', + content: 'ce-block__content' + }; + + this._html = this.compose(); + } + + /** + * Make default block wrappers and put tool`s content there + * + * @returns {HTMLDivElement} + * @private + */ + + + _createClass(Block, [{ + key: 'compose', + value: function compose() { + + var wrapper = $.make('div', this.CSS.wrapper), + content = $.make('div', this.CSS.content); + + content.appendChild(this.tool.html); + wrapper.appendChild(content); + + return wrapper; + } + + /** + * Get block`s HTML + * + * @returns {HTMLDivElement} + */ + + }, { + key: 'html', + get: function get() { + + return this._html; + } + }]); + + return Block; +}(); + +Block.displayName = 'Block'; +exports.default = Block; +module.exports = exports['default']; +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) + /***/ }) /******/ ]); //# sourceMappingURL=codex-editor.js.map \ No newline at end of file diff --git a/build/codex-editor.js.map b/build/codex-editor.js.map index 81c517c5..3da323ba 100644 --- a/build/codex-editor.js.map +++ b/build/codex-editor.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap 0f36217c23af5eb40c0b","webpack:///./src/components/__module.js","webpack:///./src/components/utils.js","webpack:///./src/components/dom.js","webpack:///./src/codex.js","webpack:///./src/components/modules nonrecursive [^_](blockManager.js|events.js|renderer.js|toolbar.js|tools.js|ui.js)$","webpack:///./src/components/modules/blockManager.js","webpack:///./src/components/block.js","webpack:///./src/components/modules/events.js","webpack:///./src/components/modules/renderer.js","webpack:///./src/components/modules/toolbar.js","webpack:///./src/components/modules/tools.js","webpack:///./src/components/modules/ui.js","webpack:///./src/styles/main.css","webpack:///./node_modules/css-loader/lib/css-base.js"],"names":["Module","config","new","target","TypeError","Editor","Util","chains","success","fallback","Promise","resolve","reduce","previousValue","currentValue","iteration","then","waitNextBlock","length","chainData","successCallback","fallbackCallback","function","data","catch","collection","Array","prototype","slice","call","Dom","tagName","classNames","attributes","el","document","createElement","isArray","classList","add","attrName","parent","elements","forEach","appendChild","selector","querySelector","querySelectorAll","node","nodeType","Node","ELEMENT_NODE","modules","editorModules","map","module","exports","moduleInstances","configuration","init","start","console","log","error","constructModules","configureModules","displayName","e","name","state","getModulesDiff","diff","moduleName","prepareDecorator","prepare","UI","Tools","items","Renderer","render","BlockManager","holderId","placeholder","sanitizer","p","b","a","hideToolbar","tools","toolsConfig","_blocks","currentBlockIndex","blocks","Blocks","nodes","redactor","Proxy","set","get","toolName","toolInstance","construct","block","insert","element","index","indexOf","array","workingArea","push","html","replace","remove","deleteCount","splice","previousBlock","insertAdjacentElement","nextBlock","targetBlock","newBlock","_","children","instance","isNaN","Number","Block","tool","CSS","wrapper","content","_html","compose","$","make","Events","subscribers","eventName","callback","previousData","currentHandler","newData","i","insertBlock","sequence","item","type","Toolbar","actions","plusButton","toolbox","settingsToggler","removeBlockButton","settings","pluginSettings","defaultSettings","toolbar","append","makeRemoveBlockButton","makeBlockSettingsPanel","toolsAvailable","toolsUnavailable","iconClassName","displayInToolbox","enableLineBreaks","toolClasses","hasOwnProperty","reject","sequenceData","getListOfPrepareFunctions","toolPreparationList","toolClass","toolInstances","plugin","editorWrapper","editorZone","holder","getElementById","Error","loadStyles","styles","require","tag","textContent","toString","head"],"mappings":"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ACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,U;;;;;;;;;;;;;;;;;;;;;;ACjRA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmDqBoE,O;;;AAEjB;;;AAGA,mBAAYjJ,MAAZ,EAAoB;AAAA;;AAAA,kHAEVA,MAFU;;AAIhB,UAAK6F,KAAL,GAAa;AACTkC,eAAU,IADD;AAETC,eAAU,IAFD;AAGTkB,eAAU,IAHD;;AAKT;AACAC,kBAAa,IANJ;AAOTC,eAAU,IAPD;;AAST;AACAC,uBAAkB,IAVT;AAWTC,yBAAmB,IAXV;AAYTC,gBAAU,IAZD;;AAcT;AACAC,sBAAgB,IAfP;AAgBTC,uBAAiB;AAhBR,KAAb;;AAmBA,UAAK3B,GAAL,GAAW;AACP4B,eAAS,YADF;AAEP1B,eAAS,qBAFF;AAGPkB,eAAS,qBAHF;;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ApB;AACA;;;AAGA,eAAK6C,UAAL;;AAEAvK;AAEH,OAnCM;;AAqCP;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAlDO,OAoDFa,KApDE,CAoDI,aAAK;;AAERqC,gBAAQE,KAAR,CAAcI,CAAd;;AAEJ;AAEC,OA1DE,CAAP;AA4DH;;;iCAEY;;AAET;;;AAGA,UAAIgH,SAAS,mBAAAC,CAAQ,EAAR,CAAb;;AAEA;;;AAGA,UAAIC,MAAMjD,EAAEC,IAAF,CAAO,OAAP,EAAgB,IAAhB,EAAsB;AAC5BiD,qBAAaH,OAAOI,QAAP;AADe,OAAtB,CAAV;;AAIA;;;AAGAnD,QAAEwB,MAAF,CAASzH,SAASqJ,IAAlB,EAAwBH,GAAxB;AAEH;;;;EA3G2BrL,M;;AA+GhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;kBApXqB2E,E;;;;;;;;ACzDrB;AACA;;;AAGA;AACA,gCAAiC,iDAAiD,2CAA2C,yBAAyB,6BAA6B,oBAAoB,GAAG,uBAAuB,wBAAwB,OAAO;;AAEhQ;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,mCAAmC,gBAAgB;AACnD,IAAI;AACJ;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAgB,iBAAiB;AACjC;AACA;AACA;AACA;AACA,YAAY,oBAAoB;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,oDAAoD,cAAc;;AAElE;AACA","file":"codex-editor.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 3);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 0f36217c23af5eb40c0b","/**\n * @abstract\n * @class Module\n * @classdesc All modules inherites from this class.\n *\n * @typedef {Module} Module\n * @property {Object} config - Editor user settings\n * @property {Object} Editor - List of Editor modules\n */\nexport default class Module {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor(config) {\n\n if (new.target === Module) {\n\n throw new TypeError('Constructors for abstract class Module are not allowed.');\n\n }\n\n this.config = config;\n this.Editor = null;\n\n }\n\n /**\n * Editor modules setter\n *\n * @param Editor\n * @param Editor.modules {@link CodexEditor#moduleInstances}\n * @param Editor.config {@link CodexEditor#configuration}\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/__module.js","/**\n * Codex Editor Util\n */\nexport default class Util {\n\n /**\n * @typedef {Object} ChainData\n * @property {Object} data - data that will be passed to the success or fallback\n * @property {Function} function - function's that must be called asynchronically\n */\n\n /**\n * Fires a promise sequence asyncronically\n *\n * @param {Object[]} chains - list or ChainData's\n * @param {Function} success - success callback\n * @param {Function} fallback - callback that fires in case of errors\n *\n * @return {Promise}\n */\n static sequence(chains, success = () => {}, fallback = () => {}) {\n\n return new Promise(function (resolve) {\n\n /**\n * pluck each element from queue\n * First, send resolved Promise as previous value\n * Each plugins \"prepare\" method returns a Promise, that's why\n * reduce current element will not be able to continue while can't get\n * a resolved Promise\n */\n chains.reduce(function (previousValue, currentValue, iteration) {\n\n return previousValue\n .then(() => waitNextBlock(currentValue, success, fallback))\n .then(() => {\n\n // finished\n if (iteration === chains.length - 1) {\n\n resolve();\n\n }\n\n });\n\n }, Promise.resolve());\n\n });\n\n /**\n * Decorator\n *\n * @param {ChainData} chainData\n *\n * @param {Function} successCallback\n * @param {Function} fallbackCallback\n *\n * @return {Promise}\n */\n function waitNextBlock(chainData, successCallback, fallbackCallback) {\n\n return new Promise(function (resolve) {\n\n chainData.function()\n .then(() => {\n\n successCallback(chainData.data);\n\n })\n .then(resolve)\n .catch(function () {\n\n fallbackCallback(chainData.data);\n\n // anyway, go ahead even it falls\n resolve();\n\n });\n\n });\n\n }\n\n }\n\n /**\n * Make array from array-like collection\n *\n * @param {*} collection\n *\n * @return {Array}\n */\n static array(collection) {\n\n return Array.prototype.slice.call(collection);\n\n }\n\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/utils.js","/**\n * DOM manupulations helper\n */\nexport default class Dom {\n\n /**\n * Helper for making Elements with classname and attributes\n *\n * @param {string} tagName - new Element tag name\n * @param {array|string} classNames - list or name of CSS classname(s)\n * @param {Object} attributes - any attributes\n * @return {Element}\n */\n static make(tagName, classNames = null, attributes = {}) {\n\n var el = document.createElement(tagName);\n\n if ( Array.isArray(classNames) ) {\n\n el.classList.add(...classNames);\n\n } else if( classNames ) {\n\n el.classList.add(classNames);\n\n }\n\n for (let attrName in attributes) {\n\n el[attrName] = attributes[attrName];\n\n }\n\n return el;\n\n }\n\n /**\n * Append one or several elements to the parent\n *\n * @param {Element} parent - where to append\n * @param {Element|Element[]} - element ore elements list\n */\n static append(parent, elements) {\n\n if ( Array.isArray(elements) ) {\n\n elements.forEach( el => parent.appendChild(el) );\n\n } else {\n\n parent.appendChild(elements);\n\n }\n\n }\n\n /**\n * Selector Decorator\n *\n * Returns first match\n *\n * @param {Element} el - element we searching inside. Default - DOM Document\n * @param {String} selector - searching string\n *\n * @returns {Element}\n */\n static find(el = document, selector) {\n\n return el.querySelector(selector);\n\n }\n\n /**\n * Selector Decorator.\n *\n * Returns all matches\n *\n * @param {Element} el - element we searching inside. Default - DOM Document\n * @param {String} selector - searching string\n * @returns {NodeList}\n */\n static findAll(el = document, selector) {\n\n return el.querySelectorAll(selector);\n\n }\n\n /**\n * Check if object is DOM node\n *\n * @param {Object} node\n * @returns {boolean}\n */\n static isNode(node) {\n\n return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.ELEMENT_NODE;\n\n }\n\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/dom.js","/**\n * Codex Editor\n *\n * Short Description (눈_눈;)\n * @version 2.0.0\n *\n * How to start?\n * Example:\n * new CodexEditor({\n * holderId : 'codex-editor',\n * initialBlock : 'paragraph',\n * placeholder : 'Write your story....',\n * tools: {\n * quote: Quote,\n * anotherTool : AnotherTool\n * },\n * toolsConfig: {\n * quote: {\n * iconClassname : 'quote-icon',\n * displayInToolbox : true,\n * enableLineBreaks : true\n * },\n * anotherTool: {\n * iconClassname : 'tool-icon'\n * }\n * }\n * });\n *\n * - tools is an object: {\n * pluginName: PluginClass,\n * .....\n * }\n * - toolsConfig is an additional configuration that uses Codex Editor API\n * iconClassname - CSS classname of toolbox icon\n * displayInToolbox - if you want to see your Tool in toolbox hided in \"plus\" button, than set \"True\". By default : \"False\"\n * enableLineBreaks - by default enter creates new block that set as initialblock, but if you set this property \"True\", enter will break the lines in current block\n *\n * @author CodeX-Team \n *\n */\n\n/**\n * @typedef {CodexEditor} CodexEditor - editor class\n */\n\n/**\n * @typedef {Object} EditorConfig\n * @property {String} holderId - Element to append Editor\n * @property {Array} data - Blocks list in JSON-format\n * ...\n */\n\n'use strict';\n\n/**\n * Require Editor modules places in components/modules dir\n */\n// eslint-disable-next-line\nlet modules = editorModules.map( module => require('./components/modules/' + module ));\n\n/**\n * @class\n *\n * @classdesc CodeX Editor base class\n *\n * @property this.config - all settings\n * @property this.moduleInstances - constructed editor components\n *\n * @type {CodexEditor}\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n\n /**\n * Configuration object\n */\n this.config = {};\n\n /**\n * Editor Components\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n\n this.configuration = config;\n\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n\n console.log('CodeX Editor is ready');\n\n })\n .catch(error => {\n\n console.log('CodeX Editor does not ready beecause of %o', error);\n\n });\n\n }\n\n /**\n * Setting for configuration\n * @param {Object} config\n */\n set configuration(config = {}) {\n\n this.config.holderId = config.holderId;\n this.config.placeholder = config.placeholder || 'write your story...';\n this.config.sanitizer = config.sanitizer || {\n p: true,\n b: true,\n a: true\n };\n\n this.config.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n this.config.tools = config.tools || {};\n this.config.toolsConfig = config.toolsConfig || {};\n this.config.data = config.data || [];\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this.config;\n\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n this.constructModules();\n\n /**\n * Modules configuration\n */\n this.configureModules();\n\n }\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n\n modules.forEach( Module => {\n\n try {\n\n /**\n * We use class name provided by displayName property\n *\n * On build, Babel will transform all Classes to the Functions so, name will always be 'Function'\n * To prevent this, we use 'babel-plugin-class-display-name' plugin\n * @see https://www.npmjs.com/package/babel-plugin-class-display-name\n */\n\n this.moduleInstances[Module.displayName] = new Module({\n config : this.configuration\n });\n\n } catch ( e ) {\n\n console.log('Module %o skipped because %o', Module, e);\n\n }\n\n });\n\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n\n for(let name in this.moduleInstances) {\n\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n\n }\n\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n\n let diff = {};\n\n for(let moduleName in this.moduleInstances) {\n\n /**\n * Skip module with passed name\n */\n if (moduleName === name) {\n\n continue;\n\n }\n diff[moduleName] = this.moduleInstances[moduleName];\n\n }\n\n return diff;\n\n }\n\n /**\n * Start Editor!\n *\n * @return {Promise}\n */\n start() {\n\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances.UI))\n .then(prepareDecorator(this.moduleInstances.Tools))\n .then(() => {\n\n if (this.config.data && this.config.data.items) {\n\n this.moduleInstances.Renderer.render(this.config.data.items);\n\n }\n\n })\n .then(prepareDecorator(this.moduleInstances.BlockManager))\n\n .catch(function (error) {\n\n console.log('Error occured', error);\n\n });\n\n }\n\n};\n\n// module.exports = (function (editor) {\n//\n// 'use strict';\n//\n// editor.version = VERSION;\n// editor.scriptPrefix = 'cdx-script-';\n//\n// var init = function () {\n//\n// editor.core = require('./modules/core');\n// editor.tools = require('./modules/tools');\n// editor.ui = require('./modules/ui');\n// editor.transport = require('./modules/transport');\n// editor.renderer = require('./modules/renderer');\n// editor.saver = require('./modules/saver');\n// editor.content = require('./modules/content');\n// editor.toolbar = require('./modules/toolbar/toolbar');\n// editor.callback = require('./modules/callbacks');\n// editor.draw = require('./modules/draw');\n// editor.caret = require('./modules/caret');\n// editor.notifications = require('./modules/notifications');\n// editor.parser = require('./modules/parser');\n// editor.sanitizer = require('./modules/sanitizer');\n// editor.listeners = require('./modules/listeners');\n// editor.destroyer = require('./modules/destroyer');\n// editor.paste = require('./modules/paste');\n//\n// };\n//\n// /**\n// * @public\n// * holds initial settings\n// */\n// editor.settings = {\n// tools : ['paragraph', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],\n// holderId : 'codex-editor',\n//\n// // Type of block showing on empty editor\n// initialBlockPlugin: 'paragraph'\n// };\n//\n// /**\n// * public\n// *\n// * Static nodes\n// */\n// editor.nodes = {\n// holder : null,\n// wrapper : null,\n// toolbar : null,\n// inlineToolbar : {\n// wrapper : null,\n// buttons : null,\n// actions : null\n// },\n// toolbox : null,\n// notifications : null,\n// plusButton : null,\n// showSettingsButton: null,\n// showTrashButton : null,\n// blockSettings : null,\n// pluginSettings : null,\n// defaultSettings : null,\n// toolbarButtons : {}, // { type : DomEl, ... }\n// redactor : null\n// };\n//\n// /**\n// * @public\n// *\n// * Output state\n// */\n// editor.state = {\n// jsonOutput : [],\n// blocks : [],\n// inputs : []\n// };\n//\n// /**\n// * @public\n// * Editor plugins\n// */\n// editor.tools = {};\n//\n// editor.start = function (userSettings) {\n//\n// init();\n//\n// editor.core.prepare(userSettings)\n//\n// // If all ok, make UI, bind events and parse initial-content\n// .then(editor.ui.prepare)\n// .then(editor.tools.prepare)\n// .then(editor.sanitizer.prepare)\n// .then(editor.paste.prepare)\n// .then(editor.transport.prepare)\n// .then(editor.renderer.makeBlocksFromData)\n// .then(editor.ui.saveInputs)\n// .catch(function (error) {\n//\n// editor.core.log('Initialization failed with error: %o', 'warn', error);\n//\n// });\n//\n// };\n//\n// return editor;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/codex.js","var map = {\n\t\"./blockManager.js\": 5,\n\t\"./events.js\": 7,\n\t\"./renderer.js\": 8,\n\t\"./toolbar.js\": 9,\n\t\"./tools.js\": 10,\n\t\"./ui.js\": 11\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) // check for number or string\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\treturn id;\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 4;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/modules nonrecursive [^_](blockManager.js|events.js|renderer.js|toolbar.js|tools.js|ui.js)$\n// module id = 4\n// module chunks = 0","/**\n * @class BlockManager\n * @classdesc Manage editor`s blocks storage and appearance\n */\n\nimport Block from '../block';\n\nclass BlockManager {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({ config }) {\n\n this.config = config;\n this.Editor = null;\n\n /**\n * Proxy for Blocks instance {@link Blocks}\n *\n * @type {Proxy}\n * @private\n */\n this._blocks = null;\n\n /**\n * Index of current working block\n *\n * @type {number}\n * @private\n */\n this.currentBlockIndex = -1;\n\n }\n\n /**\n * Editor modules setting\n *\n * @param Editor\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n * Should be called after Editor.UI preparation\n * Define this._blocks property\n *\n * @returns {Promise}\n */\n prepare() {\n\n return new Promise(resolve => {\n\n let blocks = new Blocks(this.Editor.UI.nodes.redactor);\n\n /**\n * We need to use Proxy to overload set/get [] operator.\n * So we can use array-like syntax to access blocks\n *\n * @example\n * this._blocks[0] = new Block(...);\n *\n * block = this._blocks[0];\n *\n * @todo proxy the enumerate method\n *\n * @type {Proxy}\n * @private\n */\n this._blocks = new Proxy(blocks, {\n set: Blocks.set,\n get: Blocks.get\n });\n\n resolve();\n\n });\n\n }\n\n /**\n * Insert new block into _blocks\n *\n * @param {String} toolName — plugin name\n * @param {Object} data — plugin data\n */\n insert(toolName, data) {\n\n let toolInstance = this.Editor.Tools.construct(toolName, data),\n block = new Block(toolInstance);\n\n this._blocks[++this.currentBlockIndex] = block;\n\n }\n\n /**\n * Replace current working block\n *\n * @param {String} toolName — plugin name\n * @param {Object} data — plugin data\n */\n replace(toolName, data) {\n\n let toolInstance = this.Editor.Tools.construct(toolName, data),\n block = new Block(toolInstance);\n\n this._blocks.insert(this.currentBlockIndex, block, true);\n\n }\n\n /**\n * Get Block instance by html element\n *\n * @todo get first level block before searching\n *\n * @param {HTMLElement} element\n * @returns {Block}\n */\n getBlock(element) {\n\n let nodes = this._blocks.nodes,\n index = nodes.indexOf(element);\n\n if (index >= 0) {\n\n return this._blocks[index];\n\n }\n\n }\n\n /**\n * Get current Block instance\n *\n * @return {Block}\n */\n get currentBlock() {\n\n return this._blocks[this.currentBlockIndex];\n\n }\n\n /**\n * Get working html element\n *\n * @return {HTMLElement}\n */\n get currentNode() {\n\n return this._blocks.nodes[this.currentBlockIndex];\n\n }\n\n /**\n * Set currentBlockIndex to passed block\n *\n * @todo get first level block before searching\n *\n * @param {HTMLElement} element\n */\n set currentNode(element) {\n\n let nodes = this._blocks.nodes;\n\n this.currentBlockIndex = nodes.indexOf(element);\n\n }\n\n /**\n * Get array of Block instances\n *\n * @returns {Block[]} {@link Blocks#array}\n */\n get blocks() {\n\n return this._blocks.array;\n\n }\n\n}\n\n/**\n * @class Blocks\n * @classdesc Class to work with Block instances array\n *\n * @private\n *\n * @property {HTMLElement} workingArea — editor`s working node\n *\n */\nclass Blocks {\n\n /**\n * @constructor\n *\n * @param {HTMLElement} workingArea — editor`s working node\n */\n constructor(workingArea) {\n\n this.blocks = [];\n this.workingArea = workingArea;\n\n }\n\n /**\n * Push back new Block\n *\n * @param {Block} block\n */\n push(block) {\n\n this.blocks.push(block);\n this.workingArea.appendChild(block.html);\n\n }\n\n /**\n * Insert new Block at passed index\n *\n * @param {Number} index — index to insert Block\n * @param {Block} block — Block to insert\n * @param {Boolean} replace — it true, replace block on given index\n */\n insert(index, block, replace = false) {\n\n if (!this.length) {\n\n this.push(block);\n return;\n\n }\n\n if (index > this.length) {\n\n index = this.length;\n\n }\n\n if (replace) {\n\n this.blocks[index].html.remove();\n\n }\n\n let deleteCount = replace ? 1 : 0;\n\n this.blocks.splice(index, deleteCount, block);\n\n if (index > 0) {\n\n let previousBlock = this.blocks[index - 1];\n\n previousBlock.html.insertAdjacentElement('afterend', block.html);\n\n } else {\n\n let nextBlock = this.blocks[index + 1];\n\n if (nextBlock) {\n\n nextBlock.html.insertAdjacentElement('beforebegin', block.html);\n\n } else {\n\n this.workingArea.appendChild(block.html);\n\n }\n\n }\n\n }\n\n /**\n * Insert Block after passed target\n *\n * @todo decide if this method is necessary\n *\n * @param {Block} targetBlock — target after wich Block should be inserted\n * @param {Block} newBlock — Block to insert\n */\n insertAfter(targetBlock, newBlock) {\n\n let index = this.blocks.indexOf(targetBlock);\n\n this.insert(index + 1, newBlock);\n\n }\n\n /**\n * Get Block by index\n *\n * @param {Number} index — Block index\n * @returns {Block}\n */\n get(index) {\n\n return this.blocks[index];\n\n }\n\n /**\n * Return index of passed Block\n *\n * @param {Block} block\n * @returns {Number}\n */\n indexOf(block) {\n\n return this.blocks.indexOf(block);\n\n }\n\n /**\n * Get length of Block instances array\n *\n * @returns {Number}\n */\n get length() {\n\n return this.blocks.length;\n\n }\n\n /**\n * Get Block instances array\n *\n * @returns {Block[]}\n */\n get array() {\n\n return this.blocks;\n\n }\n\n /**\n * Get blocks html elements array\n *\n * @returns {HTMLElement[]}\n */\n get nodes() {\n\n return _.array(this.workingArea.children);\n\n }\n\n /**\n * Proxy trap to implement array-like setter\n *\n * @example\n * blocks[0] = new Block(...)\n *\n * @param {Blocks} instance — Blocks instance\n * @param {Number|String} index — block index\n * @param {Block} block — Block to set\n * @returns {Boolean}\n */\n static set(instance, index, block) {\n\n if (isNaN(Number(index))) {\n\n return false;\n\n }\n\n instance.insert(index, block);\n\n return true;\n\n }\n\n /**\n * Proxy trap to implement array-like getter\n *\n * @param {Blocks} instance — Blocks instance\n * @param {Number|String} index — Block index\n * @returns {Block|*}\n */\n static get(instance, index) {\n\n if (isNaN(Number(index))) {\n\n return instance[index];\n\n }\n\n return instance.get(index);\n\n }\n\n}\n\nmodule.exports = BlockManager;\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/blockManager.js","/**\n *\n * @class Block\n * @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool\n *\n * @property {Tool} tool — current block tool (Paragraph, for example)\n * @property {Object} CSS — block`s css classes\n *\n */\n\n\nexport default class Block {\n\n /**\n * @constructor\n *\n * @param {Object} tool — current block plugin`s instance\n */\n constructor(tool) {\n\n this.tool = tool;\n\n this.CSS = {\n wrapper: 'ce-block',\n content: 'ce-block__content'\n };\n\n this._html = this.compose();\n\n }\n\n /**\n * Make default block wrappers and put tool`s content there\n *\n * @returns {HTMLDivElement}\n * @private\n */\n compose() {\n\n let wrapper = $.make('div', this.CSS.wrapper),\n content = $.make('div', this.CSS.content);\n\n content.appendChild(this.tool.html);\n wrapper.appendChild(content);\n\n return wrapper;\n\n }\n\n /**\n * Get block`s HTML\n *\n * @returns {HTMLDivElement}\n */\n get html() {\n\n return this._html;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/block.js","/**\n * @module eventDispatcher\n *\n * Has two important methods:\n * - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one\n * - {Function} emit - fires all subscribers with data\n *\n * @version 1.0.0\n *\n * @typedef {Events} Events\n * @property {Object} subscribers - all subscribers grouped by event name\n */\nexport default class Events extends Module {\n\n /**\n * @constructor\n */\n constructor() {\n\n super();\n\n this.subscribers = {};\n\n }\n\n /**\n * @param {String} eventName - event name\n * @param {Function} callback - subscriber\n */\n on(eventName, callback) {\n\n if (!(eventName in this.subscribers)) {\n\n this.subscribers[eventName] = [];\n\n }\n\n // group by events\n this.subscribers[eventName].push(callback);\n\n }\n\n /**\n * @param {String} eventName - event name\n * @param {Object} data - subscribers get this data when they were fired\n */\n emit(eventName, data) {\n\n this.subscribers[eventName].reduce(function (previousData, currentHandler) {\n\n let newData = currentHandler(previousData);\n\n return newData ? newData : previousData;\n\n }, data);\n\n }\n\n /**\n * Destroyer\n */\n destroy() {\n\n this.Editor = null;\n this.subscribers = null;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/events.js","/**\n * Codex Editor Renderer Module\n *\n * @author Codex Team\n * @version 2.0.0\n */\n\nclass Renderer {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor(config) {\n\n this.config = config;\n this.Editor = null;\n\n }\n\n /**\n * Editor modules setter\n *\n * @param {Object} Editor\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n *\n * Make plugin blocks from array of plugin`s data\n *\n * @param {Object[]} items\n */\n render(items) {\n\n let chainData = [];\n\n for (let i = 0; i < items.length; i++) {\n\n chainData.push({\n function: () => this.insertBlock(items[i])\n });\n\n }\n\n _.sequence(chainData);\n\n }\n\n /**\n * Get plugin instance\n * Add plugin instance to BlockManager\n * Insert block to working zone\n *\n * @param {Object} item\n * @returns {Promise.}\n * @private\n */\n insertBlock(item) {\n\n let tool = item.type,\n data = item.data;\n\n this.Editor.BlockManager.insert(tool, data);\n\n return Promise.resolve();\n\n }\n\n}\n\nmodule.exports = Renderer;\n\n// module.exports = (function (renderer) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * Asyncronously parses input JSON to redactor blocks\n// */\n// renderer.makeBlocksFromData = function () {\n//\n// /**\n// * If redactor is empty, add first paragraph to start writing\n// */\n// if (editor.core.isEmpty(editor.state.blocks) || !editor.state.blocks.items.length) {\n//\n// editor.ui.addInitialBlock();\n// return;\n//\n// }\n//\n// Promise.resolve()\n//\n// /** First, get JSON from state */\n// .then(function () {\n//\n// return editor.state.blocks;\n//\n// })\n//\n// /** Then, start to iterate they */\n// .then(editor.renderer.appendBlocks)\n//\n// /** Write log if something goes wrong */\n// .catch(function (error) {\n//\n// editor.core.log('Error while parsing JSON: %o', 'error', error);\n//\n// });\n//\n// };\n//\n// /**\n// * Parses JSON to blocks\n// * @param {object} data\n// * @return Promise -> nodeList\n// */\n// renderer.appendBlocks = function (data) {\n//\n// var blocks = data.items;\n//\n// /**\n// * Sequence of one-by-one blocks appending\n// * Uses to save blocks order after async-handler\n// */\n// var nodeSequence = Promise.resolve();\n//\n// for (var index = 0; index < blocks.length ; index++ ) {\n//\n// /** Add node to sequence at specified index */\n// editor.renderer.appendNodeAtIndex(nodeSequence, blocks, index);\n//\n// }\n//\n// };\n//\n// /**\n// * Append node at specified index\n// */\n// renderer.appendNodeAtIndex = function (nodeSequence, blocks, index) {\n//\n// /** We need to append node to sequence */\n// nodeSequence\n//\n// /** first, get node async-aware */\n// .then(function () {\n//\n// return editor.renderer.getNodeAsync(blocks, index);\n//\n// })\n//\n// /**\n// * second, compose editor-block from JSON object\n// */\n// .then(editor.renderer.createBlockFromData)\n//\n// /**\n// * now insert block to redactor\n// */\n// .then(function (blockData) {\n//\n// /**\n// * blockData has 'block', 'type' and 'stretched' information\n// */\n// editor.content.insertBlock(blockData);\n//\n// /** Pass created block to next step */\n// return blockData.block;\n//\n// })\n//\n// /** Log if something wrong with node */\n// .catch(function (error) {\n//\n// editor.core.log('Node skipped while parsing because %o', 'error', error);\n//\n// });\n//\n// };\n//\n// /**\n// * Asynchronously returns block data from blocksList by index\n// * @return Promise to node\n// */\n// renderer.getNodeAsync = function (blocksList, index) {\n//\n// return Promise.resolve().then(function () {\n//\n// return {\n// tool : blocksList[index],\n// position : index\n// };\n//\n// });\n//\n// };\n//\n// /**\n// * Creates editor block by JSON-data\n// *\n// * @uses render method of each plugin\n// *\n// * @param {Object} toolData.tool\n// * { header : {\n// * text: '',\n// * type: 'H3', ...\n// * }\n// * }\n// * @param {Number} toolData.position - index in input-blocks array\n// * @return {Object} with type and Element\n// */\n// renderer.createBlockFromData = function ( toolData ) {\n//\n// /** New parser */\n// var block,\n// tool = toolData.tool,\n// pluginName = tool.type;\n//\n// /** Get first key of object that stores plugin name */\n// // for (var pluginName in blockData) break;\n//\n// /** Check for plugin existance */\n// if (!editor.tools[pluginName]) {\n//\n// throw Error(`Plugin «${pluginName}» not found`);\n//\n// }\n//\n// /** Check for plugin having render method */\n// if (typeof editor.tools[pluginName].render != 'function') {\n//\n// throw Error(`Plugin «${pluginName}» must have «render» method`);\n//\n// }\n//\n// if ( editor.tools[pluginName].available === false ) {\n//\n// block = editor.draw.unavailableBlock();\n//\n// block.innerHTML = editor.tools[pluginName].loadingMessage;\n//\n// /**\n// * Saver will extract data from initial block data by position in array\n// */\n// block.dataset.inputPosition = toolData.position;\n//\n// } else {\n//\n// /** New Parser */\n// block = editor.tools[pluginName].render(tool.data);\n//\n// }\n//\n// /** is first-level block stretched */\n// var stretched = editor.tools[pluginName].isStretched || false;\n//\n// /** Retrun type and block */\n// return {\n// type : pluginName,\n// block : block,\n// stretched : stretched\n// };\n//\n// };\n//\n// return renderer;\n//\n// })({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/renderer.js","/**\n *\n * «Toolbar» is the node that moves up/down over current block\n *\n * ______________________________________ Toolbar ____________________________________________\n * | |\n * | ..................... Content .................... ......... Block Actions .......... |\n * | . . . . |\n * | . . . [Open Settings] [Remove Block] . |\n * | . [Plus Button] [Toolbox: {Tool1}, {Tool2}] . . . |\n * | . . . [Settings Panel] . |\n * | .................................................. .................................. |\n * | |\n * |___________________________________________________________________________________________|\n *\n *\n * Toolbox — its an Element contains tools buttons. Can be shown by Plus Button.\n *\n * _______________ Toolbox _______________\n * | |\n * | [Header] [Image] [List] [Quote] ... |\n * |_______________________________________|\n *\n *\n * Settings Panel — is an Element with block settings:\n *\n * ____ Settings Panel ____\n * | ...................... |\n * | . Tool Settings . |\n * | ...................... |\n * | . Default Settings . |\n * | ...................... |\n * |________________________|\n *\n *\n * @class\n * @classdesc Toolbar module\n *\n * @typedef {Toolbar} Toolbar\n * @property {Object} nodes\n * @property {Element} nodes.wrapper - Toolbar main element\n * @property {Element} nodes.content - Zone with Plus button and toolbox.\n * @property {Element} nodes.actions - Zone with Block Settings and Remove Button\n * @property {Element} nodes.plusButton - Button that opens or closes Toolbox\n * @property {Element} nodes.toolbox - Container for tools\n * @property {Element} nodes.settingsToggler - open/close Settings Panel button\n * @property {Element} nodes.removeBlockButton - Remove Block button\n * @property {Element} nodes.settings - Settings Panel\n * @property {Element} nodes.pluginSettings - Plugin Settings section of Settings Panel\n * @property {Element} nodes.defaultSettings - Default Settings section of Settings Panel\n */\nexport default class Toolbar extends Module {\n\n /**\n * @constructor\n */\n constructor(config) {\n\n super(config);\n\n this.nodes = {\n wrapper : null,\n content : null,\n actions : null,\n\n // Content Zone\n plusButton : null,\n toolbox : null,\n\n // Actions Zone\n settingsToggler : null,\n removeBlockButton: null,\n settings: null,\n\n // Settings Zone: Plugin Settings and Default Settings\n pluginSettings: null,\n defaultSettings: null,\n };\n\n this.CSS = {\n toolbar: 'ce-toolbar',\n content: 'ce-toolbar__content',\n actions: 'ce-toolbar__actions',\n\n // Content Zone\n toolbox: 'ce-toolbar__toolbox',\n plusButton: 'ce-toolbar__plus',\n\n // Actions Zone\n settingsToggler: 'ce-toolbar__settings-btn',\n removeBlockButton: 'ce-toolbar__remove-btn',\n\n // Settings Panel\n settings: 'ce-settings',\n defaultSettings: 'ce-settings_default',\n pluginSettings: 'ce-settings_plugin',\n };\n\n }\n\n /**\n * Makes toolbar\n */\n make() {\n\n this.nodes.wrapper = $.make('div', this.CSS.toolbar);\n\n /**\n * Make Content Zone and Actions Zone\n */\n ['content', 'actions'].forEach( el => {\n\n this.nodes[el] = $.make('div', this.CSS[el]);\n $.append(this.nodes.wrapper, this.nodes[el]);\n\n });\n\n\n /**\n * Fill Content Zone:\n * - Plus Button\n * - Toolbox\n */\n ['plusButton', 'toolbox'].forEach( el => {\n\n this.nodes[el] = $.make('div', this.CSS[el]);\n $.append(this.nodes.content, this.nodes[el]);\n\n });\n\n /**\n * Fill Actions Zone:\n * - Settings Toggler\n * - Remove Block Button\n * - Settings Panel\n */\n this.nodes.settingsToggler = $.make('span', this.CSS.settingsToggler);\n this.nodes.removeBlockButton = this.makeRemoveBlockButton();\n\n $.append(this.nodes.actions, [this.nodes.settingsToggler, this.nodes.removeBlockButton]);\n\n /**\n * Make and append Settings Panel\n */\n this.makeBlockSettingsPanel();\n\n /**\n * Append toolbar to the Editor\n */\n $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);\n\n }\n\n /**\n * Panel with block settings with 2 sections:\n *\n * @return {Element}\n */\n makeBlockSettingsPanel() {\n\n this.nodes.settings = $.make('div', this.CSS.settings);\n\n this.nodes.pluginSettings = $.make('div', this.CSS.pluginSettings);\n this.nodes.defaultSettings = $.make('div', this.CSS.defaultSettings);\n\n $.append(this.nodes.settings, [this.nodes.pluginSettings, this.nodes.defaultSettings]);\n $.append(this.nodes.actions, this.nodes.settings);\n\n }\n\n /**\n * Makes Remove Block button, and confirmation panel\n * @return {Element} wrapper with button and panel\n */\n makeRemoveBlockButton() {\n\n /**\n * @todo add confirmation panel and handlers\n * @see {@link settings#makeRemoveBlockButton}\n */\n return $.make('span', this.CSS.removeBlockButton);\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar.js","/**\n * @module Codex Editor Tools Submodule\n *\n * Creates Instances from Plugins and binds external config to the instances\n */\n\n/**\n * Load user defined tools\n * Tools must contain the following important objects:\n *\n * @typedef {Object} ToolsConfig\n * @property {String} iconClassname - this a icon in toolbar\n * @property {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE\n * @property {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE\n */\n\n/**\n * @todo update according to current API\n *\n * @typedef {Object} Tool\n * @property render\n * @property save\n * @property settings\n * @property validate\n */\n\n/**\n * Class properties:\n *\n * @typedef {Tool} Tool\n * @property {String} name - name of this module\n * @property {Object[]} toolInstances - list of tool instances\n * @property {Tools[]} available - available Tools\n * @property {Tools[]} unavailable - unavailable Tools\n * @property {Object} toolsClasses - all classes\n * @property {EditorConfig} config - Editor config\n */\n\nexport default class Tools extends Module {\n\n /**\n * Returns available Tools\n * @return {Tool[]}\n */\n get available() {\n\n return this.toolsAvailable;\n\n }\n\n /**\n * Returns unavailable Tools\n * @return {Tool[]}\n */\n get unavailable() {\n\n return this.toolsUnavailable;\n\n }\n\n /**\n * If config wasn't passed by user\n * @return {ToolsConfig}\n */\n get defaultConfig() {\n\n return {\n iconClassName : 'default-icon',\n displayInToolbox : false,\n enableLineBreaks : false\n };\n\n }\n\n /**\n * @constructor\n *\n * @param {ToolsConfig} config\n */\n constructor({ config }) {\n\n super(config);\n\n this.toolClasses = {};\n this.toolsAvailable = {};\n this.toolsUnavailable = {};\n\n }\n\n /**\n * Creates instances via passed or default configuration\n * @return {boolean}\n */\n prepare() {\n\n if (!this.config.hasOwnProperty('tools')) {\n\n return Promise.reject(\"Can't start without tools\");\n\n }\n\n for(let toolName in this.config.tools) {\n\n this.toolClasses[toolName] = this.config.tools[toolName];\n\n }\n\n /**\n * getting classes that has prepare method\n */\n let sequenceData = this.getListOfPrepareFunctions();\n\n /**\n * if sequence data contains nothing then resolve current chain and run other module prepare\n */\n if (sequenceData.length === 0) {\n\n return Promise.resolve();\n\n }\n\n /**\n * to see how it works {@link Util#sequence}\n */\n return _.sequence(sequenceData, (data) => {\n\n this.success(data);\n\n }, (data) => {\n\n this.fallback(data);\n\n });\n\n }\n\n /**\n * Binds prepare function of plugins with user or default config\n * @return {Array} list of functions that needs to be fired sequently\n */\n getListOfPrepareFunctions() {\n\n let toolPreparationList = [];\n\n for(let toolName in this.toolClasses) {\n\n let toolClass = this.toolClasses[toolName];\n\n if (typeof toolClass.prepare === 'function') {\n\n toolPreparationList.push({\n function : toolClass.prepare,\n data : {\n toolName\n }\n });\n\n }\n\n }\n\n return toolPreparationList;\n\n }\n\n /**\n * @param {ChainData.data} data - append tool to available list\n */\n success(data) {\n\n this.toolsAvailable[data.toolName] = this.toolClasses[data.toolName];\n\n }\n\n /**\n * @param {ChainData.data} data - append tool to unavailable list\n */\n fallback(data) {\n\n this.toolsUnavailable[data.toolName] = this.toolClasses[data.toolName];\n\n }\n\n /**\n * Returns all tools\n * @return {Array}\n */\n getTools() {\n\n return this.toolInstances;\n\n }\n\n /**\n * Return tool`a instance\n *\n * @param {String} tool — tool name\n * @param {Object} data — initial data\n *\n * @todo throw exceptions if tool doesnt exist\n *\n */\n construct(tool, data) {\n\n let plugin = this.toolClasses[tool],\n config = this.config.toolsConfig[tool];\n\n let instance = new plugin(data, config);\n\n return instance;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/tools.js","/**\n * Module UI\n *\n * @type {UI}\n */\n// let className = {\n\n/**\n * @const {string} BLOCK_CLASSNAME - redactor blocks name\n */\n// BLOCK_CLASSNAME : 'ce-block',\n\n/**\n * @const {String} wrapper for plugins content\n */\n// BLOCK_CONTENT : 'ce-block__content',\n\n/**\n * @const {String} BLOCK_STRETCHED - makes block stretched\n */\n// BLOCK_STRETCHED : 'ce-block--stretched',\n\n/**\n * @const {String} BLOCK_HIGHLIGHTED - adds background\n */\n// BLOCK_HIGHLIGHTED : 'ce-block--focused',\n\n/**\n * @const {String} - for all default settings\n */\n// SETTINGS_ITEM : 'ce-settings__item'\n// };\n\nlet CSS = {\n editorWrapper : 'codex-editor',\n editorZone : 'ce-redactor'\n};\n\n/**\n * @class\n *\n * @classdesc Makes CodeX Editor UI:\n * \n * \n * \n * \n * \n *\n * @typedef {UI} UI\n * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}\n * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}\n * @property {Object} nodes -\n * @property {Element} nodes.holder - element where we need to append redactor\n * @property {Element} nodes.wrapper - \n * @property {Element} nodes.redactor - \n */\n\nexport default class UI extends Module {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({ config }) {\n\n super(config);\n\n this.nodes = {\n holder: null,\n wrapper: null,\n redactor: null\n };\n\n }\n\n /**\n * @protected\n *\n * Making main interface\n */\n prepare() {\n\n return new Promise( (resolve, reject) => {\n\n /**\n * Element where we need to append CodeX Editor\n * @type {Element}\n */\n this.nodes.holder = document.getElementById(this.config.holderId);\n\n if (!this.nodes.holder) {\n\n reject(Error(\"Holder wasn't found by ID: #\" + this.config.holderId));\n return;\n\n }\n\n /**\n * Create and save main UI elements\n */\n this.nodes.wrapper = $.make('div', CSS.editorWrapper);\n this.nodes.redactor = $.make('div', CSS.editorZone);\n\n this.nodes.wrapper.appendChild(this.nodes.redactor);\n this.nodes.holder.appendChild(this.nodes.wrapper);\n\n /**\n * Make toolbar\n */\n this.Editor.Toolbar.make();\n /**\n * Load and append CSS\n */\n this.loadStyles();\n\n resolve();\n\n })\n\n /** Add toolbox tools */\n // .then(addTools_)\n\n /** Make container for inline toolbar */\n // .then(makeInlineToolbar_)\n\n /** Add inline toolbar tools */\n // .then(addInlineToolbarTools_)\n\n /** Draw wrapper for notifications */\n // .then(makeNotificationHolder_)\n\n /** Add eventlisteners to redactor elements */\n // .then(bindEvents_)\n\n .catch(e => {\n\n console.error(e);\n\n // editor.core.log(\"Can't draw editor interface\");\n\n });\n\n }\n\n loadStyles() {\n\n /**\n * Load CSS\n */\n let styles = require('../../styles/main.css');\n\n /**\n * Make tag\n */\n let tag = $.make('style', null, {\n textContent: styles.toString()\n });\n\n /**\n * Append styles\n */\n $.append(document.head, tag);\n\n }\n\n}\n\n// /**\n// * Codex Editor UI module\n// *\n// * @author Codex Team\n// * @version 1.2.0\n// */\n//\n// module.exports = (function (ui) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * Basic editor classnames\n// */\n// ui.prepare = function () {\n//\n\n//\n// };\n//\n// /** Draw notifications holder */\n// var makeNotificationHolder_ = function () {\n//\n// /** Append block with notifications to the document */\n// editor.nodes.notifications = editor.notifications.createHolder();\n//\n// };\n//\n// /**\n// * @private\n// * Append tools passed in editor.tools\n// */\n// var addTools_ = function () {\n//\n// var tool,\n// toolName,\n// toolButton;\n//\n// for ( toolName in editor.settings.tools ) {\n//\n// tool = editor.settings.tools[toolName];\n//\n// editor.tools[toolName] = tool;\n//\n// if (!tool.iconClassname && tool.displayInToolbox) {\n//\n// editor.core.log('Toolbar icon classname missed. Tool %o skipped', 'warn', toolName);\n// continue;\n//\n// }\n//\n// if (typeof tool.render != 'function') {\n//\n// editor.core.log('render method missed. Tool %o skipped', 'warn', toolName);\n// continue;\n//\n// }\n//\n// if (!tool.displayInToolbox) {\n//\n// continue;\n//\n// } else {\n//\n// /** if tools is for toolbox */\n// toolButton = editor.draw.toolbarButton(toolName, tool.iconClassname);\n//\n// editor.nodes.toolbox.appendChild(toolButton);\n//\n// editor.nodes.toolbarButtons[toolName] = toolButton;\n//\n// }\n//\n// }\n//\n// };\n//\n// var addInlineToolbarTools_ = function () {\n//\n// var tools = {\n//\n// bold: {\n// icon : 'ce-icon-bold',\n// command : 'bold'\n// },\n//\n// italic: {\n// icon : 'ce-icon-italic',\n// command : 'italic'\n// },\n//\n// link: {\n// icon : 'ce-icon-link',\n// command : 'createLink'\n// }\n// };\n//\n// var toolButton,\n// tool;\n//\n// for(var name in tools) {\n//\n// tool = tools[name];\n//\n// toolButton = editor.draw.toolbarButtonInline(name, tool.icon);\n//\n// editor.nodes.inlineToolbar.buttons.appendChild(toolButton);\n// /**\n// * Add callbacks to this buttons\n// */\n// editor.ui.setInlineToolbarButtonBehaviour(toolButton, tool.command);\n//\n// }\n//\n// };\n//\n// /**\n// * @private\n// * Bind editor UI events\n// */\n// var bindEvents_ = function () {\n//\n// editor.core.log('ui.bindEvents fired', 'info');\n//\n// // window.addEventListener('error', function (errorMsg, url, lineNumber) {\n// // editor.notifications.errorThrown(errorMsg, event);\n// // }, false );\n//\n// /** All keydowns on Document */\n// editor.listeners.add(document, 'keydown', editor.callback.globalKeydown, false);\n//\n// /** All keydowns on Redactor zone */\n// editor.listeners.add(editor.nodes.redactor, 'keydown', editor.callback.redactorKeyDown, false);\n//\n// /** All keydowns on Document */\n// editor.listeners.add(document, 'keyup', editor.callback.globalKeyup, false );\n//\n// /**\n// * Mouse click to radactor\n// */\n// editor.listeners.add(editor.nodes.redactor, 'click', editor.callback.redactorClicked, false );\n//\n// /**\n// * Clicks to the Plus button\n// */\n// editor.listeners.add(editor.nodes.plusButton, 'click', editor.callback.plusButtonClicked, false);\n//\n// /**\n// * Clicks to SETTINGS button in toolbar\n// */\n// editor.listeners.add(editor.nodes.showSettingsButton, 'click', editor.callback.showSettingsButtonClicked, false );\n//\n// /** Bind click listeners on toolbar buttons */\n// for (var button in editor.nodes.toolbarButtons) {\n//\n// editor.listeners.add(editor.nodes.toolbarButtons[button], 'click', editor.callback.toolbarButtonClicked, false);\n//\n// }\n//\n// };\n//\n// ui.addBlockHandlers = function (block) {\n//\n// if (!block) return;\n//\n// /**\n// * Block keydowns\n// */\n// editor.listeners.add(block, 'keydown', editor.callback.blockKeydown, false);\n//\n// /**\n// * Pasting content from another source\n// * We have two type of sanitization\n// * First - uses deep-first search algorithm to get sub nodes,\n// * sanitizes whole Block_content and replaces cleared nodes\n// * This method is deprecated\n// * Method is used in editor.callback.blockPaste(event)\n// *\n// * Secont - uses Mutation observer.\n// * Observer \"observe\" DOM changes and send changings to callback.\n// * Callback gets changed node, not whole Block_content.\n// * Inserted or changed node, which we've gotten have been cleared and replaced with diry node\n// *\n// * Method is used in editor.callback.blockPasteViaSanitize(event)\n// *\n// * @uses html-janitor\n// * @example editor.callback.blockPasteViaSanitize(event), the second method.\n// *\n// */\n// editor.listeners.add(block, 'paste', editor.paste.blockPasteCallback, false);\n//\n// /**\n// * Show inline toolbar for selected text\n// */\n// editor.listeners.add(block, 'mouseup', editor.toolbar.inline.show, false);\n// editor.listeners.add(block, 'keyup', editor.toolbar.inline.show, false);\n//\n// };\n//\n// /** getting all contenteditable elements */\n// ui.saveInputs = function () {\n//\n// var redactor = editor.nodes.redactor;\n//\n// editor.state.inputs = [];\n//\n// /** Save all inputs in global variable state */\n// var inputs = redactor.querySelectorAll('[contenteditable], input, textarea');\n//\n// Array.prototype.map.call(inputs, function (current) {\n//\n// if (!current.type || current.type == 'text' || current.type == 'textarea') {\n//\n// editor.state.inputs.push(current);\n//\n// }\n//\n// });\n//\n// };\n//\n// /**\n// * Adds first initial block on empty redactor\n// */\n// ui.addInitialBlock = function () {\n//\n// var initialBlockType = editor.settings.initialBlockPlugin,\n// initialBlock;\n//\n// if ( !editor.tools[initialBlockType] ) {\n//\n// editor.core.log('Plugin %o was not implemented and can\\'t be used as initial block', 'warn', initialBlockType);\n// return;\n//\n// }\n//\n// initialBlock = editor.tools[initialBlockType].render();\n//\n// initialBlock.setAttribute('data-placeholder', editor.settings.placeholder);\n//\n// editor.content.insertBlock({\n// type : initialBlockType,\n// block : initialBlock\n// });\n//\n// editor.content.workingNodeChanged(initialBlock);\n//\n// };\n//\n// ui.setInlineToolbarButtonBehaviour = function (button, type) {\n//\n// editor.listeners.add(button, 'mousedown', function (event) {\n//\n// editor.toolbar.inline.toolClicked(event, type);\n//\n// }, false);\n//\n// };\n//\n// return ui;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/ui.js","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(undefined);\n// imports\n\n\n// module\nexports.push([module.id, \":root {\\n\\n /**\\n * Toolbar buttons\\n */\\n\\n}\\n/**\\n* Editor wrapper\\n*/\\n.codex-editor{\\n position: relative;\\n border: 1px solid #ccc;\\n padding: 10px;\\n}\\n.codex-editor .hide {\\n display: none;\\n }\\n\", \"\"]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/main.css\n// module id = 12\n// module chunks = 0","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader/lib/css-base.js\n// module id = 13\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap 085a7f316dc8d48f2889","webpack:///./src/components/__module.js","webpack:///./src/components/utils.js","webpack:///./src/components/dom.js","webpack:///./src/codex.js","webpack:///./src/components/modules nonrecursive [^_](blockManager.js|events.js|renderer.js|sanitizer.js|toolbar.js|tools.js|ui.js)$","webpack:///./src/components/modules/blockManager.js","webpack:///./src/components/modules/events.js","webpack:///./src/components/modules/renderer.js","webpack:///./src/components/modules/sanitizer.js","webpack:///./node_modules/html-janitor/src/html-janitor.js","webpack:///./src/components/modules/toolbar.js","webpack:///./src/components/modules/tools.js","webpack:///./src/components/modules/ui.js","webpack:///./src/styles/main.css","webpack:///./node_modules/css-loader/lib/css-base.js","webpack:///./src/components/block.js"],"names":["Module","config","new","target","TypeError","Editor","Util","chains","success","fallback","Promise","resolve","reduce","previousValue","currentValue","iteration","then","waitNextBlock","length","chainData","successCallback","fallbackCallback","function","data","catch","collection","Array","prototype","slice","call","object","Object","keys","constructor","Dom","tagName","classNames","attributes","el","document","createElement","isArray","classList","add","attrName","parent","elements","forEach","appendChild","selector","querySelector","querySelectorAll","node","nodeType","Node","ELEMENT_NODE","modules","editorModules","map","module","exports","moduleInstances","configuration","init","start","console","log","error","constructModules","configureModules","displayName","e","name","state","getModulesDiff","diff","moduleName","prepareDecorator","prepare","UI","Tools","items","Renderer","render","BlockManager","holderId","placeholder","sanitizer","p","b","a","hideToolbar","tools","toolsConfig","_blocks","currentBlockIndex","blocks","Blocks","nodes","redactor","Proxy","set","get","toolName","toolInstance","construct","block","insert","element","index","indexOf","array","workingArea","push","html","replace","remove","deleteCount","splice","previousBlock","insertAdjacentElement","nextBlock","targetBlock","newBlock","_","children","instance","isNaN","Number","Events","subscribers","eventName","callback","previousData","currentHandler","newData","i","insertBlock","sequence","item","tool","type","Sanitizer","instantConfig","janitorInstance","sanitizerConfig","settings","sanitizerInstance","require","taintString","clean","library","instanceConfig","isEmpty","tags","href","rel","customConfig","newInstance","Toolbar","wrapper","content","actions","plusButton","toolbox","settingsToggler","removeBlockButton","pluginSettings","defaultSettings","CSS","toolbar","$","make","append","makeRemoveBlockButton","makeBlockSettingsPanel","toolsAvailable","toolsUnavailable","iconClassName","displayInToolbox","enableLineBreaks","toolClasses","hasOwnProperty","reject","sequenceData","getListOfPrepareFunctions","toolPreparationList","toolClass","toolInstances","plugin","editorWrapper","editorZone","holder","getElementById","Error","loadStyles","styles","tag","textContent","toString","head","Block","_html","compose"],"mappings":"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AJC;;AAMNrH,0BAAU8F,IAAV,CAAe;AACX3F,8BAAU;AAAA,+BAAM,MAAKmH,WAAL,CAAiBxD,MAAMuD,CAAN,CAAjB,CAAN;AAAA;AADC,iBAAf;AANM;;AAIV,iBAAK,IAAIA,IAAI,CAAb,EAAgBA,IAAIvD,MAAM/D,MAA1B,EAAkCsH,GAAlC,EAAuC;AAAA,sBAA9BA,CAA8B;AAMtC;;AAEDZ,cAAEc,QAAF,CAAWvH,SAAX;AAEH;;AAED;;;;;;;;;;;;oCASYwH,I,EAAM;;AAEd,gBAAIC,OAAOD,KAAKE,IAAhB;AAAA,gBACItH,OAAOoH,KAAKpH,IADhB;;AAGA,iBAAKlB,MAAL,CAAY+E,YAAZ,CAAyBuB,MAAzB,CAAgCiC,IAAhC,EAAsCrH,IAAtC;;AAEA,mBAAOb,QAAQC,OAAR,EAAP;AAEH;;;0BA9CSN,M,EAAQ;;AAEd,iBAAKA,MAAL,GAAcA,MAAd;AAEH;;;;;;;;;AA8CLsD,OAAOC,OAAP,GAAiBsB,QAAjB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,U;;;;;;;;;;;;;;;;;;;;;;ACjRA;;;;;;;;;;;;;;;;;;;AAoBA;;;;;;;;;;;;;;;IAeqB4D,S;;;AAEjB;;;;;;;;AAQA,uBAAY7I,MAAZ,EAAoB;AAAA;;AAIhB;AAJgB,0HAEVA,MAFU;;AAKhB,cAAK8I,aAAL,GAAqB,EAArB;AACA,cAAKC,eAAL,GAAuB,IAAvB;;AAEA;AACA,cAAKC,eAAL,GAAuBhJ,OAAOiJ,QAAP,GAAkBjJ,OAAOiJ,QAAP,CAAgB3D,SAAlC,GAA8C,EAArE;;AAEA;AACA,cAAK4D,iBAAL,GAAyB,mBAAAC,CAAQ,CAAR,CAAzB;;AAZgB;AAcnB;;AAED;;;;;;;;;;;;;;;AA0CA;;;;;;8BAMMC,W,EAAa;;AAEf,mBAAO,KAAKL,eAAL,CAAqBM,KAArB,CAA2BD,WAA3B,CAAP;AAEH;;AAED;;;;;;;;;;;;;;0BA7CsBE,O,EAAS;;AAE3B,iBAAKP,eAAL,GAAuB,IAAIO,OAAJ,CAAY,KAAKC,cAAjB,CAAvB;AAEH;;AAED;;;;;;;0BAIoBvJ,M,EAAQ;;AAExB,gBAAI2H,EAAE6B,OAAF,CAAUxJ,MAAV,CAAJ,EAAuB;;AAEnB,qBAAKuJ,cAAL,GAAsB;AAClBE,0BAAM;AACFlE,2BAAG,EADD;AAEFE,2BAAG;AACCiE,kCAAM,IADP;AAECxJ,oCAAQ,QAFT;AAGCyJ,iCAAK;AAHN;AAFD;AADY,iBAAtB;AAWH,aAbD,MAaO;;AAEH,qBAAKJ,cAAL,GAAsBvJ,MAAtB;AAEH;AAEJ;;;8BAyBYoJ,W,EAAaQ,Y,EAAc;;AAEpC,gBAAIC,cAAchB,UAAUe,YAAV,CAAlB;;AAEA,mBAAOC,YAAYR,KAAZ,CAAkBD,WAAlB,CAAP;AAEH;;;;EAjGkCrJ,M;;;kBAAlB8I,S;;;;;;;;ACnCrB;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;AACA,CAAC;;AAED;AACA,aAAa,OAAO;AACpB,aAAa,QAAQ;AACrB;AACA;;AAEA;AACA;;AAEA;AACA,wBAAwB,iCAAiC,EAAE;AAC3D,6BAA6B,uEAAuE,EAAE;;AAEtG;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,gBAAgB,QAAQ;;AAExB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,+DAA+D;AAC/D;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,qBAAqB,4BAA4B;AACjD;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;;AAEA,CAAC;;;;;;;;;;;;;;;;;;;;;;ACxLD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmDqBiB,O;;;AAEjB;;;AAGA,mBAAY9J,MAAZ,EAAo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CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;kBApXqB+E,E;;;;;;;;ACzDrB;AACA;;;AAGA;AACA,gCAAiC,iDAAiD,2CAA2C,yBAAyB,6BAA6B,oBAAoB,GAAG,uBAAuB,wBAAwB,OAAO;;AAEhQ;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,mCAAmC,gBAAgB;AACnD,IAAI;AACJ;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAgB,iBAAiB;AACjC;AACA;AACA;AACA;AACA,YAAY,oBAAoB;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,oDAAoD,cAAc;;AAElE;AACA;;;;;;;;;;;;;;;;;;AC3EA;;;;;;;;;;IAWqB0H,K;;AAEjB;;;;;AAKA,mBAAY7D,IAAZ,EAAkB;AAAA;;AAEd,aAAKA,IAAL,GAAYA,IAAZ;;AAEA,aAAK6B,GAAL,GAAW;AACPT,qBAAS,UADF;AAEPC,qBAAS;AAFF,SAAX;;AAKA,aAAKyC,KAAL,GAAa,KAAKC,OAAL,EAAb;AAEH;;AAED;;;;;;;;;;kCAMU;;AAEN,gBAAI3C,UAAUW,EAAEC,IAAF,CAAO,KAAP,EAAc,KAAKH,GAAL,CAAST,OAAvB,CAAd;AAAA,gBACIC,UAAUU,EAAEC,IAAF,CAAO,KAAP,EAAc,KAAKH,GAAL,CAASR,OAAvB,CADd;;AAGAA,oBAAQjH,WAAR,CAAoB,KAAK4F,IAAL,CAAU1B,IAA9B;AACA8C,oBAAQhH,WAAR,CAAoBiH,OAApB;;AAEA,mBAAOD,OAAP;AAEH;;AAED;;;;;;;;4BAKW;;AAEP,mBAAO,KAAK0C,KAAZ;AAEH;;;;;;;kBA/CgBD,K","file":"codex-editor.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 3);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 085a7f316dc8d48f2889","/**\n * @abstract\n * @class Module\n * @classdesc All modules inherites from this class.\n *\n * @typedef {Module} Module\n * @property {Object} config - Editor user settings\n * @property {Object} Editor - List of Editor modules\n */\nexport default class Module {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor(config) {\n\n if (new.target === Module) {\n\n throw new TypeError('Constructors for abstract class Module are not allowed.');\n\n }\n\n this.config = config;\n this.Editor = null;\n\n }\n\n /**\n * Editor modules setter\n *\n * @param Editor\n * @param Editor.modules {@link CodexEditor#moduleInstances}\n * @param Editor.config {@link CodexEditor#configuration}\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/__module.js","/**\n * Codex Editor Util\n */\nexport default class Util {\n\n /**\n * @typedef {Object} ChainData\n * @property {Object} data - data that will be passed to the success or fallback\n * @property {Function} function - function's that must be called asynchronically\n */\n\n /**\n * Fires a promise sequence asyncronically\n *\n * @param {Object[]} chains - list or ChainData's\n * @param {Function} success - success callback\n * @param {Function} fallback - callback that fires in case of errors\n *\n * @return {Promise}\n */\n static sequence(chains, success = () => {}, fallback = () => {}) {\n\n return new Promise(function (resolve) {\n\n /**\n * pluck each element from queue\n * First, send resolved Promise as previous value\n * Each plugins \"prepare\" method returns a Promise, that's why\n * reduce current element will not be able to continue while can't get\n * a resolved Promise\n */\n chains.reduce(function (previousValue, currentValue, iteration) {\n\n return previousValue\n .then(() => waitNextBlock(currentValue, success, fallback))\n .then(() => {\n\n // finished\n if (iteration === chains.length - 1) {\n\n resolve();\n\n }\n\n });\n\n }, Promise.resolve());\n\n });\n\n /**\n * Decorator\n *\n * @param {ChainData} chainData\n *\n * @param {Function} successCallback\n * @param {Function} fallbackCallback\n *\n * @return {Promise}\n */\n function waitNextBlock(chainData, successCallback, fallbackCallback) {\n\n return new Promise(function (resolve) {\n\n chainData.function()\n .then(() => {\n\n successCallback(chainData.data);\n\n })\n .then(resolve)\n .catch(function () {\n\n fallbackCallback(chainData.data);\n\n // anyway, go ahead even it falls\n resolve();\n\n });\n\n });\n\n }\n\n }\n\n /**\n * Make array from array-like collection\n *\n * @param {*} collection\n *\n * @return {Array}\n */\n static array(collection) {\n\n return Array.prototype.slice.call(collection);\n\n }\n\n /**\n * Checks if object is empty\n *\n * @param {Object} object\n * @return {boolean}\n */\n static isEmpty(object) {\n\n return Object.keys(object).length === 0 && object.constructor === Object;\n\n }\n\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/utils.js","/**\n * DOM manupulations helper\n */\nexport default class Dom {\n\n /**\n * Helper for making Elements with classname and attributes\n *\n * @param {string} tagName - new Element tag name\n * @param {array|string} classNames - list or name of CSS classname(s)\n * @param {Object} attributes - any attributes\n * @return {Element}\n */\n static make(tagName, classNames = null, attributes = {}) {\n\n var el = document.createElement(tagName);\n\n if ( Array.isArray(classNames) ) {\n\n el.classList.add(...classNames);\n\n } else if( classNames ) {\n\n el.classList.add(classNames);\n\n }\n\n for (let attrName in attributes) {\n\n el[attrName] = attributes[attrName];\n\n }\n\n return el;\n\n }\n\n /**\n * Append one or several elements to the parent\n *\n * @param {Element} parent - where to append\n * @param {Element|Element[]} - element ore elements list\n */\n static append(parent, elements) {\n\n if ( Array.isArray(elements) ) {\n\n elements.forEach( el => parent.appendChild(el) );\n\n } else {\n\n parent.appendChild(elements);\n\n }\n\n }\n\n /**\n * Selector Decorator\n *\n * Returns first match\n *\n * @param {Element} el - element we searching inside. Default - DOM Document\n * @param {String} selector - searching string\n *\n * @returns {Element}\n */\n static find(el = document, selector) {\n\n return el.querySelector(selector);\n\n }\n\n /**\n * Selector Decorator.\n *\n * Returns all matches\n *\n * @param {Element} el - element we searching inside. Default - DOM Document\n * @param {String} selector - searching string\n * @returns {NodeList}\n */\n static findAll(el = document, selector) {\n\n return el.querySelectorAll(selector);\n\n }\n\n /**\n * Check if object is DOM node\n *\n * @param {Object} node\n * @returns {boolean}\n */\n static isNode(node) {\n\n return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.ELEMENT_NODE;\n\n }\n\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/dom.js","/**\n * Codex Editor\n *\n * Short Description (눈_눈;)\n * @version 2.0.0\n *\n * How to start?\n * Example:\n * new CodexEditor({\n * holderId : 'codex-editor',\n * initialBlock : 'paragraph',\n * placeholder : 'Write your story....',\n * tools: {\n * quote: Quote,\n * anotherTool : AnotherTool\n * },\n * toolsConfig: {\n * quote: {\n * iconClassname : 'quote-icon',\n * displayInToolbox : true,\n * enableLineBreaks : true\n * },\n * anotherTool: {\n * iconClassname : 'tool-icon'\n * }\n * }\n * });\n *\n * - tools is an object: {\n * pluginName: PluginClass,\n * .....\n * }\n * - toolsConfig is an additional configuration that uses Codex Editor API\n * iconClassname - CSS classname of toolbox icon\n * displayInToolbox - if you want to see your Tool in toolbox hided in \"plus\" button, than set \"True\". By default : \"False\"\n * enableLineBreaks - by default enter creates new block that set as initialblock, but if you set this property \"True\", enter will break the lines in current block\n *\n * @author CodeX-Team \n *\n */\n\n/**\n * @typedef {CodexEditor} CodexEditor - editor class\n */\n\n/**\n * @typedef {Object} EditorConfig\n * @property {String} holderId - Element to append Editor\n * @property {Array} data - Blocks list in JSON-format\n * ...\n */\n\n'use strict';\n\n/**\n * Require Editor modules places in components/modules dir\n */\n// eslint-disable-next-line\nlet modules = editorModules.map( module => require('./components/modules/' + module ));\n\n/**\n * @class\n *\n * @classdesc CodeX Editor base class\n *\n * @property this.config - all settings\n * @property this.moduleInstances - constructed editor components\n *\n * @type {CodexEditor}\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n\n /**\n * Configuration object\n */\n this.config = {};\n\n /**\n * Editor Components\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n\n this.configuration = config;\n\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n\n console.log('CodeX Editor is ready');\n\n })\n .catch(error => {\n\n console.log('CodeX Editor does not ready beecause of %o', error);\n\n });\n\n }\n\n /**\n * Setting for configuration\n * @param {Object} config\n */\n set configuration(config = {}) {\n\n this.config.holderId = config.holderId;\n this.config.placeholder = config.placeholder || 'write your story...';\n this.config.sanitizer = config.sanitizer || {\n p: true,\n b: true,\n a: true\n };\n\n this.config.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n this.config.tools = config.tools || {};\n this.config.toolsConfig = config.toolsConfig || {};\n this.config.data = config.data || [];\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this.config;\n\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n this.constructModules();\n\n /**\n * Modules configuration\n */\n this.configureModules();\n\n }\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n\n modules.forEach( Module => {\n\n try {\n\n /**\n * We use class name provided by displayName property\n *\n * On build, Babel will transform all Classes to the Functions so, name will always be 'Function'\n * To prevent this, we use 'babel-plugin-class-display-name' plugin\n * @see https://www.npmjs.com/package/babel-plugin-class-display-name\n */\n\n this.moduleInstances[Module.displayName] = new Module({\n config : this.configuration\n });\n\n } catch ( e ) {\n\n console.log('Module %o skipped because %o', Module, e);\n\n }\n\n });\n\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n\n for(let name in this.moduleInstances) {\n\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n\n }\n\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n\n let diff = {};\n\n for(let moduleName in this.moduleInstances) {\n\n /**\n * Skip module with passed name\n */\n if (moduleName === name) {\n\n continue;\n\n }\n diff[moduleName] = this.moduleInstances[moduleName];\n\n }\n\n return diff;\n\n }\n\n /**\n * Start Editor!\n *\n * @return {Promise}\n */\n start() {\n\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances.UI))\n .then(prepareDecorator(this.moduleInstances.Tools))\n .then(() => {\n\n if (this.config.data && this.config.data.items) {\n\n this.moduleInstances.Renderer.render(this.config.data.items);\n\n }\n\n })\n .then(prepareDecorator(this.moduleInstances.BlockManager))\n\n .catch(function (error) {\n\n console.log('Error occured', error);\n\n });\n\n }\n\n};\n\n// module.exports = (function (editor) {\n//\n// 'use strict';\n//\n// editor.version = VERSION;\n// editor.scriptPrefix = 'cdx-script-';\n//\n// var init = function () {\n//\n// editor.core = require('./modules/core');\n// editor.tools = require('./modules/tools');\n// editor.ui = require('./modules/ui');\n// editor.transport = require('./modules/transport');\n// editor.renderer = require('./modules/renderer');\n// editor.saver = require('./modules/saver');\n// editor.content = require('./modules/content');\n// editor.toolbar = require('./modules/toolbar/toolbar');\n// editor.callback = require('./modules/callbacks');\n// editor.draw = require('./modules/draw');\n// editor.caret = require('./modules/caret');\n// editor.notifications = require('./modules/notifications');\n// editor.parser = require('./modules/parser');\n// editor.sanitizer = require('./modules/sanitizer');\n// editor.listeners = require('./modules/listeners');\n// editor.destroyer = require('./modules/destroyer');\n// editor.paste = require('./modules/paste');\n//\n// };\n//\n// /**\n// * @public\n// * holds initial settings\n// */\n// editor.settings = {\n// tools : ['paragraph', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],\n// holderId : 'codex-editor',\n//\n// // Type of block showing on empty editor\n// initialBlockPlugin: 'paragraph'\n// };\n//\n// /**\n// * public\n// *\n// * Static nodes\n// */\n// editor.nodes = {\n// holder : null,\n// wrapper : null,\n// toolbar : null,\n// inlineToolbar : {\n// wrapper : null,\n// buttons : null,\n// actions : null\n// },\n// toolbox : null,\n// notifications : null,\n// plusButton : null,\n// showSettingsButton: null,\n// showTrashButton : null,\n// blockSettings : null,\n// pluginSettings : null,\n// defaultSettings : null,\n// toolbarButtons : {}, // { type : DomEl, ... }\n// redactor : null\n// };\n//\n// /**\n// * @public\n// *\n// * Output state\n// */\n// editor.state = {\n// jsonOutput : [],\n// blocks : [],\n// inputs : []\n// };\n//\n// /**\n// * @public\n// * Editor plugins\n// */\n// editor.tools = {};\n//\n// editor.start = function (userSettings) {\n//\n// init();\n//\n// editor.core.prepare(userSettings)\n//\n// // If all ok, make UI, bind events and parse initial-content\n// .then(editor.ui.prepare)\n// .then(editor.tools.prepare)\n// .then(editor.sanitizer.prepare)\n// .then(editor.paste.prepare)\n// .then(editor.transport.prepare)\n// .then(editor.renderer.makeBlocksFromData)\n// .then(editor.ui.saveInputs)\n// .catch(function (error) {\n//\n// editor.core.log('Initialization failed with error: %o', 'warn', error);\n//\n// });\n//\n// };\n//\n// return editor;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/codex.js","var map = {\n\t\"./blockManager.js\": 5,\n\t\"./events.js\": 6,\n\t\"./renderer.js\": 7,\n\t\"./sanitizer.js\": 8,\n\t\"./toolbar.js\": 10,\n\t\"./tools.js\": 11,\n\t\"./ui.js\": 12\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) // check for number or string\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\treturn id;\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 4;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/modules nonrecursive [^_](blockManager.js|events.js|renderer.js|sanitizer.js|toolbar.js|tools.js|ui.js)$\n// module id = 4\n// module chunks = 0","/**\n * @class BlockManager\n * @classdesc Manage editor`s blocks storage and appearance\n */\n\nimport Block from '../block';\n\nclass BlockManager {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({ config }) {\n\n this.config = config;\n this.Editor = null;\n\n /**\n * Proxy for Blocks instance {@link Blocks}\n *\n * @type {Proxy}\n * @private\n */\n this._blocks = null;\n\n /**\n * Index of current working block\n *\n * @type {number}\n * @private\n */\n this.currentBlockIndex = -1;\n\n }\n\n /**\n * Editor modules setting\n *\n * @param Editor\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n * Should be called after Editor.UI preparation\n * Define this._blocks property\n *\n * @returns {Promise}\n */\n prepare() {\n\n return new Promise(resolve => {\n\n let blocks = new Blocks(this.Editor.UI.nodes.redactor);\n\n /**\n * We need to use Proxy to overload set/get [] operator.\n * So we can use array-like syntax to access blocks\n *\n * @example\n * this._blocks[0] = new Block(...);\n *\n * block = this._blocks[0];\n *\n * @todo proxy the enumerate method\n *\n * @type {Proxy}\n * @private\n */\n this._blocks = new Proxy(blocks, {\n set: Blocks.set,\n get: Blocks.get\n });\n\n resolve();\n\n });\n\n }\n\n /**\n * Insert new block into _blocks\n *\n * @param {String} toolName — plugin name\n * @param {Object} data — plugin data\n */\n insert(toolName, data) {\n\n let toolInstance = this.Editor.Tools.construct(toolName, data),\n block = new Block(toolInstance);\n\n this._blocks[++this.currentBlockIndex] = block;\n\n }\n\n /**\n * Replace current working block\n *\n * @param {String} toolName — plugin name\n * @param {Object} data — plugin data\n */\n replace(toolName, data) {\n\n let toolInstance = this.Editor.Tools.construct(toolName, data),\n block = new Block(toolInstance);\n\n this._blocks.insert(this.currentBlockIndex, block, true);\n\n }\n\n /**\n * Get Block instance by html element\n *\n * @todo get first level block before searching\n *\n * @param {HTMLElement} element\n * @returns {Block}\n */\n getBlock(element) {\n\n let nodes = this._blocks.nodes,\n index = nodes.indexOf(element);\n\n if (index >= 0) {\n\n return this._blocks[index];\n\n }\n\n }\n\n /**\n * Get current Block instance\n *\n * @return {Block}\n */\n get currentBlock() {\n\n return this._blocks[this.currentBlockIndex];\n\n }\n\n /**\n * Get working html element\n *\n * @return {HTMLElement}\n */\n get currentNode() {\n\n return this._blocks.nodes[this.currentBlockIndex];\n\n }\n\n /**\n * Set currentBlockIndex to passed block\n *\n * @todo get first level block before searching\n *\n * @param {HTMLElement} element\n */\n set currentNode(element) {\n\n let nodes = this._blocks.nodes;\n\n this.currentBlockIndex = nodes.indexOf(element);\n\n }\n\n /**\n * Get array of Block instances\n *\n * @returns {Block[]} {@link Blocks#array}\n */\n get blocks() {\n\n return this._blocks.array;\n\n }\n\n}\n\n/**\n * @class Blocks\n * @classdesc Class to work with Block instances array\n *\n * @private\n *\n * @property {HTMLElement} workingArea — editor`s working node\n *\n */\nclass Blocks {\n\n /**\n * @constructor\n *\n * @param {HTMLElement} workingArea — editor`s working node\n */\n constructor(workingArea) {\n\n this.blocks = [];\n this.workingArea = workingArea;\n\n }\n\n /**\n * Push back new Block\n *\n * @param {Block} block\n */\n push(block) {\n\n this.blocks.push(block);\n this.workingArea.appendChild(block.html);\n\n }\n\n /**\n * Insert new Block at passed index\n *\n * @param {Number} index — index to insert Block\n * @param {Block} block — Block to insert\n * @param {Boolean} replace — it true, replace block on given index\n */\n insert(index, block, replace = false) {\n\n if (!this.length) {\n\n this.push(block);\n return;\n\n }\n\n if (index > this.length) {\n\n index = this.length;\n\n }\n\n if (replace) {\n\n this.blocks[index].html.remove();\n\n }\n\n let deleteCount = replace ? 1 : 0;\n\n this.blocks.splice(index, deleteCount, block);\n\n if (index > 0) {\n\n let previousBlock = this.blocks[index - 1];\n\n previousBlock.html.insertAdjacentElement('afterend', block.html);\n\n } else {\n\n let nextBlock = this.blocks[index + 1];\n\n if (nextBlock) {\n\n nextBlock.html.insertAdjacentElement('beforebegin', block.html);\n\n } else {\n\n this.workingArea.appendChild(block.html);\n\n }\n\n }\n\n }\n\n /**\n * Insert Block after passed target\n *\n * @todo decide if this method is necessary\n *\n * @param {Block} targetBlock — target after wich Block should be inserted\n * @param {Block} newBlock — Block to insert\n */\n insertAfter(targetBlock, newBlock) {\n\n let index = this.blocks.indexOf(targetBlock);\n\n this.insert(index + 1, newBlock);\n\n }\n\n /**\n * Get Block by index\n *\n * @param {Number} index — Block index\n * @returns {Block}\n */\n get(index) {\n\n return this.blocks[index];\n\n }\n\n /**\n * Return index of passed Block\n *\n * @param {Block} block\n * @returns {Number}\n */\n indexOf(block) {\n\n return this.blocks.indexOf(block);\n\n }\n\n /**\n * Get length of Block instances array\n *\n * @returns {Number}\n */\n get length() {\n\n return this.blocks.length;\n\n }\n\n /**\n * Get Block instances array\n *\n * @returns {Block[]}\n */\n get array() {\n\n return this.blocks;\n\n }\n\n /**\n * Get blocks html elements array\n *\n * @returns {HTMLElement[]}\n */\n get nodes() {\n\n return _.array(this.workingArea.children);\n\n }\n\n /**\n * Proxy trap to implement array-like setter\n *\n * @example\n * blocks[0] = new Block(...)\n *\n * @param {Blocks} instance — Blocks instance\n * @param {Number|String} index — block index\n * @param {Block} block — Block to set\n * @returns {Boolean}\n */\n static set(instance, index, block) {\n\n if (isNaN(Number(index))) {\n\n return false;\n\n }\n\n instance.insert(index, block);\n\n return true;\n\n }\n\n /**\n * Proxy trap to implement array-like getter\n *\n * @param {Blocks} instance — Blocks instance\n * @param {Number|String} index — Block index\n * @returns {Block|*}\n */\n static get(instance, index) {\n\n if (isNaN(Number(index))) {\n\n return instance[index];\n\n }\n\n return instance.get(index);\n\n }\n\n}\n\nmodule.exports = BlockManager;\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/blockManager.js","/**\n * @module eventDispatcher\n *\n * Has two important methods:\n * - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one\n * - {Function} emit - fires all subscribers with data\n *\n * @version 1.0.0\n *\n * @typedef {Events} Events\n * @property {Object} subscribers - all subscribers grouped by event name\n */\nexport default class Events extends Module {\n\n /**\n * @constructor\n */\n constructor() {\n\n super();\n\n this.subscribers = {};\n\n }\n\n /**\n * @param {String} eventName - event name\n * @param {Function} callback - subscriber\n */\n on(eventName, callback) {\n\n if (!(eventName in this.subscribers)) {\n\n this.subscribers[eventName] = [];\n\n }\n\n // group by events\n this.subscribers[eventName].push(callback);\n\n }\n\n /**\n * @param {String} eventName - event name\n * @param {Object} data - subscribers get this data when they were fired\n */\n emit(eventName, data) {\n\n this.subscribers[eventName].reduce(function (previousData, currentHandler) {\n\n let newData = currentHandler(previousData);\n\n return newData ? newData : previousData;\n\n }, data);\n\n }\n\n /**\n * Destroyer\n */\n destroy() {\n\n this.Editor = null;\n this.subscribers = null;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/events.js","/**\n * Codex Editor Renderer Module\n *\n * @author Codex Team\n * @version 2.0.0\n */\n\nclass Renderer {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor(config) {\n\n this.config = config;\n this.Editor = null;\n\n }\n\n /**\n * Editor modules setter\n *\n * @param {Object} Editor\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n *\n * Make plugin blocks from array of plugin`s data\n *\n * @param {Object[]} items\n */\n render(items) {\n\n let chainData = [];\n\n for (let i = 0; i < items.length; i++) {\n\n chainData.push({\n function: () => this.insertBlock(items[i])\n });\n\n }\n\n _.sequence(chainData);\n\n }\n\n /**\n * Get plugin instance\n * Add plugin instance to BlockManager\n * Insert block to working zone\n *\n * @param {Object} item\n * @returns {Promise.}\n * @private\n */\n insertBlock(item) {\n\n let tool = item.type,\n data = item.data;\n\n this.Editor.BlockManager.insert(tool, data);\n\n return Promise.resolve();\n\n }\n\n}\n\nmodule.exports = Renderer;\n\n// module.exports = (function (renderer) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * Asyncronously parses input JSON to redactor blocks\n// */\n// renderer.makeBlocksFromData = function () {\n//\n// /**\n// * If redactor is empty, add first paragraph to start writing\n// */\n// if (editor.core.isEmpty(editor.state.blocks) || !editor.state.blocks.items.length) {\n//\n// editor.ui.addInitialBlock();\n// return;\n//\n// }\n//\n// Promise.resolve()\n//\n// /** First, get JSON from state */\n// .then(function () {\n//\n// return editor.state.blocks;\n//\n// })\n//\n// /** Then, start to iterate they */\n// .then(editor.renderer.appendBlocks)\n//\n// /** Write log if something goes wrong */\n// .catch(function (error) {\n//\n// editor.core.log('Error while parsing JSON: %o', 'error', error);\n//\n// });\n//\n// };\n//\n// /**\n// * Parses JSON to blocks\n// * @param {object} data\n// * @return Promise -> nodeList\n// */\n// renderer.appendBlocks = function (data) {\n//\n// var blocks = data.items;\n//\n// /**\n// * Sequence of one-by-one blocks appending\n// * Uses to save blocks order after async-handler\n// */\n// var nodeSequence = Promise.resolve();\n//\n// for (var index = 0; index < blocks.length ; index++ ) {\n//\n// /** Add node to sequence at specified index */\n// editor.renderer.appendNodeAtIndex(nodeSequence, blocks, index);\n//\n// }\n//\n// };\n//\n// /**\n// * Append node at specified index\n// */\n// renderer.appendNodeAtIndex = function (nodeSequence, blocks, index) {\n//\n// /** We need to append node to sequence */\n// nodeSequence\n//\n// /** first, get node async-aware */\n// .then(function () {\n//\n// return editor.renderer.getNodeAsync(blocks, index);\n//\n// })\n//\n// /**\n// * second, compose editor-block from JSON object\n// */\n// .then(editor.renderer.createBlockFromData)\n//\n// /**\n// * now insert block to redactor\n// */\n// .then(function (blockData) {\n//\n// /**\n// * blockData has 'block', 'type' and 'stretched' information\n// */\n// editor.content.insertBlock(blockData);\n//\n// /** Pass created block to next step */\n// return blockData.block;\n//\n// })\n//\n// /** Log if something wrong with node */\n// .catch(function (error) {\n//\n// editor.core.log('Node skipped while parsing because %o', 'error', error);\n//\n// });\n//\n// };\n//\n// /**\n// * Asynchronously returns block data from blocksList by index\n// * @return Promise to node\n// */\n// renderer.getNodeAsync = function (blocksList, index) {\n//\n// return Promise.resolve().then(function () {\n//\n// return {\n// tool : blocksList[index],\n// position : index\n// };\n//\n// });\n//\n// };\n//\n// /**\n// * Creates editor block by JSON-data\n// *\n// * @uses render method of each plugin\n// *\n// * @param {Object} toolData.tool\n// * { header : {\n// * text: '',\n// * type: 'H3', ...\n// * }\n// * }\n// * @param {Number} toolData.position - index in input-blocks array\n// * @return {Object} with type and Element\n// */\n// renderer.createBlockFromData = function ( toolData ) {\n//\n// /** New parser */\n// var block,\n// tool = toolData.tool,\n// pluginName = tool.type;\n//\n// /** Get first key of object that stores plugin name */\n// // for (var pluginName in blockData) break;\n//\n// /** Check for plugin existance */\n// if (!editor.tools[pluginName]) {\n//\n// throw Error(`Plugin «${pluginName}» not found`);\n//\n// }\n//\n// /** Check for plugin having render method */\n// if (typeof editor.tools[pluginName].render != 'function') {\n//\n// throw Error(`Plugin «${pluginName}» must have «render» method`);\n//\n// }\n//\n// if ( editor.tools[pluginName].available === false ) {\n//\n// block = editor.draw.unavailableBlock();\n//\n// block.innerHTML = editor.tools[pluginName].loadingMessage;\n//\n// /**\n// * Saver will extract data from initial block data by position in array\n// */\n// block.dataset.inputPosition = toolData.position;\n//\n// } else {\n//\n// /** New Parser */\n// block = editor.tools[pluginName].render(tool.data);\n//\n// }\n//\n// /** is first-level block stretched */\n// var stretched = editor.tools[pluginName].isStretched || false;\n//\n// /** Retrun type and block */\n// return {\n// type : pluginName,\n// block : block,\n// stretched : stretched\n// };\n//\n// };\n//\n// return renderer;\n//\n// })({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/renderer.js","/**\n * Codex Sanitizer\n *\n * @module Sanitizer module\n * Clears HTML from taint tags\n *\n * @version 2.0.0\n *\n * @usage\n * Module can be used within two ways:\n * 1) When you have an instance\n * - this.moduleInstance['Sanitizer'].clean(yourDirtyString);\n * 2) As static method\n * - CodexEditor.Sanitizer.clean(yourDirtyString, yourCustomConfiguration);\n *\n *\n * Look up the SanitizerConfig object as example to make your custom restrictions\n */\n\n\n/**\n * @typedef {Object} SanitizerConfig\n * @property {Object} tags - define tags restrictions\n *\n * @example\n *\n * tags : {\n * p: true,\n * a: {\n * href: true,\n * rel: \"nofollow\",\n * target: \"_blank\"\n * }\n * }\n */\nexport default class Sanitizer extends Module {\n\n /**\n * Initializes Sanitizer module\n * Sets default configuration if custom not exists\n *\n * @property {HTMLJanitor} this.janitor - Sanitizer library\n *\n * @param {SanitizerConfig} config\n */\n constructor(config) {\n\n super(config);\n\n // default config\n this.instantConfig = {};\n this.janitorInstance = null;\n\n /** Custom configuration */\n this.sanitizerConfig = config.settings ? config.settings.sanitizer : {};\n\n /** HTML Janitor library */\n this.sanitizerInstance = require('html-janitor');\n\n }\n\n /**\n * If developer uses editor's API, then he can customize sanitize restrictions.\n * Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere\n * At least, if there is no config overrides, that API uses Default configuration\n *\n * @uses https://www.npmjs.com/package/html-janitor\n *\n * @param {HTMLJanitor} library - sanitizer extension\n */\n set sanitizerInstance(library) {\n\n this.janitorInstance = new library(this.instanceConfig);\n\n }\n\n /**\n * Sets sanitizer configuration. Uses default config if user didn't pass the restriction\n * @param {SanitizerConfig} config\n */\n set sanitizerConfig(config) {\n\n if (_.isEmpty(config)) {\n\n this.instanceConfig = {\n tags: {\n p: {},\n a: {\n href: true,\n target: '_blank',\n rel: 'nofollow'\n }\n }\n };\n\n } else {\n\n this.instanceConfig = config;\n\n }\n\n }\n\n /**\n * Cleans string from unwanted tags\n * @param {String} taintString - HTML string\n *\n * @return {String} clean HTML\n */\n clean(taintString) {\n\n return this.janitorInstance.clean(taintString);\n\n }\n\n /**\n * Cleans string from unwanted tags\n * @static\n *\n * Method allows to use default config\n *\n * @param {String} taintString - taint string\n * @param {SanitizerConfig} customConfig - allowed tags\n *\n * @return {String} clean HTML\n */\n static clean(taintString, customConfig) {\n\n let newInstance = Sanitizer(customConfig);\n\n return newInstance.clean(taintString);\n\n }\n\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/sanitizer.js","(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define('html-janitor', factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.HTMLJanitor = factory();\n }\n}(this, function () {\n\n /**\n * @param {Object} config.tags Dictionary of allowed tags.\n * @param {boolean} config.keepNestedBlockElements Default false.\n */\n function HTMLJanitor(config) {\n\n var tagDefinitions = config['tags'];\n var tags = Object.keys(tagDefinitions);\n\n var validConfigValues = tags\n .map(function(k) { return typeof tagDefinitions[k]; })\n .every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; });\n\n if(!validConfigValues) {\n throw new Error(\"The configuration was invalid\");\n }\n\n this.config = config;\n }\n\n // TODO: not exhaustive?\n var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE'];\n function isBlockElement(node) {\n return blockElementNames.indexOf(node.nodeName) !== -1;\n }\n\n var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE'];\n function isInlineElement(node) {\n return inlineElementNames.indexOf(node.nodeName) !== -1;\n }\n\n HTMLJanitor.prototype.clean = function (html) {\n var sandbox = document.createElement('div');\n sandbox.innerHTML = html;\n\n this._sanitize(sandbox);\n\n return sandbox.innerHTML;\n };\n\n HTMLJanitor.prototype._sanitize = function (parentNode) {\n var treeWalker = createTreeWalker(parentNode);\n var node = treeWalker.firstChild();\n if (!node) { return; }\n\n do {\n // Ignore nodes that have already been sanitized\n if (node._sanitized) {\n continue;\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n // If this text node is just whitespace and the previous or next element\n // sibling is a block element, remove it\n // N.B.: This heuristic could change. Very specific to a bug with\n // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output\n // FIXME: make this an option?\n if (node.data.trim() === ''\n && ((node.previousElementSibling && isBlockElement(node.previousElementSibling))\n || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) {\n parentNode.removeChild(node);\n this._sanitize(parentNode);\n break;\n } else {\n continue;\n }\n }\n\n // Remove all comments\n if (node.nodeType === Node.COMMENT_NODE) {\n parentNode.removeChild(node);\n this._sanitize(parentNode);\n break;\n }\n\n var isInline = isInlineElement(node);\n var containsBlockElement;\n if (isInline) {\n containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement);\n }\n\n // Block elements should not be nested (e.g.

  • ...); if\n // they are, we want to unwrap the inner block element.\n var isNotTopContainer = !! parentNode.parentNode;\n var isNestedBlockElement =\n isBlockElement(parentNode) &&\n isBlockElement(node) &&\n isNotTopContainer;\n\n var nodeName = node.nodeName.toLowerCase();\n\n var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);\n\n var isInvalid = isInline && containsBlockElement;\n\n // Drop tag entirely according to the whitelist *and* if the markup\n // is invalid.\n if (isInvalid || shouldRejectNode(node, allowedAttrs)\n || (!this.config.keepNestedBlockElements && isNestedBlockElement)) {\n // Do not keep the inner text of SCRIPT/STYLE elements.\n if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {\n while (node.childNodes.length > 0) {\n parentNode.insertBefore(node.childNodes[0], node);\n }\n }\n parentNode.removeChild(node);\n\n this._sanitize(parentNode);\n break;\n }\n\n // Sanitize attributes\n for (var a = 0; a < node.attributes.length; a += 1) {\n var attr = node.attributes[a];\n\n if (shouldRejectAttr(attr, allowedAttrs, node)) {\n node.removeAttribute(attr.name);\n // Shift the array to continue looping.\n a = a - 1;\n }\n }\n\n // Sanitize children\n this._sanitize(node);\n\n // Mark node as sanitized so it's ignored in future runs\n node._sanitized = true;\n } while ((node = treeWalker.nextSibling()));\n };\n\n function createTreeWalker(node) {\n return document.createTreeWalker(node,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,\n null, false);\n }\n\n function getAllowedAttrs(config, nodeName, node){\n if (typeof config.tags[nodeName] === 'function') {\n return config.tags[nodeName](node);\n } else {\n return config.tags[nodeName];\n }\n }\n\n function shouldRejectNode(node, allowedAttrs){\n if (typeof allowedAttrs === 'undefined') {\n return true;\n } else if (typeof allowedAttrs === 'boolean') {\n return !allowedAttrs;\n }\n\n return false;\n }\n\n function shouldRejectAttr(attr, allowedAttrs, node){\n var attrName = attr.name.toLowerCase();\n\n if (allowedAttrs === true){\n return false;\n } else if (typeof allowedAttrs[attrName] === 'function'){\n return !allowedAttrs[attrName](attr.value, node);\n } else if (typeof allowedAttrs[attrName] === 'undefined'){\n return true;\n } else if (allowedAttrs[attrName] === false) {\n return true;\n } else if (typeof allowedAttrs[attrName] === 'string') {\n return (allowedAttrs[attrName] !== attr.value);\n }\n\n return false;\n }\n\n return HTMLJanitor;\n\n}));\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/html-janitor/src/html-janitor.js\n// module id = 9\n// module chunks = 0","/**\n *\n * «Toolbar» is the node that moves up/down over current block\n *\n * ______________________________________ Toolbar ____________________________________________\n * | |\n * | ..................... Content .................... ......... Block Actions .......... |\n * | . . . . |\n * | . . . [Open Settings] [Remove Block] . |\n * | . [Plus Button] [Toolbox: {Tool1}, {Tool2}] . . . |\n * | . . . [Settings Panel] . |\n * | .................................................. .................................. |\n * | |\n * |___________________________________________________________________________________________|\n *\n *\n * Toolbox — its an Element contains tools buttons. Can be shown by Plus Button.\n *\n * _______________ Toolbox _______________\n * | |\n * | [Header] [Image] [List] [Quote] ... |\n * |_______________________________________|\n *\n *\n * Settings Panel — is an Element with block settings:\n *\n * ____ Settings Panel ____\n * | ...................... |\n * | . Tool Settings . |\n * | ...................... |\n * | . Default Settings . |\n * | ...................... |\n * |________________________|\n *\n *\n * @class\n * @classdesc Toolbar module\n *\n * @typedef {Toolbar} Toolbar\n * @property {Object} nodes\n * @property {Element} nodes.wrapper - Toolbar main element\n * @property {Element} nodes.content - Zone with Plus button and toolbox.\n * @property {Element} nodes.actions - Zone with Block Settings and Remove Button\n * @property {Element} nodes.plusButton - Button that opens or closes Toolbox\n * @property {Element} nodes.toolbox - Container for tools\n * @property {Element} nodes.settingsToggler - open/close Settings Panel button\n * @property {Element} nodes.removeBlockButton - Remove Block button\n * @property {Element} nodes.settings - Settings Panel\n * @property {Element} nodes.pluginSettings - Plugin Settings section of Settings Panel\n * @property {Element} nodes.defaultSettings - Default Settings section of Settings Panel\n */\nexport default class Toolbar extends Module {\n\n /**\n * @constructor\n */\n constructor(config) {\n\n super(config);\n\n this.nodes = {\n wrapper : null,\n content : null,\n actions : null,\n\n // Content Zone\n plusButton : null,\n toolbox : null,\n\n // Actions Zone\n settingsToggler : null,\n removeBlockButton: null,\n settings: null,\n\n // Settings Zone: Plugin Settings and Default Settings\n pluginSettings: null,\n defaultSettings: null,\n };\n\n this.CSS = {\n toolbar: 'ce-toolbar',\n content: 'ce-toolbar__content',\n actions: 'ce-toolbar__actions',\n\n // Content Zone\n toolbox: 'ce-toolbar__toolbox',\n plusButton: 'ce-toolbar__plus',\n\n // Actions Zone\n settingsToggler: 'ce-toolbar__settings-btn',\n removeBlockButton: 'ce-toolbar__remove-btn',\n\n // Settings Panel\n settings: 'ce-settings',\n defaultSettings: 'ce-settings_default',\n pluginSettings: 'ce-settings_plugin',\n };\n\n }\n\n /**\n * Makes toolbar\n */\n make() {\n\n this.nodes.wrapper = $.make('div', this.CSS.toolbar);\n\n /**\n * Make Content Zone and Actions Zone\n */\n ['content', 'actions'].forEach( el => {\n\n this.nodes[el] = $.make('div', this.CSS[el]);\n $.append(this.nodes.wrapper, this.nodes[el]);\n\n });\n\n\n /**\n * Fill Content Zone:\n * - Plus Button\n * - Toolbox\n */\n ['plusButton', 'toolbox'].forEach( el => {\n\n this.nodes[el] = $.make('div', this.CSS[el]);\n $.append(this.nodes.content, this.nodes[el]);\n\n });\n\n /**\n * Fill Actions Zone:\n * - Settings Toggler\n * - Remove Block Button\n * - Settings Panel\n */\n this.nodes.settingsToggler = $.make('span', this.CSS.settingsToggler);\n this.nodes.removeBlockButton = this.makeRemoveBlockButton();\n\n $.append(this.nodes.actions, [this.nodes.settingsToggler, this.nodes.removeBlockButton]);\n\n /**\n * Make and append Settings Panel\n */\n this.makeBlockSettingsPanel();\n\n /**\n * Append toolbar to the Editor\n */\n $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);\n\n }\n\n /**\n * Panel with block settings with 2 sections:\n *\n * @return {Element}\n */\n makeBlockSettingsPanel() {\n\n this.nodes.settings = $.make('div', this.CSS.settings);\n\n this.nodes.pluginSettings = $.make('div', this.CSS.pluginSettings);\n this.nodes.defaultSettings = $.make('div', this.CSS.defaultSettings);\n\n $.append(this.nodes.settings, [this.nodes.pluginSettings, this.nodes.defaultSettings]);\n $.append(this.nodes.actions, this.nodes.settings);\n\n }\n\n /**\n * Makes Remove Block button, and confirmation panel\n * @return {Element} wrapper with button and panel\n */\n makeRemoveBlockButton() {\n\n /**\n * @todo add confirmation panel and handlers\n * @see {@link settings#makeRemoveBlockButton}\n */\n return $.make('span', this.CSS.removeBlockButton);\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar.js","/**\n * @module Codex Editor Tools Submodule\n *\n * Creates Instances from Plugins and binds external config to the instances\n */\n\n/**\n * Load user defined tools\n * Tools must contain the following important objects:\n *\n * @typedef {Object} ToolsConfig\n * @property {String} iconClassname - this a icon in toolbar\n * @property {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE\n * @property {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE\n */\n\n/**\n * @todo update according to current API\n *\n * @typedef {Object} Tool\n * @property render\n * @property save\n * @property settings\n * @property validate\n */\n\n/**\n * Class properties:\n *\n * @typedef {Tool} Tool\n * @property {String} name - name of this module\n * @property {Object[]} toolInstances - list of tool instances\n * @property {Tools[]} available - available Tools\n * @property {Tools[]} unavailable - unavailable Tools\n * @property {Object} toolsClasses - all classes\n * @property {EditorConfig} config - Editor config\n */\n\nexport default class Tools extends Module {\n\n /**\n * Returns available Tools\n * @return {Tool[]}\n */\n get available() {\n\n return this.toolsAvailable;\n\n }\n\n /**\n * Returns unavailable Tools\n * @return {Tool[]}\n */\n get unavailable() {\n\n return this.toolsUnavailable;\n\n }\n\n /**\n * If config wasn't passed by user\n * @return {ToolsConfig}\n */\n get defaultConfig() {\n\n return {\n iconClassName : 'default-icon',\n displayInToolbox : false,\n enableLineBreaks : false\n };\n\n }\n\n /**\n * @constructor\n *\n * @param {ToolsConfig} config\n */\n constructor({ config }) {\n\n super(config);\n\n this.toolClasses = {};\n this.toolsAvailable = {};\n this.toolsUnavailable = {};\n\n }\n\n /**\n * Creates instances via passed or default configuration\n * @return {boolean}\n */\n prepare() {\n\n if (!this.config.hasOwnProperty('tools')) {\n\n return Promise.reject(\"Can't start without tools\");\n\n }\n\n for(let toolName in this.config.tools) {\n\n this.toolClasses[toolName] = this.config.tools[toolName];\n\n }\n\n /**\n * getting classes that has prepare method\n */\n let sequenceData = this.getListOfPrepareFunctions();\n\n /**\n * if sequence data contains nothing then resolve current chain and run other module prepare\n */\n if (sequenceData.length === 0) {\n\n return Promise.resolve();\n\n }\n\n /**\n * to see how it works {@link Util#sequence}\n */\n return _.sequence(sequenceData, (data) => {\n\n this.success(data);\n\n }, (data) => {\n\n this.fallback(data);\n\n });\n\n }\n\n /**\n * Binds prepare function of plugins with user or default config\n * @return {Array} list of functions that needs to be fired sequently\n */\n getListOfPrepareFunctions() {\n\n let toolPreparationList = [];\n\n for(let toolName in this.toolClasses) {\n\n let toolClass = this.toolClasses[toolName];\n\n if (typeof toolClass.prepare === 'function') {\n\n toolPreparationList.push({\n function : toolClass.prepare,\n data : {\n toolName\n }\n });\n\n }\n\n }\n\n return toolPreparationList;\n\n }\n\n /**\n * @param {ChainData.data} data - append tool to available list\n */\n success(data) {\n\n this.toolsAvailable[data.toolName] = this.toolClasses[data.toolName];\n\n }\n\n /**\n * @param {ChainData.data} data - append tool to unavailable list\n */\n fallback(data) {\n\n this.toolsUnavailable[data.toolName] = this.toolClasses[data.toolName];\n\n }\n\n /**\n * Returns all tools\n * @return {Array}\n */\n getTools() {\n\n return this.toolInstances;\n\n }\n\n /**\n * Return tool`a instance\n *\n * @param {String} tool — tool name\n * @param {Object} data — initial data\n *\n * @todo throw exceptions if tool doesnt exist\n *\n */\n construct(tool, data) {\n\n let plugin = this.toolClasses[tool],\n config = this.config.toolsConfig[tool];\n\n let instance = new plugin(data, config);\n\n return instance;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/tools.js","/**\n * Module UI\n *\n * @type {UI}\n */\n// let className = {\n\n/**\n * @const {string} BLOCK_CLASSNAME - redactor blocks name\n */\n// BLOCK_CLASSNAME : 'ce-block',\n\n/**\n * @const {String} wrapper for plugins content\n */\n// BLOCK_CONTENT : 'ce-block__content',\n\n/**\n * @const {String} BLOCK_STRETCHED - makes block stretched\n */\n// BLOCK_STRETCHED : 'ce-block--stretched',\n\n/**\n * @const {String} BLOCK_HIGHLIGHTED - adds background\n */\n// BLOCK_HIGHLIGHTED : 'ce-block--focused',\n\n/**\n * @const {String} - for all default settings\n */\n// SETTINGS_ITEM : 'ce-settings__item'\n// };\n\nlet CSS = {\n editorWrapper : 'codex-editor',\n editorZone : 'ce-redactor'\n};\n\n/**\n * @class\n *\n * @classdesc Makes CodeX Editor UI:\n * \n * \n * \n * \n * \n *\n * @typedef {UI} UI\n * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}\n * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}\n * @property {Object} nodes -\n * @property {Element} nodes.holder - element where we need to append redactor\n * @property {Element} nodes.wrapper - \n * @property {Element} nodes.redactor - \n */\n\nexport default class UI extends Module {\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({ config }) {\n\n super(config);\n\n this.nodes = {\n holder: null,\n wrapper: null,\n redactor: null\n };\n\n }\n\n /**\n * @protected\n *\n * Making main interface\n */\n prepare() {\n\n return new Promise( (resolve, reject) => {\n\n /**\n * Element where we need to append CodeX Editor\n * @type {Element}\n */\n this.nodes.holder = document.getElementById(this.config.holderId);\n\n if (!this.nodes.holder) {\n\n reject(Error(\"Holder wasn't found by ID: #\" + this.config.holderId));\n return;\n\n }\n\n /**\n * Create and save main UI elements\n */\n this.nodes.wrapper = $.make('div', CSS.editorWrapper);\n this.nodes.redactor = $.make('div', CSS.editorZone);\n\n this.nodes.wrapper.appendChild(this.nodes.redactor);\n this.nodes.holder.appendChild(this.nodes.wrapper);\n\n /**\n * Make toolbar\n */\n this.Editor.Toolbar.make();\n /**\n * Load and append CSS\n */\n this.loadStyles();\n\n resolve();\n\n })\n\n /** Add toolbox tools */\n // .then(addTools_)\n\n /** Make container for inline toolbar */\n // .then(makeInlineToolbar_)\n\n /** Add inline toolbar tools */\n // .then(addInlineToolbarTools_)\n\n /** Draw wrapper for notifications */\n // .then(makeNotificationHolder_)\n\n /** Add eventlisteners to redactor elements */\n // .then(bindEvents_)\n\n .catch(e => {\n\n console.error(e);\n\n // editor.core.log(\"Can't draw editor interface\");\n\n });\n\n }\n\n loadStyles() {\n\n /**\n * Load CSS\n */\n let styles = require('../../styles/main.css');\n\n /**\n * Make tag\n */\n let tag = $.make('style', null, {\n textContent: styles.toString()\n });\n\n /**\n * Append styles\n */\n $.append(document.head, tag);\n\n }\n\n}\n\n// /**\n// * Codex Editor UI module\n// *\n// * @author Codex Team\n// * @version 1.2.0\n// */\n//\n// module.exports = (function (ui) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * Basic editor classnames\n// */\n// ui.prepare = function () {\n//\n\n//\n// };\n//\n// /** Draw notifications holder */\n// var makeNotificationHolder_ = function () {\n//\n// /** Append block with notifications to the document */\n// editor.nodes.notifications = editor.notifications.createHolder();\n//\n// };\n//\n// /**\n// * @private\n// * Append tools passed in editor.tools\n// */\n// var addTools_ = function () {\n//\n// var tool,\n// toolName,\n// toolButton;\n//\n// for ( toolName in editor.settings.tools ) {\n//\n// tool = editor.settings.tools[toolName];\n//\n// editor.tools[toolName] = tool;\n//\n// if (!tool.iconClassname && tool.displayInToolbox) {\n//\n// editor.core.log('Toolbar icon classname missed. Tool %o skipped', 'warn', toolName);\n// continue;\n//\n// }\n//\n// if (typeof tool.render != 'function') {\n//\n// editor.core.log('render method missed. Tool %o skipped', 'warn', toolName);\n// continue;\n//\n// }\n//\n// if (!tool.displayInToolbox) {\n//\n// continue;\n//\n// } else {\n//\n// /** if tools is for toolbox */\n// toolButton = editor.draw.toolbarButton(toolName, tool.iconClassname);\n//\n// editor.nodes.toolbox.appendChild(toolButton);\n//\n// editor.nodes.toolbarButtons[toolName] = toolButton;\n//\n// }\n//\n// }\n//\n// };\n//\n// var addInlineToolbarTools_ = function () {\n//\n// var tools = {\n//\n// bold: {\n// icon : 'ce-icon-bold',\n// command : 'bold'\n// },\n//\n// italic: {\n// icon : 'ce-icon-italic',\n// command : 'italic'\n// },\n//\n// link: {\n// icon : 'ce-icon-link',\n// command : 'createLink'\n// }\n// };\n//\n// var toolButton,\n// tool;\n//\n// for(var name in tools) {\n//\n// tool = tools[name];\n//\n// toolButton = editor.draw.toolbarButtonInline(name, tool.icon);\n//\n// editor.nodes.inlineToolbar.buttons.appendChild(toolButton);\n// /**\n// * Add callbacks to this buttons\n// */\n// editor.ui.setInlineToolbarButtonBehaviour(toolButton, tool.command);\n//\n// }\n//\n// };\n//\n// /**\n// * @private\n// * Bind editor UI events\n// */\n// var bindEvents_ = function () {\n//\n// editor.core.log('ui.bindEvents fired', 'info');\n//\n// // window.addEventListener('error', function (errorMsg, url, lineNumber) {\n// // editor.notifications.errorThrown(errorMsg, event);\n// // }, false );\n//\n// /** All keydowns on Document */\n// editor.listeners.add(document, 'keydown', editor.callback.globalKeydown, false);\n//\n// /** All keydowns on Redactor zone */\n// editor.listeners.add(editor.nodes.redactor, 'keydown', editor.callback.redactorKeyDown, false);\n//\n// /** All keydowns on Document */\n// editor.listeners.add(document, 'keyup', editor.callback.globalKeyup, false );\n//\n// /**\n// * Mouse click to radactor\n// */\n// editor.listeners.add(editor.nodes.redactor, 'click', editor.callback.redactorClicked, false );\n//\n// /**\n// * Clicks to the Plus button\n// */\n// editor.listeners.add(editor.nodes.plusButton, 'click', editor.callback.plusButtonClicked, false);\n//\n// /**\n// * Clicks to SETTINGS button in toolbar\n// */\n// editor.listeners.add(editor.nodes.showSettingsButton, 'click', editor.callback.showSettingsButtonClicked, false );\n//\n// /** Bind click listeners on toolbar buttons */\n// for (var button in editor.nodes.toolbarButtons) {\n//\n// editor.listeners.add(editor.nodes.toolbarButtons[button], 'click', editor.callback.toolbarButtonClicked, false);\n//\n// }\n//\n// };\n//\n// ui.addBlockHandlers = function (block) {\n//\n// if (!block) return;\n//\n// /**\n// * Block keydowns\n// */\n// editor.listeners.add(block, 'keydown', editor.callback.blockKeydown, false);\n//\n// /**\n// * Pasting content from another source\n// * We have two type of sanitization\n// * First - uses deep-first search algorithm to get sub nodes,\n// * sanitizes whole Block_content and replaces cleared nodes\n// * This method is deprecated\n// * Method is used in editor.callback.blockPaste(event)\n// *\n// * Secont - uses Mutation observer.\n// * Observer \"observe\" DOM changes and send changings to callback.\n// * Callback gets changed node, not whole Block_content.\n// * Inserted or changed node, which we've gotten have been cleared and replaced with diry node\n// *\n// * Method is used in editor.callback.blockPasteViaSanitize(event)\n// *\n// * @uses html-janitor\n// * @example editor.callback.blockPasteViaSanitize(event), the second method.\n// *\n// */\n// editor.listeners.add(block, 'paste', editor.paste.blockPasteCallback, false);\n//\n// /**\n// * Show inline toolbar for selected text\n// */\n// editor.listeners.add(block, 'mouseup', editor.toolbar.inline.show, false);\n// editor.listeners.add(block, 'keyup', editor.toolbar.inline.show, false);\n//\n// };\n//\n// /** getting all contenteditable elements */\n// ui.saveInputs = function () {\n//\n// var redactor = editor.nodes.redactor;\n//\n// editor.state.inputs = [];\n//\n// /** Save all inputs in global variable state */\n// var inputs = redactor.querySelectorAll('[contenteditable], input, textarea');\n//\n// Array.prototype.map.call(inputs, function (current) {\n//\n// if (!current.type || current.type == 'text' || current.type == 'textarea') {\n//\n// editor.state.inputs.push(current);\n//\n// }\n//\n// });\n//\n// };\n//\n// /**\n// * Adds first initial block on empty redactor\n// */\n// ui.addInitialBlock = function () {\n//\n// var initialBlockType = editor.settings.initialBlockPlugin,\n// initialBlock;\n//\n// if ( !editor.tools[initialBlockType] ) {\n//\n// editor.core.log('Plugin %o was not implemented and can\\'t be used as initial block', 'warn', initialBlockType);\n// return;\n//\n// }\n//\n// initialBlock = editor.tools[initialBlockType].render();\n//\n// initialBlock.setAttribute('data-placeholder', editor.settings.placeholder);\n//\n// editor.content.insertBlock({\n// type : initialBlockType,\n// block : initialBlock\n// });\n//\n// editor.content.workingNodeChanged(initialBlock);\n//\n// };\n//\n// ui.setInlineToolbarButtonBehaviour = function (button, type) {\n//\n// editor.listeners.add(button, 'mousedown', function (event) {\n//\n// editor.toolbar.inline.toolClicked(event, type);\n//\n// }, false);\n//\n// };\n//\n// return ui;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/ui.js","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(undefined);\n// imports\n\n\n// module\nexports.push([module.id, \":root {\\n\\n /**\\n * Toolbar buttons\\n */\\n\\n}\\n/**\\n* Editor wrapper\\n*/\\n.codex-editor{\\n position: relative;\\n border: 1px solid #ccc;\\n padding: 10px;\\n}\\n.codex-editor .hide {\\n display: none;\\n }\\n\", \"\"]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/main.css\n// module id = 13\n// module chunks = 0","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader/lib/css-base.js\n// module id = 14\n// module chunks = 0","/**\n *\n * @class Block\n * @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool\n *\n * @property {Tool} tool — current block tool (Paragraph, for example)\n * @property {Object} CSS — block`s css classes\n *\n */\n\n\nexport default class Block {\n\n /**\n * @constructor\n *\n * @param {Object} tool — current block plugin`s instance\n */\n constructor(tool) {\n\n this.tool = tool;\n\n this.CSS = {\n wrapper: 'ce-block',\n content: 'ce-block__content'\n };\n\n this._html = this.compose();\n\n }\n\n /**\n * Make default block wrappers and put tool`s content there\n *\n * @returns {HTMLDivElement}\n * @private\n */\n compose() {\n\n let wrapper = $.make('div', this.CSS.wrapper),\n content = $.make('div', this.CSS.content);\n\n content.appendChild(this.tool.html);\n wrapper.appendChild(content);\n\n return wrapper;\n\n }\n\n /**\n * Get block`s HTML\n *\n * @returns {HTMLDivElement}\n */\n get html() {\n\n return this._html;\n\n }\n\n}\n\n\n// WEBPACK FOOTER //\n// ./src/components/block.js"],"sourceRoot":""} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3e366622..672e07f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2986,6 +2986,14 @@ } } }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, "string-width": { "version": "1.0.2", "bundled": true, @@ -2996,14 +3004,6 @@ "strip-ansi": "3.0.1" } }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, "stringstream": { "version": "0.0.5", "bundled": true, @@ -7994,6 +7994,15 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -8021,15 +8030,6 @@ } } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", diff --git a/src/components/modules/sanitizer.js b/src/components/modules/sanitizer.js index 7f6f0bfa..1f9a9fca 100644 --- a/src/components/modules/sanitizer.js +++ b/src/components/modules/sanitizer.js @@ -2,9 +2,36 @@ * Codex Sanitizer * * @module Sanitizer module - * Clears HTML from dirty tags + * Clears HTML from taint tags * * @version 2.0.0 + * + * @usage + * Module can be used within two ways: + * 1) When you have an instance + * - this.moduleInstance['Sanitizer'].clean(yourDirtyString); + * 2) As static method + * - CodexEditor.Sanitizer.clean(yourDirtyString, yourCustomConfiguration); + * + * + * Look up the SanitizerConfig object as example to make your custom restrictions + */ + + +/** + * @typedef {Object} SanitizerConfig + * @property {Object} tags - define tags restrictions + * + * @example + * + * tags : { + * p: true, + * a: { + * href: true, + * rel: "nofollow", + * target: "_blank" + * } + * } */ export default class Sanitizer extends Module { @@ -14,55 +41,76 @@ export default class Sanitizer extends Module { * * @property {HTMLJanitor} this.janitor - Sanitizer library * - * @param config + * @param {SanitizerConfig} config */ constructor(config) { + super(config); // default config - this._config = {}; - this._janitor = null; + this.instantConfig = {}; + this.janitorInstance = null; /** Custom configuration */ - this.sanitizerConfig = config.settings.sanitizer; + this.sanitizerConfig = config.settings ? config.settings.sanitizer : {}; /** HTML Janitor library */ this.sanitizerInstance = require('html-janitor'); + } /** - * @param library + * If developer uses editor's API, then he can customize sanitize restrictions. + * Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere + * At least, if there is no config overrides, that API uses Default configuration * - * @description If developer uses editor's API, then he can customize sane restrictions. - * Or, sane config can be defined globally in editors initialization. That config will be used everywhere - * At least, if there is no config overrides, that API uses BASIC Default configation + * @uses https://www.npmjs.com/package/html-janitor + * + * @param {HTMLJanitor} library - sanitizer extension */ set sanitizerInstance(library) { - this._janitor = new library(this._config); + + this.janitorInstance = new library(this.instanceConfig); + } + /** + * Sets sanitizer configuration. Uses default config if user didn't pass the restriction + * @param {SanitizerConfig} config + */ set sanitizerConfig(config) { - this._config = { - tags: { - p: {}, - a: { - href: true, - target: '_blank', - rel: 'nofollow' + if (_.isEmpty(config)) { + + this.instanceConfig = { + tags: { + p: {}, + a: { + href: true, + target: '_blank', + rel: 'nofollow' + } } - } - }; + }; + + } else { + + this.instanceConfig = config; + + } } /** * Cleans string from unwanted tags - * @param dirtyString - * @return {*} + * @param {String} taintString - HTML string + * + * @return {String} clean HTML */ - clean(dirtyString) { - return this._janitor.clean(dirtyString); + clean(taintString) { + + return this.janitorInstance.clean(taintString); + } /** @@ -71,13 +119,17 @@ export default class Sanitizer extends Module { * * Method allows to use default config * - * @param {String} dirtyString - taint string - * @param {Object} customConfig - allowed tags + * @param {String} taintString - taint string + * @param {SanitizerConfig} customConfig - allowed tags + * + * @return {String} clean HTML */ - static clean(dirtyString, customConfig) { + static clean(taintString, customConfig) { + let newInstance = Sanitizer(customConfig); - return newInstance.clean(dirtyString); + return newInstance.clean(taintString); + } } diff --git a/src/components/utils.js b/src/components/utils.js index 10d14073..5400792d 100644 --- a/src/components/utils.js +++ b/src/components/utils.js @@ -97,4 +97,16 @@ export default class Util { } + /** + * Checks if object is empty + * + * @param {Object} object + * @return {boolean} + */ + static isEmpty(object) { + + return Object.keys(object).length === 0 && object.constructor === Object; + + } + }; \ No newline at end of file