@eigenpal/docx-editor-core/docx
DOCX I/O
Parsing DOCX archives into the `Document` model and re-zipping a model back into a DOCX file. Use `./docx/serializer` for the lower-level Document → XML transforms.
The named exports below are the public API contract. Adding a parser helper to a source module does not automatically make it public — it must be added to this barrel to be reachable from `@eigenpal/docx-editor-core/docx`.
Functions(113)
attemptSelectiveSave
Attempt a selective save — patch only changed paragraphs in document.xml. Also updates comments, headers/footers, and core properties so that all document parts stay in sync even when only paragraphs are patched.
Returns the saved ArrayBuffer, or null if selective save is not possible (caller should fall back to full repack).
declare function attemptSelectiveSave(doc: Document, originalBuffer: ArrayBuffer, options: SelectiveSaveOptions): Promise<ArrayBuffer | null>;buildPatchedDocumentXml
Build a patched document.xml by splicing new paragraph XML into the original at the correct offsets. Only changed paragraphs are replaced; everything else is preserved byte-for-byte.
Returns null if any step fails.
declare function buildPatchedDocumentXml(originalXml: string, serializedXml: string, changedIds: Set<string>): string | null;calculateTabWidth
Calculate the width needed for a tab at a given position
declare function calculateTabWidth(currentPosition: number, tabStops: TabStop[], pageWidth: number): number;calculateTabWidthWithAlignment
Calculate tab width considering alignment
For non-left alignments (center, right, decimal), the width depends on the content that follows the tab.
declare function calculateTabWidthWithAlignment(currentPosition: number, tabStops: TabStop[], pageWidth: number, followingContentWidth?: number): {
width: number;
alignment: TabStopAlignment;
};createComplexFieldContext
Create a new complex field context
declare function createComplexFieldContext(): ComplexFieldContext;createDocx
Create a new DOCX from a Document (without requiring original buffer)
declare function createDocx(doc: Document): Promise<ArrayBuffer>;emuToPixels
Convert EMUs to pixels (at 96 DPI)
1 inch = 914400 EMUs = 96 pixels Returns 0 for null/undefined/NaN inputs.
declare function emuToPixels(emu: number | undefined | null): number;extractTextBoxContentElements
Extract raw paragraph elements from w:txbxContent Actual parsing happens via document parser to avoid circular dependencies
declare function extractTextBoxContentElements(txbxContent: Element | null): {
paragraphElements: Element[];
tableElements: Element[];
};formatNumber
Format a number according to the specified format
declare function formatNumber(num: number, format: NumberFormat): string;getBulletCharacter
Get the bullet character for a bullet list level
declare function getBulletCharacter(level: ListLevel): string;getEndnoteText
Get plain text content of an endnote
declare function getEndnoteText(endnote: Endnote): string;getFieldDisplayValue
Get the current display value of a field
declare function getFieldDisplayValue(field: Field): string;getFootnoteText
Get plain text content of a footnote
declare function getFootnoteText(footnote: Footnote): string;getFormatSwitch
Get the format switch value (* or @)
declare function getFormatSwitch(instruction: ParsedFieldInstruction): string | undefined;getHyperlinkRuns
Get all runs from a hyperlink
declare function getHyperlinkRuns(hyperlink: Hyperlink): Run[];getHyperlinkText
Get the display text of a hyperlink
Concatenates text from all child runs.
declare function getHyperlinkText(hyperlink: Hyperlink): string;getHyperlinkUrl
Get the resolved URL of a hyperlink
For external links, returns the full URL. For internal links, returns the anchor prefixed with #. Returns undefined if the link couldn't be resolved.
declare function getHyperlinkUrl(hyperlink: Hyperlink): string | undefined;getImageHeightPx
Get image height in pixels
declare function getImageHeightPx(image: Image): number;getImageWidthPx
Get image width in pixels
declare function getImageWidthPx(image: Image): number;getLeaderCharacter
Get the character used for a tab leader
declare function getLeaderCharacter(leader: TabLeader | undefined): string;getNextTabStop
Get the next tab stop position for a given current position
declare function getNextTabStop(currentPosition: number, tabStops: TabStop[], pageWidth: number): TabStop;getOutlineWidthPx
Get outline width in pixels
declare function getOutlineWidthPx(shape: Shape): number;getShapeDimensionsPx
Get shape dimensions in pixels
declare function getShapeDimensionsPx(shape: Shape): {
width: number;
height: number;
};getShapeHeightPx
Get shape height in pixels
declare function getShapeHeightPx(shape: Shape): number;getShapeWidthPx
Get shape width in pixels
declare function getShapeWidthPx(shape: Shape): number;getTableColumnCount
Get the number of columns in a table
Uses the table grid if available, otherwise counts cells in first row.
declare function getTableColumnCount(table: Table): number;getTableRowCount
Get the number of rows in a table
declare function getTableRowCount(table: Table): number;getTextBoxContentElement
Parse text box content XML element
declare function getTextBoxContentElement(wsp: Element): Element | null;getTextBoxDimensionsPx
Get text box dimensions in pixels
declare function getTextBoxDimensionsPx(textBox: TextBox): {
width: number;
height: number;
};getTextBoxHeightPx
Get text box height in pixels
declare function getTextBoxHeightPx(textBox: TextBox): number;getTextBoxMarginsPx
Get text box margins in pixels
declare function getTextBoxMarginsPx(textBox: TextBox): {
top: number;
bottom: number;
left: number;
right: number;
};getTextBoxOutlineWidthPx
Get outline width in pixels
declare function getTextBoxOutlineWidthPx(textBox: TextBox): number;getTextBoxText
Get plain text from text box (helper for search/indexing)
declare function getTextBoxText(textBox: TextBox): string;getTextBoxWidthPx
Get text box width in pixels
declare function getTextBoxWidthPx(textBox: TextBox): number;getWrapDistancesPx
Get wrap distances in pixels
declare function getWrapDistancesPx(image: Image): {
top: number;
bottom: number;
left: number;
right: number;
};hasContent
Check if a hyperlink has any content (runs)
declare function hasContent(hyperlink: Hyperlink): boolean;Check if shape has fill
declare function hasFill(shape: Shape): boolean;hasHeaderRow
Check if table has header row
declare function hasHeaderRow(table: Table): boolean;hasMergeFormat
Check if field has MERGEFORMAT switch (preserve formatting)
declare function hasMergeFormat(instruction: ParsedFieldInstruction): boolean;hasOutline
Check if shape has outline
declare function hasOutline(shape: Shape): boolean;hasTextBoxContent
Check if text box has content
declare function hasTextBoxContent(textBox: TextBox): boolean;hasTextBoxFill
Check if text box has fill
declare function hasTextBoxFill(textBox: TextBox): boolean;hasTextBoxOutline
Check if text box has outline
declare function hasTextBoxOutline(textBox: TextBox): boolean;hasTextContent
Check if a shape has text content
declare function hasTextContent(shape: Shape): boolean;hasVisibleLeader
Check if a leader type requires visible filling
declare function hasVisibleLeader(leader: TabLeader | undefined): boolean;injectReplyRangeMarkers
Inject `commentRangeStart`/`commentRangeEnd` for reply comments that share their parent comment's text range.
declare function injectReplyRangeMarkers(content: BlockContent[], comments: Comment[]): void;injectTCReplyRangeMarkers
Inject `commentRangeStart`/`commentRangeEnd` for comments whose parent is a tracked-change revision (insertion/deletion). The TC content nodes don't carry the comment's range, so we wrap them.
declare function injectTCReplyRangeMarkers(content: BlockContent[], comments: Comment[]): void;isBehindText
Check if an image is behind text
declare function isBehindText(image: Image): boolean;isBulletLevel
Check if a list level is a bullet (not numbered)
declare function isBulletLevel(level: ListLevel): boolean;isCellMergeContinuation
Check if a cell is part of a vertical merge
declare function isCellMergeContinuation(cell: TableCell): boolean;isCellMergeStart
Check if a cell starts a vertical merge
declare function isCellMergeStart(cell: TableCell): boolean;isDateTimeField
Check if field is a date/time field
declare function isDateTimeField(field: Field): boolean;isDecorativeImage
Check if image is decorative (should be ignored by screen readers)
declare function isDecorativeImage(image: Image): boolean;isDocPropertyField
Check if field is a document property field
declare function isDocPropertyField(field: Field): boolean;isExternalLink
Check if a hyperlink is an external link
declare function isExternalLink(hyperlink: Hyperlink): boolean;isFloatingImage
Check if an image is floating (anchored)
declare function isFloatingImage(image: Image): boolean;isFloatingShape
Check if shape is floating (anchored)
declare function isFloatingShape(shape: Shape): boolean;isFloatingTextBox
Check if text box is floating (anchored)
declare function isFloatingTextBox(textBox: TextBox): boolean;isInFrontOfText
Check if an image is in front of text
declare function isInFrontOfText(image: Image): boolean;isInlineImage
Check if an image is inline (not floating)
declare function isInlineImage(image: Image): boolean;isInternalLink
Check if a hyperlink is an internal bookmark link
declare function isInternalLink(hyperlink: Hyperlink): boolean;isKnownFieldType
Check if a field type is a known type
declare function isKnownFieldType(type: string): type is FieldType;isLineShape
Check if a shape is a line (connector)
declare function isLineShape(shape: Shape): boolean;isMergeField
Check if field is a mail merge field
declare function isMergeField(field: Field): boolean;isPageNumberField
Check if field represents a page number
declare function isPageNumberField(field: Field): boolean;isReferenceField
Check if field is a cross-reference field
declare function isReferenceField(field: Field): boolean;isSeparatorEndnote
Check if an endnote is a separator (not regular content)
declare function isSeparatorEndnote(endnote: Endnote): boolean;isSeparatorFootnote
Check if a footnote is a separator (not regular content)
declare function isSeparatorFootnote(footnote: Footnote): boolean;isShapeDrawing
Check if a drawing element contains a shape (not an image)
declare function isShapeDrawing(drawingEl: Element): boolean;isShapeTextBox
Check if a wps:wsp element is a text box
declare function isShapeTextBox(wsp: Element): boolean;isTextBoxDrawing
Check if a drawing element contains a text box Text boxes are shapes with wps:txbx content
declare function isTextBoxDrawing(drawingEl: Element): boolean;isTextBoxShape
Check if a shape is a text box
declare function isTextBoxShape(shape: Shape): boolean;isTocField
Check if field is a TOC/Index field
declare function isTocField(field: Field): boolean;isTotalPagesField
Check if field represents total page count
declare function isTotalPagesField(field: Field): boolean;mergeTabStops
Merge tab stops from different sources (style, direct formatting)
Direct formatting tab stops override style tab stops at the same position. "clear" alignment removes a tab stop from the style.
declare function mergeTabStops(styleTabs: TabStop[] | undefined, directTabs: TabStop[] | undefined): TabStop[];parseBorderSpec
Parse a single border specification
declare function parseBorderSpec(element: Element | null): BorderSpec | undefined;parseCellMargins
Parse cell margins (w:tblCellMar or w:tcMar)
declare function parseCellMargins(marginsElement: Element | null): CellMargins | undefined;parseDocx
Parse a DOCX file into a complete Document model
declare function parseDocx(input: DocxInput, options?: ParseOptions): Promise<Document>;parseDrawing
Parse a w:drawing element
The drawing element contains either wp:inline or wp:anchor.
declare function parseDrawing(drawingEl: Element, rels: RelationshipMap | undefined, media: Map<string, MediaFile> | undefined): Image | null;parseEndnoteProperties
Parse endnote properties from w:endnotePr element (Can appear in w:sectPr or w:settings)
declare function parseEndnoteProperties(element: Element | null): EndnoteProperties;parseEndnotes
Parse endnotes.xml
declare function parseEndnotes(endnotesXml: string | null, styles?: StyleMap | null, theme?: Theme | null, numbering?: NumberingMap | null, rels?: RelationshipMap | null, media?: Map<string, MediaFile> | null): EndnoteMap;parseFieldInstruction
Parse a complete field instruction into structured data
declare function parseFieldInstruction(instruction: string): ParsedFieldInstruction;parseFieldType
Parse field type from instruction string
Field instructions follow the format: FIELDNAME [arguments] [switches] Examples: - "PAGE \* MERGEFORMAT" - "DATE \ "MMMM d, yyyy"" - "MERGEFIELD client_name \* Upper" - "REF _Ref123456 \h"
declare function parseFieldType(instruction: string): FieldType;parseFloatingTableProperties
Parse floating table properties (w:tblpPr)
declare function parseFloatingTableProperties(tblpPrElement: Element | null): FloatingTableProperties | undefined;parseFootnoteProperties
Parse footnote properties from w:footnotePr element (Can appear in w:sectPr or w:settings)
declare function parseFootnoteProperties(element: Element | null): FootnoteProperties;parseFootnotes
Parse footnotes.xml
declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap | null, theme?: Theme | null, numbering?: NumberingMap | null, rels?: RelationshipMap | null, media?: Map<string, MediaFile> | null): FootnoteMap;parseHyperlink
Parse a hyperlink element (w:hyperlink)
Handles both external links (via r:id relationship) and internal links (via w:anchor bookmark reference).
declare function parseHyperlink(node: Element, rels: RelationshipMap | null, styles?: StyleMap | null, theme?: Theme | null, media?: Map<string, MediaFile> | null): Hyperlink;parseImage
Parse an image from a w:drawing element
This is the main entry point for image parsing.
declare function parseImage(node: Element, rels: RelationshipMap | undefined, media: Map<string, MediaFile> | undefined): Image | null;parseNumbering
Parse numbering.xml into NumberingDefinitions
declare function parseNumbering(numberingXml: string | null): NumberingMap;parseShading
Parse shading properties (w:shd)
declare function parseShading(shdElement: Element | null): ShadingProperties | undefined;parseShape
Parse a wps:wsp (Word Processing Shape) element
declare function parseShape(node: Element): Shape;parseShapeFromDrawing
Parse shape from a w:drawing element that contains a shape (not an image)
declare function parseShapeFromDrawing(drawingEl: Element): Shape | null;parseSimpleField
Parse a simple field element (w:fldSimple)
declare function parseSimpleField(node: Element, styles: StyleMap | null, theme: Theme | null): SimpleField;parseTableBorders
Parse table borders (w:tblBorders or w:tcBorders)
declare function parseTableBorders(bordersElement: Element | null): TableBorders | undefined;parseTableLook
Parse table look flags (w:tblLook)
declare function parseTableLook(lookElement: Element | null): TableLook | undefined;parseTableMeasurement
Parse a table measurement (width, height, etc.)
declare function parseTableMeasurement(element: Element | null): TableMeasurement | undefined;parseTableProperties
Parse table properties (w:tblPr)
declare function parseTableProperties(tblPrElement: Element | null): TableFormatting | undefined;parseTabStop
Parse a single tab stop element (w:tab within w:tabs)
declare function parseTabStop(tab: Element): TabStop | null;parseTabStops
Parse tab stops container (w:tabs)
declare function parseTabStops(tabs: Element | null): TabStop[];parseTabStopsFromParagraphProperties
Parse tab stops from paragraph properties element
declare function parseTabStopsFromParagraphProperties(pPr: Element | null): TabStop[] | undefined;parseTextBox
Parse a text box from a w:drawing element
This creates a TextBox object with placeholder content. The actual content parsing requires paragraph/table parsers which creates a circular dependency. The document parser should call parseTextBoxContent() separately with the required parsers.
declare function parseTextBox(drawingEl: Element): TextBox | null;parseTextBoxContent
Parse text box content with provided parser functions This avoids circular dependencies by accepting parser functions as parameters
declare function parseTextBoxContent(txbxContent: Element | null, parseParagraph: ParagraphParserFn, parseTable: TableParserFn | null, styles: StyleMap | null, theme: Theme | null, numbering: NumberingMap | null, rels?: RelationshipMap | null, _media?: Map<string, MediaFile>): Paragraph[];parseTextBoxFromShape
Parse text box from a wps:wsp element directly Useful when you already have the shape element
declare function parseTextBoxFromShape(wsp: Element, size: ImageSize, position?: ImagePosition, wrap?: ImageWrap): TextBox | null;pixelsToEmu
Convert pixels to EMUs. EMU coordinates in OOXML are integer-typed (xs:long); rounding here keeps floating-point drift (e.g. 52 px → 495299.99999999994) out of the document.
declare function pixelsToEmu(px: number): number;renderListMarker
Render list marker text by replacing placeholders with formatted numbers
declare function renderListMarker(lvlText: string, counters: number[], formats: NumberFormat[]): string;repackDocx
Repack a Document into a valid DOCX file
declare function repackDocx(doc: Document, options?: RepackOptions): Promise<ArrayBuffer>;resolveFillColor
Resolve fill color to CSS color string
declare function resolveFillColor(shape: Shape): string | undefined;resolveHyperlinkUrl
Resolve a hyperlink's rId to a URL using a relationship map
This is useful when you have a hyperlink that was parsed without relationship context and need to resolve it later.
declare function resolveHyperlinkUrl(hyperlink: Hyperlink, rels: RelationshipMap): string | undefined;resolveOutlineColor
Resolve outline color to CSS color string
declare function resolveOutlineColor(shape: Shape): string | undefined;resolveTextBoxFillColor
Resolve fill color to CSS color string
declare function resolveTextBoxFillColor(textBox: TextBox): string | undefined;resolveTextBoxOutlineColor
Resolve outline color to CSS color string
declare function resolveTextBoxOutlineColor(textBox: TextBox): string | undefined;updateMultipleFiles
Update multiple files in a DOCX buffer
declare function updateMultipleFiles(originalBuffer: ArrayBuffer, updates: Map<string, string | ArrayBuffer>, options?: RepackOptions): Promise<ArrayBuffer>;validatePatchSafety
Validate that a selective patch can be safely applied.
Checks: - All changed paraIds exist in original XML (exactly once) - All changed paraIds exist in serialized XML (exactly once) - Paragraph count matches between original and serialized
declare function validatePatchSafety(originalXml: string, serializedXml: string, changedIds: Set<string>): PatchValidationResult;Interfaces(5)
ComplexFieldContext
Complex field parsing context
interface ComplexFieldContext| Member | Type | Summary |
|---|---|---|
| codeRuns | Run[] | Runs in the field code section |
| dirty | boolean | Whether field needs update |
| fldLock | boolean | Whether field is locked |
| instruction | string | Accumulated instruction text |
| nestingLevel | number | Nesting level (for nested fields) |
| resultRuns | Run[] | Runs in the result section |
| state | ComplexFieldState | Current state |
EndnoteMap
Endnote map returned by parseEndnotes
interface EndnoteMap| Member | Type | Summary |
|---|---|---|
| byId | Map<number, Endnote> | All endnotes indexed by ID |
| endnotes | Endnote[] | Array of all endnotes in document order |
| getContinuationSeparator | — | Get continuation separator if exists |
| getEndnote | — | Get endnote by ID |
| getNormalEndnotes | — | Get all normal (non-separator) endnotes |
| getSeparator | — | Get separator endnote if exists |
| hasEndnote | — | Check if endnote exists |
FieldSwitch
Field switch parsed from instruction
interface FieldSwitch| Member | Type | Summary |
|---|---|---|
| switch | string | Switch character (e.g., '*', '', '#', 'h', 'p') |
| value? | string | Switch value if any |
FootnoteMap
Footnote map returned by parseFootnotes
interface FootnoteMap| Member | Type | Summary |
|---|---|---|
| byId | Map<number, Footnote> | All footnotes indexed by ID |
| footnotes | Footnote[] | Array of all footnotes in document order |
| getContinuationSeparator | — | Get continuation separator if exists |
| getFootnote | — | Get footnote by ID |
| getNormalFootnotes | — | Get all normal (non-separator) footnotes |
| getSeparator | — | Get separator footnote if exists |
| hasFootnote | — | Check if footnote exists |
ParsedFieldInstruction
Parsed field instruction with arguments and switches
interface ParsedFieldInstruction| Member | Type | Summary |
|---|---|---|
| argument? | string | Field argument (e.g., property name for DOCPROPERTY, bookmark name for REF) |
| raw | string | Raw instruction string |
| switches | FieldSwitch[] | Field switches (e.g., * MERGEFORMAT, @ "date format") |
| type | FieldType | Field type |
Type aliases(4)
ComplexFieldState
State machine for tracking complex field parsing
type ComplexFieldState = 'outside' | 'code' | 'result';NumberingMap
Map of rId to numbering definitions
type NumberingMap = {
definitions: NumberingDefinitions;
getLevel: (numId: number, ilvl: number) => ListLevel | null;
getAbstract: (abstractNumId: number) => AbstractNumbering | null;
getInstance: (numId: number) => NumberingInstance | null;
hasNumbering: (numId: number) => boolean;
};ParagraphParserFn
Type for the paragraph parser function to avoid circular imports
type ParagraphParserFn = (node: Element, styles: StyleMap | null, theme: Theme | null, numbering: NumberingMap | null, rels?: RelationshipMap | null) => Paragraph;TableParserFn
Type for the table parser function to avoid circular imports
type TableParserFn = (node: Element, styles: StyleMap | null, theme: Theme | null, numbering: NumberingMap | null, rels?: RelationshipMap | null, media?: Map<string, MediaFile>) => Table;Variables(4)
DEFAULT_TAB_ALIGNMENT
Default tab alignment
DEFAULT_TAB_ALIGNMENT: TabStopAlignmentDEFAULT_TAB_INTERVAL_TWIPS
Default tab stop interval in twips (0.5 inches = 720 twips at 1440 twips/inch) Word uses this when no explicit tab stops are defined
DEFAULT_TAB_INTERVAL_TWIPS = 720DEFAULT_TAB_LEADER
Default tab leader
DEFAULT_TAB_LEADER: TabLeaderKNOWN_FIELD_TYPES
All known field types from OOXML specification
KNOWN_FIELD_TYPES: FieldType[]