1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-17 04:34:00 +02:00

fix deleteAtRange to split only to common ancestor

This commit is contained in:
Ian Storm Taylor
2016-07-28 17:17:18 -07:00
parent 52c29d8143
commit dfcd791b3b
8 changed files with 169 additions and 17 deletions

View File

@@ -296,6 +296,32 @@ const Node = {
return this.nodes.find(node => node.key == key)
},
/**
* Get the common ancestor of nodes `one` and `two` by keys.
*
* @param {String or Node} one
* @param {String or Node} two
* @return {Node}
*/
getCommonAncestor(one, two) {
this.assertDescendant(one)
this.assertDescendant(two)
let ancestors = new List()
let oneParent = this.getParent(one)
let twoParent = this.getParent(two)
while (oneParent) {
ancestors = ancestors.push(oneParent)
oneParent = this.getParent(oneParent)
}
while (twoParent) {
if (ancestors.includes(twoParent)) return twoParent
twoParent = this.getParent(twoParent)
}
},
/**
* Get a descendant node by `key`.
*

View File

@@ -86,42 +86,50 @@ const Transforms = {
// Split the blocks and determine the edge boundaries.
const start = range.collapseToStart()
const end = range.collapseToEnd()
node = node.splitBlockAtRange(start, Infinity)
node = node.splitBlockAtRange(end, Infinity)
let ancestor = node.getCommonAncestor(startKey, endKey)
const isAncestor = ancestor == node
const startText = node.getDescendant(startKey)
const startEdgeText = node.getNextText(startKey)
ancestor = ancestor.splitBlockAtRange(start, Infinity)
ancestor = ancestor.splitBlockAtRange(end, Infinity)
const endText = node.getNextText(endKey)
const endEdgeText = node.getDescendant(endKey)
const startText = ancestor.getDescendant(startKey)
const startEdgeText = ancestor.getNextText(startKey)
const endText = ancestor.getNextText(endKey)
const endEdgeText = ancestor.getDescendant(endKey)
// Remove the new blocks inside the edges.
const startEdgeBlock = node.getFurthestBlock(startEdgeText)
const endEdgeBlock = node.getFurthestBlock(endEdgeText)
const startEdgeBlock = ancestor.getFurthestBlock(startEdgeText)
const endEdgeBlock = ancestor.getFurthestBlock(endEdgeText)
const nodes = node.nodes
const nodes = ancestor.nodes
.takeUntil(n => n == startEdgeBlock)
.concat(node.nodes.skipUntil(n => n == endEdgeBlock).rest())
.concat(ancestor.nodes.skipUntil(n => n == endEdgeBlock).rest())
node = node.merge({ nodes })
ancestor = ancestor.merge({ nodes })
// Take the end edge's split text and move it to the start edge.
let startBlock = node.getClosestBlock(startText)
let endChild = node.getFurthestInline(endText) || endText
let startBlock = ancestor.getClosestBlock(startText)
let endChild = ancestor.getFurthestInline(endText) || endText
const startNodes = startBlock.nodes.push(endChild)
startBlock = startBlock.merge({ nodes: startNodes })
node = node.updateDescendant(startBlock)
ancestor = ancestor.updateDescendant(startBlock)
// While the end child is an only child, remove the block it's in.
let endParent = node.getClosestBlock(endChild)
let endParent = ancestor.getClosestBlock(endChild)
while (endParent && endParent.nodes.size == 1) {
endChild = endParent
endParent = node.getClosestBlock(endParent)
endParent = ancestor.getClosestBlock(endParent)
}
node = node.removeDescendant(endChild)
ancestor = ancestor.removeDescendant(endChild)
// Update the node.
node = isAncestor
? ancestor
: node.updateDescendant(ancestor)
// Normalize the adjacent text nodes.
return node.normalize()

View File

@@ -0,0 +1,19 @@
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.get(0)
const second = texts.get(1)
const third = texts.get(2)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: first.length,
focusKey: second.key,
focusOffset: 0
})
return state
.transform()
.deleteAtRange(range)
.apply()
}

View File

@@ -0,0 +1,20 @@
nodes:
- kind: block
type: list
nodes:
- kind: block
type: item
nodes:
- kind: text
text: one
- kind: block
type: item
nodes:
- kind: text
text: two
- kind: block
type: item
nodes:
- kind: text
text: three

View File

@@ -0,0 +1,15 @@
nodes:
- kind: block
type: list
nodes:
- kind: block
type: item
nodes:
- kind: text
text: onetwo
- kind: block
type: item
nodes:
- kind: text
text: three

View File

@@ -0,0 +1,29 @@
import assert from 'assert'
export default function (state) {
const { document, selection } = state
const texts = document.getTexts()
const first = texts.get(0)
const second = texts.get(1)
const third = texts.get(2)
const range = selection.merge({
anchorKey: first.key,
anchorOffset: first.length,
focusKey: second.key,
focusOffset: 0
})
const next = state
.transform()
.moveTo(range)
.delete()
.apply()
assert.deepEqual(
next.selection.toJS(),
range.collapseToStart().toJS()
)
return next
}

View File

@@ -0,0 +1,20 @@
nodes:
- kind: block
type: list
nodes:
- kind: block
type: item
nodes:
- kind: text
text: one
- kind: block
type: item
nodes:
- kind: text
text: two
- kind: block
type: item
nodes:
- kind: text
text: three

View File

@@ -0,0 +1,15 @@
nodes:
- kind: block
type: list
nodes:
- kind: block
type: item
nodes:
- kind: text
text: onetwo
- kind: block
type: item
nodes:
- kind: text
text: three