diff --git a/packages/client/src/tiptap/core/extensions/paste.ts b/packages/client/src/tiptap/core/extensions/paste.ts index db1bcbab..8e7e17af 100644 --- a/packages/client/src/tiptap/core/extensions/paste.ts +++ b/packages/client/src/tiptap/core/extensions/paste.ts @@ -8,6 +8,7 @@ import { debug, handleFileEvent, isInCode, + isInTitle, isMarkdown, isTitleNode, isValidURL, @@ -16,6 +17,37 @@ import { import { TitleExtensionName } from './title'; +function insertText(view, text) { + const texts = text.split('\n').filter(Boolean); + event.preventDefault(); + view.dispatch(view.state.tr.insertText(texts[0])); + + const json = { + type: 'doc', + content: [{ type: 'title', attrs: { cover: '' }, content: [{ type: 'text', text: texts[0] }] }].concat( + // @ts-ignore + texts.slice(1).map((t) => { + return { + type: 'paragraph', + attrs: { indent: 0, textAlign: 'left' }, + content: [{ type: 'text', text: t }], + }; + }) + ), + }; + + let tr = view.state.tr; + const selection = tr.selection; + view.state.doc.nodesBetween(selection.from, selection.to, (node, position) => { + const startPosition = Math.min(position, selection.from) || 0; + const endPosition = Math.min(position + node.nodeSize, selection.to); + tr = tr.replaceWith(startPosition, endPosition, view.state.schema.nodeFromJSON(json)); + }); + view.dispatch(tr.scrollIntoView()); + + return true; +} + interface IPasteOptions { /** * @@ -87,6 +119,12 @@ export const Paste = Extension.create({ console.groupEnd(); }); + if (isInTitle(view.state)) { + if (text.length) { + return insertText(view, text); + } + } + // 直接复制节点 if (node) { const json = safeJSONParse(node); @@ -202,9 +240,7 @@ export const Paste = Extension.create({ } if (text.length !== 0) { - event.preventDefault(); - view.dispatch(view.state.tr.insertText(text)); - return true; + return insertText(view, text); } return false; diff --git a/packages/client/src/tiptap/core/extensions/title.ts b/packages/client/src/tiptap/core/extensions/title.ts index c501d18d..7d3b6681 100644 --- a/packages/client/src/tiptap/core/extensions/title.ts +++ b/packages/client/src/tiptap/core/extensions/title.ts @@ -160,19 +160,25 @@ export const Title = Node.create({ } } - const newTitleNodes = (newState.tr.doc.content.content || []).filter((item) => item.type.name === this.name); + const filterTitleNode = (nodes, equal = true) => { + return (nodes || []) + .filter(Boolean) + .filter((item) => (equal ? item.type.name === this.name : item.type.name !== this.name)); + }; + + const newTitleNodes = filterTitleNode(newState.tr.doc.content.content || []); if (newTitleNodes.length > 1) { - const oldTitleNode = (oldState.tr.doc.content.content || []).filter((item) => item.type.name === this.name); + const oldTitleNodes = filterTitleNode(oldState.tr.doc.content.content || []); + const allTitleNodes = [...oldTitleNodes, ...newTitleNodes].filter(Boolean); + const nextNewTitleNode = allTitleNodes.find((node) => node.nodeSize > 2) || allTitleNodes[0]; - const otherNewNodes = (newState.tr.doc.content.content || []).filter( - (item) => item.type.name !== this.name - ); + const otherNewNodes = filterTitleNode(newState.tr.doc.content.content || [], false); const fixedDoc = { ...newState.tr.doc.toJSON(), content: [].concat( - ((oldTitleNode && oldTitleNode[0]) || newTitleNodes[0]).toJSON(), + nextNewTitleNode.toJSON(), otherNewNodes.map((node) => node.toJSON()) ), };