From b12c86cd5b46a81fc4b0cfe492e3f137b67b3ce2 Mon Sep 17 00:00:00 2001 From: felixfeng Date: Thu, 28 Mar 2024 17:12:27 +0800 Subject: [PATCH 1/2] chore: add shouldMergeNodesRemovePrevNode --- .changeset/early-mayflies-grow.md | 5 +++++ packages/slate/src/create-editor.ts | 3 +++ packages/slate/src/editor/index.ts | 1 + .../editor/shouldMergeNodesRemovePrevNode.ts | 17 +++++++++++++++++ packages/slate/src/interfaces/editor.ts | 15 +++++++++++++++ .../slate/src/transforms-node/merge-nodes.ts | 7 +------ 6 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 .changeset/early-mayflies-grow.md create mode 100644 packages/slate/src/editor/shouldMergeNodesRemovePrevNode.ts diff --git a/.changeset/early-mayflies-grow.md b/.changeset/early-mayflies-grow.md new file mode 100644 index 0000000000..e1a8a95a4f --- /dev/null +++ b/.changeset/early-mayflies-grow.md @@ -0,0 +1,5 @@ +--- +'slate': patch +--- + +add interface shouldMergeNodesRemovePrevNode diff --git a/packages/slate/src/create-editor.ts b/packages/slate/src/create-editor.ts index ba2b921c25..68b5de0233 100644 --- a/packages/slate/src/create-editor.ts +++ b/packages/slate/src/create-editor.ts @@ -57,6 +57,7 @@ import { rangeRef, rangeRefs, setNormalizing, + shouldMergeNodesRemovePrevNode, start, string, unhangRange, @@ -181,6 +182,8 @@ export const createEditor = (): Editor => { void: (...args) => getVoid(editor, ...args), withoutNormalizing: (...args) => withoutNormalizing(editor, ...args), wrapNodes: (...args) => wrapNodes(editor, ...args), + shouldMergeNodesRemovePrevNode: (...args) => + shouldMergeNodesRemovePrevNode(editor, ...args), } return editor diff --git a/packages/slate/src/editor/index.ts b/packages/slate/src/editor/index.ts index a946e316e0..80625b021d 100644 --- a/packages/slate/src/editor/index.ts +++ b/packages/slate/src/editor/index.ts @@ -52,3 +52,4 @@ export * from './start' export * from './string' export * from './unhang-range' export * from './without-normalizing' +export * from './shouldMergeNodesRemovePrevNode' diff --git a/packages/slate/src/editor/shouldMergeNodesRemovePrevNode.ts b/packages/slate/src/editor/shouldMergeNodesRemovePrevNode.ts new file mode 100644 index 0000000000..47c7ae826e --- /dev/null +++ b/packages/slate/src/editor/shouldMergeNodesRemovePrevNode.ts @@ -0,0 +1,17 @@ +import { EditorInterface, Element, Editor, Text } from '../interfaces' + +export const shouldMergeNodesRemovePrevNode: EditorInterface['shouldMergeNodesRemovePrevNode'] = + (editor, [prevNode, prevPath], [curNode, curNodePath]) => { + // If the target node that we're merging with is empty, remove it instead + // of merging the two. This is a common rich text editor behavior to + // prevent losing formatting when deleting entire nodes when you have a + // hanging selection. + // if prevNode is first child in parent,don't remove it. + + return ( + (Element.isElement(prevNode) && Editor.isEmpty(editor, prevNode)) || + (Text.isText(prevNode) && + prevNode.text === '' && + prevPath[prevPath.length - 1] !== 0) + ) + } diff --git a/packages/slate/src/interfaces/editor.ts b/packages/slate/src/interfaces/editor.ts index 3907e89526..524ce8c7f4 100644 --- a/packages/slate/src/interfaces/editor.ts +++ b/packages/slate/src/interfaces/editor.ts @@ -167,6 +167,9 @@ export interface BaseEditor { string: OmitFirstArg unhangRange: OmitFirstArg void: OmitFirstArg + shouldMergeNodesRemovePrevNode: OmitFirstArg< + typeof Editor.shouldMergeNodesRemovePrevNode + > } export type Editor = ExtendedType<'Editor', BaseEditor> @@ -709,6 +712,15 @@ export interface EditorInterface { * Call a function, deferring normalization until after it completes. */ withoutNormalizing: (editor: Editor, fn: () => void) => void + + /** + * Call a function, Determine whether or not remove the previous node when merge. + */ + shouldMergeNodesRemovePrevNode: ( + editor: Editor, + prevNodeEntry: NodeEntry, + curNodeEntry: NodeEntry + ) => boolean } // eslint-disable-next-line no-redeclare @@ -953,6 +965,9 @@ export const Editor: EditorInterface = { withoutNormalizing(editor, fn: () => void) { editor.withoutNormalizing(fn) }, + shouldMergeNodesRemovePrevNode: (editor, prevNode, curNode) => { + return editor.shouldMergeNodesRemovePrevNode(prevNode, curNode) + }, } /** diff --git a/packages/slate/src/transforms-node/merge-nodes.ts b/packages/slate/src/transforms-node/merge-nodes.ts index aa66e8040f..883dc5af9a 100644 --- a/packages/slate/src/transforms-node/merge-nodes.ts +++ b/packages/slate/src/transforms-node/merge-nodes.ts @@ -133,12 +133,7 @@ export const mergeNodes: NodeTransforms['mergeNodes'] = ( // prevent losing formatting when deleting entire nodes when you have a // hanging selection. // if prevNode is first child in parent,don't remove it. - if ( - (Element.isElement(prevNode) && Editor.isEmpty(editor, prevNode)) || - (Text.isText(prevNode) && - prevNode.text === '' && - prevPath[prevPath.length - 1] !== 0) - ) { + if (editor.shouldMergeNodesRemovePrevNode(prev, current)) { Transforms.removeNodes(editor, { at: prevPath, voids }) } else { editor.apply({ From e2575e63c66e1bd28b5efc16f6827ccbe3cd3e21 Mon Sep 17 00:00:00 2001 From: felixfeng Date: Thu, 28 Mar 2024 20:27:41 +0800 Subject: [PATCH 2/2] fix: typo --- .changeset/early-mayflies-grow.md | 4 ++-- packages/slate/src/editor/index.ts | 2 +- ...ePrevNode.ts => should-merge-nodes-remove-prev-node.ts} | 0 packages/slate/src/transforms-node/merge-nodes.ts | 7 +------ 4 files changed, 4 insertions(+), 9 deletions(-) rename packages/slate/src/editor/{shouldMergeNodesRemovePrevNode.ts => should-merge-nodes-remove-prev-node.ts} (100%) diff --git a/.changeset/early-mayflies-grow.md b/.changeset/early-mayflies-grow.md index e1a8a95a4f..16d906a462 100644 --- a/.changeset/early-mayflies-grow.md +++ b/.changeset/early-mayflies-grow.md @@ -1,5 +1,5 @@ --- -'slate': patch +'slate': minor --- -add interface shouldMergeNodesRemovePrevNode +Add a `shouldMergeNodesRemovePrevNode` editor method to control when `Transforms.mergeNodes` should remove the previous node rather than carrying out a merge operation. diff --git a/packages/slate/src/editor/index.ts b/packages/slate/src/editor/index.ts index 80625b021d..aeeadd5a53 100644 --- a/packages/slate/src/editor/index.ts +++ b/packages/slate/src/editor/index.ts @@ -52,4 +52,4 @@ export * from './start' export * from './string' export * from './unhang-range' export * from './without-normalizing' -export * from './shouldMergeNodesRemovePrevNode' +export * from './should-merge-nodes-remove-prev-node' diff --git a/packages/slate/src/editor/shouldMergeNodesRemovePrevNode.ts b/packages/slate/src/editor/should-merge-nodes-remove-prev-node.ts similarity index 100% rename from packages/slate/src/editor/shouldMergeNodesRemovePrevNode.ts rename to packages/slate/src/editor/should-merge-nodes-remove-prev-node.ts diff --git a/packages/slate/src/transforms-node/merge-nodes.ts b/packages/slate/src/transforms-node/merge-nodes.ts index 883dc5af9a..2c68e4e52d 100644 --- a/packages/slate/src/transforms-node/merge-nodes.ts +++ b/packages/slate/src/transforms-node/merge-nodes.ts @@ -128,12 +128,7 @@ export const mergeNodes: NodeTransforms['mergeNodes'] = ( Transforms.removeNodes(editor, { at: emptyRef.current!, voids }) } - // If the target node that we're merging with is empty, remove it instead - // of merging the two. This is a common rich text editor behavior to - // prevent losing formatting when deleting entire nodes when you have a - // hanging selection. - // if prevNode is first child in parent,don't remove it. - if (editor.shouldMergeNodesRemovePrevNode(prev, current)) { + if (Editor.shouldMergeNodesRemovePrevNode(editor, prev, current)) { Transforms.removeNodes(editor, { at: prevPath, voids }) } else { editor.apply({