How to Export Editor Content to Word (.docx) in React Tiptap Editor
The ExportWord extension in reactjs-tiptap-editor exposes an exportToWord command that serializes the ProseMirror document into a Word-compatible .docx file and triggers an automatic browser download.
The hunghg255/reactjs-tiptap-editor repository provides a dedicated solution for converting Tiptap editor content to Microsoft Word format. By leveraging the prosemirror-docx library alongside the docx npm package, this extension traverses the editor's node tree and generates properly formatted Word documents with support for tables, text styling, and line breaks.
How the ExportWord Extension Works
The export process follows a four-step pipeline implemented across several source files. Understanding this flow helps you debug issues or extend the functionality for custom node types.
Extension Registration
In src/extensions/ExportWord/ExportWord.ts, the extension registers the exportToWord command within the Tiptap editor ecosystem. When initialized, it accepts the current editor state (doc) and makes the export functionality available through the editor's command chain.
Document Serialization
The core conversion logic uses DocxSerializer from prosemirror-docx to walk the ProseMirror node tree. The extension defines custom node serializers in the same file to handle specific formatting:
- Tables are configured to occupy 100% page width using
WidthType.PERCENTAGE(lines 32-40) - Line breaks and paragraph spacing preserve the document structure
- Images currently render as inline placeholders only, as binary embedding requires additional
ArrayBufferconversion viagetImageBuffer
Blob Generation and Download
After serialization, the Document object from the docx library is converted to a binary Blob using Packer.toBlob. The helper function downloadFromBlob in src/utils/download.ts creates a temporary object URL and programmatically clicks an invisible anchor element, saving the file as richtext-export-document.docx by default.
UI Integration
The RichTextExportWord component in src/extensions/ExportWord/components/RichTextExportWord.tsx provides the toolbar button. It consumes the button configuration via useButtonProps and invokes the exportToWord command when clicked, as demonstrated in the playground at playground/src/App.tsx.
Implementation Guide
Integrating Word export capability requires three steps: importing the extension, adding it to your editor configuration, and rendering the trigger button.
1. Import the ExportWord Extension
Import the extension from the dedicated export path to enable the serialization logic.
import { ExportWord } from 'reactjs-tiptap-editor/exportword';
2. Configure Your Editor
Add ExportWord to your extensions array when initializing the Tiptap editor. The extension automatically registers the necessary commands and serializers.
import { useEditor } from '@tiptap/react';
import { Document } from '@tiptap/extension-document';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import { ExportWord } from 'reactjs-tiptap-editor/exportword';
const editor = useEditor({
extensions: [
Document,
Paragraph,
Text,
ExportWord, // Enables .docx export functionality
],
content: '<p>Your initial content here</p>',
});
3. Add the Export Button to Your Toolbar
Place the RichTextExportWord component in your toolbar or action bar to provide the user interface for triggering the download.
import { RichTextExportWord } from 'reactjs-tiptap-editor/exportword';
function Toolbar() {
return (
<div className="flex gap-2">
{/* Other toolbar items */}
<RichTextExportWord /> {/* Click to download .docx */}
</div>
);
}
4. Complete Working Example
The following example from playground/src/App.tsx demonstrates a minimal implementation connecting all pieces together.
import { useEditor, EditorContent } from '@tiptap/react';
import { Document } from '@tiptap/extension-document';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import { ExportWord } from 'reactjs-tiptap-editor/exportword';
import { RichTextExportWord } from 'reactjs-tiptap-editor/exportword';
export default function App() {
const editor = useEditor({
extensions: [Document, Paragraph, Text, ExportWord],
content: '<p>Export this content to Word format</p>',
});
return (
<>
<RichTextExportWord />
<EditorContent editor={editor} />
</>
);
}
Technical Details and Limitations
When implementing Word export in production applications, consider these implementation specifics from the source code.
Image Handling Constraints
The current implementation in ExportWord.ts deliberately skips image embedding. The image serializer calls state.renderInline(node) to create a placeholder rather than embedding binary data. To support embedded images, extend the serializer to utilize the getImageBuffer helper, which fetches image URLs and returns Uint8Array data suitable for the docx library.
Table Formatting
Tables automatically expand to full page width (width: { size: 100, type: WidthType.PERCENTAGE }) to prevent content shrinking or collapsing in Word. This behavior is hardcoded in the table node serializer to ensure consistent Word document layouts regardless of browser rendering differences.
Source File Reference
These files contain the implementation details referenced throughout this guide:
src/extensions/ExportWord/ExportWord.ts– Core extension logic, command definition, and node serializerssrc/extensions/ExportWord/components/RichTextExportWord.tsx– React toolbar button componentsrc/utils/download.ts– Browser download helper using Blob URLsplayground/src/App.tsx– Real-world integration example
Summary
- Enable the extension by importing
ExportWordfromreactjs-tiptap-editor/exportwordand adding it to your Tiptap extensions array. - Trigger downloads via the
exportToWordcommand, which usesprosemirror-docxto serialize the ProseMirror document into adocxlibraryDocumentobject. - Use the UI component
RichTextExportWordto provide a ready-made toolbar button that wires into the export command. - Handle limitations by noting that images export as placeholders only, and tables default to 100% width to maintain layout integrity.
- Reference key files in
src/extensions/ExportWord/andsrc/utils/download.tsfor customization or debugging.
Frequently Asked Questions
Can I export images to the Word document?
Currently, the ExportWord extension renders images as inline placeholders only. The source code in src/extensions/ExportWord/ExportWord.ts intentionally skips binary embedding to avoid complexity. However, the codebase includes a getImageBuffer utility that fetches image URLs as ArrayBuffer objects. You can extend the node serializer to utilize these buffers and embed Uint8Array data into the Word document if your use case requires image support.
How do I customize the filename of the exported document?
The default filename is richtext-export-document.docx, defined in the exportToWord command within ExportWord.ts. To customize this, you would need to fork or patch the extension to pass a custom filename parameter to the downloadFromBlob helper in src/utils/download.ts, which currently creates the download link with a hardcoded or default name.
Why do tables appear at 100% width in the exported file?
The serializer enforces full-width tables (WidthType.PERCENTAGE with size 100) in lines 32-40 of ExportWord.ts to prevent table content from shrinking or collapsing in Word. This ensures consistent rendering across different Word versions and screen sizes, regardless of the table's appearance in the browser editor.
Does this extension support all Tiptap node types?
The extension supports standard text nodes, paragraphs, headings, and tables through the custom nodeSerializer configuration. Complex or custom node types may require additional serializers in ExportWord.ts to map ProseMirror nodes to their docx library equivalents. Unsupported nodes will be skipped or rendered as plain text during serialization.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →