diff --git a/packages/slate/src/interfaces/editor.ts b/packages/slate/src/interfaces/editor.ts index 90ab78e7b..f1a8fe3db 100644 --- a/packages/slate/src/interfaces/editor.ts +++ b/packages/slate/src/interfaces/editor.ts @@ -1721,3 +1721,5 @@ export const Editor: EditorInterface = { export type NodeMatch = | ((node: Node, path: Path) => node is T) | ((node: Node, path: Path) => boolean) + +export type PropsCompare = (prop: Partial, node: Partial) => boolean diff --git a/packages/slate/src/transforms/node.ts b/packages/slate/src/transforms/node.ts index 31ef577ae..c2747ffa4 100644 --- a/packages/slate/src/transforms/node.ts +++ b/packages/slate/src/transforms/node.ts @@ -11,7 +11,7 @@ import { NodeEntry, Ancestor, } from '..' -import { NodeMatch } from '../interfaces/editor' +import { NodeMatch, PropsCompare } from '../interfaces/editor' export interface NodeTransforms { insertNodes: ( @@ -75,6 +75,7 @@ export interface NodeTransforms { hanging?: boolean split?: boolean voids?: boolean + compare?: PropsCompare } ) => void splitNodes: ( @@ -568,10 +569,11 @@ export const NodeTransforms: NodeTransforms = { hanging?: boolean split?: boolean voids?: boolean + compare?: PropsCompare } = {} ): void { Editor.withoutNormalizing(editor, () => { - let { match, at = editor.selection } = options + let { match, at = editor.selection, compare } = options const { hanging = false, mode = 'lowest', @@ -628,6 +630,10 @@ export const NodeTransforms: NodeTransforms = { } } + if (!compare) { + compare = (prop, nodeProp) => prop !== nodeProp + } + for (const [node, path] of Editor.nodes(editor, { at, match, @@ -649,7 +655,7 @@ export const NodeTransforms: NodeTransforms = { continue } - if (props[k] !== node[k]) { + if (compare(props[k], node[k])) { hasChanges = true // Omit new properties from the old properties list if (node.hasOwnProperty(k)) properties[k] = node[k] diff --git a/packages/slate/test/transforms/normalization/set_node.tsx b/packages/slate/test/transforms/normalization/set_node.tsx new file mode 100644 index 000000000..d399196a7 --- /dev/null +++ b/packages/slate/test/transforms/normalization/set_node.tsx @@ -0,0 +1,43 @@ +/** @jsx jsx */ +import { Editor, Element, Transforms } from 'slate' +import { jsx } from '../..' +import _ from 'lodash' + +export const input = ( + + + one + + +) + +const editor = (input as unknown) as Editor +const defaultNormalize = editor.normalizeNode +editor.normalizeNode = entry => { + const [node, path] = entry + if ( + Element.isElement(node) && + (node as any).type === 'body' && + Editor.string(editor, path, { voids: true }) === 'one' + ) { + Transforms.setNodes( + editor, + { attr: { a: false } }, + { at: path, compare: (p, n) => !_.isEqual(p, n) } + ) + } + + defaultNormalize(entry) +} + +export const run = editor => { + Editor.normalize(editor, { force: true }) +} + +export const output = ( + + + one + + +)