diff --git a/codex-editor.js b/codex-editor.js index 8ea60238..86c6aef9 100644 --- a/codex-editor.js +++ b/codex-editor.js @@ -30,7 +30,8 @@ var cEditor = (function (cEditor) { // Current editor state cEditor.state = { html : '', - blocks : [] + blocks : [], + inputs : [], }; /** @@ -53,6 +54,7 @@ var cEditor = (function (cEditor) { .then(this.transport.prepare) // .then(this.parser.parseTextareaContent) .then(this.renderer.makeBlocksFromData) + .then(this.ui.getAllInputs) .catch(function (error) { cEditor.core.log('Initialization failed with error: %o', 'warn', error); }); @@ -247,7 +249,7 @@ cEditor.renderer = { /** * add handlers to new block */ - .then(cEditor.ui.addBlockHandlers) + // .then(cEditor.ui.addBlockHandlers) /** Log if something wrong with node */ .catch(function(error) { @@ -430,8 +432,6 @@ cEditor.ui = { cEditor.callback.redactorClicked(event); - cEditor.caret.save(); - }, false ); /** Clicks to SETTINGS button in toolbar */ @@ -447,9 +447,6 @@ cEditor.ui = { */ cEditor.nodes.redactor.addEventListener('input', function (event) { - /** Saving caret in every modifications */ - cEditor.caret.save(); - cEditor.callback.redactorInputEvent(event); }, false ); @@ -477,6 +474,34 @@ cEditor.ui = { cEditor.callback.blockPaste(event, block); }, false); + }, + + /** getting all contenteditable elements */ + getAllInputs : function() { + + var redactor = cEditor.nodes.redactor, + elements = []; + + setTimeout(function () { + + var inputs = redactor.querySelectorAll('[contenteditable]'); + + for (var key in inputs) { + + /** + * querySelectorAll('[contenteditable]') returns object methods like length, keys and so on. + * We need to get only DOM elements + */ + if (cEditor.core.isDomNode(inputs[key])) { + elements[key] = inputs[key]; + } + } + + /** Save all inputs in global variable state */ + cEditor.state.inputs = elements; + + }, 10); + } }; @@ -643,6 +668,7 @@ cEditor.callback = { blockRightOrDownArrowPressed : function (block) { var selection = window.getSelection(), + inputs = cEditor.state.inputs, focusedNode = selection.anchorNode, focusedNodeHolder; @@ -651,20 +677,26 @@ cEditor.callback = { return false; } - /** Saving caret after keydown event happend */ - cEditor.caret.save(); - /** Looking for closest (parent) contentEditable element of focused node */ - while (focusedNode.className != cEditor.ui.BLOCK_CLASSNAME) { + while (focusedNode.contentEditable != 'true') { focusedNodeHolder = focusedNode.parentNode; focusedNode = focusedNodeHolder; } - /** Founded contentEditable element doesn't have childs */ - if (focusedNode.childNodes.length === 0) + /** Input index in DOM level */ + var index = 0; + while (focusedNode != inputs[index]) { + index ++; + } + + /** + * Founded contentEditable element doesn't have childs + * Or maybe New created block + */ + if (!focusedNode.textContent) { - cEditor.caret.setToNextBlock(focusedNode); + cEditor.caret.setToNextBlock(index); return; } @@ -674,16 +706,10 @@ cEditor.callback = { var caretInLastChild = false, caretAtTheEndOfText = false; - var editableElement = focusedNode.querySelector('[contenteditable]'), - lastChild, + var lastChild, deepestTextnode; - if (!editableElement) { - cEditor.core.log('Can not find editable element in current block: %o', 'warn', focusedNode); - return; - } - - lastChild = editableElement.childNodes[editableElement.childNodes.length - 1 ]; + lastChild = focusedNode.childNodes[focusedNode.childNodes.length - 1 ]; if (cEditor.core.isDomNode(lastChild)) { @@ -706,7 +732,7 @@ cEditor.callback = { return false; } - cEditor.caret.setToNextBlock(focusedNode); + cEditor.caret.setToNextBlock(index); }, @@ -716,6 +742,7 @@ cEditor.callback = { blockLeftOrUpArrowPressed : function (block) { var selection = window.getSelection(), + inputs = cEditor.state.inputs, focusedNode = selection.anchorNode, focusedNodeHolder; @@ -731,31 +758,37 @@ cEditor.callback = { return false; } - /** Saving caret after keydown event happend */ - cEditor.caret.save(); - /** Looking for parent contentEditable block */ - while (focusedNode.className != cEditor.ui.BLOCK_CLASSNAME) { + while (focusedNode.contentEditable != 'true') { focusedNodeHolder = focusedNode.parentNode; focusedNode = focusedNodeHolder; } + /** Input index in DOM level */ + var index = 0; + while (focusedNode != inputs[index]) { + index ++; + } + /** * Do nothing if caret is not at the beginning of first child */ var caretInFirstChild = false, caretAtTheBeginning = false; - var editableElement = focusedNode.querySelector('[contenteditable]'), - firstChild, + var firstChild, deepestTextnode; - if (!editableElement) { - cEditor.core.log('Can not find editable element in current block: %o', 'warn', focusedNode); + /** + * Founded contentEditable element doesn't have childs + * Or maybe New created block + */ + if (!focusedNode.textContent) { + cEditor.caret.setToPreviousBlock(index); return; } - firstChild = editableElement.childNodes[0]; + firstChild = focusedNode.childNodes[0]; if (cEditor.core.isDomNode(firstChild)) { @@ -768,14 +801,14 @@ cEditor.callback = { } caretInFirstChild = selection.anchorNode == deepestTextnode; - caretAtTheBeginning = cEditor.caret.offset === 0; + caretAtTheBeginning = selection.anchorOffset === 0; console.log("каретка в первом узле: %o", caretInFirstChild); console.log("каретка в начале первого узла: %o", caretAtTheBeginning); if ( caretInFirstChild && caretAtTheBeginning ) { - cEditor.caret.setToPreviousBlock(focusedNode); + cEditor.caret.setToPreviousBlock(index); } @@ -818,12 +851,13 @@ cEditor.callback = { backspacePressed: function (block) { - if (block.textContent.trim()) return; + cEditor.ui.getAllInputs(); - cEditor.caret.setToPreviousBlock(block); + if (block.textContent.trim()) return; block.remove(); + cEditor.toolbar.close(); cEditor.toolbar.move(); event.preventDefault(); @@ -966,10 +1000,14 @@ cEditor.content = { cEditor.content.workingNodeChanged(newBlock); /** - * Setting caret - * @todo is it necessary? + * Add block handlers */ - cEditor.caret.set(newBlock); + cEditor.ui.addBlockHandlers(newBlock); + + /** + * Save changes + */ + cEditor.ui.getAllInputs(); }, @@ -995,6 +1033,15 @@ cEditor.content = { cEditor.nodes.redactor.appendChild(newBlock); } + /** + * Save changes + */ + cEditor.ui.getAllInputs(); + + /** + * Block handler + */ + cEditor.ui.addBlockHandlers(newBlock); /** * Set new node as current @@ -1078,7 +1125,7 @@ cEditor.content = { */ cEditor.content.workingNodeChanged(nodeCreated); - cEditor.caret.set(nodeCreated); + //cEditor.caret.set(nodeCreated); }, /** @@ -1099,8 +1146,11 @@ cEditor.content = { /** Replacing */ cEditor.content.replaceBlock(blockToReplace, newBlockComposed, blockType); + /** Save new Inputs when block is changed */ + cEditor.ui.getAllInputs(); + /** Add event listeners */ - cEditor.ui.addBlockHandlers(newBlock); + //cEditor.ui.addBlockHandlers(newBlockComposed); }, @@ -1198,6 +1248,11 @@ cEditor.content = { cEditor.caret = { + /** + * @var {int} InputIndex - editable element in DOM + */ + InputIndex : null, + /** * @var {int} offset - caret position in a text node. */ @@ -1261,8 +1316,6 @@ cEditor.caret = { * Creates Document Range and sets caret to the element. * @uses caret.save — if you need to save caret position * @param {Element} el - Changed Node. - * @todo remove saving positon - * @todo - Check nodeToSet for type: if TAG -> look for nearest TextNode */ set : function( el , index, offset) { @@ -1282,6 +1335,11 @@ cEditor.caret = { } + if (cEditor.core.isDomNode(nodeToSet)) { + + nodeToSet = cEditor.content.getDeepestTextNodeFromPosition(nodeToSet, nodeToSet.childNodes.length); + } + var range = document.createRange(), selection = window.getSelection(); @@ -1293,7 +1351,7 @@ cEditor.caret = { selection.removeAllRanges(); selection.addRange(range); - }, 50); + }, 20); }, /** @@ -1306,58 +1364,41 @@ cEditor.caret = { /** * @param {Element} block - element from which we take next block */ - setToNextBlock : function(block) { + setToNextBlock : function(index) { - cEditor.caret.offset = 0; - cEditor.caret.focusedNodeIndex = 0; + var inputs = cEditor.state.inputs, + nextInput = inputs[index + 1]; - var nextBlock = block.nextSibling, - nextBlockEditableElement; - - console.log("nextBlock: %o", nextBlock); - - nextBlockEditableElement = nextBlock.querySelector('[contenteditable]'); - - console.log("nextBlockEditableElement: %o", nextBlockEditableElement); - - - if ( !block.nextSibling ) { - return false; + if (nextInput.childNodes.length === 0) { + var emptyTextElement = document.createTextNode(''); + nextInput.appendChild(emptyTextElement); } + cEditor.caret.InputIndex = nextInput; + cEditor.caret.set(nextInput, 0, 0); + cEditor.content.workingNodeChanged(nextInput); - cEditor.caret.set(nextBlockEditableElement, 0, 0); - cEditor.content.workingNodeChanged(block.nextSibling); }, /** * @todo передалать на prevBlock.querySelector('[contenteditable]') по аналогии с setToNextBlock */ - setToPreviousBlock : function(block) { + setToPreviousBlock : function(index) { - if ( !block.previousSibling ) { - return false; + var inputs = cEditor.state.inputs, + previousInput = inputs[index - 1]; + + lastChildNode = cEditor.content.getDeepestTextNodeFromPosition(previousInput, previousInput.childNodes.length); + lengthOfLastChildNode = lastChildNode.length; + + if (previousInput.childNodes.length === 0) { + var emptyTextElement = document.createTextNode(''); + previousInput.appendChild(emptyTextElement); } - var lastChildOfPreiviousBlockIndex = block.previousSibling.childNodes.length, - previousBlock = block.previousSibling, - theEndOfPreviousBlockLastNode = 0; - - /** Index in childs Array */ - if (block.previousSibling.childNodes.length !== 0) { - - previousBlock = cEditor.content.getDeepestTextNodeFromPosition(block.previousSibling, lastChildOfPreiviousBlockIndex); - theEndOfPreviousBlockLastNode = previousBlock.length; - lastChildOfPreiviousBlockIndex = 0; - - } - - cEditor.caret.offset = theEndOfPreviousBlockLastNode; - cEditor.caret.focusedNodeIndex = lastChildOfPreiviousBlockIndex; - - cEditor.caret.set(previousBlock, lastChildOfPreiviousBlockIndex, theEndOfPreviousBlockLastNode); - - cEditor.content.workingNodeChanged(block.previousSibling); + cEditor.caret.InputIndex = previousInput; + cEditor.caret.set(previousInput, previousInput.childNodes.length - 1, lengthOfLastChildNode); + cEditor.content.workingNodeChanged(inputs[index - 1]); }, }; @@ -1414,13 +1455,11 @@ cEditor.toolbar = { leaf : function(){ var currentTool = this.current, - // tools = cEditor.settings.tools, tools = Object.keys(cEditor.tools), barButtons = cEditor.nodes.toolbarButtons, nextToolIndex, toolToSelect; - // console.log(tools); if ( !currentTool ) { /** Get first tool from object*/ @@ -1479,6 +1518,8 @@ cEditor.toolbar = { appendCallback.call(); } + /** Save new changes */ + cEditor.ui.getAllInputs(); }, @@ -1771,6 +1812,7 @@ cEditor.parser = { } return null; }) + .then(cEditor.ui.addBlockHandlers) /** Log if something wrong with node */ @@ -1877,11 +1919,6 @@ cEditor.parser = { }; -cEditor.tools = { - -}; - - /** * Creates HTML elements */ @@ -1979,285 +2016,13 @@ cEditor.draw = { } - }; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** -* Paragraph Plugin\ -* Creates P tag and adds content to this tag +* Developer plugins */ -var paragraphTool = { - /** - * Make initial header block - * @param {object} JSON with block data - * @return {Element} element to append - */ - make : function (data) { - - var tag = document.createElement('DIV'); - - if (data && data.text) { - tag.innerHTML = data.text; - } - - tag.contentEditable = true; - - return tag; - - }, - - /** - * Method to render HTML block from JSON - */ - render : function (data) { - - return paragraphTool.make(data); - - }, - - /** - * Method to extract JSON data from HTML block - */ - save : function (block){ - - var data = { - text : null - }; - - data.text = blockData.textContent; - - return data; - - }, - -}; - -/** -* Now plugin is ready. -* Add it to redactor tools -*/ -cEditor.tools.paragraph = { - - type : 'paragraph', - iconClassname : 'ce-icon-paragraph', - make : paragraphTool.make, - appendCallback : null, - settings : null, - render : paragraphTool.render, - save : paragraphTool.save - -}; - -/** -* Example of making plugin -* H e a d e r -*/ -var headerTool = { - - /** - * Make initial header block - * @param {object} JSON with block data - * @return {Element} element to append - */ - make : function (data) { - - var availableTypes = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'], - tag; - - if (data && data.type && availableTypes.includes(data.type)) { - - tag = document.createElement( data.type ); - - /** - * Save header type in data-attr. - * We need it in save method to extract type from HTML to JSON - */ - tag.dataset.headerData = data.type; - - } else { - - tag = document.createElement( 'H2' ); - - } - - if (data && data.text) { - tag.textContent = data.text; - } - - tag.contentEditable = true; - - return tag; - - }, - - /** - * Method to render HTML block from JSON - */ - render : function (data) { - - return headerTool.make(data); - - }, - - /** - * Method to extract JSON data from HTML block - */ - save : function (block){ - - var data = { - type : null, - text : null - }; - - data.type = blockData.dataset.headerData; - data.text = blockData.textContent; - - return data; - - }, - - /** - * Block appending callback - */ - appendCallback : function (argument) { - - console.log('header appended...'); - - }, - - /** - * Settings panel content - * - - - - - - - - - - - - - - * | настройки H1 H2 H3 | - * - - - - - - - - - - - - - - * @return {Element} element contains all settings - */ - makeSettings : function () { - - var holder = document.createElement('DIV'), - caption = document.createElement('SPAN'), - types = { - H2: 'Заголовок раздела', - H3: 'Подзаголовок', - H4: 'Заголовок 3-его уровня' - }, - selectTypeButton; - - /** Add holder classname */ - holder.className = 'ce_plugin_header--settings'; - - /** Add settings helper caption */ - caption.textContent = 'Настройки заголовка'; - caption.className = 'ce_plugin_header--caption'; - - holder.appendChild(caption); - - /** Now add type selectors */ - for (var type in types){ - - selectTypeButton = document.createElement('SPAN'); - - selectTypeButton.textContent = types[type]; - selectTypeButton.className = 'ce_plugin_header--select_button'; - - this.addSelectTypeClickListener(selectTypeButton, type); - - holder.appendChild(selectTypeButton); - - } - - return holder; - - }, - - /** - * Binds click event to passed button - */ - addSelectTypeClickListener : function (el, type) { - - el.addEventListener('click', function () { - - headerTool.selectTypeClicked(type); - - }, false); - }, - - /** - * Replaces old header with new type - * @params {string} type - new header tagName: H1—H6 - */ - selectTypeClicked : function (type) { - - var old_header, new_header; - - /** Now current header stored as a currentNode */ - old_header = cEditor.content.currentNode; - - /** Making new header */ - new_header = document.createElement(type); - - new_header.innerHTML = old_header.innerHTML; - new_header.contentEditable = true; - - cEditor.content.replaceBlock(old_header, new_header, 'header'); - - /** Add listeners for Arrow keys*/ - cEditor.ui.addBlockHandlers(new_header); - - /** Close settings after replacing */ - cEditor.toolbar.settings.close(); - - }, - -}; - -/** -* Now plugin is ready. -* Add it to redactor tools -*/ -cEditor.tools.header = { - - type : 'header', - iconClassname : 'ce-icon-header', - make : headerTool.make, - appendCallback : headerTool.appendCallback, - settings : headerTool.makeSettings(), - render : headerTool.render, - save : headerTool.save +cEditor.tools = { }; diff --git a/editor.css b/editor.css index 19643e52..d39925d5 100644 --- a/editor.css +++ b/editor.css @@ -181,39 +181,6 @@ border-radius: 3px; } - - - - - - - -/** -* Plugin styles -*/ - - -/** H e a d e r - settings */ -.ce_plugin_header--settings{ - white-space: nowrap; - /*padding-right: 10px; */ -} -.ce_plugin_header--caption{ - color: #b9c2c2; -} -.ce_plugin_header--select_button{ - display: inline-block; - margin-left: 40px; - border-bottom: 1px solid #c3d5ed; - padding-bottom: 2px; - color: #5399d4; - cursor: pointer; -} - .ce_plugin_header--select_button:hover{ - border-bottom-color: #f6d8da; - color: #cc7d74; - } - /* @-webkit-keyframes bounceIn { 0% { opacity: 0; -webkit-transform: scale(.3);} diff --git a/example.html b/example.html index 69483bfb..25dce745 100644 --- a/example.html +++ b/example.html @@ -269,16 +269,22 @@ - - + + - - + + - - + + - - + + + + + + + + diff --git a/plugins/ceditor-tool-code/ceditor-tool-code.css b/plugins/code/code.css similarity index 100% rename from plugins/ceditor-tool-code/ceditor-tool-code.css rename to plugins/code/code.css diff --git a/plugins/ceditor-tool-code/ceditor-tool-code.js b/plugins/code/code.js similarity index 100% rename from plugins/ceditor-tool-code/ceditor-tool-code.js rename to plugins/code/code.js diff --git a/plugins/header/header.css b/plugins/header/header.css new file mode 100644 index 00000000..ffc21f06 --- /dev/null +++ b/plugins/header/header.css @@ -0,0 +1,23 @@ +/** +* Plugin styles +*/ +/** H e a d e r - settings */ +.ce_plugin_header--settings{ + white-space: nowrap; + /*padding-right: 10px; */ +} +.ce_plugin_header--caption{ + color: #b9c2c2; +} +.ce_plugin_header--select_button{ + display: inline-block; + margin-left: 40px; + border-bottom: 1px solid #c3d5ed; + padding-bottom: 2px; + color: #5399d4; + cursor: pointer; +} + .ce_plugin_header--select_button:hover{ + border-bottom-color: #f6d8da; + color: #cc7d74; + } diff --git a/plugins/header/header.js b/plugins/header/header.js new file mode 100644 index 00000000..e1fdab35 --- /dev/null +++ b/plugins/header/header.js @@ -0,0 +1,178 @@ +/** +* Example of making plugin +* H e a d e r +*/ +var headerTool = { + + /** + * Make initial header block + * @param {object} JSON with block data + * @return {Element} element to append + */ + make : function (data) { + + var availableTypes = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'], + tag; + + if (data && data.type && availableTypes.includes(data.type)) { + + tag = document.createElement( data.type ); + + /** + * Save header type in data-attr. + * We need it in save method to extract type from HTML to JSON + */ + tag.dataset.headerData = data.type; + + } else { + + tag = document.createElement( 'H2' ); + + } + + if (data && data.text) { + tag.textContent = data.text; + } + + tag.contentEditable = true; + + return tag; + + }, + + /** + * Method to render HTML block from JSON + */ + render : function (data) { + + return headerTool.make(data); + + }, + + /** + * Method to extract JSON data from HTML block + */ + save : function (block){ + + var data = { + type : null, + text : null + }; + + data.type = blockData.dataset.headerData; + data.text = blockData.textContent; + + return data; + + }, + + /** + * Block appending callback + */ + appendCallback : function (argument) { + + console.log('header appended...'); + + }, + + /** + * Settings panel content + * - - - - - - - - - - - - - + * | настройки H1 H2 H3 | + * - - - - - - - - - - - - - + * @return {Element} element contains all settings + */ + makeSettings : function () { + + var holder = document.createElement('DIV'), + caption = document.createElement('SPAN'), + types = { + H2: 'Заголовок раздела', + H3: 'Подзаголовок', + H4: 'Заголовок 3-его уровня' + }, + selectTypeButton; + + /** Add holder classname */ + holder.className = 'ce_plugin_header--settings'; + + /** Add settings helper caption */ + caption.textContent = 'Настройки заголовка'; + caption.className = 'ce_plugin_header--caption'; + + holder.appendChild(caption); + + /** Now add type selectors */ + for (var type in types){ + + selectTypeButton = document.createElement('SPAN'); + + selectTypeButton.textContent = types[type]; + selectTypeButton.className = 'ce_plugin_header--select_button'; + + this.addSelectTypeClickListener(selectTypeButton, type); + + holder.appendChild(selectTypeButton); + + } + + return holder; + + }, + + /** + * Binds click event to passed button + */ + addSelectTypeClickListener : function (el, type) { + + el.addEventListener('click', function () { + + headerTool.selectTypeClicked(type); + + }, false); + }, + + /** + * Replaces old header with new type + * @params {string} type - new header tagName: H1—H6 + */ + selectTypeClicked : function (type) { + + var old_header, new_header; + + /** Now current header stored as a currentNode */ + old_header = cEditor.content.currentNode; + + /** Making new header */ + new_header = document.createElement(type); + + new_header.innerHTML = old_header.innerHTML; + new_header.contentEditable = true; + + cEditor.content.replaceBlock(old_header, new_header, 'header'); + + /** Add listeners for Arrow keys*/ + cEditor.ui.addBlockHandlers(new_header); + + /** Close settings after replacing */ + cEditor.toolbar.settings.close(); + + }, + +}; + +/** +* Now plugin is ready. +* Add it to redactor tools +*/ +cEditor.tools.header = { + + type : 'header', + iconClassname : 'ce-icon-header', + make : headerTool.make, + appendCallback : headerTool.appendCallback, + settings : headerTool.makeSettings(), + render : headerTool.render, + save : headerTool.save + +}; diff --git a/plugins/ceditor-tool-link/ceditor-tool-link.css b/plugins/link/link.css similarity index 100% rename from plugins/ceditor-tool-link/ceditor-tool-link.css rename to plugins/link/link.css diff --git a/plugins/ceditor-tool-link/ceditor-tool-link.js b/plugins/link/link.js similarity index 100% rename from plugins/ceditor-tool-link/ceditor-tool-link.js rename to plugins/link/link.js diff --git a/plugins/ceditor-tool-link/loading.gif b/plugins/link/loading.gif similarity index 100% rename from plugins/ceditor-tool-link/loading.gif rename to plugins/link/loading.gif diff --git a/plugins/ceditor-tool-list/ceditor-tool-list.css b/plugins/list/list.css similarity index 100% rename from plugins/ceditor-tool-list/ceditor-tool-list.css rename to plugins/list/list.css diff --git a/plugins/ceditor-tool-list/ceditor-tool-list.js b/plugins/list/list.js similarity index 100% rename from plugins/ceditor-tool-list/ceditor-tool-list.js rename to plugins/list/list.js diff --git a/plugins/paragraph/paragraph.css b/plugins/paragraph/paragraph.css new file mode 100644 index 00000000..e69de29b diff --git a/plugins/paragraph/paragraph.js b/plugins/paragraph/paragraph.js new file mode 100644 index 00000000..28e49282 --- /dev/null +++ b/plugins/paragraph/paragraph.js @@ -0,0 +1,66 @@ +/** +* Paragraph Plugin\ +* Creates P tag and adds content to this tag +*/ +var paragraphTool = { + + /** + * Make initial header block + * @param {object} JSON with block data + * @return {Element} element to append + */ + make : function (data) { + + var tag = document.createElement('DIV'); + + if (data && data.text) { + tag.innerHTML = data.text; + } + + tag.contentEditable = true; + + return tag; + + }, + + /** + * Method to render HTML block from JSON + */ + render : function (data) { + + return paragraphTool.make(data); + + }, + + /** + * Method to extract JSON data from HTML block + */ + save : function (block){ + + var data = { + text : null + }; + + data.text = blockData.textContent; + + return data; + + }, + +}; + +/** +* Now plugin is ready. +* Add it to redactor tools +*/ +cEditor.tools.paragraph = { + + type : 'paragraph', + iconClassname : 'ce-icon-paragraph', + make : paragraphTool.make, + appendCallback : null, + settings : null, + render : paragraphTool.render, + save : paragraphTool.save + +}; diff --git a/plugins/ceditor-tool-quote/img/01.jpg b/plugins/quote/img/01.jpg similarity index 100% rename from plugins/ceditor-tool-quote/img/01.jpg rename to plugins/quote/img/01.jpg diff --git a/plugins/ceditor-tool-quote/img/codex.png b/plugins/quote/img/codex.png similarity index 100% rename from plugins/ceditor-tool-quote/img/codex.png rename to plugins/quote/img/codex.png diff --git a/plugins/ceditor-tool-quote/img/upload.png b/plugins/quote/img/upload.png similarity index 100% rename from plugins/ceditor-tool-quote/img/upload.png rename to plugins/quote/img/upload.png diff --git a/plugins/ceditor-tool-quote/ceditor-tool-quote.css b/plugins/quote/quote.css similarity index 100% rename from plugins/ceditor-tool-quote/ceditor-tool-quote.css rename to plugins/quote/quote.css diff --git a/plugins/ceditor-tool-quote/ceditor-tool-quote.js b/plugins/quote/quote.js similarity index 100% rename from plugins/ceditor-tool-quote/ceditor-tool-quote.js rename to plugins/quote/quote.js