diff --git a/.changeset/spotty-squids-walk.md b/.changeset/spotty-squids-walk.md
new file mode 100644
index 000000000..43a7a142e
--- /dev/null
+++ b/.changeset/spotty-squids-walk.md
@@ -0,0 +1,5 @@
+---
+'slate': minor
+---
+
+Don't set `null` in `set_node`'s `newProperties` object when using `Transforms.unsetNodes()`
diff --git a/packages/slate/src/transforms/node.ts b/packages/slate/src/transforms/node.ts
index e90412b32..caa863170 100644
--- a/packages/slate/src/transforms/node.ts
+++ b/packages/slate/src/transforms/node.ts
@@ -632,19 +632,23 @@ export const NodeTransforms: NodeTransforms = {
continue
}
+ let hasChanges = false
+
for (const k in props) {
if (k === 'children' || k === 'text') {
continue
}
if (props[k] !== node[k]) {
- // Omit new properties from the old property list rather than set them to undefined
+ hasChanges = true
+ // Omit new properties from the old properties list
if (node.hasOwnProperty(k)) properties[k] = node[k]
- newProperties[k] = props[k]
+ // Omit properties that have been removed from the new properties list
+ if (props[k] != null) newProperties[k] = props[k]
}
}
- if (Object.keys(newProperties).length !== 0) {
+ if (hasChanges) {
editor.apply({
type: 'set_node',
path,
diff --git a/packages/slate/test/operations/set_node/remove-null.tsx b/packages/slate/test/operations/set_node/remove-null.tsx
index 918d65809..b50357575 100644
--- a/packages/slate/test/operations/set_node/remove-null.tsx
+++ b/packages/slate/test/operations/set_node/remove-null.tsx
@@ -10,6 +10,7 @@ export const input = (
)
+// this is supported for backwards compatibility only; newProperties should omit removed values.
export const operations = [
{
type: 'set_node',
diff --git a/packages/slate/test/operations/set_node/remove-undefined.tsx b/packages/slate/test/operations/set_node/remove-undefined.tsx
index 0c8cc7d96..826e03278 100644
--- a/packages/slate/test/operations/set_node/remove-undefined.tsx
+++ b/packages/slate/test/operations/set_node/remove-undefined.tsx
@@ -10,6 +10,7 @@ export const input = (
)
+// this is supported for backwards compatibility only; newProperties should omit removed values.
export const operations = [
{
type: 'set_node',
diff --git a/packages/slate/test/transforms/unsetNodes/operation-contents-check.tsx b/packages/slate/test/transforms/unsetNodes/operation-contents-check.tsx
new file mode 100644
index 000000000..321a651b2
--- /dev/null
+++ b/packages/slate/test/transforms/unsetNodes/operation-contents-check.tsx
@@ -0,0 +1,35 @@
+/** @jsx jsx */
+import assert from 'assert'
+import { Transforms, Text, Editor } from 'slate'
+import { jsx } from '../..'
+
+export const run = (editor: Editor) => {
+ Transforms.unsetNodes(editor, 'key', { at: [0] })
+
+ // unsetNodes uses null to remove properties, but that should not
+ // flow through to the operation
+ const [setNode] = editor.operations
+
+ if (setNode.type === 'set_node') {
+ assert.deepStrictEqual(setNode, {
+ type: 'set_node',
+ path: [0],
+ properties: { key: true },
+ newProperties: {},
+ })
+ } else {
+ // eslint-disable-next-line no-console
+ console.error('operations:', editor.operations)
+ assert.fail('operation was not a set node')
+ }
+}
+export const input = (
+
+ word
+
+)
+export const output = (
+
+ word
+
+)
diff --git a/packages/slate/test/transforms/unsetNodes/text/text.tsx b/packages/slate/test/transforms/unsetNodes/text.tsx
similarity index 92%
rename from packages/slate/test/transforms/unsetNodes/text/text.tsx
rename to packages/slate/test/transforms/unsetNodes/text.tsx
index 306af936b..d35d436f3 100644
--- a/packages/slate/test/transforms/unsetNodes/text/text.tsx
+++ b/packages/slate/test/transforms/unsetNodes/text.tsx
@@ -1,6 +1,6 @@
/** @jsx jsx */
import { Transforms, Text } from 'slate'
-import { jsx } from '../../..'
+import { jsx } from '../..'
export const run = editor => {
Transforms.unsetNodes(editor, 'key', { match: Text.isText })