@docx-editor.dev/editor-api

v2.1.3 · 2 published subpaths with full TypeScript signatures and JSDoc.

Subpaths

Package root

Work is described against proxy objects and nothing reaches the document until context.sync(), which sends one ordered batch and either applies all of it or none of it. Reading a property nobody asked for is an error rather than a silent undefined.

This entry needs no browser. It opens DOCX bytes, drives them, and saves them back, so a server, a worker or a build script can import the package name and get the whole API.

Functions (1)

isDocxEditorErrorfunctionSource ↗

Whether a caught value is one of ours.

By name as well as by instanceof: a consumer can end up with two copies of this module (a bundle plus a dependency's), and an instanceof that fails across them would send a perfectly ordinary PropertyNotLoaded down a consumer's unexpected-error path.

declare function isDocxEditorError(value: unknown): value is DocxEditorError;

Classes (30)

Body_2class

A story: the main body of a document, a header or footer variant, or a note's body — and everything in it in reading order.

Its paragraphs are the DOCUMENT'S, not just the top level's. A paragraph inside a table cell, or inside a table inside a cell, or inside a block-level content control, is an ordinary editable paragraph and appears here, exactly as it does in Word's own paragraph collection. A collection listing only direct children would describe a smaller document than the one on screen.

[Body.clear](Body.clear) leaves one empty paragraph, matching what Word produces when a reader selects everything and deletes. A body that already holds no paragraph reports InvalidArgument rather than inventing a block.

declare class Body extends ModelObject
MemberTypeSummary
clearEmpty the story, leaving one empty paragraph behind.
contentControlsContentControlCollectionThe content controls this story holds, in document order — the OUTERMOST ones.
fontFontThe character formatting of the whole story: what all of it agrees on, and what a write sets.
getCommentsThe comments anchored in this story, in document order. Replies hang off the comment.
insertParagraphAdd a paragraph at the start or the end of the story. Answers the new paragraph.
insertTextWrite text over the whole story, or at either edge of it. Answers the text's own range.
listsListCollectionEvery list this story holds, in the order their numbers first appear.
paragraphsParagraphCollectionEvery paragraph in this story in reading order, at every depth.
revisionsRevisionCollectionThe tracked changes in this story that the engine can resolve, in document order.
stylestringThe paragraph style, by the name a reader sees in the styles gallery.
textstringThe whole story's text.

BookmarkclassSource ↗

A name a document gives to a stretch of itself.

A bookmark IS its name. OOXML writes it as a pair of markers around the text, and the name is the only thing identifying it — so this object is a name plus the range those markers currently enclose. A bookmark whose markers left with the text they surrounded refuses rather than answering where they used to be.

start, end and delete are absent by design: the first two are document-wide character offsets, the coordinate space this API does not maintain, and delete would have to remove a marker pair, which the canonical write path does not offer.

declare class Bookmark extends ModelObject implements PromisedItem
MemberTypeSummary
namestringThe name the document declares this bookmark with.
rangeRangeThe text the bookmark's markers enclose.
selectPut the reader's selection on the bookmark. `NotSupported` where there is no reader.

BookmarkCollectionclassSource ↗

The bookmarks of a story or a range, as of the batch that loaded them.

Like every collection here, items is the LOADED answer rather than a live view: bookmarks added after the load are not in it, and reaching them means loading again.

declare class BookmarkCollection extends HandleCollection<Bookmark>

ClientObjectclassSource ↗

The base every document proxy extends.

A proxy is three things and no more: the context it belongs to, the path that says whether it can be addressed, and the properties a completed load filled in.

A RELEASED proxy still answers what it already knew. Reading a property loaded before the run ended is served from memory, because that value is a copy the consumer already holds — it is not a reach into a document. Anything that would talk to the document (load, a write, a method) refuses with InvalidObjectPath. The line is "does this need the document", not "does this look like a read".

declare abstract class ClientObject implements RuntimeManagedObject
MemberTypeSummary
(constructor)Constructs a new instance of the `ClientObject` class
contextRequestContextThe context this object currently belongs to.
handleThe handle to address this object with, or `InvalidObjectPath`.
isNullObjectbooleanWhether this object turned out not to exist.
loadQueue the reads that fill in the selected properties.
onLoadWhat this kind of object does with a resolved load request.
requireAddressableThe check every call that talks to the document makes first.

ClientResultclassSource ↗

A value a queued method promised to produce, readable after the next sync().

Deliberately not a Promise. A method call inside a batch has not been sent yet, so there is no pending work to await and nothing that could resolve on its own — awaiting one would deadlock a consumer who then never calls sync(). A result is a box that stays EMPTY until the sync fills it, and reading it early is ValueNotLoaded rather than undefined flowing onwards into something that misinterprets it.

declare class ClientResult<T>

The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the ClientResult class.

```ts
const count = body.getParagraphCount();
await context.sync();
console.log(count.value);
```
MemberTypeSummary
isLoadedbooleanWhether the sync that fills this has happened.
valueTThe value, once a `sync()` has filled it in.

Comment_2class

A comment: a conversation about a stretch of the document, not a single remark.

[Comment.replies](Comment.replies) holds the answers, and resolving is a property of the whole thread — assigning resolved marks this comment and everything answering it, which is what Word's own pane does.

authorEmail, a writable content, and delete are absent: CT_Comment records only an author and initials (Word's addresses live in people.xml, which this API does not read), and neither a body rewrite nor a marker-pair removal is an operation the canonical write path offers. The comment's text is published as text.

declare class Comment extends CommentBase
MemberTypeSummary
getRangeThe words the comment is about.
repliesCommentReplyCollectionThe answers to this comment, in document order.
replyAnswer the comment, over the same words it is anchored to.
resolvedbooleanWhether the thread is resolved.

CommentCollectionclassSource ↗

The comments on a document, story or range, as of the batch that loaded them.

declare class CommentCollection extends HandleCollection<Comment>
MemberTypeSummary
getFirstThe first comment. `ItemNotFound` at the sync if there are none.

CommentReplyclassSource ↗

One answer in a comment thread.

Authored over the parent comment's own range, because that is where the conversation is anchored and OOXML gives a reply no other place to be. Resolving is a property of the whole thread rather than of any one reply — see [Comment.resolved](Comment.resolved).

declare class CommentReply extends CommentBase

CommentReplyCollectionclassSource ↗

The replies to one comment, in thread order, as of the batch that loaded them.

declare class CommentReplyCollection extends HandleCollection<CommentReply>
MemberTypeSummary
getFirstThe first reply. `ItemNotFound` at the sync if nobody answered.

ContentControlclassSource ↗

A part of a document a template marked as a field.

A control is NOT its w:id. The attribute is optional in OOXML and unique nowhere, so a document may hold one control with no id and two with the same one. This object is addressed by an opaque host-minted handle instead, and [ContentControl.id](ContentControl.id) is answered as METADATA — a label the file wrote, empty where it wrote none. getById still exists, because a template author knows their own numbering, and it answers the first match in document order rather than refusing.

A control's contents are not its value. text reads the characters; setValue writes in the vocabulary the control's own type accepts — a declared item for a dropdown, an ISO date for a date picker, a state for a checkbox — because writing "true" into a checkbox's runs would produce a document whose glyph and whose w14:checked disagree.

declare class ContentControl extends ModelObject implements PromisedItem
MemberTypeSummary
cannotDeletebooleanWhether the control refuses to be deleted.
cannotEditbooleanWhether the control's contents refuse to be edited. Resolved like `cannotDelete`.
contentControlsContentControlCollectionThe controls INSIDE this one, in document order.
deleteRemove the control.
getRangeThe stretch of the story the control's content covers.
idstringThe `w:id` the file wrote, as a string, and `''` where it wrote none.
insertTextPut text into the control: over what it holds, or at one end of it.
paragraphsParagraphCollectionThe paragraphs the control holds. Empty for an inline control, which holds none.
placeholderShownbooleanWhether the control is showing its prompt rather than a value (`w:showingPlcHdr`).
setValueWrite the control's value.
subtypestringWhat kind of control it is: `plainText`, `dropDownList`, `checkbox`, `date`, …
tagstring`w:tag` — the machine-readable label a template puts on a field. `''` where absent.
temporarybooleanWhether the control removes its own wrapper on the first content edit (`w:temporary`).
textstringThe characters the control encloses, as the document reads them.
titlestring`w:alias` — what Word's UI calls the control's title. `''` where absent.

ContentControlCollectionclassSource ↗

The content controls of a document, story or range, as of the batch that loaded them.

getById answers the first match in document order, because w:id is optional in OOXML and unique nowhere — see [ContentControl](ContentControl) for why choosing predictably beats refusing.

declare class ContentControlCollection extends HandleCollection<ContentControl>
MemberTypeSummary
getByIdThe first control carrying one `w:id`, or `ItemNotFound` where the scope holds none.
getByTagEvery control in the scope carrying one tag, in document order.
getByTitleEvery control in the scope carrying one title, in document order.
getFirstThe first control. `ItemNotFound` at the sync if the scope holds none.
getFirstOrNullObjectThe first control, or an object that says `isNullObject` where there is none.

Document_2class

The document: the root every other object is reached from.

Deliberately thin. A document here is not a bag of content — it is the thing that HAS stories. It publishes the main story as [Document.body](Document.body), plus that story's paragraphs directly as document.paragraphs, because that is how source-compatible code walks a document.

Reached once per [RequestContext](RequestContext) and memoized: context.document is the same object every time, so a property loaded through one reference reads back through any other.

declare class Document extends ModelObject
```ts
await runtime.run(async (context) => {
  const paragraphs = context.document.paragraphs;
  paragraphs.load('text');
  await context.sync();
  for (const paragraph of paragraphs.items) console.log(paragraph.text);
});
```
MemberTypeSummary
bodyBodyThe main story.
commentsCommentCollectionThe comments anchored in the main story, in document order.
contentControlsContentControlCollectionThe content controls of the main story, in document order — the outermost ones.
endnotesNoteItemCollectionThe document's endnotes, in the order its notes part writes them.
footnotesNoteItemCollectionThe document's footnotes, in the order its notes part writes them.
paragraphsParagraphCollectionThe main story's paragraphs, in reading order.
revisionsRevisionCollectionThe tracked changes of the main story that the engine can resolve.
sectionsSectionCollectionThe document's sections, in document order.

DocxEditorErrorclassSource ↗

Every refusal this runtime throws.

Branch on [DocxEditorError.code](DocxEditorError.code), never on the message. Codes are stable public API — added rather than repurposed — so a consumer that handles PropertyNotLoaded by loading and syncing again keeps working across versions.

Nothing from the engine appears in the message. Host rejection reasons, opaque handle refs and offset ranges are all withheld: a ref in a message is a name a consumer can start depending on, and a store's rejection reason would become a documented one the moment somebody matched on it. What a consumer gets instead is a stable code, a fixed sentence, and target — the consumer-facing path they wrote themselves.

declare class DocxEditorError extends Error
```ts
try {
  await context.sync();
} catch (error) {
  if (error instanceof DocxEditorError && error.code === 'StaleDocument') {
    // Re-read and retry: someone else changed the document first.
  }
}
```
MemberTypeSummary
(constructor)Constructs a new instance of the `DocxEditorError` class
actualRevision?numberFor `StaleDocument`: the revision the document was actually at.
codeDocxEditorErrorCodeWhich refusal this is. Stable across versions; the thing to branch on.
expectedRevision?numberFor `StaleDocument`: the revision the context had read at.
target?stringConsumer-facing path of the object or property involved, when there is one to name.

FontclassSource ↗

The character formatting of whatever it belongs to: a story, a stretch of one, or a paragraph.

A font has no identity of its own — it is a view onto its owner's characters and shares its owner's path, so a font reached from a deleted paragraph's range refuses at the same moment the range does rather than holding a stale address.

Reading is AGREEMENT, and null means "no agreed value": every run the owner covers says bold, or the answer is null. Null is also the answer when nothing in range authors the property at all. Both are one answer on purpose, because this API reads what the document AUTHORS rather than what the style cascade computes — a heading whose bold comes from styles.xml reads null. Answering the cascade would let a caller read an inherited value, write it straight back, and silently freeze it into the paragraph as if the author had chosen it.

Assignments within one sync() are ONE write: font.bold = true; font.size = 12 accumulates into a single run-property operation. That is required, not an optimisation — a run-property write carries the run's whole property bag, so a second write planned from the same pre-batch tree would carry a bag the first had already superseded, which the host refuses with ConflictingChanges.

declare class Font extends ModelObject
MemberTypeSummary
boldbooleanWhether every character agrees it is bold, or `null` where they do not.
colorstring`#RRGGBB`. `null` where the characters disagree, or where the colour is `auto`.
italicbooleanWhether every run in range is italic. `null` where they disagree or none says.
namestringThe typeface name the characters state, or `null` where they do not agree on one.
onLoadOne read for every property asked for.
sizenumberPoints.

ListclassSource ↗

A list: the set of paragraphs sharing one numbering id.

A list is not an ELEMENT. OOXML has no list — it has paragraphs that each name a w:numId, and a list is the set that name the same one. So [List.id](List.id) is that number, [List.paragraphs](List.paragraphs) is the set, and a list exists exactly as long as some paragraph is still in it.

declare class List extends ModelObject implements PromisedItem
MemberTypeSummary
getLevelParagraphsThe list's paragraphs at one level, in reading order.
idnumberThe `w:numId` the list's paragraphs share — the document's own identity for the list.
insertParagraphAdd a numbered paragraph to the list, at its start or its end.
paragraphsParagraphCollectionEvery paragraph in the list, in reading order.

ListCollectionclassSource ↗

The lists in a story, as of the batch that loaded them.

declare class ListCollection extends HandleCollection<List>
MemberTypeSummary
getByIdThe list with one `w:numId`, or `ItemNotFound` where the story has none.
getFirstThe first list. `ItemNotFound` at the sync if the story has none.

ListItemclassSource ↗

A paragraph's membership of a list: which list, and at what level.

listString (the "3." or "iv)" a reader sees) and siblingIndex are absent because they are PAINTED, not authored — computed during layout by a counter that walks the story applying numbering.xml, its abstract-numbering indirection, restarts and overrides. Answering them here would mean a second counter that disagrees with the one on screen the first time a document overrides a level.

declare class ListItem extends ModelObject
MemberTypeSummary
levelnumberHow deeply the item is nested: zero for a top-level item, up to eight.

NoteItemclassSource ↗

One footnote or endnote: text that belongs to the document but not to its flow.

A note IS a story. Its [NoteItem.body](NoteItem.body) is an ordinary [Body](Body) — paragraphs, formatting, styles, the same operations — laid out at the foot of a page or the end of the document rather than in the column, so everything the object model can do to the main story it can do to a note without a second vocabulary.

delete() removes the reference too. A note's body and the citation that reached it are one thing to a reader, and deleting the body alone would leave a mark pointing at nothing. The engine spells that as a package-level transaction, which is why it travels alone in its batch.

declare class NoteItem extends ModelObject implements PromisedItem
MemberTypeSummary
bodyBodyThe note's own story.
deleteRemove the note and every reference to it.
getNextThe next note of the same kind. `ItemNotFound` at the sync when this is the last one.
typeNoteItemTypeWhether this is a footnote or an endnote.

NoteItemCollectionclassSource ↗

The notes of one kind, in the order the notes part writes them.

DocxEditor's own collection type: the pinned reference fixture does not carry Word.NoteItemCollection, so it is not measured for conformance — recorded as an omission in compat/manifest.json — while NoteItem itself is. Without it a note would be unreachable, which is the one thing worse than an unmeasured collection.

declare class NoteItemCollection extends HandleCollection<NoteItem>
MemberTypeSummary
getFirstThe first note. `ItemNotFound` at the sync if the document has none of this kind.

PageSetupclassSource ↗

The page a section is laid out on: paper size, margins, and orientation.

This is w:sectPr — everything a caller usually wants from a section lives here rather than on [Section](Section) itself, which is mostly navigation.

declare class PageSetup extends ModelObject
MemberTypeSummary
bottomMarginnumberPoints.
leftMarginnumberPoints.
orientationPageOrientationWhich way round the page is.
pageHeightnumberPoints.
pageWidthnumberPoints.
rightMarginnumberPoints.
topMarginnumberPoints.

ParagraphclassSource ↗

One paragraph: what it says, what it is, and the ways it can be changed.

Identity is the document's own. [Paragraph.uniqueLocalId](Paragraph.uniqueLocalId) is the w14:paraId the file carries — the value Word writes, and the one commentsExtended.xml and coauthoring merges already anchor to — never a position in a collection. Deleting the paragraph above this one does not change it, which is the point: an agent that read a document, thought about it, and now wants to write to "the paragraph I was looking at" cannot express that with an index. A paragraph the file gave no id gets one deterministically at open, so the same bytes always answer the same identities and saving writes them back.

A structural edit owns its paragraph for the batch: delete(), split() and insertParagraph() change what offsets mean, so a second call in the same sync() that also touches this paragraph is refused with ConflictingChanges rather than planned against coordinates that have stopped describing it. Two syncs get both edits, each exactly as asked.

declare class Paragraph extends ModelObject implements PromisedItem
MemberTypeSummary
alignmentParagraphAlignmentHow the paragraph's lines are aligned, or `Unknown` where it authors no alignment.
clearEmpty this paragraph's text, leaving the paragraph itself where it is.
deleteRemove this paragraph and everything in it.
firstLineIndentnumberPoints. Negative for a hanging indent — the first line starting left of the rest.
fontFontThe character formatting of this paragraph's characters, and of its paragraph mark.
insertParagraphAdd a paragraph beside this one. Answers the new paragraph.
insertTextWrite text over this paragraph or at either edge of it. Answers the written text's range.
leftIndentnumberPoints.
lineSpacingnumberPoints between the paragraph's lines.
listListThe list this paragraph is in.
listItemListItemWhere this paragraph sits in its list. Reading `level` on a paragraph in none refuses.
rightIndentnumberPoints.
spaceAfternumberPoints below the paragraph.
spaceBeforenumberPoints above the paragraph.
splitBreak this paragraph at every occurrence of any delimiter.
stylestringThe paragraph style, by the name a reader sees in the styles gallery.
textstringThis paragraph's text. Readable after `load('text')` and a `sync()`.
uniqueLocalIdstringThe document's own identity for this paragraph.

ParagraphCollectionclassSource ↗

The paragraphs of a story, a range, or a list, as of the batch that loaded them.

Contains paragraphs at every depth — inside table cells, nested tables, and block-level content controls — matching Word's own collection rather than only the owner's direct children.

One of the two collections whose members are not plain handles: the pieces a [Paragraph.split](Paragraph.split) answers are filled in by the split's own command rather than by a separate listing read.

declare class ParagraphCollection extends ItemCollection<Paragraph>
MemberTypeSummary
getFirstThe first paragraph. `ItemNotFound` at the sync if the collection holds none.
getFirstOrNullObjectThe first paragraph, or an object that will report `isNullObject`.
getLastThe last paragraph. `ItemNotFound` at the sync if the collection holds none.
getLastOrNullObjectThe last paragraph, or an object that will report `isNullObject`.

Range_2class

A stretch of a story: two endpoints, each a paragraph and a UTF-16 offset.

A range is a SNAPSHOT, not a tracked region. Its endpoints name the paragraphs they were found in and the offsets they were found at, so it stays meaningful across edits ELSEWHERE in the document and becomes an explicit InvalidObjectPath refusal once one of its paragraphs is gone. What it deliberately does not do is follow edits INSIDE itself: a range over "alpha" whose paragraph then gains a word at offset 0 still names offsets 0..5. Word's own ranges do move, by keeping a live region in the document; this API has none, and pretending otherwise would answer text from a place the caller was not looking at.

That is also why start and end are absent rather than unimplemented — they are document-wide character positions, a different addressing scheme from this API's paragraph identity plus UTF-16 offset. Ask a range for its [Range.paragraphs](Range.paragraphs) instead.

declare class Range extends ModelObject implements PromisedItem
MemberTypeSummary
bookmarksBookmarkCollectionThe bookmarks whose text this range overlaps, in document order.
fontFontThe character formatting of the characters this range covers.
insertParagraphAdd a paragraph before or after the one this range starts or ends in.
insertTextWrite text at or over this range. Answers the range the written text occupies.
paragraphsParagraphCollectionThe paragraphs this range covers, in reading order.
selectPut the reader's selection on this range.
stylestringThe paragraph style, by the name a reader sees in the styles gallery.
textstringThe text between this range's endpoints.

RangeCollectionclassSource ↗

Ranges a read produced — the hits of a search, or the pieces a split answered.

Its members are SPANS rather than handles, which is what separates it from the handle-backed collections: each item carries its own paragraph-plus-offset endpoints instead of an opaque host-minted id.

declare class RangeCollection extends ItemCollection<Range>
MemberTypeSummary
getFirstThe first range. `ItemNotFound` at the sync if nothing matched.
getFirstOrNullObjectThe first range, or an object that will report `isNullObject`.
getLastThe last range. `ItemNotFound` at the sync if nothing matched.

RequestContextclassSource ↗

What a run hands its callback: one queue, one document, one sync at a time.

sync() is the only thing in this runtime that talks to the document, and it does so exactly once per call — plan the queued actions in order, send ONE batch, hydrate the answers. That is where atomicity comes from: the host commits a batch as one transaction, and the runtime never splits a consumer's sync() into several batches behind their back.

Conditional writes come from the same place. A context that has READ from the document remembers the revision it read at, and a later batch that writes goes out conditional on it, failing StaleDocument if the document moved. That is what stops a decision made from a cached read being applied to a document that has since changed — the hazard the read-decide-write shape of any batching API invites. A context that has read nothing has nothing to be stale about, so its writes go out unconditionally.

declare class RequestContext
MemberTypeSummary
capabilitiesDocumentCapabilitiesWhat the document host behind this context can do.
documentDocumentThe document this run is against.
syncSend everything queued as one batch and hydrate the answers.
trackedObjectsTrackedObjectsObjects kept addressable past the run that created them. See [TrackedObjects](TrackedObjects).

RevisionclassSource ↗

One tracked change, and a decision the engine can act on.

Only revisions the engine can actually resolve are answered as objects. Structural ones — a row, a cell, a section, the table grid — are omitted from the collection entirely rather than shipped as objects whose accept and reject both refuse: code walking the collection would stall on such an item with nothing to read that explains why.

declare class Revision extends ModelObject implements PromisedItem
MemberTypeSummary
acceptKeep the change, resolving every site that carries its identity in one transaction.
authorstringWho proposed the change.
dateDateWhen they proposed it, or `null` where the file recorded no date.
rangeRangeThe words the change covers.
rejectUndo the change, likewise in one transaction.
typeRevisionTypeWhat kind of change it is, by Word's own name for it.

RevisionCollectionclassSource ↗

The tracked changes on a document, story or range, as of the batch that loaded them.

Carries only the revisions the engine can resolve; see [Revision](Revision) for what is left out and why.

declare class RevisionCollection extends HandleCollection<Revision>
MemberTypeSummary
acceptAllKeep every change, as ONE decision and one undo unit.
rejectAllUndo every change, likewise as one decision.

SectionclassSource ↗

One section: the document's layout, not its content.

Everything a caller usually wants — paper size, margins, orientation — is on [Section.pageSetup](Section.pageSetup). The section itself is mostly navigation: the story it governs, the header and footer stories it declares, and the section after it.

getHeader and getFooter answer a body that may not exist yet, and say so. A section with no first-page header inherits the previous section's; one at the start of a document with none at all is refused with ItemNotFound rather than minting the part. Word creates the header when a script asks for it — doing that here would make a READ write to the document, and a header that exists only because it was asked about is a header the author never added.

declare class Section extends ModelObject implements PromisedItem
MemberTypeSummary
bodyBodyThe story this section governs.
getFooterThe footer story of one variant, as a body. `ItemNotFound` where the document has none.
getHeaderThe header story of one variant, as a body. `ItemNotFound` where the document has none.
getNextThe next section. `ItemNotFound` at the sync when this is the last one.
pageSetupPageSetupThe page this section is laid out on.

SectionCollectionclassSource ↗

The sections of a document, in document order, as of the batch that loaded them.

declare class SectionCollection extends HandleCollection<Section>
MemberTypeSummary
getFirstThe first section. `ItemNotFound` at the sync if the document has none.

TrackedObjectsclassSource ↗

The objects a context keeps addressable beyond the run that created them.

An ordinary proxy stops being usable when its run ends. Tracking one keeps its address alive so a later run(object, callback) can adopt it, and untracking releases it — which matters for long-lived callers, since a tracked object is a document reference that will not be collected on its own.

declare class TrackedObjects

The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the TrackedObjects class.

MemberTypeSummary
addKeep these objects usable after this run ends.
removeStop keeping them: they are released when this run ends, like any other object.

Interfaces (11)

CreateServerOptionsinterfaceSource ↗

How DocxEditor.createServer opens a document.

Opening DOCX bytes is a bounded parse: decompression-ratio and size caps, part and relationship path validation, DTD- and entity-free XML. A refusal comes back as InvalidArgument rather than as a throw from inside a zip decoder, and says nothing about WHY — a caller opening files they did not author gets "not a document this API can open", so a probe cannot use the error to learn the reader's limits.

interface CreateServerOptions
MemberTypeSummary
author?stringWho comments this runtime writes are recorded as.
limits?DocumentLimitsTighter budgets for the bounded reader — zip ratio, part count, XML depth.

DocumentCapabilitiesinterfaceSource ↗

Capabilities exposed by a DocxEditor runtime, frozen for its lifetime.

interface DocumentCapabilities
MemberTypeSummary
documentbooleanThere is a document to address at all. False for a browser host between mounts.
eventsbooleanThe host raises document events.
layoutbooleanThe host lays the document out, so paginated positions are meaningful.
saveboolean`save()` is offered — true for a server runtime, false for one borrowing an editor.
scrollingbooleanThe host can be scrolled to a position.
selectionbooleanThe host has a user selection to read or move.

DocumentLimitsinterfaceSource ↗

Optional tighter limits applied while opening untrusted DOCX bytes.

interface DocumentLimits
MemberTypeSummary
maxRelationships?numberMost relationships the package may declare.
maxXmlParts?numberMost XML parts the package may hold.
xml?DocumentXmlLimitsPer-part XML caps.
zip?DocumentZipLimitsArchive-level caps.

DocumentXmlLimitsinterfaceSource ↗

Resource limits for each parsed XML part.

interface DocumentXmlLimits
MemberTypeSummary
maxBytesnumberMost bytes any one XML part may be.
maxElements?numberMost elements any one XML part may contain.

DocumentZipLimitsinterfaceSource ↗

Resource limits for the DOCX archive.

interface DocumentZipLimits
MemberTypeSummary
maxEntriesnumberMost entries the archive may contain.
maxRatio?numberHighest tolerated decompression ratio — the zip-bomb guard.
maxTotalBytesnumberMost bytes the archive may decompress to in total.

DocxEditorErrorInitinterfaceSource ↗

The fields a [DocxEditorError](DocxEditorError) is constructed from.

interface DocxEditorErrorInit
MemberTypeSummary
actualRevision?numberThe revision the document was actually at, for `StaleDocument`.
codeDocxEditorErrorCodeWhich refusal this is. The stable thing to branch on.
expectedRevision?numberThe revision the context had read at, for `StaleDocument`.
target?stringThe consumer-facing path of the object or property involved — `document.body.text`, not a handle. Omitted when there is nothing to name.

DocxEditorNamespaceinterfaceSource ↗

The entry point, as much of it as works without an editor.

An object rather than a TypeScript namespace: a namespace with runtime members is a declaration-merging construct that does not survive being re-exported through a bundler as predictably, and DocxEditor.createServer reads the same either way.

Import from @docx-editor.dev/editor-api/browser for the same namespace plus createBrowser.

interface DocxEditorNamespace
MemberTypeSummary
createServerA runtime over DOCX bytes. Additionally offers `save()`.

DocxEditorRuntimeinterfaceSource ↗

A runtime: one document host, many runs.

Runs are ISOLATED, not serialized. Every [DocxEditorRuntime.run](DocxEditorRuntime.run) gets its own context and its own queue, so two runs cannot interleave into one batch, and a run started inside another run works instead of waiting for a lock its own caller holds. Batches are still ordered — each sync() sends one atomic batch, in the order the sync() calls happen.

Disposal is final: [DocxEditorRuntime.dispose](DocxEditorRuntime.dispose) releases the host once and is safe to call again, and every later run fails with RuntimeDisposed.

interface DocxEditorRuntime
MemberTypeSummary
capabilitiesDocumentCapabilitiesWhat the document host behind this runtime can do. Frozen at construction.
disposeRelease the host. Idempotent.
runRun one batch of work against the document. Answers with the callback's value.
runRun one batch of work, adopting objects a previous run tracked.

DocxEditorServerRuntimeinterfaceSource ↗

A runtime over DOCX bytes rather than a live editor — what DocxEditor.createServer answers.

Adds [DocxEditorServerRuntime.save](DocxEditorServerRuntime.save) to the shared contract, because a server runtime owns its document and can serialize it; a browser runtime borrows the editor's and cannot.

interface DocxEditorServerRuntime extends DocxEditorRuntime
MemberTypeSummary
saveThe current document as DOCX bytes.

LoadQueryOptionsinterfaceSource ↗

The object form of load(...): which properties, and how much of a collection.

An unknown key, a non-integer top, a property name that is not an identifier, or a value of the wrong type is refused as InvalidArgument here, naming the option — a misspelled key is the difference between "load selected properties" and "load nothing", which would otherwise surface as a PropertyNotLoaded much later at a call that looks correct.

interface LoadQueryOptions
MemberTypeSummary
expand?string | readonly string[]Which navigation properties to load along with them.
select?string | readonly string[]Which properties to load.
skip?numberFor a collection: skip this many items first.
top?numberFor a collection: at most this many items.

SearchOptionsinterfaceSource ↗

How a search is narrowed.

Every flag is honoured or REFUSED — never quietly ignored. A search that accepted matchWildcards and then ran a plain-text scan would answer the wrong offsets to a caller who edits at them, so the unimplemented options reach the host and come back as NotSupported.

They are declared here rather than left off the type because omitting them would make { matchWildcards: true } a compile error in code that is otherwise source-compatible with Word. The honest answer to that code is a runtime refusal naming the option, not a type error naming the interface.

interface SearchOptions
MemberTypeSummary
ignorePunct?booleanNot implemented; `true` is refused with `NotSupported`.
ignoreSpace?booleanNot implemented; `true` is refused with `NotSupported`.
matchCase?booleanMatch the query's case. Off by default, like Word's Find.
matchWholeWord?booleanOnly match where the query stands alone as a word.
matchWildcards?booleanNot implemented; `true` is refused with `NotSupported`.

Type aliases (18)

BesideLocationtypeSource ↗

Which side of a paragraph or a range a new paragraph goes on.

type BesideLocation = Extract<InsertLocation, 'Before' | 'After'>;

BodyInsertParagraphLocationtypeSource ↗

Where a story accepts a paragraph. Start/End mean "before the first"/"after the last".

type BodyInsertParagraphLocation = Extract<InsertLocation, 'Start' | 'End'>;

BodyInsertTextLocationtypeSource ↗

Where a story accepts text: over all of it, or at either edge.

type BodyInsertTextLocation = Extract<InsertLocation, 'Replace' | 'Start' | 'End'>;

ContentControlLockStatetypeSource ↗

The lock a control carries. ST_Lock, spelled as the schema spells it.

type ContentControlLockState = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';

ContentControlSubtypetypeSource ↗

The control types this API can create. Picture and repeating section are deferred.

type ContentControlSubtype = 'richText' | 'plainText' | 'dropDownList' | 'comboBox' | 'date';

ContentControlValuetypeSource ↗

What a control's own type accepts as a value.

A discriminated union rather than unknown: a dropdown and a checkbox do not take the same kind of thing, and a single setValue(value: string) would have to guess what 'true' means to a date picker.

type ContentControlValue = {
    readonly kind: 'text';
    readonly text: string;
} | {
    readonly kind: 'listItem';
    readonly value: string;
} | {
    readonly kind: 'checkbox';
    readonly checked: boolean;
}
/** `YYYY-MM-DD`, or a full ISO-8601 instant. */
 | {
    readonly kind: 'date';
    readonly iso: string;
};

DocxEditorErrorCodetypeSource ↗

What went wrong, as a value a consumer may branch on.

type DocxEditorErrorCode = 
/** A property was read before a `load(...)` for it completed in a `sync()`. */
'PropertyNotLoaded'
/** A `ClientResult` value was read before the sync that fills it. */
 | 'ValueNotLoaded'
/**
 * The object cannot be addressed, in either of the two ways that happens.
 *
 * NOT YET: an item accessor answers a proxy the read that names it has not answered for, and it
 * becomes usable at the next `sync()`. NOT ANY MORE: its run ended and nothing tracked it, which
 * is terminal. One code because from a consumer's side both are "this object cannot be used
 * here"; the message says which one, because the fix for one is not the fix for the other.
 */
 | 'InvalidObjectPath'
/** The object still belongs to a run that has not finished, so it cannot be handed over. */
 | 'ObjectInUse'
/** An argument or load option this API does not accept. */
 | 'InvalidArgument'
/** The collection has no such item — `getFirst()` on an empty one. */
 | 'ItemNotFound'
/** The host cannot do this at all — a capability it reports false. */
 | 'NotSupported'
/**
 * The member exists in this API's shape but this version does not implement it.
 *
 * Distinct from `NotSupported`, which is about the HOST: a headless document really has no
 * caret, and no version of this library will give it one. This code means the library, not the
 * document, is the limit — so a consumer knows to check the release notes rather than the host.
 */
 | 'NotImplemented'
/**
 * Two calls in one batch make claims on the same paragraph that cannot both hold.
 *
 * A batch is one transaction planned against the state at its start, which stops being
 * unambiguous once two calls restructure the same paragraph. Split them across two `sync()`
 * calls and each gets exactly what it asked for.
 */
 | 'ConflictingChanges'
/** The request context's `run` has finished, so it can no longer be used. */
 | 'InvalidRequestContext'
/** The runtime was disposed. Every later operation fails this way. */
 | 'RuntimeDisposed'
/** The document moved under a context that had already read from it; nothing was applied. */
 | 'StaleDocument'
/** The host is live but holds no document right now — an editor between mounts. */
 | 'DocumentUnavailable'
/** The document refused the change, or answered something this runtime cannot use. */
 | 'GeneralException';

HeaderFooterTypetypeSource ↗

Which header or footer of a section: Word's own three variants.

type HeaderFooterType = 'Primary' | 'FirstPage' | 'EvenPages';

InsertLocationtypeSource ↗

Every place this API can insert at. Individual members accept a subset.

type InsertLocation = 'Replace' | 'Start' | 'End' | 'Before' | 'After';

LoadOptiontypeSource ↗

Everything load(...) accepts: one property name, several, or a [LoadQueryOptions](LoadQueryOptions) object.

type LoadOption = string | readonly string[] | LoadQueryOptions;
```ts
paragraph.load('text');
paragraph.load(['text', 'style']);
paragraphs.load({ select: ['text'], top: 5 });
```

NoteItemTypetypeSource ↗

Which kind of note: Word's own two.

type NoteItemType = 'Footnote' | 'Endnote';

PageOrientationtypeSource ↗

Which way round a page is, in Word's own spelling.

Capitalised here and lower-case in the engine on purpose: the engine speaks OOXML's vocabulary, and this is the public API's. The mapping lives in this file and nowhere else.

type PageOrientation = 'Portrait' | 'Landscape';

ParagraphAlignmenttypeSource ↗

Paragraph alignment values readable and writable through this object model.

type ParagraphAlignment = 'Mixed' | 'Unknown' | 'Left' | 'Centered' | 'Right' | 'Justified';

ParagraphInsertTextLocationtypeSource ↗

Where a paragraph accepts text: over all of it, or at either edge of it.

type ParagraphInsertTextLocation = Extract<InsertLocation, 'Replace' | 'Start' | 'End'>;

RangeInsertTextLocationtypeSource ↗

Where a range accepts text. See Range#insertText for what Before/Start mean here.

type RangeInsertTextLocation = InsertLocation;

RevisionTypetypeSource ↗

Word's own names for a kind of change.

The WHOLE upstream vocabulary, because a declaration says what a caller may be handed and a caller switching on it should not have to be told which subset this engine happens to produce. Seven of these actually occur — insert, delete, replace, the two property kinds and the two move halves — because a change to a row, a cell or a section is structural, and this engine reports only the changes it can also accept or reject. See compat/manifest.json.

type RevisionType = 'None' | 'Insert' | 'Delete' | 'Property' | 'ParagraphNumber' | 'DisplayField' | 'Reconcile' | 'Conflict' | 'Style' | 'Replace' | 'ParagraphProperty' | 'TableProperty' | 'SectionProperty' | 'StyleDefinition' | 'MovedFrom' | 'MovedTo' | 'CellInsertion' | 'CellDeletion' | 'CellMerge' | 'CellSplit' | 'ConflictInsert' | 'ConflictDelete';

RunCallbacktypeSource ↗

What a run callback is given, and what it may answer with.

type RunCallback<T> = (context: RequestContext) => Promise<T>;

SelectionMode_2type

Where a selection lands: over the range, or collapsed to one of its edges.

type SelectionMode = 'Select' | 'Start' | 'End';

Variables (1)

DocxEditorconstSource ↗

The entry point: open a document and get a runtime to work against.

Import from @docx-editor.dev/editor-api/browser for the same namespace plus createBrowser, which borrows a live editor instead of owning bytes.

DocxEditor: DocxEditorNamespace
```ts
import { DocxEditor } from '@docx-editor.dev/editor-api';

const runtime = await DocxEditor.createServer(bytes, { author: 'Payroll bot' });
await runtime.run(async (context) => {
  const body = context.document.body;
  body.load('text');
  await context.sync();
});
const saved = await runtime.save();
```

On this page