1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-18 13:11:17 +02:00

fix internal copies that start with a void node

This commit is contained in:
Ian Storm Taylor
2018-04-27 15:28:02 -07:00
parent da89f58c4c
commit f19cde92c7

View File

@@ -16,13 +16,12 @@ import { ZERO_WIDTH_SELECTOR, ZERO_WIDTH_ATTRIBUTE } from './find-point'
function cloneFragment(event, value, fragment = value.fragment) { function cloneFragment(event, value, fragment = value.fragment) {
const window = getWindow(event.target) const window = getWindow(event.target)
const native = window.getSelection() const native = window.getSelection()
const { startKey, endKey, startText, endBlock, endInline } = value const { startKey, endKey, startText } = value
const isVoidBlock = endBlock && endBlock.isVoid const startVoid = value.document.getClosestVoid(startKey)
const isVoidInline = endInline && endInline.isVoid const endVoid = value.document.getClosestVoid(endKey)
const isVoid = isVoidBlock || isVoidInline
// If the selection is collapsed, and it isn't inside a void node, abort. // 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 // Create a fake selection so that we can add a Base64-encoded copy of the
// fragment to the HTML, to decode on future pastes. // 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 contents = range.cloneContents()
let attach = contents.childNodes[0] let attach = contents.childNodes[0]
// If the end node is a void node, we need to move the end of the range from // COMPAT: If the end node is a void node, we need to move the end of the
// the void node's spacer span, to the end of the void node's content. // range from the void node's spacer span, to the end of the void node's
if (isVoid) { // content, since the spacer is before void's content in the DOM.
if (endVoid) {
const r = range.cloneRange() const r = range.cloneRange()
const n = isVoidBlock ? endBlock : endInline const node = findDOMNode(endVoid, window)
const node = findDOMNode(n, window)
r.setEndAfter(node) r.setEndAfter(node)
contents = r.cloneContents() contents = r.cloneContents()
attach = contents.childNodes[contents.childNodes.length - 1].firstChild
} }
// COMPAT: in Safari and Chrome when selecting a single marked word, // COMPAT: If the start node is a void node, we need to attach the encoded
// marks are not preserved when copying. // fragment to the void node's content node instead of the spacer, because
// If the attatched is not void, and the startKey and endKey is the same, // attaching it to empty `<div>/<span>` nodes will end up having it erased by
// check if there is marks involved. If so, set the range start just before the // most browsers. (2018/04/27)
// startText node if (startVoid) {
if ((IS_CHROME || IS_SAFARI) && !isVoid && startKey === endKey) { attach = contents.childNodes[0].childNodes[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 start key
// and endKey is the same, check if there is marks involved. If so, set the
// range start just before the start text node.
if ((IS_CHROME || IS_SAFARI) && !endVoid && startKey === endKey) {
const hasMarks = const hasMarks =
startText.characters startText.characters
.slice(value.selection.anchorOffset, value.selection.focusOffset) .slice(value.selection.anchorOffset, value.selection.focusOffset)