mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-31 02:49:56 +02:00
refactor operations
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
import Operations from '../transforms/operations'
|
||||||
import Transforms from '../transforms'
|
import Transforms from '../transforms'
|
||||||
import includes from 'lodash/includes'
|
import includes from 'lodash/includes'
|
||||||
import xor from 'lodash/xor'
|
import xor from 'lodash/xor'
|
||||||
@@ -70,13 +71,19 @@ class Transform {
|
|||||||
/**
|
/**
|
||||||
* Add an `operation` to the transform that resulted in `state`.
|
* Add an `operation` to the transform that resulted in `state`.
|
||||||
*
|
*
|
||||||
* @param {State} state
|
|
||||||
* @param {Object} operation
|
* @param {Object} operation
|
||||||
* @return {Transform}
|
* @return {Transform}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
add(state, operation) {
|
operate(operation) {
|
||||||
this.state = state
|
const { type } = operation
|
||||||
|
const fn = Operations[type]
|
||||||
|
|
||||||
|
if (!fn) {
|
||||||
|
throw new Error(`Unknown operation type: "${type}".`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = fn(this.state, operation)
|
||||||
this.operations.push(operation)
|
this.operations.push(operation)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ export function addMark(transform, mark) {
|
|||||||
if (selection.isCollapsed) {
|
if (selection.isCollapsed) {
|
||||||
const marks = document.getMarksAtRange(selection).add(mark)
|
const marks = document.getMarksAtRange(selection).add(mark)
|
||||||
const sel = selection.merge({ marks })
|
const sel = selection.merge({ marks })
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.addMarkAtRange(selection, mark)
|
return transform.addMarkAtRange(selection, mark)
|
||||||
@@ -73,7 +73,7 @@ export function _delete(transform) {
|
|||||||
|
|
||||||
return transform
|
return transform
|
||||||
.deleteAtRange(selection)
|
.deleteAtRange(selection)
|
||||||
.updateSelection(after)
|
.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,7 +147,7 @@ export function deleteBackward(transform, n = 1) {
|
|||||||
|
|
||||||
return transform
|
return transform
|
||||||
.deleteBackwardAtRange(selection, n)
|
.deleteBackwardAtRange(selection, n)
|
||||||
.updateSelection(after)
|
.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,7 +206,7 @@ export function deleteForward(transform, n = 1) {
|
|||||||
|
|
||||||
return transform
|
return transform
|
||||||
.deleteForwardAtRange(selection, n)
|
.deleteForwardAtRange(selection, n)
|
||||||
.updateSelection(after)
|
.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -229,7 +229,7 @@ export function insertBlock(transform, block) {
|
|||||||
const text = document.getTexts().find(n => !keys.includes(n.key))
|
const text = document.getTexts().find(n => !keys.includes(n.key))
|
||||||
const after = selection.collapseToEndOf(text)
|
const after = selection.collapseToEndOf(text)
|
||||||
|
|
||||||
return transform.updateSelection(after)
|
return transform.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -279,7 +279,7 @@ export function insertFragment(transform, fragment) {
|
|||||||
.moveForward(lastText.length)
|
.moveForward(lastText.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.updateSelection(after)
|
return transform.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -311,7 +311,7 @@ export function insertInline(transform, inline) {
|
|||||||
after = selection.collapseToEndOf(text)
|
after = selection.collapseToEndOf(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.updateSelection(after)
|
return transform.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,7 +346,7 @@ export function insertText(transform, text, marks) {
|
|||||||
|
|
||||||
return transform
|
return transform
|
||||||
.insertTextAtRange(selection, text, marks)
|
.insertTextAtRange(selection, text, marks)
|
||||||
.updateSelection(after)
|
.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,7 +399,7 @@ export function splitBlock(transform, depth = 1) {
|
|||||||
const nextNode = document.getNextText(startNode)
|
const nextNode = document.getNextText(startNode)
|
||||||
const after = selection.collapseToStartOf(nextNode)
|
const after = selection.collapseToStartOf(nextNode)
|
||||||
|
|
||||||
return transform.updateSelection(after)
|
return transform.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -428,7 +428,7 @@ export function splitInline(transform, depth = Infinity) {
|
|||||||
after = selection.collapseToStartOf(nextNode)
|
after = selection.collapseToStartOf(nextNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.updateSelection(after)
|
return transform.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -448,7 +448,7 @@ export function removeMark(transform, mark) {
|
|||||||
if (selection.isCollapsed) {
|
if (selection.isCollapsed) {
|
||||||
const marks = document.getMarksAtRange(selection).remove(mark)
|
const marks = document.getMarksAtRange(selection).remove(mark)
|
||||||
const sel = selection.merge({ marks })
|
const sel = selection.merge({ marks })
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.removeMarkAtRange(selection, mark)
|
return transform.removeMarkAtRange(selection, mark)
|
||||||
@@ -566,7 +566,7 @@ export function wrapInline(transform, properties) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
after = after.normalize(document)
|
after = after.normalize(document)
|
||||||
return transform.updateSelection(after)
|
return transform.setSelection(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -597,5 +597,5 @@ export function wrapText(transform, prefix, suffix = prefix) {
|
|||||||
|
|
||||||
return transform
|
return transform
|
||||||
.wrapTextAtRange(selection, prefix, suffix)
|
.wrapTextAtRange(selection, prefix, suffix)
|
||||||
.updateSelection(after)
|
.setSelection(after)
|
||||||
}
|
}
|
||||||
|
@@ -323,7 +323,7 @@ export function insertFragmentAtRange(transform, range, fragment) {
|
|||||||
const lastIndex = lastBlock.nodes.size
|
const lastIndex = lastBlock.nodes.size
|
||||||
|
|
||||||
nextNodes.forEach((node, i) => {
|
nextNodes.forEach((node, i) => {
|
||||||
const newIndex = lastIndex + i + 1
|
const newIndex = lastIndex + i
|
||||||
transform.moveNodeByKey(node.key, lastBlock.key, newIndex)
|
transform.moveNodeByKey(node.key, lastBlock.key, newIndex)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -737,7 +737,7 @@ export function wrapBlockAtRange(transform, range, block) {
|
|||||||
const parent = document.getParent(first)
|
const parent = document.getParent(first)
|
||||||
const index = parent.nodes.indexOf(first)
|
const index = parent.nodes.indexOf(first)
|
||||||
|
|
||||||
transform.insertNodeByKey(parent.key, index + 1, block)
|
transform.insertNodeByKey(parent.key, index, block)
|
||||||
|
|
||||||
siblings.forEach((node, i) => {
|
siblings.forEach((node, i) => {
|
||||||
transform.moveNodeByKey(node.key, block.key, i)
|
transform.moveNodeByKey(node.key, block.key, i)
|
||||||
@@ -818,8 +818,8 @@ export function wrapInlineAtRange(transform, range, inline) {
|
|||||||
const startNode = inline.merge({ key: uid() })
|
const startNode = inline.merge({ key: uid() })
|
||||||
const endNode = inline.merge({ key: uid() })
|
const endNode = inline.merge({ key: uid() })
|
||||||
|
|
||||||
transform.insertNodeByKey(startBlock.key, startIndex + 1, startNode)
|
transform.insertNodeByKey(startBlock.key, startIndex - 1, startNode)
|
||||||
transform.insertNodeByKey(endBlock.key, endIndex + 1, endNode)
|
transform.insertNodeByKey(endBlock.key, endIndex, endNode)
|
||||||
|
|
||||||
startInlines.forEach((child, i) => {
|
startInlines.forEach((child, i) => {
|
||||||
transform.moveNodeByKey(child.key, startNode.key, i)
|
transform.moveNodeByKey(child.key, startNode.key, i)
|
||||||
|
@@ -16,22 +16,28 @@ import uid from '../utils/uid'
|
|||||||
export function addMarkByKey(transform, key, offset, length, mark) {
|
export function addMarkByKey(transform, key, offset, length, mark) {
|
||||||
mark = Normalize.mark(mark)
|
mark = Normalize.mark(mark)
|
||||||
|
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const path = document.getPath(node)
|
|
||||||
|
|
||||||
node = node.addMark(offset, length, mark)
|
const inverse = {
|
||||||
document = document.updateDescendant(node)
|
type: 'remove_mark',
|
||||||
state = state.merge({ document })
|
path,
|
||||||
|
offset,
|
||||||
return transform.add(state, {
|
|
||||||
type: 'add-mark',
|
|
||||||
length,
|
length,
|
||||||
mark,
|
mark,
|
||||||
offset,
|
}
|
||||||
|
|
||||||
|
const operation = {
|
||||||
|
type: 'add_mark',
|
||||||
path,
|
path,
|
||||||
})
|
offset,
|
||||||
|
length,
|
||||||
|
mark,
|
||||||
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,23 +51,25 @@ export function addMarkByKey(transform, key, offset, length, mark) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function insertNodeByKey(transform, key, index, node) {
|
export function insertNodeByKey(transform, key, index, node) {
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let parent = document.key == key ? document : document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const isParent = document == parent
|
const newPath = path.slice().push(index)
|
||||||
const path = document.getPath(parent)
|
|
||||||
const nodes = parent.nodes.splice(index, 0, node)
|
|
||||||
|
|
||||||
parent = parent.merge({ nodes })
|
const inverse = {
|
||||||
document = isParent ? parent : document.updateDescendant(parent)
|
type: 'remove_node',
|
||||||
state = state.merge({ document })
|
path: newPath,
|
||||||
|
}
|
||||||
|
|
||||||
return transform.add(state, {
|
const operation = {
|
||||||
type: 'insert-node',
|
type: 'insert_node',
|
||||||
|
path,
|
||||||
index,
|
index,
|
||||||
node,
|
node,
|
||||||
path,
|
inverse,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,22 +84,26 @@ export function insertNodeByKey(transform, key, index, node) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function insertTextByKey(transform, key, offset, text, marks) {
|
export function insertTextByKey(transform, key, offset, text, marks) {
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const path = document.getPath(node)
|
|
||||||
|
|
||||||
node = node.insertText(offset, text, marks)
|
const inverse = {
|
||||||
document = document.updateDescendant(node)
|
type: 'remove_text',
|
||||||
state = state.merge({ document })
|
|
||||||
|
|
||||||
return transform.add(state, {
|
|
||||||
type: 'insert-text',
|
|
||||||
offset,
|
|
||||||
marks,
|
|
||||||
path,
|
path,
|
||||||
|
offset,
|
||||||
|
length: text.length,
|
||||||
|
}
|
||||||
|
|
||||||
|
const operation = {
|
||||||
|
type: 'insert_text',
|
||||||
|
path,
|
||||||
|
offset,
|
||||||
text,
|
text,
|
||||||
})
|
marks,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,32 +117,32 @@ export function insertTextByKey(transform, key, offset, text, marks) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function moveNodeByKey(transform, key, newKey, newIndex) {
|
export function moveNodeByKey(transform, key, newKey, newIndex) {
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
const node = document.assertDescendant(key)
|
const node = document.assertDescendant(key)
|
||||||
const path = document.getPath(node)
|
const path = document.getPath(key)
|
||||||
|
const parent = document.getParent(key)
|
||||||
|
const parentPath = path.slice(0, -1)
|
||||||
|
const parentIndex = path[path.length - 1]
|
||||||
const newPath = document.getPath(newKey)
|
const newPath = document.getPath(newKey)
|
||||||
let parent = document.getParent(node)
|
const nodePath = newPath.slice().concat([newIndex])
|
||||||
const isParent = document == parent
|
|
||||||
const index = parent.nodes.indexOf(node)
|
|
||||||
|
|
||||||
parent = parent.removeNode(index)
|
const inverse = {
|
||||||
document = isParent ? parent : document.updateDescendant(parent)
|
type: 'move_node',
|
||||||
|
path: nodePath,
|
||||||
|
newPath: parentPath,
|
||||||
|
newIndex: parentIndex,
|
||||||
|
}
|
||||||
|
|
||||||
let target = document.key == newKey ? document : document.assertDescendant(newKey)
|
const operation = {
|
||||||
const isTarget = document == target
|
type: 'move_node',
|
||||||
|
|
||||||
target = target.insertNode(newIndex, node)
|
|
||||||
document = isTarget ? target : document.updateDescendant(target)
|
|
||||||
// document = document.normalize()
|
|
||||||
state = state.merge({ document })
|
|
||||||
|
|
||||||
return transform.add(state, {
|
|
||||||
type: 'move-node',
|
|
||||||
path,
|
path,
|
||||||
newPath,
|
newPath,
|
||||||
newIndex,
|
newIndex,
|
||||||
})
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,22 +159,28 @@ export function moveNodeByKey(transform, key, newKey, newIndex) {
|
|||||||
export function removeMarkByKey(transform, key, offset, length, mark) {
|
export function removeMarkByKey(transform, key, offset, length, mark) {
|
||||||
mark = Normalize.mark(mark)
|
mark = Normalize.mark(mark)
|
||||||
|
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const path = document.getPath(node)
|
|
||||||
|
|
||||||
node = node.removeMark(offset, length, mark)
|
const inverse = {
|
||||||
document = document.updateDescendant(node)
|
type: 'add_mark',
|
||||||
state = state.merge({ document })
|
path,
|
||||||
|
|
||||||
return transform.add(state, {
|
|
||||||
type: 'remove-mark',
|
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
mark,
|
mark,
|
||||||
|
}
|
||||||
|
|
||||||
|
const operation = {
|
||||||
|
type: 'remove_mark',
|
||||||
path,
|
path,
|
||||||
})
|
offset,
|
||||||
|
length,
|
||||||
|
mark,
|
||||||
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,23 +192,27 @@ export function removeMarkByKey(transform, key, offset, length, mark) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function removeNodeByKey(transform, key) {
|
export function removeNodeByKey(transform, key) {
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
const node = document.assertDescendant(key)
|
const node = document.assertDescendant(key)
|
||||||
const path = document.getPath(node)
|
const path = document.getPath(key)
|
||||||
let parent = document.getParent(node)
|
const parentPath = path.slice(0, -1)
|
||||||
const index = parent.nodes.indexOf(node)
|
const parentIndex = path.slice(-1)
|
||||||
const isParent = document == parent
|
|
||||||
|
|
||||||
parent = parent.removeNode(index)
|
const inverse = {
|
||||||
document = isParent ? parent : document.updateDescendant(parent)
|
type: 'insert_node',
|
||||||
document = document.normalize()
|
path: parentPath,
|
||||||
state = state.merge({ document })
|
index: parentIndex,
|
||||||
|
node,
|
||||||
|
}
|
||||||
|
|
||||||
return transform.add(state, {
|
const operation = {
|
||||||
type: 'remove-node',
|
type: 'remove_node',
|
||||||
path,
|
path,
|
||||||
})
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,22 +226,22 @@ export function removeNodeByKey(transform, key) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function removeTextByKey(transform, key, offset, length) {
|
export function removeTextByKey(transform, key, offset, length) {
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const path = document.getPath(node)
|
|
||||||
|
|
||||||
node = node.removeText(offset, length)
|
// TODO!
|
||||||
document = document.updateDescendant(node)
|
const inverse = {}
|
||||||
document = document.normalize()
|
|
||||||
state = state.merge({ document })
|
|
||||||
|
|
||||||
return transform.add(state, {
|
const operation = {
|
||||||
type: 'remove-text',
|
type: 'remove_text',
|
||||||
|
path,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
path,
|
inverse,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,23 +259,23 @@ export function setMarkByKey(transform, key, offset, length, mark, properties) {
|
|||||||
mark = Normalize.mark(mark)
|
mark = Normalize.mark(mark)
|
||||||
properties = Normalize.markProperties(properties)
|
properties = Normalize.markProperties(properties)
|
||||||
|
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const path = document.getPath(node)
|
|
||||||
|
|
||||||
node = node.updateMark(offset, length, mark, properties)
|
// TODO!
|
||||||
document = document.updateDescendant(node)
|
const inverse = {}
|
||||||
state = state.merge({ document })
|
|
||||||
|
|
||||||
return transform.add(state, {
|
const operation = {
|
||||||
type: 'set-mark',
|
type: 'set_mark',
|
||||||
|
path,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
mark,
|
mark,
|
||||||
path,
|
|
||||||
properties,
|
properties,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -268,21 +290,30 @@ export function setMarkByKey(transform, key, offset, length, mark, properties) {
|
|||||||
export function setNodeByKey(transform, key, properties) {
|
export function setNodeByKey(transform, key, properties) {
|
||||||
properties = Normalize.nodeProperties(properties)
|
properties = Normalize.nodeProperties(properties)
|
||||||
|
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const node = document.assertDescendant(key)
|
||||||
const path = document.getPath(node)
|
const path = document.getPath(key)
|
||||||
|
const prevProps = {}
|
||||||
|
|
||||||
node = node.merge(properties)
|
for (const k in properties) {
|
||||||
document = document.updateDescendant(node)
|
prevProps[k] = node[k]
|
||||||
document = document.normalize()
|
}
|
||||||
state = state.merge({ document })
|
|
||||||
|
|
||||||
return transform.add(state, {
|
const inverse = {
|
||||||
type: 'set-node',
|
type: 'set_node',
|
||||||
|
path,
|
||||||
|
properties: prevProps
|
||||||
|
}
|
||||||
|
|
||||||
|
const operation = {
|
||||||
|
type: 'set_node',
|
||||||
path,
|
path,
|
||||||
properties,
|
properties,
|
||||||
})
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,53 +326,20 @@ export function setNodeByKey(transform, key, properties) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function splitNodeByKey(transform, key, offset) {
|
export function splitNodeByKey(transform, key, offset) {
|
||||||
let { state } = transform
|
const { state } = transform
|
||||||
let { document } = state
|
const { document } = state
|
||||||
let node = document.assertDescendant(key)
|
const path = document.getPath(key)
|
||||||
const path = document.getPath(node)
|
|
||||||
let parent = document.getParent(node)
|
|
||||||
const isParent = document == parent
|
|
||||||
const index = parent.nodes.indexOf(node)
|
|
||||||
|
|
||||||
let child = node
|
// TODO!
|
||||||
let one
|
const inverse = {}
|
||||||
let two
|
|
||||||
|
|
||||||
if (node.kind != 'text') {
|
const operation = {
|
||||||
child = node.getTextAtOffset(offset)
|
type: 'split_node',
|
||||||
}
|
|
||||||
|
|
||||||
while (child && child != parent) {
|
|
||||||
if (child.kind == 'text') {
|
|
||||||
const i = node.kind == 'text' ? offset : offset - node.getOffset(child)
|
|
||||||
const { characters } = child
|
|
||||||
const oneChars = characters.take(i)
|
|
||||||
const twoChars = characters.skip(i)
|
|
||||||
one = child.merge({ characters: oneChars })
|
|
||||||
two = child.merge({ characters: twoChars, key: uid() })
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
const { nodes } = child
|
|
||||||
const oneNodes = nodes.takeUntil(n => n.key == one.key).push(one)
|
|
||||||
const twoNodes = nodes.skipUntil(n => n.key == one.key).rest().unshift(two)
|
|
||||||
one = child.merge({ nodes: oneNodes })
|
|
||||||
two = child.merge({ nodes: twoNodes, key: uid() })
|
|
||||||
}
|
|
||||||
|
|
||||||
child = document.getParent(child)
|
|
||||||
}
|
|
||||||
|
|
||||||
parent = parent.removeNode(index)
|
|
||||||
parent = parent.insertNode(index, two)
|
|
||||||
parent = parent.insertNode(index, one)
|
|
||||||
document = isParent ? parent : document.updateDescendant(parent)
|
|
||||||
state = state.merge({ document })
|
|
||||||
|
|
||||||
return transform.add(state, {
|
|
||||||
type: 'split-node',
|
|
||||||
offset,
|
|
||||||
path,
|
path,
|
||||||
})
|
offset,
|
||||||
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -98,7 +98,7 @@ import {
|
|||||||
moveTo,
|
moveTo,
|
||||||
moveToOffsets,
|
moveToOffsets,
|
||||||
moveToRangeOf,
|
moveToRangeOf,
|
||||||
updateSelection,
|
setSelection,
|
||||||
} from './on-selection'
|
} from './on-selection'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,7 +210,7 @@ export default {
|
|||||||
moveTo,
|
moveTo,
|
||||||
moveToOffsets,
|
moveToOffsets,
|
||||||
moveToRangeOf,
|
moveToRangeOf,
|
||||||
updateSelection,
|
setSelection,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize.
|
* Normalize.
|
||||||
|
@@ -13,7 +13,15 @@ export function blur(transform) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const sel = selection.blur()
|
const sel = selection.blur()
|
||||||
return transform.updateSelection(sel)
|
|
||||||
|
return transform.operate({
|
||||||
|
type: 'set_selection',
|
||||||
|
selection: sel,
|
||||||
|
inverse: {
|
||||||
|
type: 'set_selection',
|
||||||
|
selection,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,7 +35,7 @@ export function collapseToAnchor(transform) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const sel = selection.collapseToAnchor()
|
const sel = selection.collapseToAnchor()
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,7 +49,7 @@ export function collapseToFocus(transform) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const sel = selection.collapseToFocus()
|
const sel = selection.collapseToFocus()
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +64,7 @@ export function collapseToEndOf(transform, node) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const sel = selection.collapseToEndOf(node)
|
const sel = selection.collapseToEndOf(node)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +83,7 @@ export function collapseToEndOfNextBlock(transform) {
|
|||||||
if (!next) return transform
|
if (!next) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToEndOf(next)
|
const sel = selection.collapseToEndOf(next)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,7 +102,7 @@ export function collapseToEndOfNextText(transform) {
|
|||||||
if (!next) return transform
|
if (!next) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToEndOf(next)
|
const sel = selection.collapseToEndOf(next)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,7 +121,7 @@ export function collapseToEndOfPreviousBlock(transform) {
|
|||||||
if (!previous) return transform
|
if (!previous) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToEndOf(previous)
|
const sel = selection.collapseToEndOf(previous)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +140,7 @@ export function collapseToEndOfPreviousText(transform) {
|
|||||||
if (!previous) return transform
|
if (!previous) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToEndOf(previous)
|
const sel = selection.collapseToEndOf(previous)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,7 +155,7 @@ export function collapseToStartOf(transform, node) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const sel = selection.collapseToStartOf(node)
|
const sel = selection.collapseToStartOf(node)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,7 +174,7 @@ export function collapseToStartOfNextBlock(transform) {
|
|||||||
if (!next) return transform
|
if (!next) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToStartOf(next)
|
const sel = selection.collapseToStartOf(next)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +193,7 @@ export function collapseToStartOfNextText(transform) {
|
|||||||
if (!next) return transform
|
if (!next) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToStartOf(next)
|
const sel = selection.collapseToStartOf(next)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,7 +212,7 @@ export function collapseToStartOfPreviousBlock(transform) {
|
|||||||
if (!previous) return transform
|
if (!previous) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToStartOf(previous)
|
const sel = selection.collapseToStartOf(previous)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,7 +231,7 @@ export function collapseToStartOfPreviousText(transform) {
|
|||||||
if (!previous) return transform
|
if (!previous) return transform
|
||||||
|
|
||||||
const sel = selection.collapseToStartOf(previous)
|
const sel = selection.collapseToStartOf(previous)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,7 +246,7 @@ export function extendBackward(transform, n) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.extendBackward(n).normalize(document)
|
const sel = selection.extendBackward(n).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,7 +261,7 @@ export function extendForward(transform, n) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.extendForward(n).normalize(document)
|
const sel = selection.extendForward(n).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -268,7 +276,7 @@ export function extendToEndOf(transform, node) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.extendToEndOf(node).normalize(document)
|
const sel = selection.extendToEndOf(node).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,7 +291,7 @@ export function extendToStartOf(transform, node) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.extendToStartOf(node).normalize(document)
|
const sel = selection.extendToStartOf(node).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -297,7 +305,7 @@ export function focus(transform) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const sel = selection.focus()
|
const sel = selection.focus()
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,7 +320,7 @@ export function moveBackward(transform, n) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.moveBackward(n).normalize(document)
|
const sel = selection.moveBackward(n).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -327,7 +335,7 @@ export function moveForward(transform, n) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.moveForward(n).normalize(document)
|
const sel = selection.moveForward(n).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,7 +351,7 @@ export function moveTo(transform, properties) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.merge(properties).normalize(document)
|
const sel = selection.merge(properties).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -359,7 +367,7 @@ export function moveToOffsets(transform, anchor, fokus) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.moveToOffsets(anchor, fokus)
|
const sel = selection.moveToOffsets(anchor, fokus)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -375,27 +383,31 @@ export function moveToRangeOf(transform, start, end) {
|
|||||||
const { state } = transform
|
const { state } = transform
|
||||||
const { document, selection } = state
|
const { document, selection } = state
|
||||||
const sel = selection.moveToRangeOf(start, end).normalize(document)
|
const sel = selection.moveToRangeOf(start, end).normalize(document)
|
||||||
return transform.updateSelection(sel)
|
return transform.setSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the selection with a new `selection`.
|
* Set the selection to a new `selection`.
|
||||||
*
|
*
|
||||||
* @param {Transform} transform
|
* @param {Transform} transform
|
||||||
* @param {Mixed} sel
|
* @param {Mixed} selection
|
||||||
* @return {Transform}
|
* @return {Transform}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function updateSelection(transform, sel) {
|
export function setSelection(transform, selection) {
|
||||||
sel = Normalize.selection(sel)
|
selection = Normalize.selection(selection)
|
||||||
|
const { state } = transform
|
||||||
|
|
||||||
let { state } = transform
|
const inverse = {
|
||||||
let { selection } = state
|
type: 'set_selection',
|
||||||
selection = selection.merge(sel)
|
selection: state.selection,
|
||||||
state = state.merge({ selection })
|
}
|
||||||
|
|
||||||
return transform.add(state, {
|
const operation = {
|
||||||
type: 'update-selection',
|
type: 'set_selection',
|
||||||
selection,
|
selection,
|
||||||
})
|
inverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.operate(operation)
|
||||||
}
|
}
|
||||||
|
279
lib/transforms/operations.js
Normal file
279
lib/transforms/operations.js
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
|
||||||
|
import uid from '../utils/uid'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add mark to text at `offset` and `length` in node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addMark(state, operation) {
|
||||||
|
const { path, offset, length, mark } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
node = node.addMark(offset, length, mark)
|
||||||
|
document = document.updateDescendant(node)
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a `node` at `index` in a node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function insertNode(state, operation) {
|
||||||
|
const { path, index, node } = operation
|
||||||
|
let { document } = state
|
||||||
|
let parent = document.assertPath(path)
|
||||||
|
const isParent = document == parent
|
||||||
|
const nodes = parent.nodes.splice(index, 0, node)
|
||||||
|
parent = parent.merge({ nodes })
|
||||||
|
document = isParent ? parent : document.updateDescendant(parent)
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert `text` at `offset` in node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function insertText(state, operation) {
|
||||||
|
const { path, offset, text, marks } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
node = node.insertText(offset, text, marks)
|
||||||
|
document = document.updateDescendant(node)
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a node by `key` to a new parent by `key` and `index`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function moveNode(state, operation) {
|
||||||
|
const { path, newPath, newIndex } = operation
|
||||||
|
let { document } = state
|
||||||
|
const node = document.assertPath(path)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
let target = document.assertPath(newPath)
|
||||||
|
const isTarget = document == target
|
||||||
|
target = target.insertNode(newIndex, node)
|
||||||
|
document = isTarget ? target : document.updateDescendant(target)
|
||||||
|
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove mark from text at `offset` and `length` in node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function removeMark(state, operation) {
|
||||||
|
const { path, offset, length, mark } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
node = node.removeMark(offset, length, mark)
|
||||||
|
document = document.updateDescendant(node)
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function removeNode(state, operation) {
|
||||||
|
const { path } = operation
|
||||||
|
let { document } = state
|
||||||
|
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)
|
||||||
|
document = document.normalize()
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove text at `offset` and `length` in node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function removeText(state, operation) {
|
||||||
|
const { path, offset, length } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
node = node.removeText(offset, length)
|
||||||
|
document = document.updateDescendant(node)
|
||||||
|
document = document.normalize()
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set `properties` on mark on text at `offset` and `length` in node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function setMark(state, operation) {
|
||||||
|
const { path, offset, length, mark, properties } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
node = node.updateMark(offset, length, mark, properties)
|
||||||
|
document = document.updateDescendant(node)
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set `properties` on a node by `key`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function setNode(state, operation) {
|
||||||
|
const { path, properties } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
node = node.merge(properties)
|
||||||
|
document = document.updateDescendant(node)
|
||||||
|
document = document.normalize()
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the selection to a new `selection`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function setSelection(state, operation) {
|
||||||
|
let { selection } = operation
|
||||||
|
selection = state.selection.merge(selection)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split a node by `key` at `offset`.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Object} operation
|
||||||
|
* @return {State}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function splitNode(state, operation) {
|
||||||
|
const { path, offset } = operation
|
||||||
|
let { document } = state
|
||||||
|
let node = document.assertPath(path)
|
||||||
|
let parent = document.getParent(node)
|
||||||
|
const isParent = document == parent
|
||||||
|
const index = parent.nodes.indexOf(node)
|
||||||
|
|
||||||
|
let child = node
|
||||||
|
let one
|
||||||
|
let two
|
||||||
|
|
||||||
|
if (node.kind != 'text') {
|
||||||
|
child = node.getTextAtOffset(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (child && child != parent) {
|
||||||
|
if (child.kind == 'text') {
|
||||||
|
const i = node.kind == 'text' ? offset : offset - node.getOffset(child)
|
||||||
|
const { characters } = child
|
||||||
|
const oneChars = characters.take(i)
|
||||||
|
const twoChars = characters.skip(i)
|
||||||
|
one = child.merge({ characters: oneChars })
|
||||||
|
two = child.merge({ characters: twoChars, key: uid() })
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
const { nodes } = child
|
||||||
|
const oneNodes = nodes.takeUntil(n => n.key == one.key).push(one)
|
||||||
|
const twoNodes = nodes.skipUntil(n => n.key == one.key).rest().unshift(two)
|
||||||
|
one = child.merge({ nodes: oneNodes })
|
||||||
|
two = child.merge({ nodes: twoNodes, key: uid() })
|
||||||
|
}
|
||||||
|
|
||||||
|
child = document.getParent(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent.removeNode(index)
|
||||||
|
parent = parent.insertNode(index, two)
|
||||||
|
parent = parent.insertNode(index, one)
|
||||||
|
document = isParent ? parent : document.updateDescendant(parent)
|
||||||
|
state = state.merge({ document })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
// Text operations.
|
||||||
|
insert_text: insertText,
|
||||||
|
remove_text: removeText,
|
||||||
|
|
||||||
|
// Mark operations.
|
||||||
|
add_mark: addMark,
|
||||||
|
remove_mark: removeMark,
|
||||||
|
set_mark: setMark,
|
||||||
|
|
||||||
|
// Node operations.
|
||||||
|
insert_node: insertNode,
|
||||||
|
move_node: moveNode,
|
||||||
|
remove_node: removeNode,
|
||||||
|
set_node: setNode,
|
||||||
|
split_node: splitNode,
|
||||||
|
|
||||||
|
// Selection operations.
|
||||||
|
set_selection: setSelection,
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user