diff --git a/src/transforms/at-range.js b/src/transforms/at-range.js index e5ed5455a..9f0a54747 100644 --- a/src/transforms/at-range.js +++ b/src/transforms/at-range.js @@ -66,8 +66,8 @@ export function deleteAtRange(transform, range, options = {}) { let ancestor = document.getCommonAncestor(startKey, endKey) let startChild = ancestor.getHighestChild(startKey) let endChild = ancestor.getHighestChild(endKey) - const startOff = startChild.getOffset(startKey) + startOffset - const endOff = endChild.getOffset(endKey) + endOffset + const startOff = (startChild.key === startKey ? 0 : startChild.getOffset(startKey)) + startOffset + const endOff = (endChild.key === endKey ? 0 : endChild.getOffset(endKey)) + endOffset transform = transform .splitNodeByKey(startChild.key, startOff, { normalize: false }) @@ -78,30 +78,37 @@ export function deleteAtRange(transform, range, options = {}) { ancestor = document.getCommonAncestor(startKey, endKey) const startBlock = document.getClosestBlock(startKey) const endBlock = document.getClosestBlock(document.getNextText(endKey)) - startChild = ancestor.getHighestChild(startBlock) - endChild = ancestor.getHighestChild(endBlock) + startChild = ancestor.getHighestChild(startKey) + endChild = ancestor.getHighestChild(endKey) const startIndex = ancestor.nodes.indexOf(startChild) const endIndex = ancestor.nodes.indexOf(endChild) - const middles = ancestor.nodes.slice(startIndex + 1, endIndex) + const middles = ancestor.nodes.slice(startIndex + 1, endIndex + 1) - middles.forEach((child) => { - transform.removeNodeByKey(child.key, { normalize: false }) - }) + if (middles.size) { + // remove first nodes directly so the document is not normalized + middles.butLast().forEach(child => { + transform.removeNodeOperation(transform.state.document.getPath(child.key)) + }) - endBlock.nodes.forEach((child, i) => { - const newKey = startBlock.key - const newIndex = startBlock.nodes.size + i - transform.moveNodeByKey(child.key, newKey, newIndex, { normalize: false }) - }) + // remove last node so the document is normalized + transform.removeNodeByKey(middles.last().key) + } - const lonely = document.getFurthest(endBlock, p => p.nodes.size == 1) || endBlock - transform.removeNodeByKey(lonely.key, { normalize: false }) + if (startBlock.key !== endBlock.key) { + endBlock.nodes.forEach((child, i) => { + const newKey = startBlock.key + const newIndex = startBlock.nodes.size + i + transform.moveNodeByKey(child.key, newKey, newIndex) + }) + + const lonely = document.getFurthest(endBlock, p => p.nodes.size == 1) || endBlock + transform.removeNodeByKey(lonely.key) + } if (normalize) { transform.normalizeNodeByKey(ancestor.key) } - return transform } diff --git a/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/index.js b/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/index.js new file mode 100644 index 000000000..4fb524e62 --- /dev/null +++ b/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/index.js @@ -0,0 +1,18 @@ + +export default function (state) { + const { document, selection } = state + const texts = document.getTexts() + const first = texts.first() + const last = texts.last() + const range = selection.merge({ + anchorKey: first.key, + anchorOffset: 1, + focusKey: last.key, + focusOffset: last.length - 1 + }) + + return state + .transform() + .deleteAtRange(range) + .apply() +} diff --git a/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/input.yaml b/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/input.yaml new file mode 100644 index 000000000..1a7131b75 --- /dev/null +++ b/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/input.yaml @@ -0,0 +1,14 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: before + - kind: inline + type: link + nodes: + - kind: text + text: word + - kind: text + text: after diff --git a/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/output.yaml b/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/output.yaml new file mode 100644 index 000000000..33577c937 --- /dev/null +++ b/test/transforms/fixtures/at-range/delete-at-range/across-inline-texts/output.yaml @@ -0,0 +1,7 @@ + +nodes: + - kind: block + type: paragraph + nodes: + - kind: text + text: "br"