mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-11 17:53:59 +02:00
set_node operations did not invert correctly after serialization (#4078)
* Use null instead of undefined as the old value for set_node operations that add a property * Changelog * Omit undefined values from `set_node` operations completely. Delete missing property values in `Transforms.apply()` instead. * Add tests for removing set_node properties with null and undefined
This commit is contained in:
5
.changeset/silent-bees-sing.md
Normal file
5
.changeset/silent-bees-sing.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'slate': patch
|
||||
---
|
||||
|
||||
set_node operations did not invert correctly after serialization
|
@@ -182,7 +182,7 @@ export const GeneralTransforms: GeneralTransforms = {
|
||||
}
|
||||
|
||||
case 'set_node': {
|
||||
const { path, newProperties } = op
|
||||
const { path, properties, newProperties } = op
|
||||
|
||||
if (path.length === 0) {
|
||||
throw new Error(`Cannot set properties on the root node!`)
|
||||
@@ -204,6 +204,13 @@ export const GeneralTransforms: GeneralTransforms = {
|
||||
}
|
||||
}
|
||||
|
||||
// properties that were previously defined, but are now missing, must be deleted
|
||||
for (const key in properties) {
|
||||
if (!newProperties.hasOwnProperty(key)) {
|
||||
delete node[key]
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
|
@@ -631,7 +631,8 @@ export const NodeTransforms: NodeTransforms = {
|
||||
}
|
||||
|
||||
if (props[k] !== node[k]) {
|
||||
properties[k] = node[k]
|
||||
// Omit new properties from the old property list rather than set them to undefined
|
||||
if (node.hasOwnProperty(k)) properties[k] = node[k]
|
||||
newProperties[k] = props[k]
|
||||
}
|
||||
}
|
||||
|
28
packages/slate/test/operations/set_node/remove-null.tsx
Normal file
28
packages/slate/test/operations/set_node/remove-null.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
/** @jsx jsx */
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
import { Transforms, Editor } from 'slate'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element>
|
||||
<text key />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const operations = [
|
||||
{
|
||||
type: 'set_node',
|
||||
path: [0, 0],
|
||||
properties: { key: true },
|
||||
newProperties: { key: null },
|
||||
},
|
||||
]
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
28
packages/slate/test/operations/set_node/remove-omit.tsx
Normal file
28
packages/slate/test/operations/set_node/remove-omit.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
/** @jsx jsx */
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
import { Transforms, Editor } from 'slate'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element>
|
||||
<text key />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const operations = [
|
||||
{
|
||||
type: 'set_node',
|
||||
path: [0, 0],
|
||||
properties: { key: true },
|
||||
newProperties: {},
|
||||
},
|
||||
]
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
28
packages/slate/test/operations/set_node/remove-undefined.tsx
Normal file
28
packages/slate/test/operations/set_node/remove-undefined.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
/** @jsx jsx */
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
import { Transforms, Editor } from 'slate'
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element>
|
||||
<text key />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const operations = [
|
||||
{
|
||||
type: 'set_node',
|
||||
path: [0, 0],
|
||||
properties: { key: true },
|
||||
newProperties: { key: undefined },
|
||||
},
|
||||
]
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@@ -0,0 +1,25 @@
|
||||
/** @jsx jsx */
|
||||
import assert from 'assert'
|
||||
import { Editor, Transforms, Operation } from 'slate'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const run = (editor: Editor) => {
|
||||
Transforms.setNodes(editor, { key: true }, { at: [0] })
|
||||
const [op] = editor.operations
|
||||
const roundTrip: Operation = JSON.parse(JSON.stringify(op))
|
||||
assert.deepStrictEqual(op, roundTrip)
|
||||
}
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
<text />
|
||||
</block>
|
||||
</editor>
|
||||
)
|
||||
export const output = (
|
||||
<editor>
|
||||
<block key>
|
||||
<text />
|
||||
</block>
|
||||
</editor>
|
||||
)
|
@@ -0,0 +1,25 @@
|
||||
/** @jsx jsx */
|
||||
import { Editor, Transforms, Operation } from 'slate'
|
||||
import { jsx } from '../../..'
|
||||
|
||||
export const run = (editor: Editor) => {
|
||||
Transforms.setNodes(editor, { key: true }, { at: [0] })
|
||||
const [op] = editor.operations
|
||||
const roundTrip: Operation = JSON.parse(JSON.stringify(op))
|
||||
const inverted = Operation.inverse(roundTrip)
|
||||
editor.apply(inverted)
|
||||
}
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
<text />
|
||||
</block>
|
||||
</editor>
|
||||
)
|
||||
export const output = (
|
||||
<editor>
|
||||
<block>
|
||||
<text />
|
||||
</block>
|
||||
</editor>
|
||||
)
|
Reference in New Issue
Block a user