dante2-editor 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/demo/assets/index.html +1 -1
- data/demo/assets/license.html +1 -1
- data/demo/assets/options.html +1 -1
- data/dist/Dante2.js +5992 -4276
- data/dist/Dante2.min.js +2 -2
- data/dist/Dante2.min.js.map +1 -1
- data/dist/DanteStyles.js +6 -6
- data/dist/DanteStyles.min.js +1 -1
- data/dist/DanteStyles.min.js.map +1 -1
- data/dist/dante-vendors.js +665 -634
- data/dist/dante-vendors.min.js +2 -2
- data/dist/dante-vendors.min.js.map +1 -1
- data/docs/app.js +10 -10
- data/docs/app.js.map +1 -1
- data/docs/dante-vendors.js +8949 -7309
- data/docs/dante-vendors.js.map +1 -1
- data/docs/dante.js +272 -194
- data/docs/dante.js.map +1 -1
- data/package.json +4 -6
- data/rb_lib/dante2-editor/version.rb +1 -1
- data/src/components/blocks/image.js +3 -1
- data/src/components/core/editor.js +68 -11
- data/src/components/popovers/addButton.js +3 -27
- data/src/components/popovers/image.js +26 -19
- data/src/components/popovers/link.js +12 -3
- data/src/components/popovers/toolTip.js +16 -2
- data/src/model/index.js +1 -1
- data/src/utils/save_content.js +1 -1
- data/src/utils/selection.js +13 -0
- data/yarn.lock +22 -173
- metadata +2 -2
data/docs/dante.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"dante.js","sources":["webpack:///src/components/core/editor.js","webpack:///./src/styles/fonts/dante/dante.eot","webpack:///./src/styles/fonts/dante/fontello.eot","webpack:///src/index.js","webpack:///./src/styles/dante.scss?293d","webpack:///demo/initialize.js","webpack:///src/components/blocks/embed.js","webpack:///src/components/blocks/image.js","webpack:///src/components/blocks/placeholder.js","webpack:///src/components/blocks/video.js","webpack:///src/components/core/dante.js","webpack:///src/components/core/debug.js","webpack:///src/components/decorators/link.js","webpack:///src/components/init.js","webpack:///src/components/popovers/addButton.js","webpack:///src/components/popovers/image.js","webpack:///src/components/popovers/link.js","webpack:///src/components/popovers/toolTip.js","webpack:///src/utils/find_entities.js","webpack:///src/utils/html2content.js","webpack:///src/utils/save_content.js","webpack:///src/model/index.js","webpack:///./src/styles/fonts/dante/dante.svg","webpack:///./src/styles/fonts/dante/dante.ttf","webpack:///./src/styles/fonts/dante/dante.woff","webpack:///./src/styles/fonts/dante/fontello.svg","webpack:///./src/styles/fonts/dante/fontello.ttf","webpack:///./src/styles/fonts/dante/fontello.woff","webpack:///src/utils/selection.js"],"sourcesContent":["\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport Immutable from 'immutable'\nimport { Map, fromJS } from 'immutable'\nimport { \n convertToRaw, \n convertFromRaw, \n CompositeDecorator, \n getDefaultKeyBinding,\n ContentState, \n Editor, \n EditorState, \n Entity, \n RichUtils, \n DefaultDraftBlockRenderMap, \n SelectionState, \n Modifier\n} from 'draft-js'\n\nimport { \n convertToHTML,\n //, convertFromHTML \n} from 'draft-convert'\n\nimport { \n addNewBlock, \n resetBlockWithType, \n updateDataOfBlock, \n //updateTextOfBlock, \n getCurrentBlock, \n addNewBlockAt \n} from '../../model/index.js'\n\nimport Link from '../decorators/link'\nimport Debug from './debug'\nimport findEntities from '../../utils/find_entities'\nimport SaveBehavior from '../../utils/save_content'\nimport customHTML2Content from '../../utils/html2content'\nimport createStyles from 'draft-js-custom-styles';\n\n\nclass DanteEditor extends React.Component {\n constructor(props) {\n super(props)\n\n this.initializeState = this.initializeState.bind(this)\n this.refreshSelection = this.refreshSelection.bind(this)\n this.forceRender = this.forceRender.bind(this)\n this.onChange = this.onChange.bind(this)\n this.dispatchChangesToSave = this.dispatchChangesToSave.bind(this)\n this.setPreContent = this.setPreContent.bind(this)\n this.focus = this.focus.bind(this)\n this.getEditorState = this.getEditorState.bind(this)\n this.emitSerializedOutput = this.emitSerializedOutput.bind(this)\n this.decodeEditorContent = this.decodeEditorContent.bind(this)\n this.getTextFromEditor = this.getTextFromEditor.bind(this)\n this.getLocks = this.getLocks.bind(this)\n this.addLock = this.addLock.bind(this)\n this.removeLock = this.removeLock.bind(this)\n this.renderableBlocks = this.renderableBlocks.bind(this)\n this.defaultWrappers = this.defaultWrappers.bind(this)\n this.blockRenderer = this.blockRenderer.bind(this)\n this.handleBlockRenderer = this.handleBlockRenderer.bind(this)\n this.blockStyleFn = this.blockStyleFn.bind(this)\n this.getDataBlock = this.getDataBlock.bind(this)\n this.styleForBlock = this.styleForBlock.bind(this)\n this.handlePasteText = this.handlePasteText.bind(this)\n this.handleTXTPaste = this.handleTXTPaste.bind(this)\n this.handleHTMLPaste = this.handleHTMLPaste.bind(this)\n this.handlePasteImage = this.handlePasteImage.bind(this)\n this.handleDroppedFiles = this.handleDroppedFiles.bind(this)\n this.handleUpArrow = this.handleUpArrow.bind(this)\n this.handleDownArrow = this.handleDownArrow.bind(this)\n this.handleReturn = this.handleReturn.bind(this)\n this.handleBeforeInput = this.handleBeforeInput.bind(this)\n this.handleKeyCommand = this.handleKeyCommand.bind(this)\n this.findCommandKey = this.findCommandKey.bind(this)\n this.KeyBindingFn = this.KeyBindingFn.bind(this)\n this.updateBlockData = this.updateBlockData.bind(this)\n this.setDirection = this.setDirection.bind(this)\n this.toggleEditable = this.toggleEditable.bind(this)\n this.disableEditable = this.disableEditable.bind(this)\n this.enableEditable = this.enableEditable.bind(this)\n this.closePopOvers = this.closePopOvers.bind(this)\n this.relocateTooltips = this.relocateTooltips.bind(this)\n this.tooltipsWithProp = this.tooltipsWithProp.bind(this)\n this.tooltipHasSelectionElement = this.tooltipHasSelectionElement.bind(this)\n this.handleShowPopLinkOver = this.handleShowPopLinkOver.bind(this)\n this.handleHidePopLinkOver = this.handleHidePopLinkOver.bind(this)\n this.showPopLinkOver = this.showPopLinkOver.bind(this)\n this.hidePopLinkOver = this.hidePopLinkOver.bind(this)\n this.render = this.render.bind(this)\n\n this.decorator = new CompositeDecorator([{\n strategy: findEntities.bind(null, 'LINK', this),\n component: Link\n }])\n\n this.blockRenderMap = Map({\n \"image\": {\n element: 'figure'\n },\n \"video\": {\n element: 'figure'\n },\n \"embed\": {\n element: 'div'\n },\n 'unstyled': {\n wrapper: null,\n element: 'div'\n },\n 'paragraph': {\n wrapper: null,\n element: 'div'\n },\n 'placeholder': {\n wrapper: null,\n element: 'div'\n }\n\n })\n\n this.extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(this.blockRenderMap)\n\n this.state = {\n editorState: EditorState.createEmpty(),\n read_only: this.props.config.read_only,\n blockRenderMap: this.extendedBlockRenderMap,\n locks: 0,\n debug: this.props.config.debug\n }\n\n this.widgets = this.props.config.widgets\n this.tooltips = this.props.config.tooltips\n\n this.key_commands = this.props.config.key_commands\n\n this.continuousBlocks = this.props.config.continuousBlocks\n\n this.block_types = this.props.config.block_types\n\n this.default_wrappers = this.props.config.default_wrappers\n\n this.character_convert_mapping = this.props.config.character_convert_mapping\n\n this.save = new SaveBehavior({\n getLocks: this.getLocks,\n config: {\n xhr: this.props.config.xhr,\n data_storage: this.props.config.data_storage\n },\n editorState: this.state.editorState,\n editorContent: this.emitSerializedOutput()\n })\n\n const { styles, customStyleFn, exporter } = createStyles(['font-size', 'color', 'font-family']); //, 'PREFIX', customStyleMap);\n this.styles = styles\n this.customStyleFn = customStyleFn\n }\n\n componentDidMount(){\n this.initializeState()\n }\n\n initializeState() {\n let newEditorState = EditorState.createEmpty(this.decorator)\n if (this.props.content) {\n newEditorState = EditorState.set(this.decodeEditorContent(this.props.content), {decorator: this.decorator});\n }\n this.onChange(newEditorState) \n }\n\n decodeEditorContent(raw_as_json) {\n const new_content = convertFromRaw(raw_as_json)\n let editorState\n return editorState = EditorState.createWithContent(new_content, this.decorator)\n }\n\n refreshSelection(newEditorState) {\n const { editorState } = this.state\n // Setting cursor position after inserting to content\n const s = this.state.editorState.getSelection()\n const c = editorState.getCurrentContent()\n const focusOffset = s.getFocusOffset()\n const anchorKey = s.getAnchorKey()\n\n let selectionState = SelectionState.createEmpty(s.getAnchorKey())\n\n // console.log anchorKey, focusOffset\n selectionState = selectionState.merge({\n anchorOffset: focusOffset,\n focusKey: anchorKey,\n focusOffset\n })\n\n let newState = EditorState.forceSelection(newEditorState, selectionState)\n\n return this.onChange(newState)\n }\n\n forceRender(editorState) {\n const selection = this.state.editorState.getSelection()\n const content = editorState.getCurrentContent()\n const newEditorState = EditorState.createWithContent(content, this.decorator)\n\n return this.refreshSelection(newEditorState)\n }\n\n onChange(editorState) {\n this.setPreContent()\n this.setState({ editorState })\n\n const currentBlock = getCurrentBlock(this.state.editorState)\n const blockType = currentBlock.getType()\n\n if (!editorState.getSelection().isCollapsed()) {\n\n const tooltip = this.tooltipsWithProp('displayOnSelection')[0]\n if (!this.tooltipHasSelectionElement(tooltip, blockType)) {\n return\n }\n this.handleTooltipDisplayOn('displayOnSelection')\n } else {\n this.handleTooltipDisplayOn('displayOnSelection', false)\n }\n\n setTimeout(() => {\n return this.relocateTooltips()\n }, 0)\n\n return this.dispatchChangesToSave()\n }\n\n dispatchChangesToSave() {\n clearTimeout(this.saveTimeout)\n return this.saveTimeout = setTimeout(() => {\n return this.save.store(this.emitSerializedOutput())\n }, 100)\n }\n\n setPreContent() {\n const content = this.emitSerializedOutput()\n return this.save.editorContent = content\n }\n\n focus() {\n //debugger\n }\n //@props.refs.richEditor.focus()\n\n getEditorState() {\n return this.state.editorState\n }\n\n emitSerializedOutput() {\n const raw = convertToRaw(this.state.editorState.getCurrentContent())\n\n return raw\n }\n\n //# title utils\n getTextFromEditor() {\n const c = this.state.editorState.getCurrentContent()\n const out = c.getBlocksAsArray().map(o => {\n return o.getText()\n }).join(\"\\n\")\n\n return out\n }\n\n emitHTML2() {\n let html\n\n return html = convertToHTML({\n entityToHTML: (entity, originalText) => {\n if (entity.type === 'LINK') {\n return `<a href=\\\"${ entity.data.url }\\\">${ originalText }</a>`\n } else {\n return originalText\n }\n }\n\n })(this.state.editorState.getCurrentContent())\n }\n\n getLocks() {\n return this.state.locks\n }\n\n addLock() {\n return this.setState({\n locks: this.state.locks += 1 })\n }\n\n removeLock() {\n return this.setState({\n locks: this.state.locks -= 1 })\n }\n\n renderableBlocks() {\n return this.widgets.filter(o => o.renderable).map(o => o.type)\n }\n\n defaultWrappers(blockType) {\n return this.default_wrappers.filter(o => {\n return o.block === blockType\n }).map(o => o.className)\n }\n\n blockRenderer(block) {\n\n switch (block.getType()) {\n\n case \"atomic\":\n\n const entity = block.getEntityAt(0)\n const entity_type = Entity.get(entity).getType()\n\n break\n }\n\n if (this.renderableBlocks().includes(block.getType())) {\n return this.handleBlockRenderer(block)\n }\n\n return null\n }\n\n handleBlockRenderer(block) {\n const dataBlock = this.getDataBlock(block)\n if (!dataBlock) {\n return null\n }\n\n const read_only = this.state.read_only ? false : null\n const editable = read_only !== null ? read_only : dataBlock.editable\n return {\n component: eval(dataBlock.block),\n editable,\n props: {\n data: block.getData(),\n getEditorState: this.getEditorState,\n setEditorState: this.onChange,\n addLock: this.addLock,\n toggleEditable: this.toggleEditable,\n disableEditable: this.disableEditable,\n enableEditable: this.enableEditable,\n removeLock: this.removeLock,\n getLocks: this.getLocks,\n config: dataBlock.options\n }\n }\n\n return null\n }\n\n blockStyleFn(block) {\n const currentBlock = getCurrentBlock(this.state.editorState)\n const is_selected = currentBlock.getKey() === block.getKey() ? \"is-selected\" : \"\"\n\n if (this.renderableBlocks().includes(block.getType())) {\n return this.styleForBlock(block, currentBlock, is_selected)\n }\n\n const defaultBlockClass = this.defaultWrappers(block.getType())\n if (defaultBlockClass.length > 0) {\n return `graf ${ defaultBlockClass[0] } ${ is_selected }`\n } else {\n return `graf nana ${ is_selected }`\n }\n }\n\n getDataBlock(block) {\n return this.widgets.find(o => {\n return o.type === block.getType()\n })\n }\n\n styleForBlock(block, currentBlock, is_selected) {\n const dataBlock = this.getDataBlock(block)\n\n if (!dataBlock) {\n return null\n }\n\n const selectedFn = dataBlock.selectedFn ? dataBlock.selectedFn(block) : null\n const selected_class = is_selected ? dataBlock.selected_class : ''\n\n return `${ dataBlock.wrapper_class } ${ selected_class } ${ selectedFn }`\n }\n\n handleTooltipDisplayOn(prop, display) {\n\n // for button click on after inline style set, \n // avoids inline popver to reappear on previous selection\n if(this.state.read_only){\n return \n }\n\n if (display == null) {\n display = true\n }\n \n return setTimeout(() => {\n const items = this.tooltipsWithProp(prop)\n console.log(items)\n return items.map(o => {\n this.refs[o.ref].display(display)\n return this.refs[o.ref].relocate()\n })\n }, 20)\n }\n\n handlePasteText(text, html) {\n\n // https://github.com/facebook/draft-js/issues/685\n /*\n html = \"<p>chao</p>\n <avv>aaa</avv>\n <p>oli</p>\n <img src='x'/>\"\n */\n\n // if not html then fallback to default handler\n\n if (!html) {\n return this.handleTXTPaste(text, html)\n }\n if (html) {\n return this.handleHTMLPaste(text, html)\n }\n }\n\n handleTXTPaste(text, html) {\n const currentBlock = getCurrentBlock(this.state.editorState)\n\n let { editorState } = this.state\n\n switch (currentBlock.getType()) {\n case \"image\":case \"video\":case \"placeholder\":\n const newContent = Modifier.replaceText(editorState.getCurrentContent(), new SelectionState({\n anchorKey: currentBlock.getKey(),\n anchorOffset: 0,\n focusKey: currentBlock.getKey(),\n focusOffset: 2\n }), text)\n\n editorState = EditorState.push(editorState, newContent, 'replace-text')\n\n this.onChange(editorState)\n\n return true\n default:\n return false\n }\n }\n\n handleHTMLPaste(text, html) {\n\n const currentBlock = getCurrentBlock(this.state.editorState)\n\n // TODO: make this configurable\n switch (currentBlock.getType()) {\n case \"image\":case \"video\":case \"placeholder\":\n return this.handleTXTPaste(text, html)\n break\n }\n\n const newContentState = customHTML2Content(html, this.extendedBlockRenderMap)\n\n const selection = this.state.editorState.getSelection()\n const endKey = selection.getEndKey()\n\n const content = this.state.editorState.getCurrentContent()\n const blocksBefore = content.blockMap.toSeq().takeUntil(v => v.key === endKey)\n const blocksAfter = content.blockMap.toSeq().skipUntil(v => v.key === endKey).rest()\n\n const newBlockKey = newContentState.blockMap.first().getKey()\n\n const newBlockMap = blocksBefore.concat(newContentState.blockMap, blocksAfter).toOrderedMap()\n\n const newContent = content.merge({\n blockMap: newBlockMap,\n selectionBefore: selection,\n selectionAfter: selection.merge({\n anchorKey: newBlockKey,\n anchorOffset: 0,\n focusKey: newBlockKey,\n focusOffset: 0,\n isBackward: false\n })\n })\n\n const pushedContentState = EditorState.push(this.state.editorState, newContent, 'insert-fragment')\n\n this.onChange(pushedContentState)\n\n return true\n }\n\n handlePasteImage(files) {\n //TODO: check file types\n return files.map(file => {\n let opts = {\n url: URL.createObjectURL(file),\n file\n }\n\n return this.onChange(addNewBlock(this.state.editorState, 'image', opts))\n })\n }\n\n handleDroppedFiles(state, files) {\n return files.map(file => {\n let opts = {\n url: URL.createObjectURL(file),\n file\n }\n\n return this.onChange(addNewBlock(this.state.editorState, 'image', opts))\n })\n }\n\n handleUpArrow(e) {\n return setTimeout(() => {\n return this.forceRender(this.state.editorState)\n }, 10)\n }\n\n handleDownArrow(e) {\n return setTimeout(() => {\n return this.forceRender(this.state.editorState)\n }, 10)\n }\n\n handleReturn(e) {\n if (this.props.handleReturn) {\n if (this.props.handleReturn()) {\n return true\n }\n }\n\n let { editorState } = this.state\n\n if (e.shiftKey) {\n this.setState({ editorState: RichUtils.insertSoftNewline(editorState) });\n return true;\n }\n\n\n if (!e.altKey && !e.metaKey && !e.ctrlKey) {\n const currentBlock = getCurrentBlock(editorState)\n const blockType = currentBlock.getType()\n const selection = editorState.getSelection()\n\n const config_block = this.getDataBlock(currentBlock)\n\n if (currentBlock.getText().length === 0) {\n\n if (config_block && config_block.handleEnterWithoutText) {\n config_block.handleEnterWithText(this, currentBlock)\n this.closePopOvers()\n return true\n }\n\n //TODO turn this in configurable\n switch (blockType) {\n case \"header-one\":\n this.onChange(resetBlockWithType(editorState, \"unstyled\"))\n return true\n break\n default:\n return false\n }\n }\n\n if (currentBlock.getText().length > 0) {\n\n if (config_block && config_block.handleEnterWithText) {\n config_block.handleEnterWithText(this, currentBlock)\n this.closePopOvers()\n return true\n }\n\n if (currentBlock.getLength() === selection.getStartOffset()) {\n if (this.continuousBlocks.indexOf(blockType) < 0) {\n this.onChange(addNewBlockAt(editorState, currentBlock.getKey()))\n return true\n }\n }\n\n return false\n }\n\n // selection.isCollapsed() and # should we check collapsed here?\n if (currentBlock.getLength() === selection.getStartOffset()) {\n //or (config_block && config_block.breakOnContinuous))\n // it will match the unstyled for custom blocks\n if (this.continuousBlocks.indexOf(blockType) < 0) {\n this.onChange(addNewBlockAt(editorState, currentBlock.getKey()))\n return true\n }\n return false\n }\n\n return false\n }\n }\n\n //return false\n\n // TODO: make this configurable\n handleBeforeInput(chars) {\n const currentBlock = getCurrentBlock(this.state.editorState)\n const blockType = currentBlock.getType()\n const selection = this.state.editorState.getSelection()\n\n let { editorState } = this.state\n\n // close popovers\n if (currentBlock.getText().length !== 0) {\n //@closeInlineButton()\n this.closePopOvers()\n }\n\n // handle space on link\n const endOffset = selection.getEndOffset()\n const endKey = currentBlock.getEntityAt(endOffset - 1)\n const endEntityType = endKey && Entity.get(endKey).getType()\n const afterEndKey = currentBlock.getEntityAt(endOffset)\n const afterEndEntityType = afterEndKey && Entity.get(afterEndKey).getType()\n\n // will insert blank space when link found\n if (chars === ' ' && endEntityType === 'LINK' && afterEndEntityType !== 'LINK') {\n const newContentState = Modifier.insertText(editorState.getCurrentContent(), selection, ' ')\n const newEditorState = EditorState.push(editorState, newContentState, 'insert-characters')\n this.onChange(newEditorState)\n return true\n }\n\n // block transform\n if (blockType.indexOf('atomic') === 0) {\n return false\n }\n\n const blockLength = currentBlock.getLength()\n if (selection.getAnchorOffset() > 1 || blockLength > 1) {\n return false\n }\n\n const blockTo = this.character_convert_mapping[currentBlock.getText() + chars]\n\n console.log(`BLOCK TO SHOW: ${ blockTo }`)\n\n if (!blockTo) {\n return false\n }\n\n this.onChange(resetBlockWithType(editorState, blockTo))\n\n return true\n }\n\n // TODO: make this configurable\n handleKeyCommand(command) {\n const { editorState } = this.state\n let currentBlockType, newBlockType\n\n if (this.props.handleKeyCommand && this.props.handleKeyCommand(command)) {\n return true\n }\n\n if (command === 'add-new-block') {\n this.onChange(addNewBlock(editorState, 'blockquote'))\n return true\n }\n\n const block = getCurrentBlock(editorState)\n\n if (command.indexOf('toggle_inline:') === 0) {\n newBlockType = command.split(':')[1]\n currentBlockType = block.getType()\n this.onChange(RichUtils.toggleInlineStyle(editorState, newBlockType))\n return true\n }\n\n if (command.indexOf('toggle_block:') === 0) {\n newBlockType = command.split(':')[1]\n currentBlockType = block.getType()\n\n this.onChange(RichUtils.toggleBlockType(editorState, newBlockType))\n return true\n }\n\n const newState = RichUtils.handleKeyCommand(this.state.editorState, command)\n if (newState) {\n this.onChange(newState)\n return true\n }\n\n return false\n }\n\n findCommandKey(opt, command) {\n // console.log \"COMMAND find: #{opt} #{command}\"\n return this.key_commands[opt].find(o => o.key === command)\n }\n\n KeyBindingFn(e) {\n\n //⌘ + B / Ctrl + B Bold\n //⌘ + I / Ctrl + I Italic\n //⌘ + K / Ctrl + K Turn into link\n //⌘ + Alt + 1 / Ctrl + Alt + 1 Header\n //⌘ + Alt + 2 / Ctrl + Alt + 2 Sub-Header\n //⌘ + Alt + 5 / Ctrl + Alt + 5 Quote (Press once for a block quote, again for a pull quote and a third time to turn off quote)\n\n let cmd\n if (e.altKey) {\n if (e.shiftKey) {\n cmd = this.findCommandKey(\"alt-shift\", e.which)\n if (cmd) {\n return cmd.cmd\n }\n\n return getDefaultKeyBinding(e)\n }\n\n if (e.ctrlKey || e.metaKey) {\n cmd = this.findCommandKey(\"alt-cmd\", e.which)\n if (cmd) {\n return cmd.cmd\n }\n return getDefaultKeyBinding(e)\n }\n } else if (e.ctrlKey || e.metaKey) {\n cmd = this.findCommandKey(\"cmd\", e.which)\n if (cmd) {\n return cmd.cmd\n }\n return getDefaultKeyBinding(e)\n }\n\n return getDefaultKeyBinding(e)\n }\n\n // will update block state todo: movo to utils\n updateBlockData(block, options) {\n const data = block.getData()\n const newData = data.merge(options)\n const newState = updateDataOfBlock(this.state.editorState, block, newData)\n // this fixes enter from image caption\n return this.forceRender(newState)\n }\n\n setDirection(direction_type) {\n const contentState = this.state.editorState.getCurrentContent()\n const selectionState = this.state.editorState.getSelection()\n const block = contentState.getBlockForKey(selectionState.anchorKey)\n\n return this.updateBlockData(block, { direction: direction_type })\n }\n\n //# read only utils\n toggleEditable() {\n this.closePopOvers()\n return this.setState({ read_only: !this.state.read_only }, this.testEmitAndDecode)\n }\n\n disableEditable() {\n console.log(\"in !!\")\n this.closePopOvers()\n return this.setState({ read_only: true }, this.testEmitAndDecode)\n }\n\n enableEditable() {\n this.closePopOvers()\n console.log(\"out !!\")\n return this.setState({ read_only: false }, this.testEmitAndDecode)\n }\n\n closePopOvers() {\n return this.tooltips.map(o => {\n return this.refs[o.ref].hide()\n })\n }\n\n relocateTooltips() {\n if (this.state.read_only)\n return \n\n return this.tooltips.map(o => {\n return this.refs[o.ref].relocate()\n })\n }\n\n tooltipsWithProp(prop) {\n return this.tooltips.filter(o => {\n return o[prop]\n })\n }\n\n tooltipHasSelectionElement(tooltip, element) {\n return tooltip.selectionElements.includes(element)\n }\n\n //################################\n // TODO: this methods belongs to popovers/link\n //################################\n\n handleShowPopLinkOver(e) {\n return this.showPopLinkOver()\n }\n\n handleHidePopLinkOver(e) {\n return this.hidePopLinkOver()\n }\n\n showPopLinkOver(el) {\n // handles popover display\n // using anchor or from popover\n\n const parent_el = ReactDOM.findDOMNode(this)\n\n // set url first in order to calculate popover width\n let coords\n this.refs.anchor_popover.setState({ url: el ? el.href : this.refs.anchor_popover.state.url })\n\n if (el) {\n coords = this.refs.anchor_popover.relocate(el)\n }\n\n if (coords) {\n this.refs.anchor_popover.setPosition(coords)\n }\n\n this.refs.anchor_popover.setState({ show: true })\n\n this.isHover = true\n return this.cancelHide()\n }\n\n hidePopLinkOver() {\n return this.hideTimeout = setTimeout(() => {\n return this.refs.anchor_popover.hide()\n }, 300)\n }\n\n cancelHide() {\n // console.log \"Cancel Hide\"\n return clearTimeout(this.hideTimeout)\n }\n\n //##############################\n\n render() {\n return (\n <div id=\"content\" suppressContentEditableWarning={ true }>\n <article className=\"postArticle\">\n <div className=\"postContent\">\n <div className=\"notesSource\">\n <div id=\"editor\" className=\"postField postField--body\">\n <section className=\"section--first section--last\">\n <div className=\"section-divider layoutSingleColumn\">\n <hr className=\"section-divider\" />\n </div>\n <div className=\"section-content\">\n <div ref=\"richEditor\" \n className=\"section-inner layoutSingleColumn\"\n onClick={ this.focus }>\n <Editor\n blockRendererFn={ this.blockRenderer }\n editorState={ this.state.editorState }\n onChange={ this.onChange }\n onUpArrow={ this.handleUpArrow }\n onDownArrow={ this.handleDownArrow }\n handleReturn={ this.handleReturn }\n blockRenderMap={ this.state.blockRenderMap }\n blockStyleFn={ this.blockStyleFn }\n customStyleFn={this.customStyleFn }\n handlePastedText={ this.handlePasteText }\n handlePastedFiles={ this.handlePasteImage }\n handleDroppedFiles={ this.handleDroppedFiles }\n handleKeyCommand={ this.handleKeyCommand }\n keyBindingFn={ this.KeyBindingFn }\n handleBeforeInput={ this.handleBeforeInput }\n readOnly={ this.state.read_only }\n placeholder={ this.props.config.body_placeholder }\n ref=\"editor\"\n />\n </div>\n </div>\n </section>\n </div>\n </div>\n </div>\n </article>\n {\n this.tooltips.map( (o, i) => {\n return (\n <o.component\n ref={ o.ref }\n key={ i }\n editor={ this }\n editorState={ this.state.editorState }\n onChange={ this.onChange }\n styles={this.styles}\n configTooltip={ o }\n widget_options={ o.widget_options }\n showPopLinkOver={ this.showPopLinkOver }\n hidePopLinkOver={ this.hidePopLinkOver }\n handleOnMouseOver={ this.handleShowPopLinkOver }\n handleOnMouseOut={ this.handleHidePopLinkOver }\n />\n )\n })\n }\n {\n this.state.debug\n ? <Debug locks={ this.state.locks } editor={ this } />\n : undefined\n }\n </div>\n\n )\n }\n}\n\nexport default DanteEditor\n\n\n\n// WEBPACK FOOTER //\n// src/components/core/editor.js","module.exports = __webpack_public_path__ + \"fonts/dante.eot\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.eot\n// module id = 184\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.eot\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.eot\n// module id = 185\n// module chunks = 0","\nimport {DanteEditor, Dante} from './components/init.js'\n\nwindow.Dante = Dante\nwindow.DanteEditor = DanteEditor\n\nexport {\n Dante, \n DanteEditor\n}\n\n\n// WEBPACK FOOTER //\n// src/index.js","// removed by extract-text-webpack-plugin\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/dante.scss\n// module id = 192\n// module chunks = 0","import 'styles/dante'\nimport { Dante, DanteEditor } from '../src/index'\n/*\nmodule.exports = {\n Dante, \n DanteEditor\n}*/\n\n\n// WEBPACK FOOTER //\n// demo/initialize.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorBlock } from 'draft-js'\n\nimport axios from \"axios\"\n\nimport { updateDataOfBlock } from '../../model/index.js'\n\nexport default class EmbedBlock extends React.Component {\n constructor(props) {\n super(props)\n //api_key = \"86c28a410a104c8bb58848733c82f840\"\n\n this.updateData = this.updateData.bind(this)\n this.dataForUpdate = this.dataForUpdate.bind(this)\n this.componentDidMount = this.componentDidMount.bind(this)\n this.state = {\n embed_data: this.defaultData(),\n error: \"\"\n }\n }\n\n defaultData() {\n const existing_data = this.props.block.getData().toJS()\n return existing_data.embed_data || {}\n }\n\n // will update block state\n updateData() {\n const { block, blockProps } = this.props\n const { getEditorState, setEditorState } = this.props.blockProps\n const data = block.getData()\n const newData = data.merge(this.state)\n return setEditorState(updateDataOfBlock(getEditorState(), block, newData))\n }\n\n dataForUpdate() {\n\n return this.props.blockProps.data.toJS()\n }\n\n componentDidMount() {\n\n if (!this.props.blockProps.data) {\n return\n }\n\n // ensure data isnt already loaded\n // unless @dataForUpdate().endpoint or @dataForUpdate().provisory_text\n\n if (!this.dataForUpdate().endpoint && !this.dataForUpdate().provisory_text) {\n //debugger\n return\n }\n\n return axios({\n method: 'get',\n url: `${ this.dataForUpdate().endpoint }${ this.dataForUpdate().provisory_text }&scheme=https`\n }).then(result => {\n\n return this.setState({ embed_data: result.data } //JSON.parse(data.responseText)\n , this.updateData)\n }).catch(error => {\n\n this.setState({\n error: error.response.data.error_message })\n return console.log(\"TODO: error\")\n })\n }\n\n classForImage() {\n if (this.state.embed_data.images) {\n return \"\"\n } else {\n return \"mixtapeImage--empty u-ignoreBlock\"\n }\n }\n //if @state.embed_data.thumbnail_url then \"\" else \"mixtapeImage--empty u-ignoreBlock\"\n\n picture() {\n if (this.state.embed_data.images && this.state.embed_data.images.length > 0) {\n return this.state.embed_data.images[0].url\n } else {\n return \"\"\n }\n }\n\n render() {\n //block = @.props\n //foo = @.props.blockProps\n //data = Entity.get(block.block.getEntityAt(0)).getData()\n console.log(\"ERROR\", this.state.error)\n return (\n <span>\n { this.picture()\n ? <a\n target='_blank'\n className={ `js-mixtapeImage mixtapeImage ${ this.classForImage() }` }\n href={ this.state.embed_data.url }\n style={ { backgroundImage: `url('${ this.picture() }')` } }\n />\n : undefined\n }\n { this.state.error ? \n <h2>{ this.state.error }</h2>\n : undefined\n }\n <a\n className='markup--anchor markup--mixtapeEmbed-anchor'\n target='_blank'\n href={ this.state.embed_data.url }\n >\n <strong className='markup--strong markup--mixtapeEmbed-strong'>\n { this.state.embed_data.title }\n </strong>\n <em className='markup--em markup--mixtapeEmbed-em'>\n { this.state.embed_data.description }\n </em>\n </a>{ this.state.embed_data.provider_url }\n </span>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/embed.js","import React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport {\n Entity, \n RichUtils, \n AtomicBlockUtils, \n EditorBlock, \n EditorState } from 'draft-js'\n\nimport axios from \"axios\"\n\nimport { updateDataOfBlock } from '../../model/index.js'\n\nexport default class ImageBlock extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.blockPropsSrc = this.blockPropsSrc.bind(this)\n this.defaultUrl = this.defaultUrl.bind(this)\n this.defaultAspectRatio = this.defaultAspectRatio.bind(this)\n this.updateData = this.updateData.bind(this)\n this.replaceImg = this.replaceImg.bind(this)\n this.startLoader = this.startLoader.bind(this)\n this.stopLoader = this.stopLoader.bind(this)\n this.handleUpload = this.handleUpload.bind(this)\n this.aspectRatio = this.aspectRatio.bind(this)\n this.updateDataSelection = this.updateDataSelection.bind(this)\n this.handleGrafFigureSelectImg = this.handleGrafFigureSelectImg.bind(this)\n this.getUploadUrl = this.getUploadUrl.bind(this)\n this.uploadFile = this.uploadFile.bind(this)\n this.uploadFailed = this.uploadFailed.bind(this)\n this.uploadCompleted = this.uploadCompleted.bind(this)\n this.updateProgressBar = this.updateProgressBar.bind(this)\n this.placeHolderEnabled = this.placeHolderEnabled.bind(this)\n this.placeholderText = this.placeholderText.bind(this)\n this.handleFocus = this.handleFocus.bind(this)\n this.render = this.render.bind(this)\n let existing_data = this.props.block.getData().toJS()\n\n this.config = this.props.blockProps.config\n this.file = this.props.blockProps.data.get('file')\n this.state = {\n loading: false,\n selected: false,\n loading_progress: 0,\n caption: this.defaultPlaceholder(),\n direction: existing_data.direction || \"center\",\n width: 0,\n height: 0,\n file: null,\n url: this.blockPropsSrc() || this.defaultUrl(existing_data),\n aspect_ratio: this.defaultAspectRatio(existing_data)\n }\n }\n\n blockPropsSrc() {\n // console.log @.props.blockProps.data.src\n return this.props.blockProps.data.src\n }\n /*\n debugger\n block = @.props\n entity = block.block.getEntityAt(0)\n if entity\n data = Entity.get(entity).getData().src\n else\n null\n */\n\n defaultUrl(data) {\n if (data.url) {\n return data.url\n }\n\n if (data.url) {\n if (data.file) {\n return URL.createObjectURL(data.file)\n } else {\n return data.url\n }\n } else {\n return this.props.blockProps.data.src\n }\n }\n\n defaultPlaceholder() {\n return this.props.blockProps.config.image_caption_placeholder\n }\n\n defaultAspectRatio(data) {\n if (data.aspect_ratio) {\n return {\n width: data.aspect_ratio['width'],\n height: data.aspect_ratio['height'],\n ratio: data.aspect_ratio['ratio']\n }\n } else {\n return {\n width: 0,\n height: 0,\n ratio: 100\n }\n }\n }\n\n getAspectRatio(w, h) {\n let maxWidth = 1000\n let maxHeight = 1000\n let ratio = 0\n let width = w // Current image width\n let height = h // Current image height\n\n // Check if the current width is larger than the max\n if (width > maxWidth) {\n ratio = maxWidth / width // get ratio for scaling image\n height = height * ratio // Reset height to match scaled image\n width = width * ratio // Reset width to match scaled image\n\n // Check if current height is larger than max\n } else if (height > maxHeight) {\n ratio = maxHeight / height // get ratio for scaling image\n width = width * ratio // Reset width to match scaled image\n height = height * ratio // Reset height to match scaled image\n }\n\n let fill_ratio = height / width * 100\n let result = { width, height, ratio: fill_ratio }\n // console.log result\n return result\n }\n\n // will update block state\n updateData() {\n let { blockProps } = this.props\n let { block } = this.props\n let { getEditorState } = this.props.blockProps\n let { setEditorState } = this.props.blockProps\n let data = block.getData()\n let newData = data.merge(this.state).merge({ forceUpload: false })\n return setEditorState(updateDataOfBlock(getEditorState(), block, newData))\n }\n\n replaceImg() {\n this.img = new Image()\n this.img.src = this.refs.image_tag.src\n this.setState({\n url: this.img.src })\n let self = this\n // exit only when not blob and not forceUload\n if (!this.img.src.includes(\"blob:\") && !this.props.block.data.get(\"forceUpload\")) {\n return\n }\n return this.img.onload = () => {\n this.setState({\n width: this.img.width,\n height: this.img.height,\n aspect_ratio: self.getAspectRatio(this.img.width, this.img.height)\n })\n\n return this.handleUpload()\n }\n }\n\n startLoader() {\n return this.setState({\n loading: true })\n }\n\n stopLoader() {\n return this.setState({\n loading: false })\n }\n\n handleUpload() {\n this.startLoader()\n this.props.blockProps.addLock()\n this.updateData()\n return this.uploadFile()\n }\n\n componentDidMount() {\n return this.replaceImg()\n }\n\n aspectRatio() {\n return {\n maxWidth: `${ this.state.aspect_ratio.width }`,\n maxHeight: `${ this.state.aspect_ratio.height }`,\n ratio: `${ this.state.aspect_ratio.height }`\n }\n }\n\n updateDataSelection() {\n const { getEditorState, setEditorState } = this.props.blockProps\n const newselection = getEditorState().getSelection().merge({\n anchorKey: this.props.block.getKey(),\n focusKey: this.props.block.getKey()\n })\n\n return setEditorState(EditorState.forceSelection(getEditorState(), newselection))\n }\n\n handleGrafFigureSelectImg(e) {\n e.preventDefault()\n return this.setState({ selected: true }, this.updateDataSelection)\n }\n\n //main_editor.onChange(main_editor.state.editorState)\n\n coords() {\n return {\n maxWidth: `${ this.state.aspect_ratio.width }px`,\n maxHeight: `${ this.state.aspect_ratio.height }px`\n }\n }\n\n getBase64Image(img) {\n let canvas = document.createElement(\"canvas\")\n canvas.width = img.width\n canvas.height = img.height\n let ctx = canvas.getContext(\"2d\")\n ctx.drawImage(img, 0, 0)\n let dataURL = canvas.toDataURL(\"image/png\")\n\n return dataURL\n }\n\n formatData() {\n let formData = new FormData()\n if (this.file) {\n let formName = this.config.upload_formName || 'file'\n\n formData.append(formName, this.file)\n return formData\n } else {\n formData.append('url', this.props.blockProps.data.get(\"url\"))\n return formData\n }\n }\n\n getUploadUrl() {\n let url = this.config.upload_url\n if (typeof url === \"function\") {\n return url()\n } else {\n return url\n }\n }\n\n getUploadHeaders() {\n return this.config.upload_headers || {}\n }\n\n uploadFile() {\n\n let handleUp\n // custom upload handler\n if (this.config.upload_handler) {\n return this.config.upload_handler(this.formatData().get('file'), this)\n }\n \n if (!this.config.upload_url){\n this.stopLoader()\n return\n }\n \n axios({\n method: 'post',\n url: this.getUploadUrl(),\n headers: this.getUploadHeaders(),\n data: this.formatData(),\n onUploadProgress: e => {\n return this.updateProgressBar(e)\n }\n }).then(result => {\n this.uploadCompleted(result.data.url)\n\n if (this.config.upload_callback) {\n return this.config.upload_callback(result, this)\n }\n }).catch(error => {\n this.uploadFailed()\n\n console.log(`ERROR: got error uploading file ${ error }`)\n if (this.config.upload_error_callback) {\n return this.config.upload_error_callback(error, this)\n }\n })\n\n return handleUp = json_response => {\n return this.uploadCompleted(json_response.url, n)\n }\n }\n\n uploadFailed() {\n this.props.blockProps.removeLock()\n this.stopLoader()\n }\n\n uploadCompleted(url) {\n this.setState({ url }, this.updateData)\n this.props.blockProps.removeLock()\n this.stopLoader()\n this.file = null\n }\n\n updateProgressBar(e) {\n let complete = this.state.loading_progress\n if (e.lengthComputable) {\n complete = e.loaded / e.total * 100\n complete = complete != null ? complete : { complete: 0 }\n this.setState({\n loading_progress: complete })\n return console.log(`complete: ${ complete }`)\n }\n }\n\n placeHolderEnabled() {\n return this.state.enabled || this.props.block.getText()\n }\n\n placeholderText() {\n return this.config.image_caption_placeholder\n }\n\n handleFocus(e) {\n\n }\n\n render() {\n\n return (\n <div ref=\"image_tag2\" suppressContentEditableWarning={true}>\n <div className=\"aspectRatioPlaceholder is-locked\" \n style={this.coords()} \n onClick={this.handleGrafFigureSelectImg}>\n <div style={{ paddingBottom: `${ this.state.aspect_ratio.ratio }%` }} \n className='aspect-ratio-fill' />\n <img src={this.state.url} \n ref=\"image_tag\" \n height={this.state.aspect_ratio.height} \n width={this.state.aspect_ratio.width} \n className='graf-image' />\n <Loader toggle={this.state.loading} \n progress={this.state.loading_progress} />\n </div>\n <figcaption className='imageCaption' onMouseDown={this.handleFocus}>\n { this.props.block.getText().length === 0 ? \n <span className=\"danteDefaultPlaceholder\">\n {this.placeholderText()}\n </span> : undefined}\n <EditorBlock {...Object.assign({}, this.props, { \n \"editable\": true, \"className\": \"imageCaption\" })\n } />\n </figcaption>\n </div>\n )\n }\n}\n\nclass Loader extends React.Component {\n\n render() {\n return (\n <div>\n { this.props.toggle\n ? <div className=\"image-upoader-loader\">\n <p>\n { this.props.progress === 100\n ? \"processing image...\"\n : <span>\n <span>loading</span> { Math.round( this.props.progress ) }\n </span>\n }\n </p>\n </div>\n : undefined\n }\n </div>\n )\n }\n}\n\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/image.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorBlock } from 'draft-js'\n\nexport default class PlaceholderBlock extends React.Component {\n constructor(props) {\n super(props)\n this.placeholderText = this.placeholderText.bind(this)\n this.placeholderFromProps = this.placeholderFromProps.bind(this)\n this.defaultText = this.defaultText.bind(this)\n this.placeholderRender = this.placeholderRender.bind(this)\n this.state = {\n enabled: false,\n data: this.props.blockProps.data.toJS()\n }\n }\n\n placeholderText() {\n //if (this.state.enabled) {\n // return \"\"\n //}\n return this.props.blockProps.data.toJS().placeholder || this.placeholderFromProps() || this.defaultText()\n }\n //if @.props.blockProps.data then @.props.blockProps.data.placeholder else @defaultText()\n\n\n placeholderFromProps() {\n return this.props.block.toJS().placeholder\n }\n\n defaultText() {\n return \"write something \"\n }\n\n placeholderRender(){\n if (this.props.block.text.length === 0 ) {\n return (\n <div className=\"public-DraftEditorPlaceholder-root\">\n <div className=\"public-DraftEditorPlaceholder-inner\">\n {this.placeholderText() }\n </div>\n </div>\n )\n\n }\n }\n\n render() {\n return (\n <span onMouseDown={this.handleFocus}>\n \n {this.placeholderRender()}\n \n <EditorBlock {...Object.assign({}, this.props, {\n \"className\": \"imageCaption\",\n \"placeholder\": \"escrive alalal\"\n })} />\n </span>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/placeholder.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorBlock } from 'draft-js'\n\nimport { updateDataOfBlock } from '../../model/index.js'\n\nimport axios from \"axios\"\n\nexport default class VideoBlock extends React.Component {\n constructor(props) {\n super(props)\n //api_key = \"86c28a410a104c8bb58848733c82f840\"\n\n this.updateData = this.updateData.bind(this)\n this.dataForUpdate = this.dataForUpdate.bind(this)\n this.state = { embed_data: this.defaultData() }\n }\n\n defaultData() {\n let existing_data = this.props.block.getData().toJS()\n return existing_data.embed_data || {}\n }\n\n // will update block state\n updateData() {\n const { block, blockProps } = this.props\n const { getEditorState, setEditorState } = this.props.blockProps\n const data = block.getData()\n const newData = data.merge(this.state)\n return setEditorState(updateDataOfBlock(getEditorState(), block, newData))\n }\n\n dataForUpdate() {\n return this.props.blockProps.data.toJS()\n }\n\n componentDidMount() {\n\n if (!this.props.blockProps.data) {\n return\n }\n // ensure data isnt already loaded\n if (!this.dataForUpdate().endpoint && !this.dataForUpdate().provisory_text) {\n return\n }\n\n return axios({\n method: 'get',\n url: `${ this.dataForUpdate().endpoint }${ this.dataForUpdate().provisory_text }&scheme=https`\n }).then(result => {\n return this.setState({ embed_data: result.data } //JSON.parse(data.responseText)\n , this.updateData)\n }).catch(error => {\n return console.log(\"TODO: error\")\n })\n }\n\n classForImage() {\n if (this.state.embed_data.thumbnail_url) {\n return \"\"\n } else {\n return \"mixtapeImage--empty u-ignoreBlock\"\n }\n }\n\n render() {\n return (\n <figure className='graf--figure graf--iframe graf--first' tabIndex='0'>\n <div className='iframeContainer' \n dangerouslySetInnerHTML={ { __html: this.state.embed_data.html } } />\n <figcaption className='imageCaption'>\n <EditorBlock {...Object.assign({}, this.props, { \"className\": \"imageCaption\" })} />\n </figcaption>\n </figure>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/video.js","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport { Map, fromJS } from 'immutable'\nimport DanteEditor from './editor.js'\nimport DanteImagePopover from '../popovers/image'\nimport DanteAnchorPopover from '../popovers/link'\nimport DanteInlineTooltip from '../popovers/addButton'\nimport DanteTooltip from '../popovers/toolTip'\n\nimport ImageBlock from '../blocks/image'\nimport EmbedBlock from '../blocks/embed'\nimport VideoBlock from '../blocks/video'\nimport PlaceholderBlock from '../blocks/placeholder'\n\nimport { \n resetBlockWithType, \n addNewBlockAt \n} from '../../model/index.js'\n\nclass Dante {\n constructor(options) {\n if (options == null) {\n options = {}\n }\n console.log(\"init editor Dante!\")\n\n // deep merge on config\n let config = Map(fromJS(this.defaultOptions(options)))\n\n this.options = config.mergeDeep(options).toJS()\n console.log(this.options)\n }\n\n defaultOptions(options) {\n // default options\n if (options == null) {\n options = {}\n }\n let defaultOptions = {}\n defaultOptions.el = 'app'\n defaultOptions.content = \"\"\n defaultOptions.read_only = false\n defaultOptions.spellcheck = false\n defaultOptions.title_placeholder = \"Title\"\n defaultOptions.body_placeholder = \"Write your story\"\n\n defaultOptions.widgets = [{\n title: 'add an image',\n icon: 'image',\n type: 'image',\n block: ImageBlock,\n editable: true,\n renderable: true,\n breakOnContinuous: true,\n wrapper_class: \"graf graf--figure\",\n selected_class: \"is-selected is-mediaFocused\",\n selectedFn: block => {\n const { direction } = block.getData().toJS()\n switch (direction) {\n case \"left\":\n return \"graf--layoutOutsetLeft\"\n case \"center\":\n return \"\"\n case \"wide\":\n return \"sectionLayout--fullWidth\"\n case \"fill\":\n return \"graf--layoutFillWidth\"\n }\n },\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n widget_options: {\n displayOnInlineTooltip: true,\n insertion: \"upload\",\n insert_block: \"image\"\n },\n options: {\n upload_url: options.upload_url,\n upload_headers: options.upload_headers,\n upload_formName: options.upload_formName,\n upload_handler: options.image_upload_handler,\n upload_callback: options.image_upload_callback,\n image_delete_callback: options.image_delete_callback,\n image_caption_placeholder: options.image_caption_placeholder || \"Write caption for image (optional)\"\n }\n }, {\n icon: 'embed',\n title: 'insert embed',\n type: 'embed',\n block: EmbedBlock,\n editable: true,\n renderable: true,\n breakOnContinuous: true,\n wrapper_class: \"graf graf--mixtapeEmbed\",\n selected_class: \"is-selected is-mediaFocused\",\n widget_options: {\n displayOnInlineTooltip: true,\n insertion: \"placeholder\",\n insert_block: \"embed\"\n },\n options: {\n endpoint: `//api.embed.ly/1/extract?key=${ options.api_key }&url=`,\n placeholder: 'Paste a link to embed content from another site (e.g. Twitter) and press Enter'\n },\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n }\n }, {\n icon: 'video',\n title: 'insert video',\n editable: true,\n type: 'video',\n block: VideoBlock,\n renderable: true,\n breakOnContinuous: true,\n wrapper_class: \"graf--figure graf--iframe\",\n selected_class: \" is-selected is-mediaFocused\",\n widget_options: {\n displayOnInlineTooltip: true,\n insertion: \"placeholder\",\n insert_block: \"video\"\n },\n options: {\n endpoint: `//api.embed.ly/1/oembed?key=${ options.api_key }&url=`,\n placeholder: 'Paste a YouTube, Vine, Vimeo, or other video link, and press Enter',\n caption: 'Type caption for embed (optional)'\n },\n\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n }\n }, {\n renderable: true,\n editable: true,\n block: PlaceholderBlock,\n type: 'placeholder',\n wrapper_class: \"is-embedable\",\n selected_class: \" is-selected is-mediaFocused\",\n widget_options: {\n displayOnInlineTooltip: false\n },\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n const data = {\n provisory_text: block.getText(),\n endpoint: block.getData().get('endpoint'),\n type: block.getData().get('type')\n }\n if(block.getText().length > 0){\n return ctx.onChange(resetBlockWithType(editorState, data.type, data))\n }else{\n return ctx.onChange(resetBlockWithType(editorState, \"unstyled\", {}))\n }\n },\n\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(resetBlockWithType(editorState, data.type, data))\n\n //return ctx.onChange(resetBlockWithType(editorState, \"unstyled\", {}))\n //return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n\n }]\n\n defaultOptions.tooltips = [{\n ref: 'insert_tooltip',\n component: DanteTooltip,\n displayOnSelection: true,\n selectionElements: [\"unstyled\", \n \"blockquote\", \n \"ordered-list\", \n \"unordered-list\", \n \"unordered-list-item\", \n \"ordered-list-item\", \n \"code-block\", \n 'header-one', \n 'header-two', \n 'header-three', \n 'header-four'],\n widget_options: {\n placeholder: \"Paste or type a link\",\n block_types: [\n // {label: 'p', style: 'unstyled'},\n { label: 'h2', style: 'header-one', type: \"block\" }, \n { label: 'h3', style: 'header-two', type: \"block\" }, \n { label: 'h4', style: 'header-three', type: \"block\" }, \n { label: 'blockquote', style: 'blockquote', type: \"block\" },\n { label: 'insertunorderedlist', style: 'unordered-list-item', type: \"block\" }, \n { label: 'insertorderedlist', style: 'ordered-list-item', type: \"block\" }, \n { label: 'code', style: 'code-block', type: \"block\" }, \n { label: 'bold', style: 'BOLD', type: \"inline\" }, \n { label: 'italic', style: 'ITALIC', type: \"inline\" }\n ]\n }\n }, {\n ref: 'add_tooltip',\n component: DanteInlineTooltip\n }, {\n ref: 'anchor_popover',\n component: DanteAnchorPopover\n }, {\n ref: 'image_popover',\n component: DanteImagePopover\n }]\n\n defaultOptions.xhr = {\n before_handler: null,\n success_handler: null,\n error_handler: null\n }\n\n defaultOptions.data_storage = {\n url: null,\n method: \"POST\",\n success_handler: null,\n failure_handler: null,\n interval: 1500,\n withCredentials: false,\n crossDomain: false,\n headers: {},\n }\n\n defaultOptions.default_wrappers = [\n { className: 'graf--p', block: 'unstyled' }, \n { className: 'graf--h2', block: 'header-one' },\n { className: 'graf--h3', block: 'header-two' }, \n { className: 'graf--h4', block: 'header-three' }, \n { className: 'graf--blockquote', block: 'blockquote' }, \n { className: 'graf--insertunorderedlist', block: 'unordered-list-item' }, \n { className: 'graf--insertorderedlist', block: 'ordered-list-item' }, \n { className: 'graf--code', block: 'code-block' }, \n { className: 'graf--bold', block: 'BOLD' }, \n { className: 'graf--italic', block: 'ITALIC' }]\n\n defaultOptions.continuousBlocks = [\n \"unstyled\", \n \"blockquote\", \n \"ordered-list\", \n \"unordered-list\", \n \"unordered-list-item\", \n \"ordered-list-item\", \n \"code-block\"\n ]\n\n defaultOptions.key_commands = {\n \"alt-shift\": [{ key: 65, cmd: 'add-new-block' }],\n \"alt-cmd\": [{ key: 49, cmd: 'toggle_block:header-one' }, \n { key: 50, cmd: 'toggle_block:header-two' }, \n { key: 53, cmd: 'toggle_block:blockquote' }],\n \"cmd\": [{ key: 66, cmd: 'toggle_inline:BOLD' }, \n { key: 73, cmd: 'toggle_inline:ITALIC' }, \n { key: 75, cmd: 'insert:link' }]\n }\n\n defaultOptions.character_convert_mapping = {\n '> ': \"blockquote\",\n '*.': \"unordered-list-item\",\n '* ': \"unordered-list-item\",\n '- ': \"unordered-list-item\",\n '1.': \"ordered-list-item\",\n '# ': 'header-one',\n '##': 'header-two',\n '==': \"unstyled\",\n '` ': \"code-block\"\n }\n\n return defaultOptions\n }\n\n getContent() {\n return this.options.content\n }\n\n render() {\n return this.editor = ReactDOM.render(\n <DanteEditor content={this.getContent()} config={this.options} />,\n document.getElementById(this.options.el)\n )\n }\n}\n\nexport default Dante\n\n\n// WEBPACK FOOTER //\n// src/components/core/dante.js","import React from 'react'\n\nclass Debug extends React.Component {\n\n constructor() {\n super()\n\n this.handleToggleReadOnly = this.handleToggleReadOnly.bind(this)\n this.handleTestEmitAndDecode = this.handleTestEmitAndDecode.bind(this)\n this.handleTestEmitTEXT = this.handleTestEmitTEXT.bind(this)\n this.testEmitAndDecode = this.testEmitAndDecode.bind(this)\n this.testEmitTEXT = this.testEmitTEXT.bind(this)\n this.logState = this.logState.bind(this)\n this.toggleDisplay = this.toggleDisplay.bind(this)\n this.open = this.open.bind(this)\n this.render = this.render.bind(this)\n this.state = {\n output: \"\",\n display: \"none\"\n }\n }\n\n handleToggleReadOnly(e) {\n e.preventDefault()\n this.props.editor.toggleEditable()\n return false\n }\n\n handleTestEmitAndDecode(e) {\n e.preventDefault()\n return this.testEmitAndDecode()\n }\n\n handleTestEmitTEXT(e) {\n e.preventDefault()\n return this.testEmitTEXT()\n }\n\n testEmitAndDecode(e) {\n const raw_as_json = this.props.editor.emitSerializedOutput()\n this.props.editor.setState({ \n editorState: this.props.editor.decodeEditorContent(raw_as_json) }, \n this.logState(JSON.stringify(raw_as_json)))\n return false\n }\n\n testEmitTEXT() {\n const text = this.props.editor.getTextFromEditor()\n return this.logState(text)\n }\n\n logState(raw) {\n return this.setState({ output: raw }, this.open)\n }\n\n toggleDisplay(e) {\n e.preventDefault()\n const d = this.state.display === \"block\" ? \"none\" : this.state.display\n return this.setState({\n display: d })\n }\n\n open() {\n return this.setState({\n display: \"block\" })\n }\n\n render() {\n return (\n <div>\n <div className=\"debugControls\">\n <ul>\n <li> LOCKS: { this.props.editor.state.locks } </li>\n <li>\n <a href=\"#\" onClick={ this.handleToggleReadOnly }>\n EDITABLE: { this.props.editor.state.read_only ? 'NO' : 'YES' }\n </a>\n </li>\n <li>\n <a href=\"#\" onClick={ this.handleTestEmitTEXT }>EDITOR TEXT</a>\n </li>\n <li>\n <a href=\"#\" onClick={ this.handleTestEmitAndDecode }>EDITOR STATE</a>\n </li>\n </ul>\n </div>\n <div className=\"debugZone\" style={ { display: this.state.display } }>\n <a href=\"#\" className=\"dante-debug-close close\" onClick={ this.toggleDisplay } />\n <div className=\"debugOutput\">\n <h2>EDITOR OUTPUT</h2>\n {\n this.state.output.length > 0\n ? <pre>{ this.state.output }</pre>\n : undefined\n }\n </div>\n </div>\n </div>\n )\n }\n}\n\nexport default Debug\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/core/debug.js","import React from 'react'\nimport { Entity } from 'draft-js'\n\nexport default class Link extends React.Component {\n\n constructor(props) {\n super(props)\n this._validateLink = this._validateLink.bind(this)\n this._checkProtocol = this._checkProtocol.bind(this)\n this._showPopLinkOver = this._showPopLinkOver.bind(this)\n this._hidePopLinkOver = this._hidePopLinkOver.bind(this)\n this.isHover = false\n }\n\n _validateLink() {\n const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol\n '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name\n '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address\n '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path\n '(\\?[&a-z\\d%_.~+=-]*)?' + // query string\n '(\\#[-a-z\\d_]*)?$', 'i') // fragment locater\n if (!pattern.test(str)) {\n alert(\"Please enter a valid URL.\")\n return false\n } else {\n return true\n }\n }\n\n _checkProtocol() {\n return console.log(\"xcvd\")\n }\n\n _showPopLinkOver(e) {\n if (!this.data.showPopLinkOver) {\n return\n }\n return this.data.showPopLinkOver(this.refs.link)\n }\n\n _hidePopLinkOver(e) {\n if (!this.data.hidePopLinkOver) {\n return\n }\n return this.data.hidePopLinkOver()\n }\n\n render() {\n this.data = this.props.contentState.getEntity(this.props.entityKey).getData()\n //Entity.get(this.props.entityKey).getData()\n\n return (\n <a\n ref=\"link\"\n href={ this.data.url }\n className=\"markup--anchor\"\n onMouseOver={ this._showPopLinkOver }\n onMouseOut={ this._hidePopLinkOver }\n >\n { this.props.children }\n </a>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/decorators/link.js","\nimport Dante from './core/dante'\nimport DanteEditor from './core/editor'\n\nexport {\n Dante, \n DanteEditor\n}\n\n\n// WEBPACK FOOTER //\n// src/components/init.js","import React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { \n Entity, \n RichUtils, \n AtomicBlockUtils, \n EditorState \n } from 'draft-js'\n\nimport { \n addNewBlock, \n resetBlockWithType, \n updateDataOfBlock, \n getCurrentBlock, \n getNode } from '../../model/index.js'\n\nimport { getSelectionRect, getSelection } from \"../../utils/selection.js\"\n\nclass DanteInlineTooltip extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this._toggleScaled = this._toggleScaled.bind(this)\n this.scale = this.scale.bind(this)\n this.collapse = this.collapse.bind(this)\n this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this)\n this.clickOnFileUpload = this.clickOnFileUpload.bind(this)\n this.handlePlaceholder = this.handlePlaceholder.bind(this)\n this.insertImage = this.insertImage.bind(this)\n this.handleFileInput = this.handleFileInput.bind(this)\n this.widgets = this.widgets.bind(this)\n this.clickHandler = this.clickHandler.bind(this)\n this.relocate = this.relocate.bind(this)\n this.state = {\n position: { top: 0, left: 0 },\n show: false,\n scaled: false\n }\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n show: false })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n _toggleScaled(ev) {\n if (this.state.scaled) {\n return this.collapse()\n } else {\n return this.scale()\n }\n }\n\n scale() {\n return this.setState({\n scaled: true })\n }\n\n collapse() {\n return this.setState({\n scaled: false })\n }\n\n componentWillReceiveProps(newProps) {\n return this.collapse()\n }\n\n activeClass() {\n //if @props.show then \"is-active\" else \"\"\n if (this.isActive()) {\n return \"is-active\"\n } else {\n return \"\"\n }\n }\n\n isActive() {\n return this.state.show\n }\n\n scaledClass() {\n if (this.state.scaled) {\n return \"is-scaled\"\n } else {\n return \"\"\n }\n }\n\n scaledWidth() {\n if (this.state.scaled) {\n return \"124\"\n } else {\n return \"0\"\n }\n }\n\n clickOnFileUpload() {\n this.refs.fileInput.click()\n this.collapse()\n return this.hide()\n }\n\n handlePlaceholder(input) {\n let opts = {\n type: input.widget_options.insert_block,\n placeholder: input.options.placeholder,\n endpoint: input.options.endpoint\n }\n\n return this.props.onChange(resetBlockWithType(this.props.editorState, 'placeholder', opts))\n }\n\n insertImage(file) {\n let opts = {\n url: URL.createObjectURL(file),\n file\n }\n\n return this.props.onChange(addNewBlock(this.props.editorState, 'image', opts))\n }\n\n handleFileInput(e) {\n let fileList = e.target.files\n // TODO: support multiple file uploads\n /*\n Object.keys(fileList).forEach (o)=>\n @.insertImage(fileList[0])\n */\n return this.insertImage(fileList[0])\n }\n\n handleInsertion(e){\n this.hide()\n return this.props.onChange(addNewBlock(this.props.editorState, e.type, {}))\n }\n\n widgets() {\n return this.props.editor.widgets\n }\n\n clickHandler(e, type) {\n let request_block = this.widgets().find(o => o.icon === type)\n\n switch (request_block.widget_options.insertion) {\n case \"upload\":\n return this.clickOnFileUpload(e, request_block)\n case \"placeholder\":\n return this.handlePlaceholder(request_block)\n case \"insertion\":\n return this.handleInsertion(request_block)\n default:\n return console.log(`WRONG TYPE FOR ${ request_block.widget_options.insertion }`)\n }\n }\n\n getItems() {\n return this.widgets().filter(o => {\n return o.widget_options.displayOnInlineTooltip\n })\n }\n\n isDescendant(parent, child) {\n let node = child.parentNode\n while (node !== null) {\n if (node === parent) {\n return true\n }\n node = node.parentNode\n }\n return false\n }\n\n relocate() {\n let { editorState } = this.props\n\n if (editorState.getSelection().isCollapsed()) {\n\n let currentBlock = getCurrentBlock(editorState)\n let blockType = currentBlock.getType()\n\n let contentState = editorState.getCurrentContent()\n let selectionState = editorState.getSelection()\n\n let block = contentState.getBlockForKey(selectionState.anchorKey)\n\n let nativeSelection = getSelection(window)\n if (!nativeSelection.rangeCount) {\n return\n }\n\n let node = getNode()\n\n let selectionBoundary = getSelectionRect(nativeSelection)\n let coords = selectionBoundary //utils.getSelectionDimensions(node)\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n // hide if selected node is not in editor\n // debugger\n //console.log @isDescendant(parent, nativeSelection.anchorNode)\n\n if (!this.isDescendant(parent, nativeSelection.anchorNode)) {\n this.hide()\n return\n }\n\n if (!coords)\n return \n\n // checkeamos si esta vacio\n this.display(block.getText().length === 0 && blockType === \"unstyled\")\n return this.setPosition({\n top: coords.top + window.pageYOffset,\n left: coords.left + window.pageXOffset - 60\n })\n\n /*\n @refs.image_popover.display(blockType is \"image\")\n if blockType is \"image\"\n selectionBoundary = node.anchorNode.parentNode.parentNode.parentNode.getBoundingClientRect()\n *el = document.querySelector(\"#dante_image_popover\")\n el = @refs.image_popover.refs.image_popover\n padd = el.offsetWidth / 2\n @refs.image_popover.setPosition\n top: selectionBoundary.top - parentBoundary.top + 60\n left: selectionBoundary.left + (selectionBoundary.width / 2) - padd\n\n *@setState\n * image_popover_position:\n * top: selectionBoundary.top - parentBoundary.top + 60\n * left: selectionBoundary.left + (selectionBoundary.width / 2) - padd\n *\n */\n } else {\n return this.hide()\n }\n }\n\n render() {\n return (\n <div\n className={ `inlineTooltip ${ this.activeClass() } ${ this.scaledClass() }` }\n style={ this.state.position }\n >\n <button\n className=\"inlineTooltip-button control\"\n title=\"Close Menu\"\n data-action=\"inline-menu\"\n onClick={ this._toggleScaled }\n >\n <span className=\"tooltip-icon dante-icon-plus\" />\n </button>\n <div\n className=\"inlineTooltip-menu\"\n style={ { width: `${ this.scaledWidth() }px` } }\n >\n { this.getItems().map( (item, i) => {\n return <InlineTooltipItem\n item={ item }\n key={ i }\n clickHandler={ this.clickHandler }\n />\n })\n }\n <input\n type=\"file\"\n style={ { display: 'none' } }\n ref=\"fileInput\"\n multiple=\"multiple\"\n onChange={ this.handleFileInput }\n />\n </div>\n </div>\n )\n }\n}\n\nclass InlineTooltipItem extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.clickHandler = this.clickHandler.bind(this)\n }\n\n clickHandler(e) {\n e.preventDefault()\n return this.props.clickHandler(e, this.props.item.icon)\n }\n\n render() {\n return (\n <button\n className=\"inlineTooltip-button scale\"\n title={ this.props.title }\n onMouseDown={ this.clickHandler }\n >\n <span className={ `tooltip-icon dante-icon-${ this.props.item.icon }` } />\n </button>\n )\n }\n}\n\nexport default DanteInlineTooltip\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/addButton.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorState } from 'draft-js'\n\nimport { getSelectionRect, getSelection } from \"../../utils/selection.js\"\n\nimport { getCurrentBlock, getNode } from '../../model/index.js'\n\nclass DanteImagePopover extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this._toggleScaled = this._toggleScaled.bind(this)\n this.scale = this.scale.bind(this)\n this.collapse = this.collapse.bind(this)\n this.relocate = this.relocate.bind(this)\n this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this)\n this.handleClick = this.handleClick.bind(this)\n this.state = {\n position: {\n top: 0,\n left: 0\n },\n show: false,\n scaled: false,\n buttons: [{ type: \"left\" }, \n { type: \"center\"}, \n { type: \"fill\" }, \n { type: \"wide\" }]\n }\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n show: false })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n _toggleScaled(ev) {\n if (this.state.scaled) {\n return this.collapse()\n } else {\n return this.scale()\n }\n }\n\n scale() {\n return this.setState({\n scaled: true })\n }\n\n collapse() {\n return this.setState({\n scaled: false })\n }\n\n relocate() {\n let { editorState } = this.props\n\n if (editorState.getSelection().isCollapsed()) {\n\n let currentBlock = getCurrentBlock(editorState)\n let blockType = currentBlock.getType()\n\n let contentState = editorState.getCurrentContent()\n let selectionState = editorState.getSelection()\n\n let block = contentState.getBlockForKey(selectionState.anchorKey)\n\n let nativeSelection = getSelection(window)\n if (!nativeSelection.rangeCount) {\n return\n }\n\n let node = getNode()\n\n let selectionBoundary = getSelectionRect(nativeSelection)\n let coords = selectionBoundary\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n this.display(blockType === \"image\")\n\n if (blockType === \"image\") {\n selectionBoundary = node.anchorNode.parentNode.parentNode\n .parentNode.getBoundingClientRect()\n let el = this.refs.image_popover\n let padd = el.offsetWidth / 2\n return this.setPosition({\n top: selectionBoundary.top - parentBoundary.top + 60,\n left: selectionBoundary.left + selectionBoundary.width / 2 - padd\n })\n }\n } else {\n return this.hide()\n }\n }\n\n componentWillReceiveProps(newProps) {\n return this.collapse()\n }\n\n getStyle() {\n if (!this.state.position) {\n return {}\n }\n }\n\n handleClick(item) {\n return this.props.editor.setDirection(item.type)\n }\n\n render() {\n return (\n <div\n ref=\"image_popover\"\n className={ `dante-popover popover--Aligntooltip popover--top popover--animated ${ this.state.show ? 'is-active' : undefined }` }\n style={ \n { top: this.state.position.top,\n left: this.state.position.left }\n }\n >\n <div className='popover-inner'>\n <ul className='dante-menu-buttons'>\n { this.state.buttons.map( (item, i) => {\n return <DanteImagePopoverItem\n item={ item }\n handleClick={ this.handleClick }\n key={ i }\n />\n })\n }\n </ul>\n </div>\n <div className='popover-arrow' />\n </div>\n )\n }\n}\n\nclass DanteImagePopoverItem extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.handleClick = this.handleClick.bind(this)\n this.render = this.render.bind(this)\n }\n\n handleClick(e) {\n e.preventDefault()\n return this.props.handleClick(this.props.item)\n }\n\n render() {\n return <li \n className={`dante-menu-button align-${ this.props.item.type }`} \n onMouseDown={this.handleClick}>\n <span className={`tooltip-icon dante-icon-image-${ this.props.item.type }`} />\n </li>\n }\n}\n\nexport default DanteImagePopover\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/image.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { getCurrentBlock } from '../../model/index.js'\n\nclass DanteAnchorPopover extends React.Component {\n\n constructor(props) {\n\n super(props)\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this.relocate = this.relocate.bind(this)\n this.render = this.render.bind(this)\n this.state = {\n position: {\n top: 0,\n left: 0\n },\n show: false,\n url: \"\"\n }\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n show: false })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n relocate(node) {\n if (node == null) {\n node = null\n }\n if (!node) {\n return\n }\n\n let { editorState } = this.props\n let currentBlock = getCurrentBlock(editorState)\n let blockType = currentBlock.getType()\n\n let contentState = editorState.getCurrentContent()\n let selectionState = editorState.getSelection()\n\n let selectionBoundary = node.getBoundingClientRect()\n let coords = selectionBoundary\n\n let el = this.refs.dante_popover\n let padd = el.offsetWidth / 2\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n return {\n top: selectionBoundary.top - parentBoundary.top + 160,\n left: selectionBoundary.left + selectionBoundary.width / 2 - padd\n }\n }\n\n render() {\n let { position } = this.state\n let style = {\n left: position.left,\n top: position.top,\n visibility: `${ this.state.show ? 'visible' : 'hidden' }`\n }\n return (\n <div\n ref=\"dante_popover\"\n className='dante-popover popover--tooltip popover--Linktooltip popover--bottom is-active'\n style={ style }\n onMouseOver={ this.props.handleOnMouseOver }\n onMouseOut={ this.props.handleOnMouseOut }\n >\n <div className='popover-inner'>\n <a href={ this.props.url } target='_blank'>\n { this.state.url }\n </a>\n </div>\n <div className='popover-arrow' />\n </div>\n )\n }\n}\n\nexport default DanteAnchorPopover\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/link.js","import React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { \n convertToRaw, \n CompositeDecorator, \n getVisibleSelectionRect, \n getDefaultKeyBinding, \n getSelectionOffsetKeyForNode, \n KeyBindingUtil, \n ContentState, \n Editor, \n EditorState, \n Entity, \n RichUtils } from 'draft-js'\n\nimport { getSelectionRect, getSelection } from \"../../utils/selection.js\"\n\nimport { getCurrentBlock } from '../../model/index.js'\n\nclass DanteTooltip extends React.Component {\n\n constructor(props) {\n super(props)\n this._clickInlineHandler = this._clickInlineHandler.bind(this)\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this.relocate = this.relocate.bind(this)\n this._clickBlockHandler = this._clickBlockHandler.bind(this)\n this.displayLinkMode = this.displayLinkMode.bind(this)\n this.displayActiveMenu = this.displayActiveMenu.bind(this)\n this._enableLinkMode = this._enableLinkMode.bind(this)\n this._disableLinkMode = this._disableLinkMode.bind(this)\n this.handleInputEnter = this.handleInputEnter.bind(this)\n this.confirmLink = this.confirmLink.bind(this)\n this.inlineItems = this.inlineItems.bind(this)\n this.blockItems = this.blockItems.bind(this)\n this.getDefaultValue = this.getDefaultValue.bind(this)\n this.getVisibleSelectionRect = getVisibleSelectionRect\n this.state = {\n link_mode: false,\n show: false,\n position: {}\n }\n }\n\n _clickInlineHandler(ev, style) {\n ev.preventDefault()\n\n this.props.onChange(RichUtils.toggleInlineStyle(this.props.editorState, style))\n\n return setTimeout(() => {\n return this.relocate()\n }, 0)\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n link_mode: false,\n show: false\n })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n isDescendant(parent, child) {\n let node = child.parentNode\n while (node !== null) {\n if (node === parent) {\n return true\n }\n node = node.parentNode\n }\n return false\n }\n\n relocate() {\n\n let currentBlock = getCurrentBlock(this.props.editorState)\n let blockType = currentBlock.getType()\n // display tooltip only for unstyled\n\n if (this.props.configTooltip.selectionElements.indexOf(blockType) < 0) {\n this.hide()\n return\n }\n\n if (this.state.link_mode) {\n return\n }\n if (!this.state.show) {\n return\n }\n\n let el = this.refs.dante_menu\n let padd = el.offsetWidth / 2\n\n let nativeSelection = getSelection(window)\n if (!nativeSelection.rangeCount) {\n return\n }\n\n let selectionBoundary = getSelectionRect(nativeSelection)\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n // hide if selected node is not in editor\n if (!this.isDescendant(parent, nativeSelection.anchorNode)) {\n this.hide()\n return\n }\n\n let top = selectionBoundary.top - parentBoundary.top - -90 - 5\n let left = selectionBoundary.left + selectionBoundary.width / 2 - padd\n\n if (!top || !left) {\n return\n }\n\n // console.log \"SET SHOW FOR TOOLTIP INSERT MENU\"\n return this.setState({\n show: true,\n position: {\n left,\n top\n }\n })\n }\n\n _clickBlockHandler(ev, style) {\n ev.preventDefault()\n\n this.props.onChange(RichUtils.toggleBlockType(this.props.editorState, style))\n\n return setTimeout(() => {\n return this.relocate()\n }, 0)\n }\n\n displayLinkMode() {\n if (this.state.link_mode) {\n return \"dante-menu--linkmode\"\n } else {\n return \"\"\n }\n }\n\n displayActiveMenu() {\n if (this.state.show) {\n return \"dante-menu--active\"\n } else {\n return \"\"\n }\n }\n\n _enableLinkMode(ev) {\n ev.preventDefault()\n return this.setState({\n link_mode: true })\n }\n\n _disableLinkMode(ev) {\n ev.preventDefault()\n return this.setState({\n link_mode: false,\n url: \"\"\n })\n }\n\n hideMenu() {\n return this.hide()\n }\n\n handleInputEnter(e) {\n if (e.which === 13) {\n return this.confirmLink(e)\n }\n }\n\n confirmLink(e) {\n e.preventDefault()\n let { editorState } = this.props\n let urlValue = e.currentTarget.value\n let contentState = editorState.getCurrentContent()\n let selection = editorState.getSelection()\n\n let opts = {\n url: urlValue,\n showPopLinkOver: this.props.showPopLinkOver,\n hidePopLinkOver: this.props.hidePopLinkOver\n }\n \n let entityKey = Entity.create('LINK', 'MUTABLE', opts)\n //contentState.createEntity('LINK', 'MUTABLE', opts)\n\n if (selection.isCollapsed()) {\n console.log(\"COLLAPSED SKIPPING LINK\")\n return\n }\n\n this.props.onChange(RichUtils.toggleLink(editorState, selection, entityKey))\n\n return this._disableLinkMode(e)\n }\n\n getPosition() {\n let pos = this.state.position\n return pos\n }\n\n inlineItems() {\n return this.props.widget_options.block_types.filter(o => {\n return o.type === \"inline\"\n })\n }\n\n blockItems() {\n return this.props.widget_options.block_types.filter(o => {\n return o.type === \"block\"\n })\n }\n\n getDefaultValue() {\n if (this.refs.dante_menu_input) {\n this.refs.dante_menu_input.value = \"\"\n }\n \n let currentBlock = getCurrentBlock(this.props.editorState)\n let blockType = currentBlock.getType()\n let selection = this.props.editor.state.editorState.getSelection()\n let contentState = this.props.editorState.getCurrentContent()\n let selectedEntity = null\n let defaultUrl = null\n return currentBlock.findEntityRanges(character => {\n let entityKey = character.getEntity()\n selectedEntity = entityKey\n return entityKey !== null && contentState.getEntity(entityKey).getType() === 'LINK'\n }, (start, end) => {\n let selStart = selection.getAnchorOffset()\n let selEnd = selection.getFocusOffset()\n if (selection.getIsBackward()) {\n selStart = selection.getFocusOffset()\n selEnd = selection.getAnchorOffset()\n }\n\n if (start === selStart && end === selEnd) {\n defaultUrl = contentState.getEntity(selectedEntity).getData().url\n return this.refs.dante_menu_input.value = defaultUrl\n }\n })\n }\n\n render() {\n return (\n <div\n id=\"dante-menu\"\n ref=\"dante_menu\"\n className={ `dante-menu ${ this.displayActiveMenu() } ${ this.displayLinkMode() }` }\n style={ this.getPosition() }\n >\n <div className=\"dante-menu-linkinput\">\n <input\n className=\"dante-menu-input\"\n ref=\"dante_menu_input\"\n placeholder={this.props.widget_options.placeholder}\n onKeyPress={ this.handleInputEnter }\n defaultValue={ this.getDefaultValue() }\n />\n <div className=\"dante-menu-button\" onMouseDown={ this._disableLinkMode } />\n </div>\n <ul className=\"dante-menu-buttons\">\n { this.blockItems().map( (item, i) => {\n return <DanteTooltipItem\n key={ i }\n item={ item }\n handleClick={ this._clickBlockHandler }\n editorState={ this.props.editorState }\n type=\"block\"\n currentStyle={ this.props.editorState.getCurrentInlineStyle }\n />\n })\n }\n\n <DanteTooltipLink\n editorState={ this.props.editorState }\n enableLinkMode={ this._enableLinkMode }\n />\n\n\n { this.inlineItems().map( (item, i) => {\n return <DanteTooltipItem\n key={ i }\n item={ item }\n type=\"inline\"\n editorState={ this.props.editorState }\n handleClick={ this._clickInlineHandler }\n />\n })\n }\n </ul>\n </div>\n )\n }\n}\n\nclass DanteTooltipItem extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.handleClick = this.handleClick.bind(this)\n this.activeClass = this.activeClass.bind(this)\n this.isActive = this.isActive.bind(this)\n this.activeClassInline = this.activeClassInline.bind(this)\n this.activeClassBlock = this.activeClassBlock.bind(this)\n this.render = this.render.bind(this)\n }\n\n handleClick(ev) {\n return this.props.handleClick(ev, this.props.item.style)\n }\n\n activeClass() {\n if (this.isActive()) {\n return \"active\"\n } else {\n return \"\"\n }\n }\n\n isActive() {\n if (this.props.type === \"block\") {\n return this.activeClassBlock()\n } else {\n return this.activeClassInline()\n }\n }\n\n activeClassInline() {\n if (!this.props.editorState) {\n return\n }\n //console.log @props.item\n return this.props.editorState.getCurrentInlineStyle().has(this.props.item.style)\n }\n\n activeClassBlock() {\n //console.log \"EDITOR STATE\", @props.editorState\n if (!this.props.editorState) {\n return\n }\n let selection = this.props.editorState.getSelection()\n let blockType = this.props.editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType()\n return this.props.item.style === blockType\n }\n\n render() {\n return (\n <li className={ `dante-menu-button ${ this.activeClass() }` } onMouseDown={ this.handleClick }>\n <i className={ `dante-icon dante-icon-${ this.props.item.label }` } data-action=\"bold\" />\n </li>\n )\n }\n}\n\nclass DanteTooltipLink extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.promptForLink = this.promptForLink.bind(this)\n }\n\n promptForLink(ev) {\n let selection = this.props.editorState.getSelection()\n if (!selection.isCollapsed()) {\n return this.props.enableLinkMode(ev)\n }\n }\n\n render() {\n return (\n <li className=\"dante-menu-button\" onMouseDown={ this.promptForLink }>\n <i className=\"dante-icon icon-createlink\" data-action=\"createlink\">link</i>\n </li>\n )\n }\n}\n\n\n\n\n\n\nexport default DanteTooltip\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/toolTip.js","import { Entity } from 'draft-js'\n\n//TODO: what the f*ck is happening here? ;-;\nconst findEntities = (entityType, instance, contentBlock, callback) => {\n return contentBlock.findEntityRanges((function(_this) {\n return function(character) {\n var entityKey, opts, res\n let contentState = instance.state.editorState.getCurrentContent()\n entityKey = character.getEntity()\n return (res = entityKey !== null && contentState.getEntity(entityKey).getType() === entityType, res ? (opts = {\n showPopLinkOver: instance.showPopLinkOver,\n hidePopLinkOver: instance.hidePopLinkOver\n }, contentState.mergeEntityData(entityKey, opts)) : void 0, res)\n }\n })(this), callback)\n}\n\nexport default findEntities\n\n\n// WEBPACK FOOTER //\n// src/utils/find_entities.js","import { ContentState, genKey, Entity, CharacterMetadata, ContentBlock, convertFromHTML, getSafeBodyFromHTML } from 'draft-js'\n\nimport { List, OrderedSet, Repeat, fromJS } from 'immutable'\n\n\n// { compose\n// } = require('underscore')\n\n// underscore compose function\nlet compose = function() {\n let args = arguments\n let start = args.length - 1\n return function() {\n let i = start\n let result = args[start].apply(this, arguments)\n while (i--) {\n result = args[i].call(this, result)\n }\n return result\n }\n}\n\n// from https://gist.github.com/N1kto/6702e1c2d89a33a15a032c234fc4c34e\n\n/*\n * Helpers\n */\n\n// Prepares img meta data object based on img attributes\nlet getBlockSpecForElement = imgElement=> {\n return {\n contentType: 'image',\n imgSrc: imgElement.getAttribute('src')\n }\n}\n\n// Wraps meta data in HTML element which is 'understandable' by Draft, I used <blockquote />.\nlet wrapBlockSpec = blockSpec=> {\n if (blockSpec === null) {\n return null\n }\n\n let tempEl = document.createElement('blockquote')\n // stringify meta data and insert it as text content of temp HTML element. We will later extract\n // and parse it.\n tempEl.innerText = JSON.stringify(blockSpec)\n return tempEl\n}\n\n// Replaces <img> element with our temp element\nlet replaceElement = (oldEl, newEl)=> {\n if (!(newEl instanceof HTMLElement)) {\n return\n }\n\n let upEl = getUpEl(oldEl)\n //parentNode = oldEl.parentNode\n //return parentNode.replaceChild(newEl, oldEl)\n return upEl.parentNode.insertBefore(newEl, upEl)\n}\n\nvar getUpEl = el=> {\n let original_el = el\n while (el.parentNode) {\n if (el.parentNode.tagName !== 'BODY') {\n el = el.parentNode\n }\n if (el.parentNode.tagName === 'BODY') { return el }\n }\n}\n\nlet elementToBlockSpecElement = compose(wrapBlockSpec, getBlockSpecForElement)\n\nlet imgReplacer = imgElement=> {\n return replaceElement(imgElement, elementToBlockSpecElement(imgElement))\n}\n\n/*\n * Main function\n */\n\n// takes HTML string and returns DraftJS ContentState\nlet customHTML2Content = function(HTML, blockRn){\n let tempDoc = new DOMParser().parseFromString(HTML, 'text/html')\n // replace all <img /> with <blockquote /> elements\n\n let a = tempDoc.querySelectorAll('img').forEach( item=> imgReplacer(item))\n\n // use DraftJS converter to do initial conversion. I don't provide DOMBuilder and\n // blockRenderMap arguments here since it should fall back to its default ones, which are fine\n console.log(tempDoc.body.innerHTML)\n let content = convertFromHTML(tempDoc.body.innerHTML,\n getSafeBodyFromHTML,\n blockRn\n )\n\n let contentBlocks = content.contentBlocks\n\n // now replace <blockquote /> ContentBlocks with 'atomic' ones\n contentBlocks = contentBlocks.map(function(block){\n let newBlock\n console.log(\"CHECK BLOCK\", block.getType())\n if (block.getType() !== 'blockquote') {\n return block\n }\n\n let json = \"\"\n try {\n json = JSON.parse(block.getText())\n } catch (error) {\n return block\n }\n\n return newBlock = block.merge({\n type: \"image\",\n text: \"\",\n data: {\n url: json.imgSrc,\n forceUpload: true\n }\n })\n })\n\n tempDoc = null\n return ContentState.createFromBlockArray(contentBlocks)\n}\n\n\nexport default customHTML2Content\n\n\n// WEBPACK FOOTER //\n// src/utils/html2content.js","import axios from \"axios\"\nimport Immutable from 'immutable'\n\nclass SaveBehavior {\n constructor(options) {\n this.getLocks = options.getLocks\n this.config = options.config\n this.editorContent = options.editorContent\n this.editorState = options.editorState\n }\n\n handleStore(ev){\n return this.store()\n }\n\n store(content){\n if (!this.config.data_storage.url) { return }\n if (this.getLocks() > 0) { return }\n\n clearTimeout(this.timeout)\n\n return this.timeout = setTimeout(() => {\n return this.checkforStore(content)\n }\n , this.config.data_storage.interval)\n }\n\n getTextFromEditor(content){\n return content.blocks.map(o=> {\n return o.text\n }\n )\n .join(\"\\n\")\n }\n\n getUrl() {\n let { url } = this.config.data_storage\n if (typeof(url) === \"function\") { \n return url() \n } else { \n return url \n }\n }\n\n getMethod() {\n let { method } = this.config.data_storage\n if (typeof(method) === \"function\") { \n return method() \n } else { \n return method \n }\n }\n\n getWithCredentials(){\n let { withCredentials } = this.config.data_storage\n if (typeof(withCredentials) === \"function\") { \n return withCredentials() \n } else { \n return withCredentials \n }\n }\n\n getCrossDomain(){\n let { crossDomain } = this.config.data_storage\n if (typeof(crossDomain) === \"function\") { \n return crossDomain()\n } else { \n return crossDomain \n }\n }\n\n getHeaders(){\n let { headers } = this.config.data_storage\n if (typeof(headers) === \"function\") { \n return headers() \n } else { \n return headers \n }\n }\n\n checkforStore(content){\n // ENTER DATA STORE\n let isChanged = !Immutable.is(Immutable.fromJS(this.editorContent), Immutable.fromJS(content))\n // console.log(\"CONTENT CHANGED:\", isChanged)\n\n if (!isChanged) { return }\n\n this.save(content)\n }\n\n save(content){\n\n // use save handler from config if exists\n if (this.config.data_storage.save_handler){\n this.config.data_storage.save_handler(this, content)\n return \n }\n\n if (this.config.xhr.before_handler) { this.config.xhr.before_handler() }\n // console.log \"SAVING TO: #{@getMethod()} #{@getUrl()}\"\n\n return axios({\n method: this.getMethod(),\n url: this.getUrl(),\n data: {\n editor_content: JSON.stringify(content),\n text_content: this.getTextFromEditor(content)\n },\n withCredentials: this.getWithCredentials(),\n crossDomain: this.getCrossDomain(),\n headers: this.getHeaders(),\n })\n .then(result=> {\n // console.log \"STORING CONTENT\", result\n if (this.config.data_storage.success_handler) { this.config.data_storage.success_handler(result) }\n if (this.config.xhr.success_handler) { return this.config.xhr.success_handler(result) }\n }\n )\n .catch(error=> {\n // console.log(\"ERROR: got error saving content at #{@config.data_storage.url} - #{error}\")\n if (this.config.xhr.failure_handler) { return this.config.xhr.failure_handler(error) }\n }\n )\n }\n}\n\n\nexport default SaveBehavior\n\n\n\n// WEBPACK FOOTER //\n// src/utils/save_content.js","import { Map } from 'immutable';\n\n\n\nimport { EditorState, ContentBlock, genKey } from 'draft-js';\n\n\n/*\nUsed from [react-rte](https://github.com/brijeshb42/medium-draft)\nby [brijeshb42](https://github.com/brijeshb42/medium-draft)\n*/\n\n/*\nReturns default block-level metadata for various block type. Empty object otherwise.\n*/\nexport const getDefaultBlockData = (blockType, initialData = {}) => {\n switch (blockType) {\n //case Block.TODO: return { checked: false };\n default: return initialData;\n }\n};\n\nexport const getNode = (root=window) => {\n let t = null\n if (root.getSelection){\n t = root.getSelection()\n } else if (root.document.getSelection){\n t = root.document.getSelection()\n } else if (root.document.selection){\n t = root.document.selection.createRange().text\n }\n return t\n}\n\n/*\nGet currentBlock in the editorState.\n*/\nexport const getCurrentBlock = (editorState) => {\n const selectionState = editorState.getSelection();\n const contentState = editorState.getCurrentContent();\n const block = contentState.getBlockForKey(selectionState.getStartKey());\n return block;\n};\n\n/*\nAdds a new block (currently replaces an empty block) at the current cursor position\nof the given `newType`.\n*/\nexport const addNewBlock = (editorState, newType = \"unstyled\", initialData = {}) => {\n const selectionState = editorState.getSelection();\n if (!selectionState.isCollapsed()) {\n return editorState;\n }\n const contentState = editorState.getCurrentContent();\n const key = selectionState.getStartKey();\n const blockMap = contentState.getBlockMap();\n const currentBlock = getCurrentBlock(editorState);\n if (!currentBlock) {\n return editorState;\n }\n if (currentBlock.getLength() === 0) {\n if (currentBlock.getType() === newType) {\n return editorState;\n }\n const newBlock = currentBlock.merge({\n type: newType,\n data: getDefaultBlockData(newType, initialData),\n });\n const newContentState = contentState.merge({\n blockMap: blockMap.set(key, newBlock),\n selectionAfter: selectionState,\n });\n return EditorState.push(editorState, newContentState, 'change-block-type');\n }\n return editorState;\n};\n\n\n/*\nChanges the block type of the current block.\n*/\nexport const resetBlockWithType = (editorState, newType = \"unstyled\", data={}) => {\n const contentState = editorState.getCurrentContent();\n const selectionState = editorState.getSelection();\n const key = selectionState.getStartKey();\n const blockMap = contentState.getBlockMap();\n const block = blockMap.get(key);\n\n const text = block.getText();\n\n const newBlock = block.merge({\n text: text,\n type: newType,\n data: getDefaultBlockData(newType, data),\n });\n const newContentState = contentState.merge({\n blockMap: blockMap.set(key, newBlock),\n selectionAfter: selectionState.merge({\n anchorOffset: 0,\n focusOffset: 0,\n }),\n });\n return EditorState.push(editorState, newContentState, 'change-block-type');\n};\n\n\n/*\nUpdate block-level metadata of the given `block` to the `newData`/\n*/\nexport const updateDataOfBlock = (editorState, block, newData) => {\n const contentState = editorState.getCurrentContent();\n const newBlock = block.merge({\n data: newData,\n });\n const newContentState = contentState.merge({\n blockMap: contentState.getBlockMap().set(block.getKey(), newBlock),\n });\n return EditorState.push(editorState, newContentState, 'change-block-type');\n // return editorState;\n};\n\nexport const updateTextOfBlock = (editorState, block, text) => {\n const contentState = editorState.getCurrentContent();\n const newBlock = block.merge({\n text: text,\n });\n const newContentState = contentState.merge({\n blockMap: contentState.getBlockMap().set(block.getKey(), newBlock),\n });\n\n return EditorState.push(editorState, newContentState, 'change-block-type');\n // return editorState;\n};\n\n// const BEFORE = -1;\n// const AFTER = 1;\n\n/*\nUsed from [react-rte](https://github.com/sstur/react-rte/blob/master/src/lib/insertBlockAfter.js)\nby [sstur](https://github.com/sstur)\n*/\nexport const addNewBlockAt = (\n editorState,\n pivotBlockKey,\n newBlockType = \"unstyled\",\n initialData = {}\n ) => {\n const content = editorState.getCurrentContent();\n const blockMap = content.getBlockMap();\n const block = blockMap.get(pivotBlockKey);\n const blocksBefore = blockMap.toSeq().takeUntil((v) => (v === block));\n const blocksAfter = blockMap.toSeq().skipUntil((v) => (v === block)).rest();\n const newBlockKey = genKey();\n\n const newBlock = new ContentBlock({\n key: newBlockKey,\n type: newBlockType,\n text: '',\n characterList: block.getCharacterList().slice(0, 0),\n depth: 0,\n data: Map(getDefaultBlockData(newBlockType, initialData)),\n });\n\n const newBlockMap = blocksBefore.concat(\n [[pivotBlockKey, block], [newBlockKey, newBlock]],\n blocksAfter\n ).toOrderedMap();\n\n const selection = editorState.getSelection();\n\n const newContent = content.merge({\n blockMap: newBlockMap,\n selectionBefore: selection,\n selectionAfter: selection.merge({\n anchorKey: newBlockKey,\n anchorOffset: 0,\n focusKey: newBlockKey,\n focusOffset: 0,\n isBackward: false,\n }),\n });\n return EditorState.push(editorState, newContent, 'split-block');\n};\n\n\n\n// WEBPACK FOOTER //\n// src/model/index.js","module.exports = __webpack_public_path__ + \"fonts/dante.svg\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.svg\n// module id = 429\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/dante.ttf\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.ttf\n// module id = 430\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/dante.woff\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.woff\n// module id = 431\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.svg\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.svg\n// module id = 432\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.ttf\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.ttf\n// module id = 433\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.woff\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.woff\n// module id = 434\n// module chunks = 0","/*\nReturns the `boundingClientRect` of the passed selection.\n*/\nexport const getSelectionRect = (selected) => {\n const _rect = selected.getRangeAt(0).getBoundingClientRect();\n // selected.getRangeAt(0).getBoundingClientRect()\n let rect = _rect && _rect.top ? _rect : selected.getRangeAt(0).getClientRects()[0];\n if (!rect) {\n if (selected.anchorNode && selected.anchorNode.getBoundingClientRect) {\n rect = selected.anchorNode.getBoundingClientRect();\n rect.isEmptyline = true;\n } else {\n return null;\n }\n }\n return rect;\n};\n\n/*\nReturns the native selection node.\n*/\nexport const getSelection = (root) => {\n let t = null;\n if (root.getSelection) {\n t = root.getSelection();\n } else if (root.document.getSelection) {\n t = root.document.getSelection();\n } else if (root.document.selection) {\n t = root.document.selection.createRange().text;\n }\n return t;\n};\n\n/*\nRecursively finds the DOM Element of the block where the cursor is currently present.\nIf not found, returns null.\n*/\nexport const getSelectedBlockNode = (root) => {\n const selection = root.getSelection();\n if (selection.rangeCount === 0) {\n return null;\n }\n let node = selection.getRangeAt(0).startContainer;\n // console.log(node);\n do {\n if (node.getAttribute && node.getAttribute('data-block') === 'true') {\n return node;\n }\n node = node.parentNode;\n // console.log(node);\n } while (node !== null);\n return null;\n};\n\n\n\n// WEBPACK FOOTER //\n// src/utils/selection.js"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;AAcA;AACA;AAIA;AACA;AAQA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;;;AAEA;;;AACA;AAAA;AACA;AADA;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;AAFA;AACA;AAIA;AACA;AACA;AADA;AAGA;AACA;AADA;AAGA;AACA;AADA;AAGA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAFA;AACA;AAnBA;AACA;AAwBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AAPA;AACA;AAzGA;AAAA;AAAA;AAAA;AACA;AACA;AAiHA;AACA;AApHA;AAqHA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAUA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;;;AAEA;AACA;AACA;AACA;AAAA;AAAA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AACA;AASA;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;AAVA;AAHA;AACA;AAgBA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAFA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAJA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAfA;AAiBA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAHA;AACA;AAWA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AACA;AACA;AAOA;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;AANA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AACA;AACA;AACA;AACA;AAJA;AACA;AAMA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AAAA;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;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;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;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AADA;AAGA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlBA;AAHA;AADA;AAJA;AADA;AADA;AADA;AADA;AAwCA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAZA;AAeA;AAGA;AA7DA;AAoEA;;;AAr3BA;AACA;AAu3BA;;;;;;;ACl6BA;;;;;;;ACAA;;;;;;;;;;;;;;;ACCA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;ACRA;;;;;;;;;;ACAA;AACA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;;;AACA;AACA;;;AACA;;;AACA;AAAA;AACA;AACA;AACA;AAHA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAFA;AAPA;AAWA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAJA;AAQA;AACA;AAAA;AAAA;AAAA;AAGA;AAAA;AAAA;AACA;AACA;AACA;AAHA;AAKA;AAAA;AAAA;AACA;AADA;AAGA;AAAA;AAAA;AACA;AADA;AARA;AAWA;AAzBA;AA4BA;;;AAjHA;AACA;AADA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACVA;AACA;;;AAAA;AACA;;;AACA;AACA;AAMA;AACA;;;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;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;AAVA;AA3BA;AAuCA;AACA;;;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AADA;AAGA;AACA;AACA;AACA;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAIA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AAHA;AAKA;;;AAEA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;;;AAIA;AACA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAXA;AAaA;AAAA;AAAA;AACA;AACA;AAAA;AACA;AADA;AAGA;AACA;AANA;AAdA;AAyBA;;;AAzVA;AACA;AADA;AACA;AA2VA;;;;;;;;;;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AAEA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AACA;AADA;AAHA;AADA;AAFA;AAgBA;;;AApBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzWA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AACA;;;AACA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AANA;AAUA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AADA;AADA;AAOA;AACA;;;AAEA;AACA;AACA;AAAA;AAEA;AAEA;AACA;AACA;AAFA;AAJA;AAUA;;;AAvDA;AACA;AADA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AACA;;;AACA;AAAA;AACA;AACA;AACA;AAHA;AACA;AAGA;AACA;AACA;AANA;AAOA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AAAA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AACA;AADA;AAHA;AAQA;;;AAnEA;AACA;AADA;;;;;;;;;;;;;;;;;;;;;;ACVA;AACA;;;AAAA;AACA;;;AAAA;AACA;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AAIA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAUA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AApCA;AA8CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AAFA;AAIA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AA1BA;AA4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AAHA;AACA;AAKA;AAAA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AA7BA;AA+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AADA;AAGA;AAAA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AA9BA;AACA;AAiCA;AACA;AACA;AACA;AACA;AAWA;AACA;AACA;AACA;AACA;AAJA;AAfA;AA+BA;AACA;AAFA;AAIA;AACA;AAFA;AAIA;AACA;AAFA;AACA;AAIA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AACA;AAUA;AACA;AAWA;AACA;AASA;AACA;AACA;AAGA;AALA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AACA;AAWA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AAIA;;;;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3SA;AACA;;;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAZA;AAgBA;AACA;;;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AAEA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AADA;AADA;AAKA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AAGA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AAVA;AADA;AAgBA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAEA;AACA;AAAA;AAAA;AAAA;AAJA;AAFA;AAjBA;AA8BA;;;AAjGA;AACA;AAmGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtGA;AACA;;;AAAA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AAOA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AAPA;AAUA;;;AA3DA;AACA;AADA;;;;;;;;;;;;;;;ACFA;AACA;;;AAAA;AACA;;;;;AAEA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACNA;AACA;;;AAAA;AACA;;;AACA;AACA;AAMA;AACA;AAMA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAjBA;AAsBA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;;;AAEA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;;;AAEA;AACA;AACA;AACA;;;;AAIA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAUA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;;;;;;;;;;;;;;;;AAiBA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAFA;AAIA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAJA;AAMA;AANA;AAQA;AAAA;AAAA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;AAHA;AAKA;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAZA;AAZA;AAkCA;;;AAvRA;AACA;AAyRA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AAFA;AAGA;AACA;;;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAHA;AAKA;AALA;AAQA;;;AAtBA;AACA;AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrUA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAPA;AAZA;AAwBA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAEA;AALA;AAQA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AAPA;AADA;AAYA;AApBA;AAuBA;;;AAvJA;AACA;AAyJA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AACA;AAHA;AAIA;AACA;;;AACA;AACA;AACA;AACA;;;AAEA;AACA;AAAA;AAAA;AACA;AACA;AACA;AAHA;AAKA;;;AAnBA;AACA;AAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzLA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AANA;AARA;AAgBA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AADA;AADA;AAKA;AAZA;AAeA;;;AAhGA;AACA;AAkGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzGA;AACA;;;AAAA;AACA;;;AACA;AACA;AAYA;AACA;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAlBA;AAuBA;AACA;;;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AACA;AACA;AACA;;;AAEA;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;AAFA;AAFA;AAOA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AAJA;AAMA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AARA;AAUA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AAQA;AAGA;AACA;AACA;AAFA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AA3BA;AAhBA;AAgDA;;;AA5SA;AACA;AA8SA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAQA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AADA;AAIA;;;AAxDA;AACA;AA0DA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AAFA;AAGA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AAIA;;;AApBA;AACA;AA2BA;;;;;;;;;;;;;;AC1ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;ACjBA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAHA;AAQA;AACA;AACA;AACA;AACA;AACA;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;AChIA;AACA;;;AAAA;AACA;;;;;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;;;AAEA;AACA;AACA;AACA;AAGA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AATA;AAYA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAGA;AACA;AAAA;AAAA;AACA;AAEA;;;;;AAIA;;;;;;;;;;;;;;;AC/HA;AACA;AAGA;AACA;AAEA;;;;;AAKA;;;AAGA;AAAA;AACA;AAAA;AACA;AACA;AAAA;AAFA;AAIA;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AAAA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;AAEA;;;AAGA;AAAA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AAFA;AAFA;AAOA;AACA;AACA;AAEA;;;AAGA;AACA;AACA;AACA;AADA;AAGA;AACA;AADA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AADA;AAGA;AACA;AADA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AAKA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AACA;AAQA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAHA;AAWA;AACA;;;;;;;ACtLA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;;;;;;;ACAA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;A","sourceRoot":""}
|
1
|
+
{"version":3,"file":"dante.js","sources":["webpack:///src/components/core/editor.js","webpack:///./src/styles/fonts/dante/dante.eot","webpack:///./src/styles/fonts/dante/fontello.eot","webpack:///src/index.js","webpack:///./src/styles/dante.scss?293d","webpack:///demo/initialize.js","webpack:///src/components/blocks/embed.js","webpack:///src/components/blocks/image.js","webpack:///src/components/blocks/placeholder.js","webpack:///src/components/blocks/video.js","webpack:///src/components/core/dante.js","webpack:///src/components/core/debug.js","webpack:///src/components/decorators/link.js","webpack:///src/components/init.js","webpack:///src/components/popovers/addButton.js","webpack:///src/components/popovers/image.js","webpack:///src/components/popovers/link.js","webpack:///src/components/popovers/toolTip.js","webpack:///src/utils/find_entities.js","webpack:///src/utils/html2content.js","webpack:///src/utils/save_content.js","webpack:///src/model/index.js","webpack:///./src/styles/fonts/dante/dante.svg","webpack:///./src/styles/fonts/dante/dante.ttf","webpack:///./src/styles/fonts/dante/dante.woff","webpack:///./src/styles/fonts/dante/fontello.svg","webpack:///./src/styles/fonts/dante/fontello.ttf","webpack:///./src/styles/fonts/dante/fontello.woff","webpack:///src/utils/selection.js"],"sourcesContent":["\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport Immutable from 'immutable'\nimport { Map, fromJS } from 'immutable'\nimport { \n convertToRaw, \n convertFromRaw, \n CompositeDecorator, \n getDefaultKeyBinding,\n ContentState, \n Editor, \n EditorState, \n Entity, \n RichUtils, \n DefaultDraftBlockRenderMap, \n SelectionState, \n Modifier\n} from 'draft-js'\n\nimport { \n convertToHTML,\n //, convertFromHTML \n} from 'draft-convert'\n\nimport { \n addNewBlock, \n resetBlockWithType, \n updateDataOfBlock, \n //updateTextOfBlock, \n getCurrentBlock, \n addNewBlockAt \n} from '../../model/index.js'\n\nimport Link from '../decorators/link'\nimport Debug from '../core/debug'\nimport findEntities from '../../utils/find_entities'\nimport SaveBehavior from '../../utils/save_content'\nimport customHTML2Content from '../../utils/html2content'\nimport createStyles from 'draft-js-custom-styles'\n\n\nclass DanteEditor extends React.Component {\n constructor(props) {\n super(props)\n\n this.initializeState = this.initializeState.bind(this)\n this.refreshSelection = this.refreshSelection.bind(this)\n this.forceRender = this.forceRender.bind(this)\n this.onChange = this.onChange.bind(this)\n this.dispatchChangesToSave = this.dispatchChangesToSave.bind(this)\n this.setPreContent = this.setPreContent.bind(this)\n this.focus = this.focus.bind(this)\n this.getEditorState = this.getEditorState.bind(this)\n this.emitSerializedOutput = this.emitSerializedOutput.bind(this)\n this.decodeEditorContent = this.decodeEditorContent.bind(this)\n this.getTextFromEditor = this.getTextFromEditor.bind(this)\n this.getLocks = this.getLocks.bind(this)\n this.addLock = this.addLock.bind(this)\n this.removeLock = this.removeLock.bind(this)\n this.renderableBlocks = this.renderableBlocks.bind(this)\n this.defaultWrappers = this.defaultWrappers.bind(this)\n this.blockRenderer = this.blockRenderer.bind(this)\n this.handleBlockRenderer = this.handleBlockRenderer.bind(this)\n this.blockStyleFn = this.blockStyleFn.bind(this)\n this.getDataBlock = this.getDataBlock.bind(this)\n this.styleForBlock = this.styleForBlock.bind(this)\n this.handlePasteText = this.handlePasteText.bind(this)\n this.handleTXTPaste = this.handleTXTPaste.bind(this)\n this.handleHTMLPaste = this.handleHTMLPaste.bind(this)\n this.handlePasteImage = this.handlePasteImage.bind(this)\n this.handleDroppedFiles = this.handleDroppedFiles.bind(this)\n this.handleDrop = this.handleDrop.bind(this)\n this.handleUpArrow = this.handleUpArrow.bind(this)\n this.handleDownArrow = this.handleDownArrow.bind(this)\n this.handleReturn = this.handleReturn.bind(this)\n this.handleBeforeInput = this.handleBeforeInput.bind(this)\n this.handleKeyCommand = this.handleKeyCommand.bind(this)\n this.findCommandKey = this.findCommandKey.bind(this)\n this.KeyBindingFn = this.KeyBindingFn.bind(this)\n this.updateBlockData = this.updateBlockData.bind(this)\n this.setDirection = this.setDirection.bind(this)\n this.toggleEditable = this.toggleEditable.bind(this)\n this.disableEditable = this.disableEditable.bind(this)\n this.enableEditable = this.enableEditable.bind(this)\n this.closePopOvers = this.closePopOvers.bind(this)\n this.relocateTooltips = this.relocateTooltips.bind(this)\n this.tooltipsWithProp = this.tooltipsWithProp.bind(this)\n this.tooltipHasSelectionElement = this.tooltipHasSelectionElement.bind(this)\n this.handleShowPopLinkOver = this.handleShowPopLinkOver.bind(this)\n this.handleHidePopLinkOver = this.handleHidePopLinkOver.bind(this)\n this.showPopLinkOver = this.showPopLinkOver.bind(this)\n this.hidePopLinkOver = this.hidePopLinkOver.bind(this)\n this.render = this.render.bind(this)\n\n this.decorator = new CompositeDecorator([{\n strategy: findEntities.bind(null, 'LINK', this),\n component: Link\n }])\n\n this.blockRenderMap = Map({\n \"image\": {\n element: 'figure'\n },\n \"video\": {\n element: 'figure'\n },\n \"embed\": {\n element: 'div'\n },\n 'unstyled': {\n wrapper: null,\n element: 'div'\n },\n 'paragraph': {\n wrapper: null,\n element: 'div'\n },\n 'placeholder': {\n wrapper: null,\n element: 'div'\n }\n\n })\n\n this.extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(this.blockRenderMap)\n\n this.state = {\n editorState: EditorState.createEmpty(),\n read_only: this.props.config.read_only,\n blockRenderMap: this.extendedBlockRenderMap,\n locks: 0,\n debug: this.props.config.debug\n }\n\n this.widgets = this.props.config.widgets\n this.tooltips = this.props.config.tooltips\n\n this.key_commands = this.props.config.key_commands\n\n this.continuousBlocks = this.props.config.continuousBlocks\n\n this.block_types = this.props.config.block_types\n\n this.default_wrappers = this.props.config.default_wrappers\n\n this.character_convert_mapping = this.props.config.character_convert_mapping\n\n this.save = new SaveBehavior({\n getLocks: this.getLocks,\n config: {\n xhr: this.props.config.xhr,\n data_storage: this.props.config.data_storage\n },\n editor: this,\n editorState: this.getEditorState,\n editorContent: this.emitSerializedOutput()\n })\n\n const { styles, customStyleFn, exporter } = createStyles(['font-size', 'color', 'font-family']); //, 'PREFIX', customStyleMap);\n this.styles = styles\n this.customStyleFn = customStyleFn\n }\n\n componentDidMount(){\n this.initializeState()\n window.addEventListener('resize', ()=> {\n if(this.relocateTooltips)\n setTimeout(() => {\n return this.relocateTooltips()\n })\n })\n }\n\n initializeState() {\n let newEditorState = EditorState.createEmpty(this.decorator)\n if (this.props.content) {\n newEditorState = EditorState.set(this.decodeEditorContent(this.props.content), {decorator: this.decorator});\n }\n this.onChange(newEditorState) \n }\n\n decodeEditorContent(raw_as_json) {\n const new_content = convertFromRaw(raw_as_json)\n let editorState\n return editorState = EditorState.createWithContent(new_content, this.decorator)\n }\n\n refreshSelection(newEditorState) {\n const { editorState } = this.state\n // Setting cursor position after inserting to content\n const s = this.state.editorState.getSelection()\n const c = editorState.getCurrentContent()\n const focusOffset = s.getFocusOffset()\n const anchorKey = s.getAnchorKey()\n\n let selectionState = SelectionState.createEmpty(s.getAnchorKey())\n\n // console.log anchorKey, focusOffset\n selectionState = selectionState.merge({\n anchorOffset: focusOffset,\n focusKey: anchorKey,\n focusOffset\n })\n\n let newState = EditorState.forceSelection(newEditorState, selectionState)\n\n return this.onChange(newState)\n }\n\n forceRender(editorState) {\n const selection = this.state.editorState.getSelection()\n const content = editorState.getCurrentContent()\n const newEditorState = EditorState.createWithContent(content, this.decorator)\n\n return this.refreshSelection(newEditorState)\n }\n\n onChange(editorState) {\n\n editorState = this.handleUndeletables(editorState)\n\n this.setPreContent()\n this.setState({ editorState })\n\n const currentBlock = getCurrentBlock(this.state.editorState)\n const blockType = currentBlock.getType()\n\n\n if (!editorState.getSelection().isCollapsed()) {\n const tooltip = this.tooltipsWithProp('displayOnSelection')[0]\n if (!this.tooltipHasSelectionElement(tooltip, blockType)) {\n return\n }\n this.handleTooltipDisplayOn('displayOnSelection')\n } else {\n this.handleTooltipDisplayOn('displayOnSelection', false)\n }\n\n setTimeout(() => {\n return this.relocateTooltips()\n })\n\n return this.dispatchChangesToSave()\n }\n\n handleUndeletables(editorState){\n // undeletable behavior, will keep previous blockMap \n // if undeletables are deleted\n const undeletable_types = this.widgets.filter(\n function(o){ return o.undeletable })\n .map(function(o){ return o.type })\n \n const currentblockMap = this.state.editorState.getCurrentContent().get(\"blockMap\")\n const blockMap = editorState.getCurrentContent().get(\"blockMap\")\n\n const undeletablesMap = blockMap\n .filter(function(o){ \n return undeletable_types.indexOf(o.get(\"type\")) > 0 \n })\n\n if (undeletable_types.length > 0 && undeletablesMap.size === 0) {\n\n const contentState = editorState.getCurrentContent();\n const blockMap = contentState.getBlockMap();\n const newContentState = contentState.merge({\n blockMap: this.state.editorState.getCurrentContent().blockMap,\n selectionBefore: contentState.getSelectionAfter()\n });\n\n return editorState = EditorState.push(editorState, newContentState, 'change-block')\n }\n\n return editorState\n }\n\n dispatchChangesToSave() {\n clearTimeout(this.saveTimeout)\n return this.saveTimeout = setTimeout(() => {\n return this.save.store(this.emitSerializedOutput())\n }, 100)\n }\n\n setPreContent() {\n const content = this.emitSerializedOutput()\n return this.save.editorContent = content\n }\n\n focus() {\n //debugger\n }\n //@props.refs.richEditor.focus()\n\n getEditorState() {\n return this.state.editorState\n }\n\n emitSerializedOutput() {\n const raw = convertToRaw(this.state.editorState.getCurrentContent())\n\n return raw\n }\n\n //# title utils\n getTextFromEditor() {\n const c = this.state.editorState.getCurrentContent()\n const out = c.getBlocksAsArray().map(o => {\n return o.getText()\n }).join(\"\\n\")\n\n return out\n }\n\n emitHTML2() {\n let html\n\n return html = convertToHTML({\n entityToHTML: (entity, originalText) => {\n if (entity.type === 'LINK') {\n return `<a href=\\\"${ entity.data.url }\\\">${ originalText }</a>`\n } else {\n return originalText\n }\n }\n\n })(this.state.editorState.getCurrentContent())\n }\n\n getLocks() {\n return this.state.locks\n }\n\n addLock() {\n return this.setState({\n locks: this.state.locks += 1 })\n }\n\n removeLock() {\n return this.setState({\n locks: this.state.locks -= 1 })\n }\n\n renderableBlocks() {\n return this.widgets.filter(o => o.renderable).map(o => o.type)\n }\n\n defaultWrappers(blockType) {\n return this.default_wrappers.filter(o => {\n return o.block === blockType\n }).map(o => o.className)\n }\n\n blockRenderer(block) {\n\n switch (block.getType()) {\n\n case \"atomic\":\n\n const entity = block.getEntityAt(0)\n const entity_type = Entity.get(entity).getType()\n\n break\n }\n\n if (this.renderableBlocks().includes(block.getType())) {\n return this.handleBlockRenderer(block)\n }\n\n return null\n }\n\n handleBlockRenderer(block) {\n const dataBlock = this.getDataBlock(block)\n if (!dataBlock) {\n return null\n }\n\n const read_only = this.state.read_only ? false : null\n const editable = read_only !== null ? read_only : dataBlock.editable\n return {\n component: eval(dataBlock.block),\n editable,\n props: {\n data: block.getData(),\n getEditorState: this.getEditorState,\n setEditorState: this.onChange,\n addLock: this.addLock,\n toggleEditable: this.toggleEditable,\n disableEditable: this.disableEditable,\n enableEditable: this.enableEditable,\n removeLock: this.removeLock,\n getLocks: this.getLocks,\n config: dataBlock.options\n }\n }\n\n return null\n }\n\n blockStyleFn(block) {\n const currentBlock = getCurrentBlock(this.state.editorState)\n const is_selected = currentBlock.getKey() === block.getKey() ? \"is-selected\" : \"\"\n\n if (this.renderableBlocks().includes(block.getType())) {\n return this.styleForBlock(block, currentBlock, is_selected)\n }\n\n const defaultBlockClass = this.defaultWrappers(block.getType())\n if (defaultBlockClass.length > 0) {\n return `graf ${ defaultBlockClass[0] } ${ is_selected }`\n } else {\n return `graf ${ is_selected }`\n }\n }\n\n getDataBlock(block) {\n return this.widgets.find(o => {\n return o.type === block.getType()\n })\n }\n\n styleForBlock(block, currentBlock, is_selected) {\n const dataBlock = this.getDataBlock(block)\n\n if (!dataBlock) {\n return null\n }\n\n const selectedFn = dataBlock.selectedFn ? dataBlock.selectedFn(block) : ''\n const selected_class = (dataBlock.selected_class ? dataBlock.selected_class : '' )\n const selected_class_out = is_selected ? selected_class : ''\n\n return `${ dataBlock.wrapper_class } ${ selected_class_out } ${ selectedFn }`\n }\n\n handleTooltipDisplayOn(prop, display) {\n\n // for button click on after inline style set, \n // avoids inline popver to reappear on previous selection\n if(this.state.read_only){\n return \n }\n\n if (display == null) {\n display = true\n }\n \n return setTimeout(() => {\n const items = this.tooltipsWithProp(prop)\n console.log(items)\n return items.map(o => {\n this.refs[o.ref].display(display)\n return this.refs[o.ref].relocate()\n })\n }, 20)\n }\n\n handlePasteText(text, html) {\n\n // https://github.com/facebook/draft-js/issues/685\n /*\n html = \"<p>chao</p>\n <avv>aaa</avv>\n <p>oli</p>\n <img src='x'/>\"\n */\n\n // if not html then fallback to default handler\n\n if (!html) {\n return this.handleTXTPaste(text, html)\n }\n if (html) {\n return this.handleHTMLPaste(text, html)\n }\n }\n\n handleTXTPaste(text, html) {\n const currentBlock = getCurrentBlock(this.state.editorState)\n\n let { editorState } = this.state\n\n switch (currentBlock.getType()) {\n case \"image\":case \"video\":case \"placeholder\":\n const newContent = Modifier.replaceText(editorState.getCurrentContent(), new SelectionState({\n anchorKey: currentBlock.getKey(),\n anchorOffset: 0,\n focusKey: currentBlock.getKey(),\n focusOffset: 2\n }), text)\n\n editorState = EditorState.push(editorState, newContent, 'replace-text')\n\n this.onChange(editorState)\n\n return true\n default:\n return false\n }\n }\n\n handleHTMLPaste(text, html) {\n\n const currentBlock = getCurrentBlock(this.state.editorState)\n\n // TODO: make this configurable\n switch (currentBlock.getType()) {\n case \"image\":case \"video\":case \"placeholder\":\n return this.handleTXTPaste(text, html)\n break\n }\n\n const newContentState = customHTML2Content(html, this.extendedBlockRenderMap)\n\n const selection = this.state.editorState.getSelection()\n const endKey = selection.getEndKey()\n\n const content = this.state.editorState.getCurrentContent()\n const blocksBefore = content.blockMap.toSeq().takeUntil(v => v.key === endKey)\n const blocksAfter = content.blockMap.toSeq().skipUntil(v => v.key === endKey).rest()\n\n const newBlockKey = newContentState.blockMap.first().getKey()\n\n const newBlockMap = blocksBefore.concat(newContentState.blockMap, blocksAfter).toOrderedMap()\n\n const newContent = content.merge({\n blockMap: newBlockMap,\n selectionBefore: selection,\n selectionAfter: selection.merge({\n anchorKey: newBlockKey,\n anchorOffset: 0,\n focusKey: newBlockKey,\n focusOffset: 0,\n isBackward: false\n })\n })\n\n const pushedContentState = EditorState.push(this.state.editorState, newContent, 'insert-fragment')\n\n this.onChange(pushedContentState)\n\n return true\n }\n\n handlePasteImage(files) {\n //TODO: check file types\n return files.map(file => {\n let opts = {\n url: URL.createObjectURL(file),\n file\n }\n\n return this.onChange(addNewBlock(this.state.editorState, 'image', opts))\n })\n }\n\n handleDroppedFiles(state, files) {\n return files.map(file => {\n let opts = {\n url: URL.createObjectURL(file),\n file\n }\n\n return this.onChange(addNewBlock(this.state.editorState, 'image', opts))\n })\n }\n\n handleDrop(selection, dataTransfer, isInternal){\n\n const editorState = this.getEditorState();\n\n const raw = dataTransfer.data.getData('text');\n\n const data = JSON.parse(raw);\n\n this.onChange(addNewBlock(editorState, data.type, data.data))\n\n return 'handled';\n }\n\n handleUpArrow(e) {\n return setTimeout(() => {\n return this.forceRender(this.state.editorState)\n }, 10)\n }\n\n handleDownArrow(e) {\n return setTimeout(() => {\n return this.forceRender(this.state.editorState)\n }, 10)\n }\n\n handleReturn(e) {\n if (this.props.handleReturn) {\n if (this.props.handleReturn()) {\n return true\n }\n }\n\n let { editorState } = this.state\n\n if (e.shiftKey) {\n this.setState({ editorState: RichUtils.insertSoftNewline(editorState) });\n return true;\n }\n\n\n if (!e.altKey && !e.metaKey && !e.ctrlKey) {\n const currentBlock = getCurrentBlock(editorState)\n const blockType = currentBlock.getType()\n const selection = editorState.getSelection()\n\n const config_block = this.getDataBlock(currentBlock)\n\n if (currentBlock.getText().length === 0) {\n\n if (config_block && config_block.handleEnterWithoutText) {\n config_block.handleEnterWithoutText(this, currentBlock)\n this.closePopOvers()\n return true\n }\n\n //TODO turn this in configurable\n switch (blockType) {\n case \"header-one\":\n this.onChange(resetBlockWithType(editorState, \"unstyled\"))\n return true\n break\n default:\n return false\n }\n }\n\n if (currentBlock.getText().length > 0) {\n\n if (config_block && config_block.handleEnterWithText) {\n config_block.handleEnterWithText(this, currentBlock)\n this.closePopOvers()\n return true\n }\n\n if (currentBlock.getLength() === selection.getStartOffset()) {\n if (this.continuousBlocks.indexOf(blockType) < 0) {\n this.onChange(addNewBlockAt(editorState, currentBlock.getKey()))\n return true\n }\n }\n\n return false\n }\n\n // selection.isCollapsed() and # should we check collapsed here?\n if (currentBlock.getLength() === selection.getStartOffset()) {\n //or (config_block && config_block.breakOnContinuous))\n // it will match the unstyled for custom blocks\n if (this.continuousBlocks.indexOf(blockType) < 0) {\n this.onChange(addNewBlockAt(editorState, currentBlock.getKey()))\n return true\n }\n return false\n }\n\n return false\n }\n }\n\n //return false\n\n // TODO: make this configurable\n handleBeforeInput(chars) {\n const currentBlock = getCurrentBlock(this.state.editorState)\n const blockType = currentBlock.getType()\n const selection = this.state.editorState.getSelection()\n\n let { editorState } = this.state\n\n // close popovers\n if (currentBlock.getText().length !== 0) {\n //@closeInlineButton()\n this.closePopOvers()\n }\n\n // handle space on link\n const endOffset = selection.getEndOffset()\n const endKey = currentBlock.getEntityAt(endOffset - 1)\n const endEntityType = endKey && Entity.get(endKey).getType()\n const afterEndKey = currentBlock.getEntityAt(endOffset)\n const afterEndEntityType = afterEndKey && Entity.get(afterEndKey).getType()\n\n // will insert blank space when link found\n if (chars === ' ' && endEntityType === 'LINK' && afterEndEntityType !== 'LINK') {\n const newContentState = Modifier.insertText(editorState.getCurrentContent(), selection, ' ')\n const newEditorState = EditorState.push(editorState, newContentState, 'insert-characters')\n this.onChange(newEditorState)\n return true\n }\n\n // block transform\n if (blockType.indexOf('atomic') === 0) {\n return false\n }\n\n const blockLength = currentBlock.getLength()\n if (selection.getAnchorOffset() > 1 || blockLength > 1) {\n return false\n }\n\n const blockTo = this.character_convert_mapping[currentBlock.getText() + chars]\n\n console.log(`BLOCK TO SHOW: ${ blockTo }`)\n\n if (!blockTo) {\n return false\n }\n\n this.onChange(resetBlockWithType(editorState, blockTo))\n\n return true\n }\n\n // TODO: make this configurable\n handleKeyCommand(command) {\n const { editorState } = this.state\n let currentBlockType, newBlockType\n\n if (this.props.handleKeyCommand && this.props.handleKeyCommand(command)) {\n return true\n }\n\n if (command === 'add-new-block') {\n this.onChange(addNewBlock(editorState, 'blockquote'))\n return true\n }\n\n const block = getCurrentBlock(editorState)\n\n if (command.indexOf('toggle_inline:') === 0) {\n newBlockType = command.split(':')[1]\n currentBlockType = block.getType()\n this.onChange(RichUtils.toggleInlineStyle(editorState, newBlockType))\n return true\n }\n\n if (command.indexOf('toggle_block:') === 0) {\n newBlockType = command.split(':')[1]\n currentBlockType = block.getType()\n\n this.onChange(RichUtils.toggleBlockType(editorState, newBlockType))\n return true\n }\n\n const newState = RichUtils.handleKeyCommand(this.state.editorState, command)\n if (newState) {\n this.onChange(newState)\n return true\n }\n\n return false\n }\n\n findCommandKey(opt, command) {\n // console.log \"COMMAND find: #{opt} #{command}\"\n return this.key_commands[opt].find(o => o.key === command)\n }\n\n KeyBindingFn(e) {\n\n //⌘ + B / Ctrl + B Bold\n //⌘ + I / Ctrl + I Italic\n //⌘ + K / Ctrl + K Turn into link\n //⌘ + Alt + 1 / Ctrl + Alt + 1 Header\n //⌘ + Alt + 2 / Ctrl + Alt + 2 Sub-Header\n //⌘ + Alt + 5 / Ctrl + Alt + 5 Quote (Press once for a block quote, again for a pull quote and a third time to turn off quote)\n\n let cmd\n if (e.altKey) {\n if (e.shiftKey) {\n cmd = this.findCommandKey(\"alt-shift\", e.which)\n if (cmd) {\n return cmd.cmd\n }\n\n return getDefaultKeyBinding(e)\n }\n\n if (e.ctrlKey || e.metaKey) {\n cmd = this.findCommandKey(\"alt-cmd\", e.which)\n if (cmd) {\n return cmd.cmd\n }\n return getDefaultKeyBinding(e)\n }\n } else if (e.ctrlKey || e.metaKey) {\n cmd = this.findCommandKey(\"cmd\", e.which)\n if (cmd) {\n return cmd.cmd\n }\n return getDefaultKeyBinding(e)\n }\n\n return getDefaultKeyBinding(e)\n }\n\n // will update block state todo: movo to utils\n updateBlockData(block, options) {\n const data = block.getData()\n const newData = data.merge(options)\n const newState = updateDataOfBlock(this.state.editorState, block, newData)\n // this fixes enter from image caption\n return this.forceRender(newState)\n }\n\n setDirection(direction_type) {\n const contentState = this.state.editorState.getCurrentContent()\n const selectionState = this.state.editorState.getSelection()\n const block = contentState.getBlockForKey(selectionState.anchorKey)\n\n return this.updateBlockData(block, { direction: direction_type })\n }\n\n //# read only utils\n toggleEditable() {\n this.closePopOvers()\n return this.setState({ read_only: !this.state.read_only }, this.testEmitAndDecode)\n }\n\n disableEditable() {\n console.log(\"in !!\")\n this.closePopOvers()\n return this.setState({ read_only: true }, this.testEmitAndDecode)\n }\n\n enableEditable() {\n this.closePopOvers()\n console.log(\"out !!\")\n return this.setState({ read_only: false }, this.testEmitAndDecode)\n }\n\n closePopOvers() {\n return this.tooltips.map(o => {\n return this.refs[o.ref].hide()\n })\n }\n\n relocateTooltips() {\n if (this.state.read_only)\n return \n\n return this.tooltips.map(o => {\n return this.refs[o.ref].relocate()\n })\n }\n\n tooltipsWithProp(prop) {\n return this.tooltips.filter(o => {\n return o[prop]\n })\n }\n\n tooltipHasSelectionElement(tooltip, element) {\n return tooltip.selectionElements.includes(element)\n }\n\n //################################\n // TODO: this methods belongs to popovers/link\n //################################\n\n handleShowPopLinkOver(e) {\n return this.showPopLinkOver()\n }\n\n handleHidePopLinkOver(e) {\n return this.hidePopLinkOver()\n }\n\n showPopLinkOver(el) {\n // handles popover display\n // using anchor or from popover\n\n const parent_el = ReactDOM.findDOMNode(this)\n\n // set url first in order to calculate popover width\n let coords\n this.refs.anchor_popover.setState({ url: el ? el.href : this.refs.anchor_popover.state.url })\n\n if (el) {\n coords = this.refs.anchor_popover.relocate(el)\n }\n\n if (coords) {\n this.refs.anchor_popover.setPosition(coords)\n }\n\n this.refs.anchor_popover.setState({ show: true })\n\n this.isHover = true\n return this.cancelHide()\n }\n\n hidePopLinkOver() {\n return this.hideTimeout = setTimeout(() => {\n return this.refs.anchor_popover.hide()\n }, 300)\n }\n\n cancelHide() {\n // console.log \"Cancel Hide\"\n return clearTimeout(this.hideTimeout)\n }\n\n //##############################\n\n render() {\n return (\n <div id=\"content\" suppressContentEditableWarning={ true }>\n <article className=\"postArticle\">\n <div className=\"postContent\">\n <div className=\"notesSource\">\n <div id=\"editor\" className=\"postField postField--body\">\n <section className=\"section--first section--last\">\n <div className=\"section-divider layoutSingleColumn\">\n <hr className=\"section-divider\" />\n </div>\n <div className=\"section-content container\">\n <div ref=\"richEditor\" \n className=\"section-inner layoutSingleColumn\"\n onClick={ this.focus }>\n <Editor\n blockRendererFn={ this.blockRenderer }\n editorState={ this.state.editorState }\n onChange={ this.onChange }\n handleDrop={this.handleDrop}\n onUpArrow={ this.handleUpArrow }\n onDownArrow={ this.handleDownArrow }\n handleReturn={ this.handleReturn }\n blockRenderMap={ this.state.blockRenderMap }\n blockStyleFn={ this.blockStyleFn }\n customStyleFn={this.customStyleFn }\n handlePastedText={ this.handlePasteText }\n handlePastedFiles={ this.handlePasteImage }\n handleDroppedFiles={ this.handleDroppedFiles }\n handleKeyCommand={ this.handleKeyCommand }\n keyBindingFn={ this.KeyBindingFn }\n handleBeforeInput={ this.handleBeforeInput }\n readOnly={ this.state.read_only }\n placeholder={ this.props.config.body_placeholder }\n ref=\"editor\"\n />\n </div>\n </div>\n </section>\n </div>\n </div>\n </div>\n </article>\n {\n this.tooltips.map( (o, i) => {\n return (\n <o.component\n ref={ o.ref }\n key={ i }\n editor={ this }\n editorState={ this.state.editorState }\n onChange={ this.onChange }\n styles={this.styles}\n configTooltip={ o }\n widget_options={ o.widget_options }\n showPopLinkOver={ this.showPopLinkOver }\n hidePopLinkOver={ this.hidePopLinkOver }\n handleOnMouseOver={ this.handleShowPopLinkOver }\n handleOnMouseOut={ this.handleHidePopLinkOver }\n />\n )\n })\n }\n {\n this.state.debug\n ? <Debug locks={ this.state.locks } editor={ this } />\n : undefined\n }\n\n </div>\n\n )\n }\n}\n\nexport default DanteEditor\n\n\n\n// WEBPACK FOOTER //\n// src/components/core/editor.js","module.exports = __webpack_public_path__ + \"fonts/dante.eot\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.eot\n// module id = 187\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.eot\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.eot\n// module id = 188\n// module chunks = 0","\nimport {DanteEditor, Dante} from './components/init.js'\n\nwindow.Dante = Dante\nwindow.DanteEditor = DanteEditor\n\nexport {\n Dante, \n DanteEditor\n}\n\n\n// WEBPACK FOOTER //\n// src/index.js","// removed by extract-text-webpack-plugin\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/dante.scss\n// module id = 195\n// module chunks = 0","import 'styles/dante'\nimport { Dante, DanteEditor } from '../src/index'\n/*\nmodule.exports = {\n Dante, \n DanteEditor\n}*/\n\n\n// WEBPACK FOOTER //\n// demo/initialize.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorBlock } from 'draft-js'\n\nimport axios from \"axios\"\n\nimport { updateDataOfBlock } from '../../model/index.js'\n\nexport default class EmbedBlock extends React.Component {\n constructor(props) {\n super(props)\n //api_key = \"86c28a410a104c8bb58848733c82f840\"\n\n this.updateData = this.updateData.bind(this)\n this.dataForUpdate = this.dataForUpdate.bind(this)\n this.componentDidMount = this.componentDidMount.bind(this)\n this.state = {\n embed_data: this.defaultData(),\n error: \"\"\n }\n }\n\n defaultData() {\n const existing_data = this.props.block.getData().toJS()\n return existing_data.embed_data || {}\n }\n\n // will update block state\n updateData() {\n const { block, blockProps } = this.props\n const { getEditorState, setEditorState } = this.props.blockProps\n const data = block.getData()\n const newData = data.merge(this.state)\n return setEditorState(updateDataOfBlock(getEditorState(), block, newData))\n }\n\n dataForUpdate() {\n\n return this.props.blockProps.data.toJS()\n }\n\n componentDidMount() {\n\n if (!this.props.blockProps.data) {\n return\n }\n\n // ensure data isnt already loaded\n // unless @dataForUpdate().endpoint or @dataForUpdate().provisory_text\n\n if (!this.dataForUpdate().endpoint && !this.dataForUpdate().provisory_text) {\n //debugger\n return\n }\n\n return axios({\n method: 'get',\n url: `${ this.dataForUpdate().endpoint }${ this.dataForUpdate().provisory_text }&scheme=https`\n }).then(result => {\n\n return this.setState({ embed_data: result.data } //JSON.parse(data.responseText)\n , this.updateData)\n }).catch(error => {\n\n this.setState({\n error: error.response.data.error_message })\n return console.log(\"TODO: error\")\n })\n }\n\n classForImage() {\n if (this.state.embed_data.images) {\n return \"\"\n } else {\n return \"mixtapeImage--empty u-ignoreBlock\"\n }\n }\n //if @state.embed_data.thumbnail_url then \"\" else \"mixtapeImage--empty u-ignoreBlock\"\n\n picture() {\n if (this.state.embed_data.images && this.state.embed_data.images.length > 0) {\n return this.state.embed_data.images[0].url\n } else {\n return \"\"\n }\n }\n\n render() {\n //block = @.props\n //foo = @.props.blockProps\n //data = Entity.get(block.block.getEntityAt(0)).getData()\n console.log(\"ERROR\", this.state.error)\n return (\n <span>\n { this.picture()\n ? <a\n target='_blank'\n className={ `js-mixtapeImage mixtapeImage ${ this.classForImage() }` }\n href={ this.state.embed_data.url }\n style={ { backgroundImage: `url('${ this.picture() }')` } }\n />\n : undefined\n }\n { this.state.error ? \n <h2>{ this.state.error }</h2>\n : undefined\n }\n <a\n className='markup--anchor markup--mixtapeEmbed-anchor'\n target='_blank'\n href={ this.state.embed_data.url }\n >\n <strong className='markup--strong markup--mixtapeEmbed-strong'>\n { this.state.embed_data.title }\n </strong>\n <em className='markup--em markup--mixtapeEmbed-em'>\n { this.state.embed_data.description }\n </em>\n </a>{ this.state.embed_data.provider_url }\n </span>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/embed.js","import React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport {\n Entity, \n RichUtils, \n AtomicBlockUtils, \n EditorBlock, \n EditorState } from 'draft-js'\n\nimport axios from \"axios\"\n\nimport { updateDataOfBlock } from '../../model/index.js'\n\nexport default class ImageBlock extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.blockPropsSrc = this.blockPropsSrc.bind(this)\n this.defaultUrl = this.defaultUrl.bind(this)\n this.defaultAspectRatio = this.defaultAspectRatio.bind(this)\n this.updateData = this.updateData.bind(this)\n this.replaceImg = this.replaceImg.bind(this)\n this.startLoader = this.startLoader.bind(this)\n this.stopLoader = this.stopLoader.bind(this)\n this.handleUpload = this.handleUpload.bind(this)\n this.aspectRatio = this.aspectRatio.bind(this)\n this.updateDataSelection = this.updateDataSelection.bind(this)\n this.handleGrafFigureSelectImg = this.handleGrafFigureSelectImg.bind(this)\n this.getUploadUrl = this.getUploadUrl.bind(this)\n this.uploadFile = this.uploadFile.bind(this)\n this.uploadFailed = this.uploadFailed.bind(this)\n this.uploadCompleted = this.uploadCompleted.bind(this)\n this.updateProgressBar = this.updateProgressBar.bind(this)\n this.placeHolderEnabled = this.placeHolderEnabled.bind(this)\n this.placeholderText = this.placeholderText.bind(this)\n this.handleFocus = this.handleFocus.bind(this)\n this.render = this.render.bind(this)\n let existing_data = this.props.block.getData().toJS()\n\n this.config = this.props.blockProps.config\n this.file = this.props.blockProps.data.get('file')\n this.state = {\n loading: false,\n selected: false,\n loading_progress: 0,\n caption: this.defaultPlaceholder(),\n direction: existing_data.direction || \"center\",\n width: 0,\n height: 0,\n file: null,\n url: this.blockPropsSrc() || this.defaultUrl(existing_data),\n aspect_ratio: this.defaultAspectRatio(existing_data)\n }\n }\n\n blockPropsSrc() {\n // console.log @.props.blockProps.data.src\n return this.props.blockProps.data.src\n }\n /*\n debugger\n block = @.props\n entity = block.block.getEntityAt(0)\n if entity\n data = Entity.get(entity).getData().src\n else\n null\n */\n\n defaultUrl(data) {\n if (data.url) {\n return data.url\n }\n\n if (data.url) {\n if (data.file) {\n return URL.createObjectURL(data.file)\n } else {\n return data.url\n }\n } else {\n return this.props.blockProps.data.src\n }\n }\n\n defaultPlaceholder() {\n return this.props.blockProps.config.image_caption_placeholder\n }\n\n defaultAspectRatio(data) {\n if (data.aspect_ratio) {\n return {\n width: data.aspect_ratio['width'],\n height: data.aspect_ratio['height'],\n ratio: data.aspect_ratio['ratio']\n }\n } else {\n return {\n width: 0,\n height: 0,\n ratio: 100\n }\n }\n }\n\n getAspectRatio(w, h) {\n let maxWidth = 1000\n let maxHeight = 1000\n let ratio = 0\n let width = w // Current image width\n let height = h // Current image height\n\n // Check if the current width is larger than the max\n if (width > maxWidth) {\n ratio = maxWidth / width // get ratio for scaling image\n height = height * ratio // Reset height to match scaled image\n width = width * ratio // Reset width to match scaled image\n\n // Check if current height is larger than max\n } else if (height > maxHeight) {\n ratio = maxHeight / height // get ratio for scaling image\n width = width * ratio // Reset width to match scaled image\n height = height * ratio // Reset height to match scaled image\n }\n\n let fill_ratio = height / width * 100\n let result = { width, height, ratio: fill_ratio }\n // console.log result\n return result\n }\n\n // will update block state\n updateData() {\n let { blockProps } = this.props\n let { block } = this.props\n let { getEditorState } = this.props.blockProps\n let { setEditorState } = this.props.blockProps\n let data = block.getData()\n let newData = data.merge(this.state).merge({ forceUpload: false })\n return setEditorState(updateDataOfBlock(getEditorState(), block, newData))\n }\n\n replaceImg() {\n this.img = new Image()\n this.img.src = this.refs.image_tag.src\n this.setState({\n url: this.img.src })\n let self = this\n // exit only when not blob and not forceUload\n if (!this.img.src.includes(\"blob:\") && !this.props.block.data.get(\"forceUpload\")) {\n return\n }\n return this.img.onload = () => {\n this.setState({\n width: this.img.width,\n height: this.img.height,\n aspect_ratio: self.getAspectRatio(this.img.width, this.img.height)\n })\n\n return this.handleUpload()\n }\n }\n\n startLoader() {\n return this.setState({\n loading: true })\n }\n\n stopLoader() {\n return this.setState({\n loading: false })\n }\n\n handleUpload() {\n this.startLoader()\n this.props.blockProps.addLock()\n this.updateData()\n return this.uploadFile()\n }\n\n componentDidMount() {\n return this.replaceImg()\n }\n\n aspectRatio() {\n return {\n maxWidth: `${ this.state.aspect_ratio.width }`,\n maxHeight: `${ this.state.aspect_ratio.height }`,\n ratio: `${ this.state.aspect_ratio.height }`\n }\n }\n\n updateDataSelection() {\n const { getEditorState, setEditorState } = this.props.blockProps\n const newselection = getEditorState().getSelection().merge({\n anchorKey: this.props.block.getKey(),\n focusKey: this.props.block.getKey()\n })\n\n return setEditorState(EditorState.forceSelection(getEditorState(), newselection))\n }\n\n handleGrafFigureSelectImg(e) {\n e.preventDefault()\n return this.setState({ selected: true }, this.updateDataSelection)\n }\n\n //main_editor.onChange(main_editor.state.editorState)\n\n coords() {\n return {\n maxWidth: `${ this.state.aspect_ratio.width }px`,\n maxHeight: `${ this.state.aspect_ratio.height }px`\n }\n }\n\n getBase64Image(img) {\n let canvas = document.createElement(\"canvas\")\n canvas.width = img.width\n canvas.height = img.height\n let ctx = canvas.getContext(\"2d\")\n ctx.drawImage(img, 0, 0)\n let dataURL = canvas.toDataURL(\"image/png\")\n\n return dataURL\n }\n\n formatData() {\n let formData = new FormData()\n if (this.file) {\n let formName = this.config.upload_formName || 'file'\n\n formData.append(formName, this.file)\n return formData\n } else {\n formData.append('url', this.props.blockProps.data.get(\"url\"))\n return formData\n }\n }\n\n getUploadUrl() {\n let url = this.config.upload_url\n if (typeof url === \"function\") {\n return url()\n } else {\n return url\n }\n }\n\n getUploadHeaders() {\n return this.config.upload_headers || {}\n }\n\n uploadFile() {\n\n let handleUp\n // custom upload handler\n if (this.config.upload_handler) {\n return this.config.upload_handler(this.formatData().get('file'), this)\n }\n \n if (!this.config.upload_url){\n this.stopLoader()\n return\n }\n \n axios({\n method: 'post',\n url: this.getUploadUrl(),\n headers: this.getUploadHeaders(),\n data: this.formatData(),\n onUploadProgress: e => {\n return this.updateProgressBar(e)\n }\n }).then(result => {\n this.uploadCompleted(result.data.url)\n\n if (this.config.upload_callback) {\n return this.config.upload_callback(result, this)\n }\n }).catch(error => {\n this.uploadFailed()\n\n console.log(`ERROR: got error uploading file ${ error }`)\n if (this.config.upload_error_callback) {\n return this.config.upload_error_callback(error, this)\n }\n })\n\n return handleUp = json_response => {\n return this.uploadCompleted(json_response.url, n)\n }\n }\n\n uploadFailed() {\n this.props.blockProps.removeLock()\n this.stopLoader()\n }\n\n uploadCompleted(url) {\n this.setState({ url }, this.updateData)\n this.props.blockProps.removeLock()\n this.stopLoader()\n this.file = null\n }\n\n updateProgressBar(e) {\n let complete = this.state.loading_progress\n if (e.lengthComputable) {\n complete = e.loaded / e.total * 100\n complete = complete != null ? complete : { complete: 0 }\n this.setState({\n loading_progress: complete })\n return console.log(`complete: ${ complete }`)\n }\n }\n\n placeHolderEnabled() {\n return this.state.enabled || this.props.block.getText()\n }\n\n placeholderText() {\n return this.config.image_caption_placeholder\n }\n\n handleFocus(e) {\n\n }\n\n render() {\n\n return (\n <div ref=\"image_tag2\" suppressContentEditableWarning={true}>\n <div className=\"aspectRatioPlaceholder is-locked\" \n style={this.coords()} \n onClick={this.handleGrafFigureSelectImg}>\n <div style={{ paddingBottom: `${ this.state.aspect_ratio.ratio }%` }} \n className='aspect-ratio-fill' />\n <img src={this.state.url} \n ref=\"image_tag\" \n height={this.state.aspect_ratio.height} \n width={this.state.aspect_ratio.width} \n className='graf-image'\n contentEditable={false}\n />\n <Loader toggle={this.state.loading} \n progress={this.state.loading_progress} />\n </div>\n <figcaption className='imageCaption' onMouseDown={this.handleFocus}>\n { this.props.block.getText().length === 0 ? \n <span className=\"danteDefaultPlaceholder\">\n {this.placeholderText()}\n </span> : undefined}\n <EditorBlock {...Object.assign({}, this.props, { \n \"editable\": true, \"className\": \"imageCaption\" })\n } />\n </figcaption>\n </div>\n )\n }\n}\n\nclass Loader extends React.Component {\n\n render() {\n return (\n <div>\n { this.props.toggle\n ? <div className=\"image-upoader-loader\">\n <p>\n { this.props.progress === 100\n ? \"processing image...\"\n : <span>\n <span>loading</span> { Math.round( this.props.progress ) }\n </span>\n }\n </p>\n </div>\n : undefined\n }\n </div>\n )\n }\n}\n\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/image.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorBlock } from 'draft-js'\n\nexport default class PlaceholderBlock extends React.Component {\n constructor(props) {\n super(props)\n this.placeholderText = this.placeholderText.bind(this)\n this.placeholderFromProps = this.placeholderFromProps.bind(this)\n this.defaultText = this.defaultText.bind(this)\n this.placeholderRender = this.placeholderRender.bind(this)\n this.state = {\n enabled: false,\n data: this.props.blockProps.data.toJS()\n }\n }\n\n placeholderText() {\n //if (this.state.enabled) {\n // return \"\"\n //}\n return this.props.blockProps.data.toJS().placeholder || this.placeholderFromProps() || this.defaultText()\n }\n //if @.props.blockProps.data then @.props.blockProps.data.placeholder else @defaultText()\n\n\n placeholderFromProps() {\n return this.props.block.toJS().placeholder\n }\n\n defaultText() {\n return \"write something \"\n }\n\n placeholderRender(){\n if (this.props.block.text.length === 0 ) {\n return (\n <div className=\"public-DraftEditorPlaceholder-root\">\n <div className=\"public-DraftEditorPlaceholder-inner\">\n {this.placeholderText() }\n </div>\n </div>\n )\n\n }\n }\n\n render() {\n return (\n <span onMouseDown={this.handleFocus}>\n \n {this.placeholderRender()}\n \n <EditorBlock {...Object.assign({}, this.props, {\n \"className\": \"imageCaption\",\n \"placeholder\": \"escrive alalal\"\n })} />\n </span>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/placeholder.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorBlock } from 'draft-js'\n\nimport { updateDataOfBlock } from '../../model/index.js'\n\nimport axios from \"axios\"\n\nexport default class VideoBlock extends React.Component {\n constructor(props) {\n super(props)\n //api_key = \"86c28a410a104c8bb58848733c82f840\"\n\n this.updateData = this.updateData.bind(this)\n this.dataForUpdate = this.dataForUpdate.bind(this)\n this.state = { embed_data: this.defaultData() }\n }\n\n defaultData() {\n let existing_data = this.props.block.getData().toJS()\n return existing_data.embed_data || {}\n }\n\n // will update block state\n updateData() {\n const { block, blockProps } = this.props\n const { getEditorState, setEditorState } = this.props.blockProps\n const data = block.getData()\n const newData = data.merge(this.state)\n return setEditorState(updateDataOfBlock(getEditorState(), block, newData))\n }\n\n dataForUpdate() {\n return this.props.blockProps.data.toJS()\n }\n\n componentDidMount() {\n\n if (!this.props.blockProps.data) {\n return\n }\n // ensure data isnt already loaded\n if (!this.dataForUpdate().endpoint && !this.dataForUpdate().provisory_text) {\n return\n }\n\n return axios({\n method: 'get',\n url: `${ this.dataForUpdate().endpoint }${ this.dataForUpdate().provisory_text }&scheme=https`\n }).then(result => {\n return this.setState({ embed_data: result.data } //JSON.parse(data.responseText)\n , this.updateData)\n }).catch(error => {\n return console.log(\"TODO: error\")\n })\n }\n\n classForImage() {\n if (this.state.embed_data.thumbnail_url) {\n return \"\"\n } else {\n return \"mixtapeImage--empty u-ignoreBlock\"\n }\n }\n\n render() {\n return (\n <figure className='graf--figure graf--iframe graf--first' tabIndex='0'>\n <div className='iframeContainer' \n dangerouslySetInnerHTML={ { __html: this.state.embed_data.html } } />\n <figcaption className='imageCaption'>\n <EditorBlock {...Object.assign({}, this.props, { \"className\": \"imageCaption\" })} />\n </figcaption>\n </figure>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/blocks/video.js","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport { Map, fromJS } from 'immutable'\nimport DanteEditor from './editor.js'\nimport DanteImagePopover from '../popovers/image'\nimport DanteAnchorPopover from '../popovers/link'\nimport DanteInlineTooltip from '../popovers/addButton'\nimport DanteTooltip from '../popovers/toolTip'\n\nimport ImageBlock from '../blocks/image'\nimport EmbedBlock from '../blocks/embed'\nimport VideoBlock from '../blocks/video'\nimport PlaceholderBlock from '../blocks/placeholder'\n\nimport { \n resetBlockWithType, \n addNewBlockAt \n} from '../../model/index.js'\n\nclass Dante {\n constructor(options) {\n if (options == null) {\n options = {}\n }\n console.log(\"init editor Dante!\")\n\n // deep merge on config\n let config = Map(fromJS(this.defaultOptions(options)))\n\n this.options = config.mergeDeep(options).toJS()\n console.log(this.options)\n }\n\n defaultOptions(options) {\n // default options\n if (options == null) {\n options = {}\n }\n let defaultOptions = {}\n defaultOptions.el = 'app'\n defaultOptions.content = \"\"\n defaultOptions.read_only = false\n defaultOptions.spellcheck = false\n defaultOptions.title_placeholder = \"Title\"\n defaultOptions.body_placeholder = \"Write your story\"\n\n defaultOptions.widgets = [{\n title: 'add an image',\n icon: 'image',\n type: 'image',\n block: ImageBlock,\n editable: true,\n renderable: true,\n breakOnContinuous: true,\n wrapper_class: \"graf graf--figure\",\n selected_class: \"is-selected is-mediaFocused\",\n selectedFn: block => {\n const { direction } = block.getData().toJS()\n switch (direction) {\n case \"left\":\n return \"graf--layoutOutsetLeft\"\n case \"center\":\n return \"\"\n case \"wide\":\n return \"sectionLayout--fullWidth\"\n case \"fill\":\n return \"graf--layoutFillWidth\"\n }\n },\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n widget_options: {\n displayOnInlineTooltip: true,\n insertion: \"upload\",\n insert_block: \"image\"\n },\n options: {\n upload_url: options.upload_url,\n upload_headers: options.upload_headers,\n upload_formName: options.upload_formName,\n upload_handler: options.image_upload_handler,\n upload_callback: options.image_upload_callback,\n image_delete_callback: options.image_delete_callback,\n image_caption_placeholder: options.image_caption_placeholder || \"Write caption for image (optional)\"\n }\n }, {\n icon: 'embed',\n title: 'insert embed',\n type: 'embed',\n block: EmbedBlock,\n editable: true,\n renderable: true,\n breakOnContinuous: true,\n wrapper_class: \"graf graf--mixtapeEmbed\",\n selected_class: \"is-selected is-mediaFocused\",\n widget_options: {\n displayOnInlineTooltip: true,\n insertion: \"placeholder\",\n insert_block: \"embed\"\n },\n options: {\n endpoint: `//api.embed.ly/1/extract?key=${ options.api_key }&url=`,\n placeholder: 'Paste a link to embed content from another site (e.g. Twitter) and press Enter'\n },\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n }\n }, {\n icon: 'video',\n title: 'insert video',\n editable: true,\n type: 'video',\n block: VideoBlock,\n renderable: true,\n breakOnContinuous: true,\n wrapper_class: \"graf--figure graf--iframe\",\n selected_class: \" is-selected is-mediaFocused\",\n widget_options: {\n displayOnInlineTooltip: true,\n insertion: \"placeholder\",\n insert_block: \"video\"\n },\n options: {\n endpoint: `//api.embed.ly/1/oembed?key=${ options.api_key }&url=`,\n placeholder: 'Paste a YouTube, Vine, Vimeo, or other video link, and press Enter',\n caption: 'Type caption for embed (optional)'\n },\n\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n }\n }, {\n renderable: true,\n editable: true,\n block: PlaceholderBlock,\n type: 'placeholder',\n wrapper_class: \"is-embedable\",\n selected_class: \" is-selected is-mediaFocused\",\n widget_options: {\n displayOnInlineTooltip: false\n },\n handleEnterWithText(ctx, block) {\n const { editorState } = ctx.state\n const data = {\n provisory_text: block.getText(),\n endpoint: block.getData().get('endpoint'),\n type: block.getData().get('type')\n }\n if(block.getText().length > 0){\n return ctx.onChange(resetBlockWithType(editorState, data.type, data))\n }else{\n return ctx.onChange(resetBlockWithType(editorState, \"unstyled\", {}))\n }\n },\n\n handleEnterWithoutText(ctx, block) {\n const { editorState } = ctx.state\n return ctx.onChange(resetBlockWithType(editorState, data.type, data))\n\n //return ctx.onChange(resetBlockWithType(editorState, \"unstyled\", {}))\n //return ctx.onChange(addNewBlockAt(editorState, block.getKey()))\n },\n\n }]\n\n defaultOptions.tooltips = [{\n ref: 'insert_tooltip',\n component: DanteTooltip,\n displayOnSelection: true,\n selectionElements: [\"unstyled\", \n \"blockquote\", \n \"ordered-list\", \n \"unordered-list\", \n \"unordered-list-item\", \n \"ordered-list-item\", \n \"code-block\", \n 'header-one', \n 'header-two', \n 'header-three', \n 'header-four'],\n widget_options: {\n placeholder: \"Paste or type a link\",\n block_types: [\n // {label: 'p', style: 'unstyled'},\n { label: 'h2', style: 'header-one', type: \"block\" }, \n { label: 'h3', style: 'header-two', type: \"block\" }, \n { label: 'h4', style: 'header-three', type: \"block\" }, \n { label: 'blockquote', style: 'blockquote', type: \"block\" },\n { label: 'insertunorderedlist', style: 'unordered-list-item', type: \"block\" }, \n { label: 'insertorderedlist', style: 'ordered-list-item', type: \"block\" }, \n { label: 'code', style: 'code-block', type: \"block\" }, \n { label: 'bold', style: 'BOLD', type: \"inline\" }, \n { label: 'italic', style: 'ITALIC', type: \"inline\" }\n ]\n }\n }, {\n ref: 'add_tooltip',\n component: DanteInlineTooltip\n }, {\n ref: 'anchor_popover',\n component: DanteAnchorPopover\n }, {\n ref: 'image_popover',\n component: DanteImagePopover\n }]\n\n defaultOptions.xhr = {\n before_handler: null,\n success_handler: null,\n error_handler: null\n }\n\n defaultOptions.data_storage = {\n url: null,\n method: \"POST\",\n success_handler: null,\n failure_handler: null,\n interval: 1500,\n withCredentials: false,\n crossDomain: false,\n headers: {},\n }\n\n defaultOptions.default_wrappers = [\n { className: 'graf--p', block: 'unstyled' }, \n { className: 'graf--h2', block: 'header-one' },\n { className: 'graf--h3', block: 'header-two' }, \n { className: 'graf--h4', block: 'header-three' }, \n { className: 'graf--blockquote', block: 'blockquote' }, \n { className: 'graf--insertunorderedlist', block: 'unordered-list-item' }, \n { className: 'graf--insertorderedlist', block: 'ordered-list-item' }, \n { className: 'graf--code', block: 'code-block' }, \n { className: 'graf--bold', block: 'BOLD' }, \n { className: 'graf--italic', block: 'ITALIC' }]\n\n defaultOptions.continuousBlocks = [\n \"unstyled\", \n \"blockquote\", \n \"ordered-list\", \n \"unordered-list\", \n \"unordered-list-item\", \n \"ordered-list-item\", \n \"code-block\"\n ]\n\n defaultOptions.key_commands = {\n \"alt-shift\": [{ key: 65, cmd: 'add-new-block' }],\n \"alt-cmd\": [{ key: 49, cmd: 'toggle_block:header-one' }, \n { key: 50, cmd: 'toggle_block:header-two' }, \n { key: 53, cmd: 'toggle_block:blockquote' }],\n \"cmd\": [{ key: 66, cmd: 'toggle_inline:BOLD' }, \n { key: 73, cmd: 'toggle_inline:ITALIC' }, \n { key: 75, cmd: 'insert:link' }]\n }\n\n defaultOptions.character_convert_mapping = {\n '> ': \"blockquote\",\n '*.': \"unordered-list-item\",\n '* ': \"unordered-list-item\",\n '- ': \"unordered-list-item\",\n '1.': \"ordered-list-item\",\n '# ': 'header-one',\n '##': 'header-two',\n '==': \"unstyled\",\n '` ': \"code-block\"\n }\n\n return defaultOptions\n }\n\n getContent() {\n return this.options.content\n }\n\n render() {\n return this.editor = ReactDOM.render(\n <DanteEditor content={this.getContent()} config={this.options} />,\n document.getElementById(this.options.el)\n )\n }\n}\n\nexport default Dante\n\n\n// WEBPACK FOOTER //\n// src/components/core/dante.js","import React from 'react'\n\nclass Debug extends React.Component {\n\n constructor() {\n super()\n\n this.handleToggleReadOnly = this.handleToggleReadOnly.bind(this)\n this.handleTestEmitAndDecode = this.handleTestEmitAndDecode.bind(this)\n this.handleTestEmitTEXT = this.handleTestEmitTEXT.bind(this)\n this.testEmitAndDecode = this.testEmitAndDecode.bind(this)\n this.testEmitTEXT = this.testEmitTEXT.bind(this)\n this.logState = this.logState.bind(this)\n this.toggleDisplay = this.toggleDisplay.bind(this)\n this.open = this.open.bind(this)\n this.render = this.render.bind(this)\n this.state = {\n output: \"\",\n display: \"none\"\n }\n }\n\n handleToggleReadOnly(e) {\n e.preventDefault()\n this.props.editor.toggleEditable()\n return false\n }\n\n handleTestEmitAndDecode(e) {\n e.preventDefault()\n return this.testEmitAndDecode()\n }\n\n handleTestEmitTEXT(e) {\n e.preventDefault()\n return this.testEmitTEXT()\n }\n\n testEmitAndDecode(e) {\n const raw_as_json = this.props.editor.emitSerializedOutput()\n this.props.editor.setState({ \n editorState: this.props.editor.decodeEditorContent(raw_as_json) }, \n this.logState(JSON.stringify(raw_as_json)))\n return false\n }\n\n testEmitTEXT() {\n const text = this.props.editor.getTextFromEditor()\n return this.logState(text)\n }\n\n logState(raw) {\n return this.setState({ output: raw }, this.open)\n }\n\n toggleDisplay(e) {\n e.preventDefault()\n const d = this.state.display === \"block\" ? \"none\" : this.state.display\n return this.setState({\n display: d })\n }\n\n open() {\n return this.setState({\n display: \"block\" })\n }\n\n render() {\n return (\n <div>\n <div className=\"debugControls\">\n <ul>\n <li> LOCKS: { this.props.editor.state.locks } </li>\n <li>\n <a href=\"#\" onClick={ this.handleToggleReadOnly }>\n EDITABLE: { this.props.editor.state.read_only ? 'NO' : 'YES' }\n </a>\n </li>\n <li>\n <a href=\"#\" onClick={ this.handleTestEmitTEXT }>EDITOR TEXT</a>\n </li>\n <li>\n <a href=\"#\" onClick={ this.handleTestEmitAndDecode }>EDITOR STATE</a>\n </li>\n </ul>\n </div>\n <div className=\"debugZone\" style={ { display: this.state.display } }>\n <a href=\"#\" className=\"dante-debug-close close\" onClick={ this.toggleDisplay } />\n <div className=\"debugOutput\">\n <h2>EDITOR OUTPUT</h2>\n {\n this.state.output.length > 0\n ? <pre>{ this.state.output }</pre>\n : undefined\n }\n </div>\n </div>\n </div>\n )\n }\n}\n\nexport default Debug\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/core/debug.js","import React from 'react'\nimport { Entity } from 'draft-js'\n\nexport default class Link extends React.Component {\n\n constructor(props) {\n super(props)\n this._validateLink = this._validateLink.bind(this)\n this._checkProtocol = this._checkProtocol.bind(this)\n this._showPopLinkOver = this._showPopLinkOver.bind(this)\n this._hidePopLinkOver = this._hidePopLinkOver.bind(this)\n this.isHover = false\n }\n\n _validateLink() {\n const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol\n '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name\n '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address\n '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path\n '(\\?[&a-z\\d%_.~+=-]*)?' + // query string\n '(\\#[-a-z\\d_]*)?$', 'i') // fragment locater\n if (!pattern.test(str)) {\n alert(\"Please enter a valid URL.\")\n return false\n } else {\n return true\n }\n }\n\n _checkProtocol() {\n return console.log(\"xcvd\")\n }\n\n _showPopLinkOver(e) {\n if (!this.data.showPopLinkOver) {\n return\n }\n return this.data.showPopLinkOver(this.refs.link)\n }\n\n _hidePopLinkOver(e) {\n if (!this.data.hidePopLinkOver) {\n return\n }\n return this.data.hidePopLinkOver()\n }\n\n render() {\n this.data = this.props.contentState.getEntity(this.props.entityKey).getData()\n //Entity.get(this.props.entityKey).getData()\n\n return (\n <a\n ref=\"link\"\n href={ this.data.url }\n className=\"markup--anchor\"\n onMouseOver={ this._showPopLinkOver }\n onMouseOut={ this._hidePopLinkOver }\n >\n { this.props.children }\n </a>\n )\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/decorators/link.js","\nimport Dante from './core/dante'\nimport DanteEditor from './core/editor'\n\nexport {\n Dante, \n DanteEditor\n}\n\n\n// WEBPACK FOOTER //\n// src/components/init.js","import React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { \n Entity, \n RichUtils, \n AtomicBlockUtils, \n EditorState \n } from 'draft-js'\n\nimport { \n addNewBlock, \n resetBlockWithType, \n updateDataOfBlock, \n getCurrentBlock, \n getNode } from '../../model/index.js'\n\nimport { getSelectionRect, getSelection, getRelativeParent } from \"../../utils/selection.js\"\n\nclass DanteInlineTooltip extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this._toggleScaled = this._toggleScaled.bind(this)\n this.scale = this.scale.bind(this)\n this.collapse = this.collapse.bind(this)\n this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this)\n this.clickOnFileUpload = this.clickOnFileUpload.bind(this)\n this.handlePlaceholder = this.handlePlaceholder.bind(this)\n this.insertImage = this.insertImage.bind(this)\n this.handleFileInput = this.handleFileInput.bind(this)\n this.widgets = this.widgets.bind(this)\n this.clickHandler = this.clickHandler.bind(this)\n this.relocate = this.relocate.bind(this)\n this.state = {\n position: { top: 0, left: 0 },\n show: false,\n scaled: false\n }\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n show: false })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n _toggleScaled(ev) {\n if (this.state.scaled) {\n return this.collapse()\n } else {\n return this.scale()\n }\n }\n\n scale() {\n return this.setState({\n scaled: true })\n }\n\n collapse() {\n return this.setState({\n scaled: false })\n }\n\n componentWillReceiveProps(newProps) {\n return this.collapse()\n }\n\n activeClass() {\n //if @props.show then \"is-active\" else \"\"\n if (this.isActive()) {\n return \"is-active\"\n } else {\n return \"\"\n }\n }\n\n isActive() {\n return this.state.show\n }\n\n scaledClass() {\n if (this.state.scaled) {\n return \"is-scaled\"\n } else {\n return \"\"\n }\n }\n\n scaledWidth() {\n if (this.state.scaled) {\n return \"124\"\n } else {\n return \"0\"\n }\n }\n\n clickOnFileUpload() {\n this.refs.fileInput.click()\n this.collapse()\n return this.hide()\n }\n\n handlePlaceholder(input) {\n let opts = {\n type: input.widget_options.insert_block,\n placeholder: input.options.placeholder,\n endpoint: input.options.endpoint\n }\n\n return this.props.onChange(resetBlockWithType(this.props.editorState, 'placeholder', opts))\n }\n\n insertImage(file) {\n let opts = {\n url: URL.createObjectURL(file),\n file\n }\n\n return this.props.onChange(addNewBlock(this.props.editorState, 'image', opts))\n }\n\n handleFileInput(e) {\n let fileList = e.target.files\n // TODO: support multiple file uploads\n /*\n Object.keys(fileList).forEach (o)=>\n @.insertImage(fileList[0])\n */\n return this.insertImage(fileList[0])\n }\n\n handleInsertion(e){\n this.hide()\n return this.props.onChange(addNewBlock(this.props.editorState, e.type, {}))\n }\n\n widgets() {\n return this.props.editor.widgets\n }\n\n clickHandler(e, type) {\n let request_block = this.widgets().find(o => o.icon === type)\n\n switch (request_block.widget_options.insertion) {\n case \"upload\":\n return this.clickOnFileUpload(e, request_block)\n case \"placeholder\":\n return this.handlePlaceholder(request_block)\n case \"insertion\":\n return this.handleInsertion(request_block)\n default:\n return console.log(`WRONG TYPE FOR ${ request_block.widget_options.insertion }`)\n }\n }\n\n getItems() {\n return this.widgets().filter(o => {\n return o.widget_options.displayOnInlineTooltip\n })\n }\n\n isDescendant(parent, child) {\n let node = child.parentNode\n while (node !== null) {\n if (node === parent) {\n return true\n }\n node = node.parentNode\n }\n return false\n }\n\n relocate() {\n let { editorState } = this.props\n\n if (editorState.getSelection().isCollapsed()) {\n\n let currentBlock = getCurrentBlock(editorState)\n let blockType = currentBlock.getType()\n\n let contentState = editorState.getCurrentContent()\n let selectionState = editorState.getSelection()\n\n let block = contentState.getBlockForKey(selectionState.anchorKey)\n\n let nativeSelection = getSelection(window)\n if (!nativeSelection.rangeCount) {\n return\n }\n\n let node = getNode()\n\n let selectionBoundary = getSelectionRect(nativeSelection)\n let coords = selectionBoundary //utils.getSelectionDimensions(node)\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n if (!this.isDescendant(parent, nativeSelection.anchorNode)) {\n this.hide()\n return\n }\n\n // checkeamos si esta vacio\n this.display(block.getText().length === 0 && blockType === \"unstyled\")\n return this.setPosition({\n top: coords.top + window.scrollY,\n left: coords.left + window.scrollX - 60\n })\n\n } else {\n return this.hide()\n }\n }\n\n render() {\n return (\n <div\n className={ `inlineTooltip ${ this.activeClass() } ${ this.scaledClass() }` }\n style={ this.state.position }\n >\n <button\n className=\"inlineTooltip-button control\"\n title=\"Close Menu\"\n data-action=\"inline-menu\"\n onClick={ this._toggleScaled }\n >\n <span className=\"tooltip-icon dante-icon-plus\" />\n </button>\n <div\n className=\"inlineTooltip-menu\"\n style={ { width: `${ this.scaledWidth() }px` } }\n >\n { this.getItems().map( (item, i) => {\n return <InlineTooltipItem\n item={ item }\n key={ i }\n clickHandler={ this.clickHandler }\n />\n })\n }\n <input\n type=\"file\"\n style={ { display: 'none' } }\n ref=\"fileInput\"\n multiple=\"multiple\"\n onChange={ this.handleFileInput }\n />\n </div>\n </div>\n )\n }\n}\n\nclass InlineTooltipItem extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.clickHandler = this.clickHandler.bind(this)\n }\n\n clickHandler(e) {\n e.preventDefault()\n return this.props.clickHandler(e, this.props.item.icon)\n }\n\n render() {\n return (\n <button\n className=\"inlineTooltip-button scale\"\n title={ this.props.title }\n onMouseDown={ this.clickHandler }\n >\n <span className={ `tooltip-icon dante-icon-${ this.props.item.icon }` } />\n </button>\n )\n }\n}\n\nexport default DanteInlineTooltip\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/addButton.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { Entity, RichUtils, AtomicBlockUtils, EditorState } from 'draft-js'\n\nimport { getSelectionRect, getSelection, getRelativeParent } from \"../../utils/selection.js\"\n\nimport { getCurrentBlock, getNode } from '../../model/index.js'\n\nclass DanteImagePopover extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this._toggleScaled = this._toggleScaled.bind(this)\n this.scale = this.scale.bind(this)\n this.collapse = this.collapse.bind(this)\n this.relocate = this.relocate.bind(this)\n this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this)\n this.handleClick = this.handleClick.bind(this)\n this.state = {\n position: {\n top: 0,\n left: 0\n },\n show: false,\n scaled: false,\n buttons: [{ type: \"left\" },\n { type: \"center\"},\n { type: \"fill\" },\n { type: \"wide\" }]\n }\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n show: false })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n _toggleScaled(ev) {\n if (this.state.scaled) {\n return this.collapse()\n } else {\n return this.scale()\n }\n }\n\n scale() {\n return this.setState({\n scaled: true })\n }\n\n collapse() {\n return this.setState({\n scaled: false })\n }\n\n relocate() {\n let { editorState } = this.props\n\n if (editorState.getSelection().isCollapsed()) {\n\n let currentBlock = getCurrentBlock(editorState)\n let blockType = currentBlock.getType()\n\n let contentState = editorState.getCurrentContent()\n let selectionState = editorState.getSelection()\n\n let block = contentState.getBlockForKey(selectionState.anchorKey)\n\n let nativeSelection = getSelection(window)\n if (!nativeSelection.rangeCount) {\n return\n }\n\n let node = getNode()\n\n this.display(blockType === \"image\")\n\n if (blockType === \"image\") {\n let selectionBoundary = node.anchorNode.parentNode.parentNode\n .parentNode.getBoundingClientRect()\n \n let coords = selectionBoundary\n\n let el = this.refs.image_popover\n let padd = el.offsetWidth / 2\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n const toolbarHeight = el.offsetHeight;\n\n let left = selectionBoundary.left + selectionBoundary.width / 2 - padd\n \n let diff = window.pageYOffset + parent.getBoundingClientRect().top\n \n let top = selectionBoundary.top - parentBoundary.top + toolbarHeight //+ diff\n\n return this.setPosition({ top: top, left: left })\n\n }\n } else {\n return this.hide()\n }\n }\n\n componentWillReceiveProps(newProps) {\n return this.collapse()\n }\n\n getStyle() {\n if (!this.state.position) {\n return {}\n }\n }\n\n handleClick(item) {\n return this.props.editor.setDirection(item.type)\n }\n\n render() {\n return (\n <div\n ref=\"image_popover\"\n className={ `dante-popover popover--Aligntooltip popover--top popover--animated ${ this.state.show ? 'is-active' : undefined }` }\n style={\n { top: this.state.position.top,\n left: this.state.position.left }\n }\n >\n <div className='popover-inner'>\n <ul className='dante-menu-buttons'>\n { this.state.buttons.map( (item, i) => {\n return <DanteImagePopoverItem\n item={ item }\n handleClick={ this.handleClick }\n key={ i }\n />\n })\n }\n </ul>\n </div>\n <div className='popover-arrow' />\n </div>\n )\n }\n}\n\nclass DanteImagePopoverItem extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.handleClick = this.handleClick.bind(this)\n this.render = this.render.bind(this)\n }\n\n handleClick(e) {\n e.preventDefault()\n return this.props.handleClick(this.props.item)\n }\n\n render() {\n return <li\n className={`dante-menu-button align-${ this.props.item.type }`}\n onMouseDown={this.handleClick}>\n <span className={`tooltip-icon dante-icon dante-icon-image-${ this.props.item.type }`} />\n </li>\n }\n}\n\nexport default DanteImagePopover\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/image.js","\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { getCurrentBlock } from '../../model/index.js'\n\nimport { getRelativeParent } from \"../../utils/selection.js\"\n\nclass DanteAnchorPopover extends React.Component {\n\n constructor(props) {\n\n super(props)\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this.relocate = this.relocate.bind(this)\n this.render = this.render.bind(this)\n this.state = {\n position: {\n top: 0,\n left: 0\n },\n show: false,\n url: \"\"\n }\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n show: false })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n relocate(node) {\n if (node == null) {\n node = null\n }\n if (!node) {\n return\n }\n\n let { editorState } = this.props\n let currentBlock = getCurrentBlock(editorState)\n let blockType = currentBlock.getType()\n\n let contentState = editorState.getCurrentContent()\n let selectionState = editorState.getSelection()\n\n let selectionBoundary = node.getBoundingClientRect()\n let coords = selectionBoundary\n\n let el = this.refs.dante_popover\n let padd = el.offsetWidth / 2\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n const toolbarHeight = el.offsetHeight;\n const relativeRect = node.getBoundingClientRect();\n let left = selectionBoundary.left + selectionBoundary.width / 2 - padd\n \n let diff = window.pageYOffset + parent.getBoundingClientRect().top\n let top = relativeRect.top - parentBoundary.top + (toolbarHeight * 0.3) + diff\n\n return {\n top: top,\n left: left\n }\n }\n\n render() {\n let { position } = this.state\n let style = {\n left: position.left,\n top: position.top,\n visibility: `${ this.state.show ? 'visible' : 'hidden' }`\n }\n return (\n <div\n ref=\"dante_popover\"\n className='dante-popover popover--tooltip popover--Linktooltip popover--bottom is-active'\n style={ style }\n onMouseOver={ this.props.handleOnMouseOver }\n onMouseOut={ this.props.handleOnMouseOut }\n >\n <div className='popover-inner'>\n <a href={ this.state.url } target='_blank'>\n { this.state.url }\n </a>\n </div>\n <div className='popover-arrow' />\n </div>\n )\n }\n}\n\nexport default DanteAnchorPopover\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/link.js","import React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { \n convertToRaw, \n CompositeDecorator, \n getVisibleSelectionRect, \n getDefaultKeyBinding, \n getSelectionOffsetKeyForNode, \n KeyBindingUtil, \n ContentState, \n Editor, \n EditorState, \n Entity, \n RichUtils } from 'draft-js'\n\nimport { getSelectionRect, getSelection, getRelativeParent } from \"../../utils/selection.js\"\n\nimport { getCurrentBlock } from '../../model/index.js'\n\nclass DanteTooltip extends React.Component {\n\n constructor(props) {\n super(props)\n this._clickInlineHandler = this._clickInlineHandler.bind(this)\n this.display = this.display.bind(this)\n this.show = this.show.bind(this)\n this.hide = this.hide.bind(this)\n this.relocate = this.relocate.bind(this)\n this._clickBlockHandler = this._clickBlockHandler.bind(this)\n this.displayLinkMode = this.displayLinkMode.bind(this)\n this.displayActiveMenu = this.displayActiveMenu.bind(this)\n this._enableLinkMode = this._enableLinkMode.bind(this)\n this._disableLinkMode = this._disableLinkMode.bind(this)\n this.handleInputEnter = this.handleInputEnter.bind(this)\n this.confirmLink = this.confirmLink.bind(this)\n this.inlineItems = this.inlineItems.bind(this)\n this.blockItems = this.blockItems.bind(this)\n this.getDefaultValue = this.getDefaultValue.bind(this)\n this.getVisibleSelectionRect = getVisibleSelectionRect\n this.state = {\n link_mode: false,\n show: false,\n position: {}\n }\n }\n\n _clickInlineHandler(ev, style) {\n ev.preventDefault()\n\n this.props.onChange(RichUtils.toggleInlineStyle(this.props.editorState, style))\n\n return setTimeout(() => {\n return this.relocate()\n }, 0)\n }\n\n display(b) {\n if (b) {\n return this.show()\n } else {\n return this.hide()\n }\n }\n\n show() {\n return this.setState({\n show: true })\n }\n\n hide() {\n return this.setState({\n link_mode: false,\n show: false\n })\n }\n\n setPosition(coords) {\n return this.setState({\n position: coords })\n }\n\n isDescendant(parent, child) {\n let node = child.parentNode\n while (node !== null) {\n if (node === parent) {\n return true\n }\n node = node.parentNode\n }\n return false\n }\n\n relocate() {\n\n let currentBlock = getCurrentBlock(this.props.editorState)\n let blockType = currentBlock.getType()\n // display tooltip only for unstyled\n\n if (this.props.configTooltip.selectionElements.indexOf(blockType) < 0) {\n this.hide()\n return\n }\n\n if (this.state.link_mode) {\n return\n }\n if (!this.state.show) {\n return\n }\n\n let el = this.refs.dante_menu\n let padd = el.offsetWidth / 2\n\n let nativeSelection = getSelection(window)\n if (!nativeSelection.rangeCount) {\n return\n }\n\n let selectionBoundary = getSelectionRect(nativeSelection)\n\n let parent = ReactDOM.findDOMNode(this.props.editor)\n let parentBoundary = parent.getBoundingClientRect()\n\n // hide if selected node is not in editor\n if (!this.isDescendant(parent, nativeSelection.anchorNode)) {\n this.hide()\n return\n }\n\n //let top = selectionBoundary.top - parentBoundary.top - -90 - 5\n\n const relativeParent = getRelativeParent(this.refs.dante_menu.parentElement);\n const toolbarHeight = this.refs.dante_menu.clientHeight;\n const relativeRect = (relativeParent || document.body).getBoundingClientRect();\n const selectionRect = getVisibleSelectionRect(window);\n\n if(!selectionRect || !relativeRect || !selectionBoundary)\n return\n\n\n let diff = window.pageYOffset + parent.getBoundingClientRect().top\n let top = (selectionRect.top - relativeRect.top) - toolbarHeight + diff\n let left = selectionBoundary.left + selectionBoundary.width / 2 - padd\n\n //let left = (selectionRect.left - relativeRect.left) + (selectionRect.width / 2)\n\n if (!top || !left) {\n return\n }\n\n // console.log \"SET SHOW FOR TOOLTIP INSERT MENU\"\n return this.setState({\n show: true,\n position: {\n left,\n top\n }\n })\n }\n\n _clickBlockHandler(ev, style) {\n ev.preventDefault()\n\n this.props.onChange(RichUtils.toggleBlockType(this.props.editorState, style))\n\n return setTimeout(() => {\n return this.relocate()\n }, 0)\n }\n\n displayLinkMode() {\n if (this.state.link_mode) {\n return \"dante-menu--linkmode\"\n } else {\n return \"\"\n }\n }\n\n displayActiveMenu() {\n if (this.state.show) {\n return \"dante-menu--active\"\n } else {\n return \"\"\n }\n }\n\n _enableLinkMode(ev) {\n ev.preventDefault()\n return this.setState({\n link_mode: true })\n }\n\n _disableLinkMode(ev) {\n ev.preventDefault()\n return this.setState({\n link_mode: false,\n url: \"\"\n })\n }\n\n hideMenu() {\n return this.hide()\n }\n\n handleInputEnter(e) {\n if (e.which === 13) {\n return this.confirmLink(e)\n }\n }\n\n confirmLink(e) {\n e.preventDefault()\n let { editorState } = this.props\n let urlValue = e.currentTarget.value\n let contentState = editorState.getCurrentContent()\n let selection = editorState.getSelection()\n\n let opts = {\n url: urlValue,\n showPopLinkOver: this.props.showPopLinkOver,\n hidePopLinkOver: this.props.hidePopLinkOver\n }\n \n let entityKey = Entity.create('LINK', 'MUTABLE', opts)\n //contentState.createEntity('LINK', 'MUTABLE', opts)\n\n if (selection.isCollapsed()) {\n console.log(\"COLLAPSED SKIPPING LINK\")\n return\n }\n\n this.props.onChange(RichUtils.toggleLink(editorState, selection, entityKey))\n\n return this._disableLinkMode(e)\n }\n\n getPosition() {\n let pos = this.state.position\n return pos\n }\n\n inlineItems() {\n return this.props.widget_options.block_types.filter(o => {\n return o.type === \"inline\"\n })\n }\n\n blockItems() {\n return this.props.widget_options.block_types.filter(o => {\n return o.type === \"block\"\n })\n }\n\n getDefaultValue() {\n if (this.refs.dante_menu_input) {\n this.refs.dante_menu_input.value = \"\"\n }\n \n let currentBlock = getCurrentBlock(this.props.editorState)\n let blockType = currentBlock.getType()\n let selection = this.props.editor.state.editorState.getSelection()\n let contentState = this.props.editorState.getCurrentContent()\n let selectedEntity = null\n let defaultUrl = null\n return currentBlock.findEntityRanges(character => {\n let entityKey = character.getEntity()\n selectedEntity = entityKey\n return entityKey !== null && contentState.getEntity(entityKey).getType() === 'LINK'\n }, (start, end) => {\n let selStart = selection.getAnchorOffset()\n let selEnd = selection.getFocusOffset()\n if (selection.getIsBackward()) {\n selStart = selection.getFocusOffset()\n selEnd = selection.getAnchorOffset()\n }\n\n if (start === selStart && end === selEnd) {\n defaultUrl = contentState.getEntity(selectedEntity).getData().url\n return this.refs.dante_menu_input.value = defaultUrl\n }\n })\n }\n\n render() {\n return (\n <div\n id=\"dante-menu\"\n ref=\"dante_menu\"\n className={ `dante-menu ${ this.displayActiveMenu() } ${ this.displayLinkMode() }` }\n style={ this.getPosition() }\n >\n <div className=\"dante-menu-linkinput\">\n <input\n className=\"dante-menu-input\"\n ref=\"dante_menu_input\"\n placeholder={this.props.widget_options.placeholder}\n onKeyPress={ this.handleInputEnter }\n defaultValue={ this.getDefaultValue() }\n />\n <div className=\"dante-menu-button\" onMouseDown={ this._disableLinkMode } />\n </div>\n <ul className=\"dante-menu-buttons\">\n { this.blockItems().map( (item, i) => {\n return <DanteTooltipItem\n key={ i }\n item={ item }\n handleClick={ this._clickBlockHandler }\n editorState={ this.props.editorState }\n type=\"block\"\n currentStyle={ this.props.editorState.getCurrentInlineStyle }\n />\n })\n }\n\n <DanteTooltipLink\n editorState={ this.props.editorState }\n enableLinkMode={ this._enableLinkMode }\n />\n\n\n { this.inlineItems().map( (item, i) => {\n return <DanteTooltipItem\n key={ i }\n item={ item }\n type=\"inline\"\n editorState={ this.props.editorState }\n handleClick={ this._clickInlineHandler }\n />\n })\n }\n </ul>\n </div>\n )\n }\n}\n\nclass DanteTooltipItem extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.handleClick = this.handleClick.bind(this)\n this.activeClass = this.activeClass.bind(this)\n this.isActive = this.isActive.bind(this)\n this.activeClassInline = this.activeClassInline.bind(this)\n this.activeClassBlock = this.activeClassBlock.bind(this)\n this.render = this.render.bind(this)\n }\n\n handleClick(ev) {\n return this.props.handleClick(ev, this.props.item.style)\n }\n\n activeClass() {\n if (this.isActive()) {\n return \"active\"\n } else {\n return \"\"\n }\n }\n\n isActive() {\n if (this.props.type === \"block\") {\n return this.activeClassBlock()\n } else {\n return this.activeClassInline()\n }\n }\n\n activeClassInline() {\n if (!this.props.editorState) {\n return\n }\n //console.log @props.item\n return this.props.editorState.getCurrentInlineStyle().has(this.props.item.style)\n }\n\n activeClassBlock() {\n //console.log \"EDITOR STATE\", @props.editorState\n if (!this.props.editorState) {\n return\n }\n let selection = this.props.editorState.getSelection()\n let blockType = this.props.editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType()\n return this.props.item.style === blockType\n }\n\n render() {\n return (\n <li className={ `dante-menu-button ${ this.activeClass() }` } onMouseDown={ this.handleClick }>\n <i className={ `dante-icon dante-icon-${ this.props.item.label }` } data-action=\"bold\" />\n </li>\n )\n }\n}\n\nclass DanteTooltipLink extends React.Component {\n\n constructor(...args) {\n super(...args)\n this.promptForLink = this.promptForLink.bind(this)\n }\n\n promptForLink(ev) {\n let selection = this.props.editorState.getSelection()\n if (!selection.isCollapsed()) {\n return this.props.enableLinkMode(ev)\n }\n }\n\n render() {\n return (\n <li className=\"dante-menu-button\" onMouseDown={ this.promptForLink }>\n <i className=\"dante-icon icon-createlink\" data-action=\"createlink\">link</i>\n </li>\n )\n }\n}\n\n\n\n\n\n\nexport default DanteTooltip\n\n\n\n\n// WEBPACK FOOTER //\n// src/components/popovers/toolTip.js","import { Entity } from 'draft-js'\n\n//TODO: what the f*ck is happening here? ;-;\nconst findEntities = (entityType, instance, contentBlock, callback) => {\n return contentBlock.findEntityRanges((function(_this) {\n return function(character) {\n var entityKey, opts, res\n let contentState = instance.state.editorState.getCurrentContent()\n entityKey = character.getEntity()\n return (res = entityKey !== null && contentState.getEntity(entityKey).getType() === entityType, res ? (opts = {\n showPopLinkOver: instance.showPopLinkOver,\n hidePopLinkOver: instance.hidePopLinkOver\n }, contentState.mergeEntityData(entityKey, opts)) : void 0, res)\n }\n })(this), callback)\n}\n\nexport default findEntities\n\n\n// WEBPACK FOOTER //\n// src/utils/find_entities.js","import { ContentState, genKey, Entity, CharacterMetadata, ContentBlock, convertFromHTML, getSafeBodyFromHTML } from 'draft-js'\n\nimport { List, OrderedSet, Repeat, fromJS } from 'immutable'\n\n\n// { compose\n// } = require('underscore')\n\n// underscore compose function\nlet compose = function() {\n let args = arguments\n let start = args.length - 1\n return function() {\n let i = start\n let result = args[start].apply(this, arguments)\n while (i--) {\n result = args[i].call(this, result)\n }\n return result\n }\n}\n\n// from https://gist.github.com/N1kto/6702e1c2d89a33a15a032c234fc4c34e\n\n/*\n * Helpers\n */\n\n// Prepares img meta data object based on img attributes\nlet getBlockSpecForElement = imgElement=> {\n return {\n contentType: 'image',\n imgSrc: imgElement.getAttribute('src')\n }\n}\n\n// Wraps meta data in HTML element which is 'understandable' by Draft, I used <blockquote />.\nlet wrapBlockSpec = blockSpec=> {\n if (blockSpec === null) {\n return null\n }\n\n let tempEl = document.createElement('blockquote')\n // stringify meta data and insert it as text content of temp HTML element. We will later extract\n // and parse it.\n tempEl.innerText = JSON.stringify(blockSpec)\n return tempEl\n}\n\n// Replaces <img> element with our temp element\nlet replaceElement = (oldEl, newEl)=> {\n if (!(newEl instanceof HTMLElement)) {\n return\n }\n\n let upEl = getUpEl(oldEl)\n //parentNode = oldEl.parentNode\n //return parentNode.replaceChild(newEl, oldEl)\n return upEl.parentNode.insertBefore(newEl, upEl)\n}\n\nvar getUpEl = el=> {\n let original_el = el\n while (el.parentNode) {\n if (el.parentNode.tagName !== 'BODY') {\n el = el.parentNode\n }\n if (el.parentNode.tagName === 'BODY') { return el }\n }\n}\n\nlet elementToBlockSpecElement = compose(wrapBlockSpec, getBlockSpecForElement)\n\nlet imgReplacer = imgElement=> {\n return replaceElement(imgElement, elementToBlockSpecElement(imgElement))\n}\n\n/*\n * Main function\n */\n\n// takes HTML string and returns DraftJS ContentState\nlet customHTML2Content = function(HTML, blockRn){\n let tempDoc = new DOMParser().parseFromString(HTML, 'text/html')\n // replace all <img /> with <blockquote /> elements\n\n let a = tempDoc.querySelectorAll('img').forEach( item=> imgReplacer(item))\n\n // use DraftJS converter to do initial conversion. I don't provide DOMBuilder and\n // blockRenderMap arguments here since it should fall back to its default ones, which are fine\n console.log(tempDoc.body.innerHTML)\n let content = convertFromHTML(tempDoc.body.innerHTML,\n getSafeBodyFromHTML,\n blockRn\n )\n\n let contentBlocks = content.contentBlocks\n\n // now replace <blockquote /> ContentBlocks with 'atomic' ones\n contentBlocks = contentBlocks.map(function(block){\n let newBlock\n console.log(\"CHECK BLOCK\", block.getType())\n if (block.getType() !== 'blockquote') {\n return block\n }\n\n let json = \"\"\n try {\n json = JSON.parse(block.getText())\n } catch (error) {\n return block\n }\n\n return newBlock = block.merge({\n type: \"image\",\n text: \"\",\n data: {\n url: json.imgSrc,\n forceUpload: true\n }\n })\n })\n\n tempDoc = null\n return ContentState.createFromBlockArray(contentBlocks)\n}\n\n\nexport default customHTML2Content\n\n\n// WEBPACK FOOTER //\n// src/utils/html2content.js","import axios from \"axios\"\nimport Immutable from 'immutable'\n\nclass SaveBehavior {\n constructor(options) {\n this.getLocks = options.getLocks\n this.config = options.config\n this.editor = options.editor\n this.editorContent = options.editorContent\n this.editorState = options.editorState\n }\n\n handleStore(ev){\n return this.store()\n }\n\n store(content){\n if (!this.config.data_storage.url) { return }\n if (this.getLocks() > 0) { return }\n\n clearTimeout(this.timeout)\n\n return this.timeout = setTimeout(() => {\n return this.checkforStore(content)\n }\n , this.config.data_storage.interval)\n }\n\n getTextFromEditor(content){\n return content.blocks.map(o=> {\n return o.text\n }\n )\n .join(\"\\n\")\n }\n\n getUrl() {\n let { url } = this.config.data_storage\n if (typeof(url) === \"function\") { \n return url() \n } else { \n return url \n }\n }\n\n getMethod() {\n let { method } = this.config.data_storage\n if (typeof(method) === \"function\") { \n return method() \n } else { \n return method \n }\n }\n\n getWithCredentials(){\n let { withCredentials } = this.config.data_storage\n if (typeof(withCredentials) === \"function\") { \n return withCredentials() \n } else { \n return withCredentials \n }\n }\n\n getCrossDomain(){\n let { crossDomain } = this.config.data_storage\n if (typeof(crossDomain) === \"function\") { \n return crossDomain()\n } else { \n return crossDomain \n }\n }\n\n getHeaders(){\n let { headers } = this.config.data_storage\n if (typeof(headers) === \"function\") { \n return headers() \n } else { \n return headers \n }\n }\n\n checkforStore(content){\n // ENTER DATA STORE\n let isChanged = !Immutable.is(Immutable.fromJS(this.editorContent), Immutable.fromJS(content))\n // console.log(\"CONTENT CHANGED:\", isChanged)\n\n if (!isChanged) { return }\n\n this.save(content)\n }\n\n save(content){\n // use save handler from config if exists\n if (this.config.data_storage.save_handler){\n this.config.data_storage.save_handler(this, content)\n return \n }\n\n if (this.config.xhr.before_handler) { this.config.xhr.before_handler() }\n // console.log \"SAVING TO: #{@getMethod()} #{@getUrl()}\"\n\n return axios({\n method: this.getMethod(),\n url: this.getUrl(),\n data: {\n editor_content: JSON.stringify(content),\n text_content: this.getTextFromEditor(content)\n },\n withCredentials: this.getWithCredentials(),\n crossDomain: this.getCrossDomain(),\n headers: this.getHeaders(),\n })\n .then(result=> {\n // console.log \"STORING CONTENT\", result\n if (this.config.data_storage.success_handler) { this.config.data_storage.success_handler(result) }\n if (this.config.xhr.success_handler) { return this.config.xhr.success_handler(result) }\n }\n )\n .catch(error=> {\n // console.log(\"ERROR: got error saving content at #{@config.data_storage.url} - #{error}\")\n if (this.config.xhr.failure_handler) { return this.config.xhr.failure_handler(error) }\n }\n )\n }\n}\n\n\nexport default SaveBehavior\n\n\n\n// WEBPACK FOOTER //\n// src/utils/save_content.js","import { Map } from 'immutable';\n\n\n\nimport { EditorState, ContentBlock, genKey } from 'draft-js';\n\n\n/*\nUsed from [react-rte](https://github.com/brijeshb42/medium-draft)\nby [brijeshb42](https://github.com/brijeshb42/medium-draft)\n*/\n\n/*\nReturns default block-level metadata for various block type. Empty object otherwise.\n*/\nexport const getDefaultBlockData = (blockType, initialData = {}) => {\n switch (blockType) {\n //case Block.TODO: return { checked: false };\n default: return initialData;\n }\n};\n\nexport const getNode = (root=window) => {\n let t = null\n if (root.getSelection){\n t = root.getSelection()\n } else if (root.document.getSelection){\n t = root.document.getSelection()\n } else if (root.document.selection){\n t = root.document.selection.createRange().text\n }\n return t\n}\n\n/*\nGet currentBlock in the editorState.\n*/\nexport const getCurrentBlock = (editorState) => {\n const selectionState = editorState.getSelection();\n const contentState = editorState.getCurrentContent();\n const block = contentState.getBlockForKey(selectionState.getStartKey());\n return block;\n};\n\n/*\nAdds a new block (currently replaces an empty block) at the current cursor position\nof the given `newType`.\n*/\nexport const addNewBlock = (editorState, newType = \"unstyled\", initialData = {}) => {\n const selectionState = editorState.getSelection();\n if (!selectionState.isCollapsed()) {\n return editorState;\n }\n const contentState = editorState.getCurrentContent();\n const key = selectionState.getStartKey();\n const blockMap = contentState.getBlockMap();\n const currentBlock = getCurrentBlock(editorState);\n if (!currentBlock) {\n return editorState;\n }\n if (currentBlock.getLength() === 0) {\n if (currentBlock.getType() === newType) {\n return editorState;\n }\n const newBlock = currentBlock.merge({\n type: newType,\n data: getDefaultBlockData(newType, initialData),\n });\n const newContentState = contentState.merge({\n blockMap: blockMap.set(key, newBlock),\n selectionAfter: selectionState,\n });\n return EditorState.push(editorState, newContentState, 'change-block-type');\n }\n return editorState;\n};\n\n\n/*\nChanges the block type of the current block.\n*/\nexport const resetBlockWithType = (editorState, newType = \"unstyled\", data={}) => {\n const contentState = editorState.getCurrentContent();\n const selectionState = editorState.getSelection();\n const key = selectionState.getStartKey();\n const blockMap = contentState.getBlockMap();\n const block = blockMap.get(key);\n\n const text = block.getText();\n\n const newBlock = block.merge({\n text: text,\n type: newType,\n data: getDefaultBlockData(newType, data),\n });\n const newContentState = contentState.merge({\n blockMap: blockMap.set(key, newBlock),\n selectionAfter: selectionState.merge({\n anchorOffset: 0,\n focusOffset: 0,\n }),\n });\n return EditorState.push(editorState, newContentState, 'change-block-type');\n};\n\n\n/*\nUpdate block-level metadata of the given `block` to the `newData`/\n*/\nexport const updateDataOfBlock = (editorState, block, newData) => {\n const contentState = editorState.getCurrentContent();\n const newBlock = block.merge({\n data: newData,\n });\n const newContentState = contentState.merge({\n blockMap: contentState.getBlockMap().set(block.getKey(), newBlock),\n });\n return EditorState.push(editorState, newContentState, 'change-block-type');\n // return editorState;\n};\n\nexport const updateTextOfBlock = (editorState, block, text) => {\n const contentState = editorState.getCurrentContent();\n const newBlock = block.merge({\n text: text,\n });\n const newContentState = contentState.merge({\n blockMap: contentState.getBlockMap().set(block.getKey(), newBlock),\n });\n\n return EditorState.push(editorState, newContentState, 'replace-text');\n // return editorState;\n};\n\n// const BEFORE = -1;\n// const AFTER = 1;\n\n/*\nUsed from [react-rte](https://github.com/sstur/react-rte/blob/master/src/lib/insertBlockAfter.js)\nby [sstur](https://github.com/sstur)\n*/\nexport const addNewBlockAt = (\n editorState,\n pivotBlockKey,\n newBlockType = \"unstyled\",\n initialData = {}\n ) => {\n const content = editorState.getCurrentContent();\n const blockMap = content.getBlockMap();\n const block = blockMap.get(pivotBlockKey);\n const blocksBefore = blockMap.toSeq().takeUntil((v) => (v === block));\n const blocksAfter = blockMap.toSeq().skipUntil((v) => (v === block)).rest();\n const newBlockKey = genKey();\n\n const newBlock = new ContentBlock({\n key: newBlockKey,\n type: newBlockType,\n text: '',\n characterList: block.getCharacterList().slice(0, 0),\n depth: 0,\n data: Map(getDefaultBlockData(newBlockType, initialData)),\n });\n\n const newBlockMap = blocksBefore.concat(\n [[pivotBlockKey, block], [newBlockKey, newBlock]],\n blocksAfter\n ).toOrderedMap();\n\n const selection = editorState.getSelection();\n\n const newContent = content.merge({\n blockMap: newBlockMap,\n selectionBefore: selection,\n selectionAfter: selection.merge({\n anchorKey: newBlockKey,\n anchorOffset: 0,\n focusKey: newBlockKey,\n focusOffset: 0,\n isBackward: false,\n }),\n });\n return EditorState.push(editorState, newContent, 'split-block');\n};\n\n\n\n// WEBPACK FOOTER //\n// src/model/index.js","module.exports = __webpack_public_path__ + \"fonts/dante.svg\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.svg\n// module id = 434\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/dante.ttf\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.ttf\n// module id = 435\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/dante.woff\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/dante.woff\n// module id = 436\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.svg\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.svg\n// module id = 437\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.ttf\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.ttf\n// module id = 438\n// module chunks = 0","module.exports = __webpack_public_path__ + \"fonts/fontello.woff\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/styles/fonts/dante/fontello.woff\n// module id = 439\n// module chunks = 0","export const getRelativeParent = (element) => {\n if (!element) {\n return null;\n }\n\n const position = window.getComputedStyle(element).getPropertyValue('position');\n if (position !== 'static') {\n return element;\n }\n\n return getRelativeParent(element.parentElement);\n};\n\n/*\nReturns the `boundingClientRect` of the passed selection.\n*/\nexport const getSelectionRect = (selected) => {\n const _rect = selected.getRangeAt(0).getBoundingClientRect();\n // selected.getRangeAt(0).getBoundingClientRect()\n let rect = _rect && _rect.top ? _rect : selected.getRangeAt(0).getClientRects()[0];\n if (!rect) {\n if (selected.anchorNode && selected.anchorNode.getBoundingClientRect) {\n rect = selected.anchorNode.getBoundingClientRect();\n rect.isEmptyline = true;\n } else {\n return null;\n }\n }\n return rect;\n};\n\n/*\nReturns the native selection node.\n*/\nexport const getSelection = (root) => {\n let t = null;\n if (root.getSelection) {\n t = root.getSelection();\n } else if (root.document.getSelection) {\n t = root.document.getSelection();\n } else if (root.document.selection) {\n t = root.document.selection.createRange().text;\n }\n return t;\n};\n\n/*\nRecursively finds the DOM Element of the block where the cursor is currently present.\nIf not found, returns null.\n*/\nexport const getSelectedBlockNode = (root) => {\n const selection = root.getSelection();\n if (selection.rangeCount === 0) {\n return null;\n }\n let node = selection.getRangeAt(0).startContainer;\n // console.log(node);\n do {\n if (node.getAttribute && node.getAttribute('data-block') === 'true') {\n return node;\n }\n node = node.parentNode;\n // console.log(node);\n } while (node !== null);\n return null;\n};\n\n\n\n// WEBPACK FOOTER //\n// src/utils/selection.js"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;AAcA;AACA;AAIA;AACA;AAQA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;;;AAEA;;;AACA;AAAA;AACA;AADA;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;AAFA;AACA;AAIA;AACA;AACA;AADA;AAGA;AACA;AADA;AAGA;AACA;AADA;AAGA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAFA;AACA;AAnBA;AACA;AAwBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AARA;AACA;AA1GA;AAAA;AAAA;AAAA;AACA;AACA;AAmHA;AACA;AAtHA;AAuHA;AACA;;;AACA;AAAA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AAEA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;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;;;AAEA;AACA;AACA;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAUA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;;;AAEA;AACA;AACA;AACA;AAAA;AAAA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AACA;AASA;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;AAVA;AAHA;AACA;AAgBA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAFA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAJA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAfA;AAiBA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAHA;AACA;AAWA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AACA;AACA;AAOA;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;AANA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AACA;AACA;AACA;AACA;AAJA;AACA;AAMA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAAA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AAAA;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;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;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;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AADA;AAGA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAnBA;AAHA;AADA;AAJA;AADA;AADA;AADA;AADA;AAyCA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAZA;AAeA;AAGA;AA9DA;AAsEA;;;AA96BA;AACA;AAg7BA;;;;;;;AC39BA;;;;;;;ACAA;;;;;;;;;;;;;;;ACCA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;ACRA;;;;;;;;;;ACAA;AACA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;;;AACA;AACA;;;AACA;;;AACA;AAAA;AACA;AACA;AACA;AAHA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAFA;AAPA;AAWA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAJA;AAQA;AACA;AAAA;AAAA;AAAA;AAGA;AAAA;AAAA;AACA;AACA;AACA;AAHA;AAKA;AAAA;AAAA;AACA;AADA;AAGA;AAAA;AAAA;AACA;AADA;AARA;AAWA;AAzBA;AA4BA;;;AAjHA;AACA;AADA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACVA;AACA;;;AAAA;AACA;;;AACA;AACA;AAMA;AACA;;;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;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;AAVA;AA3BA;AAuCA;AACA;;;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AADA;AAGA;AACA;AACA;AACA;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAIA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AAHA;AAKA;;;AAEA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;;;AAIA;AACA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AACA;AAbA;AAeA;AAAA;AAAA;AACA;AACA;AAAA;AACA;AADA;AAGA;AACA;AANA;AAhBA;AA2BA;;;AA3VA;AACA;AADA;AACA;AA6VA;;;;;;;;;;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AAEA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AACA;AADA;AAHA;AADA;AAFA;AAgBA;;;AApBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3WA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AACA;;;AACA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AANA;AAUA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AADA;AADA;AAOA;AACA;;;AAEA;AACA;AACA;AAAA;AAEA;AAEA;AACA;AACA;AAFA;AAJA;AAUA;;;AAvDA;AACA;AADA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AACA;;;AACA;AAAA;AACA;AACA;AACA;AAHA;AACA;AAGA;AACA;AACA;AANA;AAOA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AAAA;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AACA;AADA;AAHA;AAQA;;;AAnEA;AACA;AADA;;;;;;;;;;;;;;;;;;;;;;ACVA;AACA;;;AAAA;AACA;;;AAAA;AACA;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;;;AAIA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAUA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AApCA;AA8CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AAFA;AAIA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AA1BA;AA4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AAHA;AACA;AAKA;AAAA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AA7BA;AA+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AADA;AAGA;AAAA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AA9BA;AACA;AAiCA;AACA;AACA;AACA;AACA;AAWA;AACA;AACA;AACA;AACA;AAJA;AAfA;AA+BA;AACA;AAFA;AAIA;AACA;AAFA;AAIA;AACA;AAFA;AACA;AAIA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AACA;AAUA;AACA;AAWA;AACA;AASA;AACA;AACA;AAGA;AALA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AACA;AAWA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AAIA;;;;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3SA;AACA;;;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAZA;AAgBA;AACA;;;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AAEA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AADA;AADA;AAKA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AAGA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AAVA;AADA;AAgBA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAEA;AACA;AAAA;AAAA;AAAA;AAJA;AAFA;AAjBA;AA8BA;;;AAjGA;AACA;AAmGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtGA;AACA;;;AAAA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AAOA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AAPA;AAUA;;;AA3DA;AACA;AADA;;;;;;;;;;;;;;;ACFA;AACA;;;AAAA;AACA;;;;;AAEA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACNA;AACA;;;AAAA;AACA;;;AACA;AACA;AAMA;AACA;AAMA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAjBA;AAsBA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;;;AAEA;AACA;AACA;AACA;AAFA;AACA;AAIA;AACA;;;AAEA;AACA;AACA;AACA;;;;AAIA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAUA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAKA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAFA;AAIA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAJA;AAMA;AANA;AAQA;AAAA;AAAA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;AAHA;AAKA;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAZA;AAZA;AAkCA;;;AA/PA;AACA;AAiQA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AAFA;AAGA;AACA;;;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AAHA;AAKA;AALA;AAQA;;;AAtBA;AACA;AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7SA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAPA;AAZA;AAwBA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAEA;AALA;AAQA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AAPA;AADA;AAYA;AApBA;AAuBA;;;AA9JA;AACA;AAgKA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AACA;AAHA;AAIA;AACA;;;AACA;AACA;AACA;AACA;;;AAEA;AACA;AAAA;AAAA;AACA;AACA;AACA;AAHA;AAKA;;;AAnBA;AACA;AAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChMA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AANA;AARA;AAgBA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AADA;AADA;AAKA;AAZA;AAeA;;;AAvGA;AACA;AAyGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClHA;AACA;;;AAAA;AACA;;;AACA;AACA;AAYA;AACA;AACA;AACA;;;AACA;;;AAEA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAlBA;AAuBA;AACA;;;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AACA;AACA;AACA;;;AAEA;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;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAFA;AAOA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AAFA;AAIA;;;AAEA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AADA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AAJA;AAMA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AARA;AAUA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AAQA;AAGA;AACA;AACA;AAFA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAOA;AA3BA;AAhBA;AAgDA;;;AA1TA;AACA;AA4TA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAQA;AACA;;;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AADA;AAIA;;;AAxDA;AACA;AA0DA;;;AAEA;AAAA;AACA;AADA;AACA;AADA;AAAA;AAAA;AACA;AADA;AACA;AACA;AAFA;AAGA;AACA;;;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AADA;AAIA;;;AApBA;AACA;AA2BA;;;;;;;;;;;;;;ACxaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;ACjBA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAHA;AAQA;AACA;AACA;AACA;AACA;AACA;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;AChIA;AACA;;;AAAA;AACA;;;;;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;;;AAEA;AACA;AACA;AACA;AAGA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;;;AAEA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AATA;AAYA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAGA;AACA;AAAA;AAAA;AACA;AAEA;;;;;AAIA;;;;;;;;;;;;;;;AC/HA;AACA;AAGA;AACA;AAEA;;;;;AAKA;;;AAGA;AAAA;AACA;AAAA;AACA;AACA;AAAA;AAFA;AAIA;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AAAA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;AAFA;AAIA;AACA;AACA;AACA;AACA;AAEA;;;AAGA;AAAA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AAFA;AAFA;AAOA;AACA;AACA;AAEA;;;AAGA;AACA;AACA;AACA;AADA;AAGA;AACA;AADA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AADA;AAGA;AACA;AADA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AAKA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AACA;AAQA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AALA;AAHA;AAWA;AACA;;;;;;;ACtLA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;ACAA;;;;;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;A","sourceRoot":""}
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "Dante2",
|
3
|
-
"version": "0.4.
|
3
|
+
"version": "0.4.4",
|
4
4
|
"description": "Dante wysiwyg rewritten in draft-js",
|
5
5
|
"author": "Miguel Michelson",
|
6
6
|
"license": "GPL-3.0",
|
@@ -26,9 +26,9 @@
|
|
26
26
|
"dependencies": {
|
27
27
|
"axios": "^0.15.2",
|
28
28
|
"babel-runtime": "^6.11.6",
|
29
|
-
"draft-convert": "^1.2
|
30
|
-
"draft-js": "0.10.
|
31
|
-
"draft-js-custom-styles": "^2.0.
|
29
|
+
"draft-convert": "^2.1.2",
|
30
|
+
"draft-js": "0.10.4",
|
31
|
+
"draft-js-custom-styles": "^2.0.4",
|
32
32
|
"immutable": "^3.8.2"
|
33
33
|
},
|
34
34
|
"devDependencies": {
|
@@ -52,8 +52,6 @@
|
|
52
52
|
"colors": "^1.1.2",
|
53
53
|
"cross-env": "^3.1.4",
|
54
54
|
"css-loader": "^0.25.0",
|
55
|
-
"draft-convert": "^1.2.3",
|
56
|
-
"draft-js": "0.10.3",
|
57
55
|
"eslint": "1.7.2",
|
58
56
|
"eslint-loader": "1.1.0",
|
59
57
|
"expose-loader": "^0.7.1",
|
@@ -342,7 +342,9 @@ export default class ImageBlock extends React.Component {
|
|
342
342
|
ref="image_tag"
|
343
343
|
height={this.state.aspect_ratio.height}
|
344
344
|
width={this.state.aspect_ratio.width}
|
345
|
-
className='graf-image'
|
345
|
+
className='graf-image'
|
346
|
+
contentEditable={false}
|
347
|
+
/>
|
346
348
|
<Loader toggle={this.state.loading}
|
347
349
|
progress={this.state.loading_progress} />
|
348
350
|
</div>
|
@@ -33,11 +33,11 @@ import {
|
|
33
33
|
} from '../../model/index.js'
|
34
34
|
|
35
35
|
import Link from '../decorators/link'
|
36
|
-
import Debug from '
|
36
|
+
import Debug from '../core/debug'
|
37
37
|
import findEntities from '../../utils/find_entities'
|
38
38
|
import SaveBehavior from '../../utils/save_content'
|
39
39
|
import customHTML2Content from '../../utils/html2content'
|
40
|
-
import createStyles from 'draft-js-custom-styles'
|
40
|
+
import createStyles from 'draft-js-custom-styles'
|
41
41
|
|
42
42
|
|
43
43
|
class DanteEditor extends React.Component {
|
@@ -70,6 +70,7 @@ class DanteEditor extends React.Component {
|
|
70
70
|
this.handleHTMLPaste = this.handleHTMLPaste.bind(this)
|
71
71
|
this.handlePasteImage = this.handlePasteImage.bind(this)
|
72
72
|
this.handleDroppedFiles = this.handleDroppedFiles.bind(this)
|
73
|
+
this.handleDrop = this.handleDrop.bind(this)
|
73
74
|
this.handleUpArrow = this.handleUpArrow.bind(this)
|
74
75
|
this.handleDownArrow = this.handleDownArrow.bind(this)
|
75
76
|
this.handleReturn = this.handleReturn.bind(this)
|
@@ -151,7 +152,8 @@ class DanteEditor extends React.Component {
|
|
151
152
|
xhr: this.props.config.xhr,
|
152
153
|
data_storage: this.props.config.data_storage
|
153
154
|
},
|
154
|
-
|
155
|
+
editor: this,
|
156
|
+
editorState: this.getEditorState,
|
155
157
|
editorContent: this.emitSerializedOutput()
|
156
158
|
})
|
157
159
|
|
@@ -162,6 +164,12 @@ class DanteEditor extends React.Component {
|
|
162
164
|
|
163
165
|
componentDidMount(){
|
164
166
|
this.initializeState()
|
167
|
+
window.addEventListener('resize', ()=> {
|
168
|
+
if(this.relocateTooltips)
|
169
|
+
setTimeout(() => {
|
170
|
+
return this.relocateTooltips()
|
171
|
+
})
|
172
|
+
})
|
165
173
|
}
|
166
174
|
|
167
175
|
initializeState() {
|
@@ -209,14 +217,17 @@ class DanteEditor extends React.Component {
|
|
209
217
|
}
|
210
218
|
|
211
219
|
onChange(editorState) {
|
220
|
+
|
221
|
+
editorState = this.handleUndeletables(editorState)
|
222
|
+
|
212
223
|
this.setPreContent()
|
213
224
|
this.setState({ editorState })
|
214
225
|
|
215
226
|
const currentBlock = getCurrentBlock(this.state.editorState)
|
216
227
|
const blockType = currentBlock.getType()
|
217
228
|
|
218
|
-
if (!editorState.getSelection().isCollapsed()) {
|
219
229
|
|
230
|
+
if (!editorState.getSelection().isCollapsed()) {
|
220
231
|
const tooltip = this.tooltipsWithProp('displayOnSelection')[0]
|
221
232
|
if (!this.tooltipHasSelectionElement(tooltip, blockType)) {
|
222
233
|
return
|
@@ -228,11 +239,41 @@ class DanteEditor extends React.Component {
|
|
228
239
|
|
229
240
|
setTimeout(() => {
|
230
241
|
return this.relocateTooltips()
|
231
|
-
}
|
242
|
+
})
|
232
243
|
|
233
244
|
return this.dispatchChangesToSave()
|
234
245
|
}
|
235
246
|
|
247
|
+
handleUndeletables(editorState){
|
248
|
+
// undeletable behavior, will keep previous blockMap
|
249
|
+
// if undeletables are deleted
|
250
|
+
const undeletable_types = this.widgets.filter(
|
251
|
+
function(o){ return o.undeletable })
|
252
|
+
.map(function(o){ return o.type })
|
253
|
+
|
254
|
+
const currentblockMap = this.state.editorState.getCurrentContent().get("blockMap")
|
255
|
+
const blockMap = editorState.getCurrentContent().get("blockMap")
|
256
|
+
|
257
|
+
const undeletablesMap = blockMap
|
258
|
+
.filter(function(o){
|
259
|
+
return undeletable_types.indexOf(o.get("type")) > 0
|
260
|
+
})
|
261
|
+
|
262
|
+
if (undeletable_types.length > 0 && undeletablesMap.size === 0) {
|
263
|
+
|
264
|
+
const contentState = editorState.getCurrentContent();
|
265
|
+
const blockMap = contentState.getBlockMap();
|
266
|
+
const newContentState = contentState.merge({
|
267
|
+
blockMap: this.state.editorState.getCurrentContent().blockMap,
|
268
|
+
selectionBefore: contentState.getSelectionAfter()
|
269
|
+
});
|
270
|
+
|
271
|
+
return editorState = EditorState.push(editorState, newContentState, 'change-block')
|
272
|
+
}
|
273
|
+
|
274
|
+
return editorState
|
275
|
+
}
|
276
|
+
|
236
277
|
dispatchChangesToSave() {
|
237
278
|
clearTimeout(this.saveTimeout)
|
238
279
|
return this.saveTimeout = setTimeout(() => {
|
@@ -368,7 +409,7 @@ class DanteEditor extends React.Component {
|
|
368
409
|
if (defaultBlockClass.length > 0) {
|
369
410
|
return `graf ${ defaultBlockClass[0] } ${ is_selected }`
|
370
411
|
} else {
|
371
|
-
return `graf
|
412
|
+
return `graf ${ is_selected }`
|
372
413
|
}
|
373
414
|
}
|
374
415
|
|
@@ -385,10 +426,11 @@ class DanteEditor extends React.Component {
|
|
385
426
|
return null
|
386
427
|
}
|
387
428
|
|
388
|
-
const selectedFn = dataBlock.selectedFn ? dataBlock.selectedFn(block) :
|
389
|
-
const selected_class =
|
429
|
+
const selectedFn = dataBlock.selectedFn ? dataBlock.selectedFn(block) : ''
|
430
|
+
const selected_class = (dataBlock.selected_class ? dataBlock.selected_class : '' )
|
431
|
+
const selected_class_out = is_selected ? selected_class : ''
|
390
432
|
|
391
|
-
return `${ dataBlock.wrapper_class } ${
|
433
|
+
return `${ dataBlock.wrapper_class } ${ selected_class_out } ${ selectedFn }`
|
392
434
|
}
|
393
435
|
|
394
436
|
handleTooltipDisplayOn(prop, display) {
|
@@ -523,6 +565,19 @@ class DanteEditor extends React.Component {
|
|
523
565
|
})
|
524
566
|
}
|
525
567
|
|
568
|
+
handleDrop(selection, dataTransfer, isInternal){
|
569
|
+
|
570
|
+
const editorState = this.getEditorState();
|
571
|
+
|
572
|
+
const raw = dataTransfer.data.getData('text');
|
573
|
+
|
574
|
+
const data = JSON.parse(raw);
|
575
|
+
|
576
|
+
this.onChange(addNewBlock(editorState, data.type, data.data))
|
577
|
+
|
578
|
+
return 'handled';
|
579
|
+
}
|
580
|
+
|
526
581
|
handleUpArrow(e) {
|
527
582
|
return setTimeout(() => {
|
528
583
|
return this.forceRender(this.state.editorState)
|
@@ -560,7 +615,7 @@ class DanteEditor extends React.Component {
|
|
560
615
|
if (currentBlock.getText().length === 0) {
|
561
616
|
|
562
617
|
if (config_block && config_block.handleEnterWithoutText) {
|
563
|
-
config_block.
|
618
|
+
config_block.handleEnterWithoutText(this, currentBlock)
|
564
619
|
this.closePopOvers()
|
565
620
|
return true
|
566
621
|
}
|
@@ -866,7 +921,7 @@ class DanteEditor extends React.Component {
|
|
866
921
|
<div className="section-divider layoutSingleColumn">
|
867
922
|
<hr className="section-divider" />
|
868
923
|
</div>
|
869
|
-
<div className="section-content">
|
924
|
+
<div className="section-content container">
|
870
925
|
<div ref="richEditor"
|
871
926
|
className="section-inner layoutSingleColumn"
|
872
927
|
onClick={ this.focus }>
|
@@ -874,6 +929,7 @@ class DanteEditor extends React.Component {
|
|
874
929
|
blockRendererFn={ this.blockRenderer }
|
875
930
|
editorState={ this.state.editorState }
|
876
931
|
onChange={ this.onChange }
|
932
|
+
handleDrop={this.handleDrop}
|
877
933
|
onUpArrow={ this.handleUpArrow }
|
878
934
|
onDownArrow={ this.handleDownArrow }
|
879
935
|
handleReturn={ this.handleReturn }
|
@@ -922,6 +978,7 @@ class DanteEditor extends React.Component {
|
|
922
978
|
? <Debug locks={ this.state.locks } editor={ this } />
|
923
979
|
: undefined
|
924
980
|
}
|
981
|
+
|
925
982
|
</div>
|
926
983
|
|
927
984
|
)
|
@@ -15,7 +15,7 @@ import {
|
|
15
15
|
getCurrentBlock,
|
16
16
|
getNode } from '../../model/index.js'
|
17
17
|
|
18
|
-
import { getSelectionRect, getSelection } from "../../utils/selection.js"
|
18
|
+
import { getSelectionRect, getSelection, getRelativeParent } from "../../utils/selection.js"
|
19
19
|
|
20
20
|
class DanteInlineTooltip extends React.Component {
|
21
21
|
|
@@ -219,42 +219,18 @@ class DanteInlineTooltip extends React.Component {
|
|
219
219
|
let parent = ReactDOM.findDOMNode(this.props.editor)
|
220
220
|
let parentBoundary = parent.getBoundingClientRect()
|
221
221
|
|
222
|
-
// hide if selected node is not in editor
|
223
|
-
// debugger
|
224
|
-
//console.log @isDescendant(parent, nativeSelection.anchorNode)
|
225
|
-
|
226
222
|
if (!this.isDescendant(parent, nativeSelection.anchorNode)) {
|
227
223
|
this.hide()
|
228
224
|
return
|
229
225
|
}
|
230
226
|
|
231
|
-
if (!coords)
|
232
|
-
return
|
233
|
-
|
234
227
|
// checkeamos si esta vacio
|
235
228
|
this.display(block.getText().length === 0 && blockType === "unstyled")
|
236
229
|
return this.setPosition({
|
237
|
-
top: coords.top + window.
|
238
|
-
left: coords.left + window.
|
230
|
+
top: coords.top + window.scrollY,
|
231
|
+
left: coords.left + window.scrollX - 60
|
239
232
|
})
|
240
233
|
|
241
|
-
/*
|
242
|
-
@refs.image_popover.display(blockType is "image")
|
243
|
-
if blockType is "image"
|
244
|
-
selectionBoundary = node.anchorNode.parentNode.parentNode.parentNode.getBoundingClientRect()
|
245
|
-
*el = document.querySelector("#dante_image_popover")
|
246
|
-
el = @refs.image_popover.refs.image_popover
|
247
|
-
padd = el.offsetWidth / 2
|
248
|
-
@refs.image_popover.setPosition
|
249
|
-
top: selectionBoundary.top - parentBoundary.top + 60
|
250
|
-
left: selectionBoundary.left + (selectionBoundary.width / 2) - padd
|
251
|
-
|
252
|
-
*@setState
|
253
|
-
* image_popover_position:
|
254
|
-
* top: selectionBoundary.top - parentBoundary.top + 60
|
255
|
-
* left: selectionBoundary.left + (selectionBoundary.width / 2) - padd
|
256
|
-
*
|
257
|
-
*/
|
258
234
|
} else {
|
259
235
|
return this.hide()
|
260
236
|
}
|
@@ -4,7 +4,7 @@ import ReactDOM from 'react-dom'
|
|
4
4
|
|
5
5
|
import { Entity, RichUtils, AtomicBlockUtils, EditorState } from 'draft-js'
|
6
6
|
|
7
|
-
import { getSelectionRect, getSelection } from "../../utils/selection.js"
|
7
|
+
import { getSelectionRect, getSelection, getRelativeParent } from "../../utils/selection.js"
|
8
8
|
|
9
9
|
import { getCurrentBlock, getNode } from '../../model/index.js'
|
10
10
|
|
@@ -29,9 +29,9 @@ class DanteImagePopover extends React.Component {
|
|
29
29
|
},
|
30
30
|
show: false,
|
31
31
|
scaled: false,
|
32
|
-
buttons: [{ type: "left" },
|
33
|
-
{ type: "center"},
|
34
|
-
{ type: "fill" },
|
32
|
+
buttons: [{ type: "left" },
|
33
|
+
{ type: "center"},
|
34
|
+
{ type: "fill" },
|
35
35
|
{ type: "wide" }]
|
36
36
|
}
|
37
37
|
}
|
@@ -97,23 +97,30 @@ class DanteImagePopover extends React.Component {
|
|
97
97
|
|
98
98
|
let node = getNode()
|
99
99
|
|
100
|
-
let selectionBoundary = getSelectionRect(nativeSelection)
|
101
|
-
let coords = selectionBoundary
|
102
|
-
|
103
|
-
let parent = ReactDOM.findDOMNode(this.props.editor)
|
104
|
-
let parentBoundary = parent.getBoundingClientRect()
|
105
|
-
|
106
100
|
this.display(blockType === "image")
|
107
101
|
|
108
102
|
if (blockType === "image") {
|
109
|
-
selectionBoundary = node.anchorNode.parentNode.parentNode
|
103
|
+
let selectionBoundary = node.anchorNode.parentNode.parentNode
|
110
104
|
.parentNode.getBoundingClientRect()
|
105
|
+
|
106
|
+
let coords = selectionBoundary
|
107
|
+
|
111
108
|
let el = this.refs.image_popover
|
112
109
|
let padd = el.offsetWidth / 2
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
110
|
+
|
111
|
+
let parent = ReactDOM.findDOMNode(this.props.editor)
|
112
|
+
let parentBoundary = parent.getBoundingClientRect()
|
113
|
+
|
114
|
+
const toolbarHeight = el.offsetHeight;
|
115
|
+
|
116
|
+
let left = selectionBoundary.left + selectionBoundary.width / 2 - padd
|
117
|
+
|
118
|
+
let diff = window.pageYOffset + parent.getBoundingClientRect().top
|
119
|
+
|
120
|
+
let top = selectionBoundary.top - parentBoundary.top + toolbarHeight //+ diff
|
121
|
+
|
122
|
+
return this.setPosition({ top: top, left: left })
|
123
|
+
|
117
124
|
}
|
118
125
|
} else {
|
119
126
|
return this.hide()
|
@@ -139,7 +146,7 @@ class DanteImagePopover extends React.Component {
|
|
139
146
|
<div
|
140
147
|
ref="image_popover"
|
141
148
|
className={ `dante-popover popover--Aligntooltip popover--top popover--animated ${ this.state.show ? 'is-active' : undefined }` }
|
142
|
-
style={
|
149
|
+
style={
|
143
150
|
{ top: this.state.position.top,
|
144
151
|
left: this.state.position.left }
|
145
152
|
}
|
@@ -176,10 +183,10 @@ class DanteImagePopoverItem extends React.Component {
|
|
176
183
|
}
|
177
184
|
|
178
185
|
render() {
|
179
|
-
return <li
|
180
|
-
className={`dante-menu-button align-${ this.props.item.type }`}
|
186
|
+
return <li
|
187
|
+
className={`dante-menu-button align-${ this.props.item.type }`}
|
181
188
|
onMouseDown={this.handleClick}>
|
182
|
-
<span className={`tooltip-icon dante-icon-image-${ this.props.item.type }`} />
|
189
|
+
<span className={`tooltip-icon dante-icon dante-icon-image-${ this.props.item.type }`} />
|
183
190
|
</li>
|
184
191
|
}
|
185
192
|
}
|
@@ -4,6 +4,8 @@ import ReactDOM from 'react-dom'
|
|
4
4
|
|
5
5
|
import { getCurrentBlock } from '../../model/index.js'
|
6
6
|
|
7
|
+
import { getRelativeParent } from "../../utils/selection.js"
|
8
|
+
|
7
9
|
class DanteAnchorPopover extends React.Component {
|
8
10
|
|
9
11
|
constructor(props) {
|
@@ -71,9 +73,16 @@ class DanteAnchorPopover extends React.Component {
|
|
71
73
|
let parent = ReactDOM.findDOMNode(this.props.editor)
|
72
74
|
let parentBoundary = parent.getBoundingClientRect()
|
73
75
|
|
76
|
+
const toolbarHeight = el.offsetHeight;
|
77
|
+
const relativeRect = node.getBoundingClientRect();
|
78
|
+
let left = selectionBoundary.left + selectionBoundary.width / 2 - padd
|
79
|
+
|
80
|
+
let diff = window.pageYOffset + parent.getBoundingClientRect().top
|
81
|
+
let top = relativeRect.top - parentBoundary.top + (toolbarHeight * 0.3) + diff
|
82
|
+
|
74
83
|
return {
|
75
|
-
top:
|
76
|
-
left:
|
84
|
+
top: top,
|
85
|
+
left: left
|
77
86
|
}
|
78
87
|
}
|
79
88
|
|
@@ -93,7 +102,7 @@ class DanteAnchorPopover extends React.Component {
|
|
93
102
|
onMouseOut={ this.props.handleOnMouseOut }
|
94
103
|
>
|
95
104
|
<div className='popover-inner'>
|
96
|
-
<a href={ this.
|
105
|
+
<a href={ this.state.url } target='_blank'>
|
97
106
|
{ this.state.url }
|
98
107
|
</a>
|
99
108
|
</div>
|
@@ -14,7 +14,7 @@ import {
|
|
14
14
|
Entity,
|
15
15
|
RichUtils } from 'draft-js'
|
16
16
|
|
17
|
-
import { getSelectionRect, getSelection } from "../../utils/selection.js"
|
17
|
+
import { getSelectionRect, getSelection, getRelativeParent } from "../../utils/selection.js"
|
18
18
|
|
19
19
|
import { getCurrentBlock } from '../../model/index.js'
|
20
20
|
|
@@ -128,9 +128,23 @@ class DanteTooltip extends React.Component {
|
|
128
128
|
return
|
129
129
|
}
|
130
130
|
|
131
|
-
let top = selectionBoundary.top - parentBoundary.top - -90 - 5
|
131
|
+
//let top = selectionBoundary.top - parentBoundary.top - -90 - 5
|
132
|
+
|
133
|
+
const relativeParent = getRelativeParent(this.refs.dante_menu.parentElement);
|
134
|
+
const toolbarHeight = this.refs.dante_menu.clientHeight;
|
135
|
+
const relativeRect = (relativeParent || document.body).getBoundingClientRect();
|
136
|
+
const selectionRect = getVisibleSelectionRect(window);
|
137
|
+
|
138
|
+
if(!selectionRect || !relativeRect || !selectionBoundary)
|
139
|
+
return
|
140
|
+
|
141
|
+
|
142
|
+
let diff = window.pageYOffset + parent.getBoundingClientRect().top
|
143
|
+
let top = (selectionRect.top - relativeRect.top) - toolbarHeight + diff
|
132
144
|
let left = selectionBoundary.left + selectionBoundary.width / 2 - padd
|
133
145
|
|
146
|
+
//let left = (selectionRect.left - relativeRect.left) + (selectionRect.width / 2)
|
147
|
+
|
134
148
|
if (!top || !left) {
|
135
149
|
return
|
136
150
|
}
|
data/src/model/index.js
CHANGED
@@ -128,7 +128,7 @@ export const updateTextOfBlock = (editorState, block, text) => {
|
|
128
128
|
blockMap: contentState.getBlockMap().set(block.getKey(), newBlock),
|
129
129
|
});
|
130
130
|
|
131
|
-
return EditorState.push(editorState, newContentState, '
|
131
|
+
return EditorState.push(editorState, newContentState, 'replace-text');
|
132
132
|
// return editorState;
|
133
133
|
};
|
134
134
|
|