Save Plate JSON when another Plate editor must recover the editable document. Use a format parser or serializer when content crosses an application boundary.
| Task | Surface |
|---|---|
| Persist the complete editor document, pending proposals included | editor.read.value() |
| Export a clean accepted or proposed document | projectAuthoredDocument from platejs/authored |
| Convert semantic HTML | platejs/html; Node parsing uses |
platejs/html/server| Convert Markdown | platejs/markdown |
| Import or export Word | platejs/docx/import and platejs/docx/export |
| Render component-styled HTML | platejs/static |
| Exchange browser clipboard MIME payloads | DataTransferFormat through platejs/dom |
There is no universal document converter. Each format owns its syntax, diagnostics, loss policy, limits, and retained source.
editor.read.value() includes the primary children, named roots, and persistent
metadata.
const document = editor.read.value();
const schema = editor.read.schema.identity();
await saveDocument({ document, schema });const document = editor.read.value();
const schema = editor.read.schema.identity();
await saveDocument({ document, schema });Saving only children drops roots and metadata. Persist an application schema
identity when stored documents require versioned migration. Validate migrated
data before publishing it to an editor.
The saved value also holds the authored review: each node's pending review
marks in its authored property and the review records in the document's
records. Loading it into an editor that installs AuthoredPlugin restores
the pending proposals. To save a clean document instead, project it:
import { projectAuthoredDocument } from 'platejs/authored';
const accepted = projectAuthoredDocument(editor.read.value(), {
projection: 'accepted',
});import { projectAuthoredDocument } from 'platejs/authored';
const accepted = projectAuthoredDocument(editor.read.value(), {
projection: 'accepted',
});HTML and Markdown carry no review. Every HTML, Markdown, plain-text and static
HTML export of a document with pending changes throws a TypeError unless
projection is 'accepted' or 'proposed'. A document without pending
changes needs no projection.
import { serializePlainText } from 'platejs';
const result = serializePlainText(editor, { projection: 'accepted' });import { serializePlainText } from 'platejs';
const result = serializePlainText(editor, { projection: 'accepted' });Feature plugins contribute structural plainText mappings through
formats/defineFormats. Plain text is one-way output; it does not become a
universal parser or persistence format.
Use direct functions for detached work:
import { parseHtml, serializeHtml } from 'platejs/html';
const parsed = parseHtml(source, { plugins: EditorKit });
const output = serializeHtml(document, {
plugins: EditorKit,
projection: 'accepted',
});import { parseHtml, serializeHtml } from 'platejs/html';
const parsed = parseHtml(source, { plugins: EditorKit });
const output = serializeHtml(document, {
plugins: EditorKit,
projection: 'accepted',
});In Node.js, import parseHtml from platejs/html/server. Install linkedom
for that server-only DOM adapter.
Install HtmlPlugin when a configured editor should expose
editor.api.html.parse, parseSlice, and serialize. See HTML.
import { parseMarkdown, serializeMarkdown } from 'platejs/markdown';
const parsed = parseMarkdown(source, { plugins: EditorKit });
const output = serializeMarkdown(document, {
plugins: EditorKit,
projection: 'proposed',
});import { parseMarkdown, serializeMarkdown } from 'platejs/markdown';
const parsed = parseMarkdown(source, { plugins: EditorKit });
const output = serializeMarkdown(document, {
plugins: EditorKit,
projection: 'proposed',
});Install MarkdownPlugin for editor.api.markdown.parse, parseSlice,
parseInline, and serialize. See Markdown.
DOCX import is detached. Supply the complete plugin target before the operation starts, then publish a successful document explicitly.
import { importDocx } from 'platejs/docx/import';
const result = await importDocx(file, { plugins: EditorKit });
if (result.ok) {
editor.update((tx) => tx.value.replace(result.document));
}import { importDocx } from 'platejs/docx/import';
const result = await importDocx(file, { plugins: EditorKit });
if (result.ok) {
editor.update((tx) => tx.value.replace(result.document));
}DOCX export captures a configured editor because static rendering, comments, retained source, and Word revisions are part of its package workflow.
import { exportDocx } from 'platejs/docx/export';
import { BaseEditorKit } from '@/components/editor/plugins-static';
const result = await exportDocx(editor, {
presentation: BaseEditorKit,
projection: 'review',
});import { exportDocx } from 'platejs/docx/export';
import { BaseEditorKit } from '@/components/editor/plugins-static';
const result = await exportDocx(editor, {
presentation: BaseEditorKit,
projection: 'review',
});A live editor's components are editing UI, so pass the app's static kit as
presentation to draw the file.
A Word file contains the visible Word document, its comments, and its tracked
revisions. A review export also stores the reviewed blocks and review records
in a custom XML part that a Plate import restores. Save Plate JSON beside it
when another Plate editor must recover named roots or metadata.
See DOCX for cancellation, package limits, comments, and retained source.
HTML, Markdown, and DOCX use format-specific diagnosed results. Success carries warnings and the requested document, slice, string, or Blob. Failure carries a nonempty error-first diagnostic tuple and no publishable carrier.
const result = editor.api.markdown.serialize({ projection: 'accepted' });
showDiagnostics(result.diagnostics);
if (!result.ok) return;
downloadMarkdown(result.data);const result = editor.api.markdown.serialize({ projection: 'accepted' });
showDiagnostics(result.diagnostics);
if (!result.ok) return;
downloadMarkdown(result.data);Expected source failure and representational loss return diagnostics.
Configuration errors, mapping bugs, and invalid serializer model data throw.
lossPolicy defaults to 'reject'; opt into 'allow' only when the caller
accepts the exact reported loss.
Feature plugins declare semantic mappings through formats and
defineFormats using the html, markdown, and plainText keys. The narrow
authoring callback cannot read a live editor or store.
Whole browser MIME payloads use DataTransferFormat, not feature mappings.
Clipboard insertion remains destination-aware and can preserve native open
edges and detached roots. See Plugin Methods and
Clipboard.
A complete parse returns EditorDocumentValue. Direct syntax slice or inline
parsing returns a closed, rootless ContentSlice. The insertion owner fits that
slice once the destination is known.
const result = editor.api.markdown.parseSlice(source);
if (result.ok) editor.update.slice.replace(result.slice);const result = editor.api.markdown.parseSlice(source);
if (result.ok) editor.update.slice.replace(result.slice);Do not turn a complete document into children before replacement; that drops
named roots and metadata. Do not invent a destination during detached parsing.