Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: markdown pasting & custom paste handlers #1490

Merged
merged 21 commits into from
Mar 31, 2025
Merged

Conversation

nperez0111
Copy link
Contributor

@nperez0111 nperez0111 commented Mar 4, 2025

This implements markdown pasting, and custom paste handlers.

Adds

  • editor.pasteText which will paste text content into the editor
  • editor.pasteHTML which will convert HTML into BlockNote HTML and then paste that into the editor
  • editor.pasteMarkdown which will convert the markdown into BlockNote HTML and then paste that into the editor
  • editorOptions.pasteHandler for allowing the developer the ability to customize how content is pasted into the editor while still allowing the default paste behavior.

Copy link

vercel bot commented Mar 4, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
blocknote 🛑 Canceled (Inspect) Mar 31, 2025 3:37pm
blocknote-website ✅ Ready (Inspect) Visit Preview Mar 31, 2025 3:37pm

Copy link
Collaborator

@YousefED YousefED left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff!

What do you think about making this pluggable? i.e.: you could register a paste handler / preprocessor, and our "default preprocessor" changes the mimetype to text/markdown if we think it's a better fit.

(just realized; we actually also have a client requesting Event listeners for "paste" events so we can do our own manipulation before inserting into the document)

@@ -0,0 +1,60 @@
// Headings H1-H6.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious how many false positives we get. I didn't review the regexpes obviously.

Figured this might be useful: https://chatgpt.com/share/67d12910-3d78-8009-8bc0-ddd23dd7cba9

defaultPasteHandler: (context: {
pasteBehavior?: "prefer-markdown" | "prefer-html";
}) => boolean | undefined;
convertHtmlToBlockNoteHtml: (html: string) => string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API feedback:

  • what about exposing pasteHTML pasteMarkdown and pasteText on the editor instead of the conversion functions? this way consumers also don't need to call into prosemirror view.paste... functions.
  • I'm not sure I like passing the defaultPasteHandler vs exporting that function directly (still in doubt)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I like exposing the methods, to keep it simple for users, I exposed pasteHTML, pasteText & pasteMarkdown methods
  • I think having too many things exposed on a top-level API make it hard for discoverability, this function would only be useful for pasting content, so it makes sense to expose on the handler you'd use it at.

return true;
}

if (pasteBehavior === "prefer-markdown" && isMarkdown(data)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this single flag is what we want. We now always turn on "detection" and for both markdown and HTML. is that desirable?

Other options I can think of what the user might want:

  • always paste plain text as markdown (i.e.: paste markdown instead of plain text at L103), regardless of detection
  • Only run the detection for plain text, not for HTML (i.e.: always prefer regular HTML paste)?
  • (Other combinations like only run the detection for HTML, not for plain text. Not sure if that makes sense)

Happy to think this through together. I don't think we need all options to be possible via different flags, especially since users can now add their own paste handlers. But I do think there should at least be a way to not rely on the auto-detection yet still paste text as markdown

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored it to make it clearer how it was being used, if prefer-markdown is used, it will try to use the plaintext version if it can, otherwise it falls back to the previous behavior.

@nperez0111 nperez0111 changed the title feat: an attempt at parsing markdown on paste feat: markdown pasting & custom paste handlers Mar 24, 2025
@YousefED
Copy link
Collaborator

@nperez0111 didn't review yet; but I just noticed (working on sth unrelated) that actually inline content markdown gets parsed. try pasting xx \*\*hello world\*\*. Did you know this / know where this is done? Tiptap feature?

@nperez0111
Copy link
Contributor Author

@nperez0111 didn't review yet; but I just noticed (working on sth unrelated) that actually inline content markdown gets parsed. try pasting xx \*\*hello world\*\*. Did you know this / know where this is done? Tiptap feature?

https://github.com/ueberdosis/tiptap/blob/dd0a25f5b48867992dd68d3effd5c98ddafcab69/packages/extension-bold/src/bold.tsx#L134-L145

Bold already has a paste rule set up. As well as a number of other Tiptap extensions. What does not work (in blocknote) though would be things across paragraphs or code blocks for example

@@ -0,0 +1,59 @@
---
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be added to sidebar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is in the sidebar?

}),
]);
} catch (error) {
window.alert("Failed to copy multiple formats");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting this error when I click this button :/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not supported by most browsers, but works in Safari. I marked as such

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants