diff --git a/packages/slate-react/src/utils/clone-fragment.js b/packages/slate-react/src/utils/clone-fragment.js index 64f33f195..b37c0b77f 100644 --- a/packages/slate-react/src/utils/clone-fragment.js +++ b/packages/slate-react/src/utils/clone-fragment.js @@ -16,13 +16,12 @@ import { ZERO_WIDTH_SELECTOR, ZERO_WIDTH_ATTRIBUTE } from './find-point' function cloneFragment(event, value, fragment = value.fragment) { const window = getWindow(event.target) const native = window.getSelection() - const { startKey, endKey, startText, endBlock, endInline } = value - const isVoidBlock = endBlock && endBlock.isVoid - const isVoidInline = endInline && endInline.isVoid - const isVoid = isVoidBlock || isVoidInline + const { startKey, endKey, startText } = value + const startVoid = value.document.getClosestVoid(startKey) + const endVoid = value.document.getClosestVoid(endKey) // If the selection is collapsed, and it isn't inside a void node, abort. - if (native.isCollapsed && !isVoid) return + if (native.isCollapsed && !startVoid) return // Create a fake selection so that we can add a Base64-encoded copy of the // fragment to the HTML, to decode on future pastes. @@ -31,23 +30,29 @@ function cloneFragment(event, value, fragment = value.fragment) { let contents = range.cloneContents() let attach = contents.childNodes[0] - // If the end node is a void node, we need to move the end of the range from - // the void node's spacer span, to the end of the void node's content. - if (isVoid) { + // COMPAT: If the end node is a void node, we need to move the end of the + // range from the void node's spacer span, to the end of the void node's + // content, since the spacer is before void's content in the DOM. + if (endVoid) { const r = range.cloneRange() - const n = isVoidBlock ? endBlock : endInline - const node = findDOMNode(n, window) + const node = findDOMNode(endVoid, window) r.setEndAfter(node) contents = r.cloneContents() - attach = contents.childNodes[contents.childNodes.length - 1].firstChild } - // COMPAT: in Safari and Chrome when selecting a single marked word, - // marks are not preserved when copying. - // If the attatched is not void, and the startKey and endKey is the same, - // check if there is marks involved. If so, set the range start just before the - // startText node - if ((IS_CHROME || IS_SAFARI) && !isVoid && startKey === endKey) { + // COMPAT: If the start node is a void node, we need to attach the encoded + // fragment to the void node's content node instead of the spacer, because + // attaching it to empty `