diff --git a/src/transforms/apply-operation.js b/src/transforms/apply-operation.js index 0c20b1d30..a4e50479e 100644 --- a/src/transforms/apply-operation.js +++ b/src/transforms/apply-operation.js @@ -285,16 +285,11 @@ function removeNode(state, operation) { function removeText(state, operation) { const { path, offset, length } = operation + const rangeOffset = offset + length let { document, selection } = state const { startKey, endKey, startOffset, endOffset } = selection let node = document.assertPath(path) - const rangeOffset = offset + length - - // Update the document - node = node.removeText(offset, length) - document = document.updateDescendant(node) - // Update the selection if (startKey == node.key && startOffset >= rangeOffset) { selection = selection.moveStartOffset(-length) @@ -303,6 +298,8 @@ function removeText(state, operation) { selection = selection.moveEndOffset(-length) } + node = node.removeText(offset, length) + document = document.updateDescendant(node) state = state.merge({ document, selection }) return state } diff --git a/src/transforms/at-current-range.js b/src/transforms/at-current-range.js index 90639d7e9..2eeccea38 100644 --- a/src/transforms/at-current-range.js +++ b/src/transforms/at-current-range.js @@ -38,64 +38,16 @@ export function addMark(transform, mark) { export function _delete(transform) { const { state } = transform - const { document, selection } = state - - // If the selection is collapsed, there's nothing to delete. + const { selection } = state if (selection.isCollapsed) return - const { startText } = state - const { startKey, startOffset, endKey, endOffset } = selection - const block = document.getClosestBlock(startKey) - const highest = block.getHighestChild(startKey) - const previous = block.getPreviousSibling(highest.key) - const next = block.getNextSibling(highest.key) - let after - - // If there's a previous node, and we're at the start of the current node, - // and the selection encompasses the entire current node, it won't exist after - // deleting, so we need to update the selection's keys. - if ( - previous && - startOffset == 0 && - (endKey != startKey || endOffset == startText.length) - ) { - - // If the nodes on either sides are text nodes, they will end up being - // combined, so we need to set the selection to right in between them. - if (previous.kind == 'text' && next && next.kind == 'text') { - after = selection.merge({ - anchorKey: previous.key, - anchorOffset: previous.length, - focusKey: previous.key, - focusOffset: previous.length - }) - } - - // Otherwise, if only the previous node is a text node, it won't be merged, - // so collapse to the end of it. - else if (previous.kind == 'text') { - after = selection.collapseToEndOf(previous) - } - - // Otherwise, if the previous node isn't a text node, we need to get the - // last text node inside of it and collapse to the end of that. - else { - const last = previous.getLastText() - after = selection.collapseToEndOf(last) - } - } - - // Otherwise, if the inline is an online child - - // Otherwise simply collapse the selection. - else { - after = selection.collapseToStart() - } - transform - .unsetSelection() + .snapshotSelection() .deleteAtRange(selection) - .moveTo(after) + // Ensure that the selection is collapsed to the start, because in certain + // cases when deleting across inline nodes this isn't guaranteed. + .collapseToStart() + .snapshotSelection() } /** diff --git a/src/transforms/index.js b/src/transforms/index.js index 3c0205f36..6ce9e61cf 100644 --- a/src/transforms/index.js +++ b/src/transforms/index.js @@ -133,6 +133,7 @@ import { moveToRangeOf, unsetMarks, unsetSelection, + snapshotSelection, } from './on-selection' /** @@ -288,6 +289,7 @@ export default { moveToRangeOf, unsetMarks, unsetSelection, + snapshotSelection, /** * History. diff --git a/src/transforms/on-selection.js b/src/transforms/on-selection.js index 8aac5e4f8..9eb177dbc 100644 --- a/src/transforms/on-selection.js +++ b/src/transforms/on-selection.js @@ -412,6 +412,18 @@ export function unsetMarks(transform) { transform.setSelectionOperation({ marks: null }) } +/** + * Snapshot the current selection. + * + * @param {Transform} transform + */ + +export function snapshotSelection(transform) { + const { state } = transform + const { selection } = state + transform.setSelectionOperation(selection, { snapshot: true }) +} + /** * Unset the selection, removing an association to a node. * diff --git a/src/transforms/operations.js b/src/transforms/operations.js index 25413ff23..923919192 100644 --- a/src/transforms/operations.js +++ b/src/transforms/operations.js @@ -352,7 +352,7 @@ export function setNodeOperation(transform, path, properties) { * @param {Mixed} selection */ -export function setSelectionOperation(transform, properties) { +export function setSelectionOperation(transform, properties, options = {}) { properties = Normalize.selectionProperties(properties) const { state } = transform @@ -364,7 +364,7 @@ export function setSelectionOperation(transform, properties) { // create a dictionary of the previous values for all of the properties that // are being changed, for the inverse operation. for (const k in properties) { - if (properties[k] == selection[k]) continue + if (!options.snapshot && properties[k] == selection[k]) continue props[k] = properties[k] prevProps[k] = selection[k] }