Understanding the need for conversion
Draft.js and Tiptap serve the same purpose but utilize different data structures. Draft.js uses a flat structure with blocks, inline styles, and entities. In contrast, Tiptap uses a nested structure of nodes and marks.
Installation
Setting up the draftjs-to-tiptap library is straightforward. You can install it using npm, yarn, pnpm, or bun:
npm install @tiptap/draftjs-to-tiptap
yarn add @tiptap/draftjs-to-tiptap
pnpm add @tiptap/draftjs-to-tiptap
bun add @tiptap/draftjs-to-tiptap
Getting started
The conversion process from Draft.js to Tiptap requires mapping various elements:
- Draft.js blocks to Tiptap nodes
- Draft.js entities to Tiptap nodes or marks
- Draft.js inline styles to Tiptap marks
Here’s a basic example to get you started:
import { DraftConverter } from '@tiptap/draftjs-to-tiptap';
const draftContent = {
blocks: [
{
key: '1',
text: 'Hello, world!',
type: 'unstyled',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
],
entityMap: {},
};
const convertDraftToTiptap = new DraftConverter();
const tiptapContent = convertDraftToTiptap.convert(draftContent);
Visualizing the conversion
To better understand the conversion process, you can use the visualizer web app available on CodeSandbox. This tool allows you to input Draft.js content and see the resulting Tiptap content in real-time.
Custom mappings for specific use cases
Since many developers customize their Draft.js content structures, draftjs-to-tiptap allows for custom mappings to fit specific needs. Here’s an example of how to map a custom Draft.js block to a Tiptap node:
import { DraftConverter } from '@tiptap/draftjs-to-tiptap';
const draftContent = {
blocks: [
{
key: '1',
text: 'Hello, world!',
type: 'unstyled',
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
],
entityMap: {},
};
const convertDraftToTiptap = new DraftConverter({
mapBlockToNode({ block, converter }) {
if (block.type === 'unstyled') {
return {
type: 'paragraph',
content: [
{
type: 'text',
text: block.text,
marks: [],
},
],
};
}
},
});
const tiptapContent = convertDraftToTiptap.convert(draftContent);
Advanced custom mappings
For more complex content structures, the library provides advanced custom mapping capabilities. This example demonstrates converting multiple unordered list items into a Tiptap bullet list:
import { DraftConverter } from '@tiptap/draftjs-to-tiptap';
const draftContent = {
blocks: [
{
key: "1",
text: "Item 1",
type: "unordered-list-item",
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
{
key: "2",
text: "Item 2",
type: "unordered-list-item",
depth: 0,
inlineStyleRanges: [],
entityRanges: [],
data: {},
},
],
entityMap: {},
};
const convertDraftToTiptap = new DraftConverter({
mapBlockToNode({ block, next, peek, converter, entityMap }) {
if (block.type === "unordered-list-item") {
const listNode = converter.createNode("bulletList");
do {
const itemNode = converter.createNode("listItem", {
content: [
converter.createNode("paragraph", {
content: [
converter.splitTextByEntityRangesAndInlineStyleRanges({
block,
entityMap,
}),
],
}),
],
});
converter.addChild(listNode, itemNode);
if (peek()?.type !== "unordered-list-item") {
break;
}
} while (next());
return listNode;
}
},
});
const tiptapContent = convertDraftToTiptap.convert(draftContent);
Conclusion
Migrating from Draft.js to Tiptap doesn’t have to be a hassle. With the draftjs-to-tiptap library, you can seamlessly transition your content, leveraging the powerful and flexible Tiptap editor. Whether you need simple conversions or complex custom mappings, this tool provides the functionality you need to keep your projects moving forward.
Explore the CodeSandbox demo to see draftjs-to-tiptap in action and visit the GitHub repository to get familiar with the library.