Office.js compatibility

Compare the supported Word JavaScript API subset, known differences, and unavailable APIs.

@docx-editor.dev/editor-api implements a subset of the Word JavaScript API object model. You can reuse code based on objects such as Document, Body, Paragraph, and Range.

Replace the Office host setup and account for the runtime differences on this page.

For task examples and every public symbol, use the API member directory. See Batching, loading, and errors for execution and recovery.

Compatibility matrix

A supported subset covers only the listed objects and operations. It does not mean that every Office.js member in that area works.

AreaStatusImplementedLimits
Batches and object lifecycleSupported subsetload(), sync(), tracked objects, null-object accessors, and prerequisite reads for supported proxiesInserted objects need a completed sync before dependent edits. Navigation expansion is unavailable.
Document and bodySupported subsetDocument.body, paragraphs, comments, revisions, sections, content controls, body text, styles, search, clear, and insertionThe package does not provide Office.onReady or Word.run.
Paragraphs and rangesSupported subsetRead text, insert or replace text, insert paragraphs, clear, delete, split, search, style, hyperlinks, and selectionThe API does not expose document-wide start or end offsets.
SearchPartialPlain-text search, matchCase, and matchWholeWordSetting ignorePunct, ignoreSpace, or matchWildcards to true fails with NotSupported.
Font formattingPartialBold, italic, color, name, size, underline, strike-through, highlight, subscript, and superscriptUnderline supports 18 styles. Highlight writes require the Word palette. Mixed, unspecified, or inherited values return null.
Paragraph formattingSupported subsetStyle, alignment, first-line indent, left indent, right indent, line spacing, space before, and space afterThe API exposes these values on Paragraph. It does not expose the full ParagraphFormat object.
ListsPartialCreate lists, attach/detach paragraphs, set bullets/numbering, nesting, indents, and restartPicture bullets are unavailable. Different list levels can batch after list creation.
BookmarksPartialDiscover bookmarks, read names and ranges, and select bookmarksThe API does not support bookmark deletion or document-wide bookmark offsets.
Sections and page setupPartialSection bodies, headers, footers, size, orientation, margins, page breaks, and next-page section breaksOther break types fail. Missing header/footer stories are created on their first write.
Footnotes and endnotesSupported subsetEnumerate notes, read note bodies and text, move to the next note, and delete notesUse document.footnotes and document.endnotes. These accessors differ from Office.js.
Comments and repliesPartialRead, create, reply, resolve, delete, and get the comment rangeWrites need an explicit author. Browser writes also need the Pro review module and an editable document. Comment body replacement does not work.
Tracked changesPartialCreate tracked text edits, read actionable revisions and their ranges, and accept or reject individual revisions or batchesTrackMineOnly supports text in one paragraph. TrackAll fails. resolve() skips unsupported groups; acceptAll() and rejectAll() fail if unsupported changes remain.
Content controlsPartialCommon properties, nested controls, lookup by ID, tag, or title, text insertion, deletion, ranges, and typed value writesThe API does not expose typed Office.js subtype objects. The runtime rejects writes to custom XML-bound controls.
HyperlinksPartialRead or write Range.hyperlinkStandalone Hyperlink and HyperlinkCollection objects do not exist.
TablesPartialCreate rectangular tables, read/write values, add/delete rows and columns, set headers/styles/widths, and format cellsThe runtime rejects structural edits on merged or unsupported tables. Existing cell content may prevent destructive value replacement.
Inline picturesPartialInsert PNG/JPEG, enumerate, delete, resize, lock aspect ratio, and set alt descriptionsFloating shapes and picture bullets are unavailable. The runtime rejects conflicting dimensions when aspect ratio is locked.
FieldsPartialInsert, enumerate, change code, update results, and delete plain PAGE/NUMPAGES fieldsThe runtime rejects creation and evaluation of other field types and switches. Server evaluation requires explicit measured pagination.

Differences that affect existing code

Office.js behaviorDocxEditor behaviorRequired change
Office.onReady and Word.run open a batch.Your application creates a server or browser runtime.Use DocxEditor.createServer(bytes) or DocxEditor.createBrowser(editor).
An item accessor returns a usable proxy immediately.Supported read-derived proxies resolve prerequisite reads during sync().Sync before inspecting loaded values. Inserted objects require a sync before dependent operations.
A collection can load item properties with paths such as items/text.A collection loads its items only.Load the collection, sync, load each item, then sync again.
LoadQueryOptions.expand loads navigation properties.A nonempty expand value throws InvalidArgument.Load each navigation object or collection directly.
sync() can return a pass-through value.sync() returns Promise<void>.Keep pass-through values in local state.
The Office host supplies the signed-in comment author.DocxEditor does not use an Office account identity.Pass { author } when you create the runtime.
Comment and revision dates have the Date type.Invalid or missing file dates return null.Narrow the nullable Date before you use it.
Font reads use concrete values.Mixed, unspecified, or inherited style values return null.Narrow the value before you reuse it in a write.
Range.select() runs inside Word.Selection needs an attached browser editor.Check runtime.capabilities.selection. A server runtime returns NotSupported.
Header and footer getters can address missing parts.A getter returns a deferred body; its first write creates the missing story.Sync after resolving the section and before using a newly created object.
ContentControl.id is a number.ContentControl.id is a string because DOCX IDs can be missing or repeated.Do not use the file ID as a unique numeric key.
ContentControl.subtype uses Word interface terms.ContentControl.subtype uses DOCX control terms.Handle values such as plainText, dropDownList, and checkbox.

