import type { AnchorInfo, AnchorTargetRef, AnnotationUpdate, BlockMetadata, BookmarkInfo, BulkEditResult, CharSpan, CommentListEntry, ContentControlFillOptions, ContentControlInfo, CrossBlockMatch, DiffEntry, DocumentAnnotation, DocumentRange, DeliverableVerificationResult, DeliverableVerificationRequest, DocxodusWasmExports, DocxSessionProjection, DocxSessionSettings, EditResult, EditSummary, FillOptions, FindOptions, FormatOp, FormattingInspection, HeaderFooterKind, HyperlinkInfo, HyperlinkKind, ImageCapabilities, ImageDimensions, ImageInsertOptions, ImageOccurrence, FloatingImageLayout, InlineSpan, NumberFormat, PageNumberField, PageNumberingOp, PageSetupOp, TableOfAuthoritiesOptions, TableOfContentsOptions, TableOfFiguresOptions, PageCitation, PageCitationRequest, PageMapRegistrationResult, PageMapStatus, PackageManifest, ParagraphBorderEdge, ParagraphFormatOp, TableBorderSpec, TableInsertOptions, TableMetadataResult, TableCellResolutionResult, TableMergeContent, TableRowOptions, TableShadingScope, ListFormat, GrepOptions, ListMembership, MutationBatchMode, MutationBatchPreviewOptions, MutationBatchPreviewStep, MutationBatchResult, MutationBatchStep, MutationTransaction, DeliveryBundleResult, DeliveryEvidenceStatus, DeliveryReceiptBuildOptions, MutationPreconditions, CrossReferenceOptions, ReplaceOptions, RevisionListEntry, RevisionRepairProposal, RevisionRepairRequest, RevisionRepairResult, SectionInfo, SemanticChangeSet, StyleInfo, TemplatePlaceholder, TextMatch } from "./types.js"; import type { PageMap } from "./pagination.js"; import { DiffFormat, ProjectionDepth, ProjectionScopes, TrackedChangeMode } from "./types.js"; export declare class DocxSession { private readonly handle; private readonly wasm; /** * The receipts this client composed for previews it retained, keyed by previewId. The host * keeps the package and the binding; the step receipts live only here, so a commit can return * the previewed steps and change sets without the host re-parsing a client-composed result. */ private readonly retainedPreviewReceipts; /** @internal */ constructor(handle: number, wasm: DocxodusWasmExports["DocxSessionBridge"]); project(): DocxSessionProjection; /** Monotonic document version (0 at open; +1 per committed mutation/undo/redo). */ getVersion(): number; /** * Verification manifest for the current logical checkpoint. Unsaved edits are included and * the read does not mutate package bytes, caches, history, or the document version. */ getPackageManifest(): PackageManifest; /** Register a browser-materialized PageMap without changing the document version. */ registerPageMap(pageMap: PageMap, expectedRendererFingerprint?: string): PageMapRegistrationResult; getPageMapStatus(request?: PageCitationRequest): PageMapStatus; getPageCitation(anchorId: string, request: PageCitationRequest): PageCitation; /** Evaluate optimistic guards without mutating or advancing the version. */ checkPreconditions(preconditions: MutationPreconditions): EditResult; /** * Guard any synchronous mutation. WASM calls are synchronous and single-threaded, so the * check and callback form one uninterrupted client-side operation. Prefer a method's native * `preconditions` option where it has one (notably replaceTextRange's match-count guard). */ runWithPreconditions(preconditions: MutationPreconditions, mutation: () => EditResult): EditResult; /** * Execute synchronous mutations atomically by default. Atomic success is one undo/version * unit; any failed or thrown step restores the exact package and history checkpoint. */ executeBatch(steps: readonly MutationBatchStep[], mode?: MutationBatchMode, transaction?: MutationTransaction): MutationBatchResult; /** * What the session's host-owned delivery evidence recorder holds (issue #748). `enabled` is * false, with the reason, unless the session was opened with `captureDeliveryEvidence`. */ getDeliveryEvidenceStatus(): DeliveryEvidenceStatus; /** * Build the receipt-bearing delivery of this session through the shared bundle service: the * clean current package (`final-docx`), the source-to-delivered semantic delta, and the change * receipt (`change-receipt`) minted from the captured evidence — verifiable with * `verifyDeliveryReceipt` against the returned artifact bytes. A history that cannot be * attested yields an `incomplete` bundle whose receipt artifact carries the reason, and * `evidence.unavailableReason` says why. */ buildDeliveryReceipt(options?: DeliveryReceiptBuildOptions): DeliveryBundleResult; /** * Describe a batch to the session's delivery evidence recorder before running it, and hand * it the step results afterwards, so the version steps the batch produced are recorded under * this description rather than as unlabeled mutations. A bundle without the recorder, or a * session not capturing evidence, simply runs the batch. */ private recorded; /** * Make a preview retained by {@link previewBatch} (`retain: true`) the live document exactly * as previewed: the previewed package is restored byte-for-byte as one undo step, so the * generated anchor ids, timestamps and `packageHash` are exactly those the preview reported. * The commit is guarded — it refuses with `preview_stale`, editing nothing, when the session's * version, package content, tracked-changes mode or revision author moved since the preview, * and with `preview_not_found` once the preview expired, was evicted, or was already * committed. A `transaction` makes a retry after a lost response safe, as for * {@link executeBatch}. */ commitPreview(previewId: string, transaction?: MutationTransaction): MutationBatchResult; private runTransactional; private runBatch; /** * Execute the same callback batch algorithm against a complete isolated package clone. * Callbacks receive the shadow session explicitly; mutate that argument. The live session's * package, caches, version, configuration, and undo/redo history are never execution targets. */ previewBatch(steps: readonly MutationBatchPreviewStep[], mode?: MutationBatchMode, options?: MutationBatchPreviewOptions): MutationBatchResult; /** * Project a slice of the document keyed off an anchor — useful for showing * one section to an LLM at a time without paying the cost of projecting the * whole document. * * - `ProjectionDepth.SelfOnly` — just the addressed block (one paragraph, * row, etc.). * - `ProjectionDepth.Subtree` — the block + descendants (e.g. a table with * all its rows/cells, but no following content). * - `ProjectionDepth.SubtreeAndFollowingSiblings` (default) — for headings * this returns the whole section (heading + content up to the next same- * or-higher heading); for non-headings it behaves like `Subtree`. * * @see docs/architecture/docx_mutation_api.md */ projectAnchor(anchorId: string, depth?: ProjectionDepth, citation?: PageCitationRequest): DocxSessionProjection; /** * Render a single block to faithful HTML from the live session — the editor's * incremental per-block re-render after an edit. Resolves against the in-memory * document (no Save round-trip). `anchorId` is a block anchor (`kind:scope:unid`) * or the bare unid carried by a `data-anchor` attribute. Returns the block's HTML * element (no ``/`
` wrapper). */ renderBlock(anchorId: string, options?: { cssPrefix?: string; fabricateClasses?: boolean; }): string; replaceText(anchorId: string, markdown: string, preconditions?: MutationPreconditions): EditResult; deleteBlock(anchorId: string, preconditions?: MutationPreconditions): EditResult; /** Reorder one top-level paragraph/heading/list/table block relative to another. */ moveBlock(sourceAnchorId: string, targetAnchorId: string, position: "before" | "after"): EditResult; /** * Delete every top-level block-level sibling between `fromAnchorId` (inclusive) * and `toAnchorIdExclusive` (exclusive). Both anchors must share a direct * parent and live in the same package part. Returns a single `EditResult` * whose `removed` lists every anchor that was deleted. * * Records ONE undo snapshot — `undo()` restores the entire range. * * @see docs/architecture/docx_mutation_api.md#deleterange */ deleteRange(fromAnchorId: string, toAnchorIdExclusive: string): EditResult; /** * Delete a heading and everything below it up to (but not including) the next * heading at the same or higher level. The heading anchor must have `kind === "h"`. * * If the target is the last heading in its parent, the section extends to the * end of the parent (heading + everything after). * * @see docs/architecture/docx_mutation_api.md#deletesection */ deleteSection(headingAnchorId: string): EditResult; insertParagraph(anchorId: string, position: "before" | "after", markdown: string): EditResult; splitParagraph(anchorId: string, characterOffset: number): EditResult; mergeParagraphs(firstAnchorId: string, secondAnchorId: string): EditResult; /** * Insert an empty paragraph carrying a bottom border — an S-1-style horizontal rule — * before/after the block. `rule` styles the line (default: a single ≈1.5pt black rule). */ insertHorizontalRule(anchorId: string, position: "before" | "after", rule?: ParagraphBorderEdge): EditResult; /** * Insert a `rows`×`cols` table before/after the block. `options` controls borders, row-major * cell markdown, and cell alignment. The returned `EditResult.created` lists canonical `tc` * anchors (row-major), so each cell can then be addressed to fill/format. */ insertTable(anchorId: string, position: "before" | "after", rows: number, cols: number, options?: TableInsertOptions): EditResult; /** Resolve a canonical `tbl` anchor to explicit table/row/column/cell identities. */ getTableMetadata(tableAnchorId: string): TableMetadataResult; /** Resolve a canonical `tc` anchor to its zero-based table-grid coordinate and spans. */ resolveTableCellAnchor(cellAnchorId: string): TableCellResolutionResult; /** Resolve a zero-based table-grid coordinate to the physical `tc` covering it. */ resolveTableCellCoordinate(tableAnchorId: string, rowIndex: number, columnIndex: number): TableCellResolutionResult; /** * Table row/column editing, addressed by the canonical `tc` anchor returned from * {@link insertTable}'s `created` or table metadata. Insert clones the reference row/column's * widths and starts empty (`created` lists new `tc` anchors); delete of the last row/column removes * the whole table. All four are grid-aware: inserting across a merge extends it, deleting * through one narrows it, and deleting a vertical merge's lead row promotes the next row to * carry it — the grid is never left ragged. */ insertTableRow(cellAnchorId: string, position: "before" | "after"): EditResult; insertTableColumn(cellAnchorId: string, position: "before" | "after"): EditResult; deleteTableRow(cellAnchorId: string): EditResult; deleteTableColumn(cellAnchorId: string): EditResult; /** * Merge the rectangle of cells anchored at `cellAnchorId` running `rowSpan` rows down × * `colSpan` cells right (Word's *Merge Cells*): `w:gridSpan` for the horizontal extent, * `w:vMerge` restart/continue for the vertical one. The rectangle must tile the same whole grid * columns in every row it covers and must not clip a vertical merge entering from above or * continuing below — a partial overlap fails with `invalid_table_merge` instead of tearing the * grid. `content` decides what happens to the absorbed cells' content (default `"append"`). */ mergeCells(cellAnchorId: string, rowSpan: number, colSpan: number, content?: TableMergeContent): EditResult; /** * Split the merged cell at `cellAnchorId` back into unit cells, dropping its `w:gridSpan` and * `w:vMerge` markup and restoring one cell per grid column (each taking its `w:tblGrid` width). * Addressing a vertical-merge continuation unmerges the whole run. A cell with no merge markup * fails with `invalid_table_merge`. */ unmergeCells(cellAnchorId: string): EditResult; /** * Table styling, addressed by a canonical `tc` anchor — the post-insert counterpart of * {@link insertTable}'s options (issue #315 Stage A). `setColumnWidths` retunes `w:tblGrid` + * every row's cell width (one positive twip value per column) and pins the table to fixed * layout, exactly as inserting with explicit `columnWidths` would. */ setColumnWidths(cellAnchorId: string, widthsTwips: number[]): EditResult; /** * Set the table-level borders (`w:tblPr/w:tblBorders`) of the table containing the anchor. * Only the edges named by `spec.scope` are written; the rest are left untouched. Style * `"none"` removes the targeted edges. Omitting `spec` writes a thin single border all round. */ setTableBorders(cellAnchorId: string, spec?: TableBorderSpec): EditResult; /** * Shade the cell containing the anchor — or, with scope `"row"`, every cell of its row * (header-row banding). `fill` is a hex RRGGBB triplet (leading '#' tolerated) or `"auto"`; * `null` removes the shading. */ setCellShading(cellAnchorId: string, fill: string | null, scope?: TableShadingScope): EditResult; /** * Mark (or unmark) the row containing the anchor as a repeating header row * (`w:trPr/w:tblHeader`), so a multi-page table re-shows it on every page. Word only honors * the flag on a run of rows starting at the table's first row. */ setRepeatHeaderRow(cellAnchorId: string, repeat: boolean): EditResult; /** Apply row layout options to the row containing the canonical cell anchor. */ setTableRowOptions(cellAnchorId: string, options: TableRowOptions): EditResult; /** * Set the running header story for the section that owns `anchorId` (any body block in that * section) to `markdown`. Creates the header part + `w:headerReference` if the story of `kind` * doesn't exist yet, else replaces its content. The created header-paragraph anchors (scope * `hdr{N}`) come back in `EditResult.created` — insert a page number into one with * {@link insertPageNumberField}. `"first"` sets the section's title-page flag; `"even"` sets the * document's even/odd-headers flag. */ setHeaderText(anchorId: string, kind: HeaderFooterKind, markdown: string): EditResult; /** Set the running footer story for the section that owns `anchorId` — see {@link setHeaderText}; * the created footer-paragraph anchors (scope `ftr{N}`) come back in `EditResult.created`. */ setFooterText(anchorId: string, kind: HeaderFooterKind, markdown: string): EditResult; /** * Append a page-number field to the paragraph `anchorId` — typically a header/footer paragraph * returned by {@link setFooterText}/{@link setHeaderText}. `"currentPage"` emits a PAGE field, * `"totalPages"` a NUMPAGES field (native complex field with a cached result), and * `"pageOfTotal"` Word's "Page X of Y" gallery entry — the text `Page `, a PAGE field, the text * ` of ` and a NUMPAGES field, every run inheriting the paragraph's last run formatting (the * pieces cannot be composed from the single-field form: text after a field cannot be appended * without rewriting the field's result). Center it by setting the paragraph alignment * ({@link setParagraphFormat}). Returns the paragraph anchor in `modified`. * * `format` writes the field's own `\*` general-formatting switch (`PAGE \* roman` → `i, ii, iii`). * Omitting it — the default — emits a plain field, which is what Word inserts and what follows the * SECTION's format ({@link setPageNumbering}). Prefer the section setting for ordinary page * numbering: a switch here overrides it for this one field and keeps overriding it if the section * later changes. */ insertPageNumberField(anchorId: string, field?: PageNumberField, format?: NumberFormat): EditResult; /** * Set the page-numbering properties (`w:pgNumType`) of the section that owns `anchorId` (any body * block in that section) — Word's *Format Page Numbers…* dialog: which number the section starts * at and which format its pages use. Omitted fields on `op` are left unchanged, so the start can * be set without disturbing the format and vice versa. Creates the element, and a trailing * `w:sectPr`, if absent. * * Applying values the section already has is a successful no-op that does NOT consume undo * history — safe to call from a dropdown's change handler. */ setPageNumbering(anchorId: string, op: PageNumberingOp): EditResult; /** * Insert a **table of contents** before or after `anchorId` (issue #607). The field is written * dirty and the document asks for a field update on open, so Word paginates and fills the table * itself — nothing here ships a cached result that is stale the moment anything above it moves. * * The table is wrapped in the `w:sdt` content control Word puts around one, which is what gives * it the *Update Table* control in Word's UI. Word's `TOCHeading` and `TOC1` styles are * find-or-created; a document that already defines them keeps its own. * * Body anchors only, and refused under tracked-change recording: a generated table is regenerated * wholesale on every field update, so there is no reversible way to redline it. */ insertTableOfContents(anchorId: string, pos?: "before" | "after", options?: TableOfContentsOptions): EditResult; /** * Insert a **table of figures** — the captions carrying `options.captionLabel` and their page * numbers. Same field mechanics as {@link insertTableOfContents}; Word writes this one as a bare * paragraph rather than inside a content control, so this does too. */ insertTableOfFigures(anchorId: string, pos?: "before" | "after", options?: TableOfFiguresOptions): EditResult; /** * Insert a **table of authorities** — the cases, statutes or other authorities marked in the * document, grouped by `options.category`. The table lists entries the document has MARKED with * `TA` fields; a document with no marked citations produces a table that is correct and empty. */ insertTableOfAuthorities(anchorId: string, pos?: "before" | "after", options?: TableOfAuthoritiesOptions): EditResult; /** * Remove the section's page-numbering start/format: it reverts to continuing the previous * section's numbering in Word's default `1, 2, 3`. Chapter-numbering attributes * (`w:chapStyle`/`w:chapSep`) are preserved. A section with nothing to clear is a no-op. */ clearPageNumbering(anchorId: string): EditResult; /** * Make the `kind` header/footer stories of the section that owns `anchorId` actually RENDER: * `"first"` sets `w:titlePg`, `"even"` sets the document-global `w:evenAndOddHeaders`; * `"default"` needs no flag and succeeds as a no-op. Idempotent. * * {@link setHeaderText}/{@link setFooterText} set these flags while writing content, which covers * authoring a story from scratch — but NOT a document that already carries a first/even reference * with the flag absent (Word leaves exactly that behind when "Different first page" is switched * off). Editing such a story through the text ops otherwise yields header content that is present * but invisible. Note the `"even"` caveat from {@link setHeaderText}: the flag is document-global * and governs footers too. */ ensureHeaderFooterVisible(anchorId: string, kind: HeaderFooterKind): EditResult; /** * Word's "Different first page" / "Different odd & even pages" checkboxes as one verb: switch * the `kind` story of the section that owns `anchorId` (any body block in it) on or off. * `enabled: true` is exactly {@link ensureHeaderFooterVisible}; `enabled: false` removes the * flag that selects the story — `w:titlePg` from the governing `w:sectPr` for `"first"`, the * document-global `w:evenAndOddHeaders` for `"even"` — and leaves the story parts in place, * which is what Word does when the checkbox is cleared (re-enabling brings the content straight * back). Disabling `"default"` fails with `invalid_page_setup`: that story has no flag. * * A flag already in the requested state is a successful no-op that records NO undo step, so a * checkbox handler can call this unconditionally. Read the current state from * {@link SectionInfo.titlePage} / {@link SectionInfo.evenAndOddHeaders}. */ setHeaderFooterKindEnabled(anchorId: string, kind: HeaderFooterKind, enabled: boolean): EditResult; /** * Set the page geometry (`w:pgSz` / `w:pgMar`) of the section that owns `anchorId` — Word's * *Page Setup* dialog: page size, orientation, margins and header/footer distance. Omitted * fields on `op` are left unchanged; the elements are created in schema order when absent, as * is a trailing `w:sectPr` for a body that has none. Read the result back with * {@link getSectionInfo}. * * `landscape: true` without an explicit size swaps a portrait-shaped page's width and height * (and `false` swaps back), matching Word's orientation toggle. Invalid geometry — a * non-positive size, a negative margin, or opposing margins that leave no room — fails with * `invalid_page_setup` and touches nothing. Values the section already has are a successful * no-op that consumes no undo history. */ setPageSetup(anchorId: string, op: PageSetupOp): EditResult; /** * Create a footnote whose body is `markdown` and cite it from the body paragraph `anchorId`, at * `characterOffset` characters into that paragraph's text (0 = before all text, text length = * after all of it). On a document with no footnotes yet this also creates the footnotes part, * Word's two reserved separator notes, the `FootnoteText`/`FootnoteReference` styles and the * `w:footnotePr` settings declaration; otherwise the existing part is reused. The note id is * allocated above every id already used in the package, so non-contiguous ids can't collide. * * Returns the created note anchors in `EditResult.created` — the definition (kind `fn`) and its * paragraphs (kind `p`, scope `fn`) — so the note can immediately be edited with * {@link replaceText} or removed with {@link deleteBlock} (which also drops the body reference). * * Body paragraphs only: Word does not allow a note reference inside a header/footer story or * inside another note, so a non-body anchor fails with `anchorWrongKind`. */ insertFootnote(anchorId: string, characterOffset: number, markdown: string): EditResult; /** * Insert a Word-faithful internal cross-reference — a `REF` field targeting an existing * bookmark — at a character offset (issue #545). The field carries a cached result run * (the bookmarked text, or the target's auto-number under `referenceNumber`), so * renderers that do not recompute fields show a faithful snapshot and Word updates it * like a hand-authored cross-reference. A missing or incoherent bookmark fails with * `missing_bookmark_target`. */ insertCrossReference(anchorId: string, characterOffset: number, bookmarkName: string, options?: CrossReferenceOptions): EditResult; /** Create an endnote — see {@link insertFootnote}; writes the endnotes part and a * `w:endnoteReference`, and the created definition anchor has kind `en`. */ insertEndnote(anchorId: string, characterOffset: number, markdown: string): EditResult; /** * Add a **native Word comment** (real `w:comment` markup, visible in Word/Google * Docs/LibreOffice's Reviewing pane — not the {@link addAnnotation} overlay) on the body * paragraph `anchorId`. `span` selects the commented character range; `null` comments the * whole block. On a document with no comments yet this also creates the comments part and * the `CommentText`/`CommentReference` styles. `opts.date` (ISO-8601) is written only when * provided, keeping output deterministic by default. * * Returns the created definition anchor (kind `cmt`) and its paragraph anchors (kind `p`, * scope `cmt`) in `EditResult.created`, so the comment can immediately be edited with * {@link updateComment} or removed with {@link removeComment}. * * Body paragraphs only (Word has no comments-on-comments); a non-body anchor fails with * `anchor_wrong_kind`, a zero-length span with `empty_comment_span`. */ addComment(anchorId: string, span: CharSpan | null, author: string, markdown: string, opts?: { initials?: string; date?: string; }): EditResult; /** Add a native Word comment around the exact live extent of a tracked revision returned by * {@link listRevisions}. Accepting/rejecting the revision keeps the comment and either leaves * its range on surviving text or collapses it to a point. */ addCommentToRevision(revisionId: string, author: string, markdown: string, opts?: { initials?: string; date?: string; }): EditResult; /** * Add a native Word reply to `parentCommentAnchorId`. It adds an adjacent reference and * inherits the thread root's range through `w15:paraIdParent`; the required * `commentsExtended.xml` and `commentsIds.xml` parts are created when the parent was flat. */ addCommentReply(parentCommentAnchorId: string, author: string, markdown: string, opts?: { initials?: string; date?: string; }): EditResult; /** Replace a comment's body text, addressed by its definition anchor (kind `cmt`); the * comment's author/initials/date are preserved, as is the last paragraph's `w14:paraId` * (Word's reply-threading key). */ updateComment(commentAnchorId: string, markdown: string): EditResult; /** Resolve or reopen one comment (`false` reopens it). Flat comments are upgraded with the * paraId-keyed metadata Word uses, and the operation is undoable. */ setCommentResolved(commentAnchorId: string, resolved: boolean): EditResult; /** Remove a comment: the definition, its body marker triple everywhere in the package, and * any `commentsExtended`/`commentsIds` threading entries keyed by it. */ removeComment(commentAnchorId: string): EditResult; /** The document's native Word comments in comments-part order. */ listComments(): CommentListEntry[]; listHyperlinks(scopes?: ProjectionScopes): HyperlinkInfo[]; addHyperlink(anchorId: string, span: CharSpan, kind: HyperlinkKind, target: string): EditResult; updateHyperlink(hyperlinkId: string, kind: HyperlinkKind, target: string): EditResult; removeHyperlink(hyperlinkId: string): EditResult; /** Versioned operational facts for native image inspection/mutation in this runtime. */ getImageCapabilities(): ImageCapabilities; listImages(scopes?: ProjectionScopes): ImageOccurrence[]; insertImage(anchorId: string, characterOffset: number, bytes: Uint8Array, options?: ImageInsertOptions): EditResult; replaceImage(imageId: string, bytes: Uint8Array): EditResult; /** * Convert an external linked picture into an embedded one using bytes the caller fetched; * the engine never reaches the network itself. Refused for pictures that already embed * their media — see `ImageOccurrence.operations`. */ embedLinkedImage(imageId: string, bytes: Uint8Array): EditResult; setImageDimensions(imageId: string, dimensions: ImageDimensions): EditResult; setImageMetadata(imageId: string, altText: string | null, title: string | null): EditResult; setImageFloatingLayout(imageId: string, layout: FloatingImageLayout): EditResult; removeImage(imageId: string): EditResult; /** Native Word structured-document tags, in outer-before-inner story order. */ listContentControls(scopes?: ProjectionScopes): ContentControlInfo[]; fillContentControlText(anchorId: string, text: string, options?: ContentControlFillOptions): EditResult; fillContentControlRichText(anchorId: string, markdown: string, options?: ContentControlFillOptions): EditResult; setContentControlChecked(anchorId: string, isChecked: boolean, options?: ContentControlFillOptions): EditResult; setContentControlDate(anchorId: string, value: string | Date, displayText?: string, options?: ContentControlFillOptions): EditResult; selectContentControlItem(anchorId: string, value: string, options?: ContentControlFillOptions): EditResult; fillContentControlPicture(anchorId: string, bytes: Uint8Array, options?: ContentControlFillOptions): EditResult; addRepeatingSectionItem(sectionAnchorId: string, afterItemAnchorId?: string, options?: ContentControlFillOptions): EditResult; removeRepeatingSectionItem(itemAnchorId: string): EditResult; listBookmarks(scopes?: ProjectionScopes): BookmarkInfo[]; addBookmark(name: string, range: DocumentRange): EditResult; renameBookmark(name: string, newName: string): EditResult; moveBookmark(name: string, range: DocumentRange): EditResult; removeBookmark(name: string): EditResult; /** Markup-native tracked-revision listing, in document order across body, headers, * footers, footnotes, and endnotes. Ids are stable while the underlying markup * exists and address {@link acceptRevision}/{@link rejectRevision}; authors/dates * are the markup's own (no accept/reject re-diff). */ listRevisions(): RevisionListEntry[]; /** * The explicit repairs the registry offers for entries it refuses to resolve (issues * #754–#758): which carriers are defective, whether a unique repair exists, and what it * would do. Read-only; listing, accept and reject never repair. */ listRevisionRepairs(): RevisionRepairProposal[]; /** * Perform requested repairs atomically as one undo step. A kind the registry did not offer, * a non-repairable proposal, or a wrap-as-deletion without author and date refuses the whole * call (`revision_repair_rejected`) with nothing mutated. Repaired entries get new ids. */ repairRevisions(repairs: readonly RevisionRepairRequest[]): RevisionRepairResult; /** Accept ONE revision by the id {@link listRevisions} reported — insertions keep * their content, deletions are carried out, a move materializes at its destination, * a format change keeps the new properties. Undoable. */ acceptRevision(revisionId: string): EditResult; /** Reject ONE revision by id — the inverse of {@link acceptRevision}: insertions are * removed, deleted content is restored, a move stays at its source, a format change * restores the stored old properties. Undoable. */ rejectRevision(revisionId: string): EditResult; /** * Accept every live revision as one undoable session mutation. * * Fails closed: an unsupported, malformed, or ambiguous registry entry aborts the whole * operation (`revisionUnsupported`/`revisionMalformed`/`revisionAmbiguous`) and nothing is * mutated. There is no force mode — call {@link listRevisions} and read each entry's * `diagnostic` to see what blocks it. */ acceptAllRevisions(): EditResult; /** Reject every live revision as one undoable session mutation. Fails closed exactly like * {@link acceptAllRevisions}. */ rejectAllRevisions(): EditResult; applyFormat(anchorId: string, span: CharSpan | null, op: FormatOp): EditResult; /** * Convenience: find `substring` in the anchor's flat text and apply `op` to the * first occurrence. Eliminates the offset-arithmetic trap from #138 — caller passes * the visible text they want formatted, the WASM-side resolves it to a CharSpan. */ applyFormatBySubstring(anchorId: string, substring: string, op: FormatOp): EditResult; /** * Convenience: apply `op` to the exact span of a {@link TextMatch} (typically from * {@link grep}). The match's `enclosingAnchor.id` + `span` address one specific * occurrence even when several identical needles share the same block. */ applyFormatToMatch(match: TextMatch, op: FormatOp): EditResult; setParagraphStyle(anchorId: string, styleId: string): EditResult; /** Set paragraph alignment / indent / page-break-before (omitted fields are left unchanged). */ setParagraphFormat(anchorId: string, op: ParagraphFormatOp): EditResult; setListLevel(anchorId: string, levelDelta: number): EditResult; removeListMembership(anchorId: string): EditResult; /** Make the paragraph a bullet/numbered list item, or remove list membership ("none"). */ applyListFormat(anchorId: string, kind: ListFormat): EditResult; /** Apply one list format across the contiguous sibling run from `firstAnchorId` to * `lastAnchorId` inclusive (either document order). Every member shares one `w:num` * instance so the numbering sequence stays intact; the whole range is a single undo step. */ applyListFormatRange(firstAnchorId: string, lastAnchorId: string, kind: ListFormat): EditResult; /** Restart the anchored list item's numbering at `value` — Word's *Set Numbering Value…*. * Writes a `w:startOverride` on a dedicated `w:num` instance and repoints the anchored item * plus every following member of its sequence, so a mid-list restart splits the sequence * exactly like Word (earlier items keep their numbers, the tail continues from `value`). */ setListStartOverride(anchorId: string, value: number): EditResult; /** Remove the numbering restart from the anchored item's whole sequence (the inverse of * {@link setListStartOverride}); the sequence reverts to the definition's own start. A * sequence with no override at the item's level is a successful no-op. */ clearListStartOverride(anchorId: string): EditResult; replaceCellContent(cellAnchorId: string, markdown: string): EditResult; readonly raw: { getXml: (anchorId: string) => string; insertXml: (anchorId: string, position: "before" | "after", xml: string) => EditResult; replaceXml: (anchorId: string, xml: string) => EditResult; }; /** * Searches the flat text of every paragraph/heading/list-item in scope for * matches of `pattern`, returning them in document order with the run * fragments each match spans. Lets callers rewrite a match in place while * preserving each fragment's formatting (bold/italic/hyperlink/etc.). * * `pattern` is a regular expression — use plain string equivalents wrapped * in `^` / `$` or pass literal text escaped via a helper. * * @see docs/architecture/docx_mutation_api.md#grep */ grep(pattern: string, options?: GrepOptions): TextMatch[]; /** * Like {@link grep}, but lets a single match span adjacent block-level * siblings (paragraphs/headings/list items) under the same parent. Block * boundaries appear in the matched text as `\n`, so `^`/`$` with the * Multiline flag anchor at boundaries and `.` won't cross unless Singleline * is set. * * Matches never cross OOXML package parts, container boundaries (body → * table cell), or non-paragraph siblings (a table between two paragraphs * breaks the run). Returned superset of {@link grep}: single-block matches * still appear with one slice. Filter `slices.length > 1` for cross-block only. * * @see docs/architecture/docx_mutation_api.md#grepcrossblock */ grepCrossBlock(pattern: string, options?: GrepOptions): CrossBlockMatch[]; /** * Finds every literal occurrence of `find` in the anchor's flat text and * replaces it with `replace`, preserving the surrounding run formatting that * the match didn't touch. Returns one `EditResult` per attempted match. * * A `find` that matches nothing fails with a single `text_not_found` result * naming the anchor and the needle — never an empty array. Pass * `expectedMatchCount: 0` to assert absence as a successful no-op instead. * * Run-formatting contract: the replacement text inherits the formatting of * the FIRST run the match spanned. Middle/trailing runs keep their `w:rPr` * but lose the slice of text the match consumed. * * @see docs/architecture/docx_mutation_api.md#replacetextrange */ replaceTextRange(anchorId: string, find: string, replace: string, options?: ReplaceOptions): EditResult[]; /** * Replaces a specific Grep match in place — addresses the exact span by * `enclosingAnchor.id` + `span.{start,length}`, so identical needles in the * same paragraph (the template-fill case where five `[___]` placeholders * each get a different value) don't collide. * * Pass `format` to replace text and format exactly the replacement atomically, with one * undo/version unit. This interactive path returns an ordinary EditResult and avoids the * package checkpoint/hash required by executeBatch's receipt. Empty replacements only delete. */ replaceMatch(match: TextMatch, replace: string, format?: FormatOp): EditResult; /** * Helper for {@link fillPlaceholders} `coalesceWhitespaceAroundEmptyFill` path — * mirrors the .NET `ReplaceMatchCoalescingNeighbors` rules. Inspects the chars * immediately surrounding the match via `match.contextBefore` / `contextAfter` * (so the option requires `contextChars >= 1`, the default) and expands the * deletion span to absorb whitespace / leading-space-before-punctuation / * matched-brackets where the patterns match. Falls back to literal-delete * when no neighbor pattern applies. * * Note: with `boundary: ContextBoundary.Bracket`, neighbor brackets are not * captured in context, so the bracket-coalesce rule won't fire on the JS side. * The .NET implementation reads flat text directly and handles that case; * callers who care should leave `boundary` at the default `Char`. */ private replaceMatchCoalescingNeighbors; /** * Replace the bracketed portion of a `TextMatch` with `newInner`, preserving any * prefix or suffix outside the brackets. Designed for `findPlaceholders` matches * like `$[___]` where the regex `\$?\[…\]` captures a leading `$`: * `replaceInner(match, "0.20")` yields `$0.20`, not `0.20`. * * Returns `MalformedMarkdown` if the match text does not contain balanced brackets. */ replaceInner(match: TextMatch, newInner: string): EditResult; /** * Picker-driven template fill. For every placeholder matching `options.kinds`, * calls `picker`; if the picker returns a non-null string, the placeholder is * replaced (with optional `$`-prefix preservation). Iterates until no more * placeholders match (or `maxPasses` is reached, or a pass makes zero changes) * — handles nested brackets that surface only after the inner ones are stripped. * * The TypeScript implementation mirrors the .NET `DocxSession.FillPlaceholders` * exactly. * * The picker is invoked synchronously by this loop on the JS side (it does * NOT run inside the WASM module). Async pickers are not supported: returning * a `Promise` will cause a `TypeError` at runtime inside the `$`-prefix * preservation branch (`Promise.startsWith is not a function`). For async * data, pre-build a lookup map before calling and have the picker read from * it synchronously. */ fillPlaceholders(picker: (p: TemplatePlaceholder) => string | null | undefined, options?: FillOptions): BulkEditResult; /** * Enumerate template placeholders in the document. Thin classifier over * {@link grep}: distinguishes `[___]` value blanks (`blank_fill`), * `[bracketed alternative clauses]` (`alternative_clause`), and * `[insert X]` / `[*italic hint*]` instructions (`instruction`). * * Combine kinds with bitwise OR: `PlaceholderKinds.BlankFill | PlaceholderKinds.Instruction`. * Default is `PlaceholderKinds.All`; default scope is body only (1). * * @see docs/architecture/docx_mutation_api.md#findplaceholders */ findPlaceholders(kinds?: number, scope?: number, contextChars?: number, boundary?: number, citation?: PageCitationRequest): TemplatePlaceholder[]; /** * Returns a snapshot of edit-state introspection signals — placeholder counts, * underscore-run leftovers, footnote/comment counts. Useful for "am I done?" * verification at the end of an edit pipeline. */ getEditSummary(): EditSummary; /** * Discoverability alias for {@link findPlaceholders}. Same return shape. */ remainingPlaceholders(kinds?: number): TemplatePlaceholder[]; /** * Diff the document's current projection against the projection captured at * session construction time. * * Requires `captureInitialProjection: true` in {@link DocxSessionSettings} * (the default). Throws if not enabled. * * The return type depends on `format`: * - `DiffFormat.Json` (default) — structured anchor-keyed `DiffEntry[]`. * - `DiffFormat.Unified` — `patch(1)`-compatible unified-diff text; * empty string when nothing has changed. * - `DiffFormat.SideBySide` — two-column human-review text * (`diff -y` style). */ getDiff(format?: typeof DiffFormat.Json): DiffEntry[]; getDiff(format: typeof DiffFormat.Unified | typeof DiffFormat.SideBySide): string; /** * Return stable semantic changes from the package opened for this session to * its current state. Requires `captureInitialProjection` (enabled by default). */ getSemanticChanges(): SemanticChangeSet; /** * Run the default deliverable gate on this session's normal clean-save checkpoint. * With initial projection capture enabled (the default), exact opening bytes are the * baseline used for dispositions and semantic/package deltas. */ verifyDeliverable(request?: DeliverableVerificationRequest): DeliverableVerificationResult; /** * Resolves an annotation's range to the block-level markdown anchors covering * it, in document order. The bridge between Docxodus' read-side annotation API * and the write-side session: an agent that wants to edit "the indemnification * clause" looks the annotation up by id and gets the anchors it can hand to * {@link replaceText} / {@link deleteBlock} / {@link raw}. Returns an empty * list when the id is unknown or its bookmark is missing. * * v1 returns the enclosing block anchors — every paragraph/heading/list-item/ * cell/row/table whose subtree overlaps the bookmark range. Filter by * `kind === "p" | "h" | "li"` when you want only text-bearing blocks. * * @see docs/architecture/docx_mutation_api.md#findbyannotation */ findByAnnotation(annotationId: string, citation?: PageCitationRequest): AnchorTargetRef[]; /** * Finds every annotation whose `labelId` matches and resolves each of their * ranges. The result is keyed by annotation id so callers can disambiguate * when the same label is applied to multiple regions (three "WARRANTY" * annotations on different paragraphs become three entries). Annotations * whose bookmark resolves to no anchors are omitted from the result. */ findByLabel(labelId: string, citation?: PageCitationRequest): Record