Rich Paste
Fixes the two pastes browsers get wrong: Word lists and code copied from a code editor.
Pasting from a web page, Excel, Google Docs or Word already keeps headings, bold, links, tables and colours, because the HTML on the clipboard maps onto the editor schema. Two sources do not:
- Word lists. Word does not put
<ul>or<ol>on the clipboard. Each item is a paragraph with anmso-liststyle and a literal bullet character in front, so a list arrives as plain paragraphs starting with·. This extension rebuilds the run as a real nested list, reading the nesting depth from Word'sleveland choosing a numbered list when the marker is1.,a)oriv.. - Code editors. VS Code, Sublime, Xcode and JetBrains copy one coloured
<span>per token inside a monospace,white-space: precontainer. That would land as paragraphs of coloured text. This extension recognises the container and inserts a code block from the plain-text copy instead. A single line becomes inline code rather than a block.
Setup
Start with the packages in Getting Started. This complete example registers the feature. It has no toolbar control; add it next to CodeBlock, BulletList and OrderedList so there is something to paste into.
'use client';
import { EditorContent, useEditor } from '@tiptap/react';
import { Document } from '@tiptap/extension-document';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import {
RichTextProvider,
BulletList,
CodeBlock,
OrderedList,
RichPaste,
} from 'ai-sparkwrite-editor';
import 'ai-sparkwrite-editor/style.css';
const extensions = [Document, Paragraph, Text, BulletList, OrderedList, CodeBlock, RichPaste];
export default function RichPasteExample() {
const editor = useEditor({
extensions,
content: '<p>Paste a Word list or a snippet from VS Code here.</p>',
immediatelyRender: false,
});
if (!editor) return null;
return (
<RichTextProvider editor={editor}>
<EditorContent editor={editor} />
</RichTextProvider>
);
}<script setup lang="ts">
import { EditorContent, useEditor } from '@tiptap/vue-3';
import { Document } from '@tiptap/extension-document';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import {
BulletList,
OrderedList,
RichPaste,
CodeBlock,
RichTextProvider,
} from 'ai-sparkwrite-editor/vue';
import 'ai-sparkwrite-editor/style.css';
const extensions = [Document, Paragraph, Text, BulletList, OrderedList, CodeBlock, RichPaste];
const editor = useEditor({
extensions,
content: '<p>Paste a Word list or a snippet from VS Code here.</p>',
});
</script>
<template>
<RichTextProvider :editor="editor">
<EditorContent :editor="editor" />
</RichTextProvider>
</template>Options
wordLists
Type: boolean
Default: true
Rebuild Word's list paragraphs as lists.
codeBlocks
Type: boolean
Default: true
Paste from a code editor as a code block.
detectLanguage
Type: (code: string) => string
Default: none
Guesses the language of a pasted block from its text and returns a name the code block understands (an empty string means "unknown"). The code block extension ships a guesser you can reuse:
import { guessLanguage } from 'ai-sparkwrite-editor';
RichPaste.configure({ detectLanguage: guessLanguage });What is not changed
Pasting inside a code block is left to the default behaviour, which already keeps the text. HTML that contains paragraphs, headings, tables or lists is never treated as code, even when it uses a monospace font.