mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-18 21:21:21 +02:00
fix getFragmentAtRange to use paths properly (#2012)
#### Is this adding or improving a _feature_ or fixing a _bug_? Bug. #### What's the new behavior? Fixes `Node.getFragmentAtRange` to use the proper argument signature when calling `Node.splitNode`, and refactors it to use paths for all of its logic. #### Have you checked that...? <!-- Please run through this checklist for your pull request: --> * [x] The new code matches the existing patterns and styles. * [x] The tests pass with `yarn test`. * [x] The linter passes with `yarn lint`. (Fix errors with `yarn prettier`.) * [x] The relevant examples still work. (Run examples with `yarn watch`.) #### Does this fix any issues or need any specific reviewers? Fixes: #2009
This commit is contained in:
@@ -673,64 +673,35 @@ class Node {
|
|||||||
|
|
||||||
getFragmentAtRange(range) {
|
getFragmentAtRange(range) {
|
||||||
range = range.normalize(this)
|
range = range.normalize(this)
|
||||||
if (range.isUnset) return Document.create()
|
|
||||||
|
|
||||||
|
if (range.isUnset) {
|
||||||
|
return Document.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
const { startPath, startOffset, endPath, endOffset } = range
|
||||||
let node = this
|
let node = this
|
||||||
|
let targetPath = endPath
|
||||||
|
let targetPosition = endOffset
|
||||||
|
let mode = 'end'
|
||||||
|
|
||||||
// Make sure the children exist.
|
while (targetPath.size) {
|
||||||
const { startKey, startOffset, endKey, endOffset } = range
|
const index = targetPath.last()
|
||||||
const startText = node.assertDescendant(startKey)
|
node = node.splitNode(targetPath, targetPosition)
|
||||||
const endText = node.assertDescendant(endKey)
|
targetPosition = index + 1
|
||||||
|
targetPath = PathUtils.lift(targetPath)
|
||||||
|
|
||||||
// Split at the start and end.
|
if (!targetPath.size && mode === 'end') {
|
||||||
let child = startText
|
targetPath = startPath
|
||||||
let previous
|
targetPosition = startOffset
|
||||||
let parent
|
mode = 'start'
|
||||||
|
}
|
||||||
while ((parent = node.getParent(child.key))) {
|
|
||||||
const index = parent.nodes.indexOf(child)
|
|
||||||
const position =
|
|
||||||
child.object == 'text' ? startOffset : child.nodes.indexOf(previous)
|
|
||||||
|
|
||||||
parent = parent.splitNode(index, position)
|
|
||||||
node = node.replaceNode(parent.key, parent)
|
|
||||||
previous = parent.nodes.get(index + 1)
|
|
||||||
child = parent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child = startKey == endKey ? node.getNextText(startKey) : endText
|
const startIndex = startPath.first() + 1
|
||||||
|
const endIndex = endPath.first() + 2
|
||||||
while ((parent = node.getParent(child.key))) {
|
|
||||||
const index = parent.nodes.indexOf(child)
|
|
||||||
const position =
|
|
||||||
child.object == 'text'
|
|
||||||
? startKey == endKey ? endOffset - startOffset : endOffset
|
|
||||||
: child.nodes.indexOf(previous)
|
|
||||||
|
|
||||||
parent = parent.splitNode(index, position)
|
|
||||||
node = node.replaceNode(parent.key, parent)
|
|
||||||
previous = parent.nodes.get(index + 1)
|
|
||||||
child = parent
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the start and end nodes.
|
|
||||||
const startNode = node.getNextSibling(
|
|
||||||
node.getFurthestAncestor(startKey).key
|
|
||||||
)
|
|
||||||
const endNode =
|
|
||||||
startKey == endKey
|
|
||||||
? node.getNextSibling(
|
|
||||||
node.getNextSibling(node.getFurthestAncestor(endKey).key).key
|
|
||||||
)
|
|
||||||
: node.getNextSibling(node.getFurthestAncestor(endKey).key)
|
|
||||||
|
|
||||||
// Get children range of nodes from start to end nodes
|
|
||||||
const startIndex = node.nodes.indexOf(startNode)
|
|
||||||
const endIndex = node.nodes.indexOf(endNode)
|
|
||||||
const nodes = node.nodes.slice(startIndex, endIndex)
|
const nodes = node.nodes.slice(startIndex, endIndex)
|
||||||
|
const fragment = Document.create({ nodes })
|
||||||
// Return a new document fragment.
|
return fragment
|
||||||
return Document.create({ nodes })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
28
packages/slate/test/models/node/get-fragment-at-range.js
Normal file
28
packages/slate/test/models/node/get-fragment-at-range.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
|
||||||
|
import h from '../../helpers/h'
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
export default function() {
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
<paragraph>
|
||||||
|
one <anchor />two<focus /> three
|
||||||
|
</paragraph>
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
|
||||||
|
const { document, selection } = value
|
||||||
|
const actual = document.getFragmentAtRange(selection)
|
||||||
|
const expected = (
|
||||||
|
<document>
|
||||||
|
<paragraph>two</paragraph>
|
||||||
|
</document>
|
||||||
|
)
|
||||||
|
|
||||||
|
const a = actual.toJSON()
|
||||||
|
const e = expected.toJSON()
|
||||||
|
assert.deepEqual(a, e)
|
||||||
|
}
|
Reference in New Issue
Block a user