mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-30 18:39:51 +02:00
Make all ops invertible and remove value
from ops (#2225)
This commit is contained in:
committed by
Ian Storm Taylor
parent
f0e37810a2
commit
bb5d6beffa
@@ -472,10 +472,10 @@ Remove `length` characters of text starting at an `offset` in a [`Node`](./node.
|
|||||||
|
|
||||||
### `setMarkByKey/Path`
|
### `setMarkByKey/Path`
|
||||||
|
|
||||||
`setMarkByKey(key: String, offset: Number, length: Number, mark: Mark, properties: Object) => Editor`
|
`setMarkByKey(key: String, offset: Number, length: Number, properties: Object, newProperties: Object) => Editor`
|
||||||
`setMarkByPath(path: List, offset: Number, length: Number, mark: Mark, properties: Object) => Editor`
|
`setMarkByPath(path: List, offset: Number, length: Number, properties: Object, newProperties: Object) => Editor`
|
||||||
|
|
||||||
Set a dictionary of `properties` on a [`mark`](./mark.md) on a [`Node`](./node.md) by its `key` or `path`.
|
Set a dictionary of `newProperties` on a [`mark`](./mark.md) on a [`Node`](./node.md) by its `key` or `path`.
|
||||||
|
|
||||||
### `setNodeByKey/Path`
|
### `setNodeByKey/Path`
|
||||||
|
|
||||||
|
@@ -83,13 +83,13 @@ Removes a `mark` from a text node at `path` starting at an `offset` and spanning
|
|||||||
path: List,
|
path: List,
|
||||||
offset: Number,
|
offset: Number,
|
||||||
length: Number,
|
length: Number,
|
||||||
mark: Mark,
|
|
||||||
properties: Object,
|
properties: Object,
|
||||||
|
newProperties: Object,
|
||||||
data: Map,
|
data: Map,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Set new `properties` on any marks that match an existing `mark` in a text node at `path`, starting at an `offset` and spanning `length` characters.
|
Set new `newProperties` on any marks that match an existing `properties` mark in a text node at `path`, starting at an `offset` and spanning `length` characters.
|
||||||
|
|
||||||
## Node Operations
|
## Node Operations
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ Remove the node at `path`.
|
|||||||
type: 'set_node',
|
type: 'set_node',
|
||||||
path: List,
|
path: List,
|
||||||
properties: Object,
|
properties: Object,
|
||||||
node: Node,
|
newProperties: Object,
|
||||||
data: Map,
|
data: Map,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -183,7 +183,7 @@ Split the node at `path` at `position`. The `position` refers to either the inde
|
|||||||
{
|
{
|
||||||
type: 'set_selection',
|
type: 'set_selection',
|
||||||
properties: Object,
|
properties: Object,
|
||||||
selection: Selection,
|
newProperties: Object,
|
||||||
data: Map,
|
data: Map,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -196,7 +196,7 @@ Set new `properties` on the selection.
|
|||||||
{
|
{
|
||||||
type: 'set_value',
|
type: 'set_value',
|
||||||
properties: Object,
|
properties: Object,
|
||||||
value: Value,
|
newProperties: Object,
|
||||||
data: Map,
|
data: Map,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@@ -71,8 +71,8 @@ class History extends React.Component {
|
|||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
onChange = ({ value }) => {
|
onChange = change => {
|
||||||
this.setState({ value })
|
this.setState({ value: change.value })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import pick from 'lodash/pick'
|
||||||
import Block from '../models/block'
|
import Block from '../models/block'
|
||||||
import Inline from '../models/inline'
|
import Inline from '../models/inline'
|
||||||
import Mark from '../models/mark'
|
import Mark from '../models/mark'
|
||||||
@@ -52,7 +53,6 @@ Commands.addMarkByPath = (editor, path, offset, length, mark) => {
|
|||||||
|
|
||||||
operations.push({
|
operations.push({
|
||||||
type: 'add_mark',
|
type: 'add_mark',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
offset: start,
|
offset: start,
|
||||||
length: end - start,
|
length: end - start,
|
||||||
@@ -88,11 +88,8 @@ Commands.insertFragmentByPath = (editor, path, index, fragment) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Commands.insertNodeByPath = (editor, path, index, node) => {
|
Commands.insertNodeByPath = (editor, path, index, node) => {
|
||||||
const { value } = editor
|
|
||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'insert_node',
|
type: 'insert_node',
|
||||||
value,
|
|
||||||
path: path.concat(index),
|
path: path.concat(index),
|
||||||
node,
|
node,
|
||||||
})
|
})
|
||||||
@@ -137,7 +134,6 @@ Commands.insertTextByPath = (editor, path, offset, text, marks) => {
|
|||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'insert_text',
|
type: 'insert_text',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
offset,
|
offset,
|
||||||
text,
|
text,
|
||||||
@@ -169,7 +165,6 @@ Commands.mergeNodeByPath = (editor, path) => {
|
|||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'merge_node',
|
type: 'merge_node',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
position,
|
position,
|
||||||
// for undos to succeed we only need the type and data because
|
// for undos to succeed we only need the type and data because
|
||||||
@@ -192,8 +187,6 @@ Commands.mergeNodeByPath = (editor, path) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Commands.moveNodeByPath = (editor, path, newParentPath, newIndex) => {
|
Commands.moveNodeByPath = (editor, path, newParentPath, newIndex) => {
|
||||||
const { value } = editor
|
|
||||||
|
|
||||||
// If the operation path and newParentPath are the same,
|
// If the operation path and newParentPath are the same,
|
||||||
// this should be considered a NOOP
|
// this should be considered a NOOP
|
||||||
if (PathUtils.isEqual(path, newParentPath)) {
|
if (PathUtils.isEqual(path, newParentPath)) {
|
||||||
@@ -208,7 +201,6 @@ Commands.moveNodeByPath = (editor, path, newParentPath, newIndex) => {
|
|||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'move_node',
|
type: 'move_node',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
newPath,
|
newPath,
|
||||||
})
|
})
|
||||||
@@ -254,7 +246,6 @@ Commands.removeMarkByPath = (editor, path, offset, length, mark) => {
|
|||||||
|
|
||||||
operations.push({
|
operations.push({
|
||||||
type: 'remove_mark',
|
type: 'remove_mark',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
offset: start,
|
offset: start,
|
||||||
length: end - start,
|
length: end - start,
|
||||||
@@ -299,7 +290,6 @@ Commands.removeNodeByPath = (editor, path) => {
|
|||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'remove_node',
|
type: 'remove_node',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
node,
|
node,
|
||||||
})
|
})
|
||||||
@@ -370,7 +360,6 @@ Commands.removeTextByPath = (editor, path, offset, length) => {
|
|||||||
|
|
||||||
removals.push({
|
removals.push({
|
||||||
type: 'remove_text',
|
type: 'remove_text',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
offset: start,
|
offset: start,
|
||||||
text: string,
|
text: string,
|
||||||
@@ -447,28 +436,35 @@ Commands.replaceTextByPath = (editor, path, offset, length, text, marks) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set `properties` on mark on text at `offset` and `length` in node by `path`.
|
* Set `newProperties` on mark on text at `offset` and `length` in node by `path`.
|
||||||
*
|
*
|
||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
* @param {Array} path
|
* @param {Array} path
|
||||||
* @param {Number} offset
|
* @param {Number} offset
|
||||||
* @param {Number} length
|
* @param {Number} length
|
||||||
* @param {Mark} mark
|
* @param {Object|Mark} properties
|
||||||
|
* @param {Object} newProperties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Commands.setMarkByPath = (editor, path, offset, length, mark, properties) => {
|
Commands.setMarkByPath = (
|
||||||
mark = Mark.create(mark)
|
editor,
|
||||||
properties = Mark.createProperties(properties)
|
|
||||||
const { value } = editor
|
|
||||||
|
|
||||||
editor.applyOperation({
|
|
||||||
type: 'set_mark',
|
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
mark,
|
|
||||||
properties,
|
properties,
|
||||||
|
newProperties
|
||||||
|
) => {
|
||||||
|
// we call Mark.create() here because we need the complete previous mark instance
|
||||||
|
properties = Mark.create(properties)
|
||||||
|
newProperties = Mark.createProperties(newProperties)
|
||||||
|
|
||||||
|
editor.applyOperation({
|
||||||
|
type: 'set_mark',
|
||||||
|
path,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
properties,
|
||||||
|
newProperties,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,21 +473,21 @@ Commands.setMarkByPath = (editor, path, offset, length, mark, properties) => {
|
|||||||
*
|
*
|
||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
* @param {Array} path
|
* @param {Array} path
|
||||||
* @param {Object|String} properties
|
* @param {Object|String} newProperties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Commands.setNodeByPath = (editor, path, properties) => {
|
Commands.setNodeByPath = (editor, path, newProperties) => {
|
||||||
properties = Node.createProperties(properties)
|
|
||||||
const { value } = editor
|
const { value } = editor
|
||||||
const { document } = value
|
const { document } = value
|
||||||
const node = document.assertNode(path)
|
const node = document.assertNode(path)
|
||||||
|
newProperties = Node.createProperties(newProperties)
|
||||||
|
const prevProperties = pick(node, Object.keys(newProperties))
|
||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'set_node',
|
type: 'set_node',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
node,
|
properties: prevProperties,
|
||||||
properties,
|
newProperties,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +525,6 @@ Commands.splitNodeByPath = (editor, path, position, options = {}) => {
|
|||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'split_node',
|
type: 'split_node',
|
||||||
value,
|
|
||||||
path,
|
path,
|
||||||
position,
|
position,
|
||||||
target,
|
target,
|
||||||
|
@@ -592,7 +592,7 @@ Commands.select = (editor, properties, options = {}) => {
|
|||||||
const { snapshot = false } = options
|
const { snapshot = false } = options
|
||||||
const { value } = editor
|
const { value } = editor
|
||||||
const { document, selection } = value
|
const { document, selection } = value
|
||||||
const props = {}
|
const newProperties = {}
|
||||||
let next = selection.setProperties(properties)
|
let next = selection.setProperties(properties)
|
||||||
next = document.resolveSelection(next)
|
next = document.resolveSelection(next)
|
||||||
|
|
||||||
@@ -604,27 +604,34 @@ Commands.select = (editor, properties, options = {}) => {
|
|||||||
// are being changed, for the inverse operation.
|
// are being changed, for the inverse operation.
|
||||||
for (const k in properties) {
|
for (const k in properties) {
|
||||||
if (snapshot === true || !is(properties[k], selection[k])) {
|
if (snapshot === true || !is(properties[k], selection[k])) {
|
||||||
props[k] = properties[k]
|
newProperties[k] = properties[k]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the selection moves, clear any marks, unless the new selection
|
// If the selection moves, clear any marks, unless the new selection
|
||||||
// properties editor the marks in some way.
|
// properties change the marks in some way.
|
||||||
if (selection.marks && !props.marks && (props.anchor || props.focus)) {
|
if (
|
||||||
props.marks = null
|
selection.marks &&
|
||||||
|
!newProperties.marks &&
|
||||||
|
(newProperties.anchor || newProperties.focus)
|
||||||
|
) {
|
||||||
|
newProperties.marks = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no new properties to set, abort to avoid extra operations.
|
// If there are no new properties to set, abort to avoid extra operations.
|
||||||
if (Object.keys(props).length === 0) {
|
if (Object.keys(newProperties).length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: for some reason toJSON() is required here (it breaks selections between blocks)? - 2018-10-10
|
||||||
|
const prevProperties = pick(selection.toJSON(), Object.keys(newProperties))
|
||||||
|
|
||||||
editor.applyOperation(
|
editor.applyOperation(
|
||||||
{
|
{
|
||||||
type: 'set_selection',
|
type: 'set_selection',
|
||||||
value,
|
value,
|
||||||
properties: props,
|
properties: prevProperties,
|
||||||
selection: selection.toJSON(),
|
newProperties,
|
||||||
},
|
},
|
||||||
snapshot ? { skip: false, merge: false } : {}
|
snapshot ? { skip: false, merge: false } : {}
|
||||||
)
|
)
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import pick from 'lodash/pick'
|
||||||
import Value from '../models/value'
|
import Value from '../models/value'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,13 +17,14 @@ const Commands = {}
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Commands.setData = (editor, data = {}) => {
|
Commands.setData = (editor, data = {}) => {
|
||||||
const properties = Value.createProperties({ data })
|
|
||||||
const { value } = editor
|
const { value } = editor
|
||||||
|
const newProperties = Value.createProperties({ data })
|
||||||
|
const prevProperties = pick(value, Object.keys(newProperties))
|
||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'set_value',
|
type: 'set_value',
|
||||||
properties,
|
properties: prevProperties,
|
||||||
value,
|
newProperties,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,13 +36,14 @@ Commands.setData = (editor, data = {}) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Commands.setDecorations = (editor, decorations = []) => {
|
Commands.setDecorations = (editor, decorations = []) => {
|
||||||
const properties = Value.createProperties({ decorations })
|
|
||||||
const { value } = editor
|
const { value } = editor
|
||||||
|
const newProperties = Value.createProperties({ decorations })
|
||||||
|
const prevProperties = pick(value, Object.keys(newProperties))
|
||||||
|
|
||||||
editor.applyOperation({
|
editor.applyOperation({
|
||||||
type: 'set_value',
|
type: 'set_value',
|
||||||
properties,
|
properties: prevProperties,
|
||||||
value,
|
newProperties,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2240,9 +2240,9 @@ class ElementInterface {
|
|||||||
* @return {Node}
|
* @return {Node}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
setMark(path, offset, length, mark, properties) {
|
setMark(path, offset, length, properties, newProperties) {
|
||||||
let node = this.assertNode(path)
|
let node = this.assertNode(path)
|
||||||
node = node.updateMark(offset, length, mark, properties)
|
node = node.updateMark(offset, length, properties, newProperties)
|
||||||
const ret = this.replaceNode(path, node)
|
const ret = this.replaceNode(path, node)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
@@ -16,19 +16,19 @@ import invert from '../operations/invert'
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const OPERATION_ATTRIBUTES = {
|
const OPERATION_ATTRIBUTES = {
|
||||||
add_mark: ['value', 'path', 'offset', 'length', 'mark', 'data'],
|
add_mark: ['path', 'offset', 'length', 'mark', 'data'],
|
||||||
insert_node: ['value', 'path', 'node', 'data'],
|
insert_node: ['path', 'node', 'data'],
|
||||||
insert_text: ['value', 'path', 'offset', 'text', 'marks', 'data'],
|
insert_text: ['path', 'offset', 'text', 'marks', 'data'],
|
||||||
merge_node: ['value', 'path', 'position', 'properties', 'target', 'data'],
|
merge_node: ['path', 'position', 'properties', 'target', 'data'],
|
||||||
move_node: ['value', 'path', 'newPath', 'data'],
|
move_node: ['path', 'newPath', 'data'],
|
||||||
remove_mark: ['value', 'path', 'offset', 'length', 'mark', 'data'],
|
remove_mark: ['path', 'offset', 'length', 'mark', 'data'],
|
||||||
remove_node: ['value', 'path', 'node', 'data'],
|
remove_node: ['path', 'node', 'data'],
|
||||||
remove_text: ['value', 'path', 'offset', 'text', 'marks', 'data'],
|
remove_text: ['path', 'offset', 'text', 'marks', 'data'],
|
||||||
set_mark: ['value', 'path', 'offset', 'length', 'mark', 'properties', 'data'],
|
set_mark: ['path', 'offset', 'length', 'properties', 'newProperties', 'data'],
|
||||||
set_node: ['value', 'path', 'node', 'properties', 'data'],
|
set_node: ['path', 'properties', 'newProperties', 'data'],
|
||||||
set_selection: ['value', 'selection', 'properties', 'data'],
|
set_selection: ['properties', 'newProperties', 'data'],
|
||||||
set_value: ['value', 'properties', 'data'],
|
set_value: ['properties', 'newProperties', 'data'],
|
||||||
split_node: ['value', 'path', 'position', 'properties', 'target', 'data'],
|
split_node: ['path', 'position', 'properties', 'target', 'data'],
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,11 +47,10 @@ const DEFAULTS = {
|
|||||||
path: undefined,
|
path: undefined,
|
||||||
position: undefined,
|
position: undefined,
|
||||||
properties: undefined,
|
properties: undefined,
|
||||||
selection: undefined,
|
newProperties: undefined,
|
||||||
target: undefined,
|
target: undefined,
|
||||||
text: undefined,
|
text: undefined,
|
||||||
type: undefined,
|
type: undefined,
|
||||||
value: undefined,
|
|
||||||
data: undefined,
|
data: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,13 +131,6 @@ class Operation extends Record(DEFAULTS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v === undefined) {
|
if (v === undefined) {
|
||||||
// Skip keys for objects that should not be serialized, and are only used
|
|
||||||
// for providing the local-only invert behavior for the history stack.
|
|
||||||
if (key === 'document') continue
|
|
||||||
if (key === 'selection') continue
|
|
||||||
if (key === 'value') continue
|
|
||||||
if (key === 'node' && type !== 'insert_node') continue
|
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`\`Operation.fromJSON\` was passed a "${type}" operation without the required "${key}" attribute.`
|
`\`Operation.fromJSON\` was passed a "${type}" operation without the required "${key}" attribute.`
|
||||||
)
|
)
|
||||||
@@ -160,31 +152,35 @@ class Operation extends Record(DEFAULTS) {
|
|||||||
v = Node.create(v)
|
v = Node.create(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'selection') {
|
|
||||||
v = Selection.create(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === 'value') {
|
|
||||||
v = Value.create(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === 'properties' && type === 'merge_node') {
|
if (key === 'properties' && type === 'merge_node') {
|
||||||
v = Node.createProperties(v)
|
v = Node.createProperties(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_mark') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_mark'
|
||||||
|
) {
|
||||||
v = Mark.createProperties(v)
|
v = Mark.createProperties(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_node') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_node'
|
||||||
|
) {
|
||||||
v = Node.createProperties(v)
|
v = Node.createProperties(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_selection') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_selection'
|
||||||
|
) {
|
||||||
v = Selection.createProperties(v)
|
v = Selection.createProperties(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_value') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_value'
|
||||||
|
) {
|
||||||
v = Value.createProperties(v)
|
v = Value.createProperties(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,13 +248,6 @@ class Operation extends Record(DEFAULTS) {
|
|||||||
for (const key of ATTRIBUTES) {
|
for (const key of ATTRIBUTES) {
|
||||||
let value = this[key]
|
let value = this[key]
|
||||||
|
|
||||||
// Skip keys for objects that should not be serialized, and are only used
|
|
||||||
// for providing the local-only invert behavior for the history stack.
|
|
||||||
if (key === 'document') continue
|
|
||||||
if (key === 'selection') continue
|
|
||||||
if (key === 'value') continue
|
|
||||||
if (key === 'node' && type !== 'insert_node') continue
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
key === 'mark' ||
|
key === 'mark' ||
|
||||||
key === 'marks' ||
|
key === 'marks' ||
|
||||||
@@ -276,21 +265,30 @@ class Operation extends Record(DEFAULTS) {
|
|||||||
value = v
|
value = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_mark') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_mark'
|
||||||
|
) {
|
||||||
const v = {}
|
const v = {}
|
||||||
if ('data' in value) v.data = value.data.toJS()
|
if ('data' in value) v.data = value.data.toJS()
|
||||||
if ('type' in value) v.type = value.type
|
if ('type' in value) v.type = value.type
|
||||||
value = v
|
value = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_node') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_node'
|
||||||
|
) {
|
||||||
const v = {}
|
const v = {}
|
||||||
if ('data' in value) v.data = value.data.toJS()
|
if ('data' in value) v.data = value.data.toJS()
|
||||||
if ('type' in value) v.type = value.type
|
if ('type' in value) v.type = value.type
|
||||||
value = v
|
value = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_selection') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_selection'
|
||||||
|
) {
|
||||||
const v = {}
|
const v = {}
|
||||||
if ('anchor' in value) v.anchor = value.anchor.toJSON()
|
if ('anchor' in value) v.anchor = value.anchor.toJSON()
|
||||||
if ('focus' in value) v.focus = value.focus.toJSON()
|
if ('focus' in value) v.focus = value.focus.toJSON()
|
||||||
@@ -299,7 +297,10 @@ class Operation extends Record(DEFAULTS) {
|
|||||||
value = v
|
value = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'properties' && type === 'set_value') {
|
if (
|
||||||
|
(key === 'properties' || key === 'newProperties') &&
|
||||||
|
type === 'set_value'
|
||||||
|
) {
|
||||||
const v = {}
|
const v = {}
|
||||||
if ('data' in value) v.data = value.data.toJS()
|
if ('data' in value) v.data = value.data.toJS()
|
||||||
if ('decorations' in value) v.decorations = value.decorations.toJS()
|
if ('decorations' in value) v.decorations = value.decorations.toJS()
|
||||||
|
@@ -2,6 +2,7 @@ import isPlainObject from 'is-plain-object'
|
|||||||
import warning from 'tiny-warning'
|
import warning from 'tiny-warning'
|
||||||
import { List, OrderedSet, Record, Set } from 'immutable'
|
import { List, OrderedSet, Record, Set } from 'immutable'
|
||||||
|
|
||||||
|
import Mark from './mark'
|
||||||
import Leaf from './leaf'
|
import Leaf from './leaf'
|
||||||
import KeyUtils from '../utils/key-utils'
|
import KeyUtils from '../utils/key-utils'
|
||||||
import memoize from '../utils/memoize'
|
import memoize from '../utils/memoize'
|
||||||
@@ -572,13 +573,14 @@ class Text extends Record(DEFAULTS) {
|
|||||||
*
|
*
|
||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
* @param {Number} length
|
* @param {Number} length
|
||||||
* @param {Mark} mark
|
|
||||||
* @param {Object} properties
|
* @param {Object} properties
|
||||||
|
* @param {Object} newProperties
|
||||||
* @return {Text}
|
* @return {Text}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
updateMark(index, length, mark, properties) {
|
updateMark(index, length, properties, newProperties) {
|
||||||
const newMark = mark.merge(properties)
|
const mark = Mark.create(properties)
|
||||||
|
const newMark = mark.merge(newProperties)
|
||||||
|
|
||||||
if (this.text === '' && length === 0 && index === 0) {
|
if (this.text === '' && length === 0 && index === 0) {
|
||||||
const { leaves } = this
|
const { leaves } = this
|
||||||
|
@@ -79,26 +79,32 @@ function applyOperation(value, op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'set_mark': {
|
case 'set_mark': {
|
||||||
const { path, offset, length, mark, properties } = op
|
const { path, offset, length, properties, newProperties } = op
|
||||||
const next = value.setMark(path, offset, length, mark, properties)
|
const next = value.setMark(
|
||||||
|
path,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
properties,
|
||||||
|
newProperties
|
||||||
|
)
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'set_node': {
|
case 'set_node': {
|
||||||
const { path, properties } = op
|
const { path, newProperties } = op
|
||||||
const next = value.setNode(path, properties)
|
const next = value.setNode(path, newProperties)
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'set_selection': {
|
case 'set_selection': {
|
||||||
const { properties } = op
|
const { newProperties } = op
|
||||||
const next = value.setSelection(properties)
|
const next = value.setSelection(newProperties)
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'set_value': {
|
case 'set_value': {
|
||||||
const { properties } = op
|
const { newProperties } = op
|
||||||
const next = value.setProperties(properties)
|
const next = value.setProperties(newProperties)
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import Debug from 'debug'
|
import Debug from 'debug'
|
||||||
import pick from 'lodash/pick'
|
|
||||||
|
|
||||||
import Operation from '../models/operation'
|
import Operation from '../models/operation'
|
||||||
import PathUtils from '../utils/path-utils'
|
import PathUtils from '../utils/path-utils'
|
||||||
@@ -74,13 +73,14 @@ function invertOperation(op) {
|
|||||||
return inverse
|
return inverse
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'set_node': {
|
case 'set_node':
|
||||||
const { properties, node } = op
|
case 'set_value':
|
||||||
const inverseNode = node.merge(properties)
|
case 'set_selection':
|
||||||
const inverseProperties = pick(node, Object.keys(properties))
|
case 'set_mark': {
|
||||||
|
const { properties, newProperties } = op
|
||||||
const inverse = op
|
const inverse = op
|
||||||
.set('node', inverseNode)
|
.set('properties', newProperties)
|
||||||
.set('properties', inverseProperties)
|
.set('newProperties', properties)
|
||||||
return inverse
|
return inverse
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,36 +104,6 @@ function invertOperation(op) {
|
|||||||
return inverse
|
return inverse
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'set_mark': {
|
|
||||||
const { properties, mark } = op
|
|
||||||
const inverseMark = mark.merge(properties)
|
|
||||||
const inverseProperties = pick(mark, Object.keys(properties))
|
|
||||||
const inverse = op
|
|
||||||
.set('mark', inverseMark)
|
|
||||||
.set('properties', inverseProperties)
|
|
||||||
return inverse
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'set_selection': {
|
|
||||||
const { properties, selection } = op
|
|
||||||
const inverseSelection = selection.merge(properties)
|
|
||||||
const inverseProps = pick(selection, Object.keys(properties))
|
|
||||||
const inverse = op
|
|
||||||
.set('selection', inverseSelection)
|
|
||||||
.set('properties', inverseProps)
|
|
||||||
return inverse
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'set_value': {
|
|
||||||
const { properties, value } = op
|
|
||||||
const inverseValue = value.merge(properties)
|
|
||||||
const inverseProperties = pick(value, Object.keys(properties))
|
|
||||||
const inverse = op
|
|
||||||
.set('value', inverseValue)
|
|
||||||
.set('properties', inverseProperties)
|
|
||||||
return inverse
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
throw new Error(`Unknown operation type: "${type}".`)
|
throw new Error(`Unknown operation type: "${type}".`)
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,11 @@ export default [
|
|||||||
{
|
{
|
||||||
type: 'remove_node',
|
type: 'remove_node',
|
||||||
path: [0],
|
path: [0],
|
||||||
|
node: (
|
||||||
|
<paragraph>
|
||||||
|
o<highlight key="a" />ne
|
||||||
|
</paragraph>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user