@docx-editor.dev/core 2.19.1 → 2.21.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.
Files changed (116) hide show
  1. package/README.md +11 -32
  2. package/dist/automation.cjs +1 -1
  3. package/dist/automation.d.ts +11 -9
  4. package/dist/automation.js +1 -1
  5. package/dist/binding.cjs +1 -1
  6. package/dist/binding.d.ts +9 -10
  7. package/dist/binding.js +1 -1
  8. package/dist/chunk-44LQJIKH.cjs +20 -0
  9. package/dist/chunk-4EHMMSFR.cjs +1 -0
  10. package/dist/chunk-AFG7Q622.cjs +2 -0
  11. package/dist/chunk-AJCCS53D.js +1 -0
  12. package/dist/chunk-AYMSP25Q.js +4 -0
  13. package/dist/{chunk-GWW5FOLJ.cjs → chunk-B4KZSKF7.cjs} +5 -5
  14. package/dist/chunk-BDAY2ETZ.js +1 -0
  15. package/dist/chunk-BNZF6DYC.cjs +18 -0
  16. package/dist/chunk-BQXF2PFF.js +2 -0
  17. package/dist/chunk-GIHKVXEO.js +2 -0
  18. package/dist/chunk-ITNK6C5M.cjs +3 -0
  19. package/dist/chunk-MP3K4LC5.js +1 -0
  20. package/dist/chunk-MXOO7KRI.cjs +11 -0
  21. package/dist/chunk-NG6IQ4SI.js +11 -0
  22. package/dist/{chunk-NIVIC7PA.cjs → chunk-PYXMAUNR.cjs} +1 -1
  23. package/dist/chunk-Q2B6HX3R.js +1 -0
  24. package/dist/chunk-Q5JPPUNR.js +5 -0
  25. package/dist/chunk-S35UK656.cjs +2 -0
  26. package/dist/chunk-S6J4O5XP.js +1 -0
  27. package/dist/chunk-TE43S3LX.cjs +1 -0
  28. package/dist/chunk-TKQH7BNE.cjs +1 -0
  29. package/dist/chunk-UKVVUHZL.cjs +1 -0
  30. package/dist/chunk-VH2DLEZK.js +20 -0
  31. package/dist/{chunk-BUNY5MRX.js → chunk-VUNFWXHF.js} +1 -1
  32. package/dist/{chunk-JWHXOJEU.cjs → chunk-WQFNWLNY.cjs} +3 -3
  33. package/dist/chunk-WZX4UGRQ.js +3 -0
  34. package/dist/{chunk-2QU7QTM7.js → chunk-X5QNSISI.js} +1 -1
  35. package/dist/chunk-XS4FOHH6.js +18 -0
  36. package/dist/{chunk-7VO6BLKV.cjs → chunk-XZY4Q6PJ.cjs} +1 -1
  37. package/dist/{chunk-76F73CY6.cjs → chunk-Z2ETEZRU.cjs} +1 -1
  38. package/dist/collaboration/replication.cjs +1 -1
  39. package/dist/collaboration/replication.d.ts +13 -4
  40. package/dist/collaboration/replication.js +1 -1
  41. package/dist/collaboration.d.ts +4 -3
  42. package/dist/contracts/document.d.ts +3 -2
  43. package/dist/contracts/editor.cjs +1 -1
  44. package/dist/contracts/editor.d.ts +9 -10
  45. package/dist/contracts/editor.js +1 -1
  46. package/dist/contracts/interaction.d.ts +2 -2
  47. package/dist/contracts/modules.cjs +1 -1
  48. package/dist/contracts/modules.d.ts +9 -9
  49. package/dist/contracts/modules.js +1 -1
  50. package/dist/contracts/types.d.ts +2 -562
  51. package/dist/{custom-node-writes-BqIv94ei.d.ts → custom-node-writes-05qS32px.d.ts} +2 -2
  52. package/dist/{document-protection-BL5zp8cU.d.ts → document-protection-Cr59VKLO.d.ts} +1 -1
  53. package/dist/{editor-WXbTSXx1.d.ts → editor-BsLSz_7y.d.ts} +43 -39
  54. package/dist/editor-scope-OHPwVQ5l.d.ts +84 -0
  55. package/dist/editor.cjs +1 -1
  56. package/dist/editor.css +1 -1
  57. package/dist/editor.d.ts +130 -29
  58. package/dist/editor.js +1 -1
  59. package/dist/export.cjs +2 -2
  60. package/dist/export.d.ts +13 -14
  61. package/dist/export.js +1 -1
  62. package/dist/{font-resolver-BSrKnTeR.d.ts → font-resolver-CzwdBJDE.d.ts} +1 -1
  63. package/dist/{headless-document-view-C4ttQJ5H.d.ts → headless-document-view-B7nAiR7P.d.ts} +2 -2
  64. package/dist/image-resources-C4ilLzog.d.ts +210 -0
  65. package/dist/{index-C3As-Xxp.d.ts → index-zkvqBQ9o.d.ts} +117 -27
  66. package/dist/index.cjs +1 -1
  67. package/dist/index.d.ts +18 -19
  68. package/dist/index.js +1 -1
  69. package/dist/{layout-shaping-Dqu3JW3p.d.ts → layout-shaping-BJKVTI6i.d.ts} +1 -1
  70. package/dist/layout.cjs +1 -1
  71. package/dist/layout.d.ts +72 -20
  72. package/dist/layout.js +1 -1
  73. package/dist/{note-properties-RjYgbmXe.d.ts → note-properties-MNztEj5s.d.ts} +2 -2
  74. package/dist/{omml-equation-hcP9AUFX.d.ts → omml-equation-CbnW9yXd.d.ts} +1 -1
  75. package/dist/output.cjs +1 -1
  76. package/dist/output.d.ts +8 -7
  77. package/dist/output.js +1 -1
  78. package/dist/{protocol-OdRd17KZ.d.ts → protocol-Co_r0SZQ.d.ts} +14 -4
  79. package/dist/{review-paragraph-order--jLHXIcd.d.ts → review-paragraph-order-EFaU7TqH.d.ts} +2 -3
  80. package/dist/{revision-projection-BIHO_qvw.d.ts → revision-projection-DEIvpxiq.d.ts} +16 -2
  81. package/dist/{semantic-cell-selection-lCYAVCCF.d.ts → semantic-cell-selection-DXmfnDCw.d.ts} +9 -4
  82. package/dist/{semantic-interaction-0vQXcMZk.d.ts → semantic-interaction-BLu3M6Nn.d.ts} +1 -1
  83. package/dist/{semantic-paint-BSan4pBk.d.ts → semantic-paint-CPsihA6k.d.ts} +18 -2
  84. package/dist/{semantic-records-ZcYuB4-H.d.ts → semantic-records-CqD0b5Ex.d.ts} +147 -6
  85. package/dist/store.cjs +1 -1
  86. package/dist/store.d.ts +462 -428
  87. package/dist/store.js +1 -1
  88. package/dist/{tree-package-fragment-1pdDnhZ_.d.ts → tree-package-fragment-CwJDixNs.d.ts} +44 -3
  89. package/dist/{tree-session-contract-Cgn6fQ-M.d.ts → tree-session-contract-D9RRWE0C.d.ts} +8 -8
  90. package/dist/{tree-op-types-DbdM7fJV.d.ts → types-barrel-DLB11iSY.d.ts} +1455 -660
  91. package/package.json +2 -2
  92. package/dist/chunk-3JKOZBQ3.cjs +0 -1
  93. package/dist/chunk-3SU7UWCR.js +0 -1
  94. package/dist/chunk-5BI4SIHO.cjs +0 -1
  95. package/dist/chunk-6ESSCMXL.js +0 -2
  96. package/dist/chunk-6W4DIR4X.cjs +0 -2
  97. package/dist/chunk-AKQRKR2H.js +0 -1
  98. package/dist/chunk-BJQDNKEX.js +0 -5
  99. package/dist/chunk-D5EHDHYV.js +0 -1
  100. package/dist/chunk-FBWBSHC4.cjs +0 -11
  101. package/dist/chunk-GOEBQ26R.js +0 -1
  102. package/dist/chunk-IA7WTZHI.js +0 -11
  103. package/dist/chunk-IXGUCLER.js +0 -20
  104. package/dist/chunk-NDPLQG4Y.cjs +0 -18
  105. package/dist/chunk-NLGUL6QL.js +0 -3
  106. package/dist/chunk-OHJQ7GPZ.cjs +0 -1
  107. package/dist/chunk-OWUSDS3L.cjs +0 -20
  108. package/dist/chunk-RDKPMNN6.cjs +0 -2
  109. package/dist/chunk-TSDGKNV7.js +0 -2
  110. package/dist/chunk-TUCDPXBD.js +0 -18
  111. package/dist/chunk-UOE4WKL7.js +0 -1
  112. package/dist/chunk-VSCPFHTD.cjs +0 -3
  113. package/dist/chunk-ZKWRCLT2.cjs +0 -1
  114. package/dist/chunk-ZUGTEKLM.js +0 -4
  115. package/dist/editor-scope-DZJT4ukT.d.ts +0 -53
  116. package/dist/review-items-CJz-kAW8.d.ts +0 -370
@@ -1,281 +1,4 @@
1
- import { ParagraphTabStop } from './contracts/types.js';
2
-
3
- /**
4
- * The engine's trust-boundary caps: recursion depth, element counts, and the rest.
5
- *
6
- * A caller may LOWER any of these but never raise or disable one — an override of `Infinity`,
7
- * zero, a negative or `NaN` clamps into `(0, ceiling]` rather than turning the limit off. These
8
- * are security ceilings, not performance budgets.
9
- */
10
- interface ResourceLimits {
11
- /** Max nested-structure recursion (tables/shapes/SDT/groups). */
12
- readonly maxRecursionDepth: number;
13
- /** Max total parsed element count. */
14
- readonly maxElementCount: number;
15
- /** Max package part count. */
16
- readonly maxPartCount: number;
17
- /** Max total decompressed bytes (zip-bomb guard). */
18
- readonly maxDecompressedBytes: number;
19
- /** Max total compressed input bytes. */
20
- readonly maxCompressedBytes: number;
21
- /** Max decompressed:compressed ratio per entry. */
22
- readonly maxCompressionRatio: number;
23
- /** In-memory chunk budget for streaming/spooling. */
24
- readonly maxChunkBytes: number;
25
- /** Max pagination passes before non-convergence is declared. */
26
- readonly maxPaginationPasses: number;
27
- /** Max queued items in any bounded work queue. */
28
- readonly maxQueueDepth: number;
29
- }
30
- /** Non-disableable hard ceilings: no resolved limit may exceed these. */
31
- declare const HARD_CEILINGS: ResourceLimits;
32
- /** Finite defaults, all <= their hard ceiling. */
33
- declare const DEFAULT_LIMITS: ResourceLimits;
34
- /**
35
- * Resolve caller overrides into a frozen, always-finite limit set. Each value is
36
- * `min(override>0 ? override : default, ceiling)`. Infinity/0/negative/NaN can
37
- * never disable a limit — the hard ceiling always wins.
38
- */
39
- declare function resolveLimits(overrides?: Partial<ResourceLimits>): ResourceLimits;
40
- /** Bounded image decode limits (typed-drawings-and-images task 4). */
41
- /** Trust-boundary caps specific to image decoding and embedding. */
42
- interface ImageResourceLimits {
43
- readonly maxEncodedBytes: number;
44
- readonly maxDecodedBytes: number;
45
- readonly maxPixels: number;
46
- readonly maxDimension: number;
47
- readonly maxPolygonPoints: number;
48
- readonly maxExternalRedirects: number;
49
- }
50
- /** Image caps nothing can raise past. A caller's override clamps into these. */
51
- declare const IMAGE_RESOURCE_HARD_CEILINGS: ImageResourceLimits;
52
- /** The image caps in force when a host configures none. Conservative and finite. */
53
- declare const DEFAULT_IMAGE_RESOURCE_LIMITS: ImageResourceLimits;
54
- /** Resolve caller overrides into frozen image limits; hard ceilings cannot be raised. */
55
- declare function resolveImageResourceLimits(overrides?: Partial<ImageResourceLimits>): ImageResourceLimits;
56
-
57
- /**
58
- * Why a part or relationship name was refused.
59
- *
60
- * Path traversal is the reason this exists: a name with `..` or a leading `/` is refused rather
61
- * than normalized, because normalizing is how a crafted package reaches outside itself.
62
- */
63
- type NameRejection = 'empty' | 'control-char' | 'backslash' | 'drive-or-unc' | 'encoded-separator' | 'encoded-dot' | 'bad-encoding' | 'empty-segment' | 'dot-segment' | 'unsafe-key' | 'segment-trailing-dot' | 'traversal-escape' | 'not-absolute-uri' | 'unsafe-scheme';
64
- /** A validated OPC name, or the typed reason it was refused. */
65
- type NameResult = {
66
- readonly ok: true;
67
- readonly partName: string;
68
- } | {
69
- readonly ok: false;
70
- readonly reason: NameRejection;
71
- };
72
- /**
73
- * Normalize a ZIP entry name or OPC part name into a canonical part name
74
- * (`/word/document.xml`). Accepts leading-slash and no-leading-slash inputs;
75
- * rejects traversal, dot segments, and the attack surface. Duplicate detection
76
- * folds ASCII case (OPC part-name equivalence).
77
- */
78
- declare function normalizePartName(raw: string): NameResult;
79
- /**
80
- * ASCII-only lowercase fold. OPC part-name/extension equivalence is US-ASCII
81
- * case-insensitive; a locale `toLowerCase()` mis-folds e.g. Turkish `I`/`İ` and
82
- * could let two "equivalent" part names evade duplicate detection.
83
- */
84
- declare function asciiFold(s: string): string;
85
- /** Case-folded key for OPC part-name equivalence / duplicate detection. */
86
- declare function partNameKey(partName: string): string;
87
- /**
88
- * Detect archive entries that collide after normalization (before inflation).
89
- * Returns the case-folded keys that more than one raw name maps to.
90
- */
91
- declare function detectDuplicateNames(rawNames: readonly string[]): {
92
- readonly duplicates: readonly string[];
93
- readonly rejected: readonly {
94
- raw: string;
95
- reason: NameRejection;
96
- }[];
97
- };
98
- /**
99
- * Resolve an internal relationship target against its owner part, without
100
- * escaping the package root. `ownerPartName` is a canonical part name; the base
101
- * is its containing folder. A leading "/" target is package-absolute. `.`/`..`
102
- * segments resolve on a stack; popping above root is `traversal-escape`.
103
- */
104
- declare function resolveInternalTarget(ownerPartName: string, rawTarget: string): NameResult;
105
- /**
106
- * Validate an external-mode relationship target. It MUST be an absolute URI, is
107
- * retained verbatim by the caller, and is NEVER owner-resolved or fetched here.
108
- * Unsafe schemes (javascript/vbscript/data/file) are rejected for runtime sinks;
109
- * the raw lexical form is still preserved separately by the authored record.
110
- */
111
- declare function validateExternalTarget(raw: string): NameResult;
112
-
113
- /** One `<Default>`: a file extension mapped to a content type. */
114
- interface DefaultRecord {
115
- readonly extension: string;
116
- readonly contentType: string;
117
- readonly order: number;
118
- }
119
- /** One `<Override>`: a specific part name mapped to a content type. Beats any Default. */
120
- interface OverrideRecord {
121
- readonly partName: string;
122
- readonly contentType: string;
123
- readonly order: number;
124
- }
125
- /**
126
- * The authored `[Content_Types].xml` records, in significant order.
127
- *
128
- * Retained rather than collapsed into a lookup, because the file's lexical form and ordering are
129
- * part of what a lossless save re-emits.
130
- */
131
- interface ContentTypeRecords {
132
- readonly defaults: readonly DefaultRecord[];
133
- readonly overrides: readonly OverrideRecord[];
134
- }
135
- /**
136
- * Why content-type records could not be indexed.
137
- *
138
- * All fail CLOSED: conflicting Defaults on one extension, duplicate normalized Override names, or
139
- * invalid MIME syntax are refused rather than resolved by picking one.
140
- */
141
- type ContentTypeError = {
142
- readonly code: 'invalid-mime';
143
- readonly value: string;
144
- } | {
145
- readonly code: 'conflicting-default';
146
- readonly extension: string;
147
- } | {
148
- readonly code: 'duplicate-override';
149
- readonly partName: string;
150
- } | {
151
- readonly code: 'invalid-override-name';
152
- readonly partName: string;
153
- } | {
154
- readonly code: 'too-many-records';
155
- readonly limit: number;
156
- };
157
- /** Whether a string is syntactically a MIME type. Syntax only — no registry lookup. */
158
- declare function isValidMime(value: string): boolean;
159
- /** ASCII-case-insensitive extension key (leading dot removed; ASCII-only fold). */
160
- declare function extensionKey(extension: string): string;
161
- /** The resolved lookup: Override by case-folded part name, Default by case-insensitive extension. */
162
- interface ContentTypeIndex {
163
- /** ext key -> single MIME (identical duplicates collapsed). */
164
- readonly defaults: ReadonlyMap<string, string>;
165
- /** case-folded part name -> MIME. */
166
- readonly overrides: ReadonlyMap<string, string>;
167
- }
168
- /** The built index, or the conflict that made it impossible. */
169
- type IndexResult = {
170
- readonly ok: true;
171
- readonly index: ContentTypeIndex;
172
- } | {
173
- readonly ok: false;
174
- readonly error: ContentTypeError;
175
- };
176
- /**
177
- * Build a resolved content-type index, failing closed on conflict/duplicate/MIME
178
- * errors. `maxRecords` bounds the combined record count (N/N+1 gate).
179
- */
180
- declare function buildContentTypeIndex(records: ContentTypeRecords, maxRecords?: number): IndexResult;
181
- /**
182
- * A part's content type, or why it has none.
183
- *
184
- * An orphan record never determines a part's type — a Default with no matching part is preserved
185
- * inertly rather than applied.
186
- */
187
- type ResolveResult = {
188
- readonly ok: true;
189
- readonly contentType: string;
190
- readonly source: 'override' | 'default';
191
- } | {
192
- readonly ok: false;
193
- readonly reason: 'unknown';
194
- };
195
- /** Resolve a part's content type: Override wins over Default; else unknown. */
196
- declare function resolveContentType(index: ContentTypeIndex, partName: string): ResolveResult;
197
-
198
- /** OOXML image relationship type for embedded or linked media parts. */
199
- declare const IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
200
- /**
201
- * Whether a relationship points inside the package or out of it.
202
- *
203
- * The security-relevant distinction: an `External` target is retained VERBATIM and never
204
- * owner-resolved or fetched, because auto-loading a file-supplied remote target is a zero-click
205
- * external fetch.
206
- */
207
- type TargetMode = 'Internal' | 'External';
208
- /**
209
- * One authored relationship, with nothing materialized away: owner part, id, type, raw target
210
- * lexical form, mode, and position.
211
- */
212
- interface RelationshipRecord {
213
- readonly ownerPart: string;
214
- readonly id: string;
215
- readonly type: string;
216
- readonly rawTarget: string;
217
- readonly targetMode: TargetMode;
218
- readonly order: number;
219
- }
220
- /** Why a relationship set is invalid. Duplicate ids within one owner fail closed. */
221
- type RelationshipError = {
222
- readonly code: 'duplicate-id';
223
- readonly ownerPart: string;
224
- readonly id: string;
225
- };
226
- /** The validated relationship set, or the conflict that rejected it. */
227
- type RelationshipSetResult = {
228
- readonly ok: true;
229
- readonly byOwner: ReadonlyMap<string, readonly RelationshipRecord[]>;
230
- } | {
231
- readonly ok: false;
232
- readonly error: RelationshipError;
233
- };
234
- /** Group relationships by owner in authored order; reject duplicate ids per owner. */
235
- declare function buildRelationshipSet(records: readonly RelationshipRecord[]): RelationshipSetResult;
236
- /**
237
- * A relationship resolved to a part, or the reason it could not be.
238
- *
239
- * External targets resolve to a refusal by design: they are never followed from a file.
240
- */
241
- type ResolvedRelationship = {
242
- readonly mode: 'Internal';
243
- readonly target: NameResult;
244
- readonly raw: string;
245
- } | {
246
- readonly mode: 'External';
247
- readonly sinkSafe: NameResult;
248
- readonly raw: string;
249
- };
250
- /**
251
- * Resolve a relationship to a runtime projection while the raw target stays
252
- * authored. Internal -> owner-relative part name; External -> sink-safe
253
- * validation only (never owner-resolved, never fetched). `raw` is always the
254
- * verbatim authored target.
255
- */
256
- declare function resolveRelationship(rec: RelationshipRecord): ResolvedRelationship;
257
- /**
258
- * An image relationship resolved to package bytes, or why it was refused.
259
- *
260
- * External-mode image rels are refused rather than fetched — the no-zero-click-external-fetch
261
- * rule applies to images exactly as it does to links.
262
- */
263
- type ImageRelationshipResolution = {
264
- readonly mode: 'internal';
265
- readonly partName: string;
266
- readonly raw: string;
267
- } | {
268
- readonly mode: 'external';
269
- readonly sinkSafe: boolean;
270
- readonly raw: string;
271
- } | {
272
- readonly mode: 'missing';
273
- };
274
- /**
275
- * Resolve an image relationship id from an owner part. Internal targets resolve
276
- * owner-relative; external targets are never fetched; a missing id is `missing`.
277
- */
278
- declare function resolveImageRelationship(records: readonly RelationshipRecord[] | undefined, ownerPart: string, relationshipId: string): ImageRelationshipResolution;
1
+ import { c as HistoryGroupOutcome } from './editor-scope-OHPwVQ5l.js';
279
2
 