A read-derived range can resolve and edit in one sync:

const first = context.document.body.search('Total').getFirst();
first.insertText('TOTAL', 'Replace');
await context.sync();

Range snapshots differ from Word

A Range retains paragraph identities and UTF-16 offsets from the moment it was found. It does not follow later edits inside those paragraphs. Tracking the proxy only extends its lifetime; it does not create a moving text region. After an edit, search again or use its returned insertion range after sync.

Disjoint plain-text edits can batch in ordinary paragraphs with direct text runs. Their returned ranges account for all edits in that transaction. The runtime rejects overlapping edits and batches that mix text edits with formatting, hyperlinks, or structural writes in the same paragraph. Rich paragraphs and browser suggesting edits need one text edit per paragraph per sync. See Text and ranges for examples and recovery.

Editing batches and runtime limits

Batch independent reads and writes. Writes commit atomically at sync(). Supported read-derived proxies can trigger prerequisite reads before that commit. These reads use one revision; a concurrent change causes StaleDocument.

Sync after creating a table, picture, list, field, or text range before configuring that returned object. Structural edits sharing a paragraph can conflict; split them into separate syncs and reconsider their targets. Different list levels can batch after list creation. Competing proxies for one level still conflict. Page-field result updates can share a sync with queries and other result updates. They cannot share a sync with layout-changing writes, because evaluation uses the measured document before those writes.

Measured page fields on a server

Server PAGE and NUMPAGES updates require pagination.measurer configured with font resources. Font substitution can change page breaks and counts. Browser runtimes use the attached editor's measured layout.

See Fields and pagination for setup and the runnable report agent, including font loading and cleanup.

Common DocxEditor additions

These common members extend the Office.js-compatible subset.

MemberPurpose
Body.bookmarksEnumerates bookmarks in one body story.
Body.revisionsEnumerates revisions in one body story.
RevisionCollection.resolve()Resolves a selected batch or supported changes in one story and reports skipped decisions.
Document.footnotes and Document.endnotesEnumerate document notes.
NoteItem.textReads the same plain text as note.body.text.
ContentControlCollection.getByTag() and getByTitle()Finds controls without a file ID.
ContentControl.setValue()Writes values for text, checkbox, date, and list controls.
ContentControl.isBoundReports whether custom XML binding exists.
ContentControl.subtypeReports the control type with DOCX terms.
Comment.text and CommentReply.textRead comment text without replacing the comment body.
Paragraph.uniqueLocalIdReads the paragraph identity for the active runtime.

Body.bookmarks and Body.revisions only cover that body's story. They do not combine the main body, headers, footers, and notes.

ContentControl.isBound is a preflight check. sync() checks the binding again before it applies a write.

APIs that do not exist

Code that uses these APIs fails during TypeScript compilation.

APIAvailable alternative
Picture list levelsUse text bullets with an explicit font.
Shape and canvasesNo editing API alternative.
Repeating-section and picture content-control objectsUse common ContentControl members for other control kinds.
ContentControl.xmlMappingUse ContentControl.isBound to detect a binding. Writes to bound controls still fail.
Hyperlink, HyperlinkCollectionUse Range.hyperlink for one range.
Body.getHtml(), Body.getOoxml(), Paragraph.getText()Load Body.text or Paragraph.text. No OOXML or HTML result exists.
BookmarkCollection.exists()Load the collection and inspect its items.
Range.start, Range.end, Bookmark.start, Bookmark.endUse ranges and paragraph text.

Migrate an add-in

  1. Replace Word.run() with a runtime from DocxEditor.createServer() or DocxEditor.createBrowser().
  2. Keep the existing load() and sync() pattern.
  3. Apply the sync boundaries listed in Differences that affect existing code.
  4. Check the compatibility matrix for every object your add-in uses.
  5. Handle typed errors such as NotSupported, NotImplemented, and ItemNotFound.

How compatibility is checked

The repository keeps a reviewed manifest of supported Word API symbols. CI compares the authored TypeScript declarations with a pinned @types/office-js reference. CI also compiles representative Word code against the DocxEditor declarations.

For a document editing compatibility report, run this command from the repository root:

bun run --filter '@docx-editor.dev/editor-api' compat:report

The report compares editing methods and property writes with actual public source exports. The scope is defined in packages/editor-api/compat/editing-scope.json. Read-only APIs, navigation, host setup, enums, and support types are excluded. Property checks compare setter types without counting getter differences. It lists matching, differing, and missing signatures, with separate runtime notes from packages/editor-api/compat/runtime-notes.json. Read packages/editor-api/compat/reports/report.md for all endpoints, or report.json for expected and actual signatures. CI shows signature percentages and uploads the full report as an informational artifact. These percentages do not measure runtime equivalence or include other Office hosts.

The same command reports an 81-member document-editing profile from packages/editor-api/compat/agent-editing-scope.json. Read packages/editor-api/compat/reports/agent-editing-summary.md for percentages by area, and agent-editing-report.md or agent-editing-report.json for endpoint details. Member presence counts exposed members; exact signature percentage counts matching signatures out of 81. Neither percentage proves Word-equivalent behavior or the success rate for arbitrary documents. Use endpoint runtime notes and the runnable consumer workflows to assess your required operations. Update packages/editor-api/compat/runtime-notes.json when a supported domain or runtime difference changes.

The package does not include Microsoft's declarations. Installation, tests, and builds do not fetch them.

Next steps

On this page