diff --git a/packages/slate/src/commands/at-range.js b/packages/slate/src/commands/at-range.js
index 1a13fa9a44..e26f8c032e 100644
--- a/packages/slate/src/commands/at-range.js
+++ b/packages/slate/src/commands/at-range.js
@@ -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())
diff --git a/packages/slate/src/commands/with-intent.js b/packages/slate/src/commands/with-intent.js
index 911e11f77c..bcfcae2f31 100644
--- a/packages/slate/src/commands/with-intent.js
+++ b/packages/slate/src/commands/with-intent.js
@@ -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)
+ )
}
/**
diff --git a/packages/slate/test/commands/at-current-range/insert-fragment/fragment-multiple-marks.js b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-multiple-marks.js
new file mode 100644
index 0000000000..f1679d26b1
--- /dev/null
+++ b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-multiple-marks.js
@@ -0,0 +1,41 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export default function(editor) {
+ editor.insertFragment(
+
+
+ b
+ u
+ i
+
+
+ )
+}
+
+export const input = (
+
+
+
+ word
+
+
+
+)
+
+export const output = (
+
+
+
+ wo
+ b
+ u
+
+ i
+
+ rd
+
+
+
+)
diff --git a/packages/slate/test/commands/at-current-range/insert-fragment/fragment-nested-blocks.js b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-nested-blocks.js
index 872c722c1d..1c0b4b1346 100644
--- a/packages/slate/test/commands/at-current-range/insert-fragment/fragment-nested-blocks.js
+++ b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-nested-blocks.js
@@ -29,11 +29,11 @@ export const output = (
wo
one
- two
+
+ two
+
-
- rd
-
+ rd
)
diff --git a/packages/slate/test/commands/at-current-range/insert-fragment/fragment-single-inline.js b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-single-inline.js
new file mode 100644
index 0000000000..6e23dd4828
--- /dev/null
+++ b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-single-inline.js
@@ -0,0 +1,41 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export default function(editor) {
+ editor.insertFragment(
+
+
+ bar
+
+
+ )
+}
+
+export const input = (
+
+
+
+
+ Foobaz
+
+
+
+
+)
+
+export const output = (
+
+
+
+
+ Foo
+
+ bar
+
+ baz
+
+
+
+
+)
diff --git a/packages/slate/test/commands/at-current-range/insert-fragment/fragment-single-mark.js b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-single-mark.js
new file mode 100644
index 0000000000..bb239535e1
--- /dev/null
+++ b/packages/slate/test/commands/at-current-range/insert-fragment/fragment-single-mark.js
@@ -0,0 +1,41 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export default function(editor) {
+ editor.insertFragment(
+
+
+ bar
+
+
+ )
+}
+
+export const input = (
+
+
+
+
+ Foobaz
+
+
+
+
+)
+
+export const output = (
+
+
+
+
+ Foo
+
+ bar
+
+ baz
+
+
+
+
+)
diff --git a/packages/slate/test/commands/at-current-range/insert-fragment/middle-inline-fragment-inline.js b/packages/slate/test/commands/at-current-range/insert-fragment/middle-inline-fragment-inline.js
index c4723fb980..629276bbc9 100644
--- a/packages/slate/test/commands/at-current-range/insert-fragment/middle-inline-fragment-inline.js
+++ b/packages/slate/test/commands/at-current-range/insert-fragment/middle-inline-fragment-inline.js
@@ -29,8 +29,9 @@ export const output = (
wo
- fragment
-
+
+ fragment
+
rd
diff --git a/packages/slate/test/commands/at-current-range/insert-fragment/nested-block-fragment-nested-blocks.js b/packages/slate/test/commands/at-current-range/insert-fragment/nested-block-fragment-nested-blocks.js
index 728a5794f4..da4bdb5a31 100644
--- a/packages/slate/test/commands/at-current-range/insert-fragment/nested-block-fragment-nested-blocks.js
+++ b/packages/slate/test/commands/at-current-range/insert-fragment/nested-block-fragment-nested-blocks.js
@@ -31,7 +31,7 @@ export const output = (
woone
- tword
+ tword