Docs
Advanced
Paste Handling

Paste Handling

BlockNote, by default, attempts to paste content in the following order:

  • VS Code compatible content
  • BlockNote HTML
  • Markdown
  • HTML
  • Plain text
  • Files

By default, in certain cases, BlockNote will attempt to convert the content of the clipboard from plain text to HTML by interpreting the plain text as markdown.

You can change this behavior by providing a custom paste handler.

const editor = new BlockNoteEditor({
  pasteHandler: ({ defaultPasteHandler }) => {
    return defaultPasteHandler({
      pasteBehavior: "prefer-html",
    });
  },
});

In this example, we change the default paste behavior to prefer HTML.

import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
 
import "./styles.css";
 
export default function App() {
  // Creates a new editor instance.
  const editor = useCreateBlockNote({
    initialContent: [
      {
        type: "paragraph",
        content: [
          {
            styles: {},
            type: "text",
            text: "Paste some text here",
          },
        ],
      },
    ],
    pasteHandler: ({ event, editor, defaultPasteHandler }) => {
      if (event.clipboardData?.types.includes("text/plain")) {
        editor.pasteMarkdown(
          event.clipboardData.getData("text/plain") +
            " - inserted by the custom paste handler"
        );
        return true;
      }
      return defaultPasteHandler();
    },
  });
 
  // Renders the editor instance using a React component.
  return (
    <div>
      <BlockNoteView editor={editor} />
      <div className={"edit-buttons"}>
        <button
          className={"edit-button"}
          onClick={async () => {
            try {
              await navigator.clipboard.writeText(
                "**This is markdown in the plain text format**"
              );
            } catch (error) {
              window.alert("Failed to copy plain text with markdown content");
            }
          }}>
          Copy text/plain with markdown content
        </button>
        <button
          className={"edit-button"}
          onClick={async () => {
            try {
              await navigator.clipboard.write([
                new ClipboardItem({
                  "text/html": "<p><strong>HTML</strong></p>",
                }),
              ]);
            } catch (error) {
              window.alert("Failed to copy HTML content");
            }
          }}>
          Copy text/html with HTML content
        </button>
        <button
          className={"edit-button"}
          onClick={async () => {
            try {
              await navigator.clipboard.writeText(
                "This is plain text in the plain text format"
              );
            } catch (error) {
              window.alert("Failed to copy plain text");
            }
          }}>
          Copy plain text
        </button>
        <button
          className={"edit-button"}
          onClick={async () => {
            try {
              await navigator.clipboard.write([
                new ClipboardItem({
                  "text/plain": "Plain text",
                }),
                new ClipboardItem({
                  "text/html": "<p><strong>HTML</strong></p>",
                }),
                new ClipboardItem({
                  "text/markdown": "**Markdown**",
                }),
              ]);
            } catch (error) {
              window.alert("Failed to copy multiple formats");
            }
          }}>
          Copy multiple formats
        </button>
      </div>
    </div>
  );
}
 

Custom Paste Handler

You can also provide your own paste handler by providing a function to the pasteHandler option.

const editor = new BlockNoteEditor({
  pasteHandler: ({ event, editor, defaultPasteHandler }) => {
    if (event.clipboardData?.types.includes("text/my-custom-format")) {
      const markdown = myCustomTransformer(event.clipboardData.getData("text/my-custom-format"));
      editor.pasteText(markdown);
      // We handled the paste event, so return true
      return true;
    }
 
    // If we didn't handle the paste event, call the default paste handler to do the default behavior
    return defaultPasteHandler();
  },
});

In this example, we handle the paste event if the clipboard data contains text/my-custom-format. If we don't handle the paste event, we call the default paste handler to do the default behavior.