From 001a083e157f0fe6ad5959e5e99fea0ca19ede87 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 30 Apr 2023 20:28:42 -0400 Subject: [PATCH] fix: Pasting single Markdown paragraph adds newlines above and below closes #5264 --- shared/editor/extensions/PasteHandler.ts | 35 ++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/shared/editor/extensions/PasteHandler.ts b/shared/editor/extensions/PasteHandler.ts index c3e5883d5..9ee38409a 100644 --- a/shared/editor/extensions/PasteHandler.ts +++ b/shared/editor/extensions/PasteHandler.ts @@ -1,4 +1,5 @@ import { toggleMark } from "prosemirror-commands"; +import { Slice } from "prosemirror-model"; import { Plugin } from "prosemirror-state"; import { isInTable } from "prosemirror-tables"; import { isUrl } from "../../utils/urls"; @@ -15,6 +16,14 @@ function isDropboxPaper(html: string): boolean { return html?.includes("usually-unique-id"); } +function sliceSingleNode(slice: Slice) { + return slice.openStart === 0 && + slice.openEnd === 0 && + slice.content.childCount === 1 + ? slice.content.firstChild + : null; +} + export default class PasteHandler extends Extension { get name() { return "paste-handler"; @@ -154,13 +163,35 @@ export default class PasteHandler extends Extension { ) { event.preventDefault(); + // get pasted content as slice const paste = this.editor.pasteParser.parse( normalizePastedMarkdown(text) ); const slice = paste.slice(0); + const tr = view.state.tr; + let currentPos = view.state.selection.from; - const transaction = view.state.tr.replaceSelection(slice); - view.dispatch(transaction); + // If the pasted content is a single paragraph then we loop over + // it's content and insert each node one at a time to allow it to + // be pasted inline with surrounding content. + const singleNode = sliceSingleNode(slice); + if (singleNode?.type === this.editor.schema.nodes.paragraph) { + singleNode.forEach((node) => { + tr.insert(currentPos, node); + currentPos += node.nodeSize; + }); + } else { + singleNode + ? tr.replaceSelectionWith(singleNode, this.shiftKey) + : tr.replaceSelection(slice); + } + + view.dispatch( + tr + .scrollIntoView() + .setMeta("paste", true) + .setMeta("uiEvent", "paste") + ); return true; }