280
3
  /**
281
4
  * One parsed XML node, preserving significant order, whitespace and raw lexical values.
@@ -1148,35 +871,430 @@ type OoxmlInvariantResult = {
1148
871
  */
1149
872
  declare function readOoxmlPart(xml: string, metadata: OoxmlPartMetadata, limits?: XmlLimits): OoxmlReadResult;
1150
873
 
1151
- /**
1152
- * Why a zip was refused at the trust boundary.
1153
- *
1154
- * `too-large` and `too-many-entries` are the zip-bomb guards; `bad-name` catches path traversal —
1155
- * an entry with `..` or a leading `/` is rejected rather than normalized.
1156
- */
1157
- type ZipRejection = 'too-many-entries' | 'too-large' | 'bad-name' | 'inflate-error';
1158
- /** Archive caps: entry count, total decompressed bytes, and the decompression ratio. */
1159
- interface ZipLimits {
1160
- readonly maxEntries: number;
1161
- /** Max total UNCOMPRESSED bytes across the archive. */
1162
- readonly maxTotalBytes: number;
1163
- /** Max per-entry uncompressed:compressed ratio (zip-bomb guard). */
1164
- readonly maxRatio?: number;
1165
- }
1166
- /** The archive caps in force when a host configures none. Conservative and finite. */
1167
- declare const DEFAULT_ZIP_LIMITS: ZipLimits;
1168
- /** The read entries, or the typed refusal. Never throws — the bytes are untrusted. */
1169
- type ZipReadResult = {
1170
- readonly ok: true;
1171
- readonly entries: ReadonlyMap<string, Uint8Array>;
874
+ type AutomationTableMutation = {
875
+ readonly kind: 'values';
876
+ readonly values: readonly (readonly string[])[];
1172
877
  } | {
1173
- readonly ok: false;
1174
- readonly reason: ZipRejection;
1175
- readonly detail?: string;
1176
- readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
1177
- };
1178
- /**
1179
- * Inflate a ZIP archive with bounds + OPC name normalization. Entry name, count,
878
+ readonly kind: 'addRows' | 'addColumns';
879
+ readonly location: 'start' | 'end';
880
+ readonly count: number;
881
+ readonly values?: readonly (readonly string[])[];
882
+ } | {
883
+ readonly kind: 'deleteRows' | 'deleteColumns';
884
+ readonly index: number;
885
+ readonly count: number;
886
+ } | {
887
+ readonly kind: 'delete';
888
+ } | {
889
+ readonly kind: 'properties';
890
+ readonly styleId?: string;
891
+ readonly headerRowCount?: number;
892
+ } | {
893
+ readonly kind: 'cell';
894
+ readonly cellId: string;
895
+ readonly value?: string;
896
+ readonly columnWidth?: number;
897
+ readonly shadingColor?: string;
898
+ readonly verticalAlignment?: 'Top' | 'Center' | 'Bottom';
899
+ };
900
+
901
+ /** Select one declared entry of a legacy Word dropdown form field. */
902
+ interface SetLegacyDropdownOp {
903
+ readonly op: 'setLegacyDropdown';
904
+ readonly paragraphId: string;
905
+ readonly fieldNodeId: string;
906
+ readonly selectedIndex: number;
907
+ }
908
+
909
+ interface SetFieldCodeOp {
910
+ readonly op: 'setFieldCode';
911
+ readonly paragraphId: string;
912
+ readonly fieldNodeId: string;
913
+ readonly code: string;
914
+ }
915
+
916
+ type InsertTextOp = {
917
+ readonly op: 'insertText';
918
+ readonly paragraphId: string;
919
+ /** Legacy text form identity for protected filling; never an inline wrapper owner. */
920
+ readonly textFormFieldId?: string;
921
+ readonly offset: number;
922
+ readonly text: string;
923
+ /**
924
+ * Write this as a TRACKED insertion, attributed here.
925
+ *
926
+ * On the op rather than on the store, so suggesting stays a decision the surface makes
927
+ * per edit and the write vocabulary stays explicit — a global "everything is tracked
928
+ * now" flag is exactly what `DocEdits` refuses, because it makes the meaning of an op
929
+ * depend on state the op does not carry.
930
+ */
931
+ readonly revision?: RevisionAttributionInput;
932
+ /**
933
+ * When set, the text belongs INSIDE this content control, whatever sits at the offset.
934
+ *
935
+ * A boundary offset is owned by the run that starts there, which at a control's trailing
936
+ * edge is the run after the control — so an offset alone cannot say "append to this field",
937
+ * the way it cannot say which run of a field result to format (see `targetRunIds`). A
938
+ * caller that names the control gets the text in the control; one that does not gets the
939
+ * plain offset rule, which is what a keystroke beside a field means.
940
+ */
941
+ readonly inside?: string;
942
+ /**
943
+ * Which side of a run BOUNDARY the text joins. Default `'left'` — Word's typing rule:
944
+ * the next character takes the formatting of the character before the caret.
945
+ *
946
+ * `'right'` is for a caller that is not typing but placing text inside the run that
947
+ * STARTS at the offset — the hyperlink editor rewriting a link's display text, where
948
+ * landing left of the boundary would put the new text outside the link. Ignored when
949
+ * the offset falls strictly inside a run, which has no boundary to choose.
950
+ */
951
+ readonly bias?: 'left' | 'right';
952
+ };
953
+ type DeleteTextOp = {
954
+ readonly op: 'deleteText';
955
+ readonly paragraphId: string;
956
+ /** Legacy text form identity for protected filling; never an inline wrapper owner. */
957
+ readonly textFormFieldId?: string;
958
+ readonly start: number;
959
+ readonly end: number;
960
+ /** Write this as a TRACKED deletion — the characters stay, wrapped in `w:del`. */
961
+ readonly revision?: RevisionAttributionInput;
962
+ };
963
+
964
+ /** Editable legacy text input types. Other authored types remain inert. */
965
+ type TextFormFieldType = 'regular' | 'number' | 'date';
966
+ /** Options stored in the legacy field definition. Zero means unlimited length. */
967
+ interface TextFormFieldOptions {
968
+ readonly type: TextFormFieldType;
969
+ readonly maxLength: number;
970
+ readonly format: string;
971
+ readonly enabled: boolean;
972
+ }
973
+ /** Supported format choices for legacy text input fields. @public */
974
+ declare const TEXT_FORM_FORMATS: {
975
+ readonly regular: readonly ["", "Uppercase", "Lowercase", "First capital", "Title case"];
976
+ readonly number: readonly ["", "0", "0.00", "#,##0", "#,##0.00", "0%", "0.00%"];
977
+ readonly date: readonly ["", "M/d/yyyy", "MM/dd/yyyy", "d/M/yyyy", "dd/MM/yyyy", "yyyy-MM-dd", "d MMMM yyyy", "MMMM d, yyyy"];
978
+ };
979
+
980
+ /** A legacy text input in the shared paragraph offset space. */
981
+ interface TextFormFieldRange {
982
+ readonly fieldNodeId: string;
983
+ readonly start: number;
984
+ readonly end: number;
985
+ readonly enabled: boolean;
986
+ readonly defaultText: string;
987
+ readonly type: string;
988
+ readonly maxLength: number;
989
+ readonly format: string;
990
+ readonly chromeIds: readonly string[];
991
+ }
992
+ /** Uses the field parser and offset index; never introduces another inline walk. */
993
+ declare function textFormFieldsOf(paragraph: OoxmlParagraphNode): readonly TextFormFieldRange[];
994
+ /** Options edit for an existing legacy text form. */
995
+ interface SetTextFormFieldDefaultOp {
996
+ readonly op: 'setTextFormFieldDefault';
997
+ /** Regional conventions for new date input; defaults to en-US. */
998
+ readonly locale?: string;
999
+ readonly paragraphId: string;
1000
+ readonly fieldNodeId: string;
1001
+ readonly text: string;
1002
+ readonly options?: TextFormFieldOptions;
1003
+ }
1004
+ /** Validate and format the existing result when a user finishes filling a field. */
1005
+ interface CommitTextFormFieldOp {
1006
+ readonly op: 'commitTextFormField';
1007
+ /** Regional conventions for new date input; defaults to en-US. */
1008
+ readonly locale?: string;
1009
+ readonly paragraphId: string;
1010
+ readonly fieldNodeId: string;
1011
+ }
1012
+
1013
+ /** One FORMCHECKBOX in the shared paragraph offset space. */
1014
+ interface LegacyCheckboxFieldRange {
1015
+ /** The begin `w:fldChar` node: what the op addresses. */
1016
+ readonly fieldNodeId: string;
1017
+ readonly start: number;
1018
+ readonly end: number;
1019
+ readonly checked: boolean;
1020
+ /** `w:enabled` under `w:ffData`; a disabled field renders but refuses the toggle. */
1021
+ readonly enabled: boolean;
1022
+ }
1023
+ /** Flip a FORMCHECKBOX's state; the only write into `w:ffData` a checkbox permits. */
1024
+ interface SetLegacyCheckboxOp {
1025
+ readonly op: 'setLegacyCheckbox';
1026
+ readonly paragraphId: string;
1027
+ readonly fieldNodeId: string;
1028
+ readonly checked: boolean;
1029
+ }
1030
+ /** Every FORMCHECKBOX in a paragraph, in document order; uses the shared field parser. */
1031
+ declare function legacyCheckboxFieldsOf(paragraph: OoxmlParagraphNode): readonly LegacyCheckboxFieldRange[];
1032
+
1033
+ /** Replace a building block gallery control's content with one block's body. */
1034
+ interface InsertBuildingBlockOp {
1035
+ readonly op: 'insertBuildingBlock';
1036
+ readonly controlId: string;
1037
+ /** `w:docPartPr/w:name` of the picked block, for the journal and the host. */
1038
+ readonly name: string;
1039
+ /**
1040
+ * Self-contained `w:docPartBody` children, cloned with fresh ids at apply.
1041
+ * Resource, style, field, bookmark, note and revision references return `unsupported`.
1042
+ */
1043
+ readonly blocks: readonly OoxmlNode[];
1044
+ }
1045
+
1046
+ /**
1047
+ * Why a part or relationship name was refused.
1048
+ *
1049
+ * Path traversal is the reason this exists: a name with `..` or a leading `/` is refused rather
1050
+ * than normalized, because normalizing is how a crafted package reaches outside itself.
1051
+ */
1052
+ type NameRejection = 'empty' | 'control-char' | 'backslash' | 'drive-or-unc' | 'encoded-separator' | 'encoded-dot' | 'bad-encoding' | 'empty-segment' | 'dot-segment' | 'unsafe-key' | 'segment-trailing-dot' | 'traversal-escape' | 'not-absolute-uri' | 'unsafe-scheme';
1053
+ /** A validated OPC name, or the typed reason it was refused. */
1054
+ type NameResult = {
1055
+ readonly ok: true;
1056
+ readonly partName: string;
1057
+ } | {
1058
+ readonly ok: false;
1059
+ readonly reason: NameRejection;
1060
+ };
1061
+ /**
1062
+ * Normalize a ZIP entry name or OPC part name into a canonical part name
1063
+ * (`/word/document.xml`). Accepts leading-slash and no-leading-slash inputs;
1064
+ * rejects traversal, dot segments, and the attack surface. Duplicate detection
1065
+ * folds ASCII case (OPC part-name equivalence).
1066
+ */
1067
+ declare function normalizePartName(raw: string): NameResult;
1068
+ /**
1069
+ * ASCII-only lowercase fold. OPC part-name/extension equivalence is US-ASCII
1070
+ * case-insensitive; a locale `toLowerCase()` mis-folds e.g. Turkish `I`/`İ` and
1071
+ * could let two "equivalent" part names evade duplicate detection.
1072
+ */
1073
+ declare function asciiFold(s: string): string;
1074
+ /** Case-folded key for OPC part-name equivalence / duplicate detection. */
1075
+ declare function partNameKey(partName: string): string;
1076
+ /**
1077
+ * Detect archive entries that collide after normalization (before inflation).
1078
+ * Returns the case-folded keys that more than one raw name maps to.
1079
+ */
1080
+ declare function detectDuplicateNames(rawNames: readonly string[]): {
1081
+ readonly duplicates: readonly string[];
1082
+ readonly rejected: readonly {
1083
+ raw: string;
1084
+ reason: NameRejection;
1085
+ }[];
1086
+ };
1087
+ /**
1088
+ * Resolve an internal relationship target against its owner part, without
1089
+ * escaping the package root. `ownerPartName` is a canonical part name; the base
1090
+ * is its containing folder. A leading "/" target is package-absolute. `.`/`..`
1091
+ * segments resolve on a stack; popping above root is `traversal-escape`.
1092
+ */
1093
+ declare function resolveInternalTarget(ownerPartName: string, rawTarget: string): NameResult;
1094
+ /**
1095
+ * Validate an external-mode relationship target. It MUST be an absolute URI, is
1096
+ * retained verbatim by the caller, and is NEVER owner-resolved or fetched here.
1097
+ * Unsafe schemes (javascript/vbscript/data/file) are rejected for runtime sinks;
1098
+ * the raw lexical form is still preserved separately by the authored record.
1099
+ */
1100
+ declare function validateExternalTarget(raw: string): NameResult;
1101
+
1102
+ /** One `<Default>`: a file extension mapped to a content type. */
1103
+ interface DefaultRecord {
1104
+ readonly extension: string;
1105
+ readonly contentType: string;
1106
+ readonly order: number;
1107
+ }
1108
+ /** One `<Override>`: a specific part name mapped to a content type. Beats any Default. */
1109
+ interface OverrideRecord {
1110
+ readonly partName: string;
1111
+ readonly contentType: string;
1112
+ readonly order: number;
1113
+ }
1114
+ /**
1115
+ * The authored `[Content_Types].xml` records, in significant order.
1116
+ *
1117
+ * Retained rather than collapsed into a lookup, because the file's lexical form and ordering are
1118
+ * part of what a lossless save re-emits.
1119
+ */
1120
+ interface ContentTypeRecords {
1121
+ readonly defaults: readonly DefaultRecord[];
1122
+ readonly overrides: readonly OverrideRecord[];
1123
+ }
1124
+ /**
1125
+ * Why content-type records could not be indexed.
1126
+ *
1127
+ * All fail CLOSED: conflicting Defaults on one extension, duplicate normalized Override names, or
1128
+ * invalid MIME syntax are refused rather than resolved by picking one.
1129
+ */
1130
+ type ContentTypeError = {
1131
+ readonly code: 'invalid-mime';
1132
+ readonly value: string;
1133
+ } | {
1134
+ readonly code: 'conflicting-default';
1135
+ readonly extension: string;
1136
+ } | {
1137
+ readonly code: 'duplicate-override';
1138
+ readonly partName: string;
1139
+ } | {
1140
+ readonly code: 'invalid-override-name';
1141
+ readonly partName: string;
1142
+ } | {
1143
+ readonly code: 'too-many-records';
1144
+ readonly limit: number;
1145
+ };
1146
+ /** Whether a string is syntactically a MIME type. Syntax only — no registry lookup. */
1147
+ declare function isValidMime(value: string): boolean;
1148
+ /** ASCII-case-insensitive extension key (leading dot removed; ASCII-only fold). */
1149
+ declare function extensionKey(extension: string): string;
1150
+ /** The resolved lookup: Override by case-folded part name, Default by case-insensitive extension. */
1151
+ interface ContentTypeIndex {
1152
+ /** ext key -> single MIME (identical duplicates collapsed). */
1153
+ readonly defaults: ReadonlyMap<string, string>;
1154
+ /** case-folded part name -> MIME. */
1155
+ readonly overrides: ReadonlyMap<string, string>;
1156
+ }
1157
+ /** The built index, or the conflict that made it impossible. */
1158
+ type IndexResult = {
1159
+ readonly ok: true;
1160
+ readonly index: ContentTypeIndex;
1161
+ } | {
1162
+ readonly ok: false;
1163
+ readonly error: ContentTypeError;
1164
+ };
1165
+ /**
1166
+ * Build a resolved content-type index, failing closed on conflict/duplicate/MIME
1167
+ * errors. `maxRecords` bounds the combined record count (N/N+1 gate).
1168
+ */
1169
+ declare function buildContentTypeIndex(records: ContentTypeRecords, maxRecords?: number): IndexResult;
1170
+ /**
1171
+ * A part's content type, or why it has none.
1172
+ *
1173
+ * An orphan record never determines a part's type — a Default with no matching part is preserved
1174
+ * inertly rather than applied.
1175
+ */
1176
+ type ResolveResult = {
1177
+ readonly ok: true;
1178
+ readonly contentType: string;
1179
+ readonly source: 'override' | 'default';
1180
+ } | {
1181
+ readonly ok: false;
1182
+ readonly reason: 'unknown';
1183
+ };
1184
+ /** Resolve a part's content type: Override wins over Default; else unknown. */
1185
+ declare function resolveContentType(index: ContentTypeIndex, partName: string): ResolveResult;
1186
+
1187
+ /** OOXML image relationship type for embedded or linked media parts. */
1188
+ declare const IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
1189
+ /**
1190
+ * Whether a relationship points inside the package or out of it.
1191
+ *
1192
+ * The security-relevant distinction: an `External` target is retained VERBATIM and never
1193
+ * owner-resolved or fetched, because auto-loading a file-supplied remote target is a zero-click
1194
+ * external fetch.
1195
+ */
1196
+ type TargetMode = 'Internal' | 'External';
1197
+ /**
1198
+ * One authored relationship, with nothing materialized away: owner part, id, type, raw target
1199
+ * lexical form, mode, and position.
1200
+ */
1201
+ interface RelationshipRecord {
1202
+ readonly ownerPart: string;
1203
+ readonly id: string;
1204
+ readonly type: string;
1205
+ readonly rawTarget: string;
1206
+ readonly targetMode: TargetMode;
1207
+ readonly order: number;
1208
+ }
1209
+ /** Why a relationship set is invalid. Duplicate ids within one owner fail closed. */
1210
+ type RelationshipError = {
1211
+ readonly code: 'duplicate-id';
1212
+ readonly ownerPart: string;
1213
+ readonly id: string;
1214
+ };
1215
+ /** The validated relationship set, or the conflict that rejected it. */
1216
+ type RelationshipSetResult = {
1217
+ readonly ok: true;
1218
+ readonly byOwner: ReadonlyMap<string, readonly RelationshipRecord[]>;
1219
+ } | {
1220
+ readonly ok: false;
1221
+ readonly error: RelationshipError;
1222
+ };
1223
+ /** Group relationships by owner in authored order; reject duplicate ids per owner. */
1224
+ declare function buildRelationshipSet(records: readonly RelationshipRecord[]): RelationshipSetResult;
1225
+ /**
1226
+ * A relationship resolved to a part, or the reason it could not be.
1227
+ *
1228
+ * External targets resolve to a refusal by design: they are never followed from a file.
1229
+ */
1230
+ type ResolvedRelationship = {
1231
+ readonly mode: 'Internal';
1232
+ readonly target: NameResult;
1233
+ readonly raw: string;
1234
+ } | {
1235
+ readonly mode: 'External';
1236
+ readonly sinkSafe: NameResult;
1237
+ readonly raw: string;
1238
+ };
1239
+ /**
1240
+ * Resolve a relationship to a runtime projection while the raw target stays
1241
+ * authored. Internal -> owner-relative part name; External -> sink-safe
1242
+ * validation only (never owner-resolved, never fetched). `raw` is always the
1243
+ * verbatim authored target.
1244
+ */
1245
+ declare function resolveRelationship(rec: RelationshipRecord): ResolvedRelationship;
1246
+ /**
1247
+ * An image relationship resolved to package bytes, or why it was refused.
1248
+ *
1249
+ * External-mode image rels are refused rather than fetched — the no-zero-click-external-fetch
1250
+ * rule applies to images exactly as it does to links.
1251
+ */
1252
+ type ImageRelationshipResolution = {
1253
+ readonly mode: 'internal';
1254
+ readonly partName: string;
1255
+ readonly raw: string;
1256
+ } | {
1257
+ readonly mode: 'external';
1258
+ readonly sinkSafe: boolean;
1259
+ readonly raw: string;
1260
+ } | {
1261
+ readonly mode: 'missing';
1262
+ };
1263
+ /**
1264
+ * Resolve an image relationship id from an owner part. Internal targets resolve
1265
+ * owner-relative; external targets are never fetched; a missing id is `missing`.
1266
+ */
1267
+ declare function resolveImageRelationship(records: readonly RelationshipRecord[] | undefined, ownerPart: string, relationshipId: string): ImageRelationshipResolution;
1268
+
1269
+ /**
1270
+ * Why a zip was refused at the trust boundary.
1271
+ *
1272
+ * `too-large` and `too-many-entries` are the zip-bomb guards; `bad-name` catches path traversal —
1273
+ * an entry with `..` or a leading `/` is rejected rather than normalized.
1274
+ */
1275
+ type ZipRejection = 'too-many-entries' | 'too-large' | 'bad-name' | 'inflate-error';
1276
+ /** Archive caps: entry count, total decompressed bytes, and the decompression ratio. */
1277
+ interface ZipLimits {
1278
+ readonly maxEntries: number;
1279
+ /** Max total UNCOMPRESSED bytes across the archive. */
1280
+ readonly maxTotalBytes: number;
1281
+ /** Max per-entry uncompressed:compressed ratio (zip-bomb guard). */
1282
+ readonly maxRatio?: number;
1283
+ }
1284
+ /** The archive caps in force when a host configures none. Conservative and finite. */
1285
+ declare const DEFAULT_ZIP_LIMITS: ZipLimits;
1286
+ /** The read entries, or the typed refusal. Never throws — the bytes are untrusted. */
1287
+ type ZipReadResult = {
1288
+ readonly ok: true;
1289
+ readonly entries: ReadonlyMap<string, Uint8Array>;
1290
+ } | {
1291
+ readonly ok: false;
1292
+ readonly reason: ZipRejection;
1293
+ readonly detail?: string;
1294
+ readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
1295
+ };
1296
+ /**
1297
+ * Inflate a ZIP archive with bounds + OPC name normalization. Entry name, count,
1180
1298
  * compression-ratio, and total-uncompressed-size limits are enforced BEFORE each
1181
1299
  * entry is decompressed (via fflate's pre-inflation filter), so a zip bomb or a
1182
1300
  * traversal name is rejected without ever being inflated. Keys are canonical part
@@ -1573,159 +1691,6 @@ declare function projectDrawing(drawing: OoxmlDrawingNode, context: Readonly<{
1573
1691
  resolveStyleMatrixReference?: ShapeStyleMatrixResolver;
1574
1692
  }>): DrawingProjection | null;
1575
1693
 
1576
- /** Opaque handle — bytes are reachable only through {@link mintValidatedImageBytes}. */
1577
- interface ValidatedImageBytesHandle {
1578
- readonly registryId: number;
1579
- readonly resourceKey: string;
1580
- readonly contentId: string;
1581
- readonly generation: number;
1582
- }
1583
-
1584
- /**
1585
- * Raster media the decode port measures and any authoring path may write.
1586
- *
1587
- * BMP and WebP are here for the same reason the other three are: an `<img>` decodes them
1588
- * natively, so they need a signature and a structural header and nothing else. BMP is what
1589
- * older documents carry; WebP is what current Word writes.
1590
- */
1591
- type SupportedImageMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/bmp' | 'image/webp';
1592
- /**
1593
- * Vector media painted straight from validated bytes. An `<img>` renders SVG in the
1594
- * browser's secure static mode — no script, no external subresource loads — so there is
1595
- * no decode step and no raster buffer sized by a file-supplied number.
1596
- */
1597
- type VectorImageMime = 'image/svg+xml';
1598
- /** Every mime the painter can hand to an `<img>`. */
1599
- type RenderableImageMime = SupportedImageMime | VectorImageMime;
1600
- /**
1601
- * Media kept in the package byte-for-byte that the painter cannot hand to an `<img>`.
1602
- * A decode port may rasterize it; without one it paints as a labelled placeholder.
1603
- */
1604
- type PreservedImageMime = 'image/tiff' | 'image/x-emf' | 'image/x-wmf';
1605
- /**
1606
- * What is known about one embedded image: validated, refused, or still decoding.
1607
- *
1608
- * Content type is a CLAIM. Signature sniffing, structural header validation and the decode port
1609
- * are authoritative, and bytes that fail them never enter public state.
1610
- */
1611
- type ImageResourceState = {
1612
- readonly kind: 'ready';
1613
- readonly partName: string;
1614
- readonly contentId: string;
1615
- readonly resourceKey: string;
1616
- readonly validatedHandle: ValidatedImageBytesHandle;
1617
- readonly mime: RenderableImageMime;
1618
- readonly pixelWidth: number;
1619
- readonly pixelHeight: number;
1620
- readonly dpiX: number;
1621
- readonly dpiY: number;
1622
- } | {
1623
- readonly kind: 'unrenderable';
1624
- readonly partName: string | null;
1625
- readonly mime: RenderableImageMime | PreservedImageMime | 'unknown';
1626
- readonly reason: 'unsupported-format' | 'non-picture-graphic' | 'signature-mismatch' | 'decode-failed' | 'resource-limit';
1627
- } | {
1628
- readonly kind: 'external';
1629
- readonly relationshipId: string;
1630
- readonly sinkSafe: boolean;
1631
- } | {
1632
- readonly kind: 'missing';
1633
- readonly relationshipId: string;
1634
- } | {
1635
- readonly kind: 'pending';
1636
- readonly resourceKey: string;
1637
- };
1638
- /**
1639
- * The injected image decoder.
1640
- *
1641
- * A port rather than a direct `Image`/`createImageBitmap` call, so a worker or server runtime
1642
- * supplies its own and the engine never reaches for a browser global.
1643
- */
1644
- interface ImageDecodePort {
1645
- decode(bytes: Uint8Array, mime: SupportedImageMime, limits: ImageResourceLimits,
1646
- /** Aborted when the owning lookup/session is disposed. */
1647
- signal?: AbortSignal): Promise<Readonly<{
1648
- pixelWidth: number;
1649
- pixelHeight: number;
1650
- dpiX: number;
1651
- dpiY: number;
1652
- }>>;
1653
- /**
1654
- * Optional conversion of media an `<img>` cannot render (EMF/WMF metafiles, TIFF) into a
1655
- * renderable raster. The returned bytes are untrusted and re-enter the full raster
1656
- * validation path (sniff, header, pixel caps, decode) before they can become a ready
1657
- * resource. A null return declines the format and keeps the labelled placeholder; so does
1658
- * a throw, as `decode-failed`.
1659
- */
1660
- convertPreserved?(bytes: Uint8Array, mime: PreservedImageMime, limits: ImageResourceLimits,
1661
- /** Aborted when the owning lookup/session is disposed. */
1662
- signal?: AbortSignal): Promise<Readonly<{
1663
- bytes: Uint8Array;
1664
- mime: SupportedImageMime;
1665
- }> | null>;
1666
- }
1667
- /** Resolves a relationship id to a validated image resource, or reports why it could not. */
1668
- interface ImageResourceLookup {
1669
- readonly resolveEmbedded: (ownerPartName: string, relationshipId: string) => Promise<ImageResourceState>;
1670
- readonly resolveLinked: (ownerPartName: string, relationshipId: string) => ImageResourceState;
1671
- readonly resolveForProjection: (projection: DrawingProjection) => Promise<ImageResourceState>;
1672
- readonly liveReferenceCount: (partName: string) => number;
1673
- readonly dispose: () => void;
1674
- }
1675
- /** Maximum prefix inspected for SVG root detection (exported for bounded-scan tests). */
1676
- declare const MAX_SVG_SNIFF_BYTES = 512;
1677
- /** A raster header that passed structural validation: its real MIME type and pixel extent. */
1678
- interface ValidatedRasterHeader {
1679
- readonly pixelWidth: number;
1680
- readonly pixelHeight: number;
1681
- /** Horizontal physical density when bounded header metadata supplies it. */
1682
- readonly dpiX?: number;
1683
- /** Vertical physical density when bounded header metadata supplies it. */
1684
- readonly dpiY?: number;
1685
- }
1686
- /** Bounded scan for an `<svg` document root (optional `<?xml` prolog only). */
1687
- declare function hasBoundedSvgRoot(bytes: Uint8Array): boolean;
1688
- /** Signature sniffing — authoritative over declared content type. */
1689
- declare function sniffImageMime(bytes: Uint8Array): RenderableImageMime | PreservedImageMime | 'unknown';
1690
- /** Structural PNG IHDR validation before decode. */
1691
- declare function validatePngHeader(bytes: Uint8Array): ValidatedRasterHeader | null;
1692
- /** Structural GIF logical screen descriptor validation before decode. */
1693
- declare function validateGifHeader(bytes: Uint8Array): ValidatedRasterHeader | null;
1694
- /** Bounded JPEG marker scan through the first supported SOF marker. */
1695
- declare function validateJpegHeader(bytes: Uint8Array): ValidatedRasterHeader | null;
1696
- /**
1697
- * Intrinsic size of an SVG, resolved the way a browser sizes one: absolute `width`/`height`
1698
- * first, then `viewBox` for the missing axis or ratio, then the CSS 300x150 default.
1699
- *
1700
- * This is metadata for insert and reset-to-natural-size only. Layout uses the authored
1701
- * `wp:extent` and the browser rasterizes into that box, so nothing here sizes an allocation
1702
- * and an out-of-range value is clamped rather than refused.
1703
- */
1704
- declare function resolveSvgIntrinsicSize(bytes: Uint8Array, limits: ImageResourceLimits): ValidatedRasterHeader | null;
1705
- /**
1706
- * Validate a raster image's header structurally and report its real MIME type and extent.
1707
- *
1708
- * Content type is a CLAIM; this is what makes it a fact. A file declaring `image/png` over JPEG
1709
- * bytes is caught here rather than at decode.
1710
- */
1711
- declare function validateRasterHeader(bytes: Uint8Array, mime: SupportedImageMime): ValidatedRasterHeader | null;
1712
- /** Package-wide live drawing references to a media part name. */
1713
- declare function liveDrawingReferenceCount(pkg: OoxmlPackage, partName: string): number;
1714
- /** How the image cache decodes, and what it will spend doing so. */
1715
- interface CreateImageResourceCacheOptions {
1716
- readonly limits?: Partial<ImageResourceLimits>;
1717
- readonly decodePort: ImageDecodePort;
1718
- }
1719
- /**
1720
- * Derived cache for one immutable package snapshot. Registry identity is
1721
- * `(package snapshot, decodePort object, normalized limits)` — the first caller
1722
- * never imposes its decoder or limits on later callers with different options.
1723
- */
1724
- declare function imageResourceLookupFor(pkg: OoxmlPackage, options: CreateImageResourceCacheOptions): ImageResourceLookup;
1725
- /** @deprecated Prefer {@link imageResourceLookupFor} — registry binds cache to package identity. */
1726
- /** Build the per-document image cache. Validated bytes only; refusals are remembered too. */
1727
- declare function createImageResourceCache(initialPkg: OoxmlPackage, options: CreateImageResourceCacheOptions): ImageResourceLookup;
1728
-
1729
1694
  /** Caps applied while loading a package: zip, XML, part count and relationship count. */
1730
1695
  interface OoxmlPackageLimits {
1731
1696
  readonly zip?: ZipLimits;
@@ -1774,162 +1739,108 @@ type OoxmlPackageResult = {
1774
1739
  readonly ok: true;
1775
1740
  readonly package: OoxmlPackage;
1776
1741
  } | {
1777
- readonly ok: false;
1778
- readonly reason: OoxmlPackageRejection;
1779
- readonly detail?: string;
1780
- readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
1781
- };
1782
- declare function readOoxmlPackage(bytes: Uint8Array, limits?: OoxmlPackageLimits): OoxmlPackageResult;
1783
- /**
1784
- * Serialize a canonical package back to DOCX bytes.
1785
- *
1786
- * Starts from the ORIGINAL entry bytes and overwrites only the parts held as trees. A part
1787
- * the loader did not model — media, fonts, an XML part outside the modeled set — passes
1788
- * through untouched, so round-tripping a document cannot lose a part the engine never
1789
- * claimed to understand.
1790
- *
1791
- * The modeled parts are re-emitted NORMALIZED from the tree rather than patched as text.
1792
- * That is the whole point of the canonical tree: correctness is judged by the two D9
1793
- * oracles (the namespace-aware fingerprint and the save/reopen semantic digest), not by
1794
- * byte equality, so a different-but-equivalent spelling is not a defect.
1795
- *
1796
- * `writeZip` re-validates every part name, so a name that became unsafe between load and
1797
- * save cannot be smuggled into the archive.
1798
- */
1799
- declare function writeOoxmlPackage(pkg: OoxmlPackage): Uint8Array;
1800
- /** Replace one part's tree, returning a new package. Pure, like the tree edits themselves. */
1801
- declare function withPart(pkg: OoxmlPackage, part: OoxmlPart): OoxmlPackage;
1802
-
1803
- type AutomationTableMutation = {
1804
- readonly kind: 'values';
1805
- readonly values: readonly (readonly string[])[];
1806
- } | {
1807
- readonly kind: 'addRows' | 'addColumns';
1808
- readonly location: 'start' | 'end';
1809
- readonly count: number;
1810
- readonly values?: readonly (readonly string[])[];
1811
- } | {
1812
- readonly kind: 'deleteRows' | 'deleteColumns';
1813
- readonly index: number;
1814
- readonly count: number;
1815
- } | {
1816
- readonly kind: 'delete';
1817
- } | {
1818
- readonly kind: 'properties';
1819
- readonly styleId?: string;
1820
- readonly headerRowCount?: number;
1821
- } | {
1822
- readonly kind: 'cell';
1823
- readonly cellId: string;
1824
- readonly value?: string;
1825
- readonly columnWidth?: number;
1826
- readonly shadingColor?: string;
1827
- readonly verticalAlignment?: 'Top' | 'Center' | 'Bottom';
1742
+ readonly ok: false;
1743
+ readonly reason: OoxmlPackageRejection;
1744
+ readonly detail?: string;
1745
+ readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
1828
1746
  };
1747
+ declare function readOoxmlPackage(bytes: Uint8Array, limits?: OoxmlPackageLimits): OoxmlPackageResult;
1748
+ /**
1749
+ * Serialize a canonical package back to DOCX bytes.
1750
+ *
1751
+ * Starts from the ORIGINAL entry bytes and overwrites only the parts held as trees. A part
1752
+ * the loader did not model — media, fonts, an XML part outside the modeled set — passes
1753
+ * through untouched, so round-tripping a document cannot lose a part the engine never
1754
+ * claimed to understand.
1755
+ *
1756
+ * The modeled parts are re-emitted NORMALIZED from the tree rather than patched as text.
1757
+ * That is the whole point of the canonical tree: correctness is judged by the two D9
1758
+ * oracles (the namespace-aware fingerprint and the save/reopen semantic digest), not by
1759
+ * byte equality, so a different-but-equivalent spelling is not a defect.
1760
+ *
1761
+ * `writeZip` re-validates every part name, so a name that became unsafe between load and
1762
+ * save cannot be smuggled into the archive.
1763
+ */
1764
+ declare function writeOoxmlPackage(pkg: OoxmlPackage): Uint8Array;
1765
+ /** Replace one part's tree, returning a new package. Pure, like the tree edits themselves. */
1766
+ declare function withPart(pkg: OoxmlPackage, part: OoxmlPart): OoxmlPackage;
1829
1767
 
1830
- interface SetFieldCodeOp {
1831
- readonly op: 'setFieldCode';
1832
- readonly paragraphId: string;
1833
- readonly fieldNodeId: string;
1834
- readonly code: string;
1835
- }
1836
-
1837
- type InsertTextOp = {
1838
- readonly op: 'insertText';
1768
+ /** The `w15` namespace: `commentsExtended.xml` — thread parent and resolved state. */
1769
+ declare const W15_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2012/wordml";
1770
+ /** A position in one story: a paragraph node id plus a UTF-16 offset inside it. */
1771
+ interface CommentPosition {
1839
1772
  readonly paragraphId: string;
1840
- /** Legacy text form identity for protected filling; never an inline wrapper owner. */
1841
- readonly textFormFieldId?: string;
1842
1773
  readonly offset: number;
1843
- readonly text: string;
1844
- /**
1845
- * Write this as a TRACKED insertion, attributed here.
1846
- *
1847
- * On the op rather than on the store, so suggesting stays a decision the surface makes
1848
- * per edit and the write vocabulary stays explicit — a global "everything is tracked
1849
- * now" flag is exactly what `DocEdits` refuses, because it makes the meaning of an op
1850
- * depend on state the op does not carry.
1851
- */
1852
- readonly revision?: RevisionAttributionInput;
1853
- /**
1854
- * When set, the text belongs INSIDE this content control, whatever sits at the offset.
1855
- *
1856
- * A boundary offset is owned by the run that starts there, which at a control's trailing
1857
- * edge is the run after the control — so an offset alone cannot say "append to this field",
1858
- * the way it cannot say which run of a field result to format (see `targetRunIds`). A
1859
- * caller that names the control gets the text in the control; one that does not gets the
1860
- * plain offset rule, which is what a keystroke beside a field means.
1861
- */
1862
- readonly inside?: string;
1863
- /**
1864
- * Which side of a run BOUNDARY the text joins. Default `'left'` — Word's typing rule:
1865
- * the next character takes the formatting of the character before the caret.
1866
- *
1867
- * `'right'` is for a caller that is not typing but placing text inside the run that
1868
- * STARTS at the offset — the hyperlink editor rewriting a link's display text, where
1869
- * landing left of the boundary would put the new text outside the link. Ignored when
1870
- * the offset falls strictly inside a run, which has no boundary to choose.
1871
- */
1872
- readonly bias?: 'left' | 'right';
1873
- };
1874
- type DeleteTextOp = {
1875
- readonly op: 'deleteText';
1876
- readonly paragraphId: string;
1877
- /** Legacy text form identity for protected filling; never an inline wrapper owner. */
1878
- readonly textFormFieldId?: string;
1879
- readonly start: number;
1880
- readonly end: number;
1881
- /** Write this as a TRACKED deletion — the characters stay, wrapped in `w:del`. */
1882
- readonly revision?: RevisionAttributionInput;
1883
- };
1884
-
1885
- /** Editable legacy text input types. Other authored types remain inert. */
1886
- type TextFormFieldType = 'regular' | 'number' | 'date';
1887
- /** Options stored in the legacy field definition. Zero means unlimited length. */
1888
- interface TextFormFieldOptions {
1889
- readonly type: TextFormFieldType;
1890
- readonly maxLength: number;
1891
- readonly format: string;
1892
- readonly enabled: boolean;
1893
1774
  }
1894
- /** Supported format choices for legacy text input fields. @public */
1895
- declare const TEXT_FORM_FORMATS: {
1896
- readonly regular: readonly ["", "Uppercase", "Lowercase", "First capital", "Title case"];
1897
- readonly number: readonly ["", "0", "0.00", "#,##0", "#,##0.00", "0%", "0.00%"];
1898
- readonly date: readonly ["", "M/d/yyyy", "MM/dd/yyyy", "d/M/yyyy", "dd/MM/yyyy", "yyyy-MM-dd", "d MMMM yyyy", "MMMM d, yyyy"];
1899
- };
1900
-
1901
- /** A legacy text input in the shared paragraph offset space. */
1902
- interface TextFormFieldRange {
1903
- readonly fieldNodeId: string;
1904
- readonly start: number;
1905
- readonly end: number;
1906
- readonly enabled: boolean;
1907
- readonly defaultText: string;
1908
- readonly type: string;
1909
- readonly maxLength: number;
1910
- readonly format: string;
1911
- readonly chromeIds: readonly string[];
1775
+ /**
1776
+ * Where a comment is anchored, as a range.
1777
+ *
1778
+ * `orphaned` records that the file did not give this comment a usable range — a reference with
1779
+ * no range markers, or a start with no end. The comment is still listed, marked orphaned,
1780
+ * rather than dropped: a reviewer's remark disappearing silently is worse than one that says
1781
+ * it lost its text.
1782
+ */
1783
+ interface CommentAnchor {
1784
+ readonly commentId: string;
1785
+ /** Canonical name of the part the range lives in, so a header comment is attributable. */
1786
+ readonly partName: string;
1787
+ readonly start: CommentPosition;
1788
+ readonly end: CommentPosition;
1789
+ readonly orphaned: boolean;
1912
1790
  }
1913
- /** Uses the field parser and offset index; never introduces another inline walk. */
1914
- declare function textFormFieldsOf(paragraph: OoxmlParagraphNode): readonly TextFormFieldRange[];
1915
- /** Options edit for an existing legacy text form. */
1916
- interface SetTextFormFieldDefaultOp {
1917
- readonly op: 'setTextFormFieldDefault';
1918
- /** Regional conventions for new date input; defaults to en-US. */
1919
- readonly locale?: string;
1920
- readonly paragraphId: string;
1921
- readonly fieldNodeId: string;
1922
- readonly text: string;
1923
- readonly options?: TextFormFieldOptions;
1791
+ /** One comment as authored in `word/comments.xml`. */
1792
+ interface CommentRecord {
1793
+ readonly id: string;
1794
+ readonly author: string;
1795
+ readonly initials?: string;
1796
+ readonly date?: string;
1797
+ /** Body paragraphs, as tree nodes, so the surface renders measured text rather than a string. */
1798
+ readonly blocks: readonly OoxmlElement[];
1799
+ /** `w14:paraId` of the last body paragraph — the key thread state is stored under. */
1800
+ readonly paraId?: string;
1801
+ /** `@w16cid:parentId` — the `w:id` of the comment this replies to, when the file names it. */
1802
+ readonly parentCommentId?: string;
1924
1803
  }
1925
- /** Validate and format the existing result when a user finishes filling a field. */
1926
- interface CommitTextFormFieldOp {
1927
- readonly op: 'commitTextFormField';
1928
- /** Regional conventions for new date input; defaults to en-US. */
1929
- readonly locale?: string;
1930
- readonly paragraphId: string;
1931
- readonly fieldNodeId: string;
1804
+ /** Thread state for one comment, read from `commentsExtended.xml`. */
1805
+ interface CommentThreadState {
1806
+ /** `@w15:paraIdParent` — the comment this one replies to, absent for a top-level comment. */
1807
+ readonly parentParaId?: string;
1808
+ readonly done: boolean;
1932
1809
  }
1810
+ /**
1811
+ * Every comment anchor in one story, in document order.
1812
+ *
1813
+ * Overlapping and nested ranges are supported because each anchor is resolved independently —
1814
+ * Word produces both, and a model that assumed ranges nest cleanly would mis-anchor them.
1815
+ *
1816
+ * A start with no matching end anchors to the end of its own paragraph and is reported orphaned
1817
+ * rather than guessed at: extending it to the next end marker would attach a reviewer's remark
1818
+ * to text they never saw.
1819
+ */
1820
+ declare function commentAnchorsOfStory(part: OoxmlPart): CommentAnchor[];
1821
+ /**
1822
+ * The comments in `word/comments.xml`, in authored order.
1823
+ *
1824
+ * Every value here comes from a file an attacker fully controls, so nothing is interpreted:
1825
+ * author, initials and date are carried verbatim for a surface that will set them as TEXT.
1826
+ */
1827
+ declare function commentsOfPart(part: OoxmlPart): CommentRecord[];
1828
+ /**
1829
+ * Thread state by `w14:paraId`, from `commentsExtended.xml`.
1830
+ *
1831
+ * The part being PRESENT is not evidence of threading. `issue-68-large-comments-suggestions.docx`
1832
+ * ships it with 212 entries carrying `@w15:done` and not one `@w15:paraIdParent`, so it records
1833
+ * resolved state for a flat list. Absent parent means top-level, and that is a fact about the
1834
+ * file rather than a default this code chose.
1835
+ */
1836
+ declare function threadStateOfPart(part: OoxmlPart): Map<string, CommentThreadState>;
1837
+ /**
1838
+ * Whether the package holds any `w:comment` record — the cheap gate before a reap.
1839
+ *
1840
+ * Overflow cannot prove the package is comment-free, so it returns true and the reap still
1841
+ * runs rather than skipping cleanup.
1842
+ */
1843
+ declare function hasAnyComment(pkg: OoxmlPackage): boolean;
1933
1844
 
1934
1845
  /** How deep controls may nest before a walk stops descending. Shared by every lane. */
1935
1846
  declare const MAX_CONTENT_CONTROL_NESTING = 32;
@@ -2087,73 +1998,363 @@ interface ContentControlEntry {
2087
1998
  readonly ancestors: readonly OoxmlContentControlNode[];
2088
1999
  }
2089
2000
  /**
2090
- * Every control under a node, in document order, bounded in depth and in count.
2001
+ * Every control under a node, in document order, bounded in depth and in count.
2002
+ *
2003
+ * ONE walk, shared. The nesting bound is the same one layout flattens with, so a control
2004
+ * a lane can address is a control every lane can address — and a file that nests past it
2005
+ * keeps its content in the tree (the serializer never stops) while no walk recurses
2006
+ * further.
2007
+ */
2008
+ declare function contentControlsIn(root: OoxmlNode, options?: {
2009
+ readonly maxDepth?: number;
2010
+ readonly limit?: number;
2011
+ }): readonly ContentControlEntry[];
2012
+ /** Find one control by canonical node id, with the same bounded walk. */
2013
+ declare function findContentControl(root: OoxmlNode, nodeId: string): ContentControlEntry | null;
2014
+ /**
2015
+ * The plain text a control's content holds, in reading order.
2016
+ *
2017
+ * `w:delText` is excluded: struck text is not the control's value, and a dropdown whose
2018
+ * old item is still present as a tracked deletion would otherwise report both.
2019
+ */
2020
+ declare function contentControlTextOf(control: OoxmlNode): string;
2021
+ /**
2022
+ * Resolve the lock a position inherits from the controls enclosing it.
2023
+ *
2024
+ * CONSERVATIVE, because a template that says a field cannot be edited and sits inside a
2025
+ * section that says it cannot be removed means both. Each half of `ST_Lock` is taken
2026
+ * independently and the strongest wins, so an unlocked control inside a `contentLocked`
2027
+ * one is still content-locked — a nested control cannot grant a permission its parent
2028
+ * withheld, which is the only reading under which a lock is a lock.
2029
+ */
2030
+ declare function resolveContentControlLock(chain: readonly ContentControlLock[]): ContentControlLock;
2031
+ /** Whether a resolved lock forbids editing the content it covers. */
2032
+ declare function lockForbidsEdit(lock: ContentControlLock): boolean;
2033
+ /** Whether a resolved lock forbids removing the control itself. */
2034
+ declare function lockForbidsRemoval(lock: ContentControlLock): boolean;
2035
+ /**
2036
+ * `CT_SdtPr`'s declared child order (§17.5.2.38), followed by the type choice.
2037
+ *
2038
+ * Serialization re-emits children in tree order, so the ONLY way a write keeps the
2039
+ * sequence valid is to place the child it authors at its schema position — which is what
2040
+ * {@link orderedContentControlProperties} does.
2041
+ */
2042
+ declare const CONTENT_CONTROL_PROPERTY_ORDER: readonly string[];
2043
+ /**
2044
+ * Rebuild a `w:sdtPr`'s children in schema order.
2045
+ *
2046
+ * Modelled children sort to their declared position and the type element follows them,
2047
+ * as the sequence requires. Everything else — a `w15:repeatingSection`, a vendor
2048
+ * extension, the `w14:checkbox` that is not part of the ECMA-376 choice — keeps the order
2049
+ * it was authored in and follows the modelled block, so a write that touches one property
2050
+ * neither drops nor reorders anything it does not name.
2051
+ */
2052
+ declare function orderedContentControlProperties(children: readonly OoxmlNode[]): readonly OoxmlNode[];
2053
+ /**
2054
+ * The next `w:id` to write.
2055
+ *
2056
+ * Solo: one past the document's own maximum. Never a clock, a timestamp, a random source
2057
+ * or a hash: those collide with ids already in the file and produce values Word rejects.
2058
+ * Null when the document already reaches the signed 32-bit bound, so the caller refuses
2059
+ * rather than wrapping into a negative id. Hostile or out-of-range existing values are
2060
+ * ignored for seeding rather than counted past.
2061
+ *
2062
+ * When a collaboration actor is bound (explicit argument or the open store transaction),
2063
+ * the next id is the next unused value in that actor's stripe. Two peers inserting a
2064
+ * generic content control — including a custom node authored as `w:sdt` — from the same
2065
+ * snapshot then cannot share a `w:id`.
2066
+ */
2067
+ declare function allocateContentControlId(root: OoxmlNode, actorId?: string): number | null;
2068
+
2069
+ /** A position in the model offset space of one story. */
2070
+ interface ReviewPosition {
2071
+ readonly paragraphId: string;
2072
+ readonly offset: number;
2073
+ }
2074
+ /** Where an item is anchored: a range in one story. */
2075
+ interface ReviewRange {
2076
+ readonly partName: string;
2077
+ readonly start: ReviewPosition;
2078
+ readonly end: ReviewPosition;
2079
+ }
2080
+ /**
2081
+ * What kind of decision a revision card represents.
2082
+ *
2083
+ * Wider than the four content wrappers, because a reviewer has to be shown every pending
2084
+ * decision, including the ones that decorate no characters. A card the surface cannot show is
2085
+ * a change the reviewer never learns about — and `acceptAllRevisions` refuses if ANY revision
2086
+ * in the document is one the engine cannot resolve, so an invisible one makes Accept All fail
2087
+ * for a reason nothing on screen explains.
2088
+ */
2089
+ type ReviewRevisionKind = 'insert' | 'delete'
2090
+ /**
2091
+ * A deletion and an insertion that are one edit: text typed over a selection.
2092
+ *
2093
+ * Word shows these as a single `Replaced "x" with "y"` card, and resolving one half
2094
+ * without the other is never what the reviewer meant — accepting the deletion alone
2095
+ * leaves the replacement text unproposed, rejecting it alone leaves both.
2096
+ */
2097
+ | 'replace' | 'moveFrom' | 'moveTo'
2098
+ /** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
2099
+ | 'format'
2100
+ /** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
2101
+ | 'paragraphMark'
2102
+ /** A row, cell, section or grid revision. Supported row revisions are resolvable. */
2103
+ | 'structural';
2104
+ /**
2105
+ * One tracked change as a review card.
2106
+ *
2107
+ * Keyed per DECISION rather than per site: a revision spanning three ranges is one card, because
2108
+ * accepting it accepts all three.
2109
+ */
2110
+ interface ReviewRevisionItem {
2111
+ readonly kind: 'revision';
2112
+ /** Stable across renders and unique per DECISION, not per site. */
2113
+ readonly id: string;
2114
+ /** The payload `acceptRevision` / `rejectRevision` take. */
2115
+ readonly address: RevisionAddress;
2116
+ /**
2117
+ * EVERY address this decision covers, `address` first.
2118
+ *
2119
+ * More than one only for a replacement, whose halves a foreign editor may have written
2120
+ * as two independent revisions. Accept and reject walk all of them in one transaction:
2121
+ * resolving one half and leaving the other is a state no reviewer asked for.
2122
+ */
2123
+ readonly addresses: readonly RevisionAddress[];
2124
+ /** The words a replacement removes. Empty for every other kind. */
2125
+ readonly replacedText: string;
2126
+ readonly revisionKind: ReviewRevisionKind;
2127
+ /** OOXML property-change element, used to resolve independently numbered formatting kinds. */
2128
+ readonly formattingKind?: string;
2129
+ /** Changed direct formatting values, ready for localized review summaries. */
2130
+ readonly formattingChanges?: readonly {
2131
+ readonly property: 'bold' | 'italic' | 'underline' | 'strike' | 'fontFamily' | 'fontSize' | 'color' | 'alignment' | 'leftIndent' | 'rightIndent' | 'firstLineIndent' | 'hangingIndent' | 'spaceBefore' | 'spaceAfter';
2132
+ /** New direct value; null means inherit. Sizes and distances are in points. */
2133
+ readonly value: string | null;
2134
+ }[];
2135
+ /** Newly applied proofing language codes in a tracked formatting change. */
2136
+ readonly formattingLanguages?: readonly string[];
2137
+ /**
2138
+ * WHICH decision a `paragraphMark` records, absent for every other kind.
2139
+ *
2140
+ * `EG_ParaRPrTrackChanges` is `ins? del? moveFrom? moveTo?`, and the four say opposite
2141
+ * things about one break. Without this a card called a deleted break an inserted one, which
2142
+ * is the reverse of what Accept on that card does.
2143
+ */
2144
+ readonly markDirection?: 'insert' | 'delete' | 'moveFrom' | 'moveTo';
2145
+ readonly author: string;
2146
+ readonly date?: string;
2147
+ /** Text the revision covers, for the card summary. Empty for changes with no characters. */
2148
+ readonly text: string;
2149
+ /** Every site this decision touches, in document order. */
2150
+ readonly ranges: readonly ReviewRange[];
2151
+ /**
2152
+ * How deeply this change is NESTED inside other changes, 0 for an unenclosed one.
2153
+ *
2154
+ * `w:ins` wrapping `w:del` is content one reviewer added and another struck. Both stay
2155
+ * pending, so both are cards, over one identical range — and a range then cannot say which
2156
+ * change a caret is in. Word treats the innermost as the operative one, so it wins the caret
2157
+ * and the change enclosing it stays listed and reachable.
2158
+ */
2159
+ readonly nesting: number;
2160
+ /**
2161
+ * How many leading `ranges` are the STRUCK half of a replacement.
2162
+ *
2163
+ * A replacement's card is one decision but its ranges are two colours — red over what is
2164
+ * going, green over what takes its place. ABSENT when the halves do not split at a single
2165
+ * point, which is what a file recording both under one revision id can produce; a surface
2166
+ * then has no basis for two colours and should paint one neutral band rather than guess.
2167
+ */
2168
+ readonly replacedRangeCount?: number;
2169
+ /**
2170
+ * True when the engine cannot resolve this kind, so accept and reject must not be offered.
2171
+ *
2172
+ * Derived by the DERIVATION rather than from a caller-supplied predicate: the refusal list
2173
+ * is internal, and a surface asked to compute it would have to guess. A card that offers a
2174
+ * button the engine will refuse is worse than one that explains why it cannot.
2175
+ */
2176
+ readonly readOnly: boolean;
2177
+ /** The other half of a move, or the other side of a delete/insert replacement. */
2178
+ readonly pairedWith?: string;
2179
+ /**
2180
+ * Comments answering this change, in document order.
2181
+ *
2182
+ * A reply to a tracked change IS a comment: `w:ins` and `w:del` carry no body, so the text
2183
+ * is written as a comment over the revision's own range and the range is what links them.
2184
+ */
2185
+ readonly replyIds: readonly string[];
2186
+ }
2187
+ /**
2188
+ * One comment as a review card. A reply carries `parentId`; OOXML gives replies no separate
2189
+ * element, so threads are reconstructed from that link.
2190
+ */
2191
+ interface ReviewCommentItem {
2192
+ readonly kind: 'comment';
2193
+ readonly id: string;
2194
+ readonly comment: CommentRecord;
2195
+ readonly range: ReviewRange | null;
2196
+ readonly resolved: boolean;
2197
+ /** The comment this replies to, absent for a top-level comment. */
2198
+ readonly parentId?: string;
2199
+ /** The REVISION this comment answers, when it covers exactly that change's characters. */
2200
+ readonly parentRevisionId?: string;
2201
+ /** Replies to this comment, in document order. Empty for a reply or a childless comment. */
2202
+ readonly replyIds: readonly string[];
2203
+ /** True when the file gave this comment no usable range. */
2204
+ readonly orphaned: boolean;
2205
+ }
2206
+ /**
2207
+ * A card contributed by a recognized custom node (`defineCustomNode` with a `reviewCard`
2208
+ * hook), anchored at the node's range.
2209
+ *
2210
+ * Informational, never resolvable: there is nothing to accept or reject, so the engine
2211
+ * refuses those verbs on it. `title` and `detail` are HOST-authored (the definition's hook
2212
+ * produced them), but `attrs` and `text` originate in a file an attacker controls — a
2213
+ * surface renders every one of these as text, never markup.
2214
+ */
2215
+ interface ReviewCustomItem {
2216
+ readonly kind: 'custom';
2217
+ /** The SDT node's stable id in the canonical tree. */
2218
+ readonly id: string;
2219
+ /** The definition's `name`. */
2220
+ readonly name: string;
2221
+ /** The raw `w:tag` the node was recognized from. Untrusted input. */
2222
+ readonly tag: string;
2223
+ /** Attrs decoded from the tag, after the definition's recognition hook. Untrusted input. */
2224
+ readonly attrs: Readonly<Record<string, string>>;
2225
+ /** The SDT's literal content text. Untrusted input. */
2226
+ readonly text: string;
2227
+ /**
2228
+ * The payload the node's control binds to, after the definition validated it.
2229
+ *
2230
+ * Undefined when the node carries none or the payload did not match — see the pro package's
2231
+ * `RecognizedCustomNode.data`, which this is carried from.
2232
+ */
2233
+ readonly data?: unknown;
2234
+ /**
2235
+ * Whether this node asked for a sidebar card.
2236
+ *
2237
+ * False for a definition with no `reviewCard`: the item exists so the chip's own surfaces can
2238
+ * read `attrs`, `text` and `data` off it, and the rail leaves it out. A surface listing cards
2239
+ * filters on this rather than on an empty `title`.
2240
+ */
2241
+ readonly carded: boolean;
2242
+ /** Card title, from the definition's `reviewCard` hook. Empty when `carded` is false. */
2243
+ readonly title: string;
2244
+ /** Card body, from the definition's `reviewCard` hook. */
2245
+ readonly detail?: string;
2246
+ /**
2247
+ * Glyph for this node in the collapsed rail, as an SVG path in a `0 -960 960 960` viewBox.
2248
+ *
2249
+ * A PATH rather than a rendered node because this item crosses core, which is DOM-free and
2250
+ * React-free — the same reason `title` and `detail` are strings. A host that wants arbitrary
2251
+ * markup overrides the `Markers` part's `icon` instead, which lives in the adapter where JSX
2252
+ * belongs. Absent falls back to the generic custom-node glyph.
2253
+ *
2254
+ * HOST-AUTHORED, never file data: it is interpolated into an SVG `d` attribute, and a path
2255
+ * taken from a document would be attacker-controlled markup.
2256
+ */
2257
+ readonly icon?: string;
2258
+ readonly range: ReviewRange | null;
2259
+ }
2260
+ /**
2261
+ * One pending decision in the review queue: a tracked change, a comment thread, or a pro
2262
+ * custom-node card. Discriminate on `kind`.
2091
2263
  *
2092
- * ONE walk, shared. The nesting bound is the same one layout flattens with, so a control
2093
- * a lane can address is a control every lane can address — and a file that nests past it
2094
- * keeps its content in the tree (the serializer never stops) while no walk recurses
2095
- * further.
2264
+ * The store's own derivation (`collectReviewItems`) only ever produces the first two; the
2265
+ * `kind: 'custom'` card is contributed by the pro review module, which recognizes the node.
2096
2266
  */
2097
- declare function contentControlsIn(root: OoxmlNode, options?: {
2098
- readonly maxDepth?: number;
2099
- readonly limit?: number;
2100
- }): readonly ContentControlEntry[];
2101
- /** Find one control by canonical node id, with the same bounded walk. */
2102
- declare function findContentControl(root: OoxmlNode, nodeId: string): ContentControlEntry | null;
2267
+ type ReviewItem = ReviewRevisionItem | ReviewCommentItem | ReviewCustomItem;
2268
+ /** What the review queue derivation reads: one story part plus its comment parts. */
2269
+ interface ReviewModelInput {
2270
+ /** The story the ranges live in — the main document, a header, a note. */
2271
+ readonly storyPart: OoxmlPart;
2272
+ /**
2273
+ * Header/footer story parts, in section order. Their revisions and comment anchors join
2274
+ * the queue: a tracked change in a header is a pending decision like any other, and a
2275
+ * queue that only walked the body silently hid it from the rail AND from Accept All.
2276
+ */
2277
+ readonly furnitureParts?: readonly OoxmlPart[] | undefined;
2278
+ /** `word/comments.xml`, absent when the package has none. */
2279
+ readonly commentsPart?: OoxmlPart | undefined;
2280
+ /** `word/commentsExtended.xml`, absent when the package has none. */
2281
+ readonly commentsExtendedPart?: OoxmlPart | undefined;
2282
+ /**
2283
+ * Custom node definitions from the module registry, forwarded OPAQUELY.
2284
+ *
2285
+ * Core carries them the way the registry does — as unknowns — so the definition shape
2286
+ * stays a capability-package concern. The pro derivation narrows them and contributes
2287
+ * `kind: 'custom'` cards for definitions that opted in.
2288
+ */
2289
+ readonly customNodes?: readonly unknown[] | undefined;
2290
+ /**
2291
+ * Where a capability package reports a node it could not read. Supplied per editor, so a page
2292
+ * with two of them keeps their diagnostics apart.
2293
+ */
2294
+ readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
2295
+ /**
2296
+ * The payload each of the story's controls binds to, keyed by the control's node id.
2297
+ *
2298
+ * Resolved by the ENGINE and handed over, because a payload lives in a customXml data part
2299
+ * and a derivation that only receives story parts has no way to reach one. Untrusted file
2300
+ * input on both members; a capability package validates it against whatever shape it
2301
+ * declared before handing it to a host.
2302
+ */
2303
+ readonly customNodePayloads?: ReadonlyMap<string, {
2304
+ readonly nodeId: string;
2305
+ readonly label: string;
2306
+ readonly data: string;
2307
+ }> | undefined;
2308
+ }
2309
+ /** The stable key a surface uses for the active item and for a React list. */
2310
+ declare function reviewItemKey(item: ReviewItem): string;
2311
+ /** Every range a decision touches. One card can cover several, in different paragraphs. */
2312
+ declare function reviewItemRanges(item: ReviewItem): readonly ReviewRange[];
2313
+ /** The first range of an item, in authored order, or null when it has none. */
2314
+ declare function firstReviewRange(item: ReviewItem): ReviewRange | null;
2103
2315
  /**
2104
- * The plain text a control's content holds, in reading order.
2316
+ * A single comparable number for document order.
2105
2317
  *
2106
- * `w:delText` is excluded: struck text is not the control's value, and a dropdown whose
2107
- * old item is still present as a tracked deletion would otherwise report both.
2318
+ * Paragraph index dominates offset, so a revision spanning paragraphs still sorts by where it
2319
+ * STARTS. An item with no resolvable range sorts last rather than to position zero, which is
2320
+ * where an orphan used to land — tearing an orphaned reply out of its own thread.
2108
2321
  */
2109
- declare function contentControlTextOf(control: OoxmlNode): string;
2322
+ declare function reviewItemPositionRank(item: ReviewItem, order: ReadonlyMap<string, number>): number;
2110
2323
  /**
2111
- * Resolve the lock a position inherits from the controls enclosing it.
2324
+ * Every item covering a position, innermost first.
2112
2325
  *
2113
- * CONSERVATIVE, because a template that says a field cannot be edited and sits inside a
2114
- * section that says it cannot be removed means both. Each half of `ST_Lock` is taken
2115
- * independently and the strongest wins, so an unlocked control inside a `contentLocked`
2116
- * one is still content-locked — a nested control cannot grant a permission its parent
2117
- * withheld, which is the only reading under which a lock is a lock.
2326
+ * Returning the whole stack rather than one winner is what lets a surface offer cycling, a
2327
+ * stacked card, or a "1 of 3" affordance. A comment wrapping a revision used to be unreachable
2328
+ * because only the tightest range was ever returned.
2118
2329
  */
2119
- declare function resolveContentControlLock(chain: readonly ContentControlLock[]): ContentControlLock;
2120
- /** Whether a resolved lock forbids editing the content it covers. */
2121
- declare function lockForbidsEdit(lock: ContentControlLock): boolean;
2122
- /** Whether a resolved lock forbids removing the control itself. */
2123
- declare function lockForbidsRemoval(lock: ContentControlLock): boolean;
2330
+ declare function reviewItemsAt(items: readonly ReviewItem[], position: ReviewPosition, order: ReadonlyMap<string, number>): ReviewItem[];
2124
2331
  /**
2125
- * `CT_SdtPr`'s declared child order (§17.5.2.38), followed by the type choice.
2332
+ * The item the caret is in, or null.
2126
2333
  *
2127
- * Serialization re-emits children in tree order, so the ONLY way a write keeps the
2128
- * sequence valid is to place the child it authors at its schema position — which is what
2129
- * {@link orderedContentControlProperties} does.
2130
- */
2131
- declare const CONTENT_CONTROL_PROPERTY_ORDER: readonly string[];
2132
- /**
2133
- * Rebuild a `w:sdtPr`'s children in schema order.
2334
+ * A resolved comment never activates: a settled thread must not reopen itself as the reviewer
2335
+ * types near it.
2134
2336
  *
2135
- * Modelled children sort to their declared position and the type element follows them,
2136
- * as the sequence requires. Everything else — a `w15:repeatingSection`, a vendor
2137
- * extension, the `w14:checkbox` that is not part of the ECMA-376 choice — keeps the order
2138
- * it was authored in and follows the modelled block, so a write that touches one property
2139
- * neither drops nor reorders anything it does not name.
2337
+ * A REPLY resolves to the thread it belongs to. A reply is anchored over its parent's range,
2338
+ * so both cover the caret — and the reply, being newer, wins the innermost test. It is not a
2339
+ * card of its own (it renders inside its parent's), so the thread would have gone active with
2340
+ * nothing on screen showing it: the reply box vanished from a comment the moment somebody
2341
+ * replied to it.
2140
2342
  */
2141
- declare function orderedContentControlProperties(children: readonly OoxmlNode[]): readonly OoxmlNode[];
2343
+ declare function activeReviewItem(items: readonly ReviewItem[], position: ReviewPosition, order: ReadonlyMap<string, number>): ReviewItem | null;
2142
2344
  /**
2143
- * The next `w:id` to write.
2345
+ * Walk a reply up to the card that heads its thread. Guarded against a cyclic file.
2144
2346
  *
2145
- * Solo: one past the document's own maximum. Never a clock, a timestamp, a random source
2146
- * or a hash: those collide with ids already in the file and produce values Word rejects.
2147
- * Null when the document already reaches the signed 32-bit bound, so the caller refuses
2148
- * rather than wrapping into a negative id. Hostile or out-of-range existing values are
2149
- * ignored for seeding rather than counted past.
2347
+ * The head is not always a comment. A reply to a tracked change renders inside the REVISION's
2348
+ * card, so resolving it to itself opened an item nothing on screen was drawing — the reply box
2349
+ * vanished the moment somebody answered a change.
2150
2350
  *
2151
- * When a collaboration actor is bound (explicit argument or the open store transaction),
2152
- * the next id is the next unused value in that actor's stripe. Two peers inserting a
2153
- * generic content control — including a custom node authored as `w:sdt` — from the same
2154
- * snapshot then cannot share a `w:id`.
2351
+ * EXPORTED because the paginated surface answers "which card is open" itself, against its own
2352
+ * dismissed-key state, rather than through {@link activeReviewItem}. Two copies of the
2353
+ * innermost-wins rule was survivable while a reply could only be a comment — the parent came
2354
+ * first in `comments.xml` order and won the tie by accident. It stopped being survivable the
2355
+ * moment a reply could answer a revision, which outranks it outright.
2155
2356
  */
2156
- declare function allocateContentControlId(root: OoxmlNode, actorId?: string): number | null;
2357
+ declare function reviewThreadRootOf(items: readonly ReviewItem[], comment: ReviewCommentItem): ReviewItem;
2157
2358
 
2158
2359
  /** The value a control accepts, by what kind of control it is. */
2159
2360
  type ContentControlValueInput = {
@@ -2182,6 +2383,32 @@ declare const INSERTABLE_CONTENT_CONTROL_TYPES: readonly ["richText", "plainText
2182
2383
  */
2183
2384
  type InsertableContentControlKind = (typeof INSERTABLE_CONTENT_CONTROL_TYPES)[number];
2184
2385
 
2386
+ /** A canonical review decision. Keys are valid only in the open document. @public */
2387
+ interface RevisionBatchEntry {
2388
+ readonly key: string;
2389
+ readonly author: string;
2390
+ readonly partName: string;
2391
+ readonly revisionKind: ReviewRevisionItem['revisionKind'];
2392
+ }
2393
+ /** Why a requested decision remains pending. @public */
2394
+ type RevisionBatchSkipReason = 'unsupported-revision' | 'incomplete-group' | 'unknown-revision';
2395
+ /** Outcome of one selected-set decision. Counts refer to review decisions, not XML markers. @public */
2396
+ interface RevisionBatchResult {
2397
+ readonly resolved: readonly RevisionBatchEntry[];
2398
+ readonly skipped: readonly {
2399
+ readonly key: string;
2400
+ readonly reason: RevisionBatchSkipReason;
2401
+ readonly revision?: RevisionBatchEntry;
2402
+ }[];
2403
+ /** All pending decisions in the addressed scope, including excluded and unsupported changes. */
2404
+ readonly remaining: number;
2405
+ }
2406
+ /** @internal Pure preflight; callers commit its operations through their normal write guards. */
2407
+ declare function planRevisionBatch(part: OoxmlPart, action: 'accept' | 'reject', keys?: readonly string[], scopeRoot?: OoxmlNode): {
2408
+ ops: readonly TreeDocOp[];
2409
+ result: RevisionBatchResult;
2410
+ };
2411
+
2185
2412
  /** Allowlisted OOXML table border line styles — store/layout authority. */
2186
2413
  declare const TABLE_BORDER_STYLES: readonly ["single", "dashed", "dotted", "double", "triple", "thick"];
2187
2414
  /**
@@ -2193,6 +2420,570 @@ declare const TABLE_BORDER_STYLES: readonly ["single", "dashed", "dotted", "doub
2193
2420
  */
2194
2421
  type TableBorderStyle = (typeof TABLE_BORDER_STYLES)[number];
2195
2422
 
2423
+ /**
2424
+ * Shared types for the `@docx-editor.dev/core` contract. Type-only, zero runtime.
2425
+ *
2426
+ * `@docx-editor.dev/core/contracts/types` re-exports this module verbatim, through
2427
+ * `types-barrel.ts`. There is no `@docx-editor.dev/core/types` subpath.
2428
+ */
2429
+ /** Which paragraph-level reads the selection disagrees about. @public */
2430
+ interface ParagraphDisagreements {
2431
+ readonly alignment: boolean;
2432
+ readonly spaceBeforePt: boolean;
2433
+ readonly spaceAfterPt: boolean;
2434
+ readonly lineSpacing: boolean;
2435
+ readonly tabStops: boolean;
2436
+ }
2437
+ /**
2438
+ * The five paragraph flags a Paragraph dialog shows as checkboxes.
2439
+ *
2440
+ * `contextualSpacing` is Word's "Don't add space between paragraphs of the same style";
2441
+ * the rest are its Pagination block. `null` means the selection disagrees.
2442
+ *
2443
+ * @public
2444
+ */
2445
+ interface ParagraphFlags {
2446
+ readonly contextualSpacing: boolean | null;
2447
+ readonly keepNext: boolean | null;
2448
+ readonly keepLines: boolean | null;
2449
+ readonly widowControl: boolean | null;
2450
+ readonly pageBreakBefore: boolean | null;
2451
+ }
2452
+ /**
2453
+ * Every field of the Paragraph dialog, as `setParagraphFormat` takes it.
2454
+ *
2455
+ * An omitted field is left as authored. `null` REMOVES a setting so the style supplies it
2456
+ * again — not the same as a zero, which blocks the cascade.
2457
+ *
2458
+ * @public
2459
+ */
2460
+ interface ParagraphFormatCommand {
2461
+ alignment?: 'left' | 'center' | 'right' | 'justify';
2462
+ spaceBeforePt?: number | null;
2463
+ spaceAfterPt?: number | null;
2464
+ lineSpacing?: {
2465
+ rule: 'multiple' | 'exact' | 'atLeast';
2466
+ value: number;
2467
+ } | null;
2468
+ indentLeftTwips?: number | null;
2469
+ indentRightTwips?: number | null;
2470
+ /** ONE signed first-line offset: negative is a hanging indent. */
2471
+ indentFirstLineTwips?: number | null;
2472
+ contextualSpacing?: boolean;
2473
+ keepNext?: boolean;
2474
+ keepLines?: boolean;
2475
+ widowControl?: boolean;
2476
+ pageBreakBefore?: boolean;
2477
+ /**
2478
+ * Replace the paragraph's custom tab stops. An empty list CLEARS them, which is what
2479
+ * "Clear All" does; omit the field to leave them as authored.
2480
+ */
2481
+ tabStops?: readonly ParagraphTabStop[];
2482
+ }
2483
+ /** One custom tab stop, as a command states it. @public */
2484
+ interface ParagraphTabStop {
2485
+ readonly positionTwips: number;
2486
+ readonly alignment: 'left' | 'center' | 'right' | 'decimal' | 'bar';
2487
+ readonly leader?: 'none' | 'dot' | 'hyphen' | 'underscore' | 'heavy' | 'middleDot';
2488
+ }
2489
+ /** Ownership token for one retained selection highlight. @public */
2490
+ type SelectionPin = symbol;
2491
+ /**
2492
+ * The LLM- and JSON-facing address for a piece of a document.
2493
+ *
2494
+ * `paraId` is the 8-hex `w14:paraId`, matched case-insensitively. `search` is a
2495
+ * phrase that must match EXACTLY ONCE inside that paragraph; ambiguous or
2496
+ * missing matches fail with `'ambiguous'` / `'notFound'` rather than falling
2497
+ * back to first-match.
2498
+ *
2499
+ * Offset-based addressing was tried and abandoned: an agent cannot compute a
2500
+ * character offset it has not seen, and offsets do not survive concurrent
2501
+ * edits. Do not reintroduce `{ blockId, offset }`.
2502
+ */
2503
+ interface DocAnchor {
2504
+ paraId: string;
2505
+ search?: string;
2506
+ /** Opt-in disambiguation. Omit to require uniqueness. */
2507
+ occurrence?: number;
2508
+ }
2509
+ /** Structural addressing for content the paraId map cannot reach. */
2510
+ interface DocLocation {
2511
+ container: ContainerRef;
2512
+ /** Block indices, descending into tables and content controls. */
2513
+ path: number[];
2514
+ offset?: number;
2515
+ }
2516
+ /**
2517
+ * Which STORY a location belongs to.
2518
+ *
2519
+ * The body is one container; every header, footer and note is another. A path alone is
2520
+ * ambiguous without it, because block index 0 exists in every story a document has.
2521
+ */
2522
+ type ContainerRef = {
2523
+ part: 'body';
2524
+ } | {
2525
+ part: 'header' | 'footer';
2526
+ rId: string;
2527
+ } | {
2528
+ part: 'footnote' | 'endnote';
2529
+ noteId: number;
2530
+ };
2531
+ /**
2532
+ * Anything an operation can be pointed at: a paragraph-relative {@link DocAnchor}, a structural
2533
+ * {@link DocLocation}, or a {@link DocRange} spanning two of them.
2534
+ */
2535
+ type DocTarget = DocAnchor | DocLocation | DocRange;
2536
+ /** A span between two positions. The endpoints may be addressed either way, independently. */
2537
+ interface DocRange {
2538
+ from: DocAnchor | DocLocation;
2539
+ to: DocAnchor | DocLocation;
2540
+ }
2541
+ /**
2542
+ * Every write returns this rather than `boolean`.
2543
+ *
2544
+ * A bare boolean cannot distinguish "no-op" from "target not found" from
2545
+ * "content control is locked", and the editor layer already throws eight
2546
+ * distinct ContentControl error classes that a boolean would flatten.
2547
+ */
2548
+ type ExecResult = {
2549
+ ok: true;
2550
+ changed: boolean;
2551
+ revisions?: RevisionBatchResult;
2552
+ history?: HistoryGroupOutcome;
2553
+ } | {
2554
+ ok: false;
2555
+ code: ExecErrorCode;
2556
+ reason: string;
2557
+ target?: DocTarget;
2558
+ revisions?: RevisionBatchResult;
2559
+ };
2560
+ /**
2561
+ * Why a write was refused, as a value to branch on.
2562
+ *
2563
+ * Deliberately finer-grained than a boolean: "no-op", "target not found" and "content control is
2564
+ * locked" are different outcomes, and a caller retrying the first should not retry the third.
2565
+ */
2566
+ type ExecErrorCode = 'notFound' | 'ambiguous' | 'locked' | 'bound' | 'typeMismatch' | 'kindMismatch' | 'outOfBounds' | 'unsupported' | 'invalidArgs';
2567
+ /**
2568
+ * A parsed .docx.
2569
+ *
2570
+ * NOT JSON-round-trippable: it holds `Map`s and `Date`s, plus an internal
2571
+ * side-table of verbatim XML used for lossless round-tripping. Use `toJSON` /
2572
+ * `fromJSON` before sending it over JSON-RPC or handing it to a model.
2573
+ */
2574
+ interface DocxDocument {
2575
+ readonly body: DocumentBody;
2576
+ readonly styles: StyleDefinitions;
2577
+ readonly theme?: Theme;
2578
+ readonly comments: readonly DocComment[];
2579
+ readonly revisions: readonly Revision[];
2580
+ }
2581
+ /** The main story: its blocks in reading order, plus the sections derived from them. */
2582
+ interface DocumentBody {
2583
+ readonly content: readonly Block[];
2584
+ /**
2585
+ * Derived, not stored: recomputed on read from section-break markers and
2586
+ * section inheritance. Never treat it as a spreadable field.
2587
+ */
2588
+ readonly sections: readonly Section[];
2589
+ }
2590
+ /** The JSON-safe projection of a document. */
2591
+ interface DocxDocumentJSON {
2592
+ readonly [key: string]: unknown;
2593
+ }
2594
+ /** One section: the page it lays out on, and the header/footer stories it declares. */
2595
+ interface Section {
2596
+ readonly properties: SectionProperties;
2597
+ readonly headers: HeaderFooterSet;
2598
+ readonly footers: HeaderFooterSet;
2599
+ }
2600
+ /**
2601
+ * A section's three header (or footer) variants, each a relationship id.
2602
+ *
2603
+ * All optional: a variant a section does not declare inherits the previous section's, and one
2604
+ * absent everywhere means the document simply has none.
2605
+ */
2606
+ interface HeaderFooterSet {
2607
+ readonly default?: string;
2608
+ readonly first?: string;
2609
+ readonly even?: string;
2610
+ }
2611
+ /** Anything that can sit at block level in a story. Discriminate on `kind`. */
2612
+ type Block = Paragraph | Table | ContentControl;
2613
+ /** One paragraph: its runs, the style it names, and its list membership. */
2614
+ interface Paragraph {
2615
+ readonly kind: 'paragraph';
2616
+ /** `w14:paraId`. The stable handle `DocAnchor` addresses. */
2617
+ readonly paraId?: string;
2618
+ readonly runs: readonly Run[];
2619
+ readonly styleId?: string;
2620
+ readonly numbering?: NumberingRef;
2621
+ }
2622
+ /** A stretch of text sharing one set of character properties. */
2623
+ interface Run {
2624
+ readonly text: string;
2625
+ readonly formatting?: RunFormatting;
2626
+ /** Set when the run carries a tracked change. Unique only within its part. */
2627
+ readonly revisionId?: number;
2628
+ }
2629
+ /**
2630
+ * Character formatting, and — at selection level — the paragraph properties a toolbar reads
2631
+ * alongside it.
2632
+ *
2633
+ * One type serves both roles so a toolbar reads alignment, style and script state from the same
2634
+ * object as bold and italic. On a {@link Run} the selection-level fields stay absent: a run has
2635
+ * no alignment or paragraph style of its own.
2636
+ */
2637
+ interface RunFormatting {
2638
+ readonly bold?: boolean;
2639
+ readonly italic?: boolean;
2640
+ readonly underline?: boolean;
2641
+ readonly strike?: boolean;
2642
+ readonly color?: ColorValue;
2643
+ readonly highlight?: string;
2644
+ readonly fontFamily?: string;
2645
+ readonly fontSizePt?: number;
2646
+ readonly superscript?: boolean;
2647
+ readonly subscript?: boolean;
2648
+ /** Paragraph alignment at the selection. `both` is OOXML's spelling of justify. */
2649
+ readonly alignment?: 'left' | 'center' | 'right' | 'both';
2650
+ /** Paragraph style id (`w:pStyle`) at the selection. */
2651
+ readonly styleId?: string;
2652
+ /**
2653
+ * Line spacing at the selection, in the unit its rule implies — LINES for `multiple`,
2654
+ * points for `exact` and `atLeast`. The same vocabulary `setLineSpacing` takes, so a
2655
+ * control can show what it reads and send back what it shows. Absent when the
2656
+ * selection's paragraphs disagree or state no line spacing.
2657
+ */
2658
+ readonly lineSpacing?: {
2659
+ readonly rule: 'multiple' | 'exact' | 'atLeast';
2660
+ readonly value: number;
2661
+ };
2662
+ /**
2663
+ * Space above and below the paragraph at the selection, in points.
2664
+ *
2665
+ * The measurement the cascade STATES — `w:docDefaults`, the style chain and direct
2666
+ * formatting resolved together — not the gap the page finally draws. The two differ for a
2667
+ * paragraph carrying `w:beforeAutospacing`, where Word substitutes its own value and
2668
+ * ignores the measurement, and again where two paragraphs collapse their adjacent spacing.
2669
+ * Absent when the selection's paragraphs disagree or no level states it.
2670
+ */
2671
+ readonly spaceBeforePt?: number;
2672
+ readonly spaceAfterPt?: number;
2673
+ /**
2674
+ * The paragraph flags the Paragraph dialog shows as checkboxes.
2675
+ *
2676
+ * Each is `true`, `false`, or `null` when the selection's paragraphs disagree — a
2677
+ * checkbox needs all three. Read through the cascade, so a flag a STYLE sets reads as on,
2678
+ * which is what the box has to show over a paragraph the page is visibly keeping with the
2679
+ * next. Absent on a `Run`, like every other selection-level field here.
2680
+ */
2681
+ readonly paragraphFlags?: ParagraphFlags;
2682
+ /**
2683
+ * Which paragraph-level fields above are absent because the selection DISAGREES, as
2684
+ * opposed to because nothing states them.
2685
+ *
2686
+ * A `null`/absent value alone cannot tell those apart, and both readings have shipped as
2687
+ * bugs: a disagreement rendered as a concrete value is uncorrectable, because the value
2688
+ * that would fix it is the one already on screen; an absent value rendered as "mixed"
2689
+ * tells a single paragraph it disagrees with itself.
2690
+ */
2691
+ readonly disagrees?: ParagraphDisagreements;
2692
+ /**
2693
+ * The paragraph's custom tab stops at the selection, cascade included. Absent when the
2694
+ * selection disagrees or the paragraphs have none.
2695
+ */
2696
+ readonly tabStops?: readonly ParagraphTabStop[];
2697
+ /**
2698
+ * The EFFECTIVE paragraph indent at the selection — cascade and numbering merge
2699
+ * included, so a numbered item that authors no `w:ind` reports the indent its list
2700
+ * definition gives it. Absent when nothing is loaded, or when the selection is inside a
2701
+ * table (see {@link IndentFormatting}).
2702
+ */
2703
+ readonly indent?: IndentFormatting;
2704
+ }
2705
+ /**
2706
+ * Indent at the selection, in twips.
2707
+ *
2708
+ * Unlike every other field here, this does NOT go absent when the selection's paragraphs
2709
+ * disagree. A ruler has to draw its handles somewhere, and Word draws them at the FIRST
2710
+ * selected paragraph's values — Select All is the commonest indent gesture, and hiding the
2711
+ * handles for it would be worse than showing one paragraph's truth. The values are
2712
+ * therefore always the first touched paragraph's, and {@link mixed} records per field
2713
+ * whether the rest agree.
2714
+ *
2715
+ * `firstLine` is ONE SIGNED offset: negative is a hanging indent. OOXML spells it as two
2716
+ * mutually exclusive attributes and this collapses them hanging-wins (§17.3.1.12), which
2717
+ * is the model Word itself keeps.
2718
+ *
2719
+ * Absent inside a table. The value would be correct there, but it is measured from the
2720
+ * cell's content edge while a ruler is drawn against the page's margin, and the ruler does
2721
+ * not know the cell.
2722
+ */
2723
+ interface IndentFormatting {
2724
+ /** Left indent, signed. Negative pulls text into the margin, as Word allows. */
2725
+ readonly left: number;
2726
+ /** Right indent, signed. */
2727
+ readonly right: number;
2728
+ /** First-line offset from {@link left}, signed. Negative is a hanging indent. */
2729
+ readonly firstLine: number;
2730
+ /** Per field, whether the selection's paragraphs disagree about it. */
2731
+ readonly mixed: {
2732
+ readonly left: boolean;
2733
+ readonly right: boolean;
2734
+ readonly firstLine: boolean;
2735
+ };
2736
+ }
2737
+ /** A table: its rows, and the table style they resolve through. */
2738
+ interface Table {
2739
+ readonly kind: 'table';
2740
+ readonly rows: readonly TableRow[];
2741
+ readonly styleId?: string;
2742
+ }
2743
+ /** One table row. Cell count may vary between rows: `colSpan` and vertical merges reshape it. */
2744
+ interface TableRow {
2745
+ readonly cells: readonly TableCell[];
2746
+ }
2747
+ /**
2748
+ * One cell. Its `content` is ordinary blocks, so a cell may hold paragraphs, nested tables and
2749
+ * content controls alike.
2750
+ */
2751
+ interface TableCell {
2752
+ readonly content: readonly Block[];
2753
+ /** Vertical merge span. Absent means 1. */
2754
+ readonly rowSpan?: number;
2755
+ /** `w:gridSpan`. Absent means 1. */
2756
+ readonly colSpan?: number;
2757
+ }
2758
+ /** Structured document tag (`w:sdt`). */
2759
+ interface ContentControl {
2760
+ readonly kind: 'contentControl';
2761
+ readonly id: string;
2762
+ readonly tag?: string;
2763
+ readonly alias?: string;
2764
+ readonly controlType: ContentControlType;
2765
+ readonly locked?: boolean;
2766
+ readonly content: readonly Block[];
2767
+ }
2768
+ /** Which kind of control a `w:sdt` is, and therefore what a value written into it must be. */
2769
+ type ContentControlType = 'richText' | 'plainText' | 'checkbox' | 'dropdown' | 'comboBox' | 'date' | 'picture' | 'buildingBlockGallery' | 'repeatingSection';
2770
+ /**
2771
+ * The control kinds an insertion can author.
2772
+ *
2773
+ * A NARROWING of {@link ContentControlType}, not a separate vocabulary: a kind read off an
2774
+ * existing control can be handed straight back to `insertContentControl`. Three kinds are
2775
+ * absent because an insertion would have to invent what they carry — a checkbox needs its two
2776
+ * declared glyph states, a picture needs an image part, a building block gallery needs a
2777
+ * glossary to list, and a repeating section is a container whose items have their own verbs. Reading still answers the wider type; a document may hold
2778
+ * kinds this cannot create.
2779
+ *
2780
+ * `dropDownList` is the same kind as `dropdown`, spelt as OOXML spells it. Both are accepted,
2781
+ * so a type read off a control can be handed back without translating it — and the OOXML
2782
+ * spelling is the one the automation protocol takes, so a caller who uses both surfaces can
2783
+ * write that one everywhere.
2784
+ */
2785
+ type InsertableContentControlType = Extract<ContentControlType, 'richText' | 'plainText' | 'dropdown' | 'comboBox' | 'date'> | 'dropDownList';
2786
+ /**
2787
+ * Narrows a content-control query. Fields combine with AND; an empty filter matches every
2788
+ * control.
2789
+ */
2790
+ interface ContentControlFilter {
2791
+ readonly tag?: string;
2792
+ readonly alias?: string;
2793
+ readonly controlType?: ContentControlType;
2794
+ }
2795
+ /**
2796
+ * A position in one story: a paragraph and a UTF-16 offset inside it.
2797
+ *
2798
+ * The same offset space the ops and the caret use, so an anchor read here can be handed
2799
+ * straight back to a selection without re-deriving anything.
2800
+ */
2801
+ interface DocAnchorRange {
2802
+ /** Canonical part name of the story the range lives in, e.g. `/word/document.xml`. */
2803
+ readonly part: string;
2804
+ readonly startParagraphId: string;
2805
+ readonly startOffset: number;
2806
+ /** May sit in a later paragraph: the range markers are independent elements. */
2807
+ readonly endParagraphId: string;
2808
+ readonly endOffset: number;
2809
+ }
2810
+ /**
2811
+ * One comment or reply, as `comments.xml` records it.
2812
+ *
2813
+ * A reply is a comment with a `parentId`; OOXML gives replies no separate element, so the thread
2814
+ * is reconstructed from that link rather than from nesting.
2815
+ */
2816
+ interface DocComment {
2817
+ readonly id: string;
2818
+ readonly author: string;
2819
+ /**
2820
+ * OPTIONAL, because `CT_Comment` makes `@w:date` optional and files omit it. A comment
2821
+ * with no date is a comment, not a defect, and fabricating one is a content change.
2822
+ */
2823
+ readonly date?: string;
2824
+ readonly text: string;
2825
+ readonly parentId?: string;
2826
+ readonly resolved?: boolean;
2827
+ /**
2828
+ * Where the comment is anchored, absent when the file gave it no usable range.
2829
+ *
2830
+ * A comment lives in `comments.xml` and is placed by markers in a STORY, so the story is
2831
+ * part of the address: a comment anchored in a header belongs to a part the body never saw.
2832
+ */
2833
+ readonly anchor?: DocAnchorRange;
2834
+ /**
2835
+ * True when the file gave this comment no usable range — a reference with no markers, or a
2836
+ * start with no end. Reported rather than dropped: a reviewer's remark vanishing silently
2837
+ * is worse than one that says it lost its text.
2838
+ */
2839
+ readonly orphaned?: boolean;
2840
+ }
2841
+ /**
2842
+ * What kind of decision a revision represents.
2843
+ *
2844
+ * Wider than insert/delete/format, and it has to be. `w:moveFrom`/`w:moveTo` are not a
2845
+ * deletion and an insertion — resolving one half alone duplicates or loses the content;
2846
+ * `w:pPr/w:rPr/w:ins|w:del` decorates no characters at all and merges paragraphs when
2847
+ * resolved; a row or cell revision is structural. A reviewer shown only three kinds is a
2848
+ * reviewer who never learns about the rest.
2849
+ */
2850
+ type RevisionType = 'insert' | 'delete'
2851
+ /** A deletion and an insertion that are one edit: text typed over a selection. */
2852
+ | 'replace' | 'moveFrom' | 'moveTo'
2853
+ /** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
2854
+ | 'format'
2855
+ /** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
2856
+ | 'paragraphMark'
2857
+ /** A row, cell, section or grid revision. */
2858
+ | 'structural';
2859
+ /**
2860
+ * One tracked change.
2861
+ *
2862
+ * Addressing needs BOTH `id` and `part`: `@w:id` is unique only within a part, so an id alone
2863
+ * names two revisions in any package that has a header or a comments part.
2864
+ */
2865
+ interface Revision {
2866
+ /** Numeric, and unique only WITHIN a part. Pair with `part` to address one. */
2867
+ readonly id: number;
2868
+ readonly type: RevisionType;
2869
+ readonly author: string;
2870
+ /**
2871
+ * OPTIONAL. `CT_TrackChange` requires `@w:id` and `@w:author` and makes `@w:date`
2872
+ * optional, and producers that omit it are ordinary. Requiring it here forced either a
2873
+ * fabricated date — a content change — or dropping the revision from the list.
2874
+ */
2875
+ readonly date?: string;
2876
+ /**
2877
+ * REQUIRED, and a canonical PART NAME rather than a three-value enum.
2878
+ *
2879
+ * `@w:id` is unique only within a part, so an address without one names two revisions in a
2880
+ * package that has both. The enum could not express the parts revisions actually occur in:
2881
+ * `header3.xml`, `footer1.xml`, `comments.xml`, and `styles.xml`, which carries
2882
+ * `w:pPrChange` inside style definitions with ids that collide with `document.xml`.
2883
+ */
2884
+ readonly part: string;
2885
+ }
2886
+ /** `w:sectPr`: the page a section lays out on. Twips throughout, as the file stores them. */
2887
+ interface SectionProperties {
2888
+ readonly pageSize: {
2889
+ widthTwips: number;
2890
+ heightTwips: number;
2891
+ };
2892
+ readonly margins: PageMargins;
2893
+ readonly columns?: {
2894
+ count: number;
2895
+ gapTwips: number;
2896
+ };
2897
+ /** `w:titlePg` — whether the section's first page takes the `first` header/footer variant. */
2898
+ readonly titlePage?: boolean;
2899
+ }
2900
+ /** Page margins in twips. */
2901
+ interface PageMargins {
2902
+ readonly topTwips: number;
2903
+ readonly rightTwips: number;
2904
+ readonly bottomTwips: number;
2905
+ readonly leftTwips: number;
2906
+ }
2907
+ /**
2908
+ * `styles.xml`, split by the three style families that address separately.
2909
+ *
2910
+ * Keyed by style ID rather than by the name a reader sees, because the ID is what a paragraph or
2911
+ * run actually references.
2912
+ */
2913
+ interface StyleDefinitions {
2914
+ readonly paragraph: ReadonlyMap<string, StyleDefinition>;
2915
+ readonly character: ReadonlyMap<string, StyleDefinition>;
2916
+ readonly table: ReadonlyMap<string, StyleDefinition>;
2917
+ }
2918
+ /** One style: the ID content references, the name a reader sees, and its inheritance link. */
2919
+ interface StyleDefinition {
2920
+ readonly id: string;
2921
+ readonly name: string;
2922
+ /** `w:basedOn` — the style this one inherits from. Absent at the root of a chain. */
2923
+ readonly basedOn?: string;
2924
+ }
2925
+ /** A paragraph's list membership: which `numbering.xml` definition, and at which level. */
2926
+ interface NumberingRef {
2927
+ readonly numId: string;
2928
+ /** Zero-based. OOXML numbering has nine levels, 0 through 8. */
2929
+ readonly level: number;
2930
+ }
2931
+ /**
2932
+ * A colour as the FILE expresses it, not as a resolved RGB string.
2933
+ *
2934
+ * A theme colour stays a theme reference — slot plus tint or shade — so that changing the theme
2935
+ * repaints the document the way Word does. Flattening to hex at read time would freeze the
2936
+ * resolved value and break that link. `auto` is Word's "let the renderer decide", usually black
2937
+ * on white.
2938
+ */
2939
+ type ColorValue = {
2940
+ readonly kind: 'hex';
2941
+ readonly value: string;
2942
+ } | {
2943
+ readonly kind: 'theme';
2944
+ readonly slot: string;
2945
+ readonly tint?: number;
2946
+ readonly shade?: number;
2947
+ } | {
2948
+ readonly kind: 'auto';
2949
+ };
2950
+ /** `theme1.xml` — what a {@link ColorValue} of kind `theme` resolves against. */
2951
+ interface Theme {
2952
+ readonly colorScheme: ThemeColorScheme;
2953
+ readonly fontScheme?: Record<string, string>;
2954
+ }
2955
+ /** Theme colour slots (`accent1`, `dk1`, `lt2`, …) to hex. */
2956
+ type ThemeColorScheme = Readonly<Record<string, string>>;
2957
+ /** A watermark, which OOXML expresses as either text or an image — never both meaningfully. */
2958
+ interface Watermark {
2959
+ readonly text?: string;
2960
+ readonly imageData?: Uint8Array;
2961
+ }
2962
+ /** A size in EMUs, the unit DrawingML stores extents in. 914400 EMU = 1 inch. */
2963
+ interface Extent {
2964
+ readonly widthEmu: number;
2965
+ readonly heightEmu: number;
2966
+ }
2967
+ /** A font the document names, and whether its bytes travel inside the package. */
2968
+ interface FontDefinition {
2969
+ readonly family: string;
2970
+ readonly embedded: boolean;
2971
+ }
2972
+ /** An axis-aligned rectangle in points, the unit layout works in throughout. */
2973
+ interface Rect {
2974
+ readonly x: number;
2975
+ readonly y: number;
2976
+ readonly width: number;
2977
+ readonly height: number;
2978
+ }
2979
+ /** A position in points. */
2980
+ interface Point {
2981
+ readonly x: number;
2982
+ readonly y: number;
2983
+ }
2984
+ /** What every subscription returns. Calling it twice is safe. */
2985
+ type Unsubscribe = () => void;
2986
+
2196
2987
  /**
2197
2988
  * How a tracked change is addressed: `@w:id`, `@w:author` and `@w:date` together, within a
2198
2989
  * part.
@@ -2373,10 +3164,14 @@ type TreeDocOp = SetFieldCodeOp | {
2373
3164
  * changes made one decision, and one undo should restore all of them.
2374
3165
  */
2375
3166
  readonly op: 'acceptAllRevisions';
3167
+ /** Exact canonical sites selected by bulk preflight. */
3168
+ readonly siteNodeIds?: readonly string[];
2376
3169
  /** Internal shared-notes scope. When present, this must be the canonical id of a note root. */
2377
3170
  readonly scopeRootId?: string;
2378
3171
  } | {
2379
3172
  readonly op: 'rejectAllRevisions';
3173
+ /** Exact canonical sites selected by bulk preflight. */
3174
+ readonly siteNodeIds?: readonly string[];
2380
3175
  /** Internal shared-notes scope. When present, this must be the canonical id of a note root. */
2381
3176
  readonly scopeRootId?: string;
2382
3177
  } | {
@@ -3098,7 +3893,7 @@ type TreeDocOp = SetFieldCodeOp | {
3098
3893
  readonly paragraphId: string;
3099
3894
  readonly pageNumberText: string;
3100
3895
  }[];
3101
- } | SetTextFormFieldDefaultOp | CommitTextFormFieldOp | {
3896
+ } | SetTextFormFieldDefaultOp | CommitTextFormFieldOp | SetLegacyCheckboxOp | SetLegacyDropdownOp | InsertBuildingBlockOp | {
3102
3897
  /**
3103
3898
  * Rewrite recognized fields' cached RESULT runs in place — between the `separate` and
3104
3899
  * `end` fldChars, or a `w:fldSimple`'s content. The instruction is never modified; a
@@ -3262,4 +4057,4 @@ type TreeOpResult = {
3262
4057
  readonly detail?: string;
3263
4058
  };
3264
4059
 
3265
- export { type VectorShapeProjection as $, type AutomationTableMutation as A, type OoxmlFootnotesNode as B, type OoxmlNoteRefNode as C, type DrawingKind as D, type OoxmlNoteReferenceNode as E, type OoxmlSeparatorNode as F, type DrawingTreeDocOp as G, type ImpactClass as H, type ImageWrapTarget as I, type TreeDocColorValue as J, DEFAULT_IMAGE_RESOURCE_LIMITS as K, IMAGE_WRAP_TARGETS as L, TEXT_FORM_FORMATS as M, resolveImageResourceLimits as N, type OoxmlPart as O, type PreservedImageMime as P, resolveSvgIntrinsicSize as Q, type RevisionAddress as R, type SourceCrop as S, type TreeDocOp as T, sniffImageMime as U, type ValidatedImageBytesHandle as V, validateRasterHeader as W, type TableBorderStyle as X, type DrawingAccessibility as Y, type DrawingImageEffects as Z, type DrawingTransform as _, type OoxmlNode as a, type OoxmlContentControlDateFormatNode as a$, type DrawingProjection as a0, type OoxmlDrawingNode as a1, type ContentControlKind as a2, type ContentControlLevel as a3, type ContentControlLock as a4, type ContentControlDataBinding as a5, type VectorShapeComponent as a6, type ResourceLimits as a7, type OoxmlInvariantResult as a8, type RelationshipRecord as a9, type DeleteTextOp as aA, HARD_CEILINGS as aB, HYPERLINK_RELATIONSHIP_TYPE as aC, type HyperlinkKind as aD, type HyperlinkTarget as aE, IMAGE_RELATIONSHIP_TYPE as aF, IMAGE_RESOURCE_HARD_CEILINGS as aG, type ImageRelationshipResolution as aH, type ImageResourceLookup as aI, type IndexResult as aJ, type InsertTextOp as aK, MAX_CONTENT_CONTROLS_PER_PART as aL, MAX_CONTENT_CONTROL_NESTING as aM, MAX_SVG_SNIFF_BYTES as aN, type NameRejection as aO, type NameResult as aP, OFFICE_RELATIONSHIP_NAMESPACE_URI as aQ, OOXML_NODE_IDENTITY_RULES as aR, type OoxmlBodyNode as aS, type OoxmlBookmarkEndNode as aT, type OoxmlBookmarkStartNode as aU, type OoxmlContentControlCalendarNode as aV, type OoxmlContentControlCheckboxNode as aW, type OoxmlContentControlCheckedNode as aX, type OoxmlContentControlCheckedStateNode as aY, type OoxmlContentControlComboBoxNode as aZ, type OoxmlContentControlDataBindingNode as a_, type OoxmlInvariantIssue as aa, type OoxmlHardBreakNode as ab, type OoxmlFldCharNode as ac, type OoxmlFldSimpleNode as ad, type OoxmlInstrTextNode as ae, type OoxmlAttribute as af, type TreeOpResult as ag, ACCEPTED_PARAGRAPH_PROPERTIES as ah, ACCEPTED_RUN_PROPERTIES as ai, CONTENT_CONTROL_ID_MAX as aj, CONTENT_CONTROL_PROPERTY_ORDER as ak, type CommitTextFormFieldOp as al, type ContentControlCheckbox as am, type ContentControlCheckboxState as an, type ContentControlDateFormat as ao, type ContentControlEntry as ap, type ContentControlListItem as aq, type ContentControlProperties as ar, type ContentTypeError as as, type ContentTypeIndex as at, type ContentTypeRecords as au, type CreateImageResourceCacheOptions as av, DEFAULT_LIMITS as aw, DEFAULT_OOXML_PACKAGE_LIMITS as ax, DEFAULT_ZIP_LIMITS as ay, type DefaultRecord as az, type OoxmlPackage as b, contentControlLevelOf as b$, type OoxmlContentControlDateNode as b0, type OoxmlContentControlDropDownListNode as b1, type OoxmlContentControlEndPropertiesNode as b2, type OoxmlContentControlLidNode as b3, type OoxmlContentControlListItemNode as b4, type OoxmlContentControlPropertiesNode as b5, type OoxmlContentControlStoreMappedDataAsNode as b6, type OoxmlContentControlTextNode as b7, type OoxmlContentControlUncheckedStateNode as b8, type OoxmlDocumentNode as b9, TABLE_BORDER_STYLES as bA, type TabStopWrite as bB, type TargetMode as bC, type TextFormFieldOptions as bD, type TextFormFieldRange as bE, type TextFormFieldType as bF, type TreeDocOpKind as bG, type TreeOpEffect as bH, type ValidatedRasterHeader as bI, WML_NAMESPACE_URI as bJ, XMLNS_NAMESPACE_URI as bK, XML_NAMESPACE_URI as bL, type XmlLimits as bM, type XmlNode as bN, type XmlRejection as bO, type XmlResult as bP, type ZipLimits as bQ, type ZipReadResult as bR, type ZipRejection as bS, allocateContentControlId as bT, asciiFold as bU, buildContentTypeIndex as bV, buildRelationshipSet as bW, childElements as bX, contentControlContentChildren as bY, contentControlContentNodeOf as bZ, contentControlEndPropertiesNodeOf as b_, type OoxmlExternalTarget as ba, type OoxmlGenericExtensionAttribute as bb, type OoxmlHyperlinkNode as bc, type OoxmlInvariantIssueCode as bd, type OoxmlKnownNodeAttribute as be, type OoxmlNamespaceBinding as bf, type OoxmlNodeIdentityRules as bg, type OoxmlPackageResult as bh, type OoxmlParagraphPropertiesNode as bi, type OoxmlPartMetadata as bj, type OoxmlReadRejection as bk, type OoxmlReadResult as bl, type OoxmlRunNode as bm, type OoxmlRunPropertiesNode as bn, type OoxmlTabNode as bo, type OoxmlTextElementNode as bp, type OoxmlTextNode as bq, type OoxmlWmlValAttribute as br, type OoxmlXmlSpaceAttribute as bs, type OverrideRecord as bt, type RelationshipError as bu, type RelationshipSetResult as bv, type RelationshipTargetResolver as bw, type ResolveResult as bx, type ResolvedRelationship as by, type SetTextFormFieldDefaultOp as bz, type OoxmlNodeId as c, contentControlPropertiesNodeOf as c0, contentControlPropertiesOf as c1, contentControlTextOf as c2, contentControlsIn as c3, createImageResourceCache as c4, detectDuplicateNames as c5, extensionKey as c6, findContentControl as c7, findElement as c8, flattenContentControls as c9, resolveContentType as cA, resolveImageRelationship as cB, resolveInternalTarget as cC, resolveLimits as cD, resolveRelationship as cE, textContent as cF, textFormFieldsOf as cG, validateExternalTarget as cH, validateGifHeader as cI, validateJpegHeader as cJ, validatePngHeader as cK, withPart as cL, writeOoxmlPackage as cM, writeZip as cN, hasBoundedSvgRoot as ca, hyperlinkAnchorOf as cb, hyperlinkRelationshipIdOf as cc, hyperlinkTargetOf as cd, imageResourceLookupFor as ce, isContentControlContentNode as cf, isContentControlNode as cg, isContentControlWrapper as ch, isContentRevisionKind as ci, isHyperlinkNode as cj, isRangeMarkerKind as ck, isValidMime as cl, liveDrawingReferenceCount as cm, lockForbidsEdit as cn, lockForbidsRemoval as co, normalizePartName as cp, orderedContentControlProperties as cq, parseContentControlId as cr, partNameKey as cs, projectDrawing as ct, readOnOffChild as cu, readOoxmlPackage as cv, readOoxmlPart as cw, readXml as cx, readZip as cy, resolveContentControlLock as cz, type OoxmlGenericElementNode as d, type OoxmlElement as e, type OoxmlPackageLimits as f, type OoxmlPackageRejection as g, type OoxmlProperty as h, type OoxmlContentControlNode as i, type OoxmlContentControlContentNode as j, type RenderableImageMime as k, type TreeOpRejection as l, type DrawingPositionInput as m, type DrawingLocks as n, type ImageResourceState as o, type SupportedImageMime as p, type DrawingHorizontalReferenceFrame as q, type DrawingVerticalReferenceFrame as r, type VectorImageMime as s, type ImageDecodePort as t, type RevisionAttributionInput as u, type ImageResourceLimits as v, type OoxmlParagraphNode as w, type OoxmlNoteNode as x, type OoxmlContinuationSeparatorNode as y, type OoxmlEndnotesNode as z };
4060
+ export { type RevisionBatchSkipReason as $, type IndentFormatting as A, type Block as B, type CommentRecord as C, type DocxDocument as D, type ExecResult as E, type ParagraphFlags as F, type ParagraphTabStop as G, type HeaderFooterSet as H, type InsertableContentControlType as I, type RevisionType as J, type Section as K, type SectionProperties as L, type StyleDefinition as M, type Theme as N, type OoxmlPart as O, type Paragraph as P, type ThemeColorScheme as Q, type ReviewModelInput as R, type StyleDefinitions as S, type Table as T, type OoxmlNodeId as U, type OoxmlGenericElementNode as V, type TreeDocOp as W, type OoxmlPackageLimits as X, type OoxmlPackageRejection as Y, type RevisionBatchEntry as Z, type RevisionBatchResult as _, type ReviewItem as a, type CommentPosition as a$, type OoxmlProperty as a0, type OoxmlElement as a1, type OoxmlContentControlNode as a2, type OoxmlContentControlContentNode as a3, type DrawingProjection as a4, type TreeOpRejection as a5, type AutomationTableMutation as a6, type SourceCrop as a7, type DrawingKind as a8, type ImageWrapTarget as a9, type OoxmlSeparatorNode as aA, type DrawingTreeDocOp as aB, type ImpactClass as aC, type TreeDocColorValue as aD, IMAGE_WRAP_TARGETS as aE, TEXT_FORM_FORMATS as aF, type TableBorderStyle as aG, type DrawingAccessibility as aH, type DrawingImageEffects as aI, type DrawingTransform as aJ, type VectorShapeProjection as aK, type OoxmlDrawingNode as aL, type OoxmlInvariantResult as aM, type OoxmlFldCharNode as aN, type OoxmlFldSimpleNode as aO, type OoxmlInstrTextNode as aP, type OoxmlInvariantIssue as aQ, type TreeOpResult as aR, type RelationshipRecord as aS, type OoxmlHardBreakNode as aT, type OoxmlAttribute as aU, type CommentThreadState as aV, ACCEPTED_PARAGRAPH_PROPERTIES as aW, ACCEPTED_RUN_PROPERTIES as aX, CONTENT_CONTROL_ID_MAX as aY, CONTENT_CONTROL_PROPERTY_ORDER as aZ, type CommentAnchor as a_, type DrawingPositionInput as aa, type DrawingLocks as ab, type ParagraphFormatCommand as ac, type Watermark as ad, type Rect as ae, type SelectionPin as af, type Unsubscribe as ag, type DocxDocumentJSON as ah, type DrawingHorizontalReferenceFrame as ai, type DrawingVerticalReferenceFrame as aj, type FontDefinition as ak, type NumberingRef as al, type PageMargins as am, type ParagraphDisagreements as an, type Point as ao, type Run as ap, type TableCell as aq, type TableRow as ar, type RevisionAttributionInput as as, type OoxmlParagraphNode as at, type OoxmlNoteNode as au, type OoxmlContinuationSeparatorNode as av, type OoxmlEndnotesNode as aw, type OoxmlFootnotesNode as ax, type OoxmlNoteRefNode as ay, type OoxmlNoteReferenceNode as az, type ReviewRevisionItem as b, type OoxmlReadRejection as b$, type CommitTextFormFieldOp as b0, type ContentControlCheckbox as b1, type ContentControlCheckboxState as b2, type ContentControlDataBinding as b3, type ContentControlDateFormat as b4, type ContentControlEntry as b5, type ContentControlKind as b6, type ContentControlLevel as b7, type ContentControlListItem as b8, type ContentControlLock as b9, type OoxmlContentControlCalendarNode as bA, type OoxmlContentControlCheckboxNode as bB, type OoxmlContentControlCheckedNode as bC, type OoxmlContentControlCheckedStateNode as bD, type OoxmlContentControlComboBoxNode as bE, type OoxmlContentControlDataBindingNode as bF, type OoxmlContentControlDateFormatNode as bG, type OoxmlContentControlDateNode as bH, type OoxmlContentControlDropDownListNode as bI, type OoxmlContentControlEndPropertiesNode as bJ, type OoxmlContentControlLidNode as bK, type OoxmlContentControlListItemNode as bL, type OoxmlContentControlPropertiesNode as bM, type OoxmlContentControlStoreMappedDataAsNode as bN, type OoxmlContentControlTextNode as bO, type OoxmlContentControlUncheckedStateNode as bP, type OoxmlDocumentNode as bQ, type OoxmlExternalTarget as bR, type OoxmlGenericExtensionAttribute as bS, type OoxmlHyperlinkNode as bT, type OoxmlInvariantIssueCode as bU, type OoxmlKnownNodeAttribute as bV, type OoxmlNamespaceBinding as bW, type OoxmlNodeIdentityRules as bX, type OoxmlPackageResult as bY, type OoxmlParagraphPropertiesNode as bZ, type OoxmlPartMetadata as b_, type ContentControlProperties as ba, type ContentTypeError as bb, type ContentTypeIndex as bc, type ContentTypeRecords as bd, DEFAULT_OOXML_PACKAGE_LIMITS as be, DEFAULT_ZIP_LIMITS as bf, type DefaultRecord as bg, type DeleteTextOp as bh, HYPERLINK_RELATIONSHIP_TYPE as bi, type HyperlinkKind as bj, type HyperlinkTarget as bk, IMAGE_RELATIONSHIP_TYPE as bl, type ImageRelationshipResolution as bm, type IndexResult as bn, type InsertBuildingBlockOp as bo, type InsertTextOp as bp, type LegacyCheckboxFieldRange as bq, MAX_CONTENT_CONTROLS_PER_PART as br, MAX_CONTENT_CONTROL_NESTING as bs, type NameRejection as bt, type NameResult as bu, OFFICE_RELATIONSHIP_NAMESPACE_URI as bv, OOXML_NODE_IDENTITY_RULES as bw, type OoxmlBodyNode as bx, type OoxmlBookmarkEndNode as by, type OoxmlBookmarkStartNode as bz, type ReviewCommentItem as c, isContentControlWrapper as c$, type OoxmlReadResult as c0, type OoxmlRunNode as c1, type OoxmlRunPropertiesNode as c2, type OoxmlTabNode as c3, type OoxmlTextElementNode as c4, type OoxmlTextNode as c5, type OoxmlWmlValAttribute as c6, type OoxmlXmlSpaceAttribute as c7, type OverrideRecord as c8, type RelationshipError as c9, allocateContentControlId as cA, asciiFold as cB, buildContentTypeIndex as cC, buildRelationshipSet as cD, childElements as cE, commentAnchorsOfStory as cF, commentsOfPart as cG, contentControlContentChildren as cH, contentControlContentNodeOf as cI, contentControlEndPropertiesNodeOf as cJ, contentControlLevelOf as cK, contentControlPropertiesNodeOf as cL, contentControlPropertiesOf as cM, contentControlTextOf as cN, contentControlsIn as cO, detectDuplicateNames as cP, extensionKey as cQ, findContentControl as cR, findElement as cS, firstReviewRange as cT, flattenContentControls as cU, hasAnyComment as cV, hyperlinkAnchorOf as cW, hyperlinkRelationshipIdOf as cX, hyperlinkTargetOf as cY, isContentControlContentNode as cZ, isContentControlNode as c_, type RelationshipSetResult as ca, type RelationshipTargetResolver as cb, type ResolveResult as cc, type ResolvedRelationship as cd, type SetLegacyCheckboxOp as ce, type SetLegacyDropdownOp as cf, type SetTextFormFieldDefaultOp as cg, TABLE_BORDER_STYLES as ch, type TabStopWrite as ci, type TargetMode as cj, type TextFormFieldOptions as ck, type TextFormFieldRange as cl, type TextFormFieldType as cm, type TreeDocOpKind as cn, type TreeOpEffect as co, W15_NAMESPACE_URI as cp, WML_NAMESPACE_URI as cq, XMLNS_NAMESPACE_URI as cr, XML_NAMESPACE_URI as cs, type XmlLimits as ct, type XmlNode as cu, type XmlRejection as cv, type XmlResult as cw, type ZipLimits as cx, type ZipReadResult as cy, type ZipRejection as cz, type ReviewCustomItem as d, isContentRevisionKind as d0, isHyperlinkNode as d1, isRangeMarkerKind as d2, isValidMime as d3, legacyCheckboxFieldsOf as d4, lockForbidsEdit as d5, lockForbidsRemoval as d6, normalizePartName as d7, orderedContentControlProperties as d8, parseContentControlId as d9, reviewItemsAt as dA, reviewThreadRootOf as dB, partNameKey as da, planRevisionBatch as db, projectDrawing as dc, readOnOffChild as dd, readOoxmlPackage as de, readOoxmlPart as df, readXml as dg, readZip as dh, resolveContentControlLock as di, resolveContentType as dj, resolveImageRelationship as dk, resolveInternalTarget as dl, resolveRelationship as dm, reviewItemKey as dn, reviewItemRanges as dp, textContent as dq, textFormFieldsOf as dr, threadStateOfPart as ds, validateExternalTarget as dt, withPart as du, writeOoxmlPackage as dv, writeZip as dw, type VectorShapeComponent as dx, activeReviewItem as dy, reviewItemPositionRank as dz, type ReviewPosition as e, type ReviewRange as f, type ReviewRevisionKind as g, type RevisionAddress as h, type OoxmlNode as i, type OoxmlPackage as j, type ContentControlType as k, type DocTarget as l, type RunFormatting as m, type Extent as n, type ContainerRef as o, type ContentControlFilter as p, type DocRange as q, type Revision as r, type DocComment as s, type ColorValue as t, type ContentControl as u, type DocAnchor as v, type DocAnchorRange as w, type DocLocation as x, type DocumentBody as y, type ExecErrorCode as z };