mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-30 18:39:51 +02:00
fix selection setting for history
This commit is contained in:
@@ -99,6 +99,16 @@ class Selection extends new Record(DEFAULTS) {
|
||||
return this.isBackward == null ? null : !this.isBackward
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the selection's keys are not set.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
get isUnset() {
|
||||
return this.anchorKey == null || this.focusKey == null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start key.
|
||||
*
|
||||
@@ -281,19 +291,18 @@ class Selection extends new Record(DEFAULTS) {
|
||||
const { isCollapsed } = selection
|
||||
let { anchorKey, anchorOffset, focusKey, focusOffset, isBackward } = selection
|
||||
|
||||
// If the selection isn't formed yet or is malformed, set it to the
|
||||
// beginning of the node.
|
||||
// If the selection isn't formed yet or is malformed, ensure that it is
|
||||
// properly zeroed out.
|
||||
if (
|
||||
anchorKey == null ||
|
||||
focusKey == null ||
|
||||
!node.hasDescendant(anchorKey) ||
|
||||
!node.hasDescendant(focusKey)
|
||||
) {
|
||||
const first = node.getTexts().first()
|
||||
return selection.merge({
|
||||
anchorKey: first.key,
|
||||
anchorKey: null,
|
||||
anchorOffset: 0,
|
||||
focusKey: first.key,
|
||||
focusKey: null,
|
||||
focusOffset: 0,
|
||||
isBackward: false
|
||||
})
|
||||
|
@@ -42,9 +42,16 @@ class State extends new Record(DEFAULTS) {
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof State) return properties
|
||||
properties.document = Document.create(properties.document)
|
||||
properties.selection = Selection.create(properties.selection).normalize(properties.document)
|
||||
return new State(properties)
|
||||
|
||||
let document = Document.create(properties.document)
|
||||
let selection = Selection.create(properties.selection)
|
||||
|
||||
if (selection.isUnset) {
|
||||
const text = document.getTexts().first()
|
||||
selection = selection.collapseToStartOf(text)
|
||||
}
|
||||
|
||||
return new State({ document, selection })
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -281,15 +281,17 @@ function setSelection(state, operation) {
|
||||
let properties = { ...operation.properties }
|
||||
let { document, selection } = state
|
||||
|
||||
if (properties.anchorPath) {
|
||||
const anchorNode = document.assertPath(properties.anchorPath)
|
||||
properties.anchorKey = anchorNode.key
|
||||
if (properties.anchorPath !== undefined) {
|
||||
properties.anchorKey = properties.anchorPath === null
|
||||
? null
|
||||
: document.assertPath(properties.anchorPath).key
|
||||
delete properties.anchorPath
|
||||
}
|
||||
|
||||
if (properties.focusPath) {
|
||||
const focusNode = document.assertPath(properties.focusPath)
|
||||
properties.focusKey = focusNode.key
|
||||
if (properties.focusPath !== undefined) {
|
||||
properties.focusKey = properties.focusPath === null
|
||||
? null
|
||||
: document.assertPath(properties.focusPath).key
|
||||
delete properties.focusPath
|
||||
}
|
||||
|
||||
|
@@ -80,6 +80,7 @@ export function _delete(transform) {
|
||||
}
|
||||
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.deleteAtRange(selection)
|
||||
.moveTo(after)
|
||||
}
|
||||
@@ -154,6 +155,7 @@ export function deleteBackward(transform, n = 1) {
|
||||
}
|
||||
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.deleteBackwardAtRange(selection, n)
|
||||
.moveTo(after)
|
||||
}
|
||||
@@ -213,6 +215,7 @@ export function deleteForward(transform, n = 1) {
|
||||
}
|
||||
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.deleteForwardAtRange(selection, n)
|
||||
.moveTo(after)
|
||||
}
|
||||
@@ -230,6 +233,7 @@ export function insertBlock(transform, block) {
|
||||
let { document, selection } = state
|
||||
const keys = document.getTexts().map(text => text.key)
|
||||
|
||||
transform.unsetSelection()
|
||||
transform.insertBlockAtRange(selection, block)
|
||||
state = transform.state
|
||||
document = state.document
|
||||
@@ -258,6 +262,7 @@ export function insertFragment(transform, fragment) {
|
||||
const lastInline = fragment.getClosestInline(lastText)
|
||||
const beforeTexts = document.getTexts()
|
||||
|
||||
transform.unsetSelection()
|
||||
transform.insertFragmentAtRange(selection, fragment)
|
||||
state = transform.state
|
||||
document = state.document
|
||||
@@ -306,6 +311,7 @@ export function insertInline(transform, inline) {
|
||||
const hasVoid = document.hasVoidParent(startText)
|
||||
const keys = document.getTexts().map(text => text.key)
|
||||
|
||||
transform.unsetSelection()
|
||||
transform.insertInlineAtRange(selection, inline)
|
||||
state = transform.state
|
||||
document = state.document
|
||||
@@ -353,6 +359,7 @@ export function insertText(transform, text, marks) {
|
||||
marks = marks || selection.marks
|
||||
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.insertTextAtRange(selection, text, marks)
|
||||
.moveTo(after)
|
||||
}
|
||||
@@ -397,6 +404,7 @@ export function splitBlock(transform, depth = 1) {
|
||||
let { state } = transform
|
||||
let { document, selection } = state
|
||||
|
||||
transform.unsetSelection()
|
||||
transform.splitBlockAtRange(selection, depth)
|
||||
|
||||
state = transform.state
|
||||
@@ -423,6 +431,7 @@ export function splitInline(transform, depth = Infinity) {
|
||||
let { document, selection } = state
|
||||
let after = selection
|
||||
|
||||
transform.unsetSelection()
|
||||
transform.splitInlineAtRange(selection, depth)
|
||||
state = transform.state
|
||||
document = state.document
|
||||
@@ -551,6 +560,7 @@ export function wrapInline(transform, properties) {
|
||||
const { startKey } = selection
|
||||
const previous = document.getPreviousText(startKey)
|
||||
|
||||
transform.unsetSelection()
|
||||
transform.wrapInlineAtRange(selection, properties)
|
||||
state = transform.state
|
||||
document = state.document
|
||||
@@ -612,6 +622,7 @@ export function wrapText(transform, prefix, suffix = prefix) {
|
||||
}
|
||||
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.wrapTextAtRange(selection, prefix, suffix)
|
||||
.moveTo(after)
|
||||
}
|
||||
|
@@ -124,6 +124,7 @@ import {
|
||||
moveTo,
|
||||
moveToOffsets,
|
||||
moveToRangeOf,
|
||||
unsetSelection,
|
||||
} from './on-selection'
|
||||
|
||||
/**
|
||||
@@ -267,6 +268,7 @@ export default {
|
||||
moveTo,
|
||||
moveToOffsets,
|
||||
moveToRangeOf,
|
||||
unsetSelection,
|
||||
|
||||
/**
|
||||
* History.
|
||||
|
@@ -364,6 +364,7 @@ export function moveForward(transform, n) {
|
||||
*/
|
||||
|
||||
export function moveTo(transform, properties) {
|
||||
debugger
|
||||
return transform.setSelectionOperation(properties)
|
||||
}
|
||||
|
||||
@@ -398,3 +399,21 @@ export function moveToRangeOf(transform, start, end) {
|
||||
const sel = selection.moveToRangeOf(start, end).normalize(document)
|
||||
return transform.setSelectionOperation(sel)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the selection, removing an association to a node.
|
||||
*
|
||||
* @param {Transform} transform
|
||||
* @return {Transform}
|
||||
*/
|
||||
|
||||
export function unsetSelection(transform) {
|
||||
return transform.setSelectionOperation({
|
||||
anchorKey: null,
|
||||
anchorOffset: 0,
|
||||
focusKey: null,
|
||||
focusOffset: 0,
|
||||
isFocused: false,
|
||||
isBackward: false
|
||||
})
|
||||
}
|
||||
|
@@ -361,39 +361,53 @@ export function setSelectionOperation(transform, properties) {
|
||||
const { document, selection } = state
|
||||
const prevProps = {}
|
||||
|
||||
if (properties.marks == selection.marks) {
|
||||
// If the current selection has marks, and the new selection doesn't change
|
||||
// them in some way, they are old and should be removed.
|
||||
if (selection.marks && properties.marks == selection.marks) {
|
||||
properties.marks = null
|
||||
}
|
||||
|
||||
// Create a dictionary of the previous values for all of the properties that
|
||||
// are being changed, for the inverse operation.
|
||||
for (const k in properties) {
|
||||
prevProps[k] = selection[k]
|
||||
}
|
||||
|
||||
// Resolve the selection keys into paths.
|
||||
if (properties.anchorKey) {
|
||||
properties.anchorPath = document.getPath(properties.anchorKey)
|
||||
prevProps.anchorPath = document.getPath(prevProps.anchorKey)
|
||||
delete properties.anchorKey
|
||||
}
|
||||
|
||||
if (prevProps.anchorKey) {
|
||||
prevProps.anchorPath = document.getPath(prevProps.anchorKey)
|
||||
delete prevProps.anchorKey
|
||||
}
|
||||
|
||||
if (properties.focusKey) {
|
||||
properties.focusPath = document.getPath(properties.focusKey)
|
||||
prevProps.focusPath = document.getPath(prevProps.focusKey)
|
||||
delete properties.focusKey
|
||||
}
|
||||
|
||||
if (prevProps.focusKey) {
|
||||
prevProps.focusPath = document.getPath(prevProps.focusKey)
|
||||
delete prevProps.focusKey
|
||||
}
|
||||
|
||||
// Define an inverse of the operation for undoing.
|
||||
const inverse = [{
|
||||
type: 'set_selection',
|
||||
properties: prevProps
|
||||
}]
|
||||
|
||||
// Define the operation.
|
||||
const operation = {
|
||||
type: 'set_selection',
|
||||
properties,
|
||||
inverse,
|
||||
}
|
||||
|
||||
// Apply the operation.
|
||||
return transform.applyOperation(operation)
|
||||
}
|
||||
|
||||
|
@@ -107,7 +107,7 @@ function markProperties(value = {}) {
|
||||
case 'object': {
|
||||
for (const k in value) {
|
||||
if (k == 'data') {
|
||||
if (value[k] != null) ret[k] = Data.create(value[k])
|
||||
if (value[k] !== undefined) ret[k] = Data.create(value[k])
|
||||
} else {
|
||||
ret[k] = value[k]
|
||||
}
|
||||
@@ -138,10 +138,10 @@ function nodeProperties(value = {}) {
|
||||
break
|
||||
}
|
||||
case 'object': {
|
||||
if (value.isVoid != null) ret.isVoid = !!value.isVoid
|
||||
if (value.isVoid !== undefined) ret.isVoid = !!value.isVoid
|
||||
for (const k in value) {
|
||||
if (k == 'data') {
|
||||
if (value[k] != null) ret[k] = Data.create(value[k])
|
||||
if (value[k] !== undefined) ret[k] = Data.create(value[k])
|
||||
} else {
|
||||
ret[k] = value[k]
|
||||
}
|
||||
@@ -188,12 +188,12 @@ function selectionProperties(value = {}) {
|
||||
|
||||
switch (typeOf(value)) {
|
||||
case 'object': {
|
||||
if (value.anchorKey != null) ret.anchorKey = value.anchorKey
|
||||
if (value.anchorOffset != null) ret.anchorOffset = value.anchorOffset
|
||||
if (value.focusKey != null) ret.focusKey = value.focusKey
|
||||
if (value.focusOffset != null) ret.focusOffset = value.focusOffset
|
||||
if (value.isBackward != null) ret.isBackward = !!value.isBackward
|
||||
if (value.isFocused != null) ret.isFocused = !!value.isFocused
|
||||
if (value.anchorKey !== undefined) ret.anchorKey = value.anchorKey
|
||||
if (value.anchorOffset !== undefined) ret.anchorOffset = value.anchorOffset
|
||||
if (value.focusKey !== undefined) ret.focusKey = value.focusKey
|
||||
if (value.focusOffset !== undefined) ret.focusOffset = value.focusOffset
|
||||
if (value.isBackward !== undefined) ret.isBackward = !!value.isBackward
|
||||
if (value.isFocused !== undefined) ret.isFocused = !!value.isFocused
|
||||
if (value.marks !== undefined) ret.marks = value.marks
|
||||
break
|
||||
}
|
||||
|
Reference in New Issue
Block a user