From zbeyens. The source code is available on GitHub.

Plate
PlatePliteEditorsTemplates
GitHub16kGitHub
DiscordDiscord
    • Stream
    • Copilot
  • Discussion
    • Comments
    • Suggestion
    • Basic Blocks
      • Blockquote
      • Heading
      • Horizontal Rule
    • Callout
    • Code Block
    • Column
    • Date
    • Equation
    • Link
    • List Classic
    • Media
    • MentionElement
    • Table
    • Table of Contents
    • Footnote
    • Toggle
  • Marks
    • Bold
    • Italic
    • Underline
    • Code
    • Highlight
    • Keyboard Input
    • Strikethrough
    • Subscript
    • Superscript
      • Font
      • Line Height
      • Text Align
    • Indent
    • List
      • Exit Break
      • Single Block
      • Trailing Block
    • Autoformat
    • Block Menu
    • Block Placeholder
    • Combobox
      • Emoji
      • MentionElement
      • Slash Command
    • Cursor Overlay
    • Drag & Drop
    • Navigation Feedback
    • Tabbable
    • Toolbar
    • Yjs
    • Multi SelectEditor
    • CSV
    • DOCX
    • HTML
    • Markdown

DOCX

PreviousNext

Paste from Word, import DOCX files, and export Plate content as DOCX.

DOCX support has three directions: paste Word clipboard content into Plate, import a .docx file into Plate nodes, and export Plate nodes as a .docx file. Each direction has a focused package, while @platejs/docx reexports all three public APIs.

Loading…
CSVComponents

On This Page

FeaturesOwnershipKit UsageInstallationAdd KitPaste from WordImport DOCXExport DOCXDOCX Export KitAPI Reference@platejs/docxDocxImportPluginDocxExportPluginexportToDocxdownloadDocx
Build your editor
Production-ready AI template and reusable components.
Get all-access

Features

  • Normalize HTML and RTF pasted from Microsoft Word
  • Import .docx files with comments and conversion warnings
  • Export Plate content with document styles, page settings, tables, lists, and images
Report an issue
Client boundary

Paste, file import, and file download use browser APIs. Keep these operations in client code. DOCX export also uses React static rendering, so pass the same plugin descriptors and static components that define your document output.

Ownership

SurfaceOwnerUse it for
DOCX facade@platejs/docxImporting paste, import, and export APIs from one package
DocxPastePlugin@platejs/docx-pastePaste from Word
DocxImportPlugin@platejs/docx-importConverting a .docx buffer into Plate nodes
DocxExportPlugin, exportToDocx@platejs/docx-exportConverting Plate nodes into a DOCX blob
Registry DocxKitApp-local copied codeChoosing and ordering the complete DOCX plugin preset
Registry DocxExportKitApp-local copied codeProviding DOCX-specific static renderers

Kit Usage

The registry kit is the fastest complete setup. The app-local array installs JuicePlugin, DocxPastePlugin, DocxImportPlugin, and DocxExportPlugin. JuicePlugin inlines pasted CSS before Plate decodes it.

Installation

pnpm add @platejs/docx @platejs/juice
pnpm add @platejs/docx @platejs/juice

Add Kit

'use client';
 
import {
  DocxExportPlugin,
  DocxImportPlugin,
  DocxPastePlugin,
} from '@platejs/docx';
import { JuicePlugin } from '@platejs/juice';
 
export const DocxKit = [
  JuicePlugin,
  DocxPastePlugin,
  DocxImportPlugin,
  DocxExportPlugin,
] as const;
'use client';
 
import {
  DocxExportPlugin,
  DocxImportPlugin,
  DocxPastePlugin,
} from '@platejs/docx';
import { JuicePlugin } from '@platejs/juice';
 
export const DocxKit = [
  JuicePlugin,
  DocxPastePlugin,
  DocxImportPlugin,
  DocxExportPlugin,
] as const;
components/editor/editor.tsx
import { createPlateEditor } from 'platejs/react';
import { DocxKit } from '@/components/editor/docx';
 
