|
1 | | -import { EditorState, Plugin, PluginKey, TextSelection, Transaction } from 'prosemirror-state'; |
| 1 | +import { EditorState, Plugin, PluginKey, TextSelection, Transaction, Selection } from 'prosemirror-state'; |
2 | 2 | import { strings } from '@douyinfe/semi-foundation/aiChatInput/constants'; |
3 | 3 | import { EditorView } from '@tiptap/pm/view'; |
4 | 4 | /** |
@@ -412,12 +412,52 @@ export function handlePasteLogic(view: EditorView, event: ClipboardEvent) { |
412 | 412 | const { state, dispatch } = view; |
413 | 413 | const $from = state.selection.$from; |
414 | 414 | let tr = state.tr; |
| 415 | + const parentNode = $from.parent; |
| 416 | + if (parentNode.type.name === 'inputSlot') { |
| 417 | + return specialPasteLogicForInputSlot(event, $from, tr, dispatch, state.selection); |
| 418 | + } |
415 | 419 | removeZeroWidthChar($from, tr); |
416 | 420 | tr.setMeta(strings.DELETABLE, true); |
417 | 421 | dispatch(tr); |
418 | 422 | return false; |
419 | 423 | } |
420 | 424 |
|
| 425 | +/** |
| 426 | + * specialPasteLogicForInputSlot 处理两种情况 |
| 427 | + * 1. 如果是 parentNode 是 input-slot,当里面内容仅为零宽字符时候 |
| 428 | + * 直接去掉零宽字符会导致 input-slot 消失, |
| 429 | + * 因此将此行为处理成获取文字部分,将零宽字符替换为文字内容 |
| 430 | + * 2. 如果 parentNode 是 input-slot,选中 input-slot 中的所有文字并粘贴 |
| 431 | + * 会导致 input-slot 被删除,因此需要处理成使用复制内容替换原有内容的 |
| 432 | + * The `specialPasteLogicForInputSlot` function handles two cases. |
| 433 | + * 1. If the parentNode is input-slot, and its content consists of only zero-width characters... |
| 434 | + * Removing zero-width characters directly will cause the input slot to disappear. |
| 435 | + * Therefore, this behavior is processed by retrieving the text portion and replacing the zero-width characters with the text content. |
| 436 | + * 2. If the parentNode is input-slot, select all the text in the input-slot and paste it. |
| 437 | + * This will cause the input slot to be deleted, so it needs to be handled by replacing the original content with copied content. |
| 438 | + */ |
| 439 | +export function specialPasteLogicForInputSlot(event: ClipboardEvent, $from: any, tr: Transaction, dispatch: (tr: Transaction) => void, selection: Selection) { |
| 440 | + const parentNode = $from.parent; |
| 441 | + const nodeText = parentNode.textContent; |
| 442 | + const isOnlyZeroWidth = nodeText && nodeText === strings.ZERO_WIDTH_CHAR; |
| 443 | + const isAllTextSelected = !selection.empty && |
| 444 | + selection.from === $from.start() && selection.to === $from.end(); |
| 445 | + if (isOnlyZeroWidth || isAllTextSelected) { |
| 446 | + const pastedText = event.clipboardData?.getData('text/plain') || ''; |
| 447 | + if (pastedText) { |
| 448 | + const pos = $from.start(); |
| 449 | + tr = tr.insertText(pastedText, pos, pos + nodeText.length); |
| 450 | + const endPos = pos + pastedText.length; |
| 451 | + tr = tr.setSelection(TextSelection.create(tr.doc, endPos)); |
| 452 | + tr.setMeta(strings.DELETABLE, true); |
| 453 | + dispatch(tr); |
| 454 | + event.preventDefault(); |
| 455 | + return true; |
| 456 | + } |
| 457 | + } |
| 458 | + return false; |
| 459 | +} |
| 460 | + |
421 | 461 | export function removeZeroWidthChar($from: any, tr: Transaction) { |
422 | 462 | // Handling zero-width characters before and after pasting |
423 | 463 | // Check the previous node of the cursor |
|
0 commit comments