/** * markdown-paste-extension.ts * * TipTap extension that intercepts paste events. If the pasted plain text * looks like Markdown, it converts it to HTML and inserts it into the editor * as structured TipTap nodes — instead of inserting it as raw text. */ import { Extension } from '@tiptap/core' import { Plugin, PluginKey } from '@tiptap/pm/state' import { looksLikeMarkdown, markdownToHTML } from './markdown-export' const MARKDOWN_PASTE_KEY = new PluginKey('markdownPaste') export const MarkdownPasteExtension = Extension.create({ name: 'markdownPaste', addProseMirrorPlugins() { const editor = this.editor return [ new Plugin({ key: MARKDOWN_PASTE_KEY, props: { handlePaste(_view, event) { const text = event.clipboardData?.getData('text/plain') if (!text || !looksLikeMarkdown(text)) return false event.preventDefault() try { const html = markdownToHTML(text) // Schedule after current event loop to avoid transaction conflicts setTimeout(() => { editor.commands.insertContent(html, { parseOptions: { preserveWhitespace: 'full' }, }) }, 0) } catch { // Fallback: let TipTap handle the paste normally return false } return true }, }, }), ] }, })