docx-editor

Core API

Programmatic DOCX import and export without mounting an editor.

@portone/docx-editor/core imports and exports DOCX without mounting an editor. importDocx returns a ProseMirror document and an opaque session that holds the rest of the package.

Import and export

Keep the session and pass it back to exportDocx with the original or transformed document:

import { exportDocx, importDocx } from "@portone/docx-editor/core";

const { doc, session } = importDocx(source);
const bytes = exportDocx(doc, session);

Both take an ArrayBuffer or Uint8Array. Outside a browser, pass an XML parser; Server environments explains how. The session must not be constructed or modified; documentNumbering(session) and documentPartPath(session) read from it.

A file that spells WordprocessingML under another prefix, or as its default namespace, opens: the parts are rewritten to the prefixes the editor writes before anything is read, and nothing of the document's content is changed by that. Such a package exports bytes that differ from the bytes that arrived, where a package already spelling those prefixes exports byte for byte. A main part that binds w itself to another namespace cannot be respelled and is still refused with unsupported-content.

What a document loses

Markup the editor cannot model is carried through the round trip, but some of it is invisible on the page and some stands behind a placeholder nobody can edit. notes reports preserved nodes in the main body:

const { doc, session, notes } = importDocx(source);

for (const note of notes) {
  console.log(note.severity, note.code, note.element, note.block);
}
FieldWhat it holds
severityhidden (kept, nothing on screen), placeholder (kept behind an uneditable placeholder), or approximated (not emitted yet).
coderange-marker for one end of a bookmark or similar range, preserved-inline and preserved-block for markup kept where it stood, preserved-run-content for a piece of a run, table-demoted for a table the editor could not model, paragraph-demoted (not emitted for a document being opened).
elementThe original element name, such as w:bookmarkStart.
partThe package path of the part it came from.
blockThe body block it falls in.
posIts position in the document, which a reader can select.

importDocx and documentFidelity cover the main body, not side stories; exportDocxReport adds what the writer had to approximate on the way out. An empty list therefore does not guarantee a lossless round trip.

exportDocxReport(doc, session) writes the file and returns { bytes, notes } for the document it wrote; exportDocx returns the bytes alone, and both take the same options. Inside an editor, documentFidelity returns the same list for the document as it stands.

Import limits

  • A single inflated part is limited to 32 MiB and the package total to 64 MiB.
  • Package paths that escape the archive and XML containing a DTD are rejected.
  • An image over 16 MiB is kept in the package but not rendered.

Utilities

  • docxSchema, the schema the imported document is built on.
  • documentNumbering(session, options?) reads the document's lists as the editor draws them, and parseNumbering(xml, options?) reads a numbering part on its own; pass links (numbering style id to list) to resolve lists defined through a numbering style.
  • toRunFormat, toParagraphFormat, toCellFormat, toRowFormat, toTableFormat, toTableWidth, and toImageExtent read a node's format attr into its typed shape, or null.
  • emuToPx and pxToEmu convert between EMU, the document's length unit, and CSS pixels.

What a plugin may rely on says which parts of the document model are stable across releases.

Guides

On this page