mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-15 19:54:02 +02:00
Fix improper selection after insertFragment (#2976)
* Fix typo & remove useless check * No need to check the end of the selection, as this part is called after the `deleteExpanded` call. Selection is collapsed at this point. * Fix insertFragment selection not place properly
This commit is contained in:
committed by
Ian Storm Taylor
parent
3ed981aedf
commit
2ea6d40ad0
@@ -735,7 +735,7 @@ Commands.insertFragmentAtRange = (editor, range, fragment) => {
|
||||
|
||||
// Regenerate the keys for all of the fragments nodes, so that they're
|
||||
// guaranteed not to collide with the existing keys in the document. Otherwise
|
||||
// they will be rengerated automatically and we won't have an easy way to
|
||||
// they will be regenerated automatically and we won't have an easy way to
|
||||
// reference them.
|
||||
fragment = fragment.mapDescendants(child => child.regenerateKey())
|
||||
|
||||
|
@@ -252,46 +252,41 @@ Commands.insertFragment = (editor, fragment) => {
|
||||
|
||||
let { value } = editor
|
||||
let { document, selection } = value
|
||||
const { start, end } = selection
|
||||
const { startText, endText, startInline } = value
|
||||
const lastText = fragment.getLastText()
|
||||
const lastInline = fragment.getClosestInline(lastText.key)
|
||||
const lastBlock = fragment.getClosestBlock(lastText.key)
|
||||
const firstChild = fragment.nodes.first()
|
||||
const lastChild = fragment.nodes.last()
|
||||
const { start } = selection
|
||||
const keys = Array.from(document.texts(), ([text]) => text.key)
|
||||
const isAppending =
|
||||
!startInline ||
|
||||
(start.isAtStartOfNode(startText) || end.isAtStartOfNode(startText)) ||
|
||||
(start.isAtEndOfNode(endText) || end.isAtEndOfNode(endText))
|
||||
|
||||
const isInserting =
|
||||
firstChild.hasBlockChildren() || lastChild.hasBlockChildren()
|
||||
|
||||
editor.insertFragmentAtRange(selection, fragment)
|
||||
value = editor.value
|
||||
document = value.document
|
||||
|
||||
const newTexts = document.getTexts().filter(n => !keys.includes(n.key))
|
||||
const newText = isAppending ? newTexts.last() : newTexts.takeLast(2).first()
|
||||
if (newTexts.size === 0) return
|
||||
const fragmentLength = fragment.text.length
|
||||
|
||||
if (newText && (lastInline || isInserting)) {
|
||||
editor.moveToEndOfNode(newText)
|
||||
} else if (newText) {
|
||||
// The position within the last text node needs to be calculated. This is the length
|
||||
// of all text nodes within the last block, but if the last block contains inline nodes,
|
||||
// these have to be skipped.
|
||||
const { nodes } = lastBlock
|
||||
const lastIndex = nodes.findLastIndex(
|
||||
node => node && node.object === 'inline'
|
||||
)
|
||||
const remainingTexts = nodes.takeLast(nodes.size - lastIndex - 1)
|
||||
const remainingTextLength = remainingTexts.reduce(
|
||||
(acc, val) => acc + val.text.length,
|
||||
0
|
||||
)
|
||||
editor.moveToStartOfNode(newText).moveForward(remainingTextLength)
|
||||
// Either startText is still here, or we want the first un-previously known text
|
||||
const startText = document.getNode(start.key) || newTexts.first()
|
||||
// We want the last un-previously known text
|
||||
let endText = newTexts.last() || startText
|
||||
|
||||
if (startText === endText) {
|
||||
editor.moveTo(endText.key, fragmentLength)
|
||||
return
|
||||
}
|
||||
|
||||
// Everything will be calculated relative to the first common ancestor to optimize speed
|
||||
const parent = document.getCommonAncestor(startText.key, endText.key)
|
||||
|
||||
const startOffset =
|
||||
parent.getOffset(startText.key) +
|
||||
(start.key === startText.key ? start.offset : 0)
|
||||
|
||||
// endText might not be the last un-previously known text node, so we precisely pick it by offset
|
||||
endText = parent.getTextAtOffset(startOffset + fragmentLength - 1) || endText
|
||||
|
||||
editor.moveTo(
|
||||
endText.key,
|
||||
startOffset + fragmentLength - parent.getOffset(endText.key)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,41 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../../../helpers/h'
|
||||
|
||||
export default function(editor) {
|
||||
editor.insertFragment(
|
||||
<document>
|
||||
<paragraph>
|
||||
<b>b</b>
|
||||
<u>u</u>
|
||||
<i>i</i>
|
||||
</paragraph>
|
||||
</document>
|
||||
)
|
||||
}
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
wo<cursor />rd
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
wo
|
||||
<b>b</b>
|
||||
<u>u</u>
|
||||
<i>
|
||||
i<cursor />
|
||||
</i>
|
||||
rd
|
||||
</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
@@ -29,11 +29,11 @@ export const output = (
|
||||
<paragraph>wo</paragraph>
|
||||
<quote>
|
||||
<quote>one</quote>
|
||||
<quote>two</quote>
|
||||
<quote>
|
||||
two<cursor />
|
||||
</quote>
|
||||
</quote>
|
||||
<paragraph>
|
||||
rd<cursor />
|
||||
</paragraph>
|
||||
<paragraph>rd</paragraph>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
@@ -0,0 +1,41 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../../../helpers/h'
|
||||
|
||||
export default function(editor) {
|
||||
editor.insertFragment(
|
||||
<document>
|
||||
<paragraph>
|
||||
<inline type="link">bar</inline>
|
||||
</paragraph>
|
||||
</document>
|
||||
)
|
||||
}
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<code>
|
||||
<paragraph>
|
||||
Foo<cursor />baz
|
||||
</paragraph>
|
||||
</code>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<value>
|
||||
<document>
|
||||
<code>
|
||||
<paragraph>
|
||||
Foo
|
||||
<inline type="link">
|
||||
bar<cursor />
|
||||
</inline>
|
||||
baz
|
||||
</paragraph>
|
||||
</code>
|
||||
</document>
|
||||
</value>
|
||||
)
|
@@ -0,0 +1,41 @@
|
||||
/** @jsx h */
|
||||
|
||||
import h from '../../../helpers/h'
|
||||
|
||||
export default function(editor) {
|
||||
editor.insertFragment(
|
||||
<document>
|
||||
<paragraph>
|
||||
<b>bar</b>
|
||||
</paragraph>
|
||||
</document>
|
||||
)
|
||||
}
|
||||
|
||||
export const input = (
|
||||
<value>
|
||||
<document>
|
||||
<code>
|
||||
<paragraph>
|
||||
Foo<cursor />baz
|
||||
</paragraph>
|
||||
</code>
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<value>
|
||||
<document>
|
||||
<code>
|
||||
<paragraph>
|
||||
Foo
|
||||
<b>
|
||||
bar<cursor />
|
||||
</b>
|
||||
baz
|
||||
</paragraph>
|
||||
</code>
|
||||
</document>
|
||||
</value>
|
||||
)
|
@@ -29,8 +29,9 @@ export const output = (
|
||||
<document>
|
||||
<paragraph>
|
||||
<link>wo</link>
|
||||
<hashtag>fragment</hashtag>
|
||||
<cursor />
|
||||
<hashtag>
|
||||
fragment<cursor />
|
||||
</hashtag>
|
||||
<link>rd</link>
|
||||
</paragraph>
|
||||
</document>
|
||||
|
@@ -31,7 +31,7 @@ export const output = (
|
||||
<quote>
|
||||
<paragraph>woone</paragraph>
|
||||
<quote>
|
||||
tword<cursor />
|
||||
two<cursor />rd
|
||||
</quote>
|
||||
</quote>
|
||||
</document>
|
||||
|
Reference in New Issue
Block a user