mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-22 06:53:25 +02:00
Implement "splitBlockAtRange" as a node method (#336)
This commit is contained in:
committed by
Ian Storm Taylor
parent
5d24e30f21
commit
2fa9edc8ae
@@ -458,6 +458,85 @@ const Node = {
|
|||||||
.getDepth(key, startAt + 1)
|
.getDepth(key, startAt + 1)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split a node by `path` at `offset`.
|
||||||
|
*
|
||||||
|
* @param {String} path
|
||||||
|
* @param {Number} offset
|
||||||
|
* @return {Node}
|
||||||
|
*/
|
||||||
|
|
||||||
|
splitNode(path, offset) {
|
||||||
|
let base = this
|
||||||
|
let node = base.assertPath(path)
|
||||||
|
let parent = base.getParent(node)
|
||||||
|
const isParent = base == parent
|
||||||
|
const index = parent.nodes.indexOf(node)
|
||||||
|
|
||||||
|
let child = node
|
||||||
|
let one
|
||||||
|
let two
|
||||||
|
|
||||||
|
if (node.kind != 'text') {
|
||||||
|
child = node.getTextAtOffset(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (child && child != parent) {
|
||||||
|
if (child.kind == 'text') {
|
||||||
|
const i = node.kind == 'text' ? offset : offset - node.getOffset(child)
|
||||||
|
const { characters } = child
|
||||||
|
const oneChars = characters.take(i)
|
||||||
|
const twoChars = characters.skip(i)
|
||||||
|
one = child.merge({ characters: oneChars })
|
||||||
|
two = child.merge({ characters: twoChars, key: uid() })
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
const { nodes } = child
|
||||||
|
const oneNodes = nodes.takeUntil(n => n.key == one.key).push(one)
|
||||||
|
const twoNodes = nodes.skipUntil(n => n.key == one.key).rest().unshift(two)
|
||||||
|
one = child.merge({ nodes: oneNodes })
|
||||||
|
two = child.merge({ nodes: twoNodes, key: uid() })
|
||||||
|
}
|
||||||
|
|
||||||
|
child = base.getParent(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent.removeNode(index)
|
||||||
|
parent = parent.insertNode(index, two)
|
||||||
|
parent = parent.insertNode(index, one)
|
||||||
|
base = isParent ? parent : base.updateDescendant(parent)
|
||||||
|
return base
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the block nodes at a `range`, to optional `height`.
|
||||||
|
*
|
||||||
|
* @param {Selection} range
|
||||||
|
* @param {Number} height (optional)
|
||||||
|
* @return {Node}
|
||||||
|
*/
|
||||||
|
|
||||||
|
splitBlockAtRange(range, height = 1) {
|
||||||
|
const { startKey, startOffset } = range
|
||||||
|
let base = this
|
||||||
|
let node = base.assertDescendant(startKey)
|
||||||
|
let parent = base.getClosestBlock(node)
|
||||||
|
let offset = startOffset
|
||||||
|
let h = 0
|
||||||
|
|
||||||
|
while (parent && parent.kind == 'block' && h < height) {
|
||||||
|
offset += parent.getOffset(node)
|
||||||
|
node = parent
|
||||||
|
parent = base.getClosestBlock(parent)
|
||||||
|
h++
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = base.getPath(node.key)
|
||||||
|
return this.splitNode(path, offset)
|
||||||
|
.normalize()
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a fragment of the node at a `range`.
|
* Get a fragment of the node at a `range`.
|
||||||
*
|
*
|
||||||
|
@@ -312,44 +312,9 @@ function setSelection(state, operation) {
|
|||||||
function splitNode(state, operation) {
|
function splitNode(state, operation) {
|
||||||
const { path, offset } = operation
|
const { path, offset } = operation
|
||||||
let { document } = state
|
let { document } = state
|
||||||
let node = document.assertPath(path)
|
|
||||||
let parent = document.getParent(node)
|
|
||||||
const isParent = document == parent
|
|
||||||
const index = parent.nodes.indexOf(node)
|
|
||||||
|
|
||||||
let child = node
|
document = document.splitNode(path, offset)
|
||||||
let one
|
|
||||||
let two
|
|
||||||
|
|
||||||
if (node.kind != 'text') {
|
|
||||||
child = node.getTextAtOffset(offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
while (child && child != parent) {
|
|
||||||
if (child.kind == 'text') {
|
|
||||||
const i = node.kind == 'text' ? offset : offset - node.getOffset(child)
|
|
||||||
const { characters } = child
|
|
||||||
const oneChars = characters.take(i)
|
|
||||||
const twoChars = characters.skip(i)
|
|
||||||
one = child.merge({ characters: oneChars })
|
|
||||||
two = child.merge({ characters: twoChars, key: uid() })
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
const { nodes } = child
|
|
||||||
const oneNodes = nodes.takeUntil(n => n.key == one.key).push(one)
|
|
||||||
const twoNodes = nodes.skipUntil(n => n.key == one.key).rest().unshift(two)
|
|
||||||
one = child.merge({ nodes: oneNodes })
|
|
||||||
two = child.merge({ nodes: twoNodes, key: uid() })
|
|
||||||
}
|
|
||||||
|
|
||||||
child = document.getParent(child)
|
|
||||||
}
|
|
||||||
|
|
||||||
parent = parent.removeNode(index)
|
|
||||||
parent = parent.insertNode(index, two)
|
|
||||||
parent = parent.insertNode(index, one)
|
|
||||||
document = isParent ? parent : document.updateDescendant(parent)
|
|
||||||
state = state.merge({ document })
|
state = state.merge({ document })
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user