mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-30 10:29:48 +02:00
Merge pull request #1 from GitbookIO/schema-normalize-selection-ops
Update selection in low-level operations
This commit is contained in:
@@ -975,38 +975,37 @@ const Node = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Join a node by `key` with another `withKey`.
|
||||
* It brings Node<key> after Node<WithKey>
|
||||
* Join a children node `first` with another children node `second`.
|
||||
* `first` and `second` will be concatenated in that order.
|
||||
* `first` and `second` must be two Nodes or two Text.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {String} withKey
|
||||
* @param {Node} first
|
||||
* @param {Node} second
|
||||
* @return {Node}
|
||||
*/
|
||||
|
||||
joinNode(key, withKey) {
|
||||
joinNode(first, second) {
|
||||
let node = this
|
||||
let target = node.assertPath(key)
|
||||
let withTarget = node.assertPath(withKey)
|
||||
let parent = node.getParent(target)
|
||||
let parent = node.getParent(second)
|
||||
const isParent = node == parent
|
||||
const index = parent.nodes.indexOf(target)
|
||||
const index = parent.nodes.indexOf(second)
|
||||
|
||||
if (target.kind == 'text') {
|
||||
let { characters } = withTarget
|
||||
characters = characters.concat(target.characters)
|
||||
withTarget = withTarget.merge({ characters })
|
||||
if (second.kind == 'text') {
|
||||
let { characters } = first
|
||||
characters = characters.concat(second.characters)
|
||||
first = first.merge({ characters })
|
||||
}
|
||||
|
||||
else {
|
||||
const size = withTarget.nodes.size
|
||||
target.nodes.forEach((child, i) => {
|
||||
withTarget = withTarget.insertNode(size + i, child)
|
||||
const size = first.nodes.size
|
||||
second.nodes.forEach((child, i) => {
|
||||
first = first.insertNode(size + i, child)
|
||||
})
|
||||
}
|
||||
|
||||
parent = parent.removeNode(index)
|
||||
node = isParent ? parent : node.updateDescendant(parent)
|
||||
node = node.updateDescendant(withTarget)
|
||||
node = node.updateDescendant(first)
|
||||
return node
|
||||
},
|
||||
|
||||
|
@@ -569,6 +569,58 @@ class Selection extends new Record(DEFAULTS) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the start point forward `n` characters.
|
||||
*
|
||||
* @param {Number} n (optional)
|
||||
* @return {Selection} selection
|
||||
*/
|
||||
|
||||
moveStartOffset(n = 1) {
|
||||
return this.isBackward
|
||||
? this.merge({ focusOffset: this.focusOffset + n })
|
||||
: this.merge({ anchorOffset: this.anchorOffset + n })
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the end point forward `n` characters.
|
||||
*
|
||||
* @param {Number} n (optional)
|
||||
* @return {Selection} selection
|
||||
*/
|
||||
|
||||
moveEndOffset(n = 1) {
|
||||
return this.isBackward
|
||||
? this.merge({ anchorOffset: this.anchorOffset + n })
|
||||
: this.merge({ focusOffset: this.focusOffset + n })
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the start key, while preserving the direction
|
||||
*
|
||||
* @param {String} key
|
||||
* @return {Selection} selection
|
||||
*/
|
||||
|
||||
moveStartTo(key, offset = 0) {
|
||||
return this.isBackward
|
||||
? this.merge({ focusKey: key, focusOffset: offset })
|
||||
: this.merge({ anchorKey: key, anchorOffset: offset })
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the end key, while preserving the direction
|
||||
*
|
||||
* @param {String} key
|
||||
* @return {Selection} selection
|
||||
*/
|
||||
|
||||
moveEndTo(key, offset = 0) {
|
||||
return this.isBackward
|
||||
? this.merge({ anchorKey: key, anchorOffset: offset })
|
||||
: this.merge({ focusKey: key, focusOffset: offset })
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the focus point to the start of a `node`.
|
||||
*
|
||||
@@ -599,6 +651,23 @@ class Selection extends new Record(DEFAULTS) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the selection
|
||||
*
|
||||
* @return {Selection} selection
|
||||
*/
|
||||
|
||||
unset() {
|
||||
return this.merge({
|
||||
anchorKey: null,
|
||||
anchorOffset: 0,
|
||||
focusKey: null,
|
||||
focusOffset: 0,
|
||||
isFocused: false,
|
||||
isBackward: false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,6 @@
|
||||
|
||||
import Debug from 'debug'
|
||||
import warning from '../utils/warning'
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
@@ -106,11 +107,23 @@ function insertNode(state, operation) {
|
||||
|
||||
function insertText(state, operation) {
|
||||
const { path, offset, text, marks } = operation
|
||||
let { document } = state
|
||||
let { document, selection } = state
|
||||
const { startKey, endKey, startOffset, endOffset } = selection
|
||||
let node = document.assertPath(path)
|
||||
|
||||
// Update the document
|
||||
node = node.insertText(offset, text, marks)
|
||||
document = document.updateDescendant(node)
|
||||
state = state.merge({ document })
|
||||
|
||||
// Update the selection
|
||||
if (startKey == node.key && startOffset >= offset) {
|
||||
selection = selection.moveStartOffset(text.length)
|
||||
}
|
||||
if (endKey == node.key && endOffset >= offset) {
|
||||
selection = selection.moveEndOffset(text.length)
|
||||
}
|
||||
|
||||
state = state.merge({ document, selection })
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -124,9 +137,33 @@ function insertText(state, operation) {
|
||||
|
||||
function joinNode(state, operation) {
|
||||
const { path, withPath } = operation
|
||||
let { document } = state
|
||||
document = document.joinNode(path, withPath)
|
||||
state = state.merge({ document })
|
||||
let { document, selection } = state
|
||||
const first = document.assertPath(withPath)
|
||||
const second = document.assertPath(path)
|
||||
|
||||
// Update doc
|
||||
document = document.joinNode(first, second)
|
||||
|
||||
// Update selection
|
||||
// When merging two texts together
|
||||
if (second.kind == 'text') {
|
||||
const { anchorKey, anchorOffset, focusKey, focusOffset } = selection
|
||||
// The final key is the `first` key
|
||||
if (anchorKey == second.key) {
|
||||
selection = selection.merge({
|
||||
anchorKey: first.key,
|
||||
anchorOffset: anchorOffset + first.characters.size
|
||||
})
|
||||
}
|
||||
if (focusKey == second.key) {
|
||||
selection = selection.merge({
|
||||
focusKey: first.key,
|
||||
focusOffset: focusOffset + first.characters.size
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
state = state.merge({ document, selection })
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -143,12 +180,14 @@ function moveNode(state, operation) {
|
||||
let { document } = state
|
||||
const node = document.assertPath(path)
|
||||
|
||||
// Remove the node from its current parent
|
||||
let parent = document.getParent(node)
|
||||
const isParent = document == parent
|
||||
const index = parent.nodes.indexOf(node)
|
||||
parent = parent.removeNode(index)
|
||||
document = isParent ? parent : document.updateDescendant(parent)
|
||||
|
||||
// Insert the new node to its new parent
|
||||
let target = document.assertPath(newPath)
|
||||
const isTarget = document == target
|
||||
target = target.insertNode(newIndex, node)
|
||||
@@ -186,14 +225,55 @@ function removeMark(state, operation) {
|
||||
|
||||
function removeNode(state, operation) {
|
||||
const { path } = operation
|
||||
let { document } = state
|
||||
let { document, selection } = state
|
||||
const { startKey, endKey } = selection
|
||||
|
||||
// Preserve previous document
|
||||
const prevDocument = document
|
||||
|
||||
// Update the document
|
||||
const node = document.assertPath(path)
|
||||
let parent = document.getParent(node)
|
||||
const index = parent.nodes.indexOf(node)
|
||||
const isParent = document == parent
|
||||
parent = parent.removeNode(index)
|
||||
document = isParent ? parent : document.updateDescendant(parent)
|
||||
state = state.merge({ document })
|
||||
|
||||
function getRemoved(key) {
|
||||
if (key === node.key) return node
|
||||
if (node.kind == 'text') return null
|
||||
return node.getDescendant(key)
|
||||
}
|
||||
|
||||
// Update the selection, if one of the anchor/focus has been removed
|
||||
const startDesc = startKey ? getRemoved(startKey) : null
|
||||
const endDesc = endKey ? getRemoved(endKey) : null
|
||||
|
||||
if (startDesc) {
|
||||
const prevText = prevDocument.getTexts()
|
||||
.takeUntil(text => text.key == startKey)
|
||||
.filter(text => !getRemoved(text.key))
|
||||
.last()
|
||||
if (!prevText) selection = selection.unset()
|
||||
else selection = selection.moveStartTo(prevText.key, prevText.length)
|
||||
}
|
||||
if (endDesc) {
|
||||
// The whole selection is inside the node, we collapse to the previous text node
|
||||
if (startKey == endKey) {
|
||||
selection = selection.collapseToStart()
|
||||
} else {
|
||||
const nextText = prevDocument.getTexts()
|
||||
.skipUntil(text => text.key == startKey)
|
||||
.slice(1)
|
||||
.filter(text => !getRemoved(text.key))
|
||||
.first()
|
||||
|
||||
if (!nextText) selection = selection.unset()
|
||||
else selection = selection.moveEndTo(nextText.key, 0)
|
||||
}
|
||||
}
|
||||
|
||||
state = state.merge({ document, selection })
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -207,11 +287,25 @@ function removeNode(state, operation) {
|
||||
|
||||
function removeText(state, operation) {
|
||||
const { path, offset, length } = operation
|
||||
let { document } = state
|
||||
let { document, selection } = state
|
||||
const { startKey, endKey, startOffset, endOffset } = selection
|
||||
let node = document.assertPath(path)
|
||||
|
||||
const rangeOffset = offset + length
|
||||
|
||||
// Update the document
|
||||
node = node.removeText(offset, length)
|
||||
document = document.updateDescendant(node)
|
||||
state = state.merge({ document })
|
||||
|
||||
// Update the selection
|
||||
if (startKey == node.key && startOffset >= rangeOffset) {
|
||||
selection = selection.moveStartOffset(-length)
|
||||
}
|
||||
if (endKey == node.key && endOffset >= rangeOffset) {
|
||||
selection = selection.moveEndOffset(-length)
|
||||
}
|
||||
|
||||
state = state.merge({ document, selection })
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -245,6 +339,16 @@ function setNode(state, operation) {
|
||||
const { path, properties } = operation
|
||||
let { document } = state
|
||||
let node = document.assertPath(path)
|
||||
|
||||
// Deprecate using setNode for updating children, or keys
|
||||
if (properties.nodes && properties.nodes != node.nodes) {
|
||||
warning('Updating Node.nodes through setNode is not allowed. Use appropriate insertion and removal functions.')
|
||||
delete properties.nodes
|
||||
} else if (properties.key && properties.key != node.key) {
|
||||
warning('Updating Node.key through setNode is not allowed. You should not have to update keys yourself.')
|
||||
delete properties.key
|
||||
}
|
||||
|
||||
node = node.merge(properties)
|
||||
document = document.updateDescendant(node)
|
||||
state = state.merge({ document })
|
||||
@@ -293,10 +397,58 @@ function setSelection(state, operation) {
|
||||
|
||||
function splitNode(state, operation) {
|
||||
const { path, offset } = operation
|
||||
let { document } = state
|
||||
const { document } = state
|
||||
|
||||
document = document.splitNode(path, offset)
|
||||
// Update document
|
||||
const newDocument = document.splitNode(path, offset)
|
||||
|
||||
state = state.merge({ document })
|
||||
// Update selection
|
||||
let { selection } = state
|
||||
const { anchorKey, anchorOffset, focusKey, focusOffset } = selection
|
||||
|
||||
const node = document.assertPath(path)
|
||||
// The text node that was split
|
||||
const splittedText = node.kind == 'text'
|
||||
? node
|
||||
: node.getTextAtOffset(offset)
|
||||
const textOffset = node.kind == 'text'
|
||||
? offset
|
||||
: offset - node.getOffset(splittedText)
|
||||
|
||||
// Should we update the selection ?
|
||||
const shouldUpdateAnchor = splittedText.key == anchorKey && textOffset <= anchorOffset
|
||||
const shouldUpdateFocus = splittedText.key == focusKey && textOffset <= focusOffset
|
||||
if (shouldUpdateFocus || shouldUpdateAnchor) {
|
||||
// The node next to `node`, resulting from the split
|
||||
const secondNode = newDocument.getNextSibling(node)
|
||||
let secondText, newOffset
|
||||
|
||||
if (shouldUpdateAnchor) {
|
||||
newOffset = anchorOffset - textOffset
|
||||
secondText = secondNode.kind == 'text'
|
||||
? secondNode
|
||||
: secondNode.getTextAtOffset(newOffset)
|
||||
selection = selection.merge({
|
||||
anchorKey: secondText.key,
|
||||
anchorOffset: newOffset
|
||||
})
|
||||
}
|
||||
|
||||
if (shouldUpdateFocus) {
|
||||
newOffset = focusOffset - textOffset
|
||||
secondText = secondNode.kind == 'text'
|
||||
? secondNode
|
||||
: secondNode.getTextAtOffset(newOffset)
|
||||
selection = selection.merge({
|
||||
focusKey: secondText.key,
|
||||
focusOffset: newOffset
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
state = state.merge({
|
||||
document: newDocument,
|
||||
selection
|
||||
})
|
||||
return state
|
||||
}
|
||||
|
@@ -95,70 +95,11 @@ export function _delete(transform) {
|
||||
|
||||
export function deleteBackward(transform, n = 1) {
|
||||
const { state } = transform
|
||||
const { document, selection } = state
|
||||
let after
|
||||
|
||||
const { startKey } = selection
|
||||
const startNode = document.getDescendant(startKey)
|
||||
|
||||
if (selection.isExpanded) {
|
||||
after = selection.collapseToStart()
|
||||
}
|
||||
|
||||
else if (selection.isAtStartOf(document)) {
|
||||
after = selection
|
||||
}
|
||||
|
||||
else if (selection.isAtStartOf(startNode)) {
|
||||
const previous = document.getPreviousText(startNode)
|
||||
const prevBlock = document.getClosestBlock(previous)
|
||||
const prevInline = document.getClosestInline(previous)
|
||||
|
||||
if (prevBlock && prevBlock.isVoid) {
|
||||
after = selection
|
||||
} else if (prevInline && prevInline.isVoid) {
|
||||
const prevPrev = document.getPreviousText(previous)
|
||||
after = selection.collapseToEndOf(prevPrev)
|
||||
} else {
|
||||
after = selection.collapseToEndOf(previous)
|
||||
}
|
||||
}
|
||||
|
||||
else if (selection.isAtEndOf(startNode) && startNode.length == 1) {
|
||||
const block = document.getClosestBlock(startKey)
|
||||
const highest = block.getHighestChild(startKey)
|
||||
const previous = block.getPreviousSibling(highest)
|
||||
const next = block.getNextSibling(highest)
|
||||
|
||||
if (previous) {
|
||||
if (previous.kind == 'text') {
|
||||
if (next && next.kind == 'text') {
|
||||
after = selection.merge({
|
||||
anchorKey: previous.key,
|
||||
anchorOffset: previous.length,
|
||||
focusKey: previous.key,
|
||||
focusOffset: previous.length
|
||||
})
|
||||
} else {
|
||||
after = selection.collapseToEndOf(previous)
|
||||
}
|
||||
} else {
|
||||
const last = previous.getTexts().last()
|
||||
after = selection.collapseToEndOf(last)
|
||||
}
|
||||
} else {
|
||||
after = selection.moveBackward(n)
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
after = selection.moveBackward(n)
|
||||
}
|
||||
const { selection } = state
|
||||
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.deleteBackwardAtRange(selection, n)
|
||||
.moveTo(after)
|
||||
.collapseToEnd()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,54 +112,10 @@ export function deleteBackward(transform, n = 1) {
|
||||
|
||||
export function deleteForward(transform, n = 1) {
|
||||
const { state } = transform
|
||||
const { document, selection, startText } = state
|
||||
const { startKey, startOffset } = selection
|
||||
let after
|
||||
|
||||
const block = document.getClosestBlock(startKey)
|
||||
const inline = document.getClosestInline(startKey)
|
||||
const highest = block.getHighestChild(startKey)
|
||||
const previous = block.getPreviousSibling(highest)
|
||||
const next = block.getNextSibling(highest)
|
||||
|
||||
if (selection.isExpanded) {
|
||||
after = selection.collapseToStart()
|
||||
}
|
||||
|
||||
else if ((block && block.isVoid) || (inline && inline.isVoid)) {
|
||||
const nextText = document.getNextText(startKey)
|
||||
const prevText = document.getPreviousText(startKey)
|
||||
after = next
|
||||
? selection.collapseToStartOf(nextText)
|
||||
: selection.collapseToEndOf(prevText)
|
||||
}
|
||||
|
||||
else if (previous && startOffset == 0 && startText.length == 1) {
|
||||
if (previous.kind == 'text') {
|
||||
if (next && next.kind == 'text') {
|
||||
after = selection.merge({
|
||||
anchorKey: previous.key,
|
||||
anchorOffset: previous.length,
|
||||
focusKey: previous.key,
|
||||
focusOffset: previous.length
|
||||
})
|
||||
} else {
|
||||
after = selection.collapseToEndOf(previous)
|
||||
}
|
||||
} else {
|
||||
const last = previous.getTexts().last()
|
||||
after = selection.collapseToEndOf(last)
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
after = selection
|
||||
}
|
||||
|
||||
const { selection } = state
|
||||
return transform
|
||||
.unsetSelection()
|
||||
.deleteForwardAtRange(selection, n)
|
||||
.moveTo(after)
|
||||
.collapseToEnd()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -15,7 +15,7 @@ export default function warning(message) {
|
||||
}
|
||||
|
||||
if (typeof console !== 'undefined') {
|
||||
console.error('Warning: ', message) // eslint-disable-line no-console
|
||||
console.error(`Warning: ${message}`) // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
try {
|
||||
|
36
test.js
36
test.js
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { Raw, Inline } from './src'
|
||||
|
||||
function printNode(node, depth = 0) {
|
||||
@@ -29,28 +31,9 @@ const state = Raw.deserialize({
|
||||
key: 'container',
|
||||
nodes: [
|
||||
{
|
||||
key: 'in1',
|
||||
kind: 'inline',
|
||||
type: 'link',
|
||||
nodes: [
|
||||
{
|
||||
key: 'sometext',
|
||||
kind: 'text',
|
||||
text: 'Hello'
|
||||
},
|
||||
{
|
||||
key: 'in2',
|
||||
kind: 'inline',
|
||||
type: 'image',
|
||||
isVoid: true,
|
||||
nodes: [
|
||||
{
|
||||
kind: 'text',
|
||||
text: ' '
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
key: 'sometext',
|
||||
kind: 'text',
|
||||
text: 'Hello'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -60,7 +43,14 @@ const state = Raw.deserialize({
|
||||
print(state)
|
||||
|
||||
const newState = state.transform()
|
||||
.moveNodeByKey('in2', 'container')
|
||||
.moveTo({
|
||||
anchorKey: 'sometext',
|
||||
focusKey: 'sometext',
|
||||
anchorOffset: 3,
|
||||
focusOffset: 3
|
||||
})
|
||||
.insertTextByKey('sometext', 1, 'X')
|
||||
.apply()
|
||||
|
||||
console.log(newState.selection.toJS())
|
||||
print(newState)
|
||||
|
@@ -2,14 +2,11 @@
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
let first = texts.first()
|
||||
const second = texts.last()
|
||||
const { selection } = state
|
||||
const range = selection.merge({
|
||||
anchorKey: first.key,
|
||||
anchorOffset: 2,
|
||||
focusKey: second.key,
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 1,
|
||||
focusKey: 'focus',
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
@@ -19,15 +16,18 @@ export default function (state) {
|
||||
.unwrapInline('hashtag')
|
||||
.apply()
|
||||
|
||||
// Selection is reset, in theory it should me on the image
|
||||
first = next.document.getTexts().first()
|
||||
// Test selection
|
||||
const { document } = next
|
||||
const first = document.getTexts().first()
|
||||
const last = document.getTexts().last()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.merge({
|
||||
anchorKey: first.key,
|
||||
anchorOffset: 0,
|
||||
focusKey: first.key,
|
||||
focusOffset: 0
|
||||
anchorOffset: 1,
|
||||
focusKey: last.key,
|
||||
focusOffset: 4
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
|
@@ -4,6 +4,7 @@ nodes:
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor' # w[o
|
||||
text: wo
|
||||
- kind: inline
|
||||
type: hashtag
|
||||
@@ -19,4 +20,5 @@ nodes:
|
||||
- kind: text
|
||||
text: an
|
||||
- kind: text
|
||||
key: 'focus' # ot]her
|
||||
text: other
|
||||
|
@@ -10,3 +10,5 @@ nodes:
|
||||
nodes:
|
||||
- kind: text
|
||||
text: another
|
||||
# Selection
|
||||
# w[ordanot]her
|
@@ -2,14 +2,11 @@
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const first = texts.first()
|
||||
const last = texts.get(1)
|
||||
const { selection } = state
|
||||
const range = selection.merge({
|
||||
anchorKey: first.key,
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 1,
|
||||
focusKey: last.key,
|
||||
focusKey: 'focus',
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
@@ -21,7 +18,10 @@ export default function (state) {
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.collapseToStartOf(next.document).toJS()
|
||||
range.merge({
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 3
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
|
@@ -7,11 +7,15 @@ nodes:
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: w
|
||||
- kind: inline
|
||||
type: hashtag
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'focus'
|
||||
text: or
|
||||
- kind: text
|
||||
text: d
|
||||
# Selection
|
||||
# w[or]d
|
@@ -2,14 +2,11 @@
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const first = texts.get(2)
|
||||
const last = texts.get(3)
|
||||
const { selection } = state
|
||||
const range = selection.merge({
|
||||
anchorKey: first.key,
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 2,
|
||||
focusKey: last.key,
|
||||
focusKey: 'focus',
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
@@ -21,7 +18,10 @@ export default function (state) {
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.collapseToStartOf(next.document).toJS()
|
||||
range.merge({
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 5
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
|
@@ -11,11 +11,16 @@ nodes:
|
||||
- kind: text
|
||||
text: ll
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: "o w"
|
||||
- kind: inline
|
||||
type: hashtag
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'focus'
|
||||
text: or
|
||||
- kind: text
|
||||
text: d
|
||||
|
||||
# Selection
|
||||
# hello [wor]d
|
@@ -12,3 +12,5 @@ nodes:
|
||||
text: ll
|
||||
- kind: text
|
||||
text: "o word"
|
||||
# Selection
|
||||
# hello [wor]d
|
@@ -2,14 +2,11 @@
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const first = texts.first()
|
||||
const last = texts.get(1)
|
||||
const { selection } = state
|
||||
const range = selection.merge({
|
||||
anchorKey: first.key,
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 1,
|
||||
focusKey: last.key,
|
||||
focusKey: 'focus',
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
@@ -21,7 +18,10 @@ export default function (state) {
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.collapseToStartOf(next.document).toJS()
|
||||
range.merge({
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 3
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
|
@@ -4,11 +4,16 @@ nodes:
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: w
|
||||
- kind: inline
|
||||
type: hashtag
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'focus'
|
||||
text: or
|
||||
- kind: text
|
||||
text: d
|
||||
|
||||
# selection:
|
||||
# w[or]d
|
@@ -0,0 +1,29 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(secondText.key, 5, 'X')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: helloX
|
@@ -0,0 +1,29 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(secondText.key, 2, 'XX', [ { type: 'bold' } ])
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,17 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
ranges:
|
||||
- text: he
|
||||
- text: XX
|
||||
marks:
|
||||
- type: bold
|
||||
- text: llo
|
@@ -0,0 +1,29 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(secondText.key, 2, 'X')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: heXllo
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(firstText.key, 0, 'XX')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 4,
|
||||
focusOffset: 4
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: XXhello
|
@@ -0,0 +1,28 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(firstText.key, 5, 'XX')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: helloXX
|
@@ -0,0 +1,30 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 4
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(firstText.key, 4, 'XX')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
focusOffset: 6
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hellXXo
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 4
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(firstText.key, 2, 'XX')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 4,
|
||||
focusOffset: 6
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: heXXllo
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 4
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(firstText.key, 3, 'XX')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 2,
|
||||
focusOffset: 6
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: helXXlo
|
@@ -0,0 +1,29 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.insertTextByKey(secondText.key, 0, 'X')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: outside
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: Xhello
|
@@ -0,0 +1,29 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { selection } = state
|
||||
|
||||
const range = selection.merge({
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 1,
|
||||
focusKey: 'focus',
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(range)
|
||||
.joinNodeByKey('key2', 'key1')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.merge({
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 5
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
key: 'key1'
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: The
|
||||
- kind: block
|
||||
key: 'key2'
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'focus'
|
||||
text: text
|
@@ -0,0 +1,8 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
key: key1
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: Thetext
|
@@ -0,0 +1,29 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { selection } = state
|
||||
|
||||
const range = selection.merge({
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 1,
|
||||
focusKey: 'focus',
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(range)
|
||||
.joinNodeByKey('focus', 'anchor')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.merge({
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 5
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: one
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
- kind: text
|
||||
text: two
|
||||
- kind: text
|
||||
key: 'focus'
|
||||
text: three
|
@@ -0,0 +1,13 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: onethree
|
||||
- kind: inline
|
||||
type: link
|
||||
nodes:
|
||||
- kind: text
|
||||
text: two
|
@@ -0,0 +1,28 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: secondText.key,
|
||||
focusKey: secondText.key,
|
||||
anchorOffset: 0,
|
||||
focusOffset: 0
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeNodeByKey('todelete')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
key: todelete
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: removed
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,28 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: secondText.key,
|
||||
focusKey: secondText.key,
|
||||
anchorOffset: 0,
|
||||
focusOffset: 0
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeNodeByKey('todelete')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: inline
|
||||
type: link
|
||||
key: todelete
|
||||
nodes:
|
||||
- kind: text
|
||||
text: removed
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ""
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,34 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: secondText.key,
|
||||
focusKey: secondText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeNodeByKey('todelete')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 5,
|
||||
focusOffset: 5
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
||||
- kind: block
|
||||
key: todelete
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: removed
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,28 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const secondText = texts.get(1)
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: secondText.key,
|
||||
focusKey: secondText.key,
|
||||
anchorOffset: 0,
|
||||
focusOffset: 0
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeNodeByKey('todelete')
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: todelete
|
||||
text: removed
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ""
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeTextByKey(firstText.key, 0, 1)
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 1,
|
||||
focusOffset: 1
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: ello
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeTextByKey(firstText.key, 3, 1)
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: helo
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 3,
|
||||
focusOffset: 3
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeTextByKey(firstText.key, 2, 1)
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 2,
|
||||
focusOffset: 2
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: helo
|
@@ -0,0 +1,31 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { document, selection } = state
|
||||
const texts = document.getTexts()
|
||||
const firstText = texts.first()
|
||||
|
||||
const nextSelection = selection.merge({
|
||||
anchorKey: firstText.key,
|
||||
focusKey: firstText.key,
|
||||
anchorOffset: 1,
|
||||
focusOffset: 5
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(nextSelection)
|
||||
.removeTextByKey(firstText.key, 2, 1)
|
||||
.apply()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
nextSelection.merge({
|
||||
anchorOffset: 1,
|
||||
focusOffset: 4
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: hello
|
@@ -0,0 +1,7 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: helo
|
@@ -0,0 +1,32 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { selection } = state
|
||||
|
||||
const range = selection.merge({
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 2,
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 5
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(range)
|
||||
.splitNodeByKey('key', 3)
|
||||
.apply()
|
||||
|
||||
|
||||
const second = next.document.getTexts().last()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.merge({
|
||||
focusKey: second.key,
|
||||
focusOffset: 2
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
key: 'key'
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: Thetext
|
||||
# Selection
|
||||
# Th[ete]xt
|
@@ -0,0 +1,12 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: The
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
text: text
|
@@ -0,0 +1,34 @@
|
||||
|
||||
import assert from 'assert'
|
||||
|
||||
export default function (state) {
|
||||
const { selection } = state
|
||||
|
||||
const range = selection.merge({
|
||||
anchorKey: 'anchor',
|
||||
anchorOffset: 4,
|
||||
focusKey: 'anchor',
|
||||
focusOffset: 5
|
||||
})
|
||||
|
||||
const next = state
|
||||
.transform()
|
||||
.moveTo(range)
|
||||
.splitNodeByKey('anchor', 3, { normalize: false })
|
||||
.apply()
|
||||
|
||||
// The second text
|
||||
const second = next.document.getTexts().last()
|
||||
|
||||
assert.deepEqual(
|
||||
next.selection.toJS(),
|
||||
range.merge({
|
||||
anchorKey: second.key,
|
||||
anchorOffset: 1,
|
||||
focusKey: second.key,
|
||||
focusOffset: 2
|
||||
}).toJS()
|
||||
)
|
||||
|
||||
return next
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: onetwo
|
||||
# Selection
|
||||
# onet[w]o
|
@@ -0,0 +1,10 @@
|
||||
|
||||
nodes:
|
||||
- kind: block
|
||||
type: paragraph
|
||||
nodes:
|
||||
- kind: text
|
||||
key: 'anchor'
|
||||
text: one
|
||||
- kind: text
|
||||
text: two
|
Reference in New Issue
Block a user