Skip to content

Commit

Permalink
Fix improper selection after insertFragment (ianstormtaylor#2976)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Calyhre authored and ianstormtaylor committed Aug 22, 2019
1 parent 3ed981a commit 2ea6d40
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 40 deletions.
2 changes: 1 addition & 1 deletion packages/slate/src/commands/at-range.js
Original file line number Diff line number Diff line change
Expand Up @@ -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())

Expand Down
59 changes: 27 additions & 32 deletions packages/slate/src/commands/with-intent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (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)
if (newTexts.size === 0) return
const fragmentLength = fragment.text.length

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

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
)
Original file line number Diff line number Diff line change
Expand Up @@ -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>
)
Original file line number Diff line number Diff line change
@@ -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>
)
Original file line number Diff line number Diff line change
@@ -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>
)
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const output = (
<quote>
<paragraph>woone</paragraph>
<quote>
tword<cursor />
two<cursor />rd
</quote>
</quote>
</document>
Expand Down

0 comments on commit 2ea6d40

Please sign in to comment.