mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-30 10:29:48 +02:00
This commit is contained in:
@@ -85,7 +85,7 @@ Changes.deleteAtRange = (change, range, options = {}) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// If it's a hanging selection, nudge it back to end in the previous text.
|
// If it's a hanging selection, nudge it back to end in the previous text.
|
||||||
if (isHanging) {
|
if (isHanging && isEndVoid) {
|
||||||
const prevText = document.getPreviousText(endKey)
|
const prevText = document.getPreviousText(endKey)
|
||||||
endKey = prevText.key
|
endKey = prevText.key
|
||||||
endOffset = prevText.text.length
|
endOffset = prevText.text.length
|
||||||
@@ -131,7 +131,7 @@ Changes.deleteAtRange = (change, range, options = {}) => {
|
|||||||
// If the start and end key are the same, and it was a hanging selection, we
|
// If the start and end key are the same, and it was a hanging selection, we
|
||||||
// can just remove the entire block.
|
// can just remove the entire block.
|
||||||
if (startKey == endKey && isHanging) {
|
if (startKey == endKey && isHanging) {
|
||||||
change.removeNodeByKey(startBlock.key)
|
change.removeNodeByKey(startBlock.key, { normalize })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,57 +144,97 @@ Changes.deleteAtRange = (change, range, options = {}) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we need to remove more than one node, so first split at the
|
// Otherwise, we need to recursively remove text and nodes inside the start
|
||||||
// range edges within a common ancestor, without normalizing. This makes it
|
// block after the start offset and inside the end block before the end
|
||||||
// easy, because we can then just remove every node inside the split.
|
// offset. Then remove any blocks that are in between the start and end
|
||||||
document = change.state.document
|
// blocks. Then finally merge the start and end nodes.
|
||||||
let ancestor = document.getCommonAncestor(startKey, endKey)
|
else {
|
||||||
let startChild = ancestor.getFurthestAncestor(startKey)
|
startBlock = document.getClosestBlock(startKey)
|
||||||
let endChild = ancestor.getFurthestAncestor(endKey)
|
endBlock = document.getClosestBlock(endKey)
|
||||||
change.splitDescendantsByKey(startChild.key, startKey, startOffset, { normalize: false })
|
const startText = document.getNode(startKey)
|
||||||
change.splitDescendantsByKey(endChild.key, endKey, endOffset, { normalize: false })
|
const endText = document.getNode(endKey)
|
||||||
|
const startLength = startText.text.length - startOffset
|
||||||
|
|
||||||
// Refresh the variables after the split.
|
const ancestor = document.getCommonAncestor(startKey, endKey)
|
||||||
document = change.state.document
|
const startChild = ancestor.getFurthestAncestor(startKey)
|
||||||
ancestor = document.getCommonAncestor(startKey, endKey)
|
const endChild = ancestor.getFurthestAncestor(endKey)
|
||||||
startChild = ancestor.getFurthestAncestor(startKey)
|
|
||||||
endChild = ancestor.getFurthestAncestor(endKey)
|
|
||||||
|
|
||||||
// Determine which are the middle nodes.
|
const startParent = document.getParent(startBlock.key)
|
||||||
const nextText = document.getNextText(endKey)
|
const startParentIndex = startParent.nodes.indexOf(startBlock)
|
||||||
const startIndex = ancestor.nodes.indexOf(startChild)
|
|
||||||
const endIndex = ancestor.nodes.indexOf(endChild)
|
|
||||||
const middles = ancestor.nodes.slice(startIndex + 1, endIndex + 1)
|
|
||||||
startBlock = document.getClosestBlock(startKey)
|
|
||||||
endBlock = document.getClosestBlock(nextText.key)
|
|
||||||
|
|
||||||
// Remove all of the middle nodes, between the splits.
|
let child
|
||||||
middles.forEach((child) => {
|
|
||||||
change.removeNodeByKey(child.key, { normalize: false })
|
|
||||||
})
|
|
||||||
|
|
||||||
// If the start and end blocks are different, and the selection was hanging,
|
// Iterate through all of the nodes in the tree after the start text node
|
||||||
// remove the start block and the orphaned end block.
|
// but inside the end child, and remove them.
|
||||||
if (startBlock.key != endBlock.key && isHanging) {
|
child = startText
|
||||||
change.removeNodeByKey(startBlock.key, { normalize: false })
|
|
||||||
change.removeNodeByKey(endBlock.key, { normalize: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, move all of the nodes from the end block into the start block.
|
while (child.key != startChild.key) {
|
||||||
else if (startBlock.key != endBlock.key) {
|
const parent = document.getParent(child.key)
|
||||||
endBlock.nodes.forEach((child, i) => {
|
const index = parent.nodes.indexOf(child)
|
||||||
const newKey = startBlock.key
|
const afters = parent.nodes.slice(index + 1)
|
||||||
const newIndex = startBlock.nodes.size + i
|
|
||||||
change.moveNodeByKey(child.key, newKey, newIndex, { normalize: false })
|
afters.reverse().forEach((node) => {
|
||||||
|
change.removeNodeByKey(node.key, { normalize: false })
|
||||||
|
})
|
||||||
|
|
||||||
|
child = parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all of the middle children.
|
||||||
|
const startChildIndex = ancestor.nodes.indexOf(startChild)
|
||||||
|
const endChildIndex = ancestor.nodes.indexOf(endChild)
|
||||||
|
const middles = ancestor.nodes.slice(startChildIndex + 1, endChildIndex)
|
||||||
|
|
||||||
|
middles.reverse().forEach((node) => {
|
||||||
|
change.removeNodeByKey(node.key, { normalize: false })
|
||||||
})
|
})
|
||||||
|
|
||||||
// Remove parents of endBlock as long as they have a single child.
|
// Remove the nodes before the end text node in the tree.
|
||||||
const lonely = document.getFurthestOnlyChildAncestor(endBlock.key) || endBlock
|
child = endText
|
||||||
change.removeNodeByKey(lonely.key, { normalize: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalize) {
|
while (child.key != endChild.key) {
|
||||||
change.normalizeNodeByKey(ancestor.key, SCHEMA)
|
const parent = document.getParent(child.key)
|
||||||
|
const index = parent.nodes.indexOf(child)
|
||||||
|
const befores = parent.nodes.slice(0, index)
|
||||||
|
|
||||||
|
befores.reverse().forEach((node) => {
|
||||||
|
change.removeNodeByKey(node.key, { normalize: false })
|
||||||
|
})
|
||||||
|
|
||||||
|
child = parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any overlapping text content from the leaf text nodes.
|
||||||
|
change.removeTextByKey(startKey, startOffset, startLength, { normalize: false })
|
||||||
|
change.removeTextByKey(endKey, 0, endOffset, { normalize: false })
|
||||||
|
|
||||||
|
// If the start and end blocks aren't the same, move and merge the end block
|
||||||
|
// into the start block.
|
||||||
|
if (startBlock.key != endBlock.key) {
|
||||||
|
document = change.state.document
|
||||||
|
const lonely = document.getFurthestOnlyChildAncestor(endBlock.key)
|
||||||
|
|
||||||
|
// Move the end block to be right after the start block.
|
||||||
|
change.moveNodeByKey(endBlock.key, startParent.key, startParentIndex + 1)
|
||||||
|
|
||||||
|
// If the selection is hanging, just remove the start block, otherwise
|
||||||
|
// merge the end block into it.
|
||||||
|
if (isHanging) {
|
||||||
|
change.removeNodeByKey(startBlock.key, { normalize: false })
|
||||||
|
} else {
|
||||||
|
change.mergeNodeByKey(endBlock.key, { normalize: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nested empty blocks are left over above the end block, remove them.
|
||||||
|
if (lonely) {
|
||||||
|
change.removeNodeByKey(lonely.key, { normalize: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we should normalize, do it now after everything.
|
||||||
|
if (normalize) {
|
||||||
|
change.normalizeNodeByKey(ancestor.key, SCHEMA)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user