docxodus 5.5.4 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ // Copyright (c) Microsoft. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ import { PlaceholderKinds } from "./types.js";
4
+ /**
5
+ * Stateful in-memory DOCX editing session keyed by markdown-projection anchor ids.
6
+ * Mirror of the .NET `DocxSession` surface. See
7
+ * `docs/architecture/docx_mutation_api.md` for the surface contract,
8
+ * anchor lifecycle, error catalog, and supported markdown subset.
9
+ *
10
+ * Sessions are not eligible for JS-side garbage collection — call {@link close}
11
+ * (or use a `using` block under TypeScript 5.2+) when done.
12
+ */
13
+ export class DocxSession {
14
+ /** @internal */
15
+ constructor(handle, wasm) {
16
+ // ─── Raw escape hatch ────────────────────────────────────────────────
17
+ this.raw = {
18
+ getXml: (anchorId) => this.wasm.RawGetXml(this.handle, anchorId),
19
+ insertXml: (anchorId, position, xml) => JSON.parse(this.wasm.RawInsertXml(this.handle, anchorId, position, xml)),
20
+ replaceXml: (anchorId, xml) => JSON.parse(this.wasm.RawReplaceXml(this.handle, anchorId, xml)),
21
+ };
22
+ this.handle = handle;
23
+ this.wasm = wasm;
24
+ }
25
+ // ─── View ────────────────────────────────────────────────────────────
26
+ project() {
27
+ return JSON.parse(this.wasm.Project(this.handle));
28
+ }
29
+ // ─── Tier A: text CRUD ───────────────────────────────────────────────
30
+ replaceText(anchorId, markdown) {
31
+ return JSON.parse(this.wasm.ReplaceText(this.handle, anchorId, markdown));
32
+ }
33
+ deleteBlock(anchorId) {
34
+ return JSON.parse(this.wasm.DeleteBlock(this.handle, anchorId));
35
+ }
36
+ // ─── Tier B: structural ──────────────────────────────────────────────
37
+ insertParagraph(anchorId, position, markdown) {
38
+ return JSON.parse(this.wasm.InsertParagraph(this.handle, anchorId, position, markdown));
39
+ }
40
+ splitParagraph(anchorId, characterOffset) {
41
+ return JSON.parse(this.wasm.SplitParagraph(this.handle, anchorId, characterOffset));
42
+ }
43
+ mergeParagraphs(firstAnchorId, secondAnchorId) {
44
+ return JSON.parse(this.wasm.MergeParagraphs(this.handle, firstAnchorId, secondAnchorId));
45
+ }
46
+ // ─── Tier C: formatting ──────────────────────────────────────────────
47
+ applyFormat(anchorId, span, op) {
48
+ const spanJson = span ? JSON.stringify(span) : "";
49
+ return JSON.parse(this.wasm.ApplyFormat(this.handle, anchorId, spanJson, JSON.stringify(op)));
50
+ }
51
+ /**
52
+ * Convenience: find `substring` in the anchor's flat text and apply `op` to the
53
+ * first occurrence. Eliminates the offset-arithmetic trap from #138 — caller passes
54
+ * the visible text they want formatted, the WASM-side resolves it to a CharSpan.
55
+ */
56
+ applyFormatBySubstring(anchorId, substring, op) {
57
+ return JSON.parse(this.wasm.ApplyFormatBySubstring(this.handle, anchorId, substring, JSON.stringify(op)));
58
+ }
59
+ /**
60
+ * Convenience: apply `op` to the exact span of a {@link TextMatch} (typically from
61
+ * {@link grep}). The match's `enclosingAnchor.id` + `span` address one specific
62
+ * occurrence even when several identical needles share the same block.
63
+ */
64
+ applyFormatToMatch(match, op) {
65
+ const span = { start: match.span.start, length: match.span.length };
66
+ return this.applyFormat(match.enclosingAnchor.id, span, op);
67
+ }
68
+ setParagraphStyle(anchorId, styleId) {
69
+ return JSON.parse(this.wasm.SetParagraphStyle(this.handle, anchorId, styleId));
70
+ }
71
+ setListLevel(anchorId, levelDelta) {
72
+ return JSON.parse(this.wasm.SetListLevel(this.handle, anchorId, levelDelta));
73
+ }
74
+ removeListMembership(anchorId) {
75
+ return JSON.parse(this.wasm.RemoveListMembership(this.handle, anchorId));
76
+ }
77
+ // ─── Tier D: cell content ────────────────────────────────────────────
78
+ replaceCellContent(cellAnchorId, markdown) {
79
+ return JSON.parse(this.wasm.ReplaceCellContent(this.handle, cellAnchorId, markdown));
80
+ }
81
+ // ─── Search ──────────────────────────────────────────────────────────
82
+ /**
83
+ * Searches the flat text of every paragraph/heading/list-item in scope for
84
+ * matches of `pattern`, returning them in document order with the run
85
+ * fragments each match spans. Lets callers rewrite a match in place while
86
+ * preserving each fragment's formatting (bold/italic/hyperlink/etc.).
87
+ *
88
+ * `pattern` is a regular expression — use plain string equivalents wrapped
89
+ * in `^` / `$` or pass literal text escaped via a helper.
90
+ *
91
+ * @see docs/architecture/docx_mutation_api.md#grep
92
+ */
93
+ grep(pattern, options) {
94
+ return JSON.parse(this.wasm.Grep(this.handle, pattern, options ? JSON.stringify(options) : ""));
95
+ }
96
+ /**
97
+ * Like {@link grep}, but lets a single match span adjacent block-level
98
+ * siblings (paragraphs/headings/list items) under the same parent. Block
99
+ * boundaries appear in the matched text as `\n`, so `^`/`$` with the
100
+ * Multiline flag anchor at boundaries and `.` won't cross unless Singleline
101
+ * is set.
102
+ *
103
+ * Matches never cross OOXML package parts, container boundaries (body →
104
+ * table cell), or non-paragraph siblings (a table between two paragraphs
105
+ * breaks the run). Returned superset of {@link grep}: single-block matches
106
+ * still appear with one slice. Filter `slices.length > 1` for cross-block only.
107
+ *
108
+ * @see docs/architecture/docx_mutation_api.md#grepcrossblock
109
+ */
110
+ grepCrossBlock(pattern, options) {
111
+ return JSON.parse(this.wasm.GrepCrossBlock(this.handle, pattern, options ? JSON.stringify(options) : ""));
112
+ }
113
+ /**
114
+ * Finds every literal occurrence of `find` in the anchor's flat text and
115
+ * replaces it with `replace`, preserving the surrounding run formatting that
116
+ * the match didn't touch. Returns one `EditResult` per attempted match.
117
+ *
118
+ * Run-formatting contract: the replacement text inherits the formatting of
119
+ * the FIRST run the match spanned. Middle/trailing runs keep their `w:rPr`
120
+ * but lose the slice of text the match consumed.
121
+ *
122
+ * @see docs/architecture/docx_mutation_api.md#replacetextrange
123
+ */
124
+ replaceTextRange(anchorId, find, replace, options) {
125
+ return JSON.parse(this.wasm.ReplaceTextRange(this.handle, anchorId, find, replace, options ? JSON.stringify(options) : ""));
126
+ }
127
+ /**
128
+ * Replaces a specific Grep match in place — addresses the exact span by
129
+ * `enclosingAnchor.id` + `span.{start,length}`, so identical needles in the
130
+ * same paragraph (the template-fill case where five `[___]` placeholders
131
+ * each get a different value) don't collide.
132
+ */
133
+ replaceMatch(match, replace) {
134
+ return JSON.parse(this.wasm.ReplaceTextAtSpan(this.handle, match.enclosingAnchor.id, match.span.start, match.span.length, replace));
135
+ }
136
+ /**
137
+ * Enumerate template placeholders in the document. Thin classifier over
138
+ * {@link grep}: distinguishes `[___]` value blanks (`blank_fill`),
139
+ * `[bracketed alternative clauses]` (`alternative_clause`), and
140
+ * `[insert X]` / `[*italic hint*]` instructions (`instruction`).
141
+ *
142
+ * Combine kinds with bitwise OR: `PlaceholderKinds.BlankFill | PlaceholderKinds.Instruction`.
143
+ * Default is `PlaceholderKinds.All`; default scope is body only (1).
144
+ *
145
+ * @see docs/architecture/docx_mutation_api.md#findplaceholders
146
+ */
147
+ findPlaceholders(kinds = PlaceholderKinds.All, scope = 1) {
148
+ return JSON.parse(this.wasm.FindPlaceholders(this.handle, kinds, scope));
149
+ }
150
+ // ─── Annotation-based anchor discovery (#132) ────────────────────────
151
+ /**
152
+ * Resolves an annotation's range to the block-level markdown anchors covering
153
+ * it, in document order. The bridge between Docxodus' read-side annotation API
154
+ * and the write-side session: an agent that wants to edit "the indemnification
155
+ * clause" looks the annotation up by id and gets the anchors it can hand to
156
+ * {@link replaceText} / {@link deleteBlock} / {@link raw}. Returns an empty
157
+ * list when the id is unknown or its bookmark is missing.
158
+ *
159
+ * v1 returns the enclosing block anchors — every paragraph/heading/list-item/
160
+ * cell/row/table whose subtree overlaps the bookmark range. Filter by
161
+ * `kind === "p" | "h" | "li"` when you want only text-bearing blocks.
162
+ *
163
+ * @see docs/architecture/docx_mutation_api.md#findbyannotation
164
+ */
165
+ findByAnnotation(annotationId) {
166
+ return JSON.parse(this.wasm.FindByAnnotation(this.handle, annotationId));
167
+ }
168
+ /**
169
+ * Finds every annotation whose `labelId` matches and resolves each of their
170
+ * ranges. The result is keyed by annotation id so callers can disambiguate
171
+ * when the same label is applied to multiple regions (three "WARRANTY"
172
+ * annotations on different paragraphs become three entries). Annotations
173
+ * whose bookmark resolves to no anchors are omitted from the result.
174
+ */
175
+ findByLabel(labelId) {
176
+ return JSON.parse(this.wasm.FindByLabel(this.handle, labelId));
177
+ }
178
+ /**
179
+ * Resolves any bookmark in the main document part (Docxodus-managed or
180
+ * user-authored) to the block-level anchors covering its range, in document
181
+ * order. Empty when the bookmark name is unknown. Use this for raw bookmark
182
+ * names that didn't come from the annotation system.
183
+ */
184
+ findByBookmark(bookmarkName) {
185
+ return JSON.parse(this.wasm.FindByBookmark(this.handle, bookmarkName));
186
+ }
187
+ /**
188
+ * Enumerates every annotation persisted in the document. Lets an agent prime
189
+ * itself with "here are the labeled regions you can target" before committing
190
+ * to a specific id.
191
+ */
192
+ listAnnotations() {
193
+ return JSON.parse(this.wasm.ListAnnotations(this.handle));
194
+ }
195
+ // ─── Lifecycle ───────────────────────────────────────────────────────
196
+ undo() {
197
+ return this.wasm.Undo(this.handle);
198
+ }
199
+ redo() {
200
+ return this.wasm.Redo(this.handle);
201
+ }
202
+ save() {
203
+ return this.wasm.Save(this.handle);
204
+ }
205
+ close() {
206
+ this.wasm.CloseSession(this.handle);
207
+ }
208
+ // TypeScript 5.2+ disposable protocol
209
+ [Symbol.dispose]() {
210
+ this.close();
211
+ }
212
+ }
213
+ /**
214
+ * Opens a new {@link DocxSession} over the supplied DOCX bytes.
215
+ * The returned session holds its document in WASM memory until you call
216
+ * {@link DocxSession.close} (or it is disposed).
217
+ */
218
+ export function openDocxSession(bytes, wasmExports, settings) {
219
+ const bridge = wasmExports.DocxSessionBridge;
220
+ const handle = bridge.OpenSession(bytes, settings ? JSON.stringify(settings) : "");
221
+ return new DocxSession(handle, bridge);
222
+ }
223
+ export { PlaceholderKinds } from "./types.js";
224
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,3 +1,96 @@
1
+ /**
2
+ * Which parts of the OOXML package to include in the markdown projection.
3
+ * Bitflags mirroring the .NET `Docxodus.ProjectionScopes` enum.
4
+ */
5
+ export declare enum ProjectionScopes {
6
+ Body = 1,
7
+ Headers = 2,
8
+ Footers = 4,
9
+ Footnotes = 8,
10
+ Endnotes = 16,
11
+ Comments = 32,
12
+ All = 63
13
+ }
14
+ /**
15
+ * How anchor markers are rendered in the markdown projection.
16
+ * Mirrors the .NET `Docxodus.AnchorRenderMode` enum.
17
+ */
18
+ export declare enum AnchorRenderMode {
19
+ /** Anchor appears on its own line before each block element (default). */
20
+ Block = 0,
21
+ /** Block anchors plus inline `{#…}` markers for spans (comments, hyperlinks). */
22
+ BlockAndInline = 1,
23
+ /** No anchor markers in the output (projection only, no addressing). */
24
+ None = 2
25
+ }
26
+ /**
27
+ * Strategy for rendering `w:tbl` elements that don't fit GFM pipe-table constraints.
28
+ * Mirrors the .NET `Docxodus.TableRenderMode` enum.
29
+ */
30
+ export declare enum TableRenderMode {
31
+ /** Emit GFM pipe tables when possible, opaque anchor blocks otherwise (default). */
32
+ GfmWithOpaqueFallback = 0,
33
+ /** Always emit GFM pipe tables, flattening complex structure with possible loss. */
34
+ AlwaysGfm = 1,
35
+ /** Always emit opaque anchor blocks. */
36
+ AlwaysOpaque = 2
37
+ }
38
+ /**
39
+ * How tracked changes are handled in the markdown projection.
40
+ * Mirrors the .NET `Docxodus.TrackedChangeMode` enum.
41
+ */
42
+ export declare enum TrackedChangeMode {
43
+ /** Accept all revisions before conversion (default). */
44
+ Accept = 0,
45
+ /** Render insertions and deletions inline as `{+ins+}` / `{-del-}`. */
46
+ RenderInline = 1,
47
+ /** Accept insertions, drop deletions. */
48
+ StripDeletions = 2
49
+ }
50
+ /**
51
+ * How empty paragraphs are rendered. Mirrors the .NET `Docxodus.EmptyParagraphMode` enum.
52
+ */
53
+ export declare enum EmptyParagraphMode {
54
+ /** Default: emit the anchor on its own line (`{#p:body:UNID}\n`). */
55
+ AnchorOnly = 0,
56
+ /** Tag the empty paragraph visibly so agents can pattern-match (`{#p:body:UNID} ∅`). */
57
+ MarkedEmpty = 1,
58
+ /** Skip empty paragraphs entirely — they don't appear in the markdown or the anchor index. */
59
+ Suppress = 2
60
+ }
61
+ /**
62
+ * Settings controlling the markdown projection. Mirrors the .NET
63
+ * `WmlToMarkdownConverterSettings` class — see `docs/architecture/markdown_projection.md`.
64
+ */
65
+ export interface MarkdownProjectionSettings {
66
+ scopes?: ProjectionScopes;
67
+ headingLevelOffset?: number;
68
+ anchorMode?: AnchorRenderMode;
69
+ tableMode?: TableRenderMode;
70
+ tableInlineCellMax?: number;
71
+ trackedChanges?: TrackedChangeMode;
72
+ resolveNumbering?: boolean;
73
+ emptyParagraphs?: EmptyParagraphMode;
74
+ }
75
+ /**
76
+ * Resolved location of an anchor in the underlying OOXML package — sufficient to walk
77
+ * back to the source element via the .NET API.
78
+ */
79
+ export interface MarkdownAnchorTarget {
80
+ id: string;
81
+ kind: string;
82
+ scope: string;
83
+ unid: string;
84
+ partUri: string;
85
+ }
86
+ /**
87
+ * Output of the markdown projection: rendered text plus the anchor index mapping
88
+ * each `{#…}` token back to a location in the OOXML package.
89
+ */
90
+ export interface MarkdownProjection {
91
+ markdown: string;
92
+ anchorIndex: Record<string, MarkdownAnchorTarget>;
93
+ }
1
94
  /**
2
95
  * Revision type enum matching the .NET WmlComparerRevisionType
3
96
  */