const editor = createPlateEditor({
  plugins: [...DocxKit],
});
components/editor/editor.tsx
import { createPlateEditor } from 'platejs/react';
import { DocxKit } from '@/components/editor/docx';
 
const editor = createPlateEditor({

Paste from Word

Install only @platejs/docx-paste when clipboard input is the only DOCX capability you need. JuicePlugin preserves styles defined in Word's pasted HTML.

pnpm add @platejs/docx-paste @platejs/juice
pnpm add @platejs/docx-paste @platejs/juice
components/editor/editor.tsx
import { DocxPastePlugin } from '@platejs/docx-paste';
import { JuicePlugin } from '@platejs/juice';
import { createPlateEditor } from 'platejs/react';
 
const editor = createPlateEditor({
  plugins: [JuicePlugin, DocxPastePlugin],
});
components/editor/editor.tsx
import { DocxPastePlugin } from '@platejs/docx-paste';
import { JuicePlugin } from '@platejs/juice';
import { createPlateEditor } from 'platejs/react';
 
const editor = createPlateEditor({
  plugins: [JuicePlugin, DocxPastePlugin],
});

Once installed, DocxPastePlugin detects Word HTML in clipboard data, cleans the HTML and RTF, and lets the installed Plate codecs decode the result.

Import DOCX

DocxImportPlugin converts a DOCX ArrayBuffer into nodes, comments, and warnings. The editor's installed HTML codecs determine the resulting Plate nodes.

pnpm add @platejs/docx-import
pnpm add @platejs/docx-import
components/editor/editor.tsx
import { DocxImportPlugin } from '@platejs/docx-import';
import { createPlateEditor } from 'platejs/react';
import { BaseEditorKit } from '@/components/editor/plugins-static';
 
const editor = createPlateEditor({
  plugins: [...BaseEditorKit, DocxImportPlugin],
});
 
export async function importDocx(file: File) {
  const result = await editor
    .plugin(DocxImportPlugin)
    .api.import(await file.arrayBuffer());
 
  editor.update.fragment.replace(result.nodes);
 
  return {
    comments: result.comments,
    warnings: result.warnings,
  };
}
components/editor/editor.tsx
import { DocxImportPlugin } from '@platejs/docx-import';
import { createPlateEditor } from 'platejs/react';
import { BaseEditorKit } from '@/components/editor/plugins-static';
 
const editor = createPlateEditor({
  plugins: [...BaseEditorKit, DocxImportPlugin],
});
 
export async function importDocx(file: File) {
  const result = await editor
    .plugin(DocxImportPlugin)
    .api.import(await file.arrayBuffer());
 
  editor.update.fragment.replace(result.nodes);
 
  return



Each imported comment contains its Word comment id, extracted text, and references into the returned node snapshot.

Export DOCX

DocxExportPlugin owns editor-bound export. Pass the document snapshot explicitly so the operation is deterministic.

pnpm add @platejs/docx-export
pnpm add @platejs/docx-export
components/editor/editor.tsx
import { DocxExportPlugin, downloadDocx } from '@platejs/docx-export';
import { createPlateEditor } from 'platejs/react';
import { BaseEditorKit } from '@/components/editor/plugins-static';
import { DocxExportKit } from '@/components/editor/docx-export';
 
const editorPlugins = [...BaseEditorKit, ...DocxExportKit] as const;
const editor = createPlateEditor({
  plugins: [...editorPlugins, DocxExportPlugin],
});
 
export async function downloadEditorDocx() {
  const blob = await editor
    .plugin(DocxExportPlugin)
    .api.toBlob(editor.read.children(), {
      editorPlugins,
      orientation: 'portrait',
    });
 
  downloadDocx(blob, 'document.docx');
}
components/editor/editor.tsx
import { DocxExportPlugin, downloadDocx } from '@platejs/docx-export';
import { createPlateEditor } from 'platejs/react';
import { BaseEditorKit } from '@/components/editor/plugins-static';
import { DocxExportKit } from '@/components/editor/docx-export';
 
const editorPlugins = [...BaseEditorKit, ...DocxExportKit] as const;
const editor = createPlateEditor({
  plugins: [...editorPlugins, DocxExportPlugin],
});
 
export async function downloadEditorDocx() {
  const blob = await editor
    .plugin(DocxExportPlugin)






Use exportToDocx when you do not need an installed plugin portal:

import { downloadDocx, exportToDocx } from '@platejs/docx-export';
 
const blob = await exportToDocx(editor.read.children(), {
  editorPlugins,
  margins: { bottom: 1440, left: 1440, right: 1440, top: 1440 },
});
 
downloadDocx(blob, 'document.docx');
import { downloadDocx, exportToDocx } from '@platejs/docx-export';
 
const blob = await exportToDocx(editor.read.children(), {
  editorPlugins,
  margins: { bottom: 1440, left: 1440, right: 1440, top: 1440 },
});
 
downloadDocx(blob, 'document.docx');

DOCX Export Kit

The app-local DocxExportKit supplies static renderers for code blocks, columns, equations, callouts, headings, and tables of contents.

import { BaseHeadingPlugin } from '@platejs/basic-nodes';
import { BaseCalloutPlugin } from '@platejs/callout';
import {
  BaseCodeBlockPlugin,
  BaseCodeHighlightPlugin,
  BaseCodeLinePlugin,
} from '@platejs/code-block';
import { BaseColumnItemPlugin, BaseColumnPlugin } from '@platejs/layout';
import { BaseEquationPlugin, BaseInlineEquationPlugin } from '@platejs/math';
import { BaseTocPlugin } from '@platejs/toc';
 
import { CalloutElementDocx } from '@/components/editor/callout-static';
import {
  CodeBlockElementDocx,
  CodeLineElementDocx,
  CodeSyntaxLeafDocx,
} from '@/components/editor/code-block-static';
import {
  ColumnElementDocx,
  ColumnGroupElementDocx,
} from '@/components/editor/column-static';
import { HeadingElementDocx } from '@/components/editor/heading-static';
import {
  EquationElementDocx,
  InlineEquationElementDocx,
} from '@/components/editor/math-static';
import { TocElementDocx } from '@/components/editor/toc-static';
 
/**
 * Editor kit for DOCX export.
 *
 * Uses standard static components for most elements (with juice CSS inlining),
 * but uses docx-specific components for elements that need special handling:
 * - Code blocks (syntax highlighting, line breaks)
 * - Columns (table layout instead of flexbox)
 * - Equations (inline font instead of KaTeX)
 * - Callouts (table layout for icon placement)
 * - Headings (bookmark anchors for TOC links)
 * - TOC (anchor links with paragraph breaks)
 *
 * Tables use base version with juice CSS inlining.
 */
export const DocxExportKit = [
  BaseCodeBlockPlugin.configure({
    component: CodeBlockElementDocx,
  }),
  BaseCodeLinePlugin.configure({
    component: CodeLineElementDocx,
  }),
  BaseCodeHighlightPlugin.configure({
    component: CodeSyntaxLeafDocx,
  }),
  BaseColumnItemPlugin.configure({
    component: ColumnElementDocx,
  }),
  BaseColumnPlugin.configure({
    component: ColumnGroupElementDocx,
  }),
  BaseEquationPlugin.configure({
    component: EquationElementDocx,
  }),
  BaseInlineEquationPlugin.configure({
    component: InlineEquationElementDocx,
  }),
  BaseCalloutPlugin.configure({
    component: CalloutElementDocx,
  }),
  BaseHeadingPlugin.configure({
    component: HeadingElementDocx,
  }),
  BaseTocPlugin.configure({
    component: TocElementDocx,
  }),
];
import { BaseHeadingPlugin } from '@platejs/basic-nodes';
import { BaseCalloutPlugin } from '@platejs/callout';
import {
  BaseCodeBlockPlugin,
  BaseCodeHighlightPlugin,
  BaseCodeLinePlugin,
} from '@platejs/code-block';
import { BaseColumnItemPlugin, BaseColumnPlugin } from '@platejs/layout';
import { BaseEquationPlugin, BaseInlineEquationPlugin } from '@platejs/math';
import { BaseTocPlugin } from '@platejs/toc';
 
import { CalloutElementDocx } from '@/components/editor/callout-static';
import {
  CodeBlockElementDocx,
  CodeLineElementDocx,
  CodeSyntaxLeafDocx,
} from '@/components/editor/code-block-static'
























































API Reference

@platejs/docx

The facade reexports DocxPastePlugin, DocxImportPlugin, DocxExportPlugin, and the focused packages' operations and types. Applications own plugin membership and order through their local plugin arrays.

DocxImportPlugin

editor.plugin(DocxImportPlugin).api.import(arrayBuffer, options?) returns:

FieldTypeDescription
nodesDescendant[]Plate nodes decoded by the installed HTML codecs
commentsDocxComment[]Comment text and references into nodes
warningsstring[]Conversion and decode warnings

options.rtf accepts matching RTF clipboard data when the caller has it.

DocxExportPlugin

editor.plugin(DocxExportPlugin).api.toBlob(value, options?) returns a DOCX Blob for the explicit node snapshot.

exportToDocx

exportToDocx(value, options?) returns a DOCX Blob without installing DocxExportPlugin.

OptionTypeDescription
allowRemoteImagesbooleanFetch remote HTTP images during export
customStylesstringAppend CSS to the default DOCX styles
editorPluginsreadonly BasePluginInput[]Descriptors used for static HTML rendering
editorStaticComponentReact.ComponentType<PlateStaticProps>Static editor wrapper
fontFamilystringDocument body font
marginsDocxExportMarginsPage margins in twentieths of a point
orientation'landscape' | 'portrait'Page orientation
pageSizePageSizePage width and height in twentieths of a point
titlestringDocument metadata title

downloadDocx

downloadDocx(blob, filename) triggers a browser download and appends .docx when needed.

plugins: [
...
DocxKit],
});
{
comments: result.comments,
warnings: result.warnings,
};
}
.api.
toBlob
(editor.read.
children
(), {
editorPlugins,
orientation: 'portrait',
});
downloadDocx(blob, 'document.docx');
}
;
import {
ColumnElementDocx,
ColumnGroupElementDocx,
} from '@/components/editor/column-static';
import { HeadingElementDocx } from '@/components/editor/heading-static';
import {
EquationElementDocx,
InlineEquationElementDocx,
} from '@/components/editor/math-static';
import { TocElementDocx } from '@/components/editor/toc-static';
/**
* Editor kit for DOCX export.
*
* Uses standard static components for most elements (with juice CSS inlining),
* but uses docx-specific components for elements that need special handling:
* - Code blocks (syntax highlighting, line breaks)
* - Columns (table layout instead of flexbox)
* - Equations (inline font instead of KaTeX)
* - Callouts (table layout for icon placement)
* - Headings (bookmark anchors for TOC links)
* - TOC (anchor links with paragraph breaks)
*
* Tables use base version with juice CSS inlining.
*/
export const DocxExportKit = [
BaseCodeBlockPlugin.configure({
component: CodeBlockElementDocx,
}),
BaseCodeLinePlugin.configure({
component: CodeLineElementDocx,
}),
BaseCodeHighlightPlugin.configure({
component: CodeSyntaxLeafDocx,
}),
BaseColumnItemPlugin.configure({
component: ColumnElementDocx,
}),
BaseColumnPlugin.configure({
component: ColumnGroupElementDocx,
}),
BaseEquationPlugin.configure({
component: EquationElementDocx,
}),
BaseInlineEquationPlugin.configure({
component: InlineEquationElementDocx,
}),
BaseCalloutPlugin.configure({
component: CalloutElementDocx,
}),
BaseHeadingPlugin.configure({
component: HeadingElementDocx,
}),
BaseTocPlugin.configure({
component: TocElementDocx,
}),
];