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 | editor.read.value() |
| Persist exact proposals and decisions | projectAuthoredReview and parseAuthoredDocument |
| 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.
Exact authored review state is canonical JSON-compatible model data:
import { parseAuthoredDocument, projectAuthoredReview } from 'platejs/authored';
const snapshot = projectAuthoredReview(editor.read.value());
const json = JSON.stringify(snapshot.review);
const document = parseAuthoredDocument(json);import { parseAuthoredDocument, projectAuthoredReview } from 'platejs/authored';
const snapshot = projectAuthoredReview(editor.read.value());
const json = JSON.stringify(snapshot.review);
const document = parseAuthoredDocument(json);HTML and Markdown do not hide an authored document in their output.
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';
const result = await exportDocx(editor, { projection: 'review' });import { exportDocx } from 'platejs/docx/export';
const result = await exportDocx(editor, { projection: 'review' });Set nativeState: 'attach' only when a review file must carry Plate-only state
for a trusted exact round trip. Ordinary Word export contains the visible Word
document without an embedded Plate document.
See DOCX for cancellation, package limits, comments, retained source, and authored trust.
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.