diff --git a/build/codex-editor.js b/build/codex-editor.js index aa1679dad..5335d87d4 100644 --- a/build/codex-editor.js +++ b/build/codex-editor.js @@ -826,102 +826,6 @@ module.exports = exports['default']; /***/ }), -/***/ "./src/components/Selection.js": -/*!*************************************!*\ - !*** ./src/components/Selection.js ***! - \*************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -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"); } } - -/** - * Working with selection - */ -var Selection = function () { - /** - * @constructor - */ - function Selection() { - _classCallCheck(this, Selection); - - this.instance = null; - this.selection = null; - } - - /** - * Returns window Selection - * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection} - * @return {Selection} - */ - - - _createClass(Selection, null, [{ - key: "get", - value: function get() { - return window.getSelection(); - } - - /** - * Returns selected anchor - * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode} - * @return {Node|null} - */ - - }, { - key: "getAnchorNode", - value: function getAnchorNode() { - var selection = window.getSelection(); - - return selection ? selection.anchorNode : null; - } - - /** - * Returns selection offset according to the anchor node - * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset} - * @return {Number|null} - */ - - }, { - key: "getAnchorOffset", - value: function getAnchorOffset() { - var selection = window.getSelection(); - - return selection ? selection.anchorOffset : null; - } - - /** - * Is current selection range collapsed - * @return {boolean|null} - */ - - }, { - key: "isCollapsed", - get: function get() { - var selection = window.getSelection(); - - return selection ? selection.isCollapsed : null; - } - }]); - - return Selection; -}(); - -Selection.displayName = "Selection"; -exports.default = Selection; -module.exports = exports["default"]; - -/***/ }), - /***/ "./src/components/__module.ts": /*!************************************!*\ !*** ./src/components/__module.ts ***! @@ -1813,7 +1717,7 @@ var BlockManager = function (_Module) { return _this3.Editor.Keyboard.blockKeydownsListener(event); }); this.Editor.Listeners.on(block.pluginsContent, 'mouseup', function (event) { - _this3.Editor.InlineToolbar.move(event); + _this3.Editor.InlineToolbar.handleShowingEvent(event); }); } @@ -1983,13 +1887,17 @@ var BlockManager = function (_Module) { /** * Get Block instance by html element - * @param {HTMLElement} element + * @param {Node} element * @returns {Block} */ }, { key: 'getBlock', value: function getBlock(element) { + if (!$.isElement(element)) { + element = element.parentNode; + } + var nodes = this._blocks.nodes, firstLevelBlock = element.closest('.' + _block2.default.CSS.wrapper), index = nodes.indexOf(firstLevelBlock); @@ -2383,9 +2291,9 @@ Object.defineProperty(exports, "__esModule", { 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; }; }(); -var _Selection = __webpack_require__(/*! ../Selection */ "./src/components/Selection.js"); +var _selection = __webpack_require__(/*! ../selection */ "./src/components/selection.js"); -var _Selection2 = _interopRequireDefault(_Selection); +var _selection2 = _interopRequireDefault(_selection); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2407,8 +2315,6 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" /** * @typedef {Caret} Caret */ - - var Caret = function (_Module) { _inherits(Caret, _Module); @@ -2485,7 +2391,7 @@ var Caret = function (_Module) { var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var range = document.createRange(), - selection = _Selection2.default.get(); + selection = _selection2.default.get(); range.setStart(element, offset); range.setEnd(element, offset); @@ -2524,7 +2430,7 @@ var Caret = function (_Module) { }, { key: 'extractFragmentFromCaretPosition', value: function extractFragmentFromCaretPosition() { - var selection = _Selection2.default.get(); + var selection = _selection2.default.get(); if (selection.rangeCount) { var selectRange = selection.getRangeAt(0), @@ -2597,11 +2503,11 @@ var Caret = function (_Module) { /** * Don't handle ranges */ - if (!_Selection2.default.isCollapsed) { + if (!_selection2.default.isCollapsed) { return false; } - var selection = _Selection2.default.get(), + var selection = _selection2.default.get(), anchorNode = selection.anchorNode, firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent); @@ -2649,11 +2555,11 @@ var Caret = function (_Module) { /** * Don't handle ranges */ - if (!_Selection2.default.isCollapsed) { + if (!_selection2.default.isCollapsed) { return false; } - var selection = _Selection2.default.get(), + var selection = _selection2.default.get(), anchorNode = selection.anchorNode, lastNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent, true); @@ -2902,7 +2808,7 @@ var Keyboard = function (_Module) { * Don't handle Enter keydowns when Tool sets enableLineBreaks to true. * Uses for Tools like where line breaks should be handled by default behaviour. */ - if (toolsConfig && toolsConfig.enableLineBreaks) { + if (toolsConfig && toolsConfig[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS]) { return; } @@ -3202,20 +3108,24 @@ var Listeners = function (_Module) { }, { key: "findAll", value: function findAll(element, eventType, handler) { - var foundAllListeners = void 0, - foundByElements = [], - foundByEventType = [], - foundByHandler = []; - - if (element) foundByElements = this.findByElement(element); - - if (eventType) foundByEventType = this.findByType(eventType); - - if (handler) foundByHandler = this.findByHandler(handler); - - foundAllListeners = foundByElements.concat(foundByEventType, foundByHandler); + var found = void 0, + foundByElements = element ? this.findByElement(element) : []; + // foundByEventType = eventType ? this.findByType(eventType) : [], + // foundByHandler = handler ? this.findByHandler(handler) : []; + + if (element && eventType && handler) { + found = foundByElements.filter(function (event) { + return event.eventType === eventType && event.handler === handler; + }); + } else if (element && eventType) { + found = foundByElements.filter(function (event) { + return event.eventType === eventType; + }); + } else { + found = foundByElements; + } - return foundAllListeners; + return found; } /** @@ -4045,6 +3955,12 @@ Object.defineProperty(exports, "__esModule", { 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; }; }(); +var _selection = __webpack_require__(/*! ../selection */ "./src/components/selection.js"); + +var _selection2 = _interopRequireDefault(_selection); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + 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; } @@ -4074,8 +3990,13 @@ var InlineToolbar = function (_Module) { * CSS styles */ _this.CSS = { - inlineToolbar: 'ce-inline-toolbar' + inlineToolbar: 'ce-inline-toolbar', + inlineToolbarShowed: 'ce-inline-toolbar--showed' }; + /** + * Margin above/below the Toolbar + */ + _this.toolbarVerticalMargin = 20; return _this; } /** @@ -4092,10 +4013,96 @@ var InlineToolbar = function (_Module) { */ $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); } + /** + * Shows Inline Toolbar by keyup/mouseup + * @param {KeyboardEvent|MouseEvent} event + */ + + }, { + key: 'handleShowingEvent', + value: function handleShowingEvent(event) { + if (!this.allowedToShow(event)) { + this.close(); + return; + } + this.move(); + this.open(); + } + /** + * Move Toolbar to the selected text + */ + }, { key: 'move', value: function move() { - // moving + var selectionRect = _selection2.default.rect; + var wrapperOffset = this.Editor.UI.nodes.wrapper.getBoundingClientRect(); + var newCoords = { + x: selectionRect.x - wrapperOffset.left, + y: selectionRect.y + selectionRect.height + // + window.scrollY + - wrapperOffset.top + this.toolbarVerticalMargin + }; + /** + * If we know selections width, place InlineToolbar to center + */ + if (selectionRect.width) { + newCoords.x += Math.floor(selectionRect.width / 2); + } + this.nodes.wrapper.style.left = Math.floor(newCoords.x) + 'px'; + this.nodes.wrapper.style.top = Math.floor(newCoords.y) + 'px'; + } + /** + * Shows Inline Toolbar + */ + + }, { + key: 'open', + value: function open() { + this.nodes.wrapper.classList.add(this.CSS.inlineToolbarShowed); + } + /** + * Hides Inline Toolbar + */ + + }, { + key: 'close', + value: function close() { + this.nodes.wrapper.classList.remove(this.CSS.inlineToolbarShowed); + } + /** + * Need to show Inline Toolbar or not + * @param {KeyboardEvent|MouseEvent} event + */ + + }, { + key: 'allowedToShow', + value: function allowedToShow(event) { + /** + * Tags conflicts with window.selection function. + * Ex. IMG tag returns null (Firefox) or Redactors wrapper (Chrome) + */ + var tagsConflictsWithSelection = ['IMG', 'INPUT']; + if (event && tagsConflictsWithSelection.includes(event.target.tagName)) { + return false; + } + var currentSelection = _selection2.default.get(), + selectedText = _selection2.default.text; + // old browsers + if (!currentSelection || !currentSelection.anchorNode) { + return false; + } + // empty selection + if (currentSelection.isCollapsed || selectedText.length < 1) { + return false; + } + // is enabled by current Block's Tool + var currentBlock = this.Editor.BlockManager.getBlock(currentSelection.anchorNode); + if (!currentBlock) { + return false; + } + var toolConfig = this.config.toolsConfig[currentBlock.name]; + return toolConfig && toolConfig[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR]; } }]); @@ -4213,7 +4220,9 @@ var Toolbox = function (_Module) { value: function addTool(toolName, tool) { var _this2 = this; - if (tool.displayInToolbox && !tool.iconClassName) { + var api = this.Editor.Tools.apiSettings; + + if (tool[api.IS_DISPLAYED_IN_TOOLBOX] && !tool[api.TOOLBAR_ICON_CLASS]) { _.log('Toolbar icon class name is missed. Tool %o skipped', 'warn', toolName); return; } @@ -4231,11 +4240,11 @@ var Toolbox = function (_Module) { /** * Skip tools that pass 'displayInToolbox=false' */ - if (!tool.displayInToolbox) { + if (!tool[api.IS_DISPLAYED_IN_TOOLBOX]) { return; } - var button = $.make('li', [Toolbox.CSS.toolboxButton, tool.iconClassName], { + var button = $.make('li', [Toolbox.CSS.toolboxButton, tool[api.TOOLBAR_ICON_CLASS]], { title: toolName }); @@ -4284,7 +4293,7 @@ var Toolbox = function (_Module) { * - block is not irreplaceable * @type {Array} */ - if (!tool.irreplaceable && currentBlock.isEmpty) { + if (!tool[this.Editor.Tools.apiSettings.IS_IRREPLACEBLE_TOOL] && currentBlock.isEmpty) { this.Editor.BlockManager.replace(toolName); } else { this.Editor.BlockManager.insert(toolName); @@ -4699,6 +4708,8 @@ Object.defineProperty(exports, "__esModule", { 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 _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + 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; } @@ -4718,6 +4729,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" * @property {String} iconClassname - this a icon in toolbar * @property {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE * @property {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE + * @property {Boolean|String[]} inlineToolbar - Pass `true` to enable the Inline Toolbar with all Tools, all pass an array with specified Tools list | * @property render @todo add description * @property save @todo add description * @property settings @todo add description @@ -4772,22 +4784,34 @@ var Tools = function (_Module) { return this.toolsUnavailable; } + /** + * Constant for available Tools Settings + * @return {object} + */ + + }, { + key: 'apiSettings', + get: function get() { + return { + TOOLBAR_ICON_CLASS: 'iconClassName', + IS_DISPLAYED_IN_TOOLBOX: 'displayInToolbox', + IS_ENABLED_LINE_BREAKS: 'enableLineBreaks', + IS_IRREPLACEBLE_TOOL: 'irreplaceable', + IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar' + }; + } + /** * Static getter for default Tool config fields - * - * @usage Tools.defaultConfig.displayInToolbox * @return {ToolConfig} */ - }], [{ + }, { key: 'defaultConfig', get: function get() { - return { - iconClassName: '', - displayInToolbox: false, - enableLineBreaks: false, - irreplaceable: false - }; + var _ref; + + return _ref = {}, _defineProperty(_ref, this.apiSettings.TOOLBAR_ICON_CLASS, false), _defineProperty(_ref, this.apiSettings.IS_DISPLAYED_IN_TOOLBOX, false), _defineProperty(_ref, this.apiSettings.IS_ENABLED_LINE_BREAKS, false), _defineProperty(_ref, this.apiSettings.IS_IRREPLACEBLE_TOOL, false), _defineProperty(_ref, this.apiSettings.IS_ENABLED_INLINE_TOOLBAR, false), _ref; } /** @@ -4798,8 +4822,8 @@ var Tools = function (_Module) { }]); - function Tools(_ref) { - var config = _ref.config; + function Tools(_ref2) { + var config = _ref2.config; _classCallCheck(this, Tools); @@ -4936,11 +4960,7 @@ var Tools = function (_Module) { var plugin = this.toolClasses[tool], config = this.config.toolsConfig[tool]; - if (!config) { - config = this.defaultConfig; - } - - var instance = new plugin(data, config); + var instance = new plugin(data, config || {}); return instance; } @@ -5247,17 +5267,9 @@ var UI = function (_Module) { } /** - * @todo hide the Inline Toolbar + * Close Inline Toolbar when nothing selected */ - // var selectedText = editor.toolbar.inline.getSelectionText(), - // firstLevelBlock; - - /** If selection range took off, then we hide inline toolbar */ - // if (selectedText.length === 0) { - - // editor.toolbar.inline.close(); - - // } + this.Editor.InlineToolbar.handleShowingEvent(event); /** * @@ -5615,6 +5627,182 @@ if (!Element.prototype.closest) Element.prototype.closest = function (s) { /***/ }), +/***/ "./src/components/selection.js": +/*!*************************************!*\ + !*** ./src/components/selection.js ***! + \*************************************/ +/*! no static exports found */ +/***/ (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"); } } + +/** + * Working with selection + * @typedef {Selection} Selection + */ +var Selection = function () { + /** + * @constructor + */ + function Selection() { + _classCallCheck(this, Selection); + + this.instance = null; + this.selection = null; + } + + /** + * Returns window Selection + * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection} + * @return {Selection} + */ + + + _createClass(Selection, null, [{ + key: 'get', + value: function get() { + return window.getSelection(); + } + + /** + * Returns selected anchor + * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode} + * @return {Node|null} + */ + + }, { + key: 'anchorNode', + get: function get() { + var selection = window.getSelection(); + + return selection ? selection.anchorNode : null; + } + + /** + * Returns selection offset according to the anchor node + * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset} + * @return {Number|null} + */ + + }, { + key: 'anchorOffset', + get: function get() { + var selection = window.getSelection(); + + return selection ? selection.anchorOffset : null; + } + + /** + * Is current selection range collapsed + * @return {boolean|null} + */ + + }, { + key: 'isCollapsed', + get: function get() { + var selection = window.getSelection(); + + return selection ? selection.isCollapsed : null; + } + + /** + * Calculates position and size of selected text + * @return {{x, y, width, height, top?, left?, bottom?, right?}} + */ + + }, { + key: 'rect', + get: function get() { + var sel = document.selection, + range = void 0; + var rect = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + + if (sel && sel.type !== 'Control') { + range = sel.createRange(); + rect.x = range.boundingLeft; + rect.y = range.boundingTop; + rect.width = range.boundingWidth; + rect.height = range.boundingHeight; + + return rect; + } + + if (!window.getSelection) { + _.log('Method window.getSelection is not supported', 'warn'); + return rect; + } + + sel = window.getSelection(); + + if (!sel.rangeCount) { + _.log('Method Selection.rangeCount() is not supported', 'warn'); + return rect; + } + + range = sel.getRangeAt(0).cloneRange(); + + if (range.getBoundingClientRect) { + rect = range.getBoundingClientRect(); + } + // Fall back to inserting a temporary element + if (rect.x === 0 && rect.y === 0) { + var span = document.createElement('span'); + + if (span.getBoundingClientRect) { + // Ensure span has dimensions and position by + // adding a zero-width space character + span.appendChild(document.createTextNode('\u200B')); + range.insertNode(span); + rect = span.getBoundingClientRect(); + + var spanParent = span.parentNode; + + spanParent.removeChild(span); + + // Glue any broken text nodes back together + spanParent.normalize(); + } + } + + return rect; + } + + /** + * Returns selected text as String + * @returns {string} + */ + + }, { + key: 'text', + get: function get() { + return window.getSelection ? window.getSelection().toString() : ''; + } + }]); + + return Selection; +}(); + +Selection.displayName = 'Selection'; +exports.default = Selection; +module.exports = exports['default']; +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! utils */ "./src/components/utils.js"))) + +/***/ }), + /***/ "./src/components/utils.js": /*!*********************************!*\ !*** ./src/components/utils.js ***! @@ -5856,7 +6044,7 @@ exports = module.exports = __webpack_require__(/*! ../../node_modules/css-loader // module -exports.push([module.i, ":root {\n\n /**\n * Toolbar buttons\n */\n --bg-light: #eff2f5;\n\n /**\n * All gray texts: placeholders, settings\n */\n --grayText: #707684;\n\n /**\n * Block content width\n */\n --content-width: 650px;\n\n /**\n * Toolbar Plus Button and Toolbox buttons height and width\n */\n --toolbar-buttons-size: 34px\n\n}\n/**\n* Editor wrapper\n*/\n.codex-editor {\n position: relative;\n border: 1px solid #ccc;\n padding: 2px;\n box-sizing: border-box;\n}\n.codex-editor .hide {\n display: none;\n }\n.codex-editor__redactor {\n padding-bottom: 300px;\n }\n.ce-toolbar {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n /*opacity: 0;*/\n /*visibility: hidden;*/\n transition: opacity 100ms ease;\n will-change: opacity, transform;\n display: none;\n}\n.ce-toolbar--opened {\n display: block;\n /*opacity: 1;*/\n /*visibility: visible;*/\n }\n.ce-toolbar__content {\n max-width: 650px;\n max-width: var(--content-width);\n margin: 0 auto;\n position: relative;\n }\n.ce-toolbar__plus {\n position: absolute;\n left: calc(-var(--toolbar-buttons-size) - 10px);\n left: calc(-var(--toolbar-buttons-size) - 10px);\n display: inline-block;\n background-color: #eff2f5;\n background-color: var(--bg-light);\n width: 34px;\n width: var(--toolbar-buttons-size);\n height: 34px;\n height: var(--toolbar-buttons-size);\n line-height: 34px;\n text-align: center;\n border-radius: 50%\n }\n.ce-toolbar__plus::after {\n content: '+';\n font-size: 26px;\n display: block;\n margin-top: -2px;\n margin-right: -2px;\n }\n.ce-toolbar__plus--hidden {\n display: none;\n }\n/**\n * Block actions Zone\n * -------------------------\n */\n.ce-toolbar__actions {\n position: absolute;\n right: 0;\n top: 0;\n border: 1px dotted #ccc;\n padding: 2px;\n }\n.ce-toolbar__actions-buttons {\n border: 1px dotted #ccc;\n padding: 2px;\n text-align: right;\n margin-bottom: 2px;\n }\n.ce-toolbar__settings-btn {\n display: inline-block;\n width: 24px;\n height: 24px;\n border: 1px dotted #ccc\n }\n.ce-toolbar__settings-btn::before {\n content: 'STN';\n font-size: 10px;\n opacity: .4;\n }\n.ce-toolbox {\n position: absolute;\n visibility: hidden;\n transition: opacity 100ms ease;\n will-change: opacity;\n}\n.ce-toolbox--opened {\n opacity: 1;\n visibility: visible;\n }\n.ce-toolbox__button {\n display: inline-block;\n list-style: none;\n margin: 0;\n background: #eff2f5;\n background: var(--bg-light);\n width: 34px;\n width: var(--toolbar-buttons-size);\n height: 34px;\n height: var(--toolbar-buttons-size);\n border-radius: 30px;\n overflow: hidden;\n text-align: center;\n line-height: 34px;\n line-height: var(--toolbar-buttons-size)\n }\n.ce-toolbox__button::before {\n content: attr(title);\n font-size: 22px;\n font-weight: 500;\n letter-spacing: 1em;\n -webkit-font-feature-settings: \"smcp\", \"c2sc\";\n font-feature-settings: \"smcp\", \"c2sc\";\n font-variant-caps: all-small-caps;\n padding-left: 11.5px;\n margin-top: -1px;\n display: inline-block;\n }\n.ce-inline-toolbar {\n position: absolute;\n z-index: 2;\n background: #FFFFFF;\n box-shadow: 0 8px 23px -6px rgba(21,40,54,0.31), 22px -14px 34px -18px rgba(33,48,73,0.26);\n border-radius: 4px;\n position: relative;\n}\n.ce-inline-toolbar::before {\n content: '';\n width: 15px;\n height: 15px;\n position: absolute;\n top: -7px;\n left: 50%;\n margin-left: -7px;\n transform: rotate(-45deg);\n background: #fff;\n }\n.ce-inline-toolbar {\n\n width: 100px;\n height: 40px;\n}\n.ce-settings {\n border: 1px dotted #ccc;\n padding: 2px;\n display: none;\n}\n.ce-settings--opened {\n display: block;\n }\n.ce-settings__plugin-zone {\n border: 1px dotted #ccc;\n padding: 2px;\n margin-bottom: 2px\n }\n.ce-settings__plugin-zone::before {\n content: 'PLUGIN SETTINGS';\n opacity: .4;\n font-size: 12px;\n }\n.ce-settings__default-zone {\n border: 1px dotted #ccc;\n padding: 2px\n }\n.ce-settings__default-zone::before {\n content: 'DEFAULT SETTINGS';\n opacity: .4;\n font-size: 12px;\n }\n.ce-settings__button {\n padding: 10px 15px;\n color: #707684;\n color: var(--grayText)\n }\n.ce-settings__button:hover {\n background: #eff2f5;\n background: var(--bg-light);\n }\n.ce-block {\n border: 1px dotted #ccc;\n margin: 2px 0\n}\n.ce-block:first-of-type {\n margin-top: 0;\n }\n.ce-block--selected {\n background-color: #eff2f5;\n background-color: var(--bg-light);\n }\n.ce-block__content {\n max-width: 650px;\n max-width: var(--content-width);\n margin: 0 auto;\n }\n", ""]); +exports.push([module.i, ":root {\n\n /**\n * Toolbar buttons\n */\n --bg-light: #eff2f5;\n\n /**\n * All gray texts: placeholders, settings\n */\n --grayText: #707684;\n\n /**\n * Block content width\n */\n --content-width: 650px;\n\n /**\n * Toolbar Plus Button and Toolbox buttons height and width\n */\n --toolbar-buttons-size: 34px\n\n}\n/**\n* Editor wrapper\n*/\n.codex-editor {\n position: relative;\n border: 1px solid #ccc;\n padding: 2px;\n box-sizing: border-box;\n}\n.codex-editor .hide {\n display: none;\n }\n.codex-editor__redactor {\n padding-bottom: 300px;\n }\n.ce-toolbar {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n /*opacity: 0;*/\n /*visibility: hidden;*/\n transition: opacity 100ms ease;\n will-change: opacity, transform;\n display: none;\n}\n.ce-toolbar--opened {\n display: block;\n /*opacity: 1;*/\n /*visibility: visible;*/\n }\n.ce-toolbar__content {\n max-width: 650px;\n max-width: var(--content-width);\n margin: 0 auto;\n position: relative;\n }\n.ce-toolbar__plus {\n position: absolute;\n left: calc(-var(--toolbar-buttons-size) - 10px);\n left: calc(-var(--toolbar-buttons-size) - 10px);\n display: inline-block;\n background-color: #eff2f5;\n background-color: var(--bg-light);\n width: 34px;\n width: var(--toolbar-buttons-size);\n height: 34px;\n height: var(--toolbar-buttons-size);\n line-height: 34px;\n text-align: center;\n border-radius: 50%\n }\n.ce-toolbar__plus::after {\n content: '+';\n font-size: 26px;\n display: block;\n margin-top: -2px;\n margin-right: -2px;\n }\n.ce-toolbar__plus--hidden {\n display: none;\n }\n/**\n * Block actions Zone\n * -------------------------\n */\n.ce-toolbar__actions {\n position: absolute;\n right: 0;\n top: 0;\n border: 1px dotted #ccc;\n padding: 2px;\n }\n.ce-toolbar__actions-buttons {\n border: 1px dotted #ccc;\n padding: 2px;\n text-align: right;\n margin-bottom: 2px;\n }\n.ce-toolbar__settings-btn {\n display: inline-block;\n width: 24px;\n height: 24px;\n border: 1px dotted #ccc\n }\n.ce-toolbar__settings-btn::before {\n content: 'STN';\n font-size: 10px;\n opacity: .4;\n }\n.ce-toolbox {\n position: absolute;\n visibility: hidden;\n transition: opacity 100ms ease;\n will-change: opacity;\n}\n.ce-toolbox--opened {\n opacity: 1;\n visibility: visible;\n }\n.ce-toolbox__button {\n display: inline-block;\n list-style: none;\n margin: 0;\n background: #eff2f5;\n background: var(--bg-light);\n width: 34px;\n width: var(--toolbar-buttons-size);\n height: 34px;\n height: var(--toolbar-buttons-size);\n border-radius: 30px;\n overflow: hidden;\n text-align: center;\n line-height: 34px;\n line-height: var(--toolbar-buttons-size)\n }\n.ce-toolbox__button::before {\n content: attr(title);\n font-size: 22px;\n font-weight: 500;\n letter-spacing: 1em;\n -webkit-font-feature-settings: \"smcp\", \"c2sc\";\n font-feature-settings: \"smcp\", \"c2sc\";\n font-variant-caps: all-small-caps;\n padding-left: 11.5px;\n margin-top: -1px;\n display: inline-block;\n }\n.ce-inline-toolbar {\n position: absolute;\n background: #FFFFFF;\n box-shadow: 0 8px 23px -6px rgba(21,40,54,0.31), 22px -14px 34px -18px rgba(33,48,73,0.26);\n border-radius: 4px;\n z-index: 2\n}\n.ce-inline-toolbar::before {\n content: '';\n width: 15px;\n height: 15px;\n position: absolute;\n top: -7px;\n left: 50%;\n margin-left: -7px;\n transform: rotate(-45deg);\n background: #fff;\n }\n.ce-inline-toolbar {\n\n width: 100px;\n height: 40px;\n transform: translateX(-50%);\n display: none;\n}\n.ce-inline-toolbar--showed {\n display: block;\n }\n.ce-settings {\n border: 1px dotted #ccc;\n padding: 2px;\n display: none;\n}\n.ce-settings--opened {\n display: block;\n }\n.ce-settings__plugin-zone {\n border: 1px dotted #ccc;\n padding: 2px;\n margin-bottom: 2px\n }\n.ce-settings__plugin-zone::before {\n content: 'PLUGIN SETTINGS';\n opacity: .4;\n font-size: 12px;\n }\n.ce-settings__default-zone {\n border: 1px dotted #ccc;\n padding: 2px\n }\n.ce-settings__default-zone::before {\n content: 'DEFAULT SETTINGS';\n opacity: .4;\n font-size: 12px;\n }\n.ce-settings__button {\n padding: 10px 15px;\n color: #707684;\n color: var(--grayText)\n }\n.ce-settings__button:hover {\n background: #eff2f5;\n background: var(--bg-light);\n }\n.ce-block {\n border: 1px dotted #ccc;\n margin: 2px 0\n}\n.ce-block:first-of-type {\n margin-top: 0;\n }\n.ce-block--selected {\n background-color: #eff2f5;\n background-color: var(--bg-light);\n }\n.ce-block__content {\n max-width: 650px;\n max-width: var(--content-width);\n margin: 0 auto;\n }\n", ""]); // exports diff --git a/build/codex-editor.js.map b/build/codex-editor.js.map index 614e9f276..8982fbe68 100644 --- a/build/codex-editor.js.map +++ b/build/codex-editor.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://CodexEditor/webpack/bootstrap","webpack://CodexEditor/./node_modules/css-loader/lib/css-base.js","webpack://CodexEditor/./node_modules/html-janitor/src/html-janitor.js","webpack://CodexEditor/./src/codex.js","webpack://CodexEditor/./src/components/Selection.js","webpack://CodexEditor/./src/components/__module.ts","webpack://CodexEditor/./src/components/block.js","webpack://CodexEditor/./src/components/dom.js","webpack://CodexEditor/./src/components/modules sync nonrecursive [^_](blockManager.js|caret.js|events.js|keyboard.js|listeners.js|renderer.js|sanitizer.js|saver.js|toolbar-blockSettings.js|toolbar-inline.ts|toolbar-toolbox.js|toolbar.js|tools.js|ui.js)$","webpack://CodexEditor/./src/components/modules/blockManager.js","webpack://CodexEditor/./src/components/modules/caret.js","webpack://CodexEditor/./src/components/modules/events.js","webpack://CodexEditor/./src/components/modules/keyboard.js","webpack://CodexEditor/./src/components/modules/listeners.js","webpack://CodexEditor/./src/components/modules/renderer.js","webpack://CodexEditor/./src/components/modules/sanitizer.js","webpack://CodexEditor/./src/components/modules/saver.js","webpack://CodexEditor/./src/components/modules/toolbar-blockSettings.js","webpack://CodexEditor/./src/components/modules/toolbar-inline.ts","webpack://CodexEditor/./src/components/modules/toolbar-toolbox.js","webpack://CodexEditor/./src/components/modules/toolbar.js","webpack://CodexEditor/./src/components/modules/tools.js","webpack://CodexEditor/./src/components/modules/ui.js","webpack://CodexEditor/./src/components/polyfills.js","webpack://CodexEditor/./src/components/utils.js","webpack://CodexEditor/./src/styles/main.css"],"names":["modules","editorModules","map","module","CodexEditor","config","moduleInstances","Promise","resolve","then","configuration","init","start","console","log","catch","error","constructModules","configureModules","forEach","Module","displayName","e","name","state","getModulesDiff","diff","moduleName","prepareDecorator","prepare","Tools","UI","BlockManager","Renderer","render","data","items","initialBlock","type","holderId","placeholder","sanitizer","p","b","a","hideToolbar","tools","toolsConfig","_","isEmpty","length","Selection","instance","selection","window","getSelection","anchorNode","anchorOffset","isCollapsed","Editor","new","target","TypeError","Block","toolName","toolInstance","tool","_html","compose","wrapper","$","make","CSS","contentNode","content","pluginsContent","appendChild","methodName","params","Function","call","merge","extractedBlock","save","measuringStart","performance","now","measuringEnd","finishedExtraction","time","isValid","validate","contentless","emptyText","emptyMedia","hasMedia","mediaTags","querySelector","join","classList","add","selected","remove","Dom","tag","tagName","includes","classNames","attributes","el","document","createElement","Array","isArray","attrName","createTextNode","parent","elements","selector","querySelectorAll","node","atLast","child","sibling","nodeType","Node","ELEMENT_NODE","nodeChild","isSingleTag","parentNode","getDeepestNode","nativeInputs","nodeText","isElement","isNativeInput","value","textContent","replace","trim","childNodes","treeWalker","leafs","isNodeEmpty","push","firstChild","shift","isLeaf","nextSibling","every","leaf","_blocks","currentBlockIndex","blocks","Blocks","nodes","redactor","Proxy","set","get","construct","block","bindEvents","Listeners","on","event","Keyboard","blockKeydownsListener","InlineToolbar","move","caretAtEnd","Caret","isAtEnd","nextBlock","setToBlock","caretAtStart","isAtStart","previousBlock","composeBlock","targetBlock","blockToMerge","blockToMergeIndex","indexOf","blockToMergeInfo","mergeWith","removeBlock","index","extractedFragment","extractFragmentFromCaretPosition","append","text","innerHTML","insert","element","firstLevelBlock","closest","childNode","parentFirstLevelBlock","currentNode","Error","isLastBlock","isFirstBlock","array","currentBlock","workingArea","html","deleteCount","splice","insertAdjacentElement","newBlock","children","isNaN","Number","offset","atEnd","focus","nodeToSet","delay","range","createRange","setStart","setEnd","removeAllRanges","addRange","lastBlock","rangeCount","selectRange","getRangeAt","blockElem","deleteContents","cloneRange","selectNodeContents","endContainer","endOffset","extractContents","from","direction","current","siblings","contentEditable","firstNode","firstLetterPosition","search","leftSiblings","getHigherLevelSiblings","nothingAtLeft","lastNode","nothingAtRight","Events","subscribers","eventName","callback","reduce","previousData","currentHandler","newData","keyCode","keyCodes","BACKSPACE","backspacePressed","ENTER","enterPressed","DOWN","RIGHT","arrowRightAndDownPressed","UP","LEFT","arrowLeftAndUpPressed","enableLineBreaks","shiftKey","split","preventDefault","BM","canMergeBlocks","getBlockByIndex","mergeable","navigatePrevious","setCaretToTheEnd","mergeBlocks","setTimeout","Toolbar","close","navigateNext","allListeners","eventType","handler","useCapture","assignedEventData","alreadyExist","findOne","addEventListener","existingListeners","findAll","i","removeEventListener","listenersOnElement","listener","listenersWithType","listenersWithHandler","foundListeners","foundAllListeners","foundByElements","foundByEventType","foundByHandler","findByElement","findByType","findByHandler","concat","chainData","function","insertBlock","sequence","item","Sanitizer","defaultConfig","_sanitizerInstance","sanitizerConfig","settings","sanitizerInstance","require","taintString","customConfig","clean","library","tags","href","rel","newInstance","Saver","output","blocksData","all","allExtractedData","makeOutput","outputData","totalTime","groupCollapsed","extraction","groupEnd","Date","version","VERSION","BlockSettings","toolSettings","defaultSettings","buttonRemove","addDefaultSettings","button","removeBlockButtonClicked","wrapperOpened","addToolSettings","contains","inlineToolbar","Toolbox","toolbox","buttons","opened","addTools","toolsAvailable","addTool","displayInToolbox","iconClassName","toolboxButton","title","dataset","buttonClicked","toolButton","toolClasses","irreplaceable","toolboxOpened","open","actions","plusButton","blockActionsButtons","settingsToggler","toolbar","plusButtonClicked","defaultToolbarHeight","defaultOffset","newYCoordinate","offsetTop","style","transform","Math","floor","toolbarOpened","toggle","settingsTogglerClicked","hide","plusButtonHidden","show","toolsUnavailable","hasOwnProperty","reject","sequenceData","getListOfPrepareFunctions","success","fallback","toolPreparationList","toolClass","plugin","available","holder","loadStyles","getElementById","editorWrapper","editorZone","styles","toString","head","redactorClicked","clickedNode","setCurrentBlockByChildNode","setToTheLastBlock","isInitialBlock","isInitial","isEmptyBlock","Element","prototype","matches","msMatchesSelector","webkitMatchesSelector","s","documentElement","parentElement","Util","msg","args","chains","previousValue","currentValue","iteration","waitNextBlock","successCallback","fallbackCallback","collection","slice","object","Object","keys","constructor","method","timeout","context","arguments","apply","TAB","SHIFT","CTRL","ALT","ESC","SPACE","DELETE","META"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;AClFA;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;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AACA,GAAG,QAIH;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;;A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AOgC,YAAZ,EAA0B;AACxB,aAAK,KAAKhC,MAAL,CAAYgC,YAAjB,IAAiC,KAAKhC,MAAL,CAAYyC,KAA7C;AAAoD;AAApD;AACD,OAFD,MAEO;AACL,aAAKzC,MAAL,CAAYgC,YAAZ,GAA2BhC,OAAOgC,YAAlC;AACD;AACF;;AAED;;;;;wBAIoB;AAClB,aAAO,KAAKhC,MAAZ;AACD;;;;;;;kBArGkBD,W;AAgMpB;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;ACrYA;;;IAGqB+C,S;AACnB;;;AAGA,uBAAc;AAAA;;AACZ,SAAKC,QAAL,GAAgB,IAAhB;AACA,SAAKC,SAAL,GAAiB,IAAjB;AACD;;AAED;;;;;;;;;0BAKa;AACX,aAAOC,OAAOC,YAAP,EAAP;AACD;;AAED;;;;;;;;oCAKuB;AACrB,UAAIF,YAAYC,OAAOC,YAAP,EAAhB;;AAEA,aAAOF,YAAYA,UAAUG,UAAtB,GAAmC,IAA1C;AACD;;AAED;;;;;;;;sCAKyB;AACvB,UAAIH,YAAYC,OAAOC,YAAP,EAAhB;;AAEA,aAAOF,YAAYA,UAAUI,YAAtB,GAAqC,IAA5C;AACD;;AAED;;;;;;;wBAIyB;AACvB,UAAIJ,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B,uBAAvB;;AAEAJ,uBAAiBxT,OAAjB,CAAyB,UAAC6T,UAAD,EAAgB;AACvC;AACAnU,gBAAQC,GAAR,UAAgBkU,WAAW9Q,IAA3B,uBAAgD8Q,UAAhD;AACAF,qBAAaE,WAAWvP,IAAxB;AACArD,cAAM2G,IAAN,CAAWiM,WAAW7S,IAAtB;AACD,OALD;;AAOAtB,cAAQC,GAAR,CAAY,OAAZ,EAAqBgU,SAArB;AACAjU,cAAQoU,QAAR;;AAEA,aAAO;AACLxP,cAAU,CAAC,IAAIyP,IAAJ,EADN;AAEL9S,eAAUA,KAFL;AAGL+S,iBAAU,OAAAC;AAHL,OAAP;AAKD;;;;EAzDgChU,M;;AA4DnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;kBAzNqBmT,K;;;;;;;;;;;;;;;;;;;;;;;;;;;;A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,cADX;AAELC,oBAAgB;AAFX,OAAP;AAID;;;;EAlE6BjY,M;;AAoRhC;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;;;;kBAzeqBW,E;;;;;;;;;;;;;;;;ACrDrB;;;;;AAKA,IAAI,CAACiY,QAAQC,SAAR,CAAkBC,OAAvB,EA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","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, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\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\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/codex.js\");\n","/*\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","(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 * 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 : 'text',\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 * @property {Object} tools - Map for used Tools in format { name : Class, ... }\n * @property {String} initialBlock - This Tool will be added by default\n * @property {String} placeholder - First Block placeholder\n * @property {Object} sanitizer - @todo fill desc\n * @property {Boolean} hideToolbar - @todo fill desc\n * @property {Object} toolsConfig - tools configuration {@link tools#ToolConfig}\n */\n\n/**\n * Dynamically imported utils\n *\n * @typedef {Dom} $ - {@link components/dom.js}\n * @typedef {Util} _ - {@link components/utils.js}\n */\n\n'use strict';\n\n/**\n * Apply polyfills\n */\nimport 'components/polyfills';\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 */\nexport default class CodexEditor {\n /** Editor version */\n static get version() {\n return VERSION;\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n /**\n * Configuration object\n * @type {EditorConfig}\n */\n this.config = {};\n\n /**\n * @typedef {Object} EditorComponents\n * @property {BlockManager} BlockManager\n * @property {Tools} Tools\n * @property {Events} Events\n * @property {UI} UI\n * @property {Toolbar} Toolbar\n * @property {Toolbox} Toolbox\n * @property {BlockSettings} BlockSettings\n * @property {Renderer} Renderer\n * @property {InlineToolbar} InlineToolbar\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n this.configuration = config;\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n console.log('CodeX Editor is ready!');\n })\n .catch(error => {\n console.log('CodeX Editor does not ready because of %o', error);\n });\n }\n\n /**\n * Setting for configuration\n * @param {EditorConfig} config\n */\n set configuration(config) {\n /**\n * Initlai block type\n * Uses in case when there is no items passed\n * @type {{type: (*), data: {text: null}}}\n */\n let initialBlock = {\n type : config.initialBlock,\n data : {}\n };\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 * Initialize items to pass data to the Renderer\n */\n if (_.isEmpty(this.config.data)) {\n this.config.data = {};\n this.config.data.items = [ initialBlock ];\n } else {\n if (!this.config.data.items || this.config.data.items.length === 0) {\n this.config.data.items = [ initialBlock ];\n }\n }\n\n /**\n * If initial Block's Tool was not passed, use the first Tool in config.tools\n */\n if (!config.initialBlock) {\n for (this.config.initialBlock in this.config.tools) break;\n } else {\n this.config.initialBlock = config.initialBlock;\n }\n }\n\n /**\n * Returns private property\n * @returns {EditorConfig}\n */\n get configuration() {\n return this.config;\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\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 * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n modules.forEach( Module => {\n try {\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 this.moduleInstances[Module.displayName] = new Module({\n config : this.configuration\n });\n } catch ( e ) {\n console.log('Module %o skipped because %o', Module, e);\n }\n });\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n for(let name in this.moduleInstances) {\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n }\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n let diff = {};\n\n for(let moduleName in this.moduleInstances) {\n /**\n * Skip module with passed name\n */\n if (moduleName === name) {\n continue;\n }\n diff[moduleName] = this.moduleInstances[moduleName];\n }\n\n return diff;\n }\n\n /**\n * Start Editor!\n *\n * Get list of modules that needs to be prepared and return a sequence (Promise)\n * @return {Promise}\n */\n start() {\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances.Tools))\n .then(prepareDecorator(this.moduleInstances.UI))\n .then(prepareDecorator(this.moduleInstances.BlockManager))\n .then(() => {\n return this.moduleInstances.Renderer.render(this.config.data.items);\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 : ['text', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],\n// holderId : 'codex-editor',\n//\n// // Type of block showing on empty editor\n// initialBlockPlugin: 'text'\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 * Working with selection\n */\nexport default class Selection {\n /**\n * @constructor\n */\n constructor() {\n this.instance = null;\n this.selection = null;\n }\n\n /**\n * Returns window Selection\n * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection}\n * @return {Selection}\n */\n static get() {\n return window.getSelection();\n }\n\n /**\n * Returns selected anchor\n * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode}\n * @return {Node|null}\n */\n static getAnchorNode() {\n let selection = window.getSelection();\n\n return selection ? selection.anchorNode : null;\n }\n\n /**\n * Returns selection offset according to the anchor node\n * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset}\n * @return {Number|null}\n */\n static getAnchorOffset() {\n let selection = window.getSelection();\n\n return selection ? selection.anchorOffset : null;\n }\n\n /**\n * Is current selection range collapsed\n * @return {boolean|null}\n */\n static get isCollapsed() {\n let selection = window.getSelection();\n\n return selection ? selection.isCollapsed : null;\n }\n}","/**\n * @abstract\n * @class Module\n * @classdesc All modules inherits 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 * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({ config }) {\n /**\n * Editor modules list\n * @type {EditorComponents}\n */\n this.Editor = null;\n /**\n * Editor configuration object\n * @type {EditorConfig}\n */\n this.config = {};\n if (new.target === Module) {\n throw new TypeError('Constructors for abstract class Module are not allowed.');\n }\n this.config = config;\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 this.Editor = Editor;\n }\n}\n","/**\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/**\n * @classdesc Abstract Block class that contains Block information, Tool name and Tool class instance\n *\n * @property tool - Tool instance\n * @property html - Returns HTML content of plugin\n * @property wrapper - Div element that wraps block content with Tool's content. Has `ce-block` CSS class\n * @property contentNode - Div element that wraps Tool's content. Has `ce-block__content` CSS class\n * @property pluginsContent - HTML content that returns by Tool's render function\n */\nexport default class Block {\n /**\n * @constructor\n * @param {String} toolName - Tool name that passed on initialization\n * @param {Object} toolInstance — passed Tool`s instance that rendered the Block\n */\n constructor(toolName, toolInstance) {\n this.name = toolName;\n this.tool = toolInstance;\n this._html = this.compose();\n }\n\n /**\n * CSS classes for the Block\n * @return {{wrapper: string, content: string}}\n */\n static get CSS() {\n return {\n wrapper: 'ce-block',\n content: 'ce-block__content',\n selected: 'ce-block--selected'\n };\n }\n\n /**\n * Make default Block wrappers and put Tool`s content there\n * @returns {HTMLDivElement}\n */\n compose() {\n this.wrapper = $.make('div', Block.CSS.wrapper);\n this.contentNode = $.make('div', Block.CSS.content);\n this.pluginsContent = this.tool.render();\n\n this.contentNode.appendChild(this.pluginsContent);\n this.wrapper.appendChild(this.contentNode);\n\n return this.wrapper;\n }\n\n /**\n * Calls Tool's method\n *\n * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function\n *\n * @param {String} methodName\n * @param {Object} params\n */\n call(methodName, params) {\n /**\n * call Tool's method with the instance context\n */\n if (this.tool[methodName] && this.tool[methodName] instanceof Function) {\n this.tool[methodName].call(this.tool, params);\n }\n }\n\n /**\n * Get Block`s HTML\n * @returns {HTMLElement}\n */\n get html() {\n return this._html;\n }\n\n /**\n * Get Block's JSON data\n * @return {Object}\n */\n get data() {\n return this.save();\n }\n\n /**\n * is block mergeable\n * We plugin have merge function then we call it mergable\n * @return {boolean}\n */\n get mergeable() {\n return typeof this.tool.merge === 'function';\n }\n\n /**\n * Call plugins merge method\n * @param {Object} data\n */\n mergeWith(data) {\n return Promise.resolve()\n .then(() => {\n this.tool.merge(data);\n });\n }\n /**\n * Extracts data from Block\n * Groups Tool's save processing time\n * @return {Object}\n */\n save() {\n let extractedBlock = this.tool.save(this.pluginsContent);\n\n /** Measuring execution time*/\n let measuringStart = window.performance.now(),\n measuringEnd;\n\n return Promise.resolve(extractedBlock)\n .then((finishedExtraction) => {\n /** measure promise execution */\n measuringEnd = window.performance.now();\n\n return {\n tool: this.name,\n data: finishedExtraction,\n time : measuringEnd - measuringStart\n };\n })\n .catch(function (error) {\n _.log(`Saving proccess for ${this.tool.name} tool failed due to the ${error}`, 'log', 'red');\n });\n }\n\n /**\n * Uses Tool's validation method to check the correctness of output data\n * Tool's validation method is optional\n *\n * @description Method also can return data if it passed the validation\n *\n * @param {Object} data\n * @returns {Boolean|Object} valid\n */\n validateData(data) {\n let isValid = true;\n\n if (this.tool.validate instanceof Function) {\n isValid = this.tool.validate(data);\n }\n\n if (!isValid) {\n return false;\n }\n\n return data;\n }\n\n /**\n * Check block for emptiness\n * @return {Boolean}\n */\n get isEmpty() {\n /**\n * Allow Tool to represent decorative contentless blocks: for example \"* * *\"-tool\n * That Tools are not empty\n */\n if (this.tool.contentless) {\n return false;\n }\n\n let emptyText = $.isEmpty(this.pluginsContent),\n emptyMedia = !this.hasMedia;\n\n return emptyText && emptyMedia;\n }\n\n /**\n * Check if block has a media content such as images, iframes and other\n * @return {Boolean}\n */\n get hasMedia() {\n /**\n * This tags represents media-content\n * @type {string[]}\n */\n const mediaTags = [\n 'img',\n 'iframe',\n 'video',\n 'audio',\n 'source',\n 'input',\n 'textarea',\n 'twitterwidget'\n ];\n\n return !!this._html.querySelector(mediaTags.join(','));\n }\n\n /**\n * Set selected state\n * @param {Boolean} state - 'true' to select, 'false' to remove selection\n */\n set selected(state) {\n /**\n * We don't need to mark Block as Selected when it is not empty\n */\n if (state === true && !this.isEmpty) {\n this._html.classList.add(Block.CSS.selected);\n } else {\n this._html.classList.remove(Block.CSS.selected);\n }\n }\n}","/**\n * DOM manipulations helper\n */\nexport default class Dom {\n /**\n * Check if passed tag has no closed tag\n * @param {Element} tag\n * @return {Boolean}\n */\n static isSingleTag(tag) {\n return tag.tagName && ['AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR'].includes(tag.tagName);\n };\n\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 let el = document.createElement(tagName);\n\n if ( Array.isArray(classNames) ) {\n el.classList.add(...classNames);\n } else if( classNames ) {\n el.classList.add(classNames);\n }\n\n for (let attrName in attributes) {\n el[attrName] = attributes[attrName];\n }\n\n return el;\n }\n\n /**\n * Creates Text Node with the passed content\n * @param {String} content - text content\n * @return {Text}\n */\n static text(content) {\n return document.createTextNode(content);\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 if ( Array.isArray(elements) ) {\n elements.forEach( el => parent.appendChild(el) );\n } else {\n parent.appendChild(elements);\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 return el.querySelector(selector);\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 return el.querySelectorAll(selector);\n }\n\n /**\n * Search for deepest node which is Leaf.\n * Leaf is the vertex that doesn't have any child nodes\n *\n * @description Method recursively goes throw the all Node until it finds the Leaf\n *\n * @param {Node} node - root Node. From this vertex we start Deep-first search {@link https://en.wikipedia.org/wiki/Depth-first_search}\n * @param {Boolean} atLast - find last text node\n * @return {Node} - it can be text Node or Element Node, so that caret will able to work with it\n */\n static getDeepestNode(node, atLast = false) {\n /**\n * Current function have two directions:\n * - starts from first child and every time gets first or nextSibling in special cases\n * - starts from last child and gets last or previousSibling\n * @type {string}\n */\n let child = atLast ? 'lastChild' : 'firstChild',\n sibling = atLast ? 'previousSibling' : 'nextSibling';\n\n if (node && node.nodeType === Node.ELEMENT_NODE && node[child]) {\n let nodeChild = node[child];\n\n /**\n * special case when child is single tag that can't contain any content\n */\n if (Dom.isSingleTag(nodeChild)) {\n /**\n * 1) We need to check the next sibling. If it is Node Element then continue searching for deepest\n * from sibling\n *\n * 2) If single tag's next sibling is null, then go back to parent and check his sibling\n * In case of Node Element continue searching\n *\n * 3) If none of conditions above happened return parent Node Element\n */\n if (nodeChild[sibling]) {\n nodeChild = nodeChild[sibling];\n } else if (nodeChild.parentNode[sibling]) {\n nodeChild = nodeChild.parentNode[sibling];\n } else {\n return nodeChild.parentNode;\n }\n }\n\n return this.getDeepestNode(nodeChild, atLast);\n }\n\n return node;\n }\n\n /**\n * Check if object is DOM node\n *\n * @param {Object} node\n * @returns {boolean}\n */\n static isElement(node) {\n return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.ELEMENT_NODE;\n }\n\n /**\n * Checks target if it is native input\n * @param {Element|String} target - HTML element or string\n * @return {Boolean}\n */\n static isNativeInput(target) {\n let nativeInputs = [\n 'INPUT',\n 'TEXTAREA'\n ];\n\n return target ? nativeInputs.includes(target.tagName) : false;\n }\n\n /**\n * Checks node if it is empty\n *\n * @description Method checks simple Node without any childs for emptiness\n * If you have Node with 2 or more children id depth, you better use {@link Dom#isEmpty} method\n *\n * @param {Node} node\n * @return {Boolean} true if it is empty\n */\n static isNodeEmpty(node) {\n let nodeText;\n\n if ( this.isElement(node) && this.isNativeInput(node) ) {\n nodeText = node.value;\n } else {\n nodeText = node.textContent.replace('\\u200B', '');\n }\n\n return nodeText.trim().length === 0;\n }\n\n /**\n * checks node if it is doesn't have any child nodes\n * @param {Node} node\n * @return {boolean}\n */\n static isLeaf(node) {\n if (!node) {\n return false;\n }\n\n return node.childNodes.length === 0;\n }\n\n /**\n * breadth-first search (BFS)\n * {@link https://en.wikipedia.org/wiki/Breadth-first_search}\n *\n * @description Pushes to stack all DOM leafs and checks for emptiness\n *\n * @param {Node} node\n * @return {boolean}\n */\n static isEmpty(node) {\n let treeWalker = [],\n leafs = [];\n\n if (!node) {\n return true;\n }\n\n if (!node.childNodes.length) {\n return this.isNodeEmpty(node);\n }\n\n treeWalker.push(node.firstChild);\n\n while ( treeWalker.length > 0 ) {\n node = treeWalker.shift();\n\n if (!node) continue;\n\n if ( this.isLeaf(node) ) {\n leafs.push(node);\n } else {\n treeWalker.push(node.firstChild);\n }\n\n while ( node && node.nextSibling ) {\n node = node.nextSibling;\n\n if (!node) continue;\n\n treeWalker.push(node);\n }\n\n /**\n * If one of childs is not empty, checked Node is not empty too\n */\n if (node && !this.isNodeEmpty(node)) {\n return false;\n }\n }\n\n return leafs.every( leaf => this.isNodeEmpty(leaf) );\n }\n};","var map = {\n\t\"./blockManager.js\": \"./src/components/modules/blockManager.js\",\n\t\"./caret.js\": \"./src/components/modules/caret.js\",\n\t\"./events.js\": \"./src/components/modules/events.js\",\n\t\"./keyboard.js\": \"./src/components/modules/keyboard.js\",\n\t\"./listeners.js\": \"./src/components/modules/listeners.js\",\n\t\"./renderer.js\": \"./src/components/modules/renderer.js\",\n\t\"./sanitizer.js\": \"./src/components/modules/sanitizer.js\",\n\t\"./saver.js\": \"./src/components/modules/saver.js\",\n\t\"./toolbar-blockSettings.js\": \"./src/components/modules/toolbar-blockSettings.js\",\n\t\"./toolbar-inline.ts\": \"./src/components/modules/toolbar-inline.ts\",\n\t\"./toolbar-toolbox.js\": \"./src/components/modules/toolbar-toolbox.js\",\n\t\"./toolbar.js\": \"./src/components/modules/toolbar.js\",\n\t\"./tools.js\": \"./src/components/modules/tools.js\",\n\t\"./ui.js\": \"./src/components/modules/ui.js\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) { // check for number or string\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn id;\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"./src/components/modules sync [^_](blockManager.js|caret.js|events.js|keyboard.js|listeners.js|renderer.js|sanitizer.js|saver.js|toolbar-blockSettings.js|toolbar-inline.ts|toolbar-toolbox.js|toolbar.js|tools.js|ui.js)$\";","/**\n * @class BlockManager\n * @classdesc Manage editor`s blocks storage and appearance\n *\n * @module BlockManager\n *\n * @version 2.0.0\n */\n\nimport Block from '../block';\n\n/**\n * @typedef {BlockManager} BlockManager\n * @property {Number} currentBlockIndex - Index of current working block\n * @property {Proxy} _blocks - Proxy for Blocks instance {@link Blocks}\n */\nexport default class BlockManager extends Module {\n /**\n * @constructor\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\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 * Should be called after Editor.UI preparation\n * Define this._blocks property\n *\n * @returns {Promise}\n */\n prepare() {\n return new Promise(resolve => {\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 * Creates Block instance by tool name\n *\n * @param {String} toolName - tools passed in editor config {@link EditorConfig#tools}\n * @param {Object} data - constructor params\n *\n * @return {Block}\n */\n composeBlock(toolName, data) {\n let toolInstance = this.Editor.Tools.construct(toolName, data),\n block = new Block(toolName, toolInstance);\n\n this.bindEvents(block);\n\n /**\n * Apply callback before inserting html\n */\n block.call('appendCallback', {});\n\n return block;\n }\n\n /**\n * Bind Events\n * @param {Object} block\n */\n bindEvents(block) {\n this.Editor.Listeners.on(block.pluginsContent, 'keydown', (event) => this.Editor.Keyboard.blockKeydownsListener(event));\n this.Editor.Listeners.on(block.pluginsContent, 'mouseup', (event) => {\n this.Editor.InlineToolbar.move(event);\n });\n }\n\n /**\n * Set's caret to the next Block\n * Before moving caret, we should check if caret position is at the end of Plugins node\n * Using {@link Dom#getDeepestNode} to get a last node and match with current selection\n */\n navigateNext() {\n let caretAtEnd = this.Editor.Caret.isAtEnd;\n\n if (!caretAtEnd) {\n return;\n }\n\n let nextBlock = this.nextBlock;\n\n if (!nextBlock) {\n return;\n }\n\n this.Editor.Caret.setToBlock( nextBlock );\n }\n\n /**\n * Set's caret to the previous Block\n * Before moving caret, we should check if caret position is start of the Plugins node\n * Using {@link Dom#getDeepestNode} to get a last node and match with current selection\n */\n navigatePrevious() {\n let caretAtStart = this.Editor.Caret.isAtStart;\n\n if (!caretAtStart) {\n return;\n }\n\n let previousBlock = this.previousBlock;\n\n if (!previousBlock) {\n return;\n }\n\n this.Editor.Caret.setToBlock( previousBlock, 0, true );\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 let block = this.composeBlock(toolName, data);\n\n this._blocks[++this.currentBlockIndex] = block;\n this.Editor.Caret.setToBlock(block);\n }\n\n /**\n * Merge two blocks\n * @param {Block} targetBlock - previous block will be append to this block\n * @param {Block} blockToMerge - block that will be merged with target block\n *\n * @return {Promise} - the sequence that can be continued\n */\n mergeBlocks(targetBlock, blockToMerge) {\n let blockToMergeIndex = this._blocks.indexOf(blockToMerge);\n\n return Promise.resolve()\n .then( () => {\n if (blockToMerge.isEmpty) {\n return;\n }\n\n return blockToMerge.data\n .then((blockToMergeInfo) => {\n targetBlock.mergeWith(blockToMergeInfo.data);\n });\n })\n .then( () => {\n this.removeBlock(blockToMergeIndex);\n this.currentBlockIndex = this._blocks.indexOf(targetBlock);\n });\n }\n\n /**\n * Remove block with passed index or remove last\n * @param {Number|null} index\n */\n removeBlock(index) {\n this._blocks.remove(index);\n }\n /**\n * Split current Block\n * 1. Extract content from Caret position to the Block`s end\n * 2. Insert a new Block below current one with extracted content\n */\n split() {\n let extractedFragment = this.Editor.Caret.extractFragmentFromCaretPosition(),\n wrapper = $.make('div');\n\n wrapper.append(extractedFragment);\n\n /**\n * @todo make object in accordance with Tool\n */\n let data = {\n text: $.isEmpty(wrapper) ? '' : wrapper.innerHTML,\n };\n\n this.insert(this.config.initialBlock, data);\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 let block = this.composeBlock(toolName, data);\n\n this._blocks.insert(this.currentBlockIndex, block, true);\n }\n\n /**\n * returns last Block\n * @return {Block}\n */\n get lastBlock() {\n return this._blocks[this._blocks.length - 1];\n }\n\n /**\n * Returns Block by passed index\n * @param {Number} index\n * @return {Block}\n */\n getBlockByIndex(index) {\n return this._blocks[index];\n }\n\n /**\n * Get Block instance by html element\n * @param {HTMLElement} element\n * @returns {Block}\n */\n getBlock(element) {\n let nodes = this._blocks.nodes,\n firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`),\n index = nodes.indexOf(firstLevelBlock);\n\n if (index >= 0) {\n return this._blocks[index];\n }\n }\n\n /**\n * Get current Block instance\n *\n * @return {Block}\n */\n get currentBlock() {\n return this._blocks[this.currentBlockIndex];\n }\n\n /**\n * Returns next Block instance\n * @return {Block|null}\n */\n get nextBlock() {\n let isLastBlock = this.currentBlockIndex === (this._blocks.length - 1);\n\n if (isLastBlock) {\n return null;\n }\n\n return this._blocks[this.currentBlockIndex + 1];\n }\n\n /**\n * Returns previous Block instance\n * @return {Block|null}\n */\n get previousBlock() {\n let isFirstBlock = this.currentBlockIndex === 0;\n\n if (isFirstBlock) {\n return null;\n }\n\n return this._blocks[this.currentBlockIndex - 1];\n }\n\n /**\n * Get working html element\n *\n * @return {HTMLElement}\n */\n get currentNode() {\n return this._blocks.nodes[this.currentBlockIndex];\n }\n\n /**\n * Set currentBlockIndex to passed block\n * @param {HTMLElement} element\n */\n set currentNode(element) {\n let nodes = this._blocks.nodes,\n firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`);\n\n /**\n * Update current Block's index\n * @type {number}\n */\n this.currentBlockIndex = nodes.indexOf(firstLevelBlock);\n\n /**\n * Remove previous selected Block's state\n */\n this._blocks.array.forEach( block => block.selected = false);\n\n /**\n * Mark current Block as selected\n * @type {boolean}\n */\n this.currentBlock.selected = true;\n }\n\n /**\n * Get array of Block instances\n *\n * @returns {Block[]} {@link Blocks#array}\n */\n get blocks() {\n return this._blocks.array;\n }\n\n /**\n * 1) Find first-level Block from passed child Node\n * 2) Mark it as current\n *\n * @param {Element|Text} childNode - look ahead from this node.\n * @throws Error - when passed Node is not included at the Block\n */\n setCurrentBlockByChildNode(childNode) {\n /**\n * If node is Text TextNode\n */\n if (!$.isElement(childNode)) {\n childNode = childNode.parentNode;\n }\n\n let parentFirstLevelBlock = childNode.closest(`.${Block.CSS.wrapper}`);\n\n if (parentFirstLevelBlock) {\n this.currentNode = parentFirstLevelBlock;\n } else {\n throw new Error('Can not find a Block from this child Node');\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 * @constructor\n *\n * @param {HTMLElement} workingArea — editor`s working node\n */\n constructor(workingArea) {\n this.blocks = [];\n this.workingArea = workingArea;\n }\n\n /**\n * Push back new Block\n *\n * @param {Block} block\n */\n push(block) {\n this.blocks.push(block);\n this.workingArea.appendChild(block.html);\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 if (!this.length) {\n this.push(block);\n return;\n }\n\n if (index > this.length) {\n index = this.length;\n }\n\n if (replace) {\n this.blocks[index].html.remove();\n }\n\n let deleteCount = replace ? 1 : 0;\n\n this.blocks.splice(index, deleteCount, block);\n\n if (index > 0) {\n let previousBlock = this.blocks[index - 1];\n\n previousBlock.html.insertAdjacentElement('afterend', block.html);\n } else {\n let nextBlock = this.blocks[index + 1];\n\n if (nextBlock) {\n nextBlock.html.insertAdjacentElement('beforebegin', block.html);\n } else {\n this.workingArea.appendChild(block.html);\n }\n }\n }\n\n /**\n * Remove block\n * @param {Number|null} index\n */\n remove(index) {\n if (!index) {\n index = this.length - 1;\n }\n\n this.blocks[index].html.remove();\n this.blocks.splice(index, 1);\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 let index = this.blocks.indexOf(targetBlock);\n\n this.insert(index + 1, newBlock);\n }\n\n /**\n * Get Block by index\n *\n * @param {Number} index — Block index\n * @returns {Block}\n */\n get(index) {\n return this.blocks[index];\n }\n\n /**\n * Return index of passed Block\n *\n * @param {Block} block\n * @returns {Number}\n */\n indexOf(block) {\n return this.blocks.indexOf(block);\n }\n\n /**\n * Get length of Block instances array\n *\n * @returns {Number}\n */\n get length() {\n return this.blocks.length;\n }\n\n /**\n * Get Block instances array\n *\n * @returns {Block[]}\n */\n get array() {\n return this.blocks;\n }\n\n /**\n * Get blocks html elements array\n *\n * @returns {HTMLElement[]}\n */\n get nodes() {\n return _.array(this.workingArea.children);\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 if (isNaN(Number(index))) {\n return false;\n }\n\n instance.insert(index, block);\n\n return true;\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 if (isNaN(Number(index))) {\n return instance[index];\n }\n\n return instance.get(index);\n }\n}","/**\n * @class Caret\n * @classdesc Contains methods for working Caret\n *\n * Uses Range methods to manipulate with caret\n *\n * @module Caret\n *\n * @version 2.0.0\n */\n\n/**\n * @typedef {Caret} Caret\n */\nimport Selection from '../Selection';\n\nexport default class Caret extends Module {\n /**\n * @constructor\n */\n constructor({config}) {\n super({config});\n }\n\n /**\n * Method gets Block instance and puts caret to the text node with offset\n * There two ways that method applies caret position:\n * - first found text node: sets at the beginning, but you can pass an offset\n * - last found text node: sets at the end of the node. Also, you can customize the behaviour\n *\n * @param {Block} block - Block class\n * @param {Number} offset - caret offset regarding to the text node\n * @param {Boolean} atEnd - put caret at the end of the text node or not\n */\n setToBlock(block, offset = 0, atEnd = false) {\n let element = block.pluginsContent;\n\n /** If Element is INPUT */\n if ($.isNativeInput(element)) {\n element.focus();\n return;\n }\n\n let nodeToSet = $.getDeepestNode(element, atEnd);\n\n if (atEnd || offset > nodeToSet.length) {\n offset = nodeToSet.length;\n }\n\n /** if found deepest node is native input */\n if ($.isNativeInput(nodeToSet)) {\n nodeToSet.focus();\n return;\n }\n\n /**\n * @todo try to fix via Promises or use querySelectorAll to not to use timeout\n */\n _.delay( () => {\n this.set(nodeToSet, offset);\n }, 20)();\n\n this.Editor.BlockManager.currentNode = block.wrapper;\n }\n\n /**\n * Creates Document Range and sets caret to the element with offset\n * @param {Element} element - target node.\n * @param {Number} offset - offset\n */\n set( element, offset = 0) {\n let range = document.createRange(),\n selection = Selection.get();\n\n range.setStart(element, offset);\n range.setEnd(element, offset);\n\n selection.removeAllRanges();\n selection.addRange(range);\n };\n\n /**\n * Set Caret to the last Block\n * If last block is not empty, append another empty block\n */\n setToTheLastBlock() {\n let lastBlock = this.Editor.BlockManager.lastBlock;\n\n if (!lastBlock) return;\n\n /**\n * If last block is empty and it is an initialBlock, set to that.\n * Otherwise, append new empty block and set to that\n */\n if (lastBlock.isEmpty) {\n this.setToBlock(lastBlock);\n } else {\n this.Editor.BlockManager.insert(this.config.initialBlock);\n }\n }\n\n /**\n * Extract content fragment of current Block from Caret position to the end of the Block\n */\n extractFragmentFromCaretPosition() {\n let selection = Selection.get();\n\n if (selection.rangeCount) {\n let selectRange = selection.getRangeAt(0),\n blockElem = this.Editor.BlockManager.currentBlock.pluginsContent;\n\n selectRange.deleteContents();\n\n if (blockElem) {\n let range = selectRange.cloneRange(true);\n\n range.selectNodeContents(blockElem);\n range.setStart(selectRange.endContainer, selectRange.endOffset);\n return range.extractContents();\n }\n }\n }\n\n /**\n * Get all first-level (first child of [contenteditabel]) siblings from passed node\n * Then you can check it for emptiness\n *\n * @example\n *

    \n *

    |\n *

    | left first-level siblings\n *

    |\n *
    adaddad
    <-- passed node for example \n *

    |\n *

    | right first-level siblings\n *

    |\n *
    \n *\n * @return {Element[]}\n */\n getHigherLevelSiblings(from, direction ) {\n let current = from,\n siblings = [];\n\n /**\n * Find passed node's firs-level parent (in example - blockquote)\n */\n while (current.parentNode && current.parentNode.contentEditable !== 'true') {\n current = current.parentNode;\n }\n\n let sibling = direction === 'left' ? 'previousSibling' : 'nextSibling';\n\n /**\n * Find all left/right siblings\n */\n while (current[sibling]) {\n current = current[sibling];\n siblings.push(current);\n }\n\n return siblings;\n }\n\n /**\n * Get's deepest first node and checks if offset is zero\n * @return {boolean}\n */\n get isAtStart() {\n /**\n * Don't handle ranges\n */\n if (!Selection.isCollapsed) {\n return false;\n }\n\n let selection = Selection.get(),\n anchorNode = selection.anchorNode,\n firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent);\n\n /**\n * Workaround case when caret in the text like \" |Hello!\"\n * selection.anchorOffset is 1, but real caret visible position is 0\n * @type {number}\n */\n let firstLetterPosition = anchorNode.textContent.search(/\\S/);\n\n if (firstLetterPosition === -1) { // empty text\n firstLetterPosition = 0;\n }\n\n /**\n * In case of\n *
    \n *

    <-- first (and deepest) node is \n * |adaddad <-- anchor node\n *
    \n */\n if ($.isEmpty(firstNode)) {\n let leftSiblings = this.getHigherLevelSiblings(anchorNode, 'left'),\n nothingAtLeft = leftSiblings.every( node => $.isEmpty(node) );\n\n\n\n if (nothingAtLeft && selection.anchorOffset === firstLetterPosition) {\n return true;\n }\n }\n\n return firstNode === null || anchorNode === firstNode && selection.anchorOffset === firstLetterPosition;\n }\n\n /**\n * Get's deepest last node and checks if offset is last node text length\n * @return {boolean}\n */\n get isAtEnd() {\n /**\n * Don't handle ranges\n */\n if (!Selection.isCollapsed) {\n return false;\n }\n\n let selection = Selection.get(),\n anchorNode = selection.anchorNode,\n lastNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent, true);\n\n /**\n * In case of\n *
    \n * adaddad| <-- anchor node\n *

    <-- first (and deepest) node is \n *
    \n */\n if ($.isEmpty(lastNode)) {\n let leftSiblings = this.getHigherLevelSiblings(anchorNode, 'right'),\n nothingAtRight = leftSiblings.every( node => $.isEmpty(node) );\n\n if (nothingAtRight && selection.anchorOffset === anchorNode.textContent.length) {\n return true;\n }\n }\n\n return anchorNode === lastNode && selection.anchorOffset === lastNode.textContent.length;\n }\n}\n","/**\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 * @constructor\n */\n constructor({config}) {\n super({config});\n this.subscribers = {};\n }\n\n /**\n * @param {String} eventName - event name\n * @param {Function} callback - subscriber\n */\n on(eventName, callback) {\n if (!(eventName in this.subscribers)) {\n this.subscribers[eventName] = [];\n }\n\n // group by events\n this.subscribers[eventName].push(callback);\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 this.subscribers[eventName].reduce(function (previousData, currentHandler) {\n let newData = currentHandler(previousData);\n\n return newData ? newData : previousData;\n }, data);\n }\n\n /**\n * Destroyer\n * clears subsribers list\n */\n destroy() {\n this.subscribers = null;\n }\n}","/**\n * @class Keyboard\n * @classdesc Сlass to handle the keydowns\n *\n * @author CodeX Team (team@ifmo.su)\n * @copyright CodeX Team 2017\n * @license The MIT License (MIT)\n * @version 1.0.0\n */\n\n/**\n * @typedef {Keyboard} Keyboard\n */\nexport default class Keyboard extends Module {\n /**\n * @constructor\n */\n constructor({config}) {\n super({config});\n }\n\n /**\n * Handler on Block for keyboard keys at keydown event\n *\n * @param {KeyboardEvent} event\n */\n blockKeydownsListener(event) {\n switch(event.keyCode) {\n case _.keyCodes.BACKSPACE:\n\n _.log('Backspace key pressed');\n this.backspacePressed(event);\n break;\n\n case _.keyCodes.ENTER:\n\n _.log('Enter key pressed');\n this.enterPressed(event);\n break;\n\n case _.keyCodes.DOWN:\n case _.keyCodes.RIGHT:\n\n _.log('Right/Down key pressed');\n this.arrowRightAndDownPressed();\n break;\n\n case _.keyCodes.UP:\n case _.keyCodes.LEFT:\n\n _.log('Left/Up key pressed');\n this.arrowLeftAndUpPressed();\n break;\n\n default:\n\n break;\n }\n }\n\n /**\n * Handle pressing enter key\n *\n * @param {KeyboardEvent} event\n */\n enterPressed(event) {\n let currentBlock = this.Editor.BlockManager.currentBlock,\n toolsConfig = this.config.toolsConfig[currentBlock.name];\n\n /**\n * Don't handle Enter keydowns when Tool sets enableLineBreaks to true.\n * Uses for Tools like where line breaks should be handled by default behaviour.\n */\n if (toolsConfig && toolsConfig.enableLineBreaks) {\n return;\n }\n\n /**\n * Allow to create linebreaks by Shift+Enter\n */\n if (event.shiftKey) {\n return;\n }\n\n\n /**\n * Split the Current Block into two blocks\n */\n this.Editor.BlockManager.split();\n event.preventDefault();\n }\n\n /**\n * Handle backspace keypress on block\n * @param {KeyboardEvent} event - keydown\n */\n backspacePressed(event) {\n const BM = this.Editor.BlockManager;\n\n let isFirstBlock = BM.currentBlockIndex === 0,\n canMergeBlocks = this.Editor.Caret.isAtStart && !isFirstBlock;\n\n if (!canMergeBlocks) {\n return;\n }\n\n // preventing browser default behaviour\n event.preventDefault();\n\n let targetBlock = BM.getBlockByIndex(BM.currentBlockIndex - 1),\n blockToMerge = BM.currentBlock;\n\n /**\n * Blocks that can be merged:\n * 1) with the same Name\n * 2) Tool has 'merge' method\n *\n * other case will handle as usual ARROW LEFT behaviour\n */\n if (blockToMerge.name !== targetBlock.name || !targetBlock.mergeable) {\n BM.navigatePrevious();\n }\n\n let setCaretToTheEnd = !targetBlock.isEmpty ? true : false;\n\n BM.mergeBlocks(targetBlock, blockToMerge)\n .then( () => {\n window.setTimeout( () => {\n // set caret to the block without offset at the end\n this.Editor.Caret.setToBlock(BM.currentBlock, 0, setCaretToTheEnd);\n this.Editor.Toolbar.close();\n }, 10);\n });\n }\n\n /**\n * Handle right and down keyboard keys\n */\n arrowRightAndDownPressed() {\n this.Editor.BlockManager.navigateNext();\n }\n\n /**\n * Handle left and up keyboard keys\n */\n arrowLeftAndUpPressed() {\n this.Editor.BlockManager.navigatePrevious();\n }\n}","/**\n * Codex Editor Listeners module\n *\n * @module Listeners\n *\n * Module-decorator for event listeners assignment\n *\n * @author Codex Team\n * @version 2.0.0\n */\n\n/**\n * @typedef {Listeners} Listeners\n * @property {Array} allListeners\n */\n\nexport default class Listeners extends Module {\n /**\n * @constructor\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n this.allListeners = [];\n }\n\n /**\n * Assigns event listener on element\n *\n * @param {Element} element - DOM element that needs to be listened\n * @param {String} eventType - event type\n * @param {Function} handler - method that will be fired on event\n * @param {Boolean} useCapture - use event bubbling\n */\n on(element, eventType, handler, useCapture = false) {\n let assignedEventData = {\n element,\n eventType,\n handler,\n useCapture\n };\n\n let alreadyExist = this.findOne(element, eventType, handler);\n\n if (alreadyExist) return;\n\n this.allListeners.push(assignedEventData);\n element.addEventListener(eventType, handler, useCapture);\n }\n\n /**\n * Removes event listener from element\n *\n * @param {Element} element - DOM element that we removing listener\n * @param {String} eventType - event type\n * @param {Function} handler - remove handler, if element listens several handlers on the same event type\n * @param {Boolean} useCapture - use event bubbling\n */\n off(element, eventType, handler, useCapture = false) {\n let existingListeners = this.findAll(element, eventType, handler);\n\n for (let i = 0; i < existingListeners.length; i++) {\n let index = this.allListeners.indexOf(existingListeners[i]);\n\n if (index > 0) {\n this.allListeners.splice(index, 1);\n }\n }\n\n element.removeEventListener(eventType, handler, useCapture);\n }\n\n /**\n * Search method: looks for listener by passed element\n * @param {Element} element - searching element\n * @returns {Array} listeners that found on element\n */\n findByElement(element) {\n let listenersOnElement = [];\n\n for (let i = 0; i < this.allListeners.length; i++) {\n let listener = this.allListeners[i];\n\n if (listener.element === element) {\n listenersOnElement.push(listener);\n }\n }\n\n return listenersOnElement;\n }\n\n /**\n * Search method: looks for listener by passed event type\n * @param {String} eventType\n * @return {Array} listeners that found on element\n */\n findByType(eventType) {\n let listenersWithType = [];\n\n for (let i = 0; i < this.allListeners.length; i++) {\n let listener = this.allListeners[i];\n\n if (listener.type === eventType) {\n listenersWithType.push(listener);\n }\n }\n\n return listenersWithType;\n }\n\n /**\n * Search method: looks for listener by passed handler\n * @param {Function} handler\n * @return {Array} listeners that found on element\n */\n findByHandler(handler) {\n let listenersWithHandler = [];\n\n for (let i = 0; i < this.allListeners.length; i++) {\n let listener = this.allListeners[i];\n\n if (listener.handler === handler) {\n listenersWithHandler.push(listener);\n }\n }\n\n return listenersWithHandler;\n }\n\n /**\n * @param {Element} element\n * @param {String} eventType\n * @param {Function} handler\n * @return {Element|null}\n */\n findOne(element, eventType, handler) {\n let foundListeners = this.findAll(element, eventType, handler);\n\n return foundListeners.length > 0 ? foundListeners[0] : null;\n }\n\n /**\n * @param {Element} element\n * @param {String} eventType\n * @param {Function} handler\n * @return {Array}\n */\n findAll(element, eventType, handler) {\n let foundAllListeners,\n foundByElements = [],\n foundByEventType = [],\n foundByHandler = [];\n\n if (element)\n foundByElements = this.findByElement(element);\n\n if (eventType)\n foundByEventType = this.findByType(eventType);\n\n if (handler)\n foundByHandler = this.findByHandler(handler);\n\n foundAllListeners = foundByElements.concat(foundByEventType, foundByHandler);\n\n return foundAllListeners;\n }\n\n /**\n * Removes all listeners\n */\n removeAll() {\n this.allListeners.map( (current) => {\n current.element.removeEventListener(current.eventType, current.handler);\n });\n\n this.allListeners = [];\n }\n}","/**\n * Codex Editor Renderer Module\n *\n * @module Renderer\n * @author CodeX Team\n *\n * @version 2.0.0\n */\nexport default class Renderer extends Module {\n /**\n * @constructor\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n }\n\n /**\n * @typedef {Object} RendererItems\n * @property {String} type - tool name\n * @property {Object} data - tool data\n */\n\n /**\n * @example\n *\n * items: [\n * {\n * type : 'paragraph',\n * data : {\n * text : 'Hello from Codex!'\n * }\n * },\n * {\n * type : 'paragraph',\n * data : {\n * text : 'Leave feedback if you like it!'\n * }\n * },\n * ]\n *\n */\n\n /**\n * Make plugin blocks from array of plugin`s data\n * @param {RendererItems[]} items\n */\n render(items) {\n let chainData = [];\n\n for (let i = 0; i < items.length; i++) {\n chainData.push({\n function: () => this.insertBlock(items[i])\n });\n }\n\n return _.sequence(chainData);\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 let tool = item.type,\n data = item.data;\n\n this.Editor.BlockManager.insert(tool, data);\n\n return Promise.resolve();\n }\n}","/**\n * CodeX Sanitizer\n *\n * @module Sanitizer\n * Clears HTML from taint tags\n *\n * @version 2.0.0\n *\n * @example\n * Module can be used within two ways:\n * 1) When you have an instance\n * - this.Editor.Sanitizer.clean(yourTaintString);\n * 2) As static method\n * - CodexEditor.Sanitizer.clean(yourTaintString, yourCustomConfiguration);\n *\n * {@link SanitizerConfig}\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 * Initializes Sanitizer module\n * Sets default configuration if custom not exists\n *\n * @property {SanitizerConfig} this.defaultConfig\n * @property {HTMLJanitor} this._sanitizerInstance - Sanitizer library\n *\n * @param {SanitizerConfig} config\n */\n constructor({config}) {\n super({config});\n\n // default config\n this.defaultConfig = null;\n this._sanitizerInstance = 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 * 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 this._sanitizerInstance = new library(this.defaultConfig);\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 if (_.isEmpty(config)) {\n this.defaultConfig = {\n tags: {\n p: {},\n a: {\n href: true,\n target: '_blank',\n rel: 'nofollow'\n }\n }\n };\n } else {\n this.defaultConfig = config;\n }\n }\n\n /**\n * Cleans string from unwanted tags\n * @param {String} taintString - HTML string\n * @param {Object} customConfig - custom sanitizer configuration. Method uses default if param is empty\n * @return {String} clean HTML\n */\n clean(taintString, customConfig = {}) {\n if (_.isEmpty(customConfig)) {\n return this._sanitizerInstance.clean(taintString);\n } else {\n return Sanitizer.clean(taintString, customConfig);\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 let newInstance = Sanitizer(customConfig);\n\n return newInstance.clean(taintString);\n }\n}\n","/**\n * Codex Editor Saver\n *\n * @module Saver\n * @author Codex Team\n * @version 2.0.0\n */\n\n/**\n * @typedef {Object} SavedData\n * @property {Date} time - saving proccess time\n * @property {Object} items - extracted data\n * @property {String} version - CodexEditor version\n */\n\n/**\n * @classdesc This method reduces all Blocks asyncronically and calls Block's save method to extract data\n *\n * @typedef {Saver} Saver\n * @property {Element} html - Editor HTML content\n * @property {String} json - Editor JSON output\n */\n\nexport default class Saver extends Module {\n /**\n * @constructor\n * @param config\n */\n constructor({config}) {\n super({config});\n\n this.output = null;\n this.blocksData = [];\n }\n\n /**\n * Composes new chain of Promises to fire them alternatelly\n * @return {SavedData}\n */\n save() {\n let blocks = this.Editor.BlockManager.blocks,\n chainData = [];\n\n blocks.forEach((block) => {\n chainData.push(block.data);\n });\n\n return Promise.all(chainData)\n .then((allExtractedData) => this.makeOutput(allExtractedData))\n .then((outputData) => {\n return outputData;\n });\n }\n\n /**\n * Creates output object with saved data, time and version of editor\n * @param {Object} allExtractedData\n * @return {SavedData}\n */\n makeOutput(allExtractedData) {\n let items = [],\n totalTime = 0;\n\n console.groupCollapsed('[CodexEditor saving]:');\n\n allExtractedData.forEach((extraction) => {\n /** Group process info */\n console.log(`«${extraction.tool}» saving info`, extraction);\n totalTime += extraction.time;\n items.push(extraction.data);\n });\n\n console.log('Total', totalTime);\n console.groupEnd();\n\n return {\n time : +new Date(),\n items : items,\n version : VERSION,\n };\n }\n}\n\n// module.exports = (function (saver) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * @public\n// * Save blocks\n// */\n// saver.save = function () {\n//\n// /** Save html content of redactor to memory */\n// editor.state.html = editor.nodes.redactor.innerHTML;\n//\n// /** Clean jsonOutput state */\n// editor.state.jsonOutput = [];\n//\n// return saveBlocks(editor.nodes.redactor.childNodes);\n//\n// };\n//\n// /**\n// * @private\n// * Save each block data\n// *\n// * @param blocks\n// * @returns {Promise.}\n// */\n// let saveBlocks = function (blocks) {\n//\n// let data = [];\n//\n// for(let index = 0; index < blocks.length; index++) {\n//\n// data.push(getBlockData(blocks[index]));\n//\n// }\n//\n// return Promise.all(data)\n// .then(makeOutput)\n// .catch(editor.core.log);\n//\n// };\n//\n// /** Save and validate block data */\n// let getBlockData = function (block) {\n//\n// return saveBlockData(block)\n// .then(validateBlockData)\n// .catch(editor.core.log);\n//\n// };\n//\n// /**\n// * @private\n// * Call block`s plugin save method and return saved data\n// *\n// * @param block\n// * @returns {Object}\n// */\n// let saveBlockData = function (block) {\n//\n// let pluginName = block.dataset.tool;\n//\n// /** Check for plugin existence */\n// if (!editor.tools[pluginName]) {\n//\n// editor.core.log(`Plugin «${pluginName}» not found`, 'error');\n// return {data: null, pluginName: null};\n//\n// }\n//\n// /** Check for plugin having save method */\n// if (typeof editor.tools[pluginName].save !== 'function') {\n//\n// editor.core.log(`Plugin «${pluginName}» must have save method`, 'error');\n// return {data: null, pluginName: null};\n//\n// }\n//\n// /** Result saver */\n// let blockContent = block.childNodes[0],\n// pluginsContent = blockContent.childNodes[0],\n// position = pluginsContent.dataset.inputPosition;\n//\n// /** If plugin wasn't available then return data from cache */\n// if ( editor.tools[pluginName].available === false ) {\n//\n// return Promise.resolve({data: codex.editor.state.blocks.items[position].data, pluginName});\n//\n// }\n//\n// return Promise.resolve(pluginsContent)\n// .then(editor.tools[pluginName].save)\n// .then(data => Object({data, pluginName}));\n//\n// };\n//\n// /**\n// * Call plugin`s validate method. Return false if validation failed\n// *\n// * @param data\n// * @param pluginName\n// * @returns {Object|Boolean}\n// */\n// let validateBlockData = function ({data, pluginName}) {\n//\n// if (!data || !pluginName) {\n//\n// return false;\n//\n// }\n//\n// if (editor.tools[pluginName].validate) {\n//\n// let result = editor.tools[pluginName].validate(data);\n//\n// /**\n// * Do not allow invalid data\n// */\n// if (!result) {\n//\n// return false;\n//\n// }\n//\n// }\n//\n// return {data, pluginName};\n//\n//\n// };\n//\n// /**\n// * Compile article output\n// *\n// * @param savedData\n// * @returns {{time: number, version, items: (*|Array)}}\n// */\n// let makeOutput = function (savedData) {\n//\n// savedData = savedData.filter(blockData => blockData);\n//\n// let items = savedData.map(blockData => Object({type: blockData.pluginName, data: blockData.data}));\n//\n// editor.state.jsonOutput = items;\n//\n// return {\n// id: editor.state.blocks.id || null,\n// time: +new Date(),\n// version: editor.version,\n// items\n// };\n//\n// };\n//\n// return saver;\n//\n// })({});\n","/**\n * Block Settings\n *\n * ____ Settings Panel ____\n * | ...................... |\n * | . Tool Settings . |\n * | ...................... |\n * | . Default Settings . |\n * | ...................... |\n * |________________________|\n */\nexport default class BlockSettings extends Module {\n constructor({config}) {\n super({config});\n\n this.nodes = {\n wrapper: null,\n toolSettings: null,\n defaultSettings: null,\n buttonRemove: null\n };\n }\n\n /**\n * Block Settings CSS\n * @return {{wrapper, wrapperOpened, toolSettings, defaultSettings, button}}\n */\n static get CSS() {\n return {\n // Settings Panel\n wrapper: 'ce-settings',\n wrapperOpened: 'ce-settings--opened',\n toolSettings: 'ce-settings__plugin-zone',\n defaultSettings: 'ce-settings__default-zone',\n\n button: 'ce-settings__button'\n };\n }\n\n /**\n * Panel with block settings with 2 sections:\n * - Tool's Settings\n * - Default Settings [Move, Remove, etc]\n *\n * @return {Element}\n */\n make() {\n this.nodes.wrapper = $.make('div', BlockSettings.CSS.wrapper);\n\n this.nodes.toolSettings = $.make('div', BlockSettings.CSS.toolSettings);\n this.nodes.defaultSettings = $.make('div', BlockSettings.CSS.defaultSettings);\n\n $.append(this.nodes.wrapper, [this.nodes.toolSettings, this.nodes.defaultSettings]);\n\n /**\n * Add default settings that presents for all Blocks\n */\n this.addDefaultSettings();\n }\n\n /**\n * Add Tool's settings\n */\n addToolSettings() {\n console.log('Block Settings: add settings for ',\n this.Editor.BlockManager.currentBlock\n );\n }\n\n /**\n * Add default settings\n */\n addDefaultSettings() {\n /**\n * Remove Block Button\n * --------------------------------------------\n */\n this.nodes.buttonRemove = $.make('div', BlockSettings.CSS.button, {\n textContent: 'Remove Block'\n });\n\n $.append(this.nodes.defaultSettings, this.nodes.buttonRemove);\n\n this.Editor.Listeners.on(this.nodes.buttonRemove, 'click', (event) => this.removeBlockButtonClicked(event));\n }\n\n /**\n * Clicks on the Remove Block Button\n */\n removeBlockButtonClicked() {\n console.log('❇️ Remove Block Button clicked');\n }\n\n /**\n * Is Block Settings opened or not\n * @returns {boolean}\n */\n get opened() {\n return this.nodes.wrapper.classList.contains(BlockSettings.CSS.wrapperOpened);\n }\n\n /**\n * Open Block Settings pane\n */\n open() {\n this.nodes.wrapper.classList.add(BlockSettings.CSS.wrapperOpened);\n\n /**\n * Fill Tool's settings\n */\n this.addToolSettings();\n }\n\n /**\n * Close Block Settings pane\n */\n close() {\n this.nodes.wrapper.classList.remove(BlockSettings.CSS.wrapperOpened);\n }\n}\n","export default class InlineToolbar extends Module {\n /**\n * @constructor\n */\n constructor({ config }) {\n super({ config });\n /**\n * Inline Toolbar elements\n */\n this.nodes = {\n wrapper: null,\n };\n /**\n * CSS styles\n */\n this.CSS = {\n inlineToolbar: 'ce-inline-toolbar',\n };\n }\n /**\n * Making DOM\n */\n make() {\n this.nodes.wrapper = $.make('div', this.CSS.inlineToolbar);\n /**\n * Append Inline Toolbar to the Editor\n */\n $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);\n }\n move() {\n // moving\n }\n}\n","/**\n * @class Toolbox\n * @classdesc Holder for Tools\n *\n * @typedef {Toolbox} Toolbox\n * @property {Boolean} opened - opening state\n * @property {Object} nodes - Toolbox nodes\n * @property {Object} CSS - CSS class names\n *\n */\nexport default class Toolbox extends Module {\n /**\n * @constructor\n */\n constructor({config}) {\n super({config});\n\n this.nodes = {\n toolbox: null,\n buttons: []\n };\n\n /**\n * Opening state\n * @type {boolean}\n */\n this.opened = false;\n }\n\n /**\n * CSS styles\n * @return {{toolbox: string, toolboxButton: string, toolboxOpened: string}}\n */\n static get CSS() {\n return {\n toolbox: 'ce-toolbox',\n toolboxButton: 'ce-toolbox__button',\n toolboxOpened: 'ce-toolbox--opened',\n };\n }\n\n /**\n * Makes the Toolbox\n */\n make() {\n this.nodes.toolbox = $.make('div', Toolbox.CSS.toolbox);\n $.append(this.Editor.Toolbar.nodes.content, this.nodes.toolbox);\n\n this.addTools();\n }\n\n /**\n * Iterates available tools and appends them to the Toolbox\n */\n addTools() {\n let tools = this.Editor.Tools.toolsAvailable;\n\n for (let toolName in tools) {\n this.addTool(toolName, tools[toolName]);\n }\n }\n\n /**\n * Append Tool to the Toolbox\n *\n * @param {string} toolName - tool name\n * @param {Tool} tool - tool class\n */\n addTool(toolName, tool) {\n if (tool.displayInToolbox && !tool.iconClassName) {\n _.log('Toolbar icon class name is missed. Tool %o skipped', 'warn', toolName);\n return;\n }\n\n /**\n * @todo Add checkup for the render method\n */\n // if (typeof tool.render !== 'function') {\n //\n // _.log('render method missed. Tool %o skipped', 'warn', tool);\n // return;\n //\n // }\n\n /**\n * Skip tools that pass 'displayInToolbox=false'\n */\n if (!tool.displayInToolbox) {\n return;\n }\n\n let button = $.make('li', [Toolbox.CSS.toolboxButton, tool.iconClassName], {\n title: toolName\n });\n\n /**\n * Save tool's name in the button data-name\n */\n button.dataset.name = toolName;\n\n $.append(this.nodes.toolbox, button);\n\n this.nodes.toolbox.appendChild(button);\n this.nodes.buttons.push(button);\n\n /**\n * @todo add event with module Listeners\n */\n // this.Editor.Listeners.add();\n button.addEventListener('click', event => {\n this.buttonClicked(event);\n }, false);\n }\n\n /**\n * Toolbox button click listener\n * 1) if block is empty -> replace\n * 2) if block is not empty -> add new block below\n *\n * @param {MouseEvent} event\n */\n buttonClicked(event) {\n let toolButton = event.target,\n toolName = toolButton.dataset.name,\n tool = this.Editor.Tools.toolClasses[toolName];\n\n /**\n * @type {Block}\n */\n let currentBlock = this.Editor.BlockManager.currentBlock;\n\n /**\n * We do replace if:\n * - block is empty\n * - block is not irreplaceable\n * @type {Array}\n */\n if (!tool.irreplaceable && currentBlock.isEmpty) {\n this.Editor.BlockManager.replace(toolName);\n } else {\n this.Editor.BlockManager.insert(toolName);\n }\n\n /**\n * @todo set caret to the new block\n */\n\n // window.setTimeout(function () {\n\n /** Set caret to current block */\n // editor.caret.setToBlock(currentInputIndex);\n\n // }, 10);\n\n /**\n * Move toolbar when node is changed\n */\n this.Editor.Toolbar.move();\n }\n\n /**\n * Open Toolbox with Tools\n */\n open() {\n this.nodes.toolbox.classList.add(Toolbox.CSS.toolboxOpened);\n this.opened = true;\n }\n\n /**\n * Close Toolbox\n */\n close() {\n this.nodes.toolbox.classList.remove(Toolbox.CSS.toolboxOpened);\n this.opened = false;\n }\n\n /**\n * Close Toolbox\n */\n toggle() {\n if (!this.opened) {\n this.open();\n } else {\n this.close();\n }\n }\n}","/**\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.blockActionsButtons - Zone with Block Buttons: [Settings]\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.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 * @constructor\n */\n constructor({config}) {\n super({config});\n\n this.nodes = {\n wrapper : null,\n content : null,\n actions : null,\n\n // Content Zone\n plusButton : null,\n\n // Actions Zone\n blockActionsButtons: null,\n settingsToggler : null,\n };\n }\n\n /**\n * CSS styles\n * @return {Object}\n * @constructor\n */\n static get CSS() {\n return {\n toolbar: 'ce-toolbar',\n content: 'ce-toolbar__content',\n actions: 'ce-toolbar__actions',\n\n toolbarOpened: 'ce-toolbar--opened',\n\n // Content Zone\n plusButton: 'ce-toolbar__plus',\n plusButtonHidden: 'ce-toolbar__plus--hidden',\n\n // Actions Zone\n blockActionsButtons: 'ce-toolbar__actions-buttons',\n settingsToggler: 'ce-toolbar__settings-btn',\n };\n }\n\n /**\n * Makes toolbar\n */\n make() {\n this.nodes.wrapper = $.make('div', Toolbar.CSS.toolbar);\n\n /**\n * Make Content Zone and Actions Zone\n */\n ['content', 'actions'].forEach( el => {\n this.nodes[el] = $.make('div', Toolbar.CSS[el]);\n $.append(this.nodes.wrapper, this.nodes[el]);\n });\n\n\n /**\n * Fill Content Zone:\n * - Plus Button\n * - Toolbox\n */\n this.nodes.plusButton = $.make('div', Toolbar.CSS.plusButton);\n $.append(this.nodes.content, this.nodes.plusButton);\n this.nodes.plusButton.addEventListener('click', event => this.plusButtonClicked(event), false);\n\n\n /**\n * Make a Toolbox\n */\n this.Editor.Toolbox.make();\n\n /**\n * Fill Actions Zone:\n * - Settings Toggler\n * - Remove Block Button\n * - Settings Panel\n */\n this.nodes.blockActionsButtons = $.make('div', Toolbar.CSS.blockActionsButtons);\n this.nodes.settingsToggler = $.make('span', Toolbar.CSS.settingsToggler);\n\n $.append(this.nodes.blockActionsButtons, this.nodes.settingsToggler);\n $.append(this.nodes.actions, this.nodes.blockActionsButtons);\n\n /**\n * Make and append Settings Panel\n */\n this.Editor.BlockSettings.make();\n $.append(this.nodes.actions, this.Editor.BlockSettings.nodes.wrapper);\n\n /**\n * Append toolbar to the Editor\n */\n $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);\n\n /**\n * Bind events on the Toolbar elements\n */\n this.bindEvents();\n }\n\n /**\n * Move Toolbar to the Current Block\n */\n move() {\n /** Close Toolbox when we move toolbar */\n this.Editor.Toolbox.close();\n\n let currentNode = this.Editor.BlockManager.currentNode;\n\n /**\n * If no one Block selected as a Current\n */\n if (!currentNode) {\n return;\n }\n\n /**\n * @todo Compute dynamically on prepare\n * @type {number}\n */\n const defaultToolbarHeight = 49;\n const defaultOffset = 34;\n\n var newYCoordinate = currentNode.offsetTop - (defaultToolbarHeight / 2) + defaultOffset;\n\n this.nodes.wrapper.style.transform = `translate3D(0, ${Math.floor(newYCoordinate)}px, 0)`;\n\n /** Close trash actions */\n // editor.toolbar.settings.hideRemoveActions();\n }\n\n /**\n * Open Toolbar with Plus Button\n */\n open() {\n this.nodes.wrapper.classList.add(Toolbar.CSS.toolbarOpened);\n }\n\n /**\n * Close the Toolbar\n */\n close() {\n this.nodes.wrapper.classList.remove(Toolbar.CSS.toolbarOpened);\n }\n\n /**\n * Plus Button public methods\n * @return {{hide: function(): void, show: function(): void}}\n */\n get plusButton() {\n return {\n hide: () => this.nodes.plusButton.classList.add(Toolbar.CSS.plusButtonHidden),\n show: () => this.nodes.plusButton.classList.remove(Toolbar.CSS.plusButtonHidden)\n };\n }\n\n /**\n * Handler for Plus Button\n * @param {MouseEvent} event\n */\n plusButtonClicked() {\n this.Editor.Toolbox.toggle();\n }\n\n /**\n * Bind events on the Toolbar Elements:\n * - Block Settings\n */\n bindEvents() {\n /**\n * Settings toggler\n */\n this.Editor.Listeners.on(this.nodes.settingsToggler, 'click', (event) => {\n this.settingsTogglerClicked(event);\n });\n }\n\n /**\n * Clicks on the Block Settings toggler\n */\n settingsTogglerClicked() {\n if (this.Editor.BlockSettings.opened) {\n this.Editor.BlockSettings.close();\n } else {\n this.Editor.BlockSettings.open();\n }\n }\n}","/**\n * @module Codex Editor Tools Submodule\n *\n * Creates Instances from Plugins and binds external config to the instances\n */\n\n/**\n * Each Tool must contain the following important objects:\n *\n * @typedef {Object} ToolConfig {@link docs/tools.md}\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 * @property render @todo add description\n * @property save @todo add description\n * @property settings @todo add description\n * @property validate - method that validates output data before saving\n */\n\n/**\n * @typedef {Function} Tool {@link docs/tools.md}\n * @property {Boolean} displayInToolbox - By default, tools won't be added in the Toolbox. Pass true to add.\n * @property {String} iconClassName - CSS class name for the Toolbox button\n * @property {Boolean} irreplaceable - Toolbox behaviour: replace or add new block below\n * @property render\n * @property save\n * @property settings\n * @property validate\n *\n * @todo update according to current API\n * @todo describe Tool in the {@link docs/tools.md}\n */\n\n/**\n * Class properties:\n *\n * @typedef {Tools} Tools\n * @property {Tools[]} toolsAvailable - available Tools\n * @property {Tools[]} toolsUnavailable - unavailable Tools\n * @property {Object} toolsClasses - all classes\n * @property {EditorConfig} config - Editor config\n */\nexport default class Tools extends Module {\n /**\n * Returns available Tools\n * @return {Tool[]}\n */\n get available() {\n return this.toolsAvailable;\n }\n\n /**\n * Returns unavailable Tools\n * @return {Tool[]}\n */\n get unavailable() {\n return this.toolsUnavailable;\n }\n\n /**\n * Static getter for default Tool config fields\n *\n * @usage Tools.defaultConfig.displayInToolbox\n * @return {ToolConfig}\n */\n static get defaultConfig() {\n return {\n iconClassName : '',\n displayInToolbox : false,\n enableLineBreaks : false,\n irreplaceable : false\n };\n }\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n\n /**\n * Map {name: Class, ...} where:\n * name — block type name in JSON. Got from EditorConfig.tools keys\n * @type {Object}\n */\n this.toolClasses = {};\n\n /**\n * Available tools list\n * {name: Class, ...}\n * @type {Object}\n */\n this.toolsAvailable = {};\n\n /**\n * Tools that rejected a prepare method\n * {name: Class, ... }\n * @type {Object}\n */\n this.toolsUnavailable = {};\n }\n\n /**\n * Creates instances via passed or default configuration\n * @return {Promise}\n */\n prepare() {\n if (!this.config.hasOwnProperty('tools')) {\n return Promise.reject(\"Can't start without tools\");\n }\n\n for(let toolName in this.config.tools) {\n this.toolClasses[toolName] = this.config.tools[toolName];\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 return Promise.resolve();\n }\n\n /**\n * to see how it works {@link Util#sequence}\n */\n return _.sequence(sequenceData, (data) => {\n this.success(data);\n }, (data) => {\n this.fallback(data);\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 sequentially\n */\n getListOfPrepareFunctions() {\n let toolPreparationList = [];\n\n for(let toolName in this.toolClasses) {\n let toolClass = this.toolClasses[toolName];\n\n if (typeof toolClass.prepare === 'function') {\n toolPreparationList.push({\n function : toolClass.prepare,\n data : {\n toolName\n }\n });\n } else {\n /**\n * If Tool hasn't a prepare method, mark it as available\n */\n this.toolsAvailable[toolName] = toolClass;\n }\n }\n\n return toolPreparationList;\n }\n\n /**\n * @param {ChainData.data} data - append tool to available list\n */\n success(data) {\n this.toolsAvailable[data.toolName] = this.toolClasses[data.toolName];\n }\n\n /**\n * @param {ChainData.data} data - append tool to unavailable list\n */\n fallback(data) {\n this.toolsUnavailable[data.toolName] = this.toolClasses[data.toolName];\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 let plugin = this.toolClasses[tool],\n config = this.config.toolsConfig[tool];\n\n if (!config) {\n config = this.defaultConfig;\n }\n\n let instance = new plugin(data, config);\n\n return instance;\n }\n\n /**\n * Check if passed Tool is an instance of Initial Block Tool\n * @param {Tool} tool - Tool to check\n * @return {Boolean}\n */\n isInitial(tool) {\n return tool instanceof this.available[this.config.initialBlock];\n }\n}","/**\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\n// import Block from '../block';\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 */\nexport default class UI extends Module {\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n\n this.nodes = {\n holder: null,\n wrapper: null,\n redactor: null\n };\n }\n\n /**\n * Making main interface\n */\n prepare() {\n return this.make()\n /**\n * Make toolbar\n */\n .then(() => this.Editor.Toolbar.make())\n /**\n * Make the Inline toolbar\n */\n .then(() => this.Editor.InlineToolbar.make())\n /**\n * Load and append CSS\n */\n .then(() => this.loadStyles())\n /**\n * Bind events for the UI elements\n */\n .then(() => this.bindEvents())\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 console.error(e);\n\n // editor.core.log(\"Can't draw editor interface\");\n });\n }\n\n /**\n * CodeX Editor UI CSS class names\n * @return {{editorWrapper: string, editorZone: string, block: string}}\n */\n get CSS() {\n return {\n editorWrapper : 'codex-editor',\n editorZone : 'codex-editor__redactor',\n };\n }\n\n /**\n * Makes CodeX Editor interface\n * @return {Promise}\n */\n make() {\n return new Promise( (resolve, reject) => {\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 reject(Error(\"Holder wasn't found by ID: #\" + this.config.holderId));\n return;\n }\n\n /**\n * Create and save main UI elements\n */\n this.nodes.wrapper = $.make('div', this.CSS.editorWrapper);\n this.nodes.redactor = $.make('div', this.CSS.editorZone);\n\n this.nodes.wrapper.appendChild(this.nodes.redactor);\n this.nodes.holder.appendChild(this.nodes.wrapper);\n\n resolve();\n });\n }\n\n /**\n * Appends CSS\n */\n loadStyles() {\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 * Bind events on the CodeX Editor interface\n */\n bindEvents() {\n /**\n * @todo bind events with the Listeners module\n */\n this.Editor.Listeners.on(this.nodes.redactor, 'click', event => this.redactorClicked(event), false );\n }\n\n /**\n * All clicks on the redactor zone\n *\n * @param {MouseEvent} event\n *\n * @description\n * 1. Save clicked Block as a current {@link BlockManager#currentNode}\n * it uses for the following:\n * - add CSS modifier for the selected Block\n * - on Enter press, we make a new Block under that\n *\n * 2. Move and show the Toolbar\n *\n * 3. Set a Caret\n *\n * 4. By clicks on the Editor's bottom zone:\n * - if last Block is empty, set a Caret to this\n * - otherwise, add a new empty Block and set a Caret to that\n *\n * 5. Hide the Inline Toolbar\n *\n * @see selectClickedBlock\n *\n */\n redactorClicked(event) {\n let clickedNode = event.target;\n\n /**\n * Select clicked Block as Current\n */\n try {\n this.Editor.BlockManager.setCurrentBlockByChildNode(clickedNode);\n } catch (e) {\n /**\n * If clicked outside first-level Blocks, set Caret to the last empty Block\n */\n this.Editor.Caret.setToTheLastBlock();\n }\n\n\n /**\n * @todo hide the Inline Toolbar\n */\n // var selectedText = editor.toolbar.inline.getSelectionText(),\n // firstLevelBlock;\n\n /** If selection range took off, then we hide inline toolbar */\n // if (selectedText.length === 0) {\n\n // editor.toolbar.inline.close();\n\n // }\n\n /**\n *\n\n /** Update current input index in memory when caret focused into existed input */\n // if (event.target.contentEditable == 'true') {\n //\n // editor.caret.saveCurrentInputIndex();\n //\n // }\n\n // if (editor.content.currentNode === null) {\n //\n // /**\n // * If inputs in redactor does not exits, then we put input index 0 not -1\n // */\n // var indexOfLastInput = editor.state.inputs.length > 0 ? editor.state.inputs.length - 1 : 0;\n //\n // /** If we have any inputs */\n // if (editor.state.inputs.length) {\n //\n // /** getting firstlevel parent of input */\n // firstLevelBlock = editor.content.getFirstLevelBlock(editor.state.inputs[indexOfLastInput]);\n //\n // }\n //\n // /** If input is empty, then we set caret to the last input */\n // if (editor.state.inputs.length && editor.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == editor.settings.initialBlockPlugin) {\n //\n // editor.caret.setToBlock(indexOfLastInput);\n //\n // } else {\n //\n // /** Create new input when caret clicked in redactors area */\n // var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n //\n // editor.content.insertBlock({\n // type : NEW_BLOCK_TYPE,\n // block : editor.tools[NEW_BLOCK_TYPE].render()\n // });\n //\n // /** If there is no inputs except inserted */\n // if (editor.state.inputs.length === 1) {\n //\n // editor.caret.setToBlock(indexOfLastInput);\n //\n // } else {\n //\n // /** Set caret to this appended input */\n // editor.caret.setToNextBlock(indexOfLastInput);\n //\n // }\n //\n // }\n //\n // } else {\n //\n // /** Close all panels */\n // editor.toolbar.settings.close();\n // editor.toolbar.toolbox.close();\n //\n // }\n //\n /**\n * Move toolbar and open\n */\n this.Editor.Toolbar.move();\n this.Editor.Toolbar.open();\n //\n // var inputIsEmpty = !editor.content.currentNode.textContent.trim(),\n // currentNodeType = editor.content.currentNode.dataset.tool,\n // isInitialType = currentNodeType == editor.settings.initialBlockPlugin;\n //\n //\n\n /**\n * Hide the Plus Button\n * */\n this.Editor.Toolbar.plusButton.hide();\n\n /**\n * Show the Plus Button if:\n * - Block is an initial-block (Text)\n * - Block is empty\n */\n let isInitialBlock = this.Editor.Tools.isInitial(this.Editor.BlockManager.currentBlock.tool),\n isEmptyBlock = this.Editor.BlockManager.currentBlock.isEmpty;\n\n if (isInitialBlock && isEmptyBlock) {\n this.Editor.Toolbar.plusButton.show();\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// 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 * Element.closest()\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/Element/closest\n */\nif (!Element.prototype.matches)\n Element.prototype.matches = Element.prototype.msMatchesSelector ||\n Element.prototype.webkitMatchesSelector;\n\nif (!Element.prototype.closest)\n Element.prototype.closest = function (s) {\n var el = this;\n\n if (!document.documentElement.contains(el)) return null;\n do {\n if (el.matches(s)) return el;\n el = el.parentElement || el.parentNode;\n } while (el !== null);\n return null;\n };\n","/**\n * Codex Editor Util\n */\nexport default class Util {\n /**\n * Custom logger\n *\n * @param {string} msg - message\n * @param {string} type - logging type 'log'|'warn'|'error'|'info'\n * @param {*} args - argument to log with a message\n */\n static log(msg, type, args) {\n type = type || 'log';\n\n if (!args) {\n args = msg || 'undefined';\n msg = '[codex-editor]: %o';\n } else {\n msg = '[codex-editor]: ' + msg;\n }\n\n try{\n if ( 'console' in window && window.console[ type ] ) {\n if ( args ) window.console[ type ]( msg, args );\n else window.console[ type ]( msg );\n }\n } catch(e) {\n // do nothing\n }\n }\n\n /**\n * Returns basic keycodes as constants\n * @return {{}}\n */\n static get keyCodes() {\n return {\n BACKSPACE: 8,\n TAB: 9,\n ENTER: 13,\n SHIFT: 16,\n CTRL: 17,\n ALT: 18,\n ESC: 27,\n SPACE: 32,\n LEFT: 37,\n UP: 38,\n DOWN: 40,\n RIGHT: 39,\n DELETE: 46,\n META: 91\n };\n }\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 return new Promise(function (resolve) {\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 return previousValue\n .then(() => waitNextBlock(currentValue, success, fallback))\n .then(() => {\n // finished\n if (iteration === chains.length - 1) {\n resolve();\n }\n });\n }, Promise.resolve());\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 return new Promise(function (resolve) {\n chainData.function()\n .then(() => {\n successCallback(chainData.data || {});\n })\n .then(resolve)\n .catch(function () {\n fallbackCallback(chainData.data || {});\n\n // anyway, go ahead even it falls\n resolve();\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 return Array.prototype.slice.call(collection);\n }\n\n /**\n * Checks if object is empty\n *\n * @param {Object} object\n * @return {boolean}\n */\n static isEmpty(object) {\n return Object.keys(object).length === 0 && object.constructor === Object;\n }\n\n /**\n * Check if passed object is a Promise\n * @param {*} object - object to check\n * @return {Boolean}\n */\n static isPromise(object) {\n return Promise.resolve(object) === object;\n }\n\n /**\n * Check if passed element is contenteditable\n * @param element\n * @return {boolean}\n */\n static isContentEditable(element) {\n return element.contentEditable === 'true';\n }\n\n /**\n * Delays method execution\n *\n * @param method\n * @param timeout\n */\n static delay(method, timeout) {\n return function () {\n let context = this,\n args = arguments;\n\n window.setTimeout(() => method.apply(context, args), timeout);\n };\n }\n};","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \":root {\\n\\n /**\\n * Toolbar buttons\\n */\\n --bg-light: #eff2f5;\\n\\n /**\\n * All gray texts: placeholders, settings\\n */\\n --grayText: #707684;\\n\\n /**\\n * Block content width\\n */\\n --content-width: 650px;\\n\\n /**\\n * Toolbar Plus Button and Toolbox buttons height and width\\n */\\n --toolbar-buttons-size: 34px\\n\\n}\\n/**\\n* Editor wrapper\\n*/\\n.codex-editor {\\n position: relative;\\n border: 1px solid #ccc;\\n padding: 2px;\\n box-sizing: border-box;\\n}\\n.codex-editor .hide {\\n display: none;\\n }\\n.codex-editor__redactor {\\n padding-bottom: 300px;\\n }\\n.ce-toolbar {\\n position: absolute;\\n left: 0;\\n right: 0;\\n top: 0;\\n /*opacity: 0;*/\\n /*visibility: hidden;*/\\n transition: opacity 100ms ease;\\n will-change: opacity, transform;\\n display: none;\\n}\\n.ce-toolbar--opened {\\n display: block;\\n /*opacity: 1;*/\\n /*visibility: visible;*/\\n }\\n.ce-toolbar__content {\\n max-width: 650px;\\n max-width: var(--content-width);\\n margin: 0 auto;\\n position: relative;\\n }\\n.ce-toolbar__plus {\\n position: absolute;\\n left: calc(-var(--toolbar-buttons-size) - 10px);\\n left: calc(-var(--toolbar-buttons-size) - 10px);\\n display: inline-block;\\n background-color: #eff2f5;\\n background-color: var(--bg-light);\\n width: 34px;\\n width: var(--toolbar-buttons-size);\\n height: 34px;\\n height: var(--toolbar-buttons-size);\\n line-height: 34px;\\n text-align: center;\\n border-radius: 50%\\n }\\n.ce-toolbar__plus::after {\\n content: '+';\\n font-size: 26px;\\n display: block;\\n margin-top: -2px;\\n margin-right: -2px;\\n }\\n.ce-toolbar__plus--hidden {\\n display: none;\\n }\\n/**\\n * Block actions Zone\\n * -------------------------\\n */\\n.ce-toolbar__actions {\\n position: absolute;\\n right: 0;\\n top: 0;\\n border: 1px dotted #ccc;\\n padding: 2px;\\n }\\n.ce-toolbar__actions-buttons {\\n border: 1px dotted #ccc;\\n padding: 2px;\\n text-align: right;\\n margin-bottom: 2px;\\n }\\n.ce-toolbar__settings-btn {\\n display: inline-block;\\n width: 24px;\\n height: 24px;\\n border: 1px dotted #ccc\\n }\\n.ce-toolbar__settings-btn::before {\\n content: 'STN';\\n font-size: 10px;\\n opacity: .4;\\n }\\n.ce-toolbox {\\n position: absolute;\\n visibility: hidden;\\n transition: opacity 100ms ease;\\n will-change: opacity;\\n}\\n.ce-toolbox--opened {\\n opacity: 1;\\n visibility: visible;\\n }\\n.ce-toolbox__button {\\n display: inline-block;\\n list-style: none;\\n margin: 0;\\n background: #eff2f5;\\n background: var(--bg-light);\\n width: 34px;\\n width: var(--toolbar-buttons-size);\\n height: 34px;\\n height: var(--toolbar-buttons-size);\\n border-radius: 30px;\\n overflow: hidden;\\n text-align: center;\\n line-height: 34px;\\n line-height: var(--toolbar-buttons-size)\\n }\\n.ce-toolbox__button::before {\\n content: attr(title);\\n font-size: 22px;\\n font-weight: 500;\\n letter-spacing: 1em;\\n -webkit-font-feature-settings: \\\"smcp\\\", \\\"c2sc\\\";\\n font-feature-settings: \\\"smcp\\\", \\\"c2sc\\\";\\n font-variant-caps: all-small-caps;\\n padding-left: 11.5px;\\n margin-top: -1px;\\n display: inline-block;\\n }\\n.ce-inline-toolbar {\\n position: absolute;\\n z-index: 2;\\n background: #FFFFFF;\\n box-shadow: 0 8px 23px -6px rgba(21,40,54,0.31), 22px -14px 34px -18px rgba(33,48,73,0.26);\\n border-radius: 4px;\\n position: relative;\\n}\\n.ce-inline-toolbar::before {\\n content: '';\\n width: 15px;\\n height: 15px;\\n position: absolute;\\n top: -7px;\\n left: 50%;\\n margin-left: -7px;\\n transform: rotate(-45deg);\\n background: #fff;\\n }\\n.ce-inline-toolbar {\\n\\n width: 100px;\\n height: 40px;\\n}\\n.ce-settings {\\n border: 1px dotted #ccc;\\n padding: 2px;\\n display: none;\\n}\\n.ce-settings--opened {\\n display: block;\\n }\\n.ce-settings__plugin-zone {\\n border: 1px dotted #ccc;\\n padding: 2px;\\n margin-bottom: 2px\\n }\\n.ce-settings__plugin-zone::before {\\n content: 'PLUGIN SETTINGS';\\n opacity: .4;\\n font-size: 12px;\\n }\\n.ce-settings__default-zone {\\n border: 1px dotted #ccc;\\n padding: 2px\\n }\\n.ce-settings__default-zone::before {\\n content: 'DEFAULT SETTINGS';\\n opacity: .4;\\n font-size: 12px;\\n }\\n.ce-settings__button {\\n padding: 10px 15px;\\n color: #707684;\\n color: var(--grayText)\\n }\\n.ce-settings__button:hover {\\n background: #eff2f5;\\n background: var(--bg-light);\\n }\\n.ce-block {\\n border: 1px dotted #ccc;\\n margin: 2px 0\\n}\\n.ce-block:first-of-type {\\n margin-top: 0;\\n }\\n.ce-block--selected {\\n background-color: #eff2f5;\\n background-color: var(--bg-light);\\n }\\n.ce-block__content {\\n max-width: 650px;\\n max-width: var(--content-width);\\n margin: 0 auto;\\n }\\n\", \"\"]);\n\n// exports\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://CodexEditor/webpack/bootstrap","webpack://CodexEditor/./node_modules/css-loader/lib/css-base.js","webpack://CodexEditor/./node_modules/html-janitor/src/html-janitor.js","webpack://CodexEditor/./src/codex.js","webpack://CodexEditor/./src/components/__module.ts","webpack://CodexEditor/./src/components/block.js","webpack://CodexEditor/./src/components/dom.js","webpack://CodexEditor/./src/components/modules sync nonrecursive [^_](blockManager.js|caret.js|events.js|keyboard.js|listeners.js|renderer.js|sanitizer.js|saver.js|toolbar-blockSettings.js|toolbar-inline.ts|toolbar-toolbox.js|toolbar.js|tools.js|ui.js)$","webpack://CodexEditor/./src/components/modules/blockManager.js","webpack://CodexEditor/./src/components/modules/caret.js","webpack://CodexEditor/./src/components/modules/events.js","webpack://CodexEditor/./src/components/modules/keyboard.js","webpack://CodexEditor/./src/components/modules/listeners.js","webpack://CodexEditor/./src/components/modules/renderer.js","webpack://CodexEditor/./src/components/modules/sanitizer.js","webpack://CodexEditor/./src/components/modules/saver.js","webpack://CodexEditor/./src/components/modules/toolbar-blockSettings.js","webpack://CodexEditor/./src/components/modules/toolbar-inline.ts","webpack://CodexEditor/./src/components/modules/toolbar-toolbox.js","webpack://CodexEditor/./src/components/modules/toolbar.js","webpack://CodexEditor/./src/components/modules/tools.js","webpack://CodexEditor/./src/components/modules/ui.js","webpack://CodexEditor/./src/components/polyfills.js","webpack://CodexEditor/./src/components/selection.js","webpack://CodexEditor/./src/components/utils.js","webpack://CodexEditor/./src/styles/main.css"],"names":["modules","editorModules","map","module","CodexEditor","config","moduleInstances","Promise","resolve","then","configuration","init","start","console","log","catch","error","constructModules","configureModules","forEach","Module","displayName","e","name","state","getModulesDiff","diff","moduleName","prepareDecorator","prepare","Tools","UI","BlockManager","Renderer","render","data","items","initialBlock","type","holderId","placeholder","sanitizer","p","b","a","hideToolbar","tools","toolsConfig","_","isEmpty","length","Editor","new","target","TypeError","Block","toolName","toolInstance","tool","_html","compose","wrapper","$","make","CSS","contentNode","content","pluginsContent","appendChild","methodName","params","Function","call","merge","extractedBlock","save","measuringStart","window","performance","now","measuringEnd","finishedExtraction","time","isValid","validate","contentless","emptyText","emptyMedia","hasMedia","mediaTags","querySelector","join","classList","add","selected","remove","Dom","tag","tagName","includes","classNames","attributes","el","document","createElement","Array","isArray","attrName","createTextNode","parent","elements","selector","querySelectorAll","node","atLast","child","sibling","nodeType","Node","ELEMENT_NODE","nodeChild","isSingleTag","parentNode","getDeepestNode","nativeInputs","nodeText","isElement","isNativeInput","value","textContent","replace","trim","childNodes","treeWalker","leafs","isNodeEmpty","push","firstChild","shift","isLeaf","nextSibling","every","leaf","_blocks","currentBlockIndex","blocks","Blocks","nodes","redactor","Proxy","set","get","construct","block","bindEvents","Listeners","on","event","Keyboard","blockKeydownsListener","InlineToolbar","handleShowingEvent","caretAtEnd","Caret","isAtEnd","nextBlock","setToBlock","caretAtStart","isAtStart","previousBlock","composeBlock","targetBlock","blockToMerge","blockToMergeIndex","indexOf","blockToMergeInfo","mergeWith","removeBlock","index","extractedFragment","extractFragmentFromCaretPosition","append","text","innerHTML","insert","element","firstLevelBlock","closest","childNode","parentFirstLevelBlock","currentNode","Error","isLastBlock","isFirstBlock","array","currentBlock","workingArea","html","deleteCount","splice","insertAdjacentElement","newBlock","children","instance","isNaN","Number","offset","atEnd","focus","nodeToSet","delay","range","createRange","selection","Selection","setStart","setEnd","removeAllRanges","addRange","lastBlock","rangeCount","selectRange","getRangeAt","blockElem","deleteContents","cloneRange","selectNodeContents","endContainer","endOffset","extractContents","from","direction","current","siblings","contentEditable","isCollapsed","anchorNode","firstNode","firstLetterPosition","search","leftSiblings","getHigherLevelSiblings","nothingAtLeft","anchorOffset","lastNode","nothingAtRight","Events","subscribers","eventName","callback","reduce","previousData","currentHandler","newData","keyCode","keyCodes","BACKSPACE","backspacePressed","ENTER","enterPressed","DOWN","RIGHT","arrowRightAndDownPressed","UP","LEFT","arrowLeftAndUpPressed","apiSettings","IS_ENABLED_LINE_BREAKS","shiftKey","split","preventDefault","BM","canMergeBlocks","getBlockByIndex","mergeable","navigatePrevious","setCaretToTheEnd","mergeBlocks","setTimeout","Toolbar","close","navigateNext","allListeners","eventType","handler","useCapture","assignedEventData","alreadyExist","findOne","addEventListener","existingListeners","findAll","i","removeEventListener","listenersOnElement","listener","listenersWithType","listenersWithHandler","foundListeners","found","foundByElements","findByElement","filter","chainData","function","insertBlock","sequence","item","Sanitizer","defaultConfig","_sanitizerInstance","sanitizerConfig","settings","sanitizerInstance","require","taintString","customConfig","clean","library","tags","href","rel","newInstance","Saver","output","blocksData","all","allExtractedData","makeOutput","outputData","totalTime","groupCollapsed","extraction","groupEnd","Date","version","VERSION","BlockSettings","toolSettings","defaultSettings","buttonRemove","addDefaultSettings","button","removeBlockButtonClicked","wrapperOpened","addToolSettings","contains","inlineToolbar","inlineToolbarShowed","toolbarVerticalMargin","allowedToShow","move","open","selectionRect","rect","wrapperOffset","getBoundingClientRect","newCoords","x","left","y","height","top","width","Math","floor","style","tagsConflictsWithSelection","currentSelection","selectedText","getBlock","toolConfig","IS_ENABLED_INLINE_TOOLBAR","Toolbox","toolbox","buttons","opened","addTools","toolsAvailable","addTool","api","IS_DISPLAYED_IN_TOOLBOX","TOOLBAR_ICON_CLASS","toolboxButton","title","dataset","buttonClicked","toolButton","toolClasses","IS_IRREPLACEBLE_TOOL","toolboxOpened","actions","plusButton","blockActionsButtons","settingsToggler","toolbar","plusButtonClicked","defaultToolbarHeight","defaultOffset","newYCoordinate","offsetTop","transform","toolbarOpened","toggle","settingsTogglerClicked","hide","plusButtonHidden","show","toolsUnavailable","hasOwnProperty","reject","sequenceData","getListOfPrepareFunctions","success","fallback","toolPreparationList","toolClass","plugin","available","holder","loadStyles","getElementById","editorWrapper","editorZone","styles","toString","head","redactorClicked","clickedNode","setCurrentBlockByChildNode","setToTheLastBlock","isInitialBlock","isInitial","isEmptyBlock","Element","prototype","matches","msMatchesSelector","webkitMatchesSelector","s","documentElement","parentElement","getSelection","sel","boundingLeft","boundingTop","boundingWidth","boundingHeight","span","insertNode","spanParent","removeChild","normalize","Util","msg","args","chains","previousValue","currentValue","iteration","waitNextBlock","successCallback","fallbackCallback","collection","slice","object","Object","keys","constructor","method","timeout","context","arguments","apply","TAB","SHIFT","CTRL","ALT","ESC","SPACE","DELETE","META"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;AClFA;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;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AACA,GAAG,QAIH;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;;A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AOgC,YAAZ,EAA0B;AACxB,aAAK,KAAKhC,MAAL,CAAYgC,YAAjB,IAAiC,KAAKhC,MAAL,CAAYyC,KAA7C;AAAoD;AAApD;AACD,OAFD,MAEO;AACL,aAAKzC,MAAL,CAAYgC,YAAZ,GAA2BhC,OAAOgC,YAAlC;AACD;AACF;;AAED;;;;;wBAIoB;AAClB,aAAO,KAAKhC,MAAZ;AACD;;;;;;;kBArGkBD,W;AAgMpB;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;ACrYA;;;;;;;;;IASqBgB,M;AACjB;;;;;AAKA,wBAAwB;AAAA,QAAVf,MAAU,QAAVA,MAAU;;AAAA;;AACpB;;;;AAIA,SAAK8C,MAAL,GAAc,IAAd;AACA;;;;AAIA,SAAK9C,MAAL,GAAc,EAAd;AACA,QAAI+C,IAAIC,MAAJ,KAAejC,MAAnB,EAA2B;AACvB,YAAM,IAAIkC,SAAJ,CAAc,yDAAd,CAAN;AACH;AACD,SAAKjD,MAAL,GAAcA,MAAd;AACH;AACD;;;;;;;;;;;sBAOU8C,M,EAAQ;AACd,WAAKA,MAAL,GAAcA,MAAd;AACH;;;;;;;kBA/BgB/B,M;;;;;;;;;;;;;;;;;;;;;;;ACTrB;;;;;;;;;;AAUA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S,eAAUA,KAFL;AAGL2S,iBAAU,OAAAC;AAHL,OAAP;AAKD;;;;EAzDgC5T,M;;AA4DnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;kBAzNqB+S,K;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvBrB;;;;;;;;;;;IAWqBc,a;;;AACnB,+BAAsB;AAAA,QAAT5U,MAAS,QAATA,MAAS;;AAAA;;AAAA,8HACd,EAACA,cAAD,EADc;;AAGpB,UAAK8I,KAAL,GAAa;AACXtF,eAAS,IADE;AAEXqR,oBAAc,IAFH;AAGXC,uBAAiB,IAHN;AAIXC,oBAAc;AAJH,KAAb;AAHoB;AASrB;;AAED;;;;;;;;;;AAgBA;;;;;;;2BAOO;AACL,WAAKjM,KAAL,CAAWtF,OAAX,GAAqBC,EAAEC,IAAF,CAAO,KAAP,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AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA,WAAK1G,MAAL,CAAYoO,OAAZ,CAAoBwE,IAApB;AACA,WAAK5S,MAAL,CAAYoO,OAAZ,CAAoByE,IAApB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AAGA,WAAK7S,MAAL,CAAYoO,OAAZ,CAAoBiH,UAApB,CAA+Ba,IAA/B;;AAEA;;;;;AAKA,UAAI0B,iBAAiB,KAAK5X,MAAL,CAAYrB,KAAZ,CAAkBkZ,SAAlB,CAA4B,KAAK7X,MAAL,CAAYnB,YAAZ,CAAyBmK,YAAzB,CAAsCzI,IAAlE,CAArB;AAAA,UACEuX,eAAe,KAAK9X,MAAL,CAAYnB,YAAZ,CAAyBmK,YAAzB,CAAsClJ,OADvD;;AAGA,UAAI8X,kBAAkBE,YAAtB,EAAoC;AAClC,aAAK9X,MAAL,CAAYoO,OAAZ,CAAoBiH,UAApB,CAA+Be,IAA/B;AACD;AACF;;;wBA5MS;AACR,aAAO;AACLe,uBAAgB,cADX;AAELC,oBAAgB;AAFX,OAAP;AAID;;;;EAlE6BnZ,M;;AA4QhC;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;;;;kBAjeqBW,E;;;;;;;;;;;;;;;;ACrDrB;;;;;AAKA,IAAI,CAACmZ,QAAQC,SAAR,CAAkBC,OAAvB,EACEF,QAAQC,SAAR,CAAkBC,OAAlB,GAA4BF,QAAQC,SAAR,CAAkBE,iBAAlB,IACtBH,QAAQC,SAAR,CAAkBG,qBADxB;;AAGF,IAAI,CAACJ,QAAQC,SAAR,CAAkBxP,OAAvB,EACEuP,QAAQC,SAAR,CAAkBxP,OAAlB,GAA4B,UAAU4P,CAAV,EAAa;AACvC,MAAIjV,KAAK,IAAT;;AAEA,MAAI,CAACC,SAASiV,eAAT,CAAyB9F,QAAzB,CAAkCpP,EAAlC,CAAL,EAA4C,OAAO,IAAP;AAC5C,KAAG;AACD,QAAIA,GAAG8U,OAAH,CAAWG,CAAX,CAAJ,EAAmB,OAAOjV,EAAP;AACnBA,SAAKA,GAAGmV,aAAH,IAAoBnV,GAAGoB,UAA5B;AACD,GAHD,QAGSpB,OAAO,IAHhB;AAIA,SAAO,IAAP;AACD,CATD,C;;;;;;;;;;;;;;;;;;;;;;ACVF;;;;IAIqBgH,S;AACnB;;;AAGA,uBAAc;AAAA;;AACZ,SAAK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","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, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\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\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/codex.js\");\n","/*\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","(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 * 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 : 'text',\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 * @property {Object} tools - Map for used Tools in format { name : Class, ... }\n * @property {String} initialBlock - This Tool will be added by default\n * @property {String} placeholder - First Block placeholder\n * @property {Object} sanitizer - @todo fill desc\n * @property {Boolean} hideToolbar - @todo fill desc\n * @property {Object} toolsConfig - tools configuration {@link tools#ToolConfig}\n */\n\n/**\n * Dynamically imported utils\n *\n * @typedef {Dom} $ - {@link components/dom.js}\n * @typedef {Util} _ - {@link components/utils.js}\n */\n\n'use strict';\n\n/**\n * Apply polyfills\n */\nimport 'components/polyfills';\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 */\nexport default class CodexEditor {\n /** Editor version */\n static get version() {\n return VERSION;\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n /**\n * Configuration object\n * @type {EditorConfig}\n */\n this.config = {};\n\n /**\n * @typedef {Object} EditorComponents\n * @property {BlockManager} BlockManager\n * @property {Tools} Tools\n * @property {Events} Events\n * @property {UI} UI\n * @property {Toolbar} Toolbar\n * @property {Toolbox} Toolbox\n * @property {BlockSettings} BlockSettings\n * @property {Renderer} Renderer\n * @property {InlineToolbar} InlineToolbar\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n this.configuration = config;\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n console.log('CodeX Editor is ready!');\n })\n .catch(error => {\n console.log('CodeX Editor does not ready because of %o', error);\n });\n }\n\n /**\n * Setting for configuration\n * @param {EditorConfig} config\n */\n set configuration(config) {\n /**\n * Initlai block type\n * Uses in case when there is no items passed\n * @type {{type: (*), data: {text: null}}}\n */\n let initialBlock = {\n type : config.initialBlock,\n data : {}\n };\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 * Initialize items to pass data to the Renderer\n */\n if (_.isEmpty(this.config.data)) {\n this.config.data = {};\n this.config.data.items = [ initialBlock ];\n } else {\n if (!this.config.data.items || this.config.data.items.length === 0) {\n this.config.data.items = [ initialBlock ];\n }\n }\n\n /**\n * If initial Block's Tool was not passed, use the first Tool in config.tools\n */\n if (!config.initialBlock) {\n for (this.config.initialBlock in this.config.tools) break;\n } else {\n this.config.initialBlock = config.initialBlock;\n }\n }\n\n /**\n * Returns private property\n * @returns {EditorConfig}\n */\n get configuration() {\n return this.config;\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\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 * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n modules.forEach( Module => {\n try {\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 this.moduleInstances[Module.displayName] = new Module({\n config : this.configuration\n });\n } catch ( e ) {\n console.log('Module %o skipped because %o', Module, e);\n }\n });\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n for(let name in this.moduleInstances) {\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n }\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n let diff = {};\n\n for(let moduleName in this.moduleInstances) {\n /**\n * Skip module with passed name\n */\n if (moduleName === name) {\n continue;\n }\n diff[moduleName] = this.moduleInstances[moduleName];\n }\n\n return diff;\n }\n\n /**\n * Start Editor!\n *\n * Get list of modules that needs to be prepared and return a sequence (Promise)\n * @return {Promise}\n */\n start() {\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances.Tools))\n .then(prepareDecorator(this.moduleInstances.UI))\n .then(prepareDecorator(this.moduleInstances.BlockManager))\n .then(() => {\n return this.moduleInstances.Renderer.render(this.config.data.items);\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 : ['text', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],\n// holderId : 'codex-editor',\n//\n// // Type of block showing on empty editor\n// initialBlockPlugin: 'text'\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 * @abstract\n * @class Module\n * @classdesc All modules inherits 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 * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({ config }) {\n /**\n * Editor modules list\n * @type {EditorComponents}\n */\n this.Editor = null;\n /**\n * Editor configuration object\n * @type {EditorConfig}\n */\n this.config = {};\n if (new.target === Module) {\n throw new TypeError('Constructors for abstract class Module are not allowed.');\n }\n this.config = config;\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 this.Editor = Editor;\n }\n}\n","/**\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/**\n * @classdesc Abstract Block class that contains Block information, Tool name and Tool class instance\n *\n * @property tool - Tool instance\n * @property html - Returns HTML content of plugin\n * @property wrapper - Div element that wraps block content with Tool's content. Has `ce-block` CSS class\n * @property contentNode - Div element that wraps Tool's content. Has `ce-block__content` CSS class\n * @property pluginsContent - HTML content that returns by Tool's render function\n */\nexport default class Block {\n /**\n * @constructor\n * @param {String} toolName - Tool name that passed on initialization\n * @param {Object} toolInstance — passed Tool`s instance that rendered the Block\n */\n constructor(toolName, toolInstance) {\n this.name = toolName;\n this.tool = toolInstance;\n this._html = this.compose();\n }\n\n /**\n * CSS classes for the Block\n * @return {{wrapper: string, content: string}}\n */\n static get CSS() {\n return {\n wrapper: 'ce-block',\n content: 'ce-block__content',\n selected: 'ce-block--selected'\n };\n }\n\n /**\n * Make default Block wrappers and put Tool`s content there\n * @returns {HTMLDivElement}\n */\n compose() {\n this.wrapper = $.make('div', Block.CSS.wrapper);\n this.contentNode = $.make('div', Block.CSS.content);\n this.pluginsContent = this.tool.render();\n\n this.contentNode.appendChild(this.pluginsContent);\n this.wrapper.appendChild(this.contentNode);\n\n return this.wrapper;\n }\n\n /**\n * Calls Tool's method\n *\n * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function\n *\n * @param {String} methodName\n * @param {Object} params\n */\n call(methodName, params) {\n /**\n * call Tool's method with the instance context\n */\n if (this.tool[methodName] && this.tool[methodName] instanceof Function) {\n this.tool[methodName].call(this.tool, params);\n }\n }\n\n /**\n * Get Block`s HTML\n * @returns {HTMLElement}\n */\n get html() {\n return this._html;\n }\n\n /**\n * Get Block's JSON data\n * @return {Object}\n */\n get data() {\n return this.save();\n }\n\n /**\n * is block mergeable\n * We plugin have merge function then we call it mergable\n * @return {boolean}\n */\n get mergeable() {\n return typeof this.tool.merge === 'function';\n }\n\n /**\n * Call plugins merge method\n * @param {Object} data\n */\n mergeWith(data) {\n return Promise.resolve()\n .then(() => {\n this.tool.merge(data);\n });\n }\n /**\n * Extracts data from Block\n * Groups Tool's save processing time\n * @return {Object}\n */\n save() {\n let extractedBlock = this.tool.save(this.pluginsContent);\n\n /** Measuring execution time*/\n let measuringStart = window.performance.now(),\n measuringEnd;\n\n return Promise.resolve(extractedBlock)\n .then((finishedExtraction) => {\n /** measure promise execution */\n measuringEnd = window.performance.now();\n\n return {\n tool: this.name,\n data: finishedExtraction,\n time : measuringEnd - measuringStart\n };\n })\n .catch(function (error) {\n _.log(`Saving proccess for ${this.tool.name} tool failed due to the ${error}`, 'log', 'red');\n });\n }\n\n /**\n * Uses Tool's validation method to check the correctness of output data\n * Tool's validation method is optional\n *\n * @description Method also can return data if it passed the validation\n *\n * @param {Object} data\n * @returns {Boolean|Object} valid\n */\n validateData(data) {\n let isValid = true;\n\n if (this.tool.validate instanceof Function) {\n isValid = this.tool.validate(data);\n }\n\n if (!isValid) {\n return false;\n }\n\n return data;\n }\n\n /**\n * Check block for emptiness\n * @return {Boolean}\n */\n get isEmpty() {\n /**\n * Allow Tool to represent decorative contentless blocks: for example \"* * *\"-tool\n * That Tools are not empty\n */\n if (this.tool.contentless) {\n return false;\n }\n\n let emptyText = $.isEmpty(this.pluginsContent),\n emptyMedia = !this.hasMedia;\n\n return emptyText && emptyMedia;\n }\n\n /**\n * Check if block has a media content such as images, iframes and other\n * @return {Boolean}\n */\n get hasMedia() {\n /**\n * This tags represents media-content\n * @type {string[]}\n */\n const mediaTags = [\n 'img',\n 'iframe',\n 'video',\n 'audio',\n 'source',\n 'input',\n 'textarea',\n 'twitterwidget'\n ];\n\n return !!this._html.querySelector(mediaTags.join(','));\n }\n\n /**\n * Set selected state\n * @param {Boolean} state - 'true' to select, 'false' to remove selection\n */\n set selected(state) {\n /**\n * We don't need to mark Block as Selected when it is not empty\n */\n if (state === true && !this.isEmpty) {\n this._html.classList.add(Block.CSS.selected);\n } else {\n this._html.classList.remove(Block.CSS.selected);\n }\n }\n}\n","/**\n * DOM manipulations helper\n */\nexport default class Dom {\n /**\n * Check if passed tag has no closed tag\n * @param {Element} tag\n * @return {Boolean}\n */\n static isSingleTag(tag) {\n return tag.tagName && ['AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR'].includes(tag.tagName);\n };\n\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 let el = document.createElement(tagName);\n\n if ( Array.isArray(classNames) ) {\n el.classList.add(...classNames);\n } else if( classNames ) {\n el.classList.add(classNames);\n }\n\n for (let attrName in attributes) {\n el[attrName] = attributes[attrName];\n }\n\n return el;\n }\n\n /**\n * Creates Text Node with the passed content\n * @param {String} content - text content\n * @return {Text}\n */\n static text(content) {\n return document.createTextNode(content);\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 if ( Array.isArray(elements) ) {\n elements.forEach( el => parent.appendChild(el) );\n } else {\n parent.appendChild(elements);\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 return el.querySelector(selector);\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 return el.querySelectorAll(selector);\n }\n\n /**\n * Search for deepest node which is Leaf.\n * Leaf is the vertex that doesn't have any child nodes\n *\n * @description Method recursively goes throw the all Node until it finds the Leaf\n *\n * @param {Node} node - root Node. From this vertex we start Deep-first search {@link https://en.wikipedia.org/wiki/Depth-first_search}\n * @param {Boolean} atLast - find last text node\n * @return {Node} - it can be text Node or Element Node, so that caret will able to work with it\n */\n static getDeepestNode(node, atLast = false) {\n /**\n * Current function have two directions:\n * - starts from first child and every time gets first or nextSibling in special cases\n * - starts from last child and gets last or previousSibling\n * @type {string}\n */\n let child = atLast ? 'lastChild' : 'firstChild',\n sibling = atLast ? 'previousSibling' : 'nextSibling';\n\n if (node && node.nodeType === Node.ELEMENT_NODE && node[child]) {\n let nodeChild = node[child];\n\n /**\n * special case when child is single tag that can't contain any content\n */\n if (Dom.isSingleTag(nodeChild)) {\n /**\n * 1) We need to check the next sibling. If it is Node Element then continue searching for deepest\n * from sibling\n *\n * 2) If single tag's next sibling is null, then go back to parent and check his sibling\n * In case of Node Element continue searching\n *\n * 3) If none of conditions above happened return parent Node Element\n */\n if (nodeChild[sibling]) {\n nodeChild = nodeChild[sibling];\n } else if (nodeChild.parentNode[sibling]) {\n nodeChild = nodeChild.parentNode[sibling];\n } else {\n return nodeChild.parentNode;\n }\n }\n\n return this.getDeepestNode(nodeChild, atLast);\n }\n\n return node;\n }\n\n /**\n * Check if object is DOM node\n *\n * @param {Object} node\n * @returns {boolean}\n */\n static isElement(node) {\n return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.ELEMENT_NODE;\n }\n\n /**\n * Checks target if it is native input\n * @param {Element|String} target - HTML element or string\n * @return {Boolean}\n */\n static isNativeInput(target) {\n let nativeInputs = [\n 'INPUT',\n 'TEXTAREA'\n ];\n\n return target ? nativeInputs.includes(target.tagName) : false;\n }\n\n /**\n * Checks node if it is empty\n *\n * @description Method checks simple Node without any childs for emptiness\n * If you have Node with 2 or more children id depth, you better use {@link Dom#isEmpty} method\n *\n * @param {Node} node\n * @return {Boolean} true if it is empty\n */\n static isNodeEmpty(node) {\n let nodeText;\n\n if ( this.isElement(node) && this.isNativeInput(node) ) {\n nodeText = node.value;\n } else {\n nodeText = node.textContent.replace('\\u200B', '');\n }\n\n return nodeText.trim().length === 0;\n }\n\n /**\n * checks node if it is doesn't have any child nodes\n * @param {Node} node\n * @return {boolean}\n */\n static isLeaf(node) {\n if (!node) {\n return false;\n }\n\n return node.childNodes.length === 0;\n }\n\n /**\n * breadth-first search (BFS)\n * {@link https://en.wikipedia.org/wiki/Breadth-first_search}\n *\n * @description Pushes to stack all DOM leafs and checks for emptiness\n *\n * @param {Node} node\n * @return {boolean}\n */\n static isEmpty(node) {\n let treeWalker = [],\n leafs = [];\n\n if (!node) {\n return true;\n }\n\n if (!node.childNodes.length) {\n return this.isNodeEmpty(node);\n }\n\n treeWalker.push(node.firstChild);\n\n while ( treeWalker.length > 0 ) {\n node = treeWalker.shift();\n\n if (!node) continue;\n\n if ( this.isLeaf(node) ) {\n leafs.push(node);\n } else {\n treeWalker.push(node.firstChild);\n }\n\n while ( node && node.nextSibling ) {\n node = node.nextSibling;\n\n if (!node) continue;\n\n treeWalker.push(node);\n }\n\n /**\n * If one of childs is not empty, checked Node is not empty too\n */\n if (node && !this.isNodeEmpty(node)) {\n return false;\n }\n }\n\n return leafs.every( leaf => this.isNodeEmpty(leaf) );\n }\n};","var map = {\n\t\"./blockManager.js\": \"./src/components/modules/blockManager.js\",\n\t\"./caret.js\": \"./src/components/modules/caret.js\",\n\t\"./events.js\": \"./src/components/modules/events.js\",\n\t\"./keyboard.js\": \"./src/components/modules/keyboard.js\",\n\t\"./listeners.js\": \"./src/components/modules/listeners.js\",\n\t\"./renderer.js\": \"./src/components/modules/renderer.js\",\n\t\"./sanitizer.js\": \"./src/components/modules/sanitizer.js\",\n\t\"./saver.js\": \"./src/components/modules/saver.js\",\n\t\"./toolbar-blockSettings.js\": \"./src/components/modules/toolbar-blockSettings.js\",\n\t\"./toolbar-inline.ts\": \"./src/components/modules/toolbar-inline.ts\",\n\t\"./toolbar-toolbox.js\": \"./src/components/modules/toolbar-toolbox.js\",\n\t\"./toolbar.js\": \"./src/components/modules/toolbar.js\",\n\t\"./tools.js\": \"./src/components/modules/tools.js\",\n\t\"./ui.js\": \"./src/components/modules/ui.js\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) { // check for number or string\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn id;\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"./src/components/modules sync [^_](blockManager.js|caret.js|events.js|keyboard.js|listeners.js|renderer.js|sanitizer.js|saver.js|toolbar-blockSettings.js|toolbar-inline.ts|toolbar-toolbox.js|toolbar.js|tools.js|ui.js)$\";","/**\n * @class BlockManager\n * @classdesc Manage editor`s blocks storage and appearance\n *\n * @module BlockManager\n *\n * @version 2.0.0\n */\n\nimport Block from '../block';\n\n/**\n * @typedef {BlockManager} BlockManager\n * @property {Number} currentBlockIndex - Index of current working block\n * @property {Proxy} _blocks - Proxy for Blocks instance {@link Blocks}\n */\nexport default class BlockManager extends Module {\n /**\n * @constructor\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\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 * Should be called after Editor.UI preparation\n * Define this._blocks property\n *\n * @returns {Promise}\n */\n prepare() {\n return new Promise(resolve => {\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 * Creates Block instance by tool name\n *\n * @param {String} toolName - tools passed in editor config {@link EditorConfig#tools}\n * @param {Object} data - constructor params\n *\n * @return {Block}\n */\n composeBlock(toolName, data) {\n let toolInstance = this.Editor.Tools.construct(toolName, data),\n block = new Block(toolName, toolInstance);\n\n this.bindEvents(block);\n\n /**\n * Apply callback before inserting html\n */\n block.call('appendCallback', {});\n\n return block;\n }\n\n /**\n * Bind Events\n * @param {Object} block\n */\n bindEvents(block) {\n this.Editor.Listeners.on(block.pluginsContent, 'keydown', (event) => this.Editor.Keyboard.blockKeydownsListener(event));\n this.Editor.Listeners.on(block.pluginsContent, 'mouseup', (event) => {\n this.Editor.InlineToolbar.handleShowingEvent(event);\n });\n }\n\n /**\n * Set's caret to the next Block\n * Before moving caret, we should check if caret position is at the end of Plugins node\n * Using {@link Dom#getDeepestNode} to get a last node and match with current selection\n */\n navigateNext() {\n let caretAtEnd = this.Editor.Caret.isAtEnd;\n\n if (!caretAtEnd) {\n return;\n }\n\n let nextBlock = this.nextBlock;\n\n if (!nextBlock) {\n return;\n }\n\n this.Editor.Caret.setToBlock( nextBlock );\n }\n\n /**\n * Set's caret to the previous Block\n * Before moving caret, we should check if caret position is start of the Plugins node\n * Using {@link Dom#getDeepestNode} to get a last node and match with current selection\n */\n navigatePrevious() {\n let caretAtStart = this.Editor.Caret.isAtStart;\n\n if (!caretAtStart) {\n return;\n }\n\n let previousBlock = this.previousBlock;\n\n if (!previousBlock) {\n return;\n }\n\n this.Editor.Caret.setToBlock( previousBlock, 0, true );\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 let block = this.composeBlock(toolName, data);\n\n this._blocks[++this.currentBlockIndex] = block;\n this.Editor.Caret.setToBlock(block);\n }\n\n /**\n * Merge two blocks\n * @param {Block} targetBlock - previous block will be append to this block\n * @param {Block} blockToMerge - block that will be merged with target block\n *\n * @return {Promise} - the sequence that can be continued\n */\n mergeBlocks(targetBlock, blockToMerge) {\n let blockToMergeIndex = this._blocks.indexOf(blockToMerge);\n\n return Promise.resolve()\n .then( () => {\n if (blockToMerge.isEmpty) {\n return;\n }\n\n return blockToMerge.data\n .then((blockToMergeInfo) => {\n targetBlock.mergeWith(blockToMergeInfo.data);\n });\n })\n .then( () => {\n this.removeBlock(blockToMergeIndex);\n this.currentBlockIndex = this._blocks.indexOf(targetBlock);\n });\n }\n\n /**\n * Remove block with passed index or remove last\n * @param {Number|null} index\n */\n removeBlock(index) {\n this._blocks.remove(index);\n }\n /**\n * Split current Block\n * 1. Extract content from Caret position to the Block`s end\n * 2. Insert a new Block below current one with extracted content\n */\n split() {\n let extractedFragment = this.Editor.Caret.extractFragmentFromCaretPosition(),\n wrapper = $.make('div');\n\n wrapper.append(extractedFragment);\n\n /**\n * @todo make object in accordance with Tool\n */\n let data = {\n text: $.isEmpty(wrapper) ? '' : wrapper.innerHTML,\n };\n\n this.insert(this.config.initialBlock, data);\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 let block = this.composeBlock(toolName, data);\n\n this._blocks.insert(this.currentBlockIndex, block, true);\n }\n\n /**\n * returns last Block\n * @return {Block}\n */\n get lastBlock() {\n return this._blocks[this._blocks.length - 1];\n }\n\n /**\n * Returns Block by passed index\n * @param {Number} index\n * @return {Block}\n */\n getBlockByIndex(index) {\n return this._blocks[index];\n }\n\n /**\n * Get Block instance by html element\n * @param {Node} element\n * @returns {Block}\n */\n getBlock(element) {\n if (!$.isElement(element)) {\n element = element.parentNode;\n }\n\n let nodes = this._blocks.nodes,\n firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`),\n index = nodes.indexOf(firstLevelBlock);\n\n if (index >= 0) {\n return this._blocks[index];\n }\n }\n\n /**\n * Get current Block instance\n *\n * @return {Block}\n */\n get currentBlock() {\n return this._blocks[this.currentBlockIndex];\n }\n\n /**\n * Returns next Block instance\n * @return {Block|null}\n */\n get nextBlock() {\n let isLastBlock = this.currentBlockIndex === (this._blocks.length - 1);\n\n if (isLastBlock) {\n return null;\n }\n\n return this._blocks[this.currentBlockIndex + 1];\n }\n\n /**\n * Returns previous Block instance\n * @return {Block|null}\n */\n get previousBlock() {\n let isFirstBlock = this.currentBlockIndex === 0;\n\n if (isFirstBlock) {\n return null;\n }\n\n return this._blocks[this.currentBlockIndex - 1];\n }\n\n /**\n * Get working html element\n *\n * @return {HTMLElement}\n */\n get currentNode() {\n return this._blocks.nodes[this.currentBlockIndex];\n }\n\n /**\n * Set currentBlockIndex to passed block\n * @param {HTMLElement} element\n */\n set currentNode(element) {\n let nodes = this._blocks.nodes,\n firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`);\n\n /**\n * Update current Block's index\n * @type {number}\n */\n this.currentBlockIndex = nodes.indexOf(firstLevelBlock);\n\n /**\n * Remove previous selected Block's state\n */\n this._blocks.array.forEach( block => block.selected = false);\n\n /**\n * Mark current Block as selected\n * @type {boolean}\n */\n this.currentBlock.selected = true;\n }\n\n /**\n * Get array of Block instances\n *\n * @returns {Block[]} {@link Blocks#array}\n */\n get blocks() {\n return this._blocks.array;\n }\n\n /**\n * 1) Find first-level Block from passed child Node\n * 2) Mark it as current\n *\n * @param {Element|Text} childNode - look ahead from this node.\n * @throws Error - when passed Node is not included at the Block\n */\n setCurrentBlockByChildNode(childNode) {\n /**\n * If node is Text TextNode\n */\n if (!$.isElement(childNode)) {\n childNode = childNode.parentNode;\n }\n\n let parentFirstLevelBlock = childNode.closest(`.${Block.CSS.wrapper}`);\n\n if (parentFirstLevelBlock) {\n this.currentNode = parentFirstLevelBlock;\n } else {\n throw new Error('Can not find a Block from this child Node');\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 * @constructor\n *\n * @param {HTMLElement} workingArea — editor`s working node\n */\n constructor(workingArea) {\n this.blocks = [];\n this.workingArea = workingArea;\n }\n\n /**\n * Push back new Block\n *\n * @param {Block} block\n */\n push(block) {\n this.blocks.push(block);\n this.workingArea.appendChild(block.html);\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 if (!this.length) {\n this.push(block);\n return;\n }\n\n if (index > this.length) {\n index = this.length;\n }\n\n if (replace) {\n this.blocks[index].html.remove();\n }\n\n let deleteCount = replace ? 1 : 0;\n\n this.blocks.splice(index, deleteCount, block);\n\n if (index > 0) {\n let previousBlock = this.blocks[index - 1];\n\n previousBlock.html.insertAdjacentElement('afterend', block.html);\n } else {\n let nextBlock = this.blocks[index + 1];\n\n if (nextBlock) {\n nextBlock.html.insertAdjacentElement('beforebegin', block.html);\n } else {\n this.workingArea.appendChild(block.html);\n }\n }\n }\n\n /**\n * Remove block\n * @param {Number|null} index\n */\n remove(index) {\n if (!index) {\n index = this.length - 1;\n }\n\n this.blocks[index].html.remove();\n this.blocks.splice(index, 1);\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 let index = this.blocks.indexOf(targetBlock);\n\n this.insert(index + 1, newBlock);\n }\n\n /**\n * Get Block by index\n *\n * @param {Number} index — Block index\n * @returns {Block}\n */\n get(index) {\n return this.blocks[index];\n }\n\n /**\n * Return index of passed Block\n *\n * @param {Block} block\n * @returns {Number}\n */\n indexOf(block) {\n return this.blocks.indexOf(block);\n }\n\n /**\n * Get length of Block instances array\n *\n * @returns {Number}\n */\n get length() {\n return this.blocks.length;\n }\n\n /**\n * Get Block instances array\n *\n * @returns {Block[]}\n */\n get array() {\n return this.blocks;\n }\n\n /**\n * Get blocks html elements array\n *\n * @returns {HTMLElement[]}\n */\n get nodes() {\n return _.array(this.workingArea.children);\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 if (isNaN(Number(index))) {\n return false;\n }\n\n instance.insert(index, block);\n\n return true;\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 if (isNaN(Number(index))) {\n return instance[index];\n }\n\n return instance.get(index);\n }\n}\n","/**\n * @class Caret\n * @classdesc Contains methods for working Caret\n *\n * Uses Range methods to manipulate with caret\n *\n * @module Caret\n *\n * @version 2.0.0\n */\n\nimport Selection from '../selection';\n\n/**\n * @typedef {Caret} Caret\n */\nexport default class Caret extends Module {\n /**\n * @constructor\n */\n constructor({config}) {\n super({config});\n }\n\n /**\n * Method gets Block instance and puts caret to the text node with offset\n * There two ways that method applies caret position:\n * - first found text node: sets at the beginning, but you can pass an offset\n * - last found text node: sets at the end of the node. Also, you can customize the behaviour\n *\n * @param {Block} block - Block class\n * @param {Number} offset - caret offset regarding to the text node\n * @param {Boolean} atEnd - put caret at the end of the text node or not\n */\n setToBlock(block, offset = 0, atEnd = false) {\n let element = block.pluginsContent;\n\n /** If Element is INPUT */\n if ($.isNativeInput(element)) {\n element.focus();\n return;\n }\n\n let nodeToSet = $.getDeepestNode(element, atEnd);\n\n if (atEnd || offset > nodeToSet.length) {\n offset = nodeToSet.length;\n }\n\n /** if found deepest node is native input */\n if ($.isNativeInput(nodeToSet)) {\n nodeToSet.focus();\n return;\n }\n\n /**\n * @todo try to fix via Promises or use querySelectorAll to not to use timeout\n */\n _.delay( () => {\n this.set(nodeToSet, offset);\n }, 20)();\n\n this.Editor.BlockManager.currentNode = block.wrapper;\n }\n\n /**\n * Creates Document Range and sets caret to the element with offset\n * @param {Element} element - target node.\n * @param {Number} offset - offset\n */\n set( element, offset = 0) {\n let range = document.createRange(),\n selection = Selection.get();\n\n range.setStart(element, offset);\n range.setEnd(element, offset);\n\n selection.removeAllRanges();\n selection.addRange(range);\n };\n\n /**\n * Set Caret to the last Block\n * If last block is not empty, append another empty block\n */\n setToTheLastBlock() {\n let lastBlock = this.Editor.BlockManager.lastBlock;\n\n if (!lastBlock) return;\n\n /**\n * If last block is empty and it is an initialBlock, set to that.\n * Otherwise, append new empty block and set to that\n */\n if (lastBlock.isEmpty) {\n this.setToBlock(lastBlock);\n } else {\n this.Editor.BlockManager.insert(this.config.initialBlock);\n }\n }\n\n /**\n * Extract content fragment of current Block from Caret position to the end of the Block\n */\n extractFragmentFromCaretPosition() {\n let selection = Selection.get();\n\n if (selection.rangeCount) {\n let selectRange = selection.getRangeAt(0),\n blockElem = this.Editor.BlockManager.currentBlock.pluginsContent;\n\n selectRange.deleteContents();\n\n if (blockElem) {\n let range = selectRange.cloneRange(true);\n\n range.selectNodeContents(blockElem);\n range.setStart(selectRange.endContainer, selectRange.endOffset);\n return range.extractContents();\n }\n }\n }\n\n /**\n * Get all first-level (first child of [contenteditabel]) siblings from passed node\n * Then you can check it for emptiness\n *\n * @example\n *

    \n *

    |\n *

    | left first-level siblings\n *

    |\n *
    adaddad
    <-- passed node for example \n *

    |\n *

    | right first-level siblings\n *

    |\n *
    \n *\n * @return {Element[]}\n */\n getHigherLevelSiblings(from, direction ) {\n let current = from,\n siblings = [];\n\n /**\n * Find passed node's firs-level parent (in example - blockquote)\n */\n while (current.parentNode && current.parentNode.contentEditable !== 'true') {\n current = current.parentNode;\n }\n\n let sibling = direction === 'left' ? 'previousSibling' : 'nextSibling';\n\n /**\n * Find all left/right siblings\n */\n while (current[sibling]) {\n current = current[sibling];\n siblings.push(current);\n }\n\n return siblings;\n }\n\n /**\n * Get's deepest first node and checks if offset is zero\n * @return {boolean}\n */\n get isAtStart() {\n /**\n * Don't handle ranges\n */\n if (!Selection.isCollapsed) {\n return false;\n }\n\n let selection = Selection.get(),\n anchorNode = selection.anchorNode,\n firstNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent);\n\n /**\n * Workaround case when caret in the text like \" |Hello!\"\n * selection.anchorOffset is 1, but real caret visible position is 0\n * @type {number}\n */\n let firstLetterPosition = anchorNode.textContent.search(/\\S/);\n\n if (firstLetterPosition === -1) { // empty text\n firstLetterPosition = 0;\n }\n\n /**\n * In case of\n *
    \n *

    <-- first (and deepest) node is \n * |adaddad <-- anchor node\n *
    \n */\n if ($.isEmpty(firstNode)) {\n let leftSiblings = this.getHigherLevelSiblings(anchorNode, 'left'),\n nothingAtLeft = leftSiblings.every( node => $.isEmpty(node) );\n\n\n\n if (nothingAtLeft && selection.anchorOffset === firstLetterPosition) {\n return true;\n }\n }\n\n return firstNode === null || anchorNode === firstNode && selection.anchorOffset === firstLetterPosition;\n }\n\n /**\n * Get's deepest last node and checks if offset is last node text length\n * @return {boolean}\n */\n get isAtEnd() {\n /**\n * Don't handle ranges\n */\n if (!Selection.isCollapsed) {\n return false;\n }\n\n let selection = Selection.get(),\n anchorNode = selection.anchorNode,\n lastNode = $.getDeepestNode(this.Editor.BlockManager.currentBlock.pluginsContent, true);\n\n /**\n * In case of\n *
    \n * adaddad| <-- anchor node\n *

    <-- first (and deepest) node is \n *
    \n */\n if ($.isEmpty(lastNode)) {\n let leftSiblings = this.getHigherLevelSiblings(anchorNode, 'right'),\n nothingAtRight = leftSiblings.every( node => $.isEmpty(node) );\n\n if (nothingAtRight && selection.anchorOffset === anchorNode.textContent.length) {\n return true;\n }\n }\n\n return anchorNode === lastNode && selection.anchorOffset === lastNode.textContent.length;\n }\n}\n","/**\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 * @constructor\n */\n constructor({config}) {\n super({config});\n this.subscribers = {};\n }\n\n /**\n * @param {String} eventName - event name\n * @param {Function} callback - subscriber\n */\n on(eventName, callback) {\n if (!(eventName in this.subscribers)) {\n this.subscribers[eventName] = [];\n }\n\n // group by events\n this.subscribers[eventName].push(callback);\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 this.subscribers[eventName].reduce(function (previousData, currentHandler) {\n let newData = currentHandler(previousData);\n\n return newData ? newData : previousData;\n }, data);\n }\n\n /**\n * Destroyer\n * clears subsribers list\n */\n destroy() {\n this.subscribers = null;\n }\n}","/**\n * @class Keyboard\n * @classdesc Сlass to handle the keydowns\n *\n * @author CodeX Team (team@ifmo.su)\n * @copyright CodeX Team 2017\n * @license The MIT License (MIT)\n * @version 1.0.0\n */\n\n/**\n * @typedef {Keyboard} Keyboard\n */\nexport default class Keyboard extends Module {\n /**\n * @constructor\n */\n constructor({config}) {\n super({config});\n }\n\n /**\n * Handler on Block for keyboard keys at keydown event\n *\n * @param {KeyboardEvent} event\n */\n blockKeydownsListener(event) {\n switch(event.keyCode) {\n case _.keyCodes.BACKSPACE:\n\n _.log('Backspace key pressed');\n this.backspacePressed(event);\n break;\n\n case _.keyCodes.ENTER:\n\n _.log('Enter key pressed');\n this.enterPressed(event);\n break;\n\n case _.keyCodes.DOWN:\n case _.keyCodes.RIGHT:\n\n _.log('Right/Down key pressed');\n this.arrowRightAndDownPressed();\n break;\n\n case _.keyCodes.UP:\n case _.keyCodes.LEFT:\n\n _.log('Left/Up key pressed');\n this.arrowLeftAndUpPressed();\n break;\n\n default:\n\n break;\n }\n }\n\n /**\n * Handle pressing enter key\n *\n * @param {KeyboardEvent} event\n */\n enterPressed(event) {\n let currentBlock = this.Editor.BlockManager.currentBlock,\n toolsConfig = this.config.toolsConfig[currentBlock.name];\n\n /**\n * Don't handle Enter keydowns when Tool sets enableLineBreaks to true.\n * Uses for Tools like where line breaks should be handled by default behaviour.\n */\n if (toolsConfig && toolsConfig[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS]) {\n return;\n }\n\n /**\n * Allow to create linebreaks by Shift+Enter\n */\n if (event.shiftKey) {\n return;\n }\n\n\n /**\n * Split the Current Block into two blocks\n */\n this.Editor.BlockManager.split();\n event.preventDefault();\n }\n\n /**\n * Handle backspace keypress on block\n * @param {KeyboardEvent} event - keydown\n */\n backspacePressed(event) {\n const BM = this.Editor.BlockManager;\n\n let isFirstBlock = BM.currentBlockIndex === 0,\n canMergeBlocks = this.Editor.Caret.isAtStart && !isFirstBlock;\n\n if (!canMergeBlocks) {\n return;\n }\n\n // preventing browser default behaviour\n event.preventDefault();\n\n let targetBlock = BM.getBlockByIndex(BM.currentBlockIndex - 1),\n blockToMerge = BM.currentBlock;\n\n /**\n * Blocks that can be merged:\n * 1) with the same Name\n * 2) Tool has 'merge' method\n *\n * other case will handle as usual ARROW LEFT behaviour\n */\n if (blockToMerge.name !== targetBlock.name || !targetBlock.mergeable) {\n BM.navigatePrevious();\n }\n\n let setCaretToTheEnd = !targetBlock.isEmpty ? true : false;\n\n BM.mergeBlocks(targetBlock, blockToMerge)\n .then( () => {\n window.setTimeout( () => {\n // set caret to the block without offset at the end\n this.Editor.Caret.setToBlock(BM.currentBlock, 0, setCaretToTheEnd);\n this.Editor.Toolbar.close();\n }, 10);\n });\n }\n\n /**\n * Handle right and down keyboard keys\n */\n arrowRightAndDownPressed() {\n this.Editor.BlockManager.navigateNext();\n }\n\n /**\n * Handle left and up keyboard keys\n */\n arrowLeftAndUpPressed() {\n this.Editor.BlockManager.navigatePrevious();\n }\n}\n","/**\n * Codex Editor Listeners module\n *\n * @module Listeners\n *\n * Module-decorator for event listeners assignment\n *\n * @author Codex Team\n * @version 2.0.0\n */\n\n/**\n * @typedef {Listeners} Listeners\n * @property {Array} allListeners\n */\n\nexport default class Listeners extends Module {\n /**\n * @constructor\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n this.allListeners = [];\n }\n\n /**\n * Assigns event listener on element\n *\n * @param {Element} element - DOM element that needs to be listened\n * @param {String} eventType - event type\n * @param {Function} handler - method that will be fired on event\n * @param {Boolean} useCapture - use event bubbling\n */\n on(element, eventType, handler, useCapture = false) {\n let assignedEventData = {\n element,\n eventType,\n handler,\n useCapture\n };\n\n let alreadyExist = this.findOne(element, eventType, handler);\n\n if (alreadyExist) return;\n\n this.allListeners.push(assignedEventData);\n element.addEventListener(eventType, handler, useCapture);\n }\n\n /**\n * Removes event listener from element\n *\n * @param {Element} element - DOM element that we removing listener\n * @param {String} eventType - event type\n * @param {Function} handler - remove handler, if element listens several handlers on the same event type\n * @param {Boolean} useCapture - use event bubbling\n */\n off(element, eventType, handler, useCapture = false) {\n let existingListeners = this.findAll(element, eventType, handler);\n\n for (let i = 0; i < existingListeners.length; i++) {\n let index = this.allListeners.indexOf(existingListeners[i]);\n\n if (index > 0) {\n this.allListeners.splice(index, 1);\n }\n }\n\n element.removeEventListener(eventType, handler, useCapture);\n }\n\n /**\n * Search method: looks for listener by passed element\n * @param {Element} element - searching element\n * @returns {Array} listeners that found on element\n */\n findByElement(element) {\n let listenersOnElement = [];\n\n for (let i = 0; i < this.allListeners.length; i++) {\n let listener = this.allListeners[i];\n\n if (listener.element === element) {\n listenersOnElement.push(listener);\n }\n }\n\n return listenersOnElement;\n }\n\n /**\n * Search method: looks for listener by passed event type\n * @param {String} eventType\n * @return {Array} listeners that found on element\n */\n findByType(eventType) {\n let listenersWithType = [];\n\n for (let i = 0; i < this.allListeners.length; i++) {\n let listener = this.allListeners[i];\n\n if (listener.type === eventType) {\n listenersWithType.push(listener);\n }\n }\n\n return listenersWithType;\n }\n\n /**\n * Search method: looks for listener by passed handler\n * @param {Function} handler\n * @return {Array} listeners that found on element\n */\n findByHandler(handler) {\n let listenersWithHandler = [];\n\n for (let i = 0; i < this.allListeners.length; i++) {\n let listener = this.allListeners[i];\n\n if (listener.handler === handler) {\n listenersWithHandler.push(listener);\n }\n }\n\n return listenersWithHandler;\n }\n\n /**\n * @param {Element} element\n * @param {String} eventType\n * @param {Function} handler\n * @return {Element|null}\n */\n findOne(element, eventType, handler) {\n let foundListeners = this.findAll(element, eventType, handler);\n\n return foundListeners.length > 0 ? foundListeners[0] : null;\n }\n\n /**\n * @param {Element} element\n * @param {String} eventType\n * @param {Function} handler\n * @return {Array}\n */\n findAll(element, eventType, handler) {\n let found,\n foundByElements = element ? this.findByElement(element) : [];\n // foundByEventType = eventType ? this.findByType(eventType) : [],\n // foundByHandler = handler ? this.findByHandler(handler) : [];\n\n if (element && eventType && handler) {\n found = foundByElements.filter( event => event.eventType === eventType && event.handler === handler );\n } else if (element && eventType) {\n found = foundByElements.filter( event => event.eventType === eventType);\n } else {\n found = foundByElements;\n }\n\n return found;\n }\n\n /**\n * Removes all listeners\n */\n removeAll() {\n this.allListeners.map( (current) => {\n current.element.removeEventListener(current.eventType, current.handler);\n });\n\n this.allListeners = [];\n }\n}\n","/**\n * Codex Editor Renderer Module\n *\n * @module Renderer\n * @author CodeX Team\n *\n * @version 2.0.0\n */\nexport default class Renderer extends Module {\n /**\n * @constructor\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n }\n\n /**\n * @typedef {Object} RendererItems\n * @property {String} type - tool name\n * @property {Object} data - tool data\n */\n\n /**\n * @example\n *\n * items: [\n * {\n * type : 'paragraph',\n * data : {\n * text : 'Hello from Codex!'\n * }\n * },\n * {\n * type : 'paragraph',\n * data : {\n * text : 'Leave feedback if you like it!'\n * }\n * },\n * ]\n *\n */\n\n /**\n * Make plugin blocks from array of plugin`s data\n * @param {RendererItems[]} items\n */\n render(items) {\n let chainData = [];\n\n for (let i = 0; i < items.length; i++) {\n chainData.push({\n function: () => this.insertBlock(items[i])\n });\n }\n\n return _.sequence(chainData);\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 let tool = item.type,\n data = item.data;\n\n this.Editor.BlockManager.insert(tool, data);\n\n return Promise.resolve();\n }\n}","/**\n * CodeX Sanitizer\n *\n * @module Sanitizer\n * Clears HTML from taint tags\n *\n * @version 2.0.0\n *\n * @example\n * Module can be used within two ways:\n * 1) When you have an instance\n * - this.Editor.Sanitizer.clean(yourTaintString);\n * 2) As static method\n * - CodexEditor.Sanitizer.clean(yourTaintString, yourCustomConfiguration);\n *\n * {@link SanitizerConfig}\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 * Initializes Sanitizer module\n * Sets default configuration if custom not exists\n *\n * @property {SanitizerConfig} this.defaultConfig\n * @property {HTMLJanitor} this._sanitizerInstance - Sanitizer library\n *\n * @param {SanitizerConfig} config\n */\n constructor({config}) {\n super({config});\n\n // default config\n this.defaultConfig = null;\n this._sanitizerInstance = 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 * 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 this._sanitizerInstance = new library(this.defaultConfig);\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 if (_.isEmpty(config)) {\n this.defaultConfig = {\n tags: {\n p: {},\n a: {\n href: true,\n target: '_blank',\n rel: 'nofollow'\n }\n }\n };\n } else {\n this.defaultConfig = config;\n }\n }\n\n /**\n * Cleans string from unwanted tags\n * @param {String} taintString - HTML string\n * @param {Object} customConfig - custom sanitizer configuration. Method uses default if param is empty\n * @return {String} clean HTML\n */\n clean(taintString, customConfig = {}) {\n if (_.isEmpty(customConfig)) {\n return this._sanitizerInstance.clean(taintString);\n } else {\n return Sanitizer.clean(taintString, customConfig);\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 let newInstance = Sanitizer(customConfig);\n\n return newInstance.clean(taintString);\n }\n}\n","/**\n * Codex Editor Saver\n *\n * @module Saver\n * @author Codex Team\n * @version 2.0.0\n */\n\n/**\n * @typedef {Object} SavedData\n * @property {Date} time - saving proccess time\n * @property {Object} items - extracted data\n * @property {String} version - CodexEditor version\n */\n\n/**\n * @classdesc This method reduces all Blocks asyncronically and calls Block's save method to extract data\n *\n * @typedef {Saver} Saver\n * @property {Element} html - Editor HTML content\n * @property {String} json - Editor JSON output\n */\n\nexport default class Saver extends Module {\n /**\n * @constructor\n * @param config\n */\n constructor({config}) {\n super({config});\n\n this.output = null;\n this.blocksData = [];\n }\n\n /**\n * Composes new chain of Promises to fire them alternatelly\n * @return {SavedData}\n */\n save() {\n let blocks = this.Editor.BlockManager.blocks,\n chainData = [];\n\n blocks.forEach((block) => {\n chainData.push(block.data);\n });\n\n return Promise.all(chainData)\n .then((allExtractedData) => this.makeOutput(allExtractedData))\n .then((outputData) => {\n return outputData;\n });\n }\n\n /**\n * Creates output object with saved data, time and version of editor\n * @param {Object} allExtractedData\n * @return {SavedData}\n */\n makeOutput(allExtractedData) {\n let items = [],\n totalTime = 0;\n\n console.groupCollapsed('[CodexEditor saving]:');\n\n allExtractedData.forEach((extraction) => {\n /** Group process info */\n console.log(`«${extraction.tool}» saving info`, extraction);\n totalTime += extraction.time;\n items.push(extraction.data);\n });\n\n console.log('Total', totalTime);\n console.groupEnd();\n\n return {\n time : +new Date(),\n items : items,\n version : VERSION,\n };\n }\n}\n\n// module.exports = (function (saver) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * @public\n// * Save blocks\n// */\n// saver.save = function () {\n//\n// /** Save html content of redactor to memory */\n// editor.state.html = editor.nodes.redactor.innerHTML;\n//\n// /** Clean jsonOutput state */\n// editor.state.jsonOutput = [];\n//\n// return saveBlocks(editor.nodes.redactor.childNodes);\n//\n// };\n//\n// /**\n// * @private\n// * Save each block data\n// *\n// * @param blocks\n// * @returns {Promise.}\n// */\n// let saveBlocks = function (blocks) {\n//\n// let data = [];\n//\n// for(let index = 0; index < blocks.length; index++) {\n//\n// data.push(getBlockData(blocks[index]));\n//\n// }\n//\n// return Promise.all(data)\n// .then(makeOutput)\n// .catch(editor.core.log);\n//\n// };\n//\n// /** Save and validate block data */\n// let getBlockData = function (block) {\n//\n// return saveBlockData(block)\n// .then(validateBlockData)\n// .catch(editor.core.log);\n//\n// };\n//\n// /**\n// * @private\n// * Call block`s plugin save method and return saved data\n// *\n// * @param block\n// * @returns {Object}\n// */\n// let saveBlockData = function (block) {\n//\n// let pluginName = block.dataset.tool;\n//\n// /** Check for plugin existence */\n// if (!editor.tools[pluginName]) {\n//\n// editor.core.log(`Plugin «${pluginName}» not found`, 'error');\n// return {data: null, pluginName: null};\n//\n// }\n//\n// /** Check for plugin having save method */\n// if (typeof editor.tools[pluginName].save !== 'function') {\n//\n// editor.core.log(`Plugin «${pluginName}» must have save method`, 'error');\n// return {data: null, pluginName: null};\n//\n// }\n//\n// /** Result saver */\n// let blockContent = block.childNodes[0],\n// pluginsContent = blockContent.childNodes[0],\n// position = pluginsContent.dataset.inputPosition;\n//\n// /** If plugin wasn't available then return data from cache */\n// if ( editor.tools[pluginName].available === false ) {\n//\n// return Promise.resolve({data: codex.editor.state.blocks.items[position].data, pluginName});\n//\n// }\n//\n// return Promise.resolve(pluginsContent)\n// .then(editor.tools[pluginName].save)\n// .then(data => Object({data, pluginName}));\n//\n// };\n//\n// /**\n// * Call plugin`s validate method. Return false if validation failed\n// *\n// * @param data\n// * @param pluginName\n// * @returns {Object|Boolean}\n// */\n// let validateBlockData = function ({data, pluginName}) {\n//\n// if (!data || !pluginName) {\n//\n// return false;\n//\n// }\n//\n// if (editor.tools[pluginName].validate) {\n//\n// let result = editor.tools[pluginName].validate(data);\n//\n// /**\n// * Do not allow invalid data\n// */\n// if (!result) {\n//\n// return false;\n//\n// }\n//\n// }\n//\n// return {data, pluginName};\n//\n//\n// };\n//\n// /**\n// * Compile article output\n// *\n// * @param savedData\n// * @returns {{time: number, version, items: (*|Array)}}\n// */\n// let makeOutput = function (savedData) {\n//\n// savedData = savedData.filter(blockData => blockData);\n//\n// let items = savedData.map(blockData => Object({type: blockData.pluginName, data: blockData.data}));\n//\n// editor.state.jsonOutput = items;\n//\n// return {\n// id: editor.state.blocks.id || null,\n// time: +new Date(),\n// version: editor.version,\n// items\n// };\n//\n// };\n//\n// return saver;\n//\n// })({});\n","/**\n * Block Settings\n *\n * ____ Settings Panel ____\n * | ...................... |\n * | . Tool Settings . |\n * | ...................... |\n * | . Default Settings . |\n * | ...................... |\n * |________________________|\n */\nexport default class BlockSettings extends Module {\n constructor({config}) {\n super({config});\n\n this.nodes = {\n wrapper: null,\n toolSettings: null,\n defaultSettings: null,\n buttonRemove: null\n };\n }\n\n /**\n * Block Settings CSS\n * @return {{wrapper, wrapperOpened, toolSettings, defaultSettings, button}}\n */\n static get CSS() {\n return {\n // Settings Panel\n wrapper: 'ce-settings',\n wrapperOpened: 'ce-settings--opened',\n toolSettings: 'ce-settings__plugin-zone',\n defaultSettings: 'ce-settings__default-zone',\n\n button: 'ce-settings__button'\n };\n }\n\n /**\n * Panel with block settings with 2 sections:\n * - Tool's Settings\n * - Default Settings [Move, Remove, etc]\n *\n * @return {Element}\n */\n make() {\n this.nodes.wrapper = $.make('div', BlockSettings.CSS.wrapper);\n\n this.nodes.toolSettings = $.make('div', BlockSettings.CSS.toolSettings);\n this.nodes.defaultSettings = $.make('div', BlockSettings.CSS.defaultSettings);\n\n $.append(this.nodes.wrapper, [this.nodes.toolSettings, this.nodes.defaultSettings]);\n\n /**\n * Add default settings that presents for all Blocks\n */\n this.addDefaultSettings();\n }\n\n /**\n * Add Tool's settings\n */\n addToolSettings() {\n console.log('Block Settings: add settings for ',\n this.Editor.BlockManager.currentBlock\n );\n }\n\n /**\n * Add default settings\n */\n addDefaultSettings() {\n /**\n * Remove Block Button\n * --------------------------------------------\n */\n this.nodes.buttonRemove = $.make('div', BlockSettings.CSS.button, {\n textContent: 'Remove Block'\n });\n\n $.append(this.nodes.defaultSettings, this.nodes.buttonRemove);\n\n this.Editor.Listeners.on(this.nodes.buttonRemove, 'click', (event) => this.removeBlockButtonClicked(event));\n }\n\n /**\n * Clicks on the Remove Block Button\n */\n removeBlockButtonClicked() {\n console.log('❇️ Remove Block Button clicked');\n }\n\n /**\n * Is Block Settings opened or not\n * @returns {boolean}\n */\n get opened() {\n return this.nodes.wrapper.classList.contains(BlockSettings.CSS.wrapperOpened);\n }\n\n /**\n * Open Block Settings pane\n */\n open() {\n this.nodes.wrapper.classList.add(BlockSettings.CSS.wrapperOpened);\n\n /**\n * Fill Tool's settings\n */\n this.addToolSettings();\n }\n\n /**\n * Close Block Settings pane\n */\n close() {\n this.nodes.wrapper.classList.remove(BlockSettings.CSS.wrapperOpened);\n }\n}\n","import Selection from '../selection';\nexport default class InlineToolbar extends Module {\n /**\n * @constructor\n */\n constructor({ config }) {\n super({ config });\n /**\n * Inline Toolbar elements\n */\n this.nodes = {\n wrapper: null,\n };\n /**\n * CSS styles\n */\n this.CSS = {\n inlineToolbar: 'ce-inline-toolbar',\n inlineToolbarShowed: 'ce-inline-toolbar--showed',\n };\n /**\n * Margin above/below the Toolbar\n */\n this.toolbarVerticalMargin = 20;\n }\n /**\n * Making DOM\n */\n make() {\n this.nodes.wrapper = $.make('div', this.CSS.inlineToolbar);\n /**\n * Append Inline Toolbar to the Editor\n */\n $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);\n }\n /**\n * Shows Inline Toolbar by keyup/mouseup\n * @param {KeyboardEvent|MouseEvent} event\n */\n handleShowingEvent(event) {\n if (!this.allowedToShow(event)) {\n this.close();\n return;\n }\n this.move();\n this.open();\n }\n /**\n * Move Toolbar to the selected text\n */\n move() {\n const selectionRect = Selection.rect;\n const wrapperOffset = this.Editor.UI.nodes.wrapper.getBoundingClientRect();\n const newCoords = {\n x: selectionRect.x - wrapperOffset.left,\n y: selectionRect.y\n + selectionRect.height\n // + window.scrollY\n - wrapperOffset.top\n + this.toolbarVerticalMargin,\n };\n /**\n * If we know selections width, place InlineToolbar to center\n */\n if (selectionRect.width) {\n newCoords.x += Math.floor(selectionRect.width / 2);\n }\n this.nodes.wrapper.style.left = Math.floor(newCoords.x) + 'px';\n this.nodes.wrapper.style.top = Math.floor(newCoords.y) + 'px';\n }\n /**\n * Shows Inline Toolbar\n */\n open() {\n this.nodes.wrapper.classList.add(this.CSS.inlineToolbarShowed);\n }\n /**\n * Hides Inline Toolbar\n */\n close() {\n this.nodes.wrapper.classList.remove(this.CSS.inlineToolbarShowed);\n }\n /**\n * Need to show Inline Toolbar or not\n * @param {KeyboardEvent|MouseEvent} event\n */\n allowedToShow(event) {\n /**\n * Tags conflicts with window.selection function.\n * Ex. IMG tag returns null (Firefox) or Redactors wrapper (Chrome)\n */\n const tagsConflictsWithSelection = ['IMG', 'INPUT'];\n if (event && tagsConflictsWithSelection.includes(event.target.tagName)) {\n return false;\n }\n const currentSelection = Selection.get(), selectedText = Selection.text;\n // old browsers\n if (!currentSelection || !currentSelection.anchorNode) {\n return false;\n }\n // empty selection\n if (currentSelection.isCollapsed || selectedText.length < 1) {\n return false;\n }\n // is enabled by current Block's Tool\n const currentBlock = this.Editor.BlockManager.getBlock(currentSelection.anchorNode);\n if (!currentBlock) {\n return false;\n }\n const toolConfig = this.config.toolsConfig[currentBlock.name];\n return toolConfig && toolConfig[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR];\n }\n}\n","/**\n * @class Toolbox\n * @classdesc Holder for Tools\n *\n * @typedef {Toolbox} Toolbox\n * @property {Boolean} opened - opening state\n * @property {Object} nodes - Toolbox nodes\n * @property {Object} CSS - CSS class names\n *\n */\nexport default class Toolbox extends Module {\n /**\n * @constructor\n */\n constructor({config}) {\n super({config});\n\n this.nodes = {\n toolbox: null,\n buttons: []\n };\n\n /**\n * Opening state\n * @type {boolean}\n */\n this.opened = false;\n }\n\n /**\n * CSS styles\n * @return {{toolbox: string, toolboxButton: string, toolboxOpened: string}}\n */\n static get CSS() {\n return {\n toolbox: 'ce-toolbox',\n toolboxButton: 'ce-toolbox__button',\n toolboxOpened: 'ce-toolbox--opened',\n };\n }\n\n /**\n * Makes the Toolbox\n */\n make() {\n this.nodes.toolbox = $.make('div', Toolbox.CSS.toolbox);\n $.append(this.Editor.Toolbar.nodes.content, this.nodes.toolbox);\n\n this.addTools();\n }\n\n /**\n * Iterates available tools and appends them to the Toolbox\n */\n addTools() {\n let tools = this.Editor.Tools.toolsAvailable;\n\n for (let toolName in tools) {\n this.addTool(toolName, tools[toolName]);\n }\n }\n\n /**\n * Append Tool to the Toolbox\n *\n * @param {string} toolName - tool name\n * @param {Tool} tool - tool class\n */\n addTool(toolName, tool) {\n const api = this.Editor.Tools.apiSettings;\n\n if (tool[api.IS_DISPLAYED_IN_TOOLBOX] && !tool[api.TOOLBAR_ICON_CLASS]) {\n _.log('Toolbar icon class name is missed. Tool %o skipped', 'warn', toolName);\n return;\n }\n\n /**\n * @todo Add checkup for the render method\n */\n // if (typeof tool.render !== 'function') {\n //\n // _.log('render method missed. Tool %o skipped', 'warn', tool);\n // return;\n //\n // }\n\n /**\n * Skip tools that pass 'displayInToolbox=false'\n */\n if (!tool[api.IS_DISPLAYED_IN_TOOLBOX]) {\n return;\n }\n\n let button = $.make('li', [Toolbox.CSS.toolboxButton, tool[api.TOOLBAR_ICON_CLASS]], {\n title: toolName\n });\n\n /**\n * Save tool's name in the button data-name\n */\n button.dataset.name = toolName;\n\n $.append(this.nodes.toolbox, button);\n\n this.nodes.toolbox.appendChild(button);\n this.nodes.buttons.push(button);\n\n /**\n * @todo add event with module Listeners\n */\n // this.Editor.Listeners.add();\n button.addEventListener('click', event => {\n this.buttonClicked(event);\n }, false);\n }\n\n /**\n * Toolbox button click listener\n * 1) if block is empty -> replace\n * 2) if block is not empty -> add new block below\n *\n * @param {MouseEvent} event\n */\n buttonClicked(event) {\n let toolButton = event.target,\n toolName = toolButton.dataset.name,\n tool = this.Editor.Tools.toolClasses[toolName];\n\n /**\n * @type {Block}\n */\n let currentBlock = this.Editor.BlockManager.currentBlock;\n\n /**\n * We do replace if:\n * - block is empty\n * - block is not irreplaceable\n * @type {Array}\n */\n if (!tool[this.Editor.Tools.apiSettings.IS_IRREPLACEBLE_TOOL] && currentBlock.isEmpty) {\n this.Editor.BlockManager.replace(toolName);\n } else {\n this.Editor.BlockManager.insert(toolName);\n }\n\n /**\n * @todo set caret to the new block\n */\n\n // window.setTimeout(function () {\n\n /** Set caret to current block */\n // editor.caret.setToBlock(currentInputIndex);\n\n // }, 10);\n\n /**\n * Move toolbar when node is changed\n */\n this.Editor.Toolbar.move();\n }\n\n /**\n * Open Toolbox with Tools\n */\n open() {\n this.nodes.toolbox.classList.add(Toolbox.CSS.toolboxOpened);\n this.opened = true;\n }\n\n /**\n * Close Toolbox\n */\n close() {\n this.nodes.toolbox.classList.remove(Toolbox.CSS.toolboxOpened);\n this.opened = false;\n }\n\n /**\n * Close Toolbox\n */\n toggle() {\n if (!this.opened) {\n this.open();\n } else {\n this.close();\n }\n }\n}\n","/**\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.blockActionsButtons - Zone with Block Buttons: [Settings]\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.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 * @constructor\n */\n constructor({config}) {\n super({config});\n\n this.nodes = {\n wrapper : null,\n content : null,\n actions : null,\n\n // Content Zone\n plusButton : null,\n\n // Actions Zone\n blockActionsButtons: null,\n settingsToggler : null,\n };\n }\n\n /**\n * CSS styles\n * @return {Object}\n * @constructor\n */\n static get CSS() {\n return {\n toolbar: 'ce-toolbar',\n content: 'ce-toolbar__content',\n actions: 'ce-toolbar__actions',\n\n toolbarOpened: 'ce-toolbar--opened',\n\n // Content Zone\n plusButton: 'ce-toolbar__plus',\n plusButtonHidden: 'ce-toolbar__plus--hidden',\n\n // Actions Zone\n blockActionsButtons: 'ce-toolbar__actions-buttons',\n settingsToggler: 'ce-toolbar__settings-btn',\n };\n }\n\n /**\n * Makes toolbar\n */\n make() {\n this.nodes.wrapper = $.make('div', Toolbar.CSS.toolbar);\n\n /**\n * Make Content Zone and Actions Zone\n */\n ['content', 'actions'].forEach( el => {\n this.nodes[el] = $.make('div', Toolbar.CSS[el]);\n $.append(this.nodes.wrapper, this.nodes[el]);\n });\n\n\n /**\n * Fill Content Zone:\n * - Plus Button\n * - Toolbox\n */\n this.nodes.plusButton = $.make('div', Toolbar.CSS.plusButton);\n $.append(this.nodes.content, this.nodes.plusButton);\n this.nodes.plusButton.addEventListener('click', event => this.plusButtonClicked(event), false);\n\n\n /**\n * Make a Toolbox\n */\n this.Editor.Toolbox.make();\n\n /**\n * Fill Actions Zone:\n * - Settings Toggler\n * - Remove Block Button\n * - Settings Panel\n */\n this.nodes.blockActionsButtons = $.make('div', Toolbar.CSS.blockActionsButtons);\n this.nodes.settingsToggler = $.make('span', Toolbar.CSS.settingsToggler);\n\n $.append(this.nodes.blockActionsButtons, this.nodes.settingsToggler);\n $.append(this.nodes.actions, this.nodes.blockActionsButtons);\n\n /**\n * Make and append Settings Panel\n */\n this.Editor.BlockSettings.make();\n $.append(this.nodes.actions, this.Editor.BlockSettings.nodes.wrapper);\n\n /**\n * Append toolbar to the Editor\n */\n $.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);\n\n /**\n * Bind events on the Toolbar elements\n */\n this.bindEvents();\n }\n\n /**\n * Move Toolbar to the Current Block\n */\n move() {\n /** Close Toolbox when we move toolbar */\n this.Editor.Toolbox.close();\n\n let currentNode = this.Editor.BlockManager.currentNode;\n\n /**\n * If no one Block selected as a Current\n */\n if (!currentNode) {\n return;\n }\n\n /**\n * @todo Compute dynamically on prepare\n * @type {number}\n */\n const defaultToolbarHeight = 49;\n const defaultOffset = 34;\n\n var newYCoordinate = currentNode.offsetTop - (defaultToolbarHeight / 2) + defaultOffset;\n\n this.nodes.wrapper.style.transform = `translate3D(0, ${Math.floor(newYCoordinate)}px, 0)`;\n\n /** Close trash actions */\n // editor.toolbar.settings.hideRemoveActions();\n }\n\n /**\n * Open Toolbar with Plus Button\n */\n open() {\n this.nodes.wrapper.classList.add(Toolbar.CSS.toolbarOpened);\n }\n\n /**\n * Close the Toolbar\n */\n close() {\n this.nodes.wrapper.classList.remove(Toolbar.CSS.toolbarOpened);\n }\n\n /**\n * Plus Button public methods\n * @return {{hide: function(): void, show: function(): void}}\n */\n get plusButton() {\n return {\n hide: () => this.nodes.plusButton.classList.add(Toolbar.CSS.plusButtonHidden),\n show: () => this.nodes.plusButton.classList.remove(Toolbar.CSS.plusButtonHidden)\n };\n }\n\n /**\n * Handler for Plus Button\n * @param {MouseEvent} event\n */\n plusButtonClicked() {\n this.Editor.Toolbox.toggle();\n }\n\n /**\n * Bind events on the Toolbar Elements:\n * - Block Settings\n */\n bindEvents() {\n /**\n * Settings toggler\n */\n this.Editor.Listeners.on(this.nodes.settingsToggler, 'click', (event) => {\n this.settingsTogglerClicked(event);\n });\n }\n\n /**\n * Clicks on the Block Settings toggler\n */\n settingsTogglerClicked() {\n if (this.Editor.BlockSettings.opened) {\n this.Editor.BlockSettings.close();\n } else {\n this.Editor.BlockSettings.open();\n }\n }\n}","/**\n * @module Codex Editor Tools Submodule\n *\n * Creates Instances from Plugins and binds external config to the instances\n */\n\n/**\n * Each Tool must contain the following important objects:\n *\n * @typedef {Object} ToolConfig {@link docs/tools.md}\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 * @property {Boolean|String[]} inlineToolbar - Pass `true` to enable the Inline Toolbar with all Tools, all pass an array with specified Tools list |\n * @property render @todo add description\n * @property save @todo add description\n * @property settings @todo add description\n * @property validate - method that validates output data before saving\n */\n\n/**\n * @typedef {Function} Tool {@link docs/tools.md}\n * @property {Boolean} displayInToolbox - By default, tools won't be added in the Toolbox. Pass true to add.\n * @property {String} iconClassName - CSS class name for the Toolbox button\n * @property {Boolean} irreplaceable - Toolbox behaviour: replace or add new block below\n * @property render\n * @property save\n * @property settings\n * @property validate\n *\n * @todo update according to current API\n * @todo describe Tool in the {@link docs/tools.md}\n */\n\n/**\n * Class properties:\n *\n * @typedef {Tools} Tools\n * @property {Tools[]} toolsAvailable - available Tools\n * @property {Tools[]} toolsUnavailable - unavailable Tools\n * @property {Object} toolsClasses - all classes\n * @property {EditorConfig} config - Editor config\n */\nexport default class Tools extends Module {\n /**\n * Returns available Tools\n * @return {Tool[]}\n */\n get available() {\n return this.toolsAvailable;\n }\n\n /**\n * Returns unavailable Tools\n * @return {Tool[]}\n */\n get unavailable() {\n return this.toolsUnavailable;\n }\n\n /**\n * Constant for available Tools Settings\n * @return {object}\n */\n get apiSettings() {\n return {\n TOOLBAR_ICON_CLASS: 'iconClassName',\n IS_DISPLAYED_IN_TOOLBOX: 'displayInToolbox',\n IS_ENABLED_LINE_BREAKS: 'enableLineBreaks',\n IS_IRREPLACEBLE_TOOL: 'irreplaceable',\n IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar',\n };\n }\n\n /**\n * Static getter for default Tool config fields\n * @return {ToolConfig}\n */\n get defaultConfig() {\n return {\n [this.apiSettings.TOOLBAR_ICON_CLASS] : false,\n [this.apiSettings.IS_DISPLAYED_IN_TOOLBOX] : false,\n [this.apiSettings.IS_ENABLED_LINE_BREAKS] : false,\n [this.apiSettings.IS_IRREPLACEBLE_TOOL] : false,\n [this.apiSettings.IS_ENABLED_INLINE_TOOLBAR]: false,\n };\n }\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n\n /**\n * Map {name: Class, ...} where:\n * name — block type name in JSON. Got from EditorConfig.tools keys\n * @type {Object}\n */\n this.toolClasses = {};\n\n /**\n * Available tools list\n * {name: Class, ...}\n * @type {Object}\n */\n this.toolsAvailable = {};\n\n /**\n * Tools that rejected a prepare method\n * {name: Class, ... }\n * @type {Object}\n */\n this.toolsUnavailable = {};\n }\n\n /**\n * Creates instances via passed or default configuration\n * @return {Promise}\n */\n prepare() {\n if (!this.config.hasOwnProperty('tools')) {\n return Promise.reject(\"Can't start without tools\");\n }\n\n for(let toolName in this.config.tools) {\n this.toolClasses[toolName] = this.config.tools[toolName];\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 return Promise.resolve();\n }\n\n /**\n * to see how it works {@link Util#sequence}\n */\n return _.sequence(sequenceData, (data) => {\n this.success(data);\n }, (data) => {\n this.fallback(data);\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 sequentially\n */\n getListOfPrepareFunctions() {\n let toolPreparationList = [];\n\n for(let toolName in this.toolClasses) {\n let toolClass = this.toolClasses[toolName];\n\n if (typeof toolClass.prepare === 'function') {\n toolPreparationList.push({\n function : toolClass.prepare,\n data : {\n toolName\n }\n });\n } else {\n /**\n * If Tool hasn't a prepare method, mark it as available\n */\n this.toolsAvailable[toolName] = toolClass;\n }\n }\n\n return toolPreparationList;\n }\n\n /**\n * @param {ChainData.data} data - append tool to available list\n */\n success(data) {\n this.toolsAvailable[data.toolName] = this.toolClasses[data.toolName];\n }\n\n /**\n * @param {ChainData.data} data - append tool to unavailable list\n */\n fallback(data) {\n this.toolsUnavailable[data.toolName] = this.toolClasses[data.toolName];\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 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 * Check if passed Tool is an instance of Initial Block Tool\n * @param {Tool} tool - Tool to check\n * @return {Boolean}\n */\n isInitial(tool) {\n return tool instanceof this.available[this.config.initialBlock];\n }\n}\n","/**\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\n// import Block from '../block';\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 */\nexport default class UI extends Module {\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor({config}) {\n super({config});\n\n this.nodes = {\n holder: null,\n wrapper: null,\n redactor: null\n };\n }\n\n /**\n * Making main interface\n */\n prepare() {\n return this.make()\n /**\n * Make toolbar\n */\n .then(() => this.Editor.Toolbar.make())\n /**\n * Make the Inline toolbar\n */\n .then(() => this.Editor.InlineToolbar.make())\n /**\n * Load and append CSS\n */\n .then(() => this.loadStyles())\n /**\n * Bind events for the UI elements\n */\n .then(() => this.bindEvents())\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 console.error(e);\n\n // editor.core.log(\"Can't draw editor interface\");\n });\n }\n\n /**\n * CodeX Editor UI CSS class names\n * @return {{editorWrapper: string, editorZone: string, block: string}}\n */\n get CSS() {\n return {\n editorWrapper : 'codex-editor',\n editorZone : 'codex-editor__redactor',\n };\n }\n\n /**\n * Makes CodeX Editor interface\n * @return {Promise}\n */\n make() {\n return new Promise( (resolve, reject) => {\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 reject(Error(\"Holder wasn't found by ID: #\" + this.config.holderId));\n return;\n }\n\n /**\n * Create and save main UI elements\n */\n this.nodes.wrapper = $.make('div', this.CSS.editorWrapper);\n this.nodes.redactor = $.make('div', this.CSS.editorZone);\n\n this.nodes.wrapper.appendChild(this.nodes.redactor);\n this.nodes.holder.appendChild(this.nodes.wrapper);\n\n resolve();\n });\n }\n\n /**\n * Appends CSS\n */\n loadStyles() {\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 * Bind events on the CodeX Editor interface\n */\n bindEvents() {\n /**\n * @todo bind events with the Listeners module\n */\n this.Editor.Listeners.on(this.nodes.redactor, 'click', event => this.redactorClicked(event), false );\n }\n\n /**\n * All clicks on the redactor zone\n *\n * @param {MouseEvent} event\n *\n * @description\n * 1. Save clicked Block as a current {@link BlockManager#currentNode}\n * it uses for the following:\n * - add CSS modifier for the selected Block\n * - on Enter press, we make a new Block under that\n *\n * 2. Move and show the Toolbar\n *\n * 3. Set a Caret\n *\n * 4. By clicks on the Editor's bottom zone:\n * - if last Block is empty, set a Caret to this\n * - otherwise, add a new empty Block and set a Caret to that\n *\n * 5. Hide the Inline Toolbar\n *\n * @see selectClickedBlock\n *\n */\n redactorClicked(event) {\n let clickedNode = event.target;\n\n /**\n * Select clicked Block as Current\n */\n try {\n this.Editor.BlockManager.setCurrentBlockByChildNode(clickedNode);\n } catch (e) {\n /**\n * If clicked outside first-level Blocks, set Caret to the last empty Block\n */\n this.Editor.Caret.setToTheLastBlock();\n }\n\n\n /**\n * Close Inline Toolbar when nothing selected\n */\n this.Editor.InlineToolbar.handleShowingEvent(event);\n\n /**\n *\n\n /** Update current input index in memory when caret focused into existed input */\n // if (event.target.contentEditable == 'true') {\n //\n // editor.caret.saveCurrentInputIndex();\n //\n // }\n\n // if (editor.content.currentNode === null) {\n //\n // /**\n // * If inputs in redactor does not exits, then we put input index 0 not -1\n // */\n // var indexOfLastInput = editor.state.inputs.length > 0 ? editor.state.inputs.length - 1 : 0;\n //\n // /** If we have any inputs */\n // if (editor.state.inputs.length) {\n //\n // /** getting firstlevel parent of input */\n // firstLevelBlock = editor.content.getFirstLevelBlock(editor.state.inputs[indexOfLastInput]);\n //\n // }\n //\n // /** If input is empty, then we set caret to the last input */\n // if (editor.state.inputs.length && editor.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == editor.settings.initialBlockPlugin) {\n //\n // editor.caret.setToBlock(indexOfLastInput);\n //\n // } else {\n //\n // /** Create new input when caret clicked in redactors area */\n // var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n //\n // editor.content.insertBlock({\n // type : NEW_BLOCK_TYPE,\n // block : editor.tools[NEW_BLOCK_TYPE].render()\n // });\n //\n // /** If there is no inputs except inserted */\n // if (editor.state.inputs.length === 1) {\n //\n // editor.caret.setToBlock(indexOfLastInput);\n //\n // } else {\n //\n // /** Set caret to this appended input */\n // editor.caret.setToNextBlock(indexOfLastInput);\n //\n // }\n //\n // }\n //\n // } else {\n //\n // /** Close all panels */\n // editor.toolbar.settings.close();\n // editor.toolbar.toolbox.close();\n //\n // }\n //\n /**\n * Move toolbar and open\n */\n this.Editor.Toolbar.move();\n this.Editor.Toolbar.open();\n //\n // var inputIsEmpty = !editor.content.currentNode.textContent.trim(),\n // currentNodeType = editor.content.currentNode.dataset.tool,\n // isInitialType = currentNodeType == editor.settings.initialBlockPlugin;\n //\n //\n\n /**\n * Hide the Plus Button\n * */\n this.Editor.Toolbar.plusButton.hide();\n\n /**\n * Show the Plus Button if:\n * - Block is an initial-block (Text)\n * - Block is empty\n */\n let isInitialBlock = this.Editor.Tools.isInitial(this.Editor.BlockManager.currentBlock.tool),\n isEmptyBlock = this.Editor.BlockManager.currentBlock.isEmpty;\n\n if (isInitialBlock && isEmptyBlock) {\n this.Editor.Toolbar.plusButton.show();\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// 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 * Element.closest()\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/Element/closest\n */\nif (!Element.prototype.matches)\n Element.prototype.matches = Element.prototype.msMatchesSelector ||\n Element.prototype.webkitMatchesSelector;\n\nif (!Element.prototype.closest)\n Element.prototype.closest = function (s) {\n var el = this;\n\n if (!document.documentElement.contains(el)) return null;\n do {\n if (el.matches(s)) return el;\n el = el.parentElement || el.parentNode;\n } while (el !== null);\n return null;\n };\n","/**\n * Working with selection\n * @typedef {Selection} Selection\n */\nexport default class Selection {\n /**\n * @constructor\n */\n constructor() {\n this.instance = null;\n this.selection = null;\n }\n\n /**\n * Returns window Selection\n * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection}\n * @return {Selection}\n */\n static get() {\n return window.getSelection();\n }\n\n /**\n * Returns selected anchor\n * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode}\n * @return {Node|null}\n */\n static get anchorNode() {\n let selection = window.getSelection();\n\n return selection ? selection.anchorNode : null;\n }\n\n /**\n * Returns selection offset according to the anchor node\n * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset}\n * @return {Number|null}\n */\n static get anchorOffset() {\n let selection = window.getSelection();\n\n return selection ? selection.anchorOffset : null;\n }\n\n /**\n * Is current selection range collapsed\n * @return {boolean|null}\n */\n static get isCollapsed() {\n let selection = window.getSelection();\n\n return selection ? selection.isCollapsed : null;\n }\n\n /**\n * Calculates position and size of selected text\n * @return {{x, y, width, height, top?, left?, bottom?, right?}}\n */\n static get rect() {\n let sel = document.selection, range;\n let rect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n\n if (sel && sel.type !== 'Control') {\n range = sel.createRange();\n rect.x = range.boundingLeft;\n rect.y = range.boundingTop;\n rect.width = range.boundingWidth;\n rect.height = range.boundingHeight;\n\n return rect;\n }\n\n if (!window.getSelection) {\n _.log('Method window.getSelection is not supported', 'warn');\n return rect;\n }\n\n sel = window.getSelection();\n\n if (!sel.rangeCount) {\n _.log('Method Selection.rangeCount() is not supported', 'warn');\n return rect;\n }\n\n range = sel.getRangeAt(0).cloneRange();\n\n if (range.getBoundingClientRect) {\n rect = range.getBoundingClientRect();\n }\n // Fall back to inserting a temporary element\n if (rect.x === 0 && rect.y === 0) {\n let span = document.createElement('span');\n\n if (span.getBoundingClientRect) {\n // Ensure span has dimensions and position by\n // adding a zero-width space character\n span.appendChild( document.createTextNode('\\u200b') );\n range.insertNode(span);\n rect = span.getBoundingClientRect();\n\n let spanParent = span.parentNode;\n\n spanParent.removeChild(span);\n\n // Glue any broken text nodes back together\n spanParent.normalize();\n }\n }\n\n return rect;\n }\n\n /**\n * Returns selected text as String\n * @returns {string}\n */\n static get text() {\n return window.getSelection ? window.getSelection().toString() : '';\n };\n}\n","/**\n * Codex Editor Util\n */\nexport default class Util {\n /**\n * Custom logger\n *\n * @param {string} msg - message\n * @param {string} type - logging type 'log'|'warn'|'error'|'info'\n * @param {*} args - argument to log with a message\n */\n static log(msg, type, args) {\n type = type || 'log';\n\n if (!args) {\n args = msg || 'undefined';\n msg = '[codex-editor]: %o';\n } else {\n msg = '[codex-editor]: ' + msg;\n }\n\n try{\n if ( 'console' in window && window.console[ type ] ) {\n if ( args ) window.console[ type ]( msg, args );\n else window.console[ type ]( msg );\n }\n } catch(e) {\n // do nothing\n }\n }\n\n /**\n * Returns basic keycodes as constants\n * @return {{}}\n */\n static get keyCodes() {\n return {\n BACKSPACE: 8,\n TAB: 9,\n ENTER: 13,\n SHIFT: 16,\n CTRL: 17,\n ALT: 18,\n ESC: 27,\n SPACE: 32,\n LEFT: 37,\n UP: 38,\n DOWN: 40,\n RIGHT: 39,\n DELETE: 46,\n META: 91\n };\n }\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 return new Promise(function (resolve) {\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 return previousValue\n .then(() => waitNextBlock(currentValue, success, fallback))\n .then(() => {\n // finished\n if (iteration === chains.length - 1) {\n resolve();\n }\n });\n }, Promise.resolve());\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 return new Promise(function (resolve) {\n chainData.function()\n .then(() => {\n successCallback(chainData.data || {});\n })\n .then(resolve)\n .catch(function () {\n fallbackCallback(chainData.data || {});\n\n // anyway, go ahead even it falls\n resolve();\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 return Array.prototype.slice.call(collection);\n }\n\n /**\n * Checks if object is empty\n *\n * @param {Object} object\n * @return {boolean}\n */\n static isEmpty(object) {\n return Object.keys(object).length === 0 && object.constructor === Object;\n }\n\n /**\n * Check if passed object is a Promise\n * @param {*} object - object to check\n * @return {Boolean}\n */\n static isPromise(object) {\n return Promise.resolve(object) === object;\n }\n\n /**\n * Check if passed element is contenteditable\n * @param element\n * @return {boolean}\n */\n static isContentEditable(element) {\n return element.contentEditable === 'true';\n }\n\n /**\n * Delays method execution\n *\n * @param method\n * @param timeout\n */\n static delay(method, timeout) {\n return function () {\n let context = this,\n args = arguments;\n\n window.setTimeout(() => method.apply(context, args), timeout);\n };\n }\n};\n","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \":root {\\n\\n /**\\n * Toolbar buttons\\n */\\n --bg-light: #eff2f5;\\n\\n /**\\n * All gray texts: placeholders, settings\\n */\\n --grayText: #707684;\\n\\n /**\\n * Block content width\\n */\\n --content-width: 650px;\\n\\n /**\\n * Toolbar Plus Button and Toolbox buttons height and width\\n */\\n --toolbar-buttons-size: 34px\\n\\n}\\n/**\\n* Editor wrapper\\n*/\\n.codex-editor {\\n position: relative;\\n border: 1px solid #ccc;\\n padding: 2px;\\n box-sizing: border-box;\\n}\\n.codex-editor .hide {\\n display: none;\\n }\\n.codex-editor__redactor {\\n padding-bottom: 300px;\\n }\\n.ce-toolbar {\\n position: absolute;\\n left: 0;\\n right: 0;\\n top: 0;\\n /*opacity: 0;*/\\n /*visibility: hidden;*/\\n transition: opacity 100ms ease;\\n will-change: opacity, transform;\\n display: none;\\n}\\n.ce-toolbar--opened {\\n display: block;\\n /*opacity: 1;*/\\n /*visibility: visible;*/\\n }\\n.ce-toolbar__content {\\n max-width: 650px;\\n max-width: var(--content-width);\\n margin: 0 auto;\\n position: relative;\\n }\\n.ce-toolbar__plus {\\n position: absolute;\\n left: calc(-var(--toolbar-buttons-size) - 10px);\\n left: calc(-var(--toolbar-buttons-size) - 10px);\\n display: inline-block;\\n background-color: #eff2f5;\\n background-color: var(--bg-light);\\n width: 34px;\\n width: var(--toolbar-buttons-size);\\n height: 34px;\\n height: var(--toolbar-buttons-size);\\n line-height: 34px;\\n text-align: center;\\n border-radius: 50%\\n }\\n.ce-toolbar__plus::after {\\n content: '+';\\n font-size: 26px;\\n display: block;\\n margin-top: -2px;\\n margin-right: -2px;\\n }\\n.ce-toolbar__plus--hidden {\\n display: none;\\n }\\n/**\\n * Block actions Zone\\n * -------------------------\\n */\\n.ce-toolbar__actions {\\n position: absolute;\\n right: 0;\\n top: 0;\\n border: 1px dotted #ccc;\\n padding: 2px;\\n }\\n.ce-toolbar__actions-buttons {\\n border: 1px dotted #ccc;\\n padding: 2px;\\n text-align: right;\\n margin-bottom: 2px;\\n }\\n.ce-toolbar__settings-btn {\\n display: inline-block;\\n width: 24px;\\n height: 24px;\\n border: 1px dotted #ccc\\n }\\n.ce-toolbar__settings-btn::before {\\n content: 'STN';\\n font-size: 10px;\\n opacity: .4;\\n }\\n.ce-toolbox {\\n position: absolute;\\n visibility: hidden;\\n transition: opacity 100ms ease;\\n will-change: opacity;\\n}\\n.ce-toolbox--opened {\\n opacity: 1;\\n visibility: visible;\\n }\\n.ce-toolbox__button {\\n display: inline-block;\\n list-style: none;\\n margin: 0;\\n background: #eff2f5;\\n background: var(--bg-light);\\n width: 34px;\\n width: var(--toolbar-buttons-size);\\n height: 34px;\\n height: var(--toolbar-buttons-size);\\n border-radius: 30px;\\n overflow: hidden;\\n text-align: center;\\n line-height: 34px;\\n line-height: var(--toolbar-buttons-size)\\n }\\n.ce-toolbox__button::before {\\n content: attr(title);\\n font-size: 22px;\\n font-weight: 500;\\n letter-spacing: 1em;\\n -webkit-font-feature-settings: \\\"smcp\\\", \\\"c2sc\\\";\\n font-feature-settings: \\\"smcp\\\", \\\"c2sc\\\";\\n font-variant-caps: all-small-caps;\\n padding-left: 11.5px;\\n margin-top: -1px;\\n display: inline-block;\\n }\\n.ce-inline-toolbar {\\n position: absolute;\\n background: #FFFFFF;\\n box-shadow: 0 8px 23px -6px rgba(21,40,54,0.31), 22px -14px 34px -18px rgba(33,48,73,0.26);\\n border-radius: 4px;\\n z-index: 2\\n}\\n.ce-inline-toolbar::before {\\n content: '';\\n width: 15px;\\n height: 15px;\\n position: absolute;\\n top: -7px;\\n left: 50%;\\n margin-left: -7px;\\n transform: rotate(-45deg);\\n background: #fff;\\n }\\n.ce-inline-toolbar {\\n\\n width: 100px;\\n height: 40px;\\n transform: translateX(-50%);\\n display: none;\\n}\\n.ce-inline-toolbar--showed {\\n display: block;\\n }\\n.ce-settings {\\n border: 1px dotted #ccc;\\n padding: 2px;\\n display: none;\\n}\\n.ce-settings--opened {\\n display: block;\\n }\\n.ce-settings__plugin-zone {\\n border: 1px dotted #ccc;\\n padding: 2px;\\n margin-bottom: 2px\\n }\\n.ce-settings__plugin-zone::before {\\n content: 'PLUGIN SETTINGS';\\n opacity: .4;\\n font-size: 12px;\\n }\\n.ce-settings__default-zone {\\n border: 1px dotted #ccc;\\n padding: 2px\\n }\\n.ce-settings__default-zone::before {\\n content: 'DEFAULT SETTINGS';\\n opacity: .4;\\n font-size: 12px;\\n }\\n.ce-settings__button {\\n padding: 10px 15px;\\n color: #707684;\\n color: var(--grayText)\\n }\\n.ce-settings__button:hover {\\n background: #eff2f5;\\n background: var(--bg-light);\\n }\\n.ce-block {\\n border: 1px dotted #ccc;\\n margin: 2px 0\\n}\\n.ce-block:first-of-type {\\n margin-top: 0;\\n }\\n.ce-block--selected {\\n background-color: #eff2f5;\\n background-color: var(--bg-light);\\n }\\n.ce-block__content {\\n max-width: 650px;\\n max-width: var(--content-width);\\n margin: 0 auto;\\n }\\n\", \"\"]);\n\n// exports\n"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/tools.md b/docs/tools.md index 9b5dbdda3..56a2be09f 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -20,7 +20,9 @@ Method that specifies how to merge two `Blocks` of the same type, for example on Method does accept data object in same format as the `Render` and it should provide logic how to combine new data with the currently stored value. -### Available settings +### Internal Tool Settings + +Options that Tool can specify. All settings should be passed as static properties of Tool's class. | Name | Type | Default Value | Description | | -- | -- | -- | -- | @@ -29,4 +31,34 @@ data with the currently stored value. | `irreplaceable` | _Boolean_ | `false` | By default, **empty** `Blocks` can be **replaced** by other `Blocks` with the `Toolbox`. Some tools with media-content may prefer another behaviour. Pass `true` and `Toolbox` will add a new block below yours. | | `contentless` | _Boolean_ | `false` | Pass `true` for Tool which represents decorative empty `Blocks` | +### User configuration + +All Tools can be configured by users. For this reason, we provide `toolConfig` option at the Editor Initial Settings. +Unlike Internal Tool Settings, this options can be specified outside the Tool class, +so users can set up different configurations for the same Tool. + +```js +var editor = new CodexEditor({ + holderId : 'codex-editor', + initialBlock : 'text', + tools: { + text: Text // 'Text' Tool class for Blocks with type 'text' + }, + toolsConfig: { + text: { // user configuration for Blocks with type 'text' + inlineToolbar : true, + } + } +}); +``` + +There are few options available by CodeX Editor. + +| Name | Type | Default Value | Description | +| -- | -- | -- | -- | +| `enableLineBreaks` | _Boolean_ | `false` | With this option, CodeX Editor won't handle Enter keydowns. Can be helpful for Tools like `` where line breaks should be handled by default behaviour. | +| `inlineToolbar` | _Boolean/Array_ | `false` | Pass `true` to enable the Inline Toolbar with all Tools, or pass an array with specified Tools list | + + + ### Sanitize diff --git a/example/example.html b/example/example.html index 82225213e..c74d8c80c 100644 --- a/example/example.html +++ b/example/example.html @@ -65,9 +65,10 @@ text: Text }, toolsConfig: { + text: { + inlineToolbar : true, + }, quote: { - iconClassname : 'quote-icon', - displayInToolbox : true, enableLineBreaks : true } }, diff --git a/example/plugins/text/text.js b/example/plugins/text/text.js index 86f110f97..0fc012f4a 100644 --- a/example/plugins/text/text.js +++ b/example/plugins/text/text.js @@ -12,146 +12,120 @@ * @property {String} text — HTML content to insert to text element * */ - class Text { - - /** - * Pass true to display this tool in the Editor's Toolbox - * - * @returns {boolean} - */ - static get displayInToolbox() { - - return true; - - } - - /** - * Class for the Toolbox icon - * - * @returns {string} - */ - static get iconClassName() { - - return 'cdx-text-icon'; - - } - - /** - * Render plugin`s html and set initial content - * - * @param {TextData} data — initial plugin content - */ - constructor(data = {}) { - - this._CSS = { - wrapper: 'ce-text' - }; - - this._data = {}; - this._element = this.draw(); - - this.data = data; - } - - /** - * Method fires before rendered data appended to the editors area - */ - appendCallback() { - - console.log("text appended"); - - } - - draw() { - - let div = document.createElement('DIV'); - - div.classList.add(this._CSS.wrapper); - div.contentEditable = true; - - return div; - } - - /** - * Create div element and add needed css classes - * @returns {HTMLDivElement} Created DIV element - */ - render() { - - return this._element; - - } - - /** - * Merge current data with passed data - * @param {TextData} data - */ - merge(data) { - let newData = { - text : this.data.text + data.text - }; - - this.data = newData; - } - - /** - * Check if saved text is empty - * - * @param {TextData} savedData — data received from plugins`s element - * @returns {boolean} false if saved text is empty, true otherwise - */ - validate(savedData) { - - if (savedData.text.trim() === '') { - - return false; - - } - - return true; - - } - - /** - * Get plugin`s element HTMLDivElement - * @param {HTMLDivElement} block - returned self content - * @returns {HTMLDivElement} Plugin`s element - */ - save(block) { - - return this.data; - - } - - /** - * Get current plugin`s data - * - * @todo sanitize data while saving - * - * @returns {TextData} Current data - */ - get data() { - - let text = this._element.innerHTML; - - this._data.text = text; - - return this._data; - - } - - /** - * Set new data for plugin - * - * @param {TextData} data — data to set - */ - set data(data) { - - Object.assign(this._data, data); - - this._element.innerHTML = this._data.text || ''; - + /** + * Pass true to display this tool in the Editor's Toolbox + * @returns {boolean} + */ + static get displayInToolbox() { + return true; + } + + /** + * Class for the Toolbox icon + * @returns {string} + */ + static get iconClassName() { + return 'cdx-text-icon'; + } + + /** + * Render plugin`s html and set initial content + * @param {TextData} data — initial plugin content + */ + constructor(data = {}, config) { + this._CSS = { + wrapper: 'ce-text' + }; + + this._data = {}; + this._element = this.draw(); + + this.data = data; + } + + /** + * Method fires before rendered data appended to the editors area + */ + appendCallback() { + console.log("text appended"); + } + + draw() { + let div = document.createElement('DIV'); + + div.classList.add(this._CSS.wrapper); + div.contentEditable = true; + + return div; + } + + /** + * Create div element and add needed css classes + * @returns {HTMLDivElement} Created DIV element + */ + render() { + return this._element; + } + + /** + * Merge current data with passed data + * @param {TextData} data + */ + merge(data) { + let newData = { + text : this.data.text + data.text + }; + + this.data = newData; + } + + /** + * Check if saved text is empty + * + * @param {TextData} savedData — data received from plugins`s element + * @returns {boolean} false if saved text is empty, true otherwise + */ + validate(savedData) { + if (savedData.text.trim() === '') { + return false; } -} \ No newline at end of file + return true; + } + + /** + * Get plugin`s element HTMLDivElement + * @param {HTMLDivElement} block - returned self content + * @returns {HTMLDivElement} Plugin`s element + */ + save(block) { + return this.data; + } + + /** + * Get current plugin`s data + * + * @todo sanitize data while saving + * + * @returns {TextData} Current data + */ + get data() { + let text = this._element.innerHTML; + + this._data.text = text; + + return this._data; + } + + /** + * Set new data for plugin + * + * @param {TextData} data — data to set + */ + set data(data) { + Object.assign(this._data, data); + + this._element.innerHTML = this._data.text || ''; + } +} diff --git a/src/components/block.js b/src/components/block.js index 24dd3c040..b5ed09ec7 100644 --- a/src/components/block.js +++ b/src/components/block.js @@ -215,4 +215,4 @@ export default class Block { this._html.classList.remove(Block.CSS.selected); } } -} \ No newline at end of file +} diff --git a/src/components/modules/blockManager.js b/src/components/modules/blockManager.js index d12269f84..9f2ac63fc 100644 --- a/src/components/modules/blockManager.js +++ b/src/components/modules/blockManager.js @@ -101,7 +101,7 @@ export default class BlockManager extends Module { bindEvents(block) { this.Editor.Listeners.on(block.pluginsContent, 'keydown', (event) => this.Editor.Keyboard.blockKeydownsListener(event)); this.Editor.Listeners.on(block.pluginsContent, 'mouseup', (event) => { - this.Editor.InlineToolbar.move(event); + this.Editor.InlineToolbar.handleShowingEvent(event); }); } @@ -246,10 +246,14 @@ export default class BlockManager extends Module { /** * Get Block instance by html element - * @param {HTMLElement} element + * @param {Node} element * @returns {Block} */ getBlock(element) { + if (!$.isElement(element)) { + element = element.parentNode; + } + let nodes = this._blocks.nodes, firstLevelBlock = element.closest(`.${Block.CSS.wrapper}`), index = nodes.indexOf(firstLevelBlock); @@ -544,4 +548,4 @@ class Blocks { return instance.get(index); } -} \ No newline at end of file +} diff --git a/src/components/modules/caret.js b/src/components/modules/caret.js index bd55c3759..db6c4bd23 100644 --- a/src/components/modules/caret.js +++ b/src/components/modules/caret.js @@ -9,11 +9,11 @@ * @version 2.0.0 */ +import Selection from '../selection'; + /** * @typedef {Caret} Caret */ -import Selection from '../Selection'; - export default class Caret extends Module { /** * @constructor diff --git a/src/components/modules/keyboard.js b/src/components/modules/keyboard.js index 0b6aff6e9..29f378755 100644 --- a/src/components/modules/keyboard.js +++ b/src/components/modules/keyboard.js @@ -71,7 +71,7 @@ export default class Keyboard extends Module { * Don't handle Enter keydowns when Tool sets enableLineBreaks to true. * Uses for Tools like where line breaks should be handled by default behaviour. */ - if (toolsConfig && toolsConfig.enableLineBreaks) { + if (toolsConfig && toolsConfig[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS]) { return; } @@ -146,4 +146,4 @@ export default class Keyboard extends Module { arrowLeftAndUpPressed() { this.Editor.BlockManager.navigatePrevious(); } -} \ No newline at end of file +} diff --git a/src/components/modules/listeners.js b/src/components/modules/listeners.js index d11f9f659..fbcf4e90b 100644 --- a/src/components/modules/listeners.js +++ b/src/components/modules/listeners.js @@ -146,23 +146,20 @@ export default class Listeners extends Module { * @return {Array} */ findAll(element, eventType, handler) { - let foundAllListeners, - foundByElements = [], - foundByEventType = [], - foundByHandler = []; - - if (element) - foundByElements = this.findByElement(element); - - if (eventType) - foundByEventType = this.findByType(eventType); - - if (handler) - foundByHandler = this.findByHandler(handler); - - foundAllListeners = foundByElements.concat(foundByEventType, foundByHandler); + let found, + foundByElements = element ? this.findByElement(element) : []; + // foundByEventType = eventType ? this.findByType(eventType) : [], + // foundByHandler = handler ? this.findByHandler(handler) : []; + + if (element && eventType && handler) { + found = foundByElements.filter( event => event.eventType === eventType && event.handler === handler ); + } else if (element && eventType) { + found = foundByElements.filter( event => event.eventType === eventType); + } else { + found = foundByElements; + } - return foundAllListeners; + return found; } /** @@ -175,4 +172,4 @@ export default class Listeners extends Module { this.allListeners = []; } -} \ No newline at end of file +} diff --git a/src/components/modules/toolbar-inline.ts b/src/components/modules/toolbar-inline.ts index c089a677e..c7e6e88d2 100644 --- a/src/components/modules/toolbar-inline.ts +++ b/src/components/modules/toolbar-inline.ts @@ -1,26 +1,28 @@ /** * Inline toolbar with actions that modifies selected text fragment * - * ________________________ - * | | + * |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| * | B i [link] [mark] | * | _______________________| */ declare var Module: any; declare var $: any; +declare var _: any; +import Selection from '../selection'; /** * DOM Elements */ -interface InlineToolbarNodes { - wrapper?: Element; // main wrapper +interface INodes { + wrapper?: HTMLElement; // main wrapper } /** * CSS */ -interface InlineToolbarCSS { +interface ICSS { inlineToolbar: string; + inlineToolbarShowed: string; } export default class InlineToolbar extends Module { @@ -28,17 +30,23 @@ export default class InlineToolbar extends Module { /** * Inline Toolbar elements */ - private nodes: InlineToolbarNodes = { - wrapper: null, + private nodes: INodes = { + wrapper: null, }; /** * CSS styles */ - private CSS: InlineToolbarCSS = { - inlineToolbar: 'ce-inline-toolbar', + private CSS: ICSS = { + inlineToolbar: 'ce-inline-toolbar', + inlineToolbarShowed: 'ce-inline-toolbar--showed', }; + /** + * Margin above/below the Toolbar + */ + private readonly toolbarVerticalMargin: number = 20; + /** * @constructor */ @@ -62,7 +70,98 @@ export default class InlineToolbar extends Module { } - public move() { - // moving + /** + * Shows Inline Toolbar by keyup/mouseup + * @param {KeyboardEvent|MouseEvent} event + */ + public handleShowingEvent(event): void { + if (!this.allowedToShow(event)) { + this.close(); + return; + } + + this.move(); + this.open(); + } + + /** + * Move Toolbar to the selected text + */ + public move(): void { + + const selectionRect = Selection.rect; + const wrapperOffset = this.Editor.UI.nodes.wrapper.getBoundingClientRect(); + + const newCoords = { + x: selectionRect.x - wrapperOffset.left, + y: selectionRect.y + + selectionRect.height + // + window.scrollY + - wrapperOffset.top + + this.toolbarVerticalMargin, + }; + + /** + * If we know selections width, place InlineToolbar to center + */ + if (selectionRect.width) { + newCoords.x += Math.floor(selectionRect.width / 2); + } + + this.nodes.wrapper.style.left = Math.floor(newCoords.x) + 'px'; + this.nodes.wrapper.style.top = Math.floor(newCoords.y) + 'px'; + } + + /** + * Shows Inline Toolbar + */ + private open() { + this.nodes.wrapper.classList.add(this.CSS.inlineToolbarShowed); + } + + /** + * Hides Inline Toolbar + */ + private close() { + this.nodes.wrapper.classList.remove(this.CSS.inlineToolbarShowed); + } + + /** + * Need to show Inline Toolbar or not + * @param {KeyboardEvent|MouseEvent} event + */ + private allowedToShow(event): boolean { + /** + * Tags conflicts with window.selection function. + * Ex. IMG tag returns null (Firefox) or Redactors wrapper (Chrome) + */ + const tagsConflictsWithSelection = ['IMG', 'INPUT']; + if (event && tagsConflictsWithSelection.includes(event.target.tagName)) { + return false; + } + + const currentSelection = Selection.get(), + selectedText = Selection.text; + + // old browsers + if (!currentSelection || !currentSelection.anchorNode) { + return false; + } + + // empty selection + if (currentSelection.isCollapsed || selectedText.length < 1) { + return false; + } + + // is enabled by current Block's Tool + const currentBlock = this.Editor.BlockManager.getBlock(currentSelection.anchorNode); + + if (!currentBlock) { + return false; + } + + const toolConfig = this.config.toolsConfig[currentBlock.name]; + + return toolConfig && toolConfig[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR]; } } diff --git a/src/components/modules/toolbar-toolbox.js b/src/components/modules/toolbar-toolbox.js index 1620c96f2..f4811ce66 100644 --- a/src/components/modules/toolbar-toolbox.js +++ b/src/components/modules/toolbar-toolbox.js @@ -67,7 +67,9 @@ export default class Toolbox extends Module { * @param {Tool} tool - tool class */ addTool(toolName, tool) { - if (tool.displayInToolbox && !tool.iconClassName) { + const api = this.Editor.Tools.apiSettings; + + if (tool[api.IS_DISPLAYED_IN_TOOLBOX] && !tool[api.TOOLBAR_ICON_CLASS]) { _.log('Toolbar icon class name is missed. Tool %o skipped', 'warn', toolName); return; } @@ -85,11 +87,11 @@ export default class Toolbox extends Module { /** * Skip tools that pass 'displayInToolbox=false' */ - if (!tool.displayInToolbox) { + if (!tool[api.IS_DISPLAYED_IN_TOOLBOX]) { return; } - let button = $.make('li', [Toolbox.CSS.toolboxButton, tool.iconClassName], { + let button = $.make('li', [Toolbox.CSS.toolboxButton, tool[api.TOOLBAR_ICON_CLASS]], { title: toolName }); @@ -135,7 +137,7 @@ export default class Toolbox extends Module { * - block is not irreplaceable * @type {Array} */ - if (!tool.irreplaceable && currentBlock.isEmpty) { + if (!tool[this.Editor.Tools.apiSettings.IS_IRREPLACEBLE_TOOL] && currentBlock.isEmpty) { this.Editor.BlockManager.replace(toolName); } else { this.Editor.BlockManager.insert(toolName); @@ -184,4 +186,4 @@ export default class Toolbox extends Module { this.close(); } } -} \ No newline at end of file +} diff --git a/src/components/modules/tools.js b/src/components/modules/tools.js index 6aba767ad..432f5be44 100644 --- a/src/components/modules/tools.js +++ b/src/components/modules/tools.js @@ -11,6 +11,7 @@ * @property {String} iconClassname - this a icon in toolbar * @property {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE * @property {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE + * @property {Boolean|String[]} inlineToolbar - Pass `true` to enable the Inline Toolbar with all Tools, all pass an array with specified Tools list | * @property render @todo add description * @property save @todo add description * @property settings @todo add description @@ -57,18 +58,31 @@ export default class Tools extends Module { return this.toolsUnavailable; } + /** + * Constant for available Tools Settings + * @return {object} + */ + get apiSettings() { + return { + TOOLBAR_ICON_CLASS: 'iconClassName', + IS_DISPLAYED_IN_TOOLBOX: 'displayInToolbox', + IS_ENABLED_LINE_BREAKS: 'enableLineBreaks', + IS_IRREPLACEBLE_TOOL: 'irreplaceable', + IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar', + }; + } + /** * Static getter for default Tool config fields - * - * @usage Tools.defaultConfig.displayInToolbox * @return {ToolConfig} */ - static get defaultConfig() { + get defaultConfig() { return { - iconClassName : '', - displayInToolbox : false, - enableLineBreaks : false, - irreplaceable : false + [this.apiSettings.TOOLBAR_ICON_CLASS] : false, + [this.apiSettings.IS_DISPLAYED_IN_TOOLBOX] : false, + [this.apiSettings.IS_ENABLED_LINE_BREAKS] : false, + [this.apiSettings.IS_IRREPLACEBLE_TOOL] : false, + [this.apiSettings.IS_ENABLED_INLINE_TOOLBAR]: false, }; } @@ -192,11 +206,7 @@ export default class Tools extends Module { let plugin = this.toolClasses[tool], config = this.config.toolsConfig[tool]; - if (!config) { - config = this.defaultConfig; - } - - let instance = new plugin(data, config); + let instance = new plugin(data, config || {}); return instance; } @@ -209,4 +219,4 @@ export default class Tools extends Module { isInitial(tool) { return tool instanceof this.available[this.config.initialBlock]; } -} \ No newline at end of file +} diff --git a/src/components/modules/ui.js b/src/components/modules/ui.js index cf17d5c44..c72a5408c 100644 --- a/src/components/modules/ui.js +++ b/src/components/modules/ui.js @@ -222,17 +222,9 @@ export default class UI extends Module { /** - * @todo hide the Inline Toolbar + * Close Inline Toolbar when nothing selected */ - // var selectedText = editor.toolbar.inline.getSelectionText(), - // firstLevelBlock; - - /** If selection range took off, then we hide inline toolbar */ - // if (selectedText.length === 0) { - - // editor.toolbar.inline.close(); - - // } + this.Editor.InlineToolbar.handleShowingEvent(event); /** * diff --git a/src/components/selection.js b/src/components/selection.js index 6e799483f..1542e10ea 100644 --- a/src/components/selection.js +++ b/src/components/selection.js @@ -1,5 +1,6 @@ /** * Working with selection + * @typedef {Selection} Selection */ export default class Selection { /** @@ -24,7 +25,7 @@ export default class Selection { * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode} * @return {Node|null} */ - static getAnchorNode() { + static get anchorNode() { let selection = window.getSelection(); return selection ? selection.anchorNode : null; @@ -35,7 +36,7 @@ export default class Selection { * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset} * @return {Number|null} */ - static getAnchorOffset() { + static get anchorOffset() { let selection = window.getSelection(); return selection ? selection.anchorOffset : null; @@ -50,4 +51,75 @@ export default class Selection { return selection ? selection.isCollapsed : null; } -} \ No newline at end of file + + /** + * Calculates position and size of selected text + * @return {{x, y, width, height, top?, left?, bottom?, right?}} + */ + static get rect() { + let sel = document.selection, range; + let rect = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + + if (sel && sel.type !== 'Control') { + range = sel.createRange(); + rect.x = range.boundingLeft; + rect.y = range.boundingTop; + rect.width = range.boundingWidth; + rect.height = range.boundingHeight; + + return rect; + } + + if (!window.getSelection) { + _.log('Method window.getSelection is not supported', 'warn'); + return rect; + } + + sel = window.getSelection(); + + if (!sel.rangeCount) { + _.log('Method Selection.rangeCount() is not supported', 'warn'); + return rect; + } + + range = sel.getRangeAt(0).cloneRange(); + + if (range.getBoundingClientRect) { + rect = range.getBoundingClientRect(); + } + // Fall back to inserting a temporary element + if (rect.x === 0 && rect.y === 0) { + let span = document.createElement('span'); + + if (span.getBoundingClientRect) { + // Ensure span has dimensions and position by + // adding a zero-width space character + span.appendChild( document.createTextNode('\u200b') ); + range.insertNode(span); + rect = span.getBoundingClientRect(); + + let spanParent = span.parentNode; + + spanParent.removeChild(span); + + // Glue any broken text nodes back together + spanParent.normalize(); + } + } + + return rect; + } + + /** + * Returns selected text as String + * @returns {string} + */ + static get text() { + return window.getSelection ? window.getSelection().toString() : ''; + }; +} diff --git a/src/components/utils.js b/src/components/utils.js index b9f0e6fc3..962983431 100644 --- a/src/components/utils.js +++ b/src/components/utils.js @@ -168,4 +168,4 @@ export default class Util { window.setTimeout(() => method.apply(context, args), timeout); }; } -}; \ No newline at end of file +}; diff --git a/src/styles/inline-toolbar.css b/src/styles/inline-toolbar.css index 467bcade1..52d3b295a 100644 --- a/src/styles/inline-toolbar.css +++ b/src/styles/inline-toolbar.css @@ -1,8 +1,12 @@ .ce-inline-toolbar { - position: absolute; - z-index: 2; - @apply --overlay-pane; + @apply --overlay-pane; - width: 100px; - height: 40px; -} \ No newline at end of file + width: 100px; + height: 40px; + transform: translateX(-50%); + display: none; + + &--showed { + display: block; + } +} diff --git a/src/styles/variables.css b/src/styles/variables.css index 0fac9f693..1fb0b4d15 100644 --- a/src/styles/variables.css +++ b/src/styles/variables.css @@ -21,10 +21,11 @@ --toolbar-buttons-size: 34px; --overlay-pane: { + position: absolute; background: #FFFFFF; box-shadow: 0 8px 23px -6px rgba(21,40,54,0.31), 22px -14px 34px -18px rgba(33,48,73,0.26); border-radius: 4px; - position: relative; + z-index: 2; &::before { content: ''; @@ -39,4 +40,4 @@ } } -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index eb2a67549..9b627a8f2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,5 +2,6 @@ "compilerOptions" : { "target": "es6", "declaration": false, + "lib": ["es2016", "dom"] } } diff --git a/tslint.json b/tslint.json index cbab96619..0d151976a 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,8 @@ { "extends": "tslint:recommended", "rules": { - "quotemark": [true, "single"] + "quotemark": [true, "single"], + "no-console": false, + "one-variable-per-declaration": false } }