From 32f18f858b31e5a464dea1fa051df661d5e4c027 Mon Sep 17 00:00:00 2001 From: Rose Robertson Date: Tue, 23 May 2017 15:55:55 -0700 Subject: [PATCH] Fix DraftJS error when pasting over non-collapsed selection addText uses insertText, so the handlePastedText method was failing if a user was highlighting text and then pasting to replace the highlighted text. (error was: Target range must be collapsed for `insertText`) A similar method, replaceText, has been aded, and the handlePastedText method has been updated to use replaceText instead. --- src/__test__/plugin-test.js | 4 ++-- src/__test__/utils-test.js | 27 +++++++++++++++++++++++++-- src/index.js | 8 ++++---- src/utils.js | 5 +++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/__test__/plugin-test.js b/src/__test__/plugin-test.js index f0c3db3..fe53b9a 100755 --- a/src/__test__/plugin-test.js +++ b/src/__test__/plugin-test.js @@ -314,7 +314,7 @@ describe('draft-js-markdown-shortcuts-plugin', () => { subject = () => plugin.handlePastedText(pastedText, html, store); }); [ - 'addText', + 'replaceText', 'addEmptyBlock', 'handleBlockType', 'handleImage', @@ -342,7 +342,7 @@ describe('draft-js-markdown-shortcuts-plugin', () => { describe('pasted just text', () => { beforeEach(() => { pastedText = 'hello'; - createMarkdownShortcutsPlugin.__Rewire__('addText', modifierSpy); // eslint-disable-line no-underscore-dangle + createMarkdownShortcutsPlugin.__Rewire__('replaceText', modifierSpy); // eslint-disable-line no-underscore-dangle }); it('returns handled', () => { expect(subject()).to.equal('handled'); diff --git a/src/__test__/utils-test.js b/src/__test__/utils-test.js index 9baa2cc..a002dfa 100644 --- a/src/__test__/utils-test.js +++ b/src/__test__/utils-test.js @@ -1,10 +1,11 @@ import { expect } from 'chai'; -import Draft, { EditorState } from 'draft-js'; -import { addText, addEmptyBlock } from '../utils'; +import Draft, { EditorState, SelectionState } from 'draft-js'; +import { addText, replaceText, addEmptyBlock } from '../utils'; describe('utils test', () => { it('is loaded', () => { expect(addText).to.be.a('function'); + expect(replaceText).to.be.a('function'); expect(addEmptyBlock).to.be.a('function'); }); @@ -45,4 +46,26 @@ describe('utils test', () => { const lastBlock = currentContent.getLastBlock(); expect(lastBlock.getText()).to.equal(randomText); }); + + it('should replaceText', () => { + let newEditorState = EditorState.createWithContent(Draft.convertFromRaw(newRawContentState)); + const randomText = Date.now().toString(32); + let currentContent = newEditorState.getCurrentContent(); + let lastBlock = currentContent.getLastBlock(); + const newSelection = new SelectionState({ + anchorKey: lastBlock.getKey(), + anchorOffset: 0, + focusKey: lastBlock.getKey(), + focusOffset: lastBlock.getText().length + }); + newEditorState = EditorState.forceSelection(newEditorState, newSelection); + + newEditorState = replaceText(newEditorState, randomText); + currentContent = newEditorState.getCurrentContent(); + expect(currentContent.hasText()).to.equal(true); + lastBlock = currentContent.getLastBlock(); + expect(lastBlock.getText()).to.equal(randomText); + const firstBlock = currentContent.getFirstBlock(); + expect(firstBlock.getText()).to.equal(randomText); + }); }); diff --git a/src/index.js b/src/index.js index 95c0adf..779a6b6 100755 --- a/src/index.js +++ b/src/index.js @@ -16,7 +16,7 @@ import leaveList from './modifiers/leaveList'; import insertText from './modifiers/insertText'; import createLinkDecorator from './decorators/link'; import createImageDecorator from './decorators/image'; -import { addText, addEmptyBlock } from './utils'; +import { replaceText, addEmptyBlock } from './utils'; const INLINE_STYLE_CHARACTERS = [' ', '*', '_']; @@ -140,16 +140,16 @@ const createMarkdownShortcutsPlugin = (config = {}) => { let buffer = []; for (let i = 0; i < text.length; i++) { // eslint-disable-line no-plusplus if (INLINE_STYLE_CHARACTERS.indexOf(text[i]) >= 0) { - newEditorState = addText(newEditorState, buffer.join('') + text[i]); + newEditorState = replaceText(newEditorState, buffer.join('') + text[i]); newEditorState = checkCharacterForState(newEditorState, text[i]); buffer = []; } else if (text[i].charCodeAt(0) === 10) { - newEditorState = addText(newEditorState, buffer.join('')); + newEditorState = replaceText(newEditorState, buffer.join('')); newEditorState = addEmptyBlock(newEditorState); newEditorState = checkReturnForState(newEditorState, {}); buffer = []; } else if (i === text.length - 1) { - newEditorState = addText(newEditorState, buffer.join('') + text[i]); + newEditorState = replaceText(newEditorState, buffer.join('') + text[i]); buffer = []; } else { buffer.push(text[i]); diff --git a/src/utils.js b/src/utils.js index 3df34b9..8227a3e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -14,6 +14,11 @@ export function addText(editorState, bufferText) { return EditorState.push(editorState, contentState, 'insert-characters'); } +export function replaceText(editorState, bufferText) { + const contentState = Modifier.replaceText(editorState.getCurrentContent(), editorState.getSelection(), bufferText); + return EditorState.push(editorState, contentState, 'insert-characters'); +} + export function addEmptyBlock(editorState) { let contentState = editorState.getCurrentContent(); const emptyBlock = getEmptyContentBlock();