1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-05 14:57:25 +02:00

chore: add shouldMergeNodesRemovePrevNode (#5621)

* chore: add shouldMergeNodesRemovePrevNode

* fix: typo
This commit is contained in:
felixfeng
2024-04-02 07:22:12 +08:00
committed by GitHub
parent 4470f37057
commit d271c4be54
6 changed files with 42 additions and 11 deletions

View File

@@ -0,0 +1,5 @@
---
'slate': minor
---
Add a `shouldMergeNodesRemovePrevNode` editor method to control when `Transforms.mergeNodes` should remove the previous node rather than carrying out a merge operation.

View File

@@ -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

View File

@@ -52,3 +52,4 @@ export * from './start'
export * from './string'
export * from './unhang-range'
export * from './without-normalizing'
export * from './should-merge-nodes-remove-prev-node'

View File

@@ -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)
)
}

View File

@@ -167,6 +167,9 @@ export interface BaseEditor {
string: OmitFirstArg<typeof Editor.string>
unhangRange: OmitFirstArg<typeof Editor.unhangRange>
void: OmitFirstArg<typeof Editor.void>
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)
},
}
/**

View File

@@ -128,17 +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 (
(Element.isElement(prevNode) && Editor.isEmpty(editor, prevNode)) ||
(Text.isText(prevNode) &&
prevNode.text === '' &&
prevPath[prevPath.length - 1] !== 0)
) {
if (Editor.shouldMergeNodesRemovePrevNode(editor, prev, current)) {
Transforms.removeNodes(editor, { at: prevPath, voids })
} else {
editor.apply({