1
0
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:
Ian Storm Taylor
2016-12-09 18:09:37 -08:00
parent 36bd59b839
commit 59b31fb9b3
5 changed files with 69 additions and 89 deletions

View File

@@ -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)
}
}
})

View File

@@ -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)

View File

@@ -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()
}
}

View File

@@ -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,

View File

@@ -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.
*