mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-27 17:09:53 +02:00
cleanup lots of selection code, get tests passing again
This commit is contained in:
@@ -3,19 +3,6 @@ import getLeafText from '../utils/get-leaf-text'
|
||||
import warn from '../utils/warn'
|
||||
import { Record } from 'immutable'
|
||||
|
||||
/**
|
||||
* Start-end-and-edge convenience methods to auto-generate.
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
|
||||
const EDGE_METHODS = [
|
||||
'has%AtStartOf',
|
||||
'has%AtEndOf',
|
||||
'has%Between',
|
||||
'has%In',
|
||||
]
|
||||
|
||||
/**
|
||||
* Default properties.
|
||||
*
|
||||
@@ -422,38 +409,6 @@ class Selection extends new Record(DEFAULTS) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the end point to the start point.
|
||||
*
|
||||
* @return {Selection}
|
||||
*/
|
||||
|
||||
collapseToStart() {
|
||||
return this.merge({
|
||||
anchorKey: this.startKey,
|
||||
anchorOffset: this.startOffset,
|
||||
focusKey: this.startKey,
|
||||
focusOffset: this.startOffset,
|
||||
isBackward: false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the end point to the start point.
|
||||
*
|
||||
* @return {Selection}
|
||||
*/
|
||||
|
||||
collapseToEnd() {
|
||||
return this.merge({
|
||||
anchorKey: this.endKey,
|
||||
anchorOffset: this.endOffset,
|
||||
focusKey: this.endKey,
|
||||
focusOffset: this.endOffset,
|
||||
isBackward: false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to the start of a `node`.
|
||||
*
|
||||
@@ -590,45 +545,35 @@ class Selection extends new Record(DEFAULTS) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the start point forward `n` characters.
|
||||
* Move the anchor offset `n` characters.
|
||||
*
|
||||
* @param {Number} n (optional)
|
||||
* @return {Selection}
|
||||
*/
|
||||
|
||||
moveStartOffset(n = 1) {
|
||||
if (this.isBackward) {
|
||||
return this.merge({
|
||||
focusOffset: this.focusOffset + n,
|
||||
isBackward: null
|
||||
})
|
||||
} else {
|
||||
return this.merge({
|
||||
anchorOffset: this.anchorOffset + n,
|
||||
isBackward: null
|
||||
})
|
||||
}
|
||||
moveAnchorOffset(n = 1) {
|
||||
const { anchorKey, focusKey, focusOffset } = this
|
||||
const anchorOffset = this.anchorOffset + n
|
||||
return this.merge({
|
||||
anchorOffset,
|
||||
isBackward: anchorKey == focusKey ? anchorOffset > focusOffset : this.isBackward
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the end point forward `n` characters.
|
||||
* Move the anchor offset `n` characters.
|
||||
*
|
||||
* @param {Number} n (optional)
|
||||
* @return {Selection}
|
||||
*/
|
||||
|
||||
moveEndOffset(n = 1) {
|
||||
if (this.isBackward) {
|
||||
return this.merge({
|
||||
anchorOffset: this.anchorOffset + n,
|
||||
isBackward: null
|
||||
})
|
||||
} else {
|
||||
return this.merge({
|
||||
focusOffset: this.focusOffset + n,
|
||||
isBackward: null
|
||||
})
|
||||
}
|
||||
moveFocusOffset(n = 1) {
|
||||
const { focusKey, anchorKey, anchorOffset } = this
|
||||
const focusOffset = this.focusOffset + n
|
||||
return this.merge({
|
||||
focusOffset,
|
||||
isBackward: focusKey == anchorKey ? anchorOffset > focusOffset : this.isBackward
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -724,14 +669,37 @@ class Selection extends new Record(DEFAULTS) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the selection.
|
||||
*
|
||||
* @return {Selection}
|
||||
*/
|
||||
|
||||
flip() {
|
||||
return this.merge({
|
||||
anchorKey: this.focusKey,
|
||||
anchorOffset: this.focusOffset,
|
||||
focusKey: this.anchorKey,
|
||||
focusOffset: this.anchorOffset,
|
||||
isBackward: this.isBackward == null ? null : !this.isBackward,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add start, end and edge convenience methods.
|
||||
*/
|
||||
|
||||
EDGE_METHODS.forEach((pattern) => {
|
||||
const [ p, s ] = pattern.split('%')
|
||||
[
|
||||
['has', 'AtStartOf', true],
|
||||
['has', 'AtEndOf', true],
|
||||
['has', 'Between', true],
|
||||
['has', 'In', true],
|
||||
['collapseTo', ''],
|
||||
['move', 'Offset'],
|
||||
].forEach((opts) => {
|
||||
const [ p, s, hasEdge ] = opts
|
||||
const anchor = `${p}Anchor${s}`
|
||||
const edge = `${p}Edge${s}`
|
||||
const end = `${p}End${s}`
|
||||
@@ -750,8 +718,10 @@ EDGE_METHODS.forEach((pattern) => {
|
||||
: this[focus](...args)
|
||||
}
|
||||
|
||||
Selection.prototype[edge] = function (...args) {
|
||||
return this[anchor](...args) || this[focus](...args)
|
||||
if (hasEdge) {
|
||||
Selection.prototype[edge] = function (...args) {
|
||||
return this[anchor](...args) || this[focus](...args)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@@ -104,7 +104,7 @@ function insertNode(state, operation) {
|
||||
function insertText(state, operation) {
|
||||
const { path, offset, text, marks } = operation
|
||||
let { document, selection } = state
|
||||
const { startKey, endKey, startOffset, endOffset } = selection
|
||||
const { anchorKey, focusKey, anchorOffset, focusOffset } = selection
|
||||
let node = document.assertPath(path)
|
||||
|
||||
// Update the document
|
||||
@@ -112,11 +112,11 @@ function insertText(state, operation) {
|
||||
document = document.updateDescendant(node)
|
||||
|
||||
// Update the selection
|
||||
if (startKey == node.key && startOffset >= offset) {
|
||||
selection = selection.moveStartOffset(text.length)
|
||||
if (anchorKey == node.key && anchorOffset >= offset) {
|
||||
selection = selection.moveAnchorOffset(text.length)
|
||||
}
|
||||
if (endKey == node.key && endOffset >= offset) {
|
||||
selection = selection.moveEndOffset(text.length)
|
||||
if (focusKey == node.key && focusOffset >= offset) {
|
||||
selection = selection.moveFocusOffset(text.length)
|
||||
}
|
||||
|
||||
state = state.merge({ document, selection })
|
||||
@@ -287,15 +287,15 @@ function removeText(state, operation) {
|
||||
const { path, offset, length } = operation
|
||||
const rangeOffset = offset + length
|
||||
let { document, selection } = state
|
||||
const { startKey, endKey, startOffset, endOffset } = selection
|
||||
const { anchorKey, focusKey, anchorOffset, focusOffset } = selection
|
||||
let node = document.assertPath(path)
|
||||
|
||||
// Update the selection
|
||||
if (startKey == node.key && startOffset >= rangeOffset) {
|
||||
selection = selection.moveStartOffset(-length)
|
||||
if (anchorKey == node.key && anchorOffset >= rangeOffset) {
|
||||
selection = selection.moveAnchorOffset(-length)
|
||||
}
|
||||
if (endKey == node.key && endOffset >= rangeOffset) {
|
||||
selection = selection.moveEndOffset(-length)
|
||||
if (focusKey == node.key && focusOffset >= rangeOffset) {
|
||||
selection = selection.moveFocusOffset(-length)
|
||||
}
|
||||
|
||||
node = node.removeText(offset, length)
|
||||
|
@@ -466,12 +466,18 @@ export function wrapText(transform, prefix, suffix = prefix) {
|
||||
const { selection } = state
|
||||
transform.wrapTextAtRange(selection, prefix, suffix)
|
||||
|
||||
// Adding the suffix will have pushed the end of the selection further on, so
|
||||
// we need to move it back to account for this.
|
||||
transform.moveEndOffset(0 - suffix.length)
|
||||
|
||||
// If the selection was collapsed, it will have moved the start offset too.
|
||||
if (selection.isCollapsed) {
|
||||
transform.moveStartOffset(0 - prefix.length)
|
||||
}
|
||||
|
||||
// Adding the suffix will have pushed the end of the selection further on, so
|
||||
// we need to move it back to account for this.
|
||||
transform.moveEndOffset(0 - suffix.length)
|
||||
|
||||
// There's a chance that the selection points moved "through" each other,
|
||||
// resulting in a now-incorrect selection direction.
|
||||
if (selection.isForward != transform.state.selection.isForward) {
|
||||
transform.flipSelection()
|
||||
}
|
||||
}
|
||||
|
@@ -144,6 +144,7 @@ import {
|
||||
extendForward,
|
||||
extendToEndOf,
|
||||
extendToStartOf,
|
||||
flipSelection,
|
||||
focus,
|
||||
moveBackward,
|
||||
moveForward,
|
||||
@@ -321,6 +322,7 @@ export default {
|
||||
extendToEndOf,
|
||||
extendToStartOf,
|
||||
focus,
|
||||
flipSelection,
|
||||
moveBackward,
|
||||
moveForward,
|
||||
moveEndOffset,
|
||||
|
@@ -22,6 +22,8 @@ export const moveToRangeOf = generate('moveToRangeOf')
|
||||
export const moveStartOffset = generate('moveStartOffset')
|
||||
export const moveEndOffset = generate('moveEndOffset')
|
||||
|
||||
export const flipSelection = generate('flip')
|
||||
|
||||
/**
|
||||
* Move the selection to the end of the next block.
|
||||
*
|
||||
|
Reference in New Issue
Block a user