@docx-editor.dev/core 0.0.1 → 2.0.1

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/LICENSE +201 -0
  2. package/README.md +92 -2
  3. package/THIRD_PARTY_NOTICES.md +18 -0
  4. package/dist/automation.cjs +1 -0
  5. package/dist/automation.d.cts +74 -0
  6. package/dist/automation.d.ts +74 -0
  7. package/dist/automation.js +1 -0
  8. package/dist/binding.cjs +1 -0
  9. package/dist/binding.d.cts +82 -0
  10. package/dist/binding.d.ts +82 -0
  11. package/dist/binding.js +1 -0
  12. package/dist/chunk-5KSCB2OZ.js +2 -0
  13. package/dist/chunk-BSC44TIT.js +5 -0
  14. package/dist/chunk-DLPL5DAG.js +12 -0
  15. package/dist/chunk-DOEIARE2.js +2 -0
  16. package/dist/chunk-G7YCQBZE.cjs +5 -0
  17. package/dist/chunk-HBL3NNH5.cjs +1 -0
  18. package/dist/chunk-HR7K3W6A.js +1 -0
  19. package/dist/chunk-HVAV2JSN.js +11 -0
  20. package/dist/chunk-MYH2HCUJ.cjs +2 -0
  21. package/dist/chunk-NSM75TN6.cjs +1 -0
  22. package/dist/chunk-PHDVKUWZ.js +1 -0
  23. package/dist/chunk-QADYGK5L.cjs +12 -0
  24. package/dist/chunk-REZUWYB7.js +1 -0
  25. package/dist/chunk-RNBHTPW7.js +10 -0
  26. package/dist/chunk-UD2ZXLFI.cjs +2 -0
  27. package/dist/chunk-VYAVK2AH.cjs +1 -0
  28. package/dist/chunk-YUK46A2N.cjs +11 -0
  29. package/dist/chunk-ZMIX42J7.cjs +10 -0
  30. package/dist/chunk-ZT55Q52J.cjs +2 -0
  31. package/dist/chunk-ZUALAR4M.js +2 -0
  32. package/dist/content-control-walk-CbTqHq6O.d.cts +56 -0
  33. package/dist/content-control-walk-D06GijR0.d.ts +56 -0
  34. package/dist/contracts/document.cjs +1 -0
  35. package/dist/contracts/document.d.cts +246 -0
  36. package/dist/contracts/document.d.ts +246 -0
  37. package/dist/contracts/document.js +0 -0
  38. package/dist/contracts/editor.cjs +1 -0
  39. package/dist/contracts/editor.d.cts +11 -0
  40. package/dist/contracts/editor.d.ts +11 -0
  41. package/dist/contracts/editor.js +1 -0
  42. package/dist/contracts/interaction.cjs +1 -0
  43. package/dist/contracts/interaction.d.cts +11 -0
  44. package/dist/contracts/interaction.d.ts +11 -0
  45. package/dist/contracts/interaction.js +0 -0
  46. package/dist/contracts/modules.cjs +1 -0
  47. package/dist/contracts/modules.d.cts +90 -0
  48. package/dist/contracts/modules.d.ts +90 -0
  49. package/dist/contracts/modules.js +1 -0
  50. package/dist/contracts/types.cjs +1 -0
  51. package/dist/contracts/types.d.cts +452 -0
  52. package/dist/contracts/types.d.ts +452 -0
  53. package/dist/contracts/types.js +0 -0
  54. package/dist/editor-C1QRi1v4.d.ts +1671 -0
  55. package/dist/editor-D0UDock4.d.cts +1671 -0
  56. package/dist/editor.cjs +1 -0
  57. package/dist/editor.css +6017 -0
  58. package/dist/editor.d.cts +271 -0
  59. package/dist/editor.d.ts +271 -0
  60. package/dist/editor.js +1 -0
  61. package/dist/hf-references-BdjsQNE_.d.ts +71 -0
  62. package/dist/hf-references-CgEOSw3i.d.cts +71 -0
  63. package/dist/image-resources-BJnTpG66.d.ts +195 -0
  64. package/dist/image-resources-BpIydXtU.d.cts +195 -0
  65. package/dist/index-CrW-IxXt.d.cts +2515 -0
  66. package/dist/index-ZqBEOrTV.d.ts +2515 -0
  67. package/dist/index.cjs +1 -0
  68. package/dist/index.d.cts +22 -0
  69. package/dist/index.d.ts +22 -0
  70. package/dist/index.js +1 -0
  71. package/dist/layout.cjs +1 -0
  72. package/dist/layout.d.cts +2316 -0
  73. package/dist/layout.d.ts +2316 -0
  74. package/dist/layout.js +1 -0
  75. package/dist/note-nodes-BPSTVDMr.d.ts +108 -0
  76. package/dist/note-nodes-C6DLxlvj.d.cts +108 -0
  77. package/dist/note-properties-CnmCoory.d.cts +68 -0
  78. package/dist/note-properties-m75hmP70.d.ts +68 -0
  79. package/dist/ooxml-package-CR5us6ad.d.cts +354 -0
  80. package/dist/ooxml-package-D_CtywTW.d.ts +354 -0
  81. package/dist/ooxml-tree-BU0e3DVi.d.cts +871 -0
  82. package/dist/ooxml-tree-BU0e3DVi.d.ts +871 -0
  83. package/dist/output.cjs +1 -0
  84. package/dist/output.d.cts +158 -0
  85. package/dist/output.d.ts +158 -0
  86. package/dist/output.js +1 -0
  87. package/dist/protocol-CAkOBBGE.d.cts +1201 -0
  88. package/dist/protocol-oxHaWmt4.d.ts +1201 -0
  89. package/dist/review-support-DS8DYX2a.d.cts +326 -0
  90. package/dist/review-support-Fy3vdIea.d.ts +326 -0
  91. package/dist/revision-projection-72ZApe-g.d.cts +84 -0
  92. package/dist/revision-projection-DHAkcD_L.d.ts +84 -0
  93. package/dist/semantic-cell-selection-CZjBSmMv.d.cts +427 -0
  94. package/dist/semantic-cell-selection-DsmHmLJ5.d.ts +427 -0
  95. package/dist/semantic-interaction-D-Dszxrn.d.cts +187 -0
  96. package/dist/semantic-interaction-Dy-dCUFF.d.ts +187 -0
  97. package/dist/semantic-paint-drawings-BA3z9jl8.d.ts +21 -0
  98. package/dist/semantic-paint-drawings-D7qbB0E2.d.cts +21 -0
  99. package/dist/semantic-records-CJR3BvHs.d.cts +1432 -0
  100. package/dist/semantic-records-CWodBJsz.d.ts +1432 -0
  101. package/dist/shaped-measurer-B-TAtcQU.d.ts +613 -0
  102. package/dist/shaped-measurer-CNIT_svZ.d.cts +613 -0
  103. package/dist/store.cjs +1 -0
  104. package/dist/store.d.cts +2247 -0
  105. package/dist/store.d.ts +2247 -0
  106. package/dist/store.js +1 -0
  107. package/dist/tree-op-types-CwOeiaQ8.d.ts +1431 -0
  108. package/dist/tree-op-types-DMiW6nIH.d.cts +1431 -0
  109. package/dist/tree-package-store-D5S7VKs5.d.ts +708 -0
  110. package/dist/tree-package-store-DOKMtCnh.d.cts +708 -0
  111. package/dist/tree-session-CiUel5Kz.d.ts +542 -0
  112. package/dist/tree-session-D47_imvR.d.cts +542 -0
  113. package/dist/tree-store-CxifqwIv.d.cts +273 -0
  114. package/dist/tree-store-hLtjeyWE.d.ts +273 -0
  115. package/package.json +105 -8
  116. package/index.js +0 -1
