diff --git a/.changeset/honest-pears-repair.md b/.changeset/honest-pears-repair.md new file mode 100644 index 00000000..47a93d08 --- /dev/null +++ b/.changeset/honest-pears-repair.md @@ -0,0 +1,5 @@ +--- +"rhino-editor": patch +--- + +Fix issues with paste extensions diff --git a/.changeset/new-donkeys-greet.md b/.changeset/new-donkeys-greet.md new file mode 100644 index 00000000..ff28e270 --- /dev/null +++ b/.changeset/new-donkeys-greet.md @@ -0,0 +1,5 @@ +--- +"rhino-editor": patch +--- + +Fix issues with attachment pasting diff --git a/src/exports/extensions/attachment.ts b/src/exports/extensions/attachment.ts index 86a8c3ee..6bb8b484 100644 --- a/src/exports/extensions/attachment.ts +++ b/src/exports/extensions/attachment.ts @@ -1088,7 +1088,26 @@ function handleAttachment( ); } - tr.replaceWith(currSelection.from - 1, currSelection.to, [ + // The following checks fix some "off by 1" issues. I _think_ these are the only nodes we need to check. May need a more robust check if this continues to be an issue. + // https://github.com/KonnorRogers/rhino-editor/issues/254 + let from = currSelection.from; + const prevNode = state.doc.resolve(from - 1); + const parentNode = prevNode.parent; + + if (parentNode && parentNode.type.name === "doc") { + from -= 1; + } else { + const closestParagraph = findParentNodeOfTypeClosestToPos( + prevNode, + schema.nodes["paragraph"], + ); + + if (closestParagraph && closestParagraph.node.textContent === "") { + from -= 1; + } + } + + tr.replaceWith(from, currSelection.to, [ ...attachmentNodes, schema.nodes.paragraph.create(), ]); diff --git a/src/exports/extensions/paste.ts b/src/exports/extensions/paste.ts index aa14d860..db66a806 100644 --- a/src/exports/extensions/paste.ts +++ b/src/exports/extensions/paste.ts @@ -5,20 +5,31 @@ export interface PasteOptions {} // Super simple plugin that dispatches a paste event. This is convenient way to make this hard to override. export function Paste() { + const handledEvents = new WeakMap(); + return new Plugin({ key: new PluginKey("rhino-paste-event"), props: { handlePaste(view, event) { const { clipboardData } = event; + // We always return false to allow other extensions to actually handle the paste via props. + if (event.defaultPrevented) { - return true; + return false; } + if (handledEvents.has(event)) { + // This event has already processed. This prevents emitting the event twice. + return false; + } + + handledEvents.set(event, null); + const rhinoPasteEvent = new RhinoPasteEvent(clipboardData); view.dom.dispatchEvent(rhinoPasteEvent); - return true; + return false; // @TODO: Future enhancements for pasting // https://github.com/basecamp/trix/blob/fda14c5ae88a0821cf8999a53dcb3572b4172cf0/src/trix/controllers/level_0_input_controller.js#L39