@@ -351,6 +444,7 @@ export interface DocxodusWasmExports {
351
444
  GetDocumentStructure: (bytes: Uint8Array) => string;
352
445
  GetDocumentMetadata: (bytes: Uint8Array) => string;
353
446
  ExportToOpenContract: (bytes: Uint8Array) => string;
447
+ ConvertWmlToMarkdown: (bytes: Uint8Array, settingsJson: string) => string;
354
448
  GetVersion: () => string;
355
449
  ConvertDocxToHtmlProfiled: (bytes: Uint8Array) => string;
356
450
  ProfileConversionDetailed: (bytes: Uint8Array) => string;
@@ -376,6 +470,264 @@ export interface DocxodusWasmExports {
376
470
  CompareDocumentsWithLog: (originalBytes: Uint8Array, modifiedBytes: Uint8Array, authorName: string, detailThreshold: number, caseInsensitive: boolean) => string;
377
471
  CompareDocumentsToHtmlWithLog: (originalBytes: Uint8Array, modifiedBytes: Uint8Array, authorName: string, detailThreshold: number, caseInsensitive: boolean, renderTrackedChanges: boolean) => string;
378
472
  };
473
+ DocxSessionBridge: {
474
+ OpenSession: (bytes: Uint8Array, settingsJson: string) => number;
475
+ CloseSession: (handle: number) => void;
476
+ Project: (handle: number) => string;
477
+ ReplaceText: (handle: number, anchor: string, md: string) => string;
478
+ DeleteBlock: (handle: number, anchor: string) => string;
479
+ InsertParagraph: (handle: number, anchor: string, pos: string, md: string) => string;
480
+ SplitParagraph: (handle: number, anchor: string, offset: number) => string;
481
+ MergeParagraphs: (handle: number, first: string, second: string) => string;
482
+ ApplyFormat: (handle: number, anchor: string, spanJson: string, opJson: string) => string;
483
+ ApplyFormatBySubstring: (handle: number, anchor: string, substring: string, opJson: string) => string;
484
+ SetParagraphStyle: (handle: number, anchor: string, styleId: string) => string;
485
+ SetListLevel: (handle: number, anchor: string, delta: number) => string;
486
+ RemoveListMembership: (handle: number, anchor: string) => string;
487
+ ReplaceCellContent: (handle: number, anchor: string, md: string) => string;
488
+ RawGetXml: (handle: number, anchor: string) => string;
489
+ RawInsertXml: (handle: number, anchor: string, pos: string, xml: string) => string;
490
+ RawReplaceXml: (handle: number, anchor: string, xml: string) => string;
491
+ Grep: (handle: number, pattern: string, optionsJson: string) => string;
492
+ GrepCrossBlock: (handle: number, pattern: string, optionsJson: string) => string;
493
+ ReplaceTextRange: (handle: number, anchor: string, find: string, replace: string, optionsJson: string) => string;
494
+ ReplaceTextAtSpan: (handle: number, anchor: string, spanStart: number, spanLength: number, replace: string) => string;
495
+ FindPlaceholders: (handle: number, kinds: number, scope: number) => string;
496
+ FindByAnnotation: (handle: number, annotationId: string) => string;
497
+ FindByLabel: (handle: number, labelId: string) => string;
498
+ FindByBookmark: (handle: number, bookmarkName: string) => string;
499
+ ListAnnotations: (handle: number) => string;
500
+ Undo: (handle: number) => boolean;
501
+ Redo: (handle: number) => boolean;
502
+ Save: (handle: number) => Uint8Array;
503
+ };
504
+ }
505
+ export type EditErrorCode = "anchor_not_found" | "anchor_wrong_kind" | "anchors_not_adjacent" | "session_disposed" | "malformed_markdown" | "unsupported_markdown_syntax" | "table_insert_not_supported" | "footnote_ref_not_supported" | "comment_marker_not_supported" | "image_insert_not_supported" | "anchor_token_in_payload" | "offset_out_of_range" | "invalid_position" | "unknown_style" | "invalid_list_level" | "malformed_xml" | "disallowed_namespace" | "incompatible_element_type" | "validation_failed" | "nothing_to_undo" | "nothing_to_redo" | "internal_error";
506
+ export interface AnchorRef {
507
+ id: string;
508
+ kind: string;
509
+ scope: string;
510
+ unid: string;
511
+ }
512
+ export interface EditError {
513
+ code: EditErrorCode;
514
+ message: string;
515
+ anchorId?: string;
516
+ }
517
+ export interface MarkdownPatch {
518
+ scopeAnchorId: string;
519
+ markdown: string;
520
+ }
521
+ export interface EditResult {
522
+ success: boolean;
523
+ error?: EditError;
524
+ created: AnchorRef[];
525
+ removed: AnchorRef[];
526
+ modified: AnchorRef[];
527
+ patch?: MarkdownPatch;
528
+ }
529
+ export interface CharSpan {
530
+ start: number;
531
+ length: number;
532
+ }
533
+ export interface FormatOp {
534
+ bold?: boolean;
535
+ italic?: boolean;
536
+ underline?: boolean;
537
+ strike?: boolean;
538
+ code?: boolean;
539
+ color?: string;
540
+ runStyle?: string;
541
+ }
542
+ export interface DocxSessionSettings {
543
+ undoDepth?: number;
544
+ validateRawOps?: boolean;
545
+ trackedChanges?: "accept" | "render_inline" | "strip_deletions";
546
+ revisionAuthor?: string;
547
+ /**
548
+ * When false (default), `save()` strips the projector's internal `PtOpenXml:Unid`
549
+ * attributes before serializing — they aren't OOXML schema, and persisting them
550
+ * bloats large documents significantly (~700 KB on a 100-page DOCX). Set to true
551
+ * only when anchor ids must survive a save/reopen round trip.
552
+ */
553
+ persistAnchorIds?: boolean;
554
+ /**
555
+ * When true, ReplaceText / ReplaceTextRange / ReplaceMatch payloads have ASCII
556
+ * `"` and `'` converted to typographic curly quotes (`“ ” ‘ ’`) based on
557
+ * context — open at start / after whitespace / after open-bracket, close
558
+ * elsewhere. Avoids the cosmetic regression where a replacement lands as
559
+ * straight-quoted text adjacent to surrounding already-curly text. Default false.
560
+ */
561
+ smartQuotes?: boolean;
562
+ }
563
+ export interface DocxSessionProjection {
564
+ markdown: string;
565
+ anchorIndex: Record<string, {
566
+ partUri: string;
567
+ unid: string;
568
+ kind: string;
569
+ scope: string;
570
+ }>;
571
+ }
572
+ /**
573
+ * Per-fragment visible formatting reported by {@link DocxSession.grep}.
574
+ */
575
+ export interface RunFormatting {
576
+ bold: boolean;
577
+ italic: boolean;
578
+ underline: boolean;
579
+ strike: boolean;
580
+ code: boolean;
581
+ color?: string;
582
+ hyperlinkUrl?: string;
583
+ runStyle?: string;
584
+ }
585
+ /**
586
+ * One piece of a {@link TextMatch} that came from a single `<w:r>` run.
587
+ */
588
+ export interface RunFragment {
589
+ /** PtOpenXml:Unid of the `w:r` element this fragment came from. */
590
+ unid: string;
591
+ /** The text from this run that participates in the match. */
592
+ text: string;
593
+ /** Character offset + length of this fragment inside the run's flat text. */
594
+ spanInElement: CharSpan;
595
+ /** Visible formatting of the run this fragment came from. */
596
+ formatting: RunFormatting;
597
+ }
598
+ /**
599
+ * A single match returned by {@link DocxSession.grep}. The match always lives
600
+ * within one block-level element.
601
+ */
602
+ export interface TextMatch {
603
+ text: string;
604
+ enclosingAnchor: AnchorRef;
605
+ span: CharSpan;
606
+ fragments: RunFragment[];
607
+ contextBefore: string;
608
+ contextAfter: string;
609
+ /** Regex capture groups; index 0 is always the whole match. */
610
+ groups: string[];
611
+ }
612
+ /**
613
+ * One block's contribution to a {@link CrossBlockMatch}. The slice's `fragments`
614
+ * list is empty when the match touches an empty paragraph — the slice is still
615
+ * recorded so callers can see the match crossed the empty block.
616
+ */
617
+ export interface BlockSlice {
618
+ anchor: AnchorRef;
619
+ /** Character offset + length of the slice within the block's own flat text. */
620
+ spanInBlock: CharSpan;
621
+ /** Run fragments contributing to this slice, in document order. */
622
+ fragments: RunFragment[];
623
+ }
624
+ /**
625
+ * A single match returned by {@link DocxSession.grepCrossBlock}. The match may
626
+ * span multiple adjacent block-level elements (paragraphs/headings/list items)
627
+ * under the same parent container. `slices` is the per-block breakdown;
628
+ * `enclosingAnchors` lists every block the match touches, in document order.
629
+ *
630
+ * Block boundaries appear in `text` / `contextBefore` / `contextAfter` as
631
+ * single `\n` characters.
632
+ */
633
+ export interface CrossBlockMatch {
634
+ text: string;
635
+ enclosingAnchors: AnchorRef[];
636
+ slices: BlockSlice[];
637
+ contextBefore: string;
638
+ contextAfter: string;
639
+ /** Regex capture groups; index 0 is always the whole match. */
640
+ groups: string[];
641
+ }
642
+ /**
643
+ * Options for {@link DocxSession.replaceTextRange}.
644
+ */
645
+ export interface ReplaceOptions {
646
+ /** Case-insensitive matching for the literal `find` needle. */
647
+ ignoreCase?: boolean;
648
+ /** Cap the number of replacements; omitted = unlimited. */
649
+ maxReplacements?: number;
650
+ }
651
+ /**
652
+ * Categories of bracketed placeholders {@link DocxSession.findPlaceholders} recognizes.
653
+ *
654
+ * - `blank_fill` — `[___]` or `$[___]` value slots
655
+ * - `alternative_clause` — `[entire clause text]`
656
+ * - `instruction` — `[insert X]`, `[specify Y]`, `[*italicized hint*]`
657
+ */
658
+ export type PlaceholderKind = "blank_fill" | "alternative_clause" | "instruction";
659
+ /**
660
+ * Numeric flag layout matching the .NET `PlaceholderKinds` enum. Combine with bitwise OR.
661
+ */
662
+ export declare const PlaceholderKinds: {
663
+ readonly BlankFill: 1;
664
+ readonly AlternativeClause: 2;
665
+ readonly Instruction: 4;
666
+ readonly All: 7;
667
+ };
668
+ export interface TemplatePlaceholder {
669
+ kind: PlaceholderKind;
670
+ /** For `instruction` placeholders: the inner text with surrounding brackets/asterisks stripped. */
671
+ hint?: string;
672
+ match: TextMatch;
673
+ }
674
+ /**
675
+ * Options for {@link DocxSession.grep}.
676
+ *
677
+ * `regexOptions` and `scope` use the numeric flag layouts of the .NET
678
+ * `System.Text.RegularExpressions.RegexOptions` and `ProjectionScopes` enums.
679
+ * Common values:
680
+ * - `RegexOptions.IgnoreCase = 1`
681
+ * - `RegexOptions.Multiline = 2`
682
+ * - `ProjectionScopes.Body = 1`, `Headers = 2`, `Footers = 4`,
683
+ * `Footnotes = 8`, `Endnotes = 16`, `Comments = 32`, `All = 63`.
684
+ */
685
+ export interface GrepOptions {
686
+ regexOptions?: number;
687
+ scope?: number;
688
+ contextChars?: number;
689
+ /**
690
+ * Whitespace handling. Numeric layout matching the .NET `WhitespaceMode` enum:
691
+ * - 0 = Preserve (default; match against the document's original characters)
692
+ * - 1 = Normalize (fold NBSP / narrow-NBSP / thin-space to ASCII space before matching)
693
+ */
694
+ whitespace?: number;
695
+ }
696
+ /**
697
+ * Resolved location of an anchor — what {@link DocxSession.findByAnnotation} and
698
+ * the other discovery helpers return. The shape is {@link AnchorRef} plus the
699
+ * `partUri` of the package part the element lives in (useful for callers that
700
+ * walk the underlying OOXML directly).
701
+ */
702
+ export interface AnchorTargetRef extends AnchorRef {
703
+ partUri: string;
704
+ }
705
+ /**
706
+ * A custom annotation persisted in the document via Docxodus' annotation system.
707
+ * Returned by {@link DocxSession.listAnnotations}; mirrors the wire-relevant
708
+ * fields of the .NET `DocumentAnnotation` type. Stale page caches and arbitrary
709
+ * metadata are omitted to keep the JSON payload compact — callers that need them
710
+ * can use the .NET API directly.
711
+ *
712
+ * See `docs/architecture/custom_annotations.md` for the persistence design.
713
+ */
714
+ export interface DocumentAnnotation {
715
+ /** Unique annotation identifier (caller-supplied at add time). */
716
+ id: string;
717
+ /** Label category/type (e.g. `"INDEMNIFICATION"`, `"CLAUSE_TYPE_A"`). */
718
+ labelId: string;
719
+ /** Human-readable label text displayed in the UI. */
720
+ label: string;
721
+ /** Highlight color in hex (e.g. `"#FFEB3B"`). */
722
+ color: string;
723
+ /** Internal bookmark name in the DOCX (`_Docxodus_Ann_{id}` for managed annotations). */
724
+ bookmarkName: string;
725
+ /** Author who created the annotation, if recorded. */
726
+ author?: string;
727
+ /** Creation timestamp in ISO-8601 (round-trip) format, if recorded. */
728
+ created?: string;
729
+ /** The text content covered by the annotation's bookmark, populated when reading. */
730
+ annotatedText?: string;
379
731
  }
380
732
  /**
381
733
  * Severity level for comparison log entries.