@@ -0,0 +1,1431 @@
1
+ import { O as OoxmlNode, o as OoxmlDrawingNode, b as OoxmlContentControlNode, d as OoxmlContentControlContentNode, p as OoxmlContentControlEndPropertiesNode, q as OoxmlContentControlPropertiesNode, e as OoxmlPart } from './ooxml-tree-BU0e3DVi.js';
2
+
3
+ /** The relationship namespace `r:id` lives in. */
4
+ declare const OFFICE_RELATIONSHIP_NAMESPACE_URI = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
5
+ /** The `Type` a hyperlink relationship declares. */
6
+ declare const HYPERLINK_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
7
+ /**
8
+ * What a part's relationships answer for one `r:id`: the authored target and whether the
9
+ * package declared it external. `null` for an id the part does not declare — a DANGLING
10
+ * relationship, which is a real thing in real documents.
11
+ */
12
+ type RelationshipTargetResolver = (relationshipId: string) => {
13
+ readonly target: string;
14
+ readonly external: boolean;
15
+ /**
16
+ * The PACKAGE's own verdict on this target (`validateExternalTarget`): whether it is an
17
+ * absolute URI with a safe scheme.
18
+ *
19
+ * Carried separately because `sanitizeHref` cannot answer it. That function is a SCHEME
20
+ * allowlist and deliberately admits relative URLs — the right rule for a value the host
21
+ * authored, and the wrong one for a value a `.docx` did. A file-supplied
22
+ * `Target="/admin/delete-account"` has no scheme to refuse, so it would pass the
23
+ * allowlist and resolve against the EMBEDDING APPLICATION'S origin: a link reading
24
+ * "Company policy" that issues an authenticated same-origin request to whatever host
25
+ * app the editor is mounted in. Absent, a target is treated as unverified.
26
+ */
27
+ readonly sinkSafe?: boolean;
28
+ } | null;
29
+ /**
30
+ * What a hyperlink points at, which decides what activating it may do.
31
+ *
32
+ * The security-relevant split: an `external` link goes through `sanitizeHref` and opens only on
33
+ * explicit user action, while an anchor merely scrolls and never navigates.
34
+ */
35
+ type HyperlinkKind =
36
+ /** `r:id` → a relationship with `TargetMode="External"`. Opens somewhere else. */
37
+ 'external'
38
+ /** `w:anchor` → a bookmark in this document. Scrolls, never navigates. */
39
+ | 'internal'
40
+ /**
41
+ * `r:id` naming a relationship the part does not declare, or one that is not external.
42
+ *
43
+ * The link keeps its runs — the text is never lost twice — but there is nothing to
44
+ * activate, so it paints inert exactly like a refused scheme.
45
+ */
46
+ | 'unresolved';
47
+ /** A resolved hyperlink: its kind, its target, and the tooltip Word shows on hover. */
48
+ interface HyperlinkTarget {
49
+ readonly kind: HyperlinkKind;
50
+ /**
51
+ * The authored target, verbatim: the relationship's `Target` for an `r:id` link, the
52
+ * anchor name for an internal one. Save re-emits from the tree, never from this — it is
53
+ * here so a UI can show what the document actually says.
54
+ */
55
+ readonly authored: string;
56
+ /**
57
+ * The sanitized runtime projection, or `null` when there is nothing safe to navigate to.
58
+ * The ONLY value permitted in a DOM `href`, `window.open`, or a copied link.
59
+ */
60
+ readonly href: string | null;
61
+ /** `w:anchor`, for an internal link. */
62
+ readonly anchor?: string;
63
+ /** `w:tooltip` — Word's hover text; paint puts it on the anchor's `title`. */
64
+ readonly tooltip?: string;
65
+ /** The authored `r:id`, so an edit can rewrite the relationship it names. */
66
+ readonly relationshipId?: string;
67
+ }
68
+ /** Whether a node is a typed `w:hyperlink`. */
69
+ declare function isHyperlinkNode(node: OoxmlNode): boolean;
70
+ /** A typed hyperlink's `w:anchor`, or undefined. */
71
+ declare function hyperlinkAnchorOf(link: OoxmlNode): string | undefined;
72
+ /** A typed hyperlink's `r:id`, or undefined. */
73
+ declare function hyperlinkRelationshipIdOf(link: OoxmlNode): string | undefined;
74
+ /**
75
+ * Read a typed `w:hyperlink` into its target record.
76
+ *
77
+ * `r:id` wins over `w:anchor` when a link carries both, matching Word: the relationship
78
+ * names the document and the anchor names a place inside it, so the pair is a link to a
79
+ * bookmark in ANOTHER file — which this engine will not follow, but whose external half is
80
+ * the part that decides where it points.
81
+ *
82
+ * A link with neither is `unresolved`: it paints its runs and does nothing.
83
+ */
84
+ declare function hyperlinkTargetOf(link: OoxmlNode, resolve: RelationshipTargetResolver): HyperlinkTarget;
85
+
86
+ interface DrawingProjectionLimits {
87
+ readonly maxCompatibilityBranches: number;
88
+ readonly maxVisitedElements: number;
89
+ readonly maxDrawingDepth: number;
90
+ }
91
+ interface DrawingDiagnostic {
92
+ readonly code: 'malformed-drawing' | 'unsupported-graphic' | 'unresolvable-frame' | 'invalid-geometry' | 'resource-refused' | 'wrap-polygon-over-limit' | 'wrap-polygon-malformed';
93
+ readonly nodeId: string;
94
+ readonly detail: string | null;
95
+ }
96
+
97
+ /**
98
+ * Whether a drawing sits in the text flow or is positioned against a frame.
99
+ *
100
+ * The distinction that decides everything downstream: an inline drawing occupies a character
101
+ * position, while an anchored one has offsets relative to a page, margin or column.
102
+ */
103
+ type DrawingKind = 'inline' | 'anchored';
104
+ /** Nine Word wrap menu targets (inline plus eight floating modes). @public */
105
+ type ImageWrapTarget = 'inline' | 'square' | 'squareLeft' | 'squareRight' | 'tight' | 'through' | 'topAndBottom' | 'behind' | 'inFront';
106
+ /** Every text-wrap mode a drawing may be set to, including `inline`. */
107
+ declare const IMAGE_WRAP_TARGETS: readonly ImageWrapTarget[];
108
+ type DrawingWrapElement = 'none' | 'square' | 'tight' | 'through' | 'topAndBottom';
109
+ type DrawingHorizontalReferenceFrame = 'character' | 'column' | 'insideMargin' | 'leftMargin' | 'margin' | 'outsideMargin' | 'page' | 'rightMargin';
110
+ type DrawingVerticalReferenceFrame = 'bottomMargin' | 'insideMargin' | 'line' | 'margin' | 'outsideMargin' | 'page' | 'paragraph' | 'topMargin';
111
+ /** `a:srcRect` — how much of each edge of the source image is cropped away, as fractions. */
112
+ interface SourceCrop {
113
+ readonly left: number;
114
+ readonly top: number;
115
+ readonly right: number;
116
+ readonly bottom: number;
117
+ }
118
+ interface DrawingTransform {
119
+ readonly rotationDegrees: number;
120
+ readonly flipHorizontal: boolean;
121
+ readonly flipVertical: boolean;
122
+ /** Source `a:off` in EMU; defaults to origin when absent. */
123
+ readonly offsetEmu: Readonly<{
124
+ x: number;
125
+ y: number;
126
+ }>;
127
+ /** Source `a:ext` in EMU; zero falls back to `wp:extent` at geometry time. */
128
+ readonly extentEmu: Readonly<{
129
+ cx: number;
130
+ cy: number;
131
+ }>;
132
+ }
133
+ /**
134
+ * What a drawing refuses: selection, movement, resizing, aspect change.
135
+ *
136
+ * Read and honoured rather than advisory — chrome that offered a handle the store will refuse
137
+ * would promise an edit that cannot happen.
138
+ */
139
+ interface DrawingLocks {
140
+ readonly select: boolean;
141
+ readonly move: boolean;
142
+ readonly resize: boolean;
143
+ readonly changeAspect: boolean;
144
+ }
145
+ interface DrawingLocksInput {
146
+ readonly select?: boolean;
147
+ readonly move?: boolean;
148
+ readonly resize?: boolean;
149
+ readonly changeAspect?: boolean;
150
+ }
151
+ /**
152
+ * An anchored drawing's position: offsets, and the frames they are relative to.
153
+ *
154
+ * The relative-to bases matter as much as the offsets. Writing an offset without preserving its
155
+ * base re-anchors the drawing against a different reference and moves it somewhere nobody asked.
156
+ */
157
+ interface DrawingPositionInput {
158
+ /**
159
+ * `'simple'` when `@simplePos="1"`: `horizontalEmu` / `verticalEmu` are authoritative
160
+ * `wp:simplePos` x/y. `'frame'` (default) uses positionH/V relative frames.
161
+ */
162
+ readonly mode?: 'frame' | 'simple';
163
+ readonly horizontalEmu?: number;
164
+ readonly verticalEmu?: number;
165
+ readonly relativeToH?: DrawingHorizontalReferenceFrame;
166
+ readonly relativeToV?: DrawingVerticalReferenceFrame;
167
+ }
168
+ interface DrawingProjection {
169
+ readonly drawingNodeId: string;
170
+ readonly ownerPartName: string;
171
+ readonly kind: DrawingKind;
172
+ readonly relationshipId: string | null;
173
+ readonly docPrId: number | null;
174
+ readonly name: string;
175
+ readonly title: string;
176
+ readonly description: string;
177
+ readonly hyperlinkHref: string | null;
178
+ readonly hidden: boolean;
179
+ readonly extentEmu: Readonly<{
180
+ cx: number;
181
+ cy: number;
182
+ }>;
183
+ readonly effectExtentEmu: Readonly<{
184
+ top: number;
185
+ right: number;
186
+ bottom: number;
187
+ left: number;
188
+ }>;
189
+ readonly inlineDistancesEmu: Readonly<{
190
+ top: number;
191
+ right: number;
192
+ bottom: number;
193
+ left: number;
194
+ }>;
195
+ readonly wrap: ImageWrapTarget;
196
+ readonly wrapGeometry: DrawingWrapProjection | null;
197
+ readonly position: DrawingPositionProjection | null;
198
+ readonly anchor: Readonly<{
199
+ simplePos: boolean;
200
+ relativeHeight: number;
201
+ behindDocument: boolean;
202
+ layoutInCell: boolean;
203
+ allowOverlap: boolean;
204
+ }> | null;
205
+ readonly picture: PictureProjection | null;
206
+ readonly vectorShape: VectorShapeProjection | null;
207
+ readonly locks: DrawingLocks;
208
+ readonly effects: Readonly<{
209
+ grayscale: boolean;
210
+ brightness: number;
211
+ contrast: number;
212
+ }>;
213
+ readonly compatibilityBranchNodeId: string | null;
214
+ readonly diagnostics: readonly DrawingDiagnostic[];
215
+ }
216
+ /**
217
+ * The renderable subset of a `wps:wsp` non-picture graphic: closed polygon subpaths
218
+ * (`a:custGeom` with move/line/close verbs only, or `a:prstGeom prst="rect"`) with a
219
+ * solid sRGB fill and/or stroke. Anything richer (curves, theme fills, text bodies,
220
+ * rotation) projects as `null` and paints the labelled placeholder instead.
221
+ */
222
+ interface VectorShapeProjection {
223
+ /** The drawing extent that frames the subpath coordinate space. */
224
+ readonly extentEmu: Readonly<{
225
+ cx: number;
226
+ cy: number;
227
+ }>;
228
+ /** Closed subpath polygons in extent-EMU space; fill rule is even-odd. */
229
+ readonly subpathsEmu: readonly (readonly Readonly<{
230
+ x: number;
231
+ y: number;
232
+ }>[])[];
233
+ /** Validated 6-digit sRGB hex (no `#`), or null for no fill. */
234
+ readonly fillHex: string | null;
235
+ /** Validated 6-digit sRGB hex (no `#`), or null for no stroke. */
236
+ readonly strokeHex: string | null;
237
+ /** Stroke width in EMU; 0 when absent. */
238
+ readonly strokeWidthEmu: number;
239
+ }
240
+ interface DrawingAccessibility {
241
+ readonly hidden: boolean;
242
+ readonly decorative: boolean;
243
+ readonly label: string | null;
244
+ }
245
+ interface DrawingPositionProjection {
246
+ readonly simplePosition: Readonly<{
247
+ xEmu: number;
248
+ yEmu: number;
249
+ }>;
250
+ readonly horizontal: Readonly<{
251
+ relativeFrom: DrawingHorizontalReferenceFrame;
252
+ align: string | null;
253
+ offsetEmu: number | null;
254
+ }>;
255
+ readonly vertical: Readonly<{
256
+ relativeFrom: DrawingVerticalReferenceFrame;
257
+ align: string | null;
258
+ offsetEmu: number | null;
259
+ }>;
260
+ }
261
+ interface DrawingWrapProjection {
262
+ readonly element: DrawingWrapElement;
263
+ readonly textSide: 'bothSides' | 'left' | 'right' | 'largest';
264
+ readonly distancesEmu: Readonly<{
265
+ top: number;
266
+ right: number;
267
+ bottom: number;
268
+ left: number;
269
+ }>;
270
+ readonly polygon: readonly Readonly<{
271
+ x: number;
272
+ y: number;
273
+ }>[];
274
+ }
275
+ interface PictureProjection {
276
+ readonly embeddedRelationshipId: string | null;
277
+ readonly linkedRelationshipId: string | null;
278
+ readonly crop: SourceCrop;
279
+ readonly fillMode: 'stretch' | 'tile';
280
+ readonly transform: DrawingTransform;
281
+ readonly presetGeometry: string | null;
282
+ }
283
+ /**
284
+ * Project one `w:drawing` into the resolved shape layout and chrome read.
285
+ *
286
+ * Bounded throughout: extents, crops and nesting all come from a file. Returns a projection that
287
+ * reports `hidden` and its locks rather than throwing, so an unusable drawing degrades to
288
+ * something the surface can skip.
289
+ */
290
+ declare function projectDrawing(drawing: OoxmlDrawingNode, context: Readonly<{
291
+ ownerPartName: string;
292
+ supportedMcRequires: ReadonlySet<string>;
293
+ limits: DrawingProjectionLimits;
294
+ namespaceScope?: ReadonlyMap<string, string>;
295
+ resolveRelationship?: RelationshipTargetResolver;
296
+ }>): DrawingProjection | null;
297
+
298
+ /** How deep controls may nest before a walk stops descending. Shared by every lane. */
299
+ declare const MAX_CONTENT_CONTROL_NESTING = 32;
300
+ /** Cap on controls one walk reports, so a hostile file cannot make a read unbounded. */
301
+ declare const MAX_CONTENT_CONTROLS_PER_PART = 10000;
302
+ /** `CT_SdtPr/w:id` is `ST_DecimalNumber`; Word treats it as a signed 32-bit integer. */
303
+ declare const CONTENT_CONTROL_ID_MAX = 2147483647;
304
+ /** `ST_Lock` (§17.5.2.24). An absent `w:lock` is `unlocked`. */
305
+ /**
306
+ * `w:lock` — what a control refuses.
307
+ *
308
+ * `sdtLocked` protects the wrapper, `contentLocked` the text inside it, and `sdtContentLocked`
309
+ * both. A control inside a locked one is locked in effect regardless of its own value.
310
+ */
311
+ type ContentControlLock = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
312
+ /**
313
+ * What kind of control this is.
314
+ *
315
+ * `checkbox` is the Microsoft `w14:checkbox` extension rather than an ECMA-376 type
316
+ * element, and the two are not mutually exclusive with "declares no type": four controls
317
+ * in the comprehensive fixture declare the extension and no `w:`-prefixed type, so a scan
318
+ * that read only the ECMA-376 choice reported them untyped. `untyped` means the control
319
+ * declares neither — a rich-text container, which is what Word treats it as.
320
+ */
321
+ /** Which kind of control a `w:sdt` is, and therefore what a written value must look like. */
322
+ type ContentControlKind = 'richText' | 'plainText' | 'checkbox' | 'dropDownList' | 'comboBox' | 'date' | 'picture' | 'docPartObj' | 'docPartList' | 'group' | 'citation' | 'bibliography' | 'equation' | 'untyped';
323
+ /** One declared option of a dropdown or combo box: its display text and its stored value. */
324
+ interface ContentControlListItem {
325
+ readonly displayText: string;
326
+ readonly value: string;
327
+ }
328
+ /** A date picker's authored format and locale, for rendering and for parsing what it stores. */
329
+ interface ContentControlDateFormat {
330
+ readonly fullDate?: string;
331
+ readonly dateFormat?: string;
332
+ readonly lid?: string;
333
+ readonly storeMappedDataAs?: string;
334
+ readonly calendar?: string;
335
+ }
336
+ /** One of a checkbox's two glyphs: the font and code point it is drawn with. */
337
+ interface ContentControlCheckboxState {
338
+ /** The `w14:val` hex code point of the glyph, exactly as the control declares it. */
339
+ readonly value: string;
340
+ readonly font?: string;
341
+ }
342
+ /**
343
+ * A checkbox's state and the two glyphs it chooses between.
344
+ *
345
+ * Both glyphs matter on a write: setting the value has to update `w14:checked` AND the run's
346
+ * character, or the document's glyph and its recorded state disagree.
347
+ */
348
+ interface ContentControlCheckbox {
349
+ readonly checked: boolean;
350
+ readonly checkedState?: ContentControlCheckboxState;
351
+ readonly uncheckedState?: ContentControlCheckboxState;
352
+ }
353
+ /** `CT_DataBinding` — preserved metadata. Never resolved, never fetched. */
354
+ /** `w:dataBinding` — the custom-XML part and XPath a control's value is bound to. */
355
+ interface ContentControlDataBinding {
356
+ readonly xpath?: string;
357
+ readonly storeItemID?: string;
358
+ readonly prefixMappings?: string;
359
+ }
360
+ /**
361
+ * A control's whole `w:sdtPr`, projected into one typed shape.
362
+ *
363
+ * What every other lane reads instead of walking `localName` strings — which also means a Word
364
+ * re-save that demotes the properties node to generic does not break the projection.
365
+ */
366
+ interface ContentControlProperties {
367
+ readonly type: ContentControlKind;
368
+ readonly alias?: string;
369
+ readonly tag?: string;
370
+ /** `@w:val` of `w:id` when the file declares a parseable one. Never fabricated. */
371
+ readonly id?: number;
372
+ readonly lock: ContentControlLock;
373
+ /** The glossary entry named by `w:placeholder/w:docPart`. Preserved, never loaded. */
374
+ readonly placeholderDocPart?: string;
375
+ readonly temporary: boolean;
376
+ readonly showingPlaceholder: boolean;
377
+ readonly dataBinding?: ContentControlDataBinding;
378
+ readonly label?: string;
379
+ readonly tabIndex?: number;
380
+ /** Items a dropdown or combo box offers. Empty for every other type. */
381
+ readonly listItems: readonly ContentControlListItem[];
382
+ readonly lastValue?: string;
383
+ readonly date?: ContentControlDateFormat;
384
+ readonly multiLine?: boolean;
385
+ readonly checkbox?: ContentControlCheckbox;
386
+ }
387
+ /** Whether a node is a `w:sdt` wrapper. */
388
+ declare function isContentControlNode(node: OoxmlNode): node is OoxmlContentControlNode;
389
+ /** Whether a node is a `w:sdtContent` — the container holding a control's actual content. */
390
+ declare function isContentControlContentNode(node: OoxmlNode): node is OoxmlContentControlContentNode;
391
+ /**
392
+ * A `w:sdt` wrapper, TYPED or DEMOTED.
393
+ *
394
+ * Flattening predates typing and must not stop at a control the reader refused to type: a
395
+ * demoted wrapper still renders its content in place in Word, so a walk that only saw the
396
+ * typed kind would drop every paragraph inside a malformed control out of the story.
397
+ */
398
+ declare function isContentControlWrapper(node: OoxmlNode): boolean;
399
+ /**
400
+ * The children of a wrapper's `w:sdtContent`, typed or demoted, in order.
401
+ *
402
+ * The one place that knows a control's content is reached through an intermediate element,
403
+ * so the four flattening walks (story blocks, layout, header/footer references, list
404
+ * resolution) ask the same question rather than each re-deriving it.
405
+ */
406
+ declare function contentControlContentChildren(wrapper: OoxmlNode): readonly OoxmlNode[];
407
+ /**
408
+ * A container's children with every content-control wrapper flattened away, bounded in depth.
409
+ *
410
+ * ONE unwrap rule, for the places where a control sits between a container and the children that
411
+ * container is defined in terms of. `CT_SdtRow` puts it between `w:tbl` and `w:tr`, `CT_SdtCell`
412
+ * between `w:tr` and `w:tc`, and a walk that filtered on the child's kind dropped the row or cell
413
+ * entirely: not measured, not painted, not addressable. Flattening at the point of the filter
414
+ * means a controlled row is the same row to the grid pass, the pagination pass and the story walk.
415
+ *
416
+ * Returns the SAME array identity when there is nothing to unwrap, so the tables that carry no
417
+ * controls — nearly all of them — allocate nothing and the incremental layout cache still sees
418
+ * its own inputs.
419
+ */
420
+ declare function flattenContentControls(children: readonly OoxmlNode[], maxDepth?: number): readonly OoxmlNode[];
421
+ /** A control's `w:sdtPr`, or null. Matches structurally, so a Word-demoted node still resolves. */
422
+ declare function contentControlPropertiesNodeOf(control: OoxmlNode): OoxmlContentControlPropertiesNode | undefined;
423
+ /** A control's `w:sdtEndPr` — the run properties applied to its closing marker. */
424
+ declare function contentControlEndPropertiesNodeOf(control: OoxmlNode): OoxmlContentControlEndPropertiesNode | undefined;
425
+ /** A control's `w:sdtContent`, or null when the wrapper has none. */
426
+ declare function contentControlContentNodeOf(control: OoxmlNode): OoxmlContentControlContentNode | undefined;
427
+ /** A signed 32-bit `ST_DecimalNumber`, or undefined when the file wrote something else. */
428
+ declare function parseContentControlId(raw: string | undefined): number | undefined;
429
+ /**
430
+ * Read a control's properties.
431
+ *
432
+ * Total: a control with no `w:sdtPr` at all answers the same shape with the defaults an
433
+ * absent property means, so no caller has to branch on the container's existence.
434
+ */
435
+ declare function contentControlPropertiesOf(control: OoxmlNode): ContentControlProperties;
436
+ /** Where a control sits, read off what its content holds. */
437
+ type ContentControlLevel = 'block' | 'inline' | 'row' | 'cell' | 'empty';
438
+ /**
439
+ * How deeply a control is nested inside other controls.
440
+ *
441
+ * Bounded by {@link MAX_CONTENT_CONTROL_NESTING}: nesting depth comes from a file and is a
442
+ * recursion bound.
443
+ */
444
+ declare function contentControlLevelOf(control: OoxmlNode): ContentControlLevel;
445
+ /** One control, plus how deeply it is nested and the controls that enclose it. */
446
+ interface ContentControlEntry {
447
+ readonly node: OoxmlContentControlNode;
448
+ /** 0 for a top-level control; the nesting depth otherwise. */
449
+ readonly depth: number;
450
+ /** Enclosing controls, outermost first. Empty at depth 0. */
451
+ readonly ancestors: readonly OoxmlContentControlNode[];
452
+ }
453
+ /**
454
+ * Every control under a node, in document order, bounded in depth and in count.
455
+ *
456
+ * ONE walk, shared. The nesting bound is the same one layout flattens with, so a control
457
+ * a lane can address is a control every lane can address — and a file that nests past it
458
+ * keeps its content in the tree (the serializer never stops) while no walk recurses
459
+ * further.
460
+ */
461
+ declare function contentControlsIn(root: OoxmlNode, options?: {
462
+ readonly maxDepth?: number;
463
+ readonly limit?: number;
464
+ }): readonly ContentControlEntry[];
465
+ /** Find one control by canonical node id, with the same bounded walk. */
466
+ declare function findContentControl(root: OoxmlNode, nodeId: string): ContentControlEntry | null;
467
+ /**
468
+ * The plain text a control's content holds, in reading order.
469
+ *
470
+ * `w:delText` is excluded: struck text is not the control's value, and a dropdown whose
471
+ * old item is still present as a tracked deletion would otherwise report both.
472
+ */
473
+ declare function contentControlTextOf(control: OoxmlNode): string;
474
+ /**
475
+ * Resolve the lock a position inherits from the controls enclosing it.
476
+ *
477
+ * CONSERVATIVE, because a template that says a field cannot be edited and sits inside a
478
+ * section that says it cannot be removed means both. Each half of `ST_Lock` is taken
479
+ * independently and the strongest wins, so an unlocked control inside a `contentLocked`
480
+ * one is still content-locked — a nested control cannot grant a permission its parent
481
+ * withheld, which is the only reading under which a lock is a lock.
482
+ */
483
+ declare function resolveContentControlLock(chain: readonly ContentControlLock[]): ContentControlLock;
484
+ /** Whether a resolved lock forbids editing the content it covers. */
485
+ declare function lockForbidsEdit(lock: ContentControlLock): boolean;
486
+ /** Whether a resolved lock forbids removing the control itself. */
487
+ declare function lockForbidsRemoval(lock: ContentControlLock): boolean;
488
+ /**
489
+ * `CT_SdtPr`'s declared child order (§17.5.2.38), followed by the type choice.
490
+ *
491
+ * Serialization re-emits children in tree order, so the ONLY way a write keeps the
492
+ * sequence valid is to place the child it authors at its schema position — which is what
493
+ * {@link orderedContentControlProperties} does.
494
+ */
495
+ declare const CONTENT_CONTROL_PROPERTY_ORDER: readonly string[];
496
+ /**
497
+ * Rebuild a `w:sdtPr`'s children in schema order.
498
+ *
499
+ * Modelled children sort to their declared position and the type element follows them,
500
+ * as the sequence requires. Everything else — a `w15:repeatingSection`, a vendor
501
+ * extension, the `w14:checkbox` that is not part of the ECMA-376 choice — keeps the order
502
+ * it was authored in and follows the modelled block, so a write that touches one property
503
+ * neither drops nor reorders anything it does not name.
504
+ */
505
+ declare function orderedContentControlProperties(children: readonly OoxmlNode[]): readonly OoxmlNode[];
506
+ /**
507
+ * The next `w:id` to write, seeded from the document's own maximum plus one.
508
+ *
509
+ * Never a clock, a timestamp, a random source or a hash: those collide with ids already
510
+ * in the file and produce values Word rejects. Null when the document already reaches the
511
+ * signed 32-bit bound, so the caller refuses rather than wrapping into a negative id.
512
+ */
513
+ declare function allocateContentControlId(root: OoxmlNode): number | null;
514
+
515
+ /** The value a control accepts, by what kind of control it is. */
516
+ type ContentControlValueInput = {
517
+ readonly kind: 'text';
518
+ readonly text: string;
519
+ } | {
520
+ readonly kind: 'listItem';
521
+ readonly value: string;
522
+ } | {
523
+ readonly kind: 'checkbox';
524
+ readonly checked: boolean;
525
+ }
526
+ /** A calendar date, `YYYY-MM-DD` or a full ISO-8601 instant. */
527
+ | {
528
+ readonly kind: 'date';
529
+ readonly iso: string;
530
+ };
531
+ /** The control types an insertion may author. Picture and repeating section are deferred. */
532
+ declare const INSERTABLE_CONTENT_CONTROL_TYPES: readonly ["richText", "plainText", "dropDownList", "comboBox", "date"];
533
+ type InsertableContentControlType = (typeof INSERTABLE_CONTENT_CONTROL_TYPES)[number];
534
+
535
+ /** Allowlisted OOXML table border line styles — store/layout authority. */
536
+ declare const TABLE_BORDER_STYLES: readonly ["single", "dashed", "dotted", "double", "triple", "thick"];
537
+ /**
538
+ * One of the border line styles this engine draws.
539
+ *
540
+ * An ALLOWLIST, not the full `ST_Border` enumeration: a file may name any of the seventy-odd
541
+ * OOXML border styles, and anything outside this set falls back rather than being passed through
542
+ * to paint.
543
+ */
544
+ type TableBorderStyle = (typeof TABLE_BORDER_STYLES)[number];
545
+
546
+ /** JSON-safe color input carried on table cell property ops. Theme/auto require a validated literal. */
547
+ /**
548
+ * A colour as an op carries it: a literal, a theme reference, or automatic.
549
+ *
550
+ * Theme references stay references so the document keeps following its theme; flattening one to
551
+ * hex at write time would freeze the resolved value into the file.
552
+ */
553
+ type TreeDocColorValue = {
554
+ readonly kind: 'hex';
555
+ readonly value: string;
556
+ } | {
557
+ readonly kind: 'theme';
558
+ readonly slot: string;
559
+ readonly resolvedHex: string;
560
+ readonly tint?: number;
561
+ readonly shade?: number;
562
+ } | {
563
+ readonly kind: 'auto';
564
+ readonly resolvedHex: string;
565
+ };
566
+ /** Which cell edges a selected-cell border op targets. */
567
+ /** Which edges a border op addresses — the four sides, the interiors, all, or clear. */
568
+ type TableBorderTarget = 'all' | 'outside' | 'inside' | 'none' | 'top' | 'bottom' | 'left' | 'right';
569
+ /** Concrete edge scopes that apply or clear a complete border spec. */
570
+ /** A {@link TableBorderTarget} that draws something — everything except clear. */
571
+ type TableBorderEdgeTarget = Exclude<TableBorderTarget, 'none'>;
572
+ /** Complete border spec for non-`none` selected-cell border scopes. Size is in eighths of a point. */
573
+ /** A complete border spec: style, width and colour. Ops carry all three, never a partial edit. */
574
+ interface TableBorderSpecInput {
575
+ readonly style: TableBorderStyle;
576
+ readonly size: number;
577
+ readonly color: TreeDocColorValue;
578
+ }
579
+ /**
580
+ * The accepted RUN property boundary (design D8), as the OOXML element names that carry it.
581
+ *
582
+ * An explicit allowlist rather than "any `w:rPr` child": a property outside D8 has no
583
+ * resolver, no layout behavior and no support claim, so accepting it here would let an
584
+ * operation assert support the engine does not have. Unknown properties still ROUND-TRIP —
585
+ * they are generic nodes in the tree — they simply cannot be authored by an op.
586
+ */
587
+ declare const ACCEPTED_RUN_PROPERTIES: readonly ["rFonts", "sz", "szCs", "color", "b", "bCs", "i", "iCs", "u", "strike", "dstrike", "highlight", "vertAlign", "position", "caps", "smallCaps", "spacing", "w", "kern"];
588
+ /** The accepted PARAGRAPH property boundary (design D8). */
589
+ declare const ACCEPTED_PARAGRAPH_PROPERTIES: readonly ["pStyle", "jc", "spacing", "ind", "tabs", "numPr", "keepNext", "keepLines", "widowControl", "pageBreakBefore", "shd"];
590
+ /**
591
+ * One authored property: an element name plus its `w:`-namespace attributes.
592
+ *
593
+ * Modeled as name+attributes rather than a typed record per property because that is what
594
+ * the tree holds, so an op maps to nodes without a lossy intermediate vocabulary. Attribute
595
+ * VALUES are validated as XML text; their meaning is the resolver's business.
596
+ */
597
+ /**
598
+ * One property an op writes, as a name plus attributes.
599
+ *
600
+ * Deliberately structural rather than a typed union: the accepted property lists bound WHICH
601
+ * properties may be written, so the shape itself does not need to enumerate them.
602
+ */
603
+ interface OoxmlProperty {
604
+ readonly localName: string;
605
+ readonly attributes?: Readonly<Record<string, string>>;
606
+ }
607
+ /**
608
+ * The identity of one revision WITHIN a part: `@w:id`, `@w:author` and `@w:date` together.
609
+ *
610
+ * `@w:id` is not unique and not author-scoped, so `(part, id)` alone would merge two authors'
611
+ * distinct revisions; and one logical revision — a tracked row insertion — is deliberately
612
+ * many elements sharing an id, which a uniqueness rule could not express at all.
613
+ */
614
+ /**
615
+ * How a tracked change is addressed: its numeric id plus the PART it lives in.
616
+ *
617
+ * Both, always — `@w:id` is unique only within a part, so an id alone names two revisions in any
618
+ * package with a header or a comments part.
619
+ */
620
+ interface RevisionAddress {
621
+ readonly id: string;
622
+ readonly author: string;
623
+ /** Absent when the file wrote no `@w:date`; part of the identity either way. */
624
+ readonly date?: string;
625
+ }
626
+ /** Who a tracked edit is attributed to. `CT_TrackChange` requires an author. */
627
+ /** The author and timestamp a tracked edit is recorded under. */
628
+ interface RevisionAttributionInput {
629
+ readonly author: string;
630
+ /** ISO-8601. Omitted writes no `@w:date`. */
631
+ readonly date?: string;
632
+ }
633
+ /**
634
+ * Every mutation the store accepts, as one JSON-safe discriminated union.
635
+ *
636
+ * The ONLY write path into a document. Each op addresses nodes by id plus UTF-16 offset, which is
637
+ * what makes editing a paragraph inside a table cell no different from editing one at the top
638
+ * level. Declarative and serializable, so the same op crosses a worker or transport boundary
639
+ * unchanged.
640
+ */
641
+ type TreeDocOp = {
642
+ /**
643
+ * Insert an SDT-wrapped TOC immediately before a body paragraph.
644
+ * The initial cached result and any heading bookmarks land in one undo unit.
645
+ */
646
+ readonly op: 'insertToc';
647
+ readonly beforeParagraphId: string;
648
+ readonly instruction: string;
649
+ readonly alias: string;
650
+ readonly entries: readonly {
651
+ readonly level: number;
652
+ readonly text: string;
653
+ readonly headingParagraphId: string;
654
+ readonly bookmarkName: string;
655
+ readonly pageNumberText: string;
656
+ }[];
657
+ readonly bookmarksToCreate: readonly {
658
+ readonly paragraphId: string;
659
+ readonly name: string;
660
+ }[];
661
+ } | {
662
+ readonly op: 'insertText';
663
+ readonly paragraphId: string;
664
+ readonly offset: number;
665
+ readonly text: string;
666
+ /**
667
+ * Write this as a TRACKED insertion, attributed here.
668
+ *
669
+ * On the op rather than on the store, so suggesting stays a decision the surface makes
670
+ * per edit and the write vocabulary stays explicit — a global "everything is tracked
671
+ * now" flag is exactly what `DocEdits` refuses, because it makes the meaning of an op
672
+ * depend on state the op does not carry.
673
+ */
674
+ readonly revision?: RevisionAttributionInput;
675
+ /**
676
+ * When set, the text belongs INSIDE this content control, whatever sits at the offset.
677
+ *
678
+ * A boundary offset is owned by the run that starts there, which at a control's trailing
679
+ * edge is the run after the control — so an offset alone cannot say "append to this field",
680
+ * the way it cannot say which run of a field result to format (see `targetRunIds`). A
681
+ * caller that names the control gets the text in the control; one that does not gets the
682
+ * plain offset rule, which is what a keystroke beside a field means.
683
+ */
684
+ readonly inside?: string;
685
+ /**
686
+ * Which side of a run BOUNDARY the text joins. Default `'left'` — Word's typing rule:
687
+ * the next character takes the formatting of the character before the caret.
688
+ *
689
+ * `'right'` is for a caller that is not typing but placing text inside the run that
690
+ * STARTS at the offset — the hyperlink editor rewriting a link's display text, where
691
+ * landing left of the boundary would put the new text outside the link. Ignored when
692
+ * the offset falls strictly inside a run, which has no boundary to choose.
693
+ */
694
+ readonly bias?: 'left' | 'right';
695
+ } | {
696
+ readonly op: 'deleteText';
697
+ readonly paragraphId: string;
698
+ readonly start: number;
699
+ readonly end: number;
700
+ /** Write this as a TRACKED deletion — the characters stay, wrapped in `w:del`. */
701
+ readonly revision?: RevisionAttributionInput;
702
+ } | {
703
+ /**
704
+ * Mark a paragraph's own MARK as inserted or deleted (`w:pPr/w:rPr/w:ins|w:del`,
705
+ * §17.13.5). The change is to the paragraph break itself, so no character carries it.
706
+ */
707
+ readonly op: 'setParagraphMarkRevision';
708
+ readonly paragraphId: string;
709
+ readonly kind: 'ins' | 'del';
710
+ readonly revision: RevisionAttributionInput;
711
+ } | {
712
+ /**
713
+ * Propose merging this paragraph into its PREDECESSOR by striking the predecessor's
714
+ * mark. Addressed by the SECOND paragraph so a multi-paragraph delete marks each
715
+ * paragraph's own predecessor rather than stamping the group head N times.
716
+ */
717
+ readonly op: 'proposeParagraphMerge';
718
+ readonly paragraphId: string;
719
+ readonly revision: RevisionAttributionInput;
720
+ } | {
721
+ /**
722
+ * Place one piece of comment markup at a model offset.
723
+ *
724
+ * Separate from the comment BODY, which lives in another part: this op is the story half
725
+ * of a comment write, and the two are staged in one package transaction.
726
+ */
727
+ readonly op: 'insertCommentMarker';
728
+ readonly paragraphId: string;
729
+ readonly offset: number;
730
+ readonly commentId: string;
731
+ readonly marker: 'start' | 'end' | 'reference';
732
+ } | {
733
+ /**
734
+ * Accept one revision, resolving every site in this part that carries its triple.
735
+ */
736
+ readonly op: 'acceptRevision';
737
+ readonly revision: RevisionAddress;
738
+ /** When set, only wrappers with this element local name resolve (ins/del/moveFrom/moveTo). */
739
+ readonly localName?: string;
740
+ } | {
741
+ readonly op: 'rejectRevision';
742
+ readonly revision: RevisionAddress;
743
+ readonly localName?: string;
744
+ } | {
745
+ /**
746
+ * Accept every revision in the part, in ONE transaction and one history entry.
747
+ *
748
+ * Deliberately not a loop over `acceptRevision`: a reviewer who accepts a document's
749
+ * changes made one decision, and one undo should restore all of them.
750
+ */
751
+ readonly op: 'acceptAllRevisions';
752
+ } | {
753
+ readonly op: 'rejectAllRevisions';
754
+ } | {
755
+ readonly op: 'insertTab';
756
+ readonly paragraphId: string;
757
+ readonly offset: number;
758
+ } | {
759
+ readonly op: 'insertHardBreak';
760
+ readonly paragraphId: string;
761
+ readonly offset: number;
762
+ } | {
763
+ readonly op: 'insertPageBreak';
764
+ readonly paragraphId: string;
765
+ readonly offset: number;
766
+ } | {
767
+ /**
768
+ * Insert an allowlisted page-number complex field at a UTF-16 offset.
769
+ *
770
+ * `PAGE_X_OF_Y` is PAGE + literal " of " + NUMPAGES in one undoable op. Non-page
771
+ * instructions are refused — never authored through this path.
772
+ */
773
+ readonly op: 'insertPageField';
774
+ readonly paragraphId: string;
775
+ readonly offset: number;
776
+ readonly field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y';
777
+ } | {
778
+ /**
779
+ * Move a numbered paragraph to another `w:numPr/w:ilvl`.
780
+ *
781
+ * A list item's LEVEL is what selects its format out of `numbering.xml`, so this is
782
+ * the op behind Increase/Decrease Indent on a list: the marker changes with it. A
783
+ * paragraph carrying no `w:numPr` is refused rather than silently numbered.
784
+ */
785
+ readonly op: 'setListLevel';
786
+ readonly paragraphId: string;
787
+ readonly level: number;
788
+ } | {
789
+ /**
790
+ * Put a paragraph in a list, or take it out of one.
791
+ *
792
+ * `numId` names a `w:num` in `numbering.xml`; null removes `w:numPr` entirely, which
793
+ * is what turning a bullet off means. Everything else in `w:pPr` survives.
794
+ */
795
+ /**
796
+ * Run properties of the PARAGRAPH MARK (`w:pPr/w:rPr`, ECMA-376 17.3.1.29).
797
+ *
798
+ * The mark carries the formatting a paragraph's own pilcrow has, and Word keeps it
799
+ * in step whenever formatting is applied to a whole paragraph. It is what a list
800
+ * marker inherits its face from — so without it, sizing a bulleted paragraph leaves
801
+ * the bullet at the old size.
802
+ */
803
+ readonly op: 'setParagraphMarkProperties';
804
+ readonly paragraphId: string;
805
+ readonly properties: readonly OoxmlProperty[];
806
+ } | {
807
+ readonly op: 'setListNumbering';
808
+ readonly paragraphId: string;
809
+ readonly numId: string | null;
810
+ readonly level?: number;
811
+ } | {
812
+ readonly op: 'splitParagraph';
813
+ readonly paragraphId: string;
814
+ readonly offset: number;
815
+ } | {
816
+ /**
817
+ * Split one `w:p` at MANY offsets in a single op.
818
+ *
819
+ * Equivalent to applying `splitParagraph` at each offset from the last to the first,
820
+ * but the paragraph's content is cut in one pass and the parent's child sequence is
821
+ * rebuilt once. A plain-text paste is a paragraph mark per line: as individual ops,
822
+ * a large paste rebuilt the body — and re-sliced the pasted text — once per line,
823
+ * which is quadratic in paste size.
824
+ */
825
+ readonly op: 'splitParagraphMany';
826
+ readonly paragraphId: string;
827
+ /**
828
+ * Non-decreasing UTF-16 offsets; each produces one paragraph boundary. A repeated
829
+ * offset produces an empty paragraph between the two boundaries — a blank line.
830
+ */
831
+ readonly offsets: readonly number[];
832
+ } | {
833
+ readonly op: 'joinParagraphs';
834
+ readonly firstId: string;
835
+ readonly secondId: string;
836
+ } | {
837
+ readonly op: 'setRunProperties';
838
+ readonly paragraphId: string;
839
+ readonly start: number;
840
+ readonly end: number;
841
+ readonly properties: readonly OoxmlProperty[];
842
+ /**
843
+ * When set, format only these runs (field result ownership). Offset range still
844
+ * gates the edit and drives edge splits; without this, multi-run field results that
845
+ * share one atom offset would homogenise under a single property bag.
846
+ */
847
+ readonly targetRunIds?: readonly string[];
848
+ } | {
849
+ readonly op: 'setParagraphProperties';
850
+ readonly paragraphId: string;
851
+ readonly properties: readonly OoxmlProperty[];
852
+ } | {
853
+ /**
854
+ * Set page-setup fields — page size, orientation, margins — on every targeted
855
+ * `w:sectPr`: all of them (Word's "Apply to: Whole document", the default) or
856
+ * only the one governing `anchorParagraphId`. A document whose write must reach
857
+ * the implicit tail section gets a body-level `w:sectPr` minted as the body's
858
+ * last child. Omitted fields are left exactly as authored per section. Explicit
859
+ * dimensions are written literally; `orientation` WITHOUT dimensions swaps each
860
+ * section's own (see `plannedSectionDimensions`), so distinct paper sizes
861
+ * survive a whole-document flip.
862
+ */
863
+ readonly op: 'setSectionProperties';
864
+ readonly pageWidthTwips?: number;
865
+ readonly pageHeightTwips?: number;
866
+ readonly orientation?: 'portrait' | 'landscape';
867
+ readonly marginTopTwips?: number;
868
+ readonly marginRightTwips?: number;
869
+ readonly marginBottomTwips?: number;
870
+ readonly marginLeftTwips?: number;
871
+ /**
872
+ * Word's "Apply to: This section": update only the section GOVERNING this
873
+ * paragraph — the nearest mid-body `w:sectPr` at or after it, else the body-level
874
+ * one. Absent means every section.
875
+ */
876
+ readonly anchorParagraphId?: string;
877
+ } | {
878
+ /**
879
+ * End a section AT this paragraph: mint a `w:pPr/w:sectPr` cloning the governing
880
+ * section's effective page setup, so the blocks up to and including this paragraph
881
+ * become their own section (a next-page section break). The paragraph must not
882
+ * already carry one.
883
+ */
884
+ readonly op: 'setSectionMark';
885
+ readonly paragraphId: string;
886
+ } | {
887
+ /**
888
+ * Wrap `[start, end)` of a paragraph in a `w:hyperlink`.
889
+ *
890
+ * The RANGE is the link — text and formatting inside it are untouched, and runs that
891
+ * straddle either edge are divided so the link covers exactly the characters asked
892
+ * for. Exactly one of `relationshipId` (an external target, already minted on the
893
+ * package) or `anchor` (a bookmark in this document) names where it goes.
894
+ *
895
+ * A collapsed range is refused: a link with no text is markup with nothing to click,
896
+ * and the caller that wants "insert a link with display text" inserts the text first.
897
+ */
898
+ readonly op: 'insertHyperlink';
899
+ readonly paragraphId: string;
900
+ readonly start: number;
901
+ readonly end: number;
902
+ readonly relationshipId?: string;
903
+ readonly anchor?: string;
904
+ readonly tooltip?: string;
905
+ /**
906
+ * Character style to mark the linked runs with (`w:rStyle`), normally `Hyperlink`.
907
+ *
908
+ * Written HERE rather than through `setRunProperties` because `w:rStyle` is preserved,
909
+ * not accepted: it is not in the set a property write replaces, and putting it there
910
+ * would make a later bold toggle delete it. Marking the text is part of making it a
911
+ * link — Word does both in one operation — so the op that wraps it also styles it.
912
+ * Omitted for a document that declares no such style.
913
+ */
914
+ readonly styleId?: string;
915
+ } | {
916
+ /**
917
+ * Re-aim an existing link. `relationshipId` moves it to another external target,
918
+ * `anchor` to a bookmark; supplying one CLEARS the other, so a link never ends up
919
+ * carrying both and resolving by the wrong one.
920
+ */
921
+ readonly op: 'setHyperlinkTarget';
922
+ readonly linkId: string;
923
+ readonly relationshipId?: string;
924
+ readonly anchor?: string;
925
+ readonly tooltip?: string;
926
+ } | {
927
+ /**
928
+ * Unlink: splice the `w:hyperlink`'s children into the paragraph in its place.
929
+ *
930
+ * The runs keep their identity, their formatting and their order, and any bookmark
931
+ * markers inside the link stay exactly where they were. Only the link element goes,
932
+ * which is what Word's Remove Hyperlink does — the text is not the link's, it was
933
+ * only wrapped by it.
934
+ */
935
+ readonly op: 'removeHyperlink';
936
+ readonly linkId: string;
937
+ } | {
938
+ /**
939
+ * Insert a NEW run-level content control at a text offset: `w:sdt` with a
940
+ * `w:sdtPr` carrying the given tag (and alias/lock) and a `w:sdtContent`
941
+ * holding one run of `text`.
942
+ *
943
+ * The write half of the custom-node contract (pro-review-and-custom-nodes):
944
+ * a node's identity lives in `w:tag`, `sdtLocked` keeps Word users from
945
+ * unwrapping the anchor, and the literal run text is what Word (and the
946
+ * free tier) render. The TAG IS ATTACKER-ADJACENT ON READ but authored
947
+ * here; it is written as an ordinary attribute value, so the serializer's
948
+ * escaping covers it like every other attribute.
949
+ */
950
+ readonly op: 'insertInlineContentControl';
951
+ readonly paragraphId: string;
952
+ readonly offset: number;
953
+ readonly tag: string;
954
+ readonly text: string;
955
+ readonly alias?: string;
956
+ /** `w:lock` value; omitted writes no lock. */
957
+ readonly lock?: 'sdtLocked' | 'sdtContentLocked' | 'contentLocked';
958
+ } | {
959
+ /** Repeating-section item insert — unsupported at this layer (out of scope). */
960
+ readonly op: 'addRepeatingSectionItem';
961
+ readonly controlId: string;
962
+ readonly index?: number;
963
+ } | {
964
+ /** Repeating-section item remove — unsupported at this layer (out of scope). */
965
+ readonly op: 'removeRepeatingSectionItem';
966
+ readonly controlId: string;
967
+ readonly index: number;
968
+ } | {
969
+ /**
970
+ * Remove a typed block and everything under it.
971
+ *
972
+ * Validation restricts this structural operation to `w:p`, `w:tbl`, and `w:tr`, and
973
+ * refuses removals that would violate required-container or section-mark invariants.
974
+ */
975
+ readonly op: 'deleteBlock';
976
+ readonly blockId: string;
977
+ } | {
978
+ /**
979
+ * Insert a fresh empty table immediately before a block-level paragraph.
980
+ *
981
+ * Before, never after, so the anchor paragraph stays as the block that follows the
982
+ * table: a `w:tbl` is not a valid final child of a story container, and two tables
983
+ * that end up adjacent merge into one when the file is reopened. When the anchor's
984
+ * previous sibling is already a table, a separating empty paragraph is authored with
985
+ * it, which is what Word does for the same reason.
986
+ */
987
+ readonly op: 'insertTable';
988
+ readonly beforeParagraphId: string;
989
+ readonly rows: number;
990
+ readonly cols: number;
991
+ /** Width of every grid column, in twips. The caller divides the content width. */
992
+ readonly columnWidthTwips: number;
993
+ } | {
994
+ /** Insert a fresh row above or below a canonical table row. */
995
+ readonly op: 'insertTableRow';
996
+ readonly tableId: string;
997
+ readonly rowId: string;
998
+ readonly where: 'above' | 'below';
999
+ /** When present, author the row as a Word tracked insertion. */
1000
+ readonly revision?: RevisionAttributionInput;
1001
+ } | {
1002
+ /** Delete one canonical table row; refuses the final row. */
1003
+ readonly op: 'deleteTableRow';
1004
+ readonly tableId: string;
1005
+ readonly rowId: string;
1006
+ /** Optional anchor cell for column-aware caret recovery after deletion. */
1007
+ readonly referenceCellId?: string;
1008
+ /** When present, retain the row and author a Word tracked deletion. */
1009
+ readonly revision?: RevisionAttributionInput;
1010
+ } | {
1011
+ /** Insert one grid column left or right of a canonical `w:gridCol`. */
1012
+ readonly op: 'insertTableColumn';
1013
+ readonly tableId: string;
1014
+ readonly where: 'left' | 'right';
1015
+ readonly gridColumnId: string;
1016
+ } | {
1017
+ /**
1018
+ * Insert one grid column beside a first-row reference cell when `w:tblGrid` is absent.
1019
+ * Synthesizes a canonical grid before mutation.
1020
+ */
1021
+ readonly op: 'insertTableColumn';
1022
+ readonly tableId: string;
1023
+ readonly where: 'left' | 'right';
1024
+ readonly referenceCellId: string;
1025
+ } | {
1026
+ /** Delete one canonical grid column; refuses the final column. */
1027
+ readonly op: 'deleteTableColumn';
1028
+ readonly tableId: string;
1029
+ readonly gridColumnId: string;
1030
+ } | {
1031
+ /**
1032
+ * Resize one internal divider between two adjacent canonical grid columns.
1033
+ * Preserves the pair total and sets fixed table layout.
1034
+ */
1035
+ readonly op: 'setTableColumnWidths';
1036
+ readonly tableId: string;
1037
+ readonly leftGridColumnId: string;
1038
+ readonly rightGridColumnId: string;
1039
+ readonly leftWidthTwips: number;
1040
+ readonly rightWidthTwips: number;
1041
+ } | {
1042
+ /**
1043
+ * Resize the outer-right edge: last grid column, matching cells, and `w:tblW` total.
1044
+ */
1045
+ readonly op: 'setTableRightEdgeWidth';
1046
+ readonly tableId: string;
1047
+ readonly gridColumnId: string;
1048
+ readonly columnWidthTwips: number;
1049
+ readonly tableWidthTwips: number;
1050
+ } | {
1051
+ /** Set one authored table row to an exact height in twips. */
1052
+ readonly op: 'setTableRowHeight';
1053
+ readonly tableId: string;
1054
+ readonly rowId: string;
1055
+ readonly heightTwips: number;
1056
+ } | {
1057
+ /** Clear the active edge target on a bounded rectangular cell selection. */
1058
+ readonly op: 'setTableCellBorders';
1059
+ readonly tableId: string;
1060
+ readonly cellIds: readonly string[];
1061
+ readonly scope: 'none';
1062
+ readonly target: TableBorderEdgeTarget;
1063
+ } | {
1064
+ /** Apply a complete border spec to the requested edge target. */
1065
+ readonly op: 'setTableCellBorders';
1066
+ readonly tableId: string;
1067
+ readonly cellIds: readonly string[];
1068
+ readonly scope: TableBorderEdgeTarget;
1069
+ readonly spec: TableBorderSpecInput;
1070
+ } | {
1071
+ /** Write or remove direct selected-cell shading (`w:tcPr/w:shd`). */
1072
+ readonly op: 'setTableCellFill';
1073
+ readonly tableId: string;
1074
+ readonly cellIds: readonly string[];
1075
+ readonly color: TreeDocColorValue | null;
1076
+ } | {
1077
+ /** Set direct selected-cell vertical alignment (`w:tcPr/w:vAlign`). */
1078
+ readonly op: 'setTableCellVerticalAlignment';
1079
+ readonly tableId: string;
1080
+ readonly cellIds: readonly string[];
1081
+ readonly alignment: 'top' | 'center' | 'bottom';
1082
+ } | {
1083
+ /** Allocate an empty header/footer part and declare it on a section. Package-level. */
1084
+ readonly op: 'createHeaderFooter';
1085
+ readonly sectionIndex: number;
1086
+ readonly kind: 'header' | 'footer';
1087
+ readonly variant: 'default' | 'first' | 'even';
1088
+ /** When true, also set section `w:titlePg` in the same package transaction. */
1089
+ readonly titlePage?: boolean;
1090
+ /** When true, also set document `w:evenAndOddHeaders` in the same package transaction. */
1091
+ readonly evenAndOddHeaders?: boolean;
1092
+ } | {
1093
+ /** Remove a section's declared header/footer reference; GC when orphaned. Package-level. */
1094
+ readonly op: 'deleteHeaderFooter';
1095
+ readonly sectionIndex: number;
1096
+ readonly kind: 'header' | 'footer';
1097
+ readonly variant: 'default' | 'first' | 'even';
1098
+ } | {
1099
+ /** Drop a declared ref so the section inherits from the previous. Package-level. */
1100
+ readonly op: 'linkToPrevious';
1101
+ readonly sectionIndex: number;
1102
+ readonly kind: 'header' | 'footer';
1103
+ readonly variant: 'default' | 'first' | 'even';
1104
+ } | {
1105
+ /** Clone an inherited part into a new declared reference. Package-level. */
1106
+ readonly op: 'unlinkFromPrevious';
1107
+ readonly sectionIndex: number;
1108
+ readonly kind: 'header' | 'footer';
1109
+ readonly variant: 'default' | 'first' | 'even';
1110
+ } | {
1111
+ /**
1112
+ * Section/document furniture options: `titlePg`, header/footer distances on the
1113
+ * section; `evenAndOddHeaders` document-wide in settings. Package-level.
1114
+ */
1115
+ readonly op: 'setSectionFurnitureOptions';
1116
+ readonly sectionIndex?: number;
1117
+ readonly titlePage?: boolean;
1118
+ readonly evenAndOddHeaders?: boolean;
1119
+ readonly headerDistanceTwips?: number;
1120
+ readonly footerDistanceTwips?: number;
1121
+ } | {
1122
+ /**
1123
+ * Insert a footnote or endnote: body reference + notes-part body (+ create the
1124
+ * notes part/rel/content-type when missing). Package-level; one ModelChange.
1125
+ */
1126
+ readonly op: 'insertNote';
1127
+ readonly noteKind: 'footnote' | 'endnote';
1128
+ readonly paragraphId: string;
1129
+ readonly offset: number;
1130
+ } | {
1131
+ /**
1132
+ * Delete a note body and every matching reference (body, HF, other notes).
1133
+ * Package-level; one ModelChange.
1134
+ */
1135
+ readonly op: 'deleteNote';
1136
+ readonly noteKind: 'footnote' | 'endnote';
1137
+ readonly noteId: number;
1138
+ } | {
1139
+ /** Convert a footnote ↔ endnote, reallocating id in the target part. Package-level. */
1140
+ readonly op: 'convertNote';
1141
+ readonly fromKind: 'footnote' | 'endnote';
1142
+ readonly noteId: number;
1143
+ } | {
1144
+ /**
1145
+ * Convert every normal footnote↔endnote of `fromKind` in one package transaction.
1146
+ * One ModelChange / undo unit; bounded by notes-part size.
1147
+ */
1148
+ readonly op: 'convertAllNotes';
1149
+ readonly fromKind: 'footnote' | 'endnote';
1150
+ } | {
1151
+ /**
1152
+ * Write a content control's VALUE, in the vocabulary its own type accepts.
1153
+ *
1154
+ * One transaction for the whole transition: the content, `w:showingPlcHdr`, and the
1155
+ * type's own record of the value (`@w:lastValue`, `@w:fullDate`, `w14:checked`) move
1156
+ * together, because a control whose glyph says checked and whose flag says unchecked is
1157
+ * a document Word and this engine read differently.
1158
+ */
1159
+ readonly op: 'setContentControlValue';
1160
+ readonly controlId: string;
1161
+ /** String is the editor-facing v2 form; structured input is the automation form. */
1162
+ readonly value: string | ContentControlValueInput;
1163
+ } | {
1164
+ /**
1165
+ * Author the metadata a control carries: its tag, its title, its lock.
1166
+ *
1167
+ * `null` removes the property. Everything else in `CT_SdtPr` — the type payload, a data
1168
+ * binding, an extension this vocabulary does not model — survives in schema order.
1169
+ */
1170
+ readonly op: 'setContentControlProperties';
1171
+ readonly controlId: string;
1172
+ readonly tag?: string | null;
1173
+ readonly alias?: string | null;
1174
+ readonly lock?: ContentControlLock;
1175
+ } | {
1176
+ /**
1177
+ * Remove a control. `keepContent` splices its content into its place — Word's own
1178
+ * "Remove content control" — and false takes the content with it.
1179
+ */
1180
+ readonly op: 'removeContentControl';
1181
+ readonly controlId: string;
1182
+ /** Defaults to true for the editor-facing v2 operation. */
1183
+ readonly keepContent?: boolean;
1184
+ } | {
1185
+ /**
1186
+ * Wrap `[start, end)` of a paragraph in a new control of the named type.
1187
+ *
1188
+ * A control is a SIBLING of runs, never a thing inside one, so a range ending mid-run
1189
+ * splits that run at both edges first. The characters and their formatting are the ones
1190
+ * that were there; only the run boundaries move.
1191
+ */
1192
+ readonly op: 'insertContentControl';
1193
+ readonly paragraphId: string;
1194
+ readonly start: number;
1195
+ readonly end: number;
1196
+ readonly type: InsertableContentControlType;
1197
+ readonly tag?: string;
1198
+ readonly alias?: string;
1199
+ readonly lock?: ContentControlLock;
1200
+ } | {
1201
+ /**
1202
+ * Author `w:footnotePr` / `w:endnotePr` at document (settings) or section scope.
1203
+ * Refuse endnote `pageBottom`. Package-level; does not invent props on unedited saves.
1204
+ */
1205
+ readonly op: 'setNoteProperties';
1206
+ readonly scope: 'document' | 'section';
1207
+ readonly sectionIndex?: number;
1208
+ readonly footnote?: {
1209
+ readonly numFmt?: string;
1210
+ readonly numRestart?: string;
1211
+ readonly position?: string;
1212
+ readonly numStart?: number;
1213
+ };
1214
+ readonly endnote?: {
1215
+ readonly numFmt?: string;
1216
+ readonly numRestart?: string;
1217
+ readonly position?: string;
1218
+ readonly numStart?: number;
1219
+ };
1220
+ } | {
1221
+ readonly op: 'insertDrawing';
1222
+ readonly paragraphId: string;
1223
+ readonly offset: number;
1224
+ readonly drawing: OoxmlDrawingNode;
1225
+ } | {
1226
+ readonly op: 'replaceDrawingResource';
1227
+ readonly drawingNodeId: string;
1228
+ readonly relationshipId: string;
1229
+ } | {
1230
+ readonly op: 'deleteDrawing';
1231
+ readonly drawingNodeId: string;
1232
+ /** Suggesting-mode tracked deletion is refused; owned by typed-revisions-and-comments. */
1233
+ readonly revision?: RevisionAttributionInput;
1234
+ } | {
1235
+ readonly op: 'resizeDrawing';
1236
+ readonly drawingNodeId: string;
1237
+ readonly extentEmu: {
1238
+ readonly cx: number;
1239
+ readonly cy: number;
1240
+ };
1241
+ } | {
1242
+ readonly op: 'cropDrawing';
1243
+ readonly drawingNodeId: string;
1244
+ readonly crop: SourceCrop;
1245
+ } | {
1246
+ readonly op: 'positionDrawing';
1247
+ readonly drawingNodeId: string;
1248
+ readonly position: DrawingPositionInput;
1249
+ } | {
1250
+ readonly op: 'setDrawingWrap';
1251
+ readonly drawingNodeId: string;
1252
+ readonly wrap: ImageWrapTarget;
1253
+ } | {
1254
+ readonly op: 'setDrawingMetadata';
1255
+ readonly drawingNodeId: string;
1256
+ readonly title: string;
1257
+ readonly description: string;
1258
+ /** Omitted preserves existing `a:hlinkClick`; null removes it; a URL needs a package transaction. */
1259
+ readonly hyperlink?: string | null;
1260
+ } | {
1261
+ readonly op: 'setDrawingLocks';
1262
+ readonly drawingNodeId: string;
1263
+ readonly locks: DrawingLocksInput;
1264
+ } | {
1265
+ readonly op: 'transformDrawing';
1266
+ readonly drawingNodeId: string;
1267
+ readonly action: 'rotateCW' | 'rotateCCW' | 'flipH' | 'flipV';
1268
+ } | {
1269
+ /**
1270
+ * Replace a detected TOC field's cached result paragraphs and ensure heading bookmarks.
1271
+ * Preserves field chrome / instruction. One undo unit (phase A of TOC refresh).
1272
+ */
1273
+ readonly op: 'replaceTocResult';
1274
+ readonly tocId: string;
1275
+ readonly entries: readonly {
1276
+ readonly level: number;
1277
+ readonly text: string;
1278
+ readonly headingParagraphId: string;
1279
+ readonly bookmarkName: string;
1280
+ readonly pageNumberText: string;
1281
+ }[];
1282
+ readonly bookmarksToCreate: readonly {
1283
+ readonly paragraphId: string;
1284
+ readonly name: string;
1285
+ }[];
1286
+ } | {
1287
+ /**
1288
+ * Rewrite page-number text runs inside existing TOC result paragraphs.
1289
+ * One undo unit (phase B of TOC refresh).
1290
+ */
1291
+ readonly op: 'rewriteTocPageNumbers';
1292
+ readonly tocId: string;
1293
+ readonly updates: readonly {
1294
+ readonly paragraphId: string;
1295
+ readonly pageNumberText: string;
1296
+ }[];
1297
+ };
1298
+ /** Drawing mutation ops from typed-drawings-and-images task 11. */
1299
+ type DrawingTreeDocOp = Extract<TreeDocOp, {
1300
+ readonly op: 'insertDrawing' | 'replaceDrawingResource' | 'deleteDrawing' | 'resizeDrawing' | 'cropDrawing' | 'positionDrawing' | 'setDrawingWrap' | 'setDrawingMetadata' | 'setDrawingLocks' | 'transformDrawing';
1301
+ }>;
1302
+ /** Just the `op` discriminants, for dispatch tables and validation. */
1303
+ type TreeDocOpKind = TreeDocOp['op'];
1304
+ /** Every {@link TreeDocOpKind}, for validation and exhaustiveness checks. */
1305
+ declare const TREE_DOC_OP_KINDS: readonly ["insertText", "deleteText", "setParagraphMarkRevision", "proposeParagraphMerge", "insertCommentMarker", "acceptRevision", "rejectRevision", "acceptAllRevisions", "rejectAllRevisions", "insertTab", "insertHardBreak", "insertPageBreak", "insertPageField", "setListLevel", "setListNumbering", "setParagraphMarkProperties", "splitParagraph", "splitParagraphMany", "joinParagraphs", "setRunProperties", "setParagraphProperties", "setSectionProperties", "setSectionMark", "insertHyperlink", "setHyperlinkTarget", "removeHyperlink", "setContentControlValue", "removeContentControl", "insertInlineContentControl", "addRepeatingSectionItem", "removeRepeatingSectionItem", "deleteBlock", "insertTable", "insertTableRow", "deleteTableRow", "insertTableColumn", "deleteTableColumn", "setTableColumnWidths", "setTableRightEdgeWidth", "setTableRowHeight", "setTableCellBorders", "setTableCellFill", "setTableCellVerticalAlignment", "createHeaderFooter", "deleteHeaderFooter", "linkToPrevious", "unlinkFromPrevious", "setSectionFurnitureOptions", "insertNote", "deleteNote", "convertNote", "convertAllNotes", "setNoteProperties", "setContentControlProperties", "insertContentControl", "insertDrawing", "replaceDrawingResource", "deleteDrawing", "resizeDrawing", "cropDrawing", "positionDrawing", "setDrawingWrap", "setDrawingMetadata", "setDrawingLocks", "transformDrawing", "insertToc", "replaceTocResult", "rewriteTocPageNumbers"];
1306
+ /**
1307
+ * How far a committed op can reach, so layout can scope its work (task 5.2).
1308
+ *
1309
+ * `text-local` touches one paragraph's characters; `paragraph-local` changes one
1310
+ * paragraph's own properties; `flow-structural` changes the block sequence and can
1311
+ * repaginate everything after it; `global` invalidates every page that shares the
1312
+ * edited story (header/footer parts attached to many sections/pages).
1313
+ */
1314
+ /**
1315
+ * How far an op's effects reach — what layout must re-do after it.
1316
+ *
1317
+ * The knob incremental layout turns: a `text-local` edit re-breaks one paragraph, while a
1318
+ * `global` one invalidates the document.
1319
+ */
1320
+ type ImpactClass = 'text-local' | 'paragraph-local' | 'flow-structural' | 'global';
1321
+ /**
1322
+ * What one applied op changed: the ids dirtied, created and deleted.
1323
+ *
1324
+ * These ids are what let layout and paint re-do only what moved instead of the whole document.
1325
+ */
1326
+ interface TreeOpEffect {
1327
+ readonly dirty: readonly string[];
1328
+ readonly created: readonly string[];
1329
+ readonly deleted: readonly string[];
1330
+ readonly split?: {
1331
+ readonly from: string;
1332
+ readonly tail: string;
1333
+ };
1334
+ /** One entry per boundary of a many-way split, in document order. */
1335
+ readonly splits?: readonly {
1336
+ readonly from: string;
1337
+ readonly tail: string;
1338
+ }[];
1339
+ readonly join?: {
1340
+ readonly kept: string;
1341
+ readonly removed: string;
1342
+ };
1343
+ readonly dependencyKeys: readonly string[];
1344
+ readonly impact: ImpactClass;
1345
+ /** First post-edit caret paragraph for table column structural ops. */
1346
+ readonly caret?: {
1347
+ readonly paragraphId: string;
1348
+ };
1349
+ }
1350
+ /**
1351
+ * Why an op was refused.
1352
+ *
1353
+ * `not-adjacent-siblings` is the notable one: a join across table cells is refused rather than
1354
+ * silently merging content out of the cell that owned it.
1355
+ */
1356
+ type TreeOpRejection = 'unknown-op' | 'unknown-paragraph' | 'not-a-paragraph' | 'offset-out-of-range' | 'invalid-range' | 'not-a-list-paragraph' | 'splits-surrogate-pair' | 'invalid-text' | 'unsupported-property' | 'invalid-property-value' | 'not-adjacent-siblings' | 'unknown-block' | 'not-a-block' | 'block-required' | 'carries-section-mark'
1357
+ /** The transaction named a part the package does not hold. */
1358
+ | 'unknown-part'
1359
+ /**
1360
+ * The transaction would have published a package that does not open: a relationship
1361
+ * pointing at a part nobody created, or a part with no declared content type.
1362
+ */
1363
+ | 'package-invariant'
1364
+ /** No revision in this part carries the addressed `(id, author, date)` triple. */
1365
+ | 'unknown-revision'
1366
+ /**
1367
+ * A matched revision is a kind whose accept/reject semantics are structural and not
1368
+ * implemented. Refusing is deliberate: removing the markup alone would report the decision
1369
+ * applied while leaving the row, cell, or section it describes untouched.
1370
+ */
1371
+ | 'unsupported-revision' | 'tree-invariant'
1372
+ /** No content control in this part carries the addressed node id. */
1373
+ | 'unknown-content-control'
1374
+ /** The addressed node exists and is not a `w:sdt`. */
1375
+ | 'not-a-content-control'
1376
+ /**
1377
+ * A content control's `w:lock` — or one an enclosing control imposes — forbids this.
1378
+ *
1379
+ * The same code for an edit inside `contentLocked` content and for the removal of an
1380
+ * `sdtLocked` control: both are "the document says no", and the two halves are already
1381
+ * distinguished by which operation was refused.
1382
+ */
1383
+ | 'locked'
1384
+ /** The control declares `w:dataBinding`; its value belongs to a custom XML part. */
1385
+ | 'bound'
1386
+ /** The value offered is not one this control's type accepts. */
1387
+ | 'typeMismatch' | 'unknown-control' | 'unsupported'
1388
+ /** Malformed lifecycle args / first-section link — mirrors Editor `invalidArgs`. */
1389
+ | 'invalidArgs'
1390
+ /** The addressed table id is missing, duplicated, or not a typed table. */
1391
+ | 'unknown-table'
1392
+ /** The addressed row id is missing or not a direct child of the table. */
1393
+ | 'unknown-row'
1394
+ /** A table property container appears more than once on a typed node. */
1395
+ | 'duplicate-property-container'
1396
+ /** Row insertion would split an active vertical-merge chain. */
1397
+ | 'vertical-merge-crossing'
1398
+ /** Column edit refused because the table carries horizontal or vertical merges. */
1399
+ | 'table-has-merge'
1400
+ /** The addressed grid column id is missing or ambiguous without `w:tblGrid`. */
1401
+ | 'unknown-grid-column'
1402
+ /** The operation would exceed bounded table topology limits. */
1403
+ | 'resource-limit'
1404
+ /** The addressed node is not a top-level `w:drawing`. */
1405
+ | 'not-a-drawing'
1406
+ /** No `w:drawing` with this id exists in the part. */
1407
+ | 'unknown-drawing'
1408
+ /** The drawing's graphic payload is not a supported picture. */
1409
+ | 'not-a-picture-drawing'
1410
+ /** A lock flag or `@locked` forbids this mutation. */
1411
+ | 'drawing-locked'
1412
+ /** Finite EMU extent, crop, or position value is out of range. */
1413
+ | 'invalid-drawing-value'
1414
+ /** Insertion would cross a table-cell boundary or wrong story container. */
1415
+ | 'cross-cell-drawing'
1416
+ /** Suggesting-mode drawing deletion is not implemented in this change. */
1417
+ | 'trackedDrawingDeletionUnsupported'
1418
+ /** Hyperlink target creation or change needs an OPC relationship in a package transaction. */
1419
+ | 'packageTransactionRequired';
1420
+ /** Whether an op applied, with the effect it produced or the reason it was refused. */
1421
+ type TreeOpResult = {
1422
+ readonly ok: true;
1423
+ readonly part: OoxmlPart;
1424
+ readonly effect: TreeOpEffect;
1425
+ } | {
1426
+ readonly ok: false;
1427
+ readonly reason: TreeOpRejection;
1428
+ readonly detail?: string;
1429
+ };
1430
+
1431
+ export { contentControlTextOf as $, ACCEPTED_PARAGRAPH_PROPERTIES as A, type HyperlinkKind as B, type ContentControlKind as C, type DrawingProjection as D, type HyperlinkTarget as E, MAX_CONTENT_CONTROL_NESTING as F, OFFICE_RELATIONSHIP_NAMESPACE_URI as G, HYPERLINK_RELATIONSHIP_TYPE as H, type ImpactClass as I, type RelationshipTargetResolver as J, TABLE_BORDER_STYLES as K, TREE_DOC_OP_KINDS as L, MAX_CONTENT_CONTROLS_PER_PART as M, type TreeDocOpKind as N, type OoxmlProperty as O, type TreeOpEffect as P, allocateContentControlId as Q, type RevisionAddress as R, type SourceCrop as S, type TreeDocOp as T, contentControlContentChildren as U, type VectorShapeProjection as V, contentControlContentNodeOf as W, contentControlEndPropertiesNodeOf as X, contentControlLevelOf as Y, contentControlPropertiesNodeOf as Z, contentControlPropertiesOf as _, type TreeOpRejection as a, contentControlsIn as a0, findContentControl as a1, flattenContentControls as a2, hyperlinkAnchorOf as a3, hyperlinkRelationshipIdOf as a4, hyperlinkTargetOf as a5, isContentControlContentNode as a6, isContentControlNode as a7, isContentControlWrapper as a8, isHyperlinkNode as a9, lockForbidsEdit as aa, lockForbidsRemoval as ab, orderedContentControlProperties as ac, parseContentControlId as ad, projectDrawing as ae, resolveContentControlLock as af, type ImageWrapTarget as b, type DrawingKind as c, type DrawingPositionInput as d, type DrawingLocks as e, type DrawingHorizontalReferenceFrame as f, type DrawingVerticalReferenceFrame as g, type TreeDocColorValue as h, IMAGE_WRAP_TARGETS as i, type DrawingAccessibility as j, type DrawingTransform as k, type TableBorderStyle as l, type DrawingTreeDocOp as m, type ContentControlLevel as n, type ContentControlLock as o, type ContentControlDataBinding as p, type TreeOpResult as q, ACCEPTED_RUN_PROPERTIES as r, CONTENT_CONTROL_ID_MAX as s, CONTENT_CONTROL_PROPERTY_ORDER as t, type ContentControlCheckbox as u, type ContentControlCheckboxState as v, type ContentControlDateFormat as w, type ContentControlEntry as x, type ContentControlListItem as y, type ContentControlProperties as z };