Files
Momento/memento-note/lib/editor/markdown-paste-extension.ts
Antigravity 6b4ed8514f
Some checks failed
CI / Lint, Unit Tests & Build (push) Successful in 5m37s
CI / Deploy production (on server) (push) Has been cancelled
Epic 6: Stories 6-2 (Markdown roundtrip) + 6-3 (Brainstorm PPTX + Canvas)
Story 6-2 — Markdown roundtrip export/import:
- lib/editor/markdown-export.ts: tiptapHTMLToMarkdown, markdownToHTML, looksLikeMarkdown
- lib/editor/markdown-paste-extension.ts: TipTap extension paste Markdown → blocs
- note-editor-toolbar.tsx: export .md + import .md (file picker)
- rich-text-editor.tsx: intégration MarkdownPasteExtension
- 40 tests unitaires markdown-export.test.ts

Story 6-3 — Brainstorm PPTX + Canvas:
- lib/brainstorm/export-pptx.ts: génération PPTX 5 slides (pptxgenjs)
- app/api/brainstorm/[sessionId]/export-pptx/route.ts: route POST protégée
- brainstorm-page.tsx: bouton PPTX, auto-select session, fix emoji, fix router.replace
- wave-canvas.tsx: fitTrigger recentrage, légende bas-droite

Onboarding activation wizard (Story 6-1):
- components/onboarding/: wizard multi-étapes, hints éditeur
- app/api/onboarding/: route PATCH onboarding
- prisma/migrations: champs onboarding user

Locales: 15 langues mises à jour (brainstorm, markdown, onboarding keys)
Sprint: 6-1 done, 6-2 review, 6-3 review

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 11:24:56 +00:00

51 lines
1.4 KiB
TypeScript

/**
* 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
},
},
}),
]
},
})