1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-02-01 05:16:10 +01: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:
Ian Storm Taylor 2018-07-31 16:26:52 -07:00 committed by GitHub
parent 638d3e8e61
commit 06bca539dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 51 deletions

View File

@ -673,64 +673,35 @@ class Node {
getFragmentAtRange(range) {
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 targetPath = endPath
let targetPosition = endOffset
let mode = 'end'
// Make sure the children exist.
const { startKey, startOffset, endKey, endOffset } = range
const startText = node.assertDescendant(startKey)
const endText = node.assertDescendant(endKey)
while (targetPath.size) {
const index = targetPath.last()
node = node.splitNode(targetPath, targetPosition)
targetPosition = index + 1
targetPath = PathUtils.lift(targetPath)
// Split at the start and end.
let child = startText
let previous
let parent
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
if (!targetPath.size && mode === 'end') {
targetPath = startPath
targetPosition = startOffset
mode = 'start'
}
}
child = startKey == endKey ? node.getNextText(startKey) : endText
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 startIndex = startPath.first() + 1
const endIndex = endPath.first() + 2
const nodes = node.nodes.slice(startIndex, endIndex)
// Return a new document fragment.
return Document.create({ nodes })
const fragment = Document.create({ nodes })
return fragment
}
/**

View 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)
}