@arbidocs/blocks 0.4.101 → 0.4.103

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 (209) hide show
  1. package/dist/chunk-6MG62I5B.cjs +272 -0
  2. package/dist/chunk-6MG62I5B.cjs.map +1 -0
  3. package/dist/{chunk-MYALCKDR.js → chunk-CVYY4X5R.js} +306 -75
  4. package/dist/chunk-CVYY4X5R.js.map +1 -0
  5. package/dist/chunk-EQB3WELX.js +269 -0
  6. package/dist/chunk-EQB3WELX.js.map +1 -0
  7. package/dist/{chunk-G5JH2YMQ.js → chunk-GQTIAATM.js} +3 -3
  8. package/dist/{chunk-G5JH2YMQ.js.map → chunk-GQTIAATM.js.map} +1 -1
  9. package/dist/{chunk-YGREW5TZ.js → chunk-H6DFXG5N.js} +3 -3
  10. package/dist/{chunk-YGREW5TZ.js.map → chunk-H6DFXG5N.js.map} +1 -1
  11. package/dist/{chunk-ZT2EBBSC.cjs → chunk-N36PWG7A.cjs} +5 -5
  12. package/dist/{chunk-ZT2EBBSC.cjs.map → chunk-N36PWG7A.cjs.map} +1 -1
  13. package/dist/{chunk-FAGQTB3D.cjs → chunk-O33EBMIX.cjs} +305 -74
  14. package/dist/chunk-O33EBMIX.cjs.map +1 -0
  15. package/dist/{chunk-Y5XW57U4.cjs → chunk-TFDU2KGS.cjs} +5 -5
  16. package/dist/{chunk-Y5XW57U4.cjs.map → chunk-TFDU2KGS.cjs.map} +1 -1
  17. package/dist/connect/docx.cjs +6 -6
  18. package/dist/connect/docx.js +4 -4
  19. package/dist/connect/index.cjs +3 -3
  20. package/dist/connect/index.js +2 -2
  21. package/dist/document-tools/AdoptSignatureDialog.d.ts +25 -0
  22. package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
  23. package/dist/document-tools/SignatureRequestBanner.d.ts +18 -0
  24. package/dist/document-tools/index.cjs +175 -0
  25. package/dist/document-tools/index.cjs.map +1 -1
  26. package/dist/document-tools/index.d.ts +3 -1
  27. package/dist/document-tools/index.js +168 -3
  28. package/dist/document-tools/index.js.map +1 -1
  29. package/dist/document-tools/viewer/GuidedSigningViewer.d.ts +26 -0
  30. package/dist/document-tools/viewer/SignatureFieldsOverlay.d.ts +41 -0
  31. package/dist/document-tools/viewer/SignatureRequestEditor.d.ts +26 -0
  32. package/dist/document-tools/viewer/index.cjs +983 -0
  33. package/dist/document-tools/viewer/index.cjs.map +1 -1
  34. package/dist/document-tools/viewer/index.d.ts +3 -0
  35. package/dist/document-tools/viewer/index.js +983 -5
  36. package/dist/document-tools/viewer/index.js.map +1 -1
  37. package/dist/docx/RibbonMenu.d.ts +4 -1
  38. package/dist/docx/RibbonOverflow.d.ts +27 -0
  39. package/dist/docx/WordReferences.d.ts +3 -2
  40. package/dist/docx/index.cjs +35 -35
  41. package/dist/docx/index.js +3 -3
  42. package/dist/docx/noteStyles.d.ts +46 -0
  43. package/dist/docx/overflowPlan.d.ts +15 -0
  44. package/dist/index.cjs +5 -5
  45. package/dist/index.js +1 -1
  46. package/node_modules/@arbidocs/coedit/LICENSE +21 -0
  47. package/node_modules/@arbidocs/coedit/dist/encoding.cjs +751 -0
  48. package/node_modules/@arbidocs/coedit/dist/encoding.cjs.map +1 -0
  49. package/node_modules/@arbidocs/coedit/dist/encoding.d.cts +192 -0
  50. package/node_modules/@arbidocs/coedit/dist/encoding.d.ts +192 -0
  51. package/node_modules/@arbidocs/coedit/dist/encoding.js +716 -0
  52. package/node_modules/@arbidocs/coedit/dist/encoding.js.map +1 -0
  53. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs +1759 -0
  54. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs.map +1 -0
  55. package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.cts +39 -0
  56. package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.ts +39 -0
  57. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js +1736 -0
  58. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js.map +1 -0
  59. package/node_modules/@arbidocs/coedit/dist/index.cjs +1692 -0
  60. package/node_modules/@arbidocs/coedit/dist/index.cjs.map +1 -0
  61. package/node_modules/@arbidocs/coedit/dist/index.d.cts +16 -0
  62. package/node_modules/@arbidocs/coedit/dist/index.d.ts +16 -0
  63. package/node_modules/@arbidocs/coedit/dist/index.js +1664 -0
  64. package/node_modules/@arbidocs/coedit/dist/index.js.map +1 -0
  65. package/node_modules/@arbidocs/coedit/dist/server.cjs +1852 -0
  66. package/node_modules/@arbidocs/coedit/dist/server.cjs.map +1 -0
  67. package/node_modules/@arbidocs/coedit/dist/server.d.cts +43 -0
  68. package/node_modules/@arbidocs/coedit/dist/server.d.ts +43 -0
  69. package/node_modules/@arbidocs/coedit/dist/server.js +1822 -0
  70. package/node_modules/@arbidocs/coedit/dist/server.js.map +1 -0
  71. package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.cts +82 -0
  72. package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.ts +82 -0
  73. package/node_modules/@arbidocs/coedit/dist/template.cjs +1627 -0
  74. package/node_modules/@arbidocs/coedit/dist/template.cjs.map +1 -0
  75. package/node_modules/@arbidocs/coedit/dist/template.d.cts +125 -0
  76. package/node_modules/@arbidocs/coedit/dist/template.d.ts +125 -0
  77. package/node_modules/@arbidocs/coedit/dist/template.js +1612 -0
  78. package/node_modules/@arbidocs/coedit/dist/template.js.map +1 -0
  79. package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.cts +8 -0
  80. package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.ts +8 -0
  81. package/node_modules/@arbidocs/coedit/package.json +68 -0
  82. package/node_modules/@docx-editor.dev/core/LICENSE +201 -0
  83. package/node_modules/@docx-editor.dev/core/README.md +125 -0
  84. package/node_modules/@docx-editor.dev/core/THIRD_PARTY_NOTICES.md +56 -0
  85. package/node_modules/@docx-editor.dev/core/dist/automation.cjs +1 -0
  86. package/node_modules/@docx-editor.dev/core/dist/automation.d.ts +162 -0
  87. package/node_modules/@docx-editor.dev/core/dist/automation.js +1 -0
  88. package/node_modules/@docx-editor.dev/core/dist/binding.cjs +1 -0
  89. package/node_modules/@docx-editor.dev/core/dist/binding.d.ts +164 -0
  90. package/node_modules/@docx-editor.dev/core/dist/binding.js +1 -0
  91. package/node_modules/@docx-editor.dev/core/dist/chunk-2GO5T2JU.cjs +1 -0
  92. package/node_modules/@docx-editor.dev/core/dist/chunk-2RC2EPND.js +3 -0
  93. package/node_modules/@docx-editor.dev/core/dist/chunk-4GBTELJV.cjs +28 -0
  94. package/node_modules/@docx-editor.dev/core/dist/chunk-4R3TEXMN.js +18 -0
  95. package/node_modules/@docx-editor.dev/core/dist/chunk-5CSUYANV.js +1 -0
  96. package/node_modules/@docx-editor.dev/core/dist/chunk-6APGXLBB.cjs +3 -0
  97. package/node_modules/@docx-editor.dev/core/dist/chunk-6AWEKBLB.cjs +1 -0
  98. package/node_modules/@docx-editor.dev/core/dist/chunk-6EYYL7FL.js +1 -0
  99. package/node_modules/@docx-editor.dev/core/dist/chunk-6JIJOZDW.js +1 -0
  100. package/node_modules/@docx-editor.dev/core/dist/chunk-BTQKU64Q.cjs +1 -0
  101. package/node_modules/@docx-editor.dev/core/dist/chunk-E7BQA6UP.js +2 -0
  102. package/node_modules/@docx-editor.dev/core/dist/chunk-EO4C5QJW.cjs +2 -0
  103. package/node_modules/@docx-editor.dev/core/dist/chunk-ETTO6GK3.js +1 -0
  104. package/node_modules/@docx-editor.dev/core/dist/chunk-FIJZIQXA.cjs +18 -0
  105. package/node_modules/@docx-editor.dev/core/dist/chunk-FRXAOVTB.js +28 -0
  106. package/node_modules/@docx-editor.dev/core/dist/chunk-J6BVWIDB.js +2 -0
  107. package/node_modules/@docx-editor.dev/core/dist/chunk-JGNVNT2A.cjs +2 -0
  108. package/node_modules/@docx-editor.dev/core/dist/chunk-K5U2PLDP.cjs +2 -0
  109. package/node_modules/@docx-editor.dev/core/dist/chunk-KKIJG3C6.js +2 -0
  110. package/node_modules/@docx-editor.dev/core/dist/chunk-LWDSDCMO.js +27 -0
  111. package/node_modules/@docx-editor.dev/core/dist/chunk-NBCVVZOM.cjs +1 -0
  112. package/node_modules/@docx-editor.dev/core/dist/chunk-O2AL2HSJ.cjs +1 -0
  113. package/node_modules/@docx-editor.dev/core/dist/chunk-O5INAWZQ.js +1 -0
  114. package/node_modules/@docx-editor.dev/core/dist/chunk-QMLCVPCD.cjs +1 -0
  115. package/node_modules/@docx-editor.dev/core/dist/chunk-RCHS4ZEH.cjs +27 -0
  116. package/node_modules/@docx-editor.dev/core/dist/chunk-RIYSCEFQ.js +2 -0
  117. package/node_modules/@docx-editor.dev/core/dist/chunk-S6J4O5XP.js +1 -0
  118. package/node_modules/@docx-editor.dev/core/dist/chunk-SRPILEWV.cjs +5 -0
  119. package/node_modules/@docx-editor.dev/core/dist/chunk-TSLBZ26X.js +1 -0
  120. package/node_modules/@docx-editor.dev/core/dist/chunk-UKVVUHZL.cjs +1 -0
  121. package/node_modules/@docx-editor.dev/core/dist/chunk-VDNNLG6X.js +2 -0
  122. package/node_modules/@docx-editor.dev/core/dist/chunk-VHAVHCQY.js +7 -0
  123. package/node_modules/@docx-editor.dev/core/dist/chunk-VX43VBAX.cjs +7 -0
  124. package/node_modules/@docx-editor.dev/core/dist/chunk-Z6WBFXJU.js +5 -0
  125. package/node_modules/@docx-editor.dev/core/dist/chunk-ZUHOMK52.cjs +2 -0
  126. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.cjs +1 -0
  127. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.d.ts +270 -0
  128. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.js +1 -0
  129. package/node_modules/@docx-editor.dev/core/dist/collaboration.cjs +1 -0
  130. package/node_modules/@docx-editor.dev/core/dist/collaboration.d.ts +269 -0
  131. package/node_modules/@docx-editor.dev/core/dist/collaboration.js +1 -0
  132. package/node_modules/@docx-editor.dev/core/dist/contracts/document.cjs +1 -0
  133. package/node_modules/@docx-editor.dev/core/dist/contracts/document.d.ts +290 -0
  134. package/node_modules/@docx-editor.dev/core/dist/contracts/document.js +0 -0
  135. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.cjs +1 -0
  136. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.d.ts +22 -0
  137. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.js +1 -0
  138. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.cjs +1 -0
  139. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.d.ts +103 -0
  140. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.js +0 -0
  141. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.cjs +1 -0
  142. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.d.ts +143 -0
  143. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.js +1 -0
  144. package/node_modules/@docx-editor.dev/core/dist/contracts/types.cjs +1 -0
  145. package/node_modules/@docx-editor.dev/core/dist/contracts/types.d.ts +11 -0
  146. package/node_modules/@docx-editor.dev/core/dist/contracts/types.js +0 -0
  147. package/node_modules/@docx-editor.dev/core/dist/custom-node-writes-cvL5rhcD.d.ts +323 -0
  148. package/node_modules/@docx-editor.dev/core/dist/dist-PKZR6RSH.js +2 -0
  149. package/node_modules/@docx-editor.dev/core/dist/document-protection-BAGVGqaP.d.ts +20 -0
  150. package/node_modules/@docx-editor.dev/core/dist/editor-Ci7IZGmG.d.ts +2448 -0
  151. package/node_modules/@docx-editor.dev/core/dist/editor-scope-OHPwVQ5l.d.ts +84 -0
  152. package/node_modules/@docx-editor.dev/core/dist/editor.cjs +1 -0
  153. package/node_modules/@docx-editor.dev/core/dist/editor.css +15 -0
  154. package/node_modules/@docx-editor.dev/core/dist/editor.d.ts +1394 -0
  155. package/node_modules/@docx-editor.dev/core/dist/editor.js +1 -0
  156. package/node_modules/@docx-editor.dev/core/dist/export.cjs +2 -0
  157. package/node_modules/@docx-editor.dev/core/dist/export.d.ts +391 -0
  158. package/node_modules/@docx-editor.dev/core/dist/export.js +2 -0
  159. package/node_modules/@docx-editor.dev/core/dist/failure-NS2lsya4.d.ts +115 -0
  160. package/node_modules/@docx-editor.dev/core/dist/font-resolver-BVQB14qT.d.ts +256 -0
  161. package/node_modules/@docx-editor.dev/core/dist/harfbuzz.wasm +0 -0
  162. package/node_modules/@docx-editor.dev/core/dist/headless-document-view-qH331moE.d.ts +143 -0
  163. package/node_modules/@docx-editor.dev/core/dist/image-resources-BN-hUgCn.d.ts +211 -0
  164. package/node_modules/@docx-editor.dev/core/dist/index-Bsg7oIKP.d.ts +3869 -0
  165. package/node_modules/@docx-editor.dev/core/dist/index.cjs +1 -0
  166. package/node_modules/@docx-editor.dev/core/dist/index.d.ts +53 -0
  167. package/node_modules/@docx-editor.dev/core/dist/index.js +1 -0
  168. package/node_modules/@docx-editor.dev/core/dist/layout-shaping-BEyuiQOk.d.ts +246 -0
  169. package/node_modules/@docx-editor.dev/core/dist/layout.cjs +1 -0
  170. package/node_modules/@docx-editor.dev/core/dist/layout.d.ts +3151 -0
  171. package/node_modules/@docx-editor.dev/core/dist/layout.js +1 -0
  172. package/node_modules/@docx-editor.dev/core/dist/node-module-shim-TTKTT66I.js +1 -0
  173. package/node_modules/@docx-editor.dev/core/dist/note-properties-4Y9o6Gyk.d.ts +68 -0
  174. package/node_modules/@docx-editor.dev/core/dist/omml-equation-CuzBL5DD.d.ts +85 -0
  175. package/node_modules/@docx-editor.dev/core/dist/output.cjs +1 -0
  176. package/node_modules/@docx-editor.dev/core/dist/output.d.ts +97 -0
  177. package/node_modules/@docx-editor.dev/core/dist/output.js +1 -0
  178. package/node_modules/@docx-editor.dev/core/dist/protocol-Bqk4Izjc.d.ts +1651 -0
  179. package/node_modules/@docx-editor.dev/core/dist/review-pane-D9jm8DcY.d.ts +128 -0
  180. package/node_modules/@docx-editor.dev/core/dist/review-paragraph-order-DT-n6ouC.d.ts +85 -0
  181. package/node_modules/@docx-editor.dev/core/dist/revision-projection-DZ4kKVev.d.ts +242 -0
  182. package/node_modules/@docx-editor.dev/core/dist/semantic-cell-selection-D9D1KSXq.d.ts +464 -0
  183. package/node_modules/@docx-editor.dev/core/dist/semantic-interaction-CIC-PooQ.d.ts +135 -0
  184. package/node_modules/@docx-editor.dev/core/dist/semantic-paint-BME37OMv.d.ts +326 -0
  185. package/node_modules/@docx-editor.dev/core/dist/semantic-record-queries-CBlZqZNa.d.ts +177 -0
  186. package/node_modules/@docx-editor.dev/core/dist/semantic-records-4B3WwFAi.d.ts +3532 -0
  187. package/node_modules/@docx-editor.dev/core/dist/store.cjs +1 -0
  188. package/node_modules/@docx-editor.dev/core/dist/store.d.ts +2706 -0
  189. package/node_modules/@docx-editor.dev/core/dist/store.js +1 -0
  190. package/node_modules/@docx-editor.dev/core/dist/tree-package-fragment-BeeKxDw8.d.ts +1201 -0
  191. package/node_modules/@docx-editor.dev/core/dist/tree-session-contract-CVbmlMlq.d.ts +664 -0
  192. package/node_modules/@docx-editor.dev/core/dist/types-barrel-D3xCgQX6.d.ts +4269 -0
  193. package/node_modules/@docx-editor.dev/core/licenses/HarfBuzz-COPYING.txt +42 -0
  194. package/node_modules/@docx-editor.dev/core/package.json +140 -0
  195. package/node_modules/@docx-editor.dev/react/LICENSE +201 -0
  196. package/node_modules/@docx-editor.dev/react/README.md +141 -0
  197. package/node_modules/@docx-editor.dev/react/THIRD_PARTY_NOTICES.md +18 -0
  198. package/node_modules/@docx-editor.dev/react/dist/index.d.mts +4928 -0
  199. package/node_modules/@docx-editor.dev/react/dist/index.d.ts +4928 -0
  200. package/node_modules/@docx-editor.dev/react/dist/index.js +4 -0
  201. package/node_modules/@docx-editor.dev/react/dist/index.mjs +4 -0
  202. package/node_modules/@docx-editor.dev/react/package.json +74 -0
  203. package/node_modules/@docx-editor.dev/react/src/styles/editor.css +6 -0
  204. package/node_modules/@docx-editor.dev/react/src/styles/zIndex.ts +28 -0
  205. package/package.json +26 -15
  206. package/src/docx/README.md +10 -0
  207. package/src/docx/styles.css +73 -5
  208. package/dist/chunk-FAGQTB3D.cjs.map +0 -1
  209. package/dist/chunk-MYALCKDR.js.map +0 -1
@@ -0,0 +1,4269 @@
1
+ import { c as HistoryGroupOutcome } from './editor-scope-OHPwVQ5l.js';
2
+
3
+ /**
4
+ * How a tracked change is addressed: `@w:id`, `@w:author` and `@w:date` together, within a
5
+ * part.
6
+ *
7
+ * All of them, always. `@w:id` is unique only within a part, so an id alone names two
8
+ * revisions in any package with a header or a comments part — and it is not author-scoped
9
+ * either, so `(part, id)` would merge two authors' distinct revisions. One logical revision is
10
+ * also deliberately many elements sharing an id, as a tracked row insertion is, which no
11
+ * uniqueness rule could express.
12
+ */
13
+ interface RevisionAddress {
14
+ readonly id: string;
15
+ readonly author: string;
16
+ /** Absent when the file wrote no `@w:date`; part of the identity either way. */
17
+ readonly date?: string;
18
+ }
19
+ /** The author and timestamp a tracked edit is recorded under. */
20
+ interface RevisionAttributionInput {
21
+ readonly author: string;
22
+ /** ISO-8601. Omitted writes no `@w:date`. */
23
+ readonly date?: string;
24
+ }
25
+
26
+ /**
27
+ * One parsed XML node, preserving significant order, whitespace and raw lexical values.
28
+ *
29
+ * Attribute records have a NULL prototype: attribute names come from a file and become object
30
+ * keys, so `__proto__` must be inert by construction rather than by filtering.
31
+ */
32
+ type XmlNode = {
33
+ readonly type: 'element';
34
+ readonly name: string;
35
+ readonly attributes: Readonly<Record<string, string>>;
36
+ readonly children: readonly XmlNode[];
37
+ } | {
38
+ readonly type: 'text';
39
+ readonly value: string;
40
+ };
41
+ /**
42
+ * Why XML was refused at the trust boundary.
43
+ *
44
+ * DTDs, entity declarations and external-entity references are PRE-rejected before parsing —
45
+ * blocking XXE and billion-laughs by never handing the parser the construct, rather than by
46
+ * trusting it to be configured safely.
47
+ */
48
+ type XmlRejection = 'too-large' | 'dtd-forbidden' | 'entity-forbidden' | 'too-deep' | 'too-many-elements' | 'invalid-limits' | 'parse-error';
49
+ /** A parsed document, or a typed refusal. Never throws — the input is untrusted. */
50
+ type XmlResult = {
51
+ readonly ok: true;
52
+ readonly nodes: readonly XmlNode[];
53
+ } | {
54
+ readonly ok: false;
55
+ readonly reason: XmlRejection;
56
+ };
57
+ /** Per-part caps on size, element count and depth. Clamped into the hard ceilings. */
58
+ interface XmlLimits {
59
+ readonly maxBytes: number;
60
+ /** Element budget; may raise or lower the engine default, up to its hard ceiling. */
61
+ readonly maxElements?: number;
62
+ }
63
+ /** Read XML into an ordered tree, refusing DTDs/entities and bounding size. */
64
+ /**
65
+ * Read XML at the trust boundary: bounded, entity-free, and fidelity-preserving.
66
+ *
67
+ * Pre-rejects DTDs and entity constructs, disables expansion and value coercion, and keeps child
68
+ * order, attributes, whitespace and raw lexical form — everything a lossless re-emit needs.
69
+ */
70
+ declare function readXml(xml: string, limits?: XmlLimits): XmlResult;
71
+ /** Find the first descendant element with the given qualified name. */
72
+ declare function findElement(nodes: readonly XmlNode[], name: string): Extract<XmlNode, {
73
+ type: 'element';
74
+ }> | undefined;
75
+ /** All direct child elements with the given name. */
76
+ declare function childElements(node: Extract<XmlNode, {
77
+ type: 'element';
78
+ }>, name: string): Extract<XmlNode, {
79
+ type: 'element';
80
+ }>[];
81
+ /** Concatenated text content of an element (all descendant text nodes). */
82
+ declare function textContent(node: Extract<XmlNode, {
83
+ type: 'element';
84
+ }>): string;
85
+
86
+ /** The WordprocessingML main namespace — the `w:` prefix in every `word/document.xml`. */
87
+ declare const WML_NAMESPACE_URI = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
88
+ /** The reserved `xml:` namespace, which carries `xml:space`. */
89
+ declare const XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
90
+ /** The reserved `xmlns:` namespace that namespace declarations themselves live in. */
91
+ declare const XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/";
92
+ /** The `w14` wordml-2010 extension namespace — `w14:paraId`/`w14:textId` live here. */
93
+ declare const W14_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2010/wordml";
94
+ declare const DRAWINGML_MAIN_NAMESPACE_URI = "http://schemas.openxmlformats.org/drawingml/2006/main";
95
+ declare const WP_NAMESPACE_URI = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
96
+ declare const PIC_NAMESPACE_URI = "http://schemas.openxmlformats.org/drawingml/2006/picture";
97
+ /** The four content-position revision wrappers, which nest and carry runs. */
98
+ declare function isContentRevisionKind(kind: OoxmlNode['kind']): kind is 'revisionInsert' | 'revisionDelete' | 'revisionMoveFrom' | 'revisionMoveTo';
99
+ /** Move-range and comment-range boundary markers, which are empty and sit between runs. */
100
+ declare function isRangeMarkerKind(kind: OoxmlNode['kind']): kind is 'moveFromRangeStart' | 'moveFromRangeEnd' | 'moveToRangeStart' | 'moveToRangeEnd' | 'commentRangeStart' | 'commentRangeEnd';
101
+ /**
102
+ * OOXML on/off toggle: on only when a same-namespace child is present and its `w:val`
103
+ * (same namespace as the child) does not explicitly disable. Foreign-namespace siblings
104
+ * with the same local name cannot turn the flag on.
105
+ */
106
+ declare function readOnOffChild(parent: OoxmlNode, localName: string, namespaceUri?: string): boolean;
107
+
108
+ /**
109
+ * A node's stable identity within its part.
110
+ *
111
+ * Minted deterministically from the structural path at parse, then RETAINED through structural
112
+ * sharing — the same bytes always produce the same ids, and an edit elsewhere in the document
113
+ * does not renumber untouched nodes. Every tree op addresses nodes by these.
114
+ */
115
+ type OoxmlNodeId = string;
116
+ /**
117
+ * One `xmlns:` declaration carried on a node.
118
+ *
119
+ * Preserved rather than normalized away: a document that binds `w14` at the root and a document
120
+ * that binds it on a paragraph are different bytes, and re-emitting the wrong one is a fidelity
121
+ * loss even though the semantics match.
122
+ */
123
+ interface OoxmlNamespaceBinding {
124
+ readonly prefix: string;
125
+ readonly namespaceUri: string;
126
+ }
127
+ interface OoxmlAttributeBase {
128
+ readonly namespaceUri: string;
129
+ readonly localName: string;
130
+ readonly prefix?: string;
131
+ readonly value: string;
132
+ }
133
+ /** `xml:space`, which decides whether a run's leading and trailing whitespace survives. */
134
+ interface OoxmlXmlSpaceAttribute extends OoxmlAttributeBase {
135
+ readonly kind: 'xmlSpace';
136
+ readonly namespaceUri: typeof XML_NAMESPACE_URI;
137
+ readonly localName: 'space';
138
+ readonly prefix: 'xml';
139
+ readonly value: 'default' | 'preserve';
140
+ }
141
+ /** `w:val` — the attribute nearly every WordprocessingML property carries its value in. */
142
+ interface OoxmlWmlValAttribute extends OoxmlAttributeBase {
143
+ readonly kind: 'wmlVal';
144
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
145
+ readonly localName: 'val';
146
+ }
147
+ /**
148
+ * Any attribute outside the typed vocabulary, carried verbatim.
149
+ *
150
+ * Where losslessness actually happens: an attribute this engine has no model for is preserved
151
+ * exactly rather than dropped, so a save re-emits what the file said.
152
+ */
153
+ interface OoxmlGenericExtensionAttribute extends OoxmlAttributeBase {
154
+ readonly kind: 'genericExtension';
155
+ }
156
+ /** Any attribute on any node: the two typed ones, plus the verbatim catch-all. */
157
+ type OoxmlAttribute = OoxmlXmlSpaceAttribute | OoxmlWmlValAttribute | OoxmlGenericExtensionAttribute;
158
+ /**
159
+ * Attributes a TYPED node may carry.
160
+ *
161
+ * Excludes `w:val` on purpose: a node the engine models keeps its value in typed fields, and
162
+ * allowing a stray `w:val` alongside them would create two sources of truth for one property.
163
+ */
164
+ type OoxmlKnownNodeAttribute = OoxmlXmlSpaceAttribute | OoxmlGenericExtensionAttribute;
165
+ interface OoxmlElementBase<Children extends readonly OoxmlNode[] = readonly OoxmlNode[], Attributes extends readonly OoxmlAttribute[] = readonly OoxmlAttribute[]> {
166
+ readonly id: OoxmlNodeId;
167
+ readonly namespaceUri: string;
168
+ readonly localName: string;
169
+ /** Authored prefix retained as non-authoritative fidelity evidence. */
170
+ readonly prefix?: string;
171
+ /** Namespace declarations authored directly on this element, in source order. */
172
+ readonly namespaceBindings: readonly OoxmlNamespaceBinding[];
173
+ readonly attributes: Attributes;
174
+ readonly children: Children;
175
+ }
176
+ /** `w:document` — the root of a main document part. */
177
+ interface OoxmlDocumentNode extends OoxmlElementBase<readonly (OoxmlBodyNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
178
+ readonly kind: 'document';
179
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
180
+ readonly localName: 'document';
181
+ }
182
+ /** `w:body` — the main story's block content. */
183
+ interface OoxmlBodyNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlContentControlNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
184
+ readonly kind: 'body';
185
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
186
+ readonly localName: 'body';
187
+ }
188
+ interface OoxmlTableNode extends OoxmlElementBase<readonly (OoxmlTablePropertiesNode | OoxmlTableGridNode | OoxmlTableRowNode | OoxmlContentControlNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
189
+ readonly kind: 'table';
190
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
191
+ readonly localName: 'tbl';
192
+ }
193
+ interface OoxmlTableRowNode extends OoxmlElementBase<readonly (OoxmlTableCellNode | OoxmlContentControlNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
194
+ readonly kind: 'tableRow';
195
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
196
+ readonly localName: 'tr';
197
+ }
198
+ interface OoxmlTableCellNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlContentControlNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
199
+ readonly kind: 'tableCell';
200
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
201
+ readonly localName: 'tc';
202
+ }
203
+ /** Grid children (`w:gridCol`) stay generic: they are property leaves, not structure. */
204
+ interface OoxmlTableGridNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
205
+ readonly kind: 'tableGrid';
206
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
207
+ readonly localName: 'tblGrid';
208
+ }
209
+ /** Property children stay generic, mirroring `runProperties`. */
210
+ interface OoxmlTablePropertiesNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
211
+ readonly kind: 'tableProperties';
212
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
213
+ readonly localName: 'tblPr';
214
+ }
215
+ /**
216
+ * `w:p` — a paragraph, and the unit every offset in this engine is relative to.
217
+ *
218
+ * Positions are addressed as this node's id plus a UTF-16 offset, which is what makes a paragraph
219
+ * inside a table cell no different from one at the top level.
220
+ */
221
+ interface OoxmlParagraphNode extends OoxmlElementBase<readonly (OoxmlParagraphPropertiesNode | OoxmlRunNode | OoxmlHyperlinkNode | OoxmlContentControlNode | OoxmlBookmarkStartNode | OoxmlBookmarkEndNode | OoxmlRevisionContentNode | OoxmlRangeMarkerNode | OoxmlFldSimpleNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
222
+ readonly kind: 'paragraph';
223
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
224
+ readonly localName: 'p';
225
+ }
226
+ /**
227
+ * `CT_Hyperlink` (ECMA-376 §17.16.22) — a RUN CONTAINER, not a leaf.
228
+ *
229
+ * Its runs are part of the paragraph's inline sequence: they measure, paint, select and
230
+ * take offsets exactly like a run written directly under the `w:p`. Typing the element is
231
+ * what lets them in; while it was generic, its runs never reached the token stream and the
232
+ * words inside every link simply did not paint.
233
+ *
234
+ * Targets live in the ATTRIBUTES, and §17.16.22 declares exactly six. They divide into two
235
+ * groups, and the difference is load-bearing:
236
+ *
237
+ * MODELED `r:id` (a relationship, resolved against the owning part's rels), `w:anchor`
238
+ * (a bookmark name in this document) and `w:tooltip`. These are the three the
239
+ * ops read and write — `setHyperlinkTarget` sets one target attribute and
240
+ * CLEARS the other, so a link never carries both and resolves by the wrong one.
241
+ *
242
+ * PRESERVED `w:tgtFrame`, `w:docLocation` and `w:history`. Nothing in this engine
243
+ * interprets them and no op names them; they survive because attributes are
244
+ * carried verbatim, and `setHyperlinkTarget` must leave them exactly as
245
+ * authored. That is a REQUIREMENT, not an incidental property of the current
246
+ * applier: `w:docLocation` names a location inside the target document, so
247
+ * silently dropping it on a retarget would change where a link goes.
248
+ * `hyperlink-lossless-editing.test.ts` pins both against a retarget.
249
+ *
250
+ * Nothing here is a runtime URL — the sanitized projection is computed separately (see
251
+ * `hyperlinkTargetOf`), and only that reaches a DOM or navigation sink.
252
+ *
253
+ * Bookmark markers are admitted as children because Word writes them inside links; anything
254
+ * else it can carry (a drawing, a field, a nested SDT) stays `generic` at its position, so a
255
+ * link around a picture keeps both the picture and the link.
256
+ *
257
+ * A link may contain ANOTHER link: §17.16.22's content model is `EG_PContent`, which lists
258
+ * `w:hyperlink` among its own members. That is why this child union is self-referential
259
+ * rather than bottoming out at runs. Demoting the inner one to `generic` would have been the
260
+ * easier type, and it would have reintroduced exactly the bug typing this element fixed —
261
+ * a generic link's runs never reach the token stream, so the words inside it stop painting.
262
+ * Every walk that descends a link therefore recurses (`segmentsOf`, `runsUnder`,
263
+ * `runPropertyEdits`) instead of descending one level.
264
+ */
265
+ interface OoxmlHyperlinkNode extends OoxmlElementBase<readonly (OoxmlRunNode | OoxmlHyperlinkNode | OoxmlContentControlNode | OoxmlBookmarkStartNode | OoxmlBookmarkEndNode | OoxmlRevisionContentNode | OoxmlRangeMarkerNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
266
+ readonly kind: 'hyperlink';
267
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
268
+ readonly localName: 'hyperlink';
269
+ }
270
+ /**
271
+ * A content-position revision wrapper — `w:ins`, `w:del`, `w:moveFrom`, `w:moveTo`.
272
+ *
273
+ * These wrap runs, so a walk that visits only direct `run` children never reaches
274
+ * the content inside them. Typing them is what lets layout descend deliberately
275
+ * rather than treating tracked content as unknown markup.
276
+ *
277
+ * ECMA-376 §17.13.5.18/.14/.25/.29. All four extend `CT_TrackChange`: `@w:id` and
278
+ * `@w:author` are required, `@w:date` is optional and is never fabricated.
279
+ *
280
+ * The SAME element names appear in property positions — `w:pPr/w:rPr/w:ins` marks a
281
+ * paragraph mark, `w:trPr/w:del` marks a row — where they carry no content and mean
282
+ * something structurally different. Those stay generic; see `contentRevisionKind`.
283
+ */
284
+ interface OoxmlRevisionContentNode extends OoxmlElementBase<readonly (OoxmlRunNode | OoxmlRevisionContentNode | OoxmlHyperlinkNode | OoxmlRangeMarkerNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
285
+ readonly kind: 'revisionInsert' | 'revisionDelete' | 'revisionMoveFrom' | 'revisionMoveTo';
286
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
287
+ readonly localName: 'ins' | 'del' | 'moveFrom' | 'moveTo';
288
+ }
289
+ /**
290
+ * `w:bookmarkStart` — a ZERO-LENGTH point anchor (`@w:id`, `@w:name`).
291
+ *
292
+ * It takes no text offset and paints nothing; it only marks a position, which is what an
293
+ * internal hyperlink's `w:anchor` names. Split and join place it by that position, the
294
+ * behaviour `tree-op-split-anchors.test.ts` pins.
295
+ */
296
+ interface OoxmlBookmarkStartNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
297
+ readonly kind: 'bookmarkStart';
298
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
299
+ readonly localName: 'bookmarkStart';
300
+ }
301
+ /** `w:bookmarkEnd` — the closing point anchor (`@w:id`), zero-length like its start. */
302
+ interface OoxmlBookmarkEndNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
303
+ readonly kind: 'bookmarkEnd';
304
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
305
+ readonly localName: 'bookmarkEnd';
306
+ }
307
+ /**
308
+ * A range marker: the move-range and comment-range boundaries.
309
+ *
310
+ * Three of the base types in this family disagree, and the disagreement is load-bearing:
311
+ *
312
+ * - `w:moveFromRangeStart` / `w:moveToRangeStart` are `CT_MoveBookmark` (§17.13.5.22/.26):
313
+ * `@w:name`, `@w:author`, and `@w:date` are all REQUIRED.
314
+ * - `w:moveFromRangeEnd` / `w:moveToRangeEnd` / `w:commentRangeStart` / `w:commentRangeEnd`
315
+ * are `CT_MarkupRange` (§17.13.5.21): `@w:id` only, with NO author and NO date. Requiring
316
+ * provenance here refuses valid files; writing it emits invalid XML.
317
+ *
318
+ * Two different join keys ride on these: `@w:name` pairs a `moveFrom` range with its
319
+ * `moveTo` range, while `@w:id` pairs a range start with its own range end. In a real
320
+ * document the two halves of a named pair carry different ids, so neither key substitutes
321
+ * for the other.
322
+ */
323
+ interface OoxmlRangeMarkerNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
324
+ readonly kind: 'moveFromRangeStart' | 'moveFromRangeEnd' | 'moveToRangeStart' | 'moveToRangeEnd' | 'commentRangeStart' | 'commentRangeEnd';
325
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
326
+ readonly localName: 'moveFromRangeStart' | 'moveFromRangeEnd' | 'moveToRangeStart' | 'moveToRangeEnd' | 'commentRangeStart' | 'commentRangeEnd';
327
+ }
328
+ /** `w:commentReference` — the in-run mark that carries the comment's anchor point. */
329
+ interface OoxmlCommentReferenceNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
330
+ readonly kind: 'commentReference';
331
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
332
+ readonly localName: 'commentReference';
333
+ }
334
+ /** The `word/comments.xml` root (`CT_Comments`, §17.13.4.2). */
335
+ interface OoxmlCommentsNode extends OoxmlElementBase<readonly (OoxmlCommentNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
336
+ readonly kind: 'comments';
337
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
338
+ readonly localName: 'comments';
339
+ }
340
+ /**
341
+ * One comment (`CT_Comment`, §17.13.4.4) — `CT_TrackChange` plus `@w:initials`, holding
342
+ * block content. The block content is why a comment body is a story rather than a string.
343
+ */
344
+ interface OoxmlCommentNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
345
+ readonly kind: 'comment';
346
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
347
+ readonly localName: 'comment';
348
+ }
349
+ /** `w:r` — a run: text and atoms sharing one set of character properties. */
350
+ interface OoxmlRunNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlTextElementNode | OoxmlDeletedTextNode | OoxmlTabNode | OoxmlHardBreakNode | OoxmlCommentReferenceNode | OoxmlFldCharNode | OoxmlInstrTextNode | OoxmlNoteReferenceNode | OoxmlNoteRefNode | OoxmlSeparatorNode | OoxmlContinuationSeparatorNode | OoxmlDrawingNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
351
+ readonly kind: 'run';
352
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
353
+ readonly localName: 'r';
354
+ }
355
+ /** `w:drawing` — run content only; exactly one typed inline or anchored child. */
356
+ interface OoxmlDrawingNode extends OoxmlElementBase<readonly (OoxmlInlineDrawingNode | OoxmlAnchoredDrawingNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
357
+ readonly kind: 'drawing';
358
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
359
+ readonly localName: 'drawing';
360
+ }
361
+ /** `wp:inline` / `wp:anchor` shared payload children. */
362
+ type OoxmlDrawingAnchorChild = OoxmlDrawingExtentNode | OoxmlDrawingEffectExtentNode | OoxmlDrawingDocPrNode | OoxmlDrawingGraphicFramePrNode | OoxmlDrawingGraphicNode | OoxmlDrawingSimplePosNode | OoxmlDrawingPositionHNode | OoxmlDrawingPositionVNode | OoxmlDrawingWrapNoneNode | OoxmlDrawingWrapSquareNode | OoxmlDrawingWrapTightNode | OoxmlDrawingWrapThroughNode | OoxmlDrawingWrapTopBottomNode | OoxmlGenericElementNode;
363
+ /** `wp:inline` (`CT_Inline`) — typed only under `w:drawing`. */
364
+ interface OoxmlInlineDrawingNode extends OoxmlElementBase<readonly OoxmlDrawingAnchorChild[], readonly OoxmlKnownNodeAttribute[]> {
365
+ readonly kind: 'inlineDrawing';
366
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
367
+ readonly localName: 'inline';
368
+ }
369
+ /** `wp:anchor` (`CT_Anchor`) — typed only under `w:drawing`. */
370
+ interface OoxmlAnchoredDrawingNode extends OoxmlElementBase<readonly OoxmlDrawingAnchorChild[], readonly OoxmlKnownNodeAttribute[]> {
371
+ readonly kind: 'anchoredDrawing';
372
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
373
+ readonly localName: 'anchor';
374
+ }
375
+ interface OoxmlDrawingExtentNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
376
+ readonly kind: 'drawingExtent';
377
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
378
+ readonly localName: 'extent';
379
+ }
380
+ interface OoxmlDrawingEffectExtentNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
381
+ readonly kind: 'drawingEffectExtent';
382
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
383
+ readonly localName: 'effectExtent';
384
+ }
385
+ interface OoxmlDrawingDocPrNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
386
+ readonly kind: 'drawingDocPr';
387
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
388
+ readonly localName: 'docPr';
389
+ }
390
+ interface OoxmlDrawingGraphicFramePrNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
391
+ readonly kind: 'drawingGraphicFramePr';
392
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
393
+ readonly localName: 'cNvGraphicFramePr';
394
+ }
395
+ interface OoxmlDrawingGraphicNode extends OoxmlElementBase<readonly (OoxmlDrawingGraphicDataNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
396
+ readonly kind: 'drawingGraphic';
397
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
398
+ readonly localName: 'graphic';
399
+ }
400
+ interface OoxmlDrawingGraphicDataNode extends OoxmlElementBase<readonly (OoxmlPictureNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
401
+ readonly kind: 'drawingGraphicData';
402
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
403
+ readonly localName: 'graphicData';
404
+ }
405
+ interface OoxmlDrawingSimplePosNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
406
+ readonly kind: 'drawingSimplePos';
407
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
408
+ readonly localName: 'simplePos';
409
+ }
410
+ interface OoxmlDrawingPositionHNode extends OoxmlElementBase<readonly (OoxmlDrawingPositionAlignNode | OoxmlDrawingPositionOffsetNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
411
+ readonly kind: 'drawingPositionH';
412
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
413
+ readonly localName: 'positionH';
414
+ }
415
+ interface OoxmlDrawingPositionVNode extends OoxmlElementBase<readonly (OoxmlDrawingPositionAlignNode | OoxmlDrawingPositionOffsetNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
416
+ readonly kind: 'drawingPositionV';
417
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
418
+ readonly localName: 'positionV';
419
+ }
420
+ interface OoxmlDrawingPositionAlignNode extends OoxmlElementBase<readonly (OoxmlTextNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
421
+ readonly kind: 'drawingPositionAlign';
422
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
423
+ readonly localName: 'align';
424
+ }
425
+ interface OoxmlDrawingPositionOffsetNode extends OoxmlElementBase<readonly (OoxmlTextNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
426
+ readonly kind: 'drawingPositionOffset';
427
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
428
+ readonly localName: 'posOffset';
429
+ }
430
+ interface OoxmlDrawingWrapNoneNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
431
+ readonly kind: 'drawingWrapNone';
432
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
433
+ readonly localName: 'wrapNone';
434
+ }
435
+ interface OoxmlDrawingWrapSquareNode extends OoxmlElementBase<readonly (OoxmlDrawingEffectExtentNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
436
+ readonly kind: 'drawingWrapSquare';
437
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
438
+ readonly localName: 'wrapSquare';
439
+ }
440
+ interface OoxmlDrawingWrapTightNode extends OoxmlElementBase<readonly (OoxmlDrawingWrapPolygonNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
441
+ readonly kind: 'drawingWrapTight';
442
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
443
+ readonly localName: 'wrapTight';
444
+ }
445
+ interface OoxmlDrawingWrapThroughNode extends OoxmlElementBase<readonly (OoxmlDrawingWrapPolygonNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
446
+ readonly kind: 'drawingWrapThrough';
447
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
448
+ readonly localName: 'wrapThrough';
449
+ }
450
+ interface OoxmlDrawingWrapTopBottomNode extends OoxmlElementBase<readonly (OoxmlDrawingEffectExtentNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
451
+ readonly kind: 'drawingWrapTopBottom';
452
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
453
+ readonly localName: 'wrapTopAndBottom';
454
+ }
455
+ interface OoxmlDrawingWrapPolygonNode extends OoxmlElementBase<readonly (OoxmlDrawingWrapPolygonStartNode | OoxmlDrawingWrapPolygonLineToNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
456
+ readonly kind: 'drawingWrapPolygon';
457
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
458
+ readonly localName: 'wrapPolygon';
459
+ }
460
+ interface OoxmlDrawingWrapPolygonStartNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
461
+ readonly kind: 'drawingWrapPolygonStart';
462
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
463
+ readonly localName: 'start';
464
+ }
465
+ interface OoxmlDrawingWrapPolygonLineToNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
466
+ readonly kind: 'drawingWrapPolygonLineTo';
467
+ readonly namespaceUri: typeof WP_NAMESPACE_URI;
468
+ readonly localName: 'lineTo';
469
+ }
470
+ /** `pic:pic` (`CT_Picture`) — typed only under picture `a:graphicData`. */
471
+ interface OoxmlPictureNode extends OoxmlElementBase<readonly (OoxmlPictureNvPicPrNode | OoxmlPictureBlipFillNode | OoxmlPictureShapePropertiesNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
472
+ readonly kind: 'picture';
473
+ readonly namespaceUri: typeof PIC_NAMESPACE_URI;
474
+ readonly localName: 'pic';
475
+ }
476
+ interface OoxmlPictureNvPicPrNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
477
+ readonly kind: 'pictureNvPicPr';
478
+ readonly namespaceUri: typeof PIC_NAMESPACE_URI;
479
+ readonly localName: 'nvPicPr';
480
+ }
481
+ interface OoxmlPictureBlipFillNode extends OoxmlElementBase<readonly (OoxmlPictureBlipNode | OoxmlPictureSrcRectNode | OoxmlPictureStretchNode | OoxmlPictureTileNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
482
+ readonly kind: 'pictureBlipFill';
483
+ readonly namespaceUri: typeof PIC_NAMESPACE_URI;
484
+ readonly localName: 'blipFill';
485
+ }
486
+ interface OoxmlPictureBlipNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
487
+ readonly kind: 'pictureBlip';
488
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
489
+ readonly localName: 'blip';
490
+ }
491
+ interface OoxmlPictureSrcRectNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
492
+ readonly kind: 'pictureSrcRect';
493
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
494
+ readonly localName: 'srcRect';
495
+ }
496
+ interface OoxmlPictureStretchNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
497
+ readonly kind: 'pictureStretch';
498
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
499
+ readonly localName: 'stretch';
500
+ }
501
+ interface OoxmlPictureTileNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
502
+ readonly kind: 'pictureTile';
503
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
504
+ readonly localName: 'tile';
505
+ }
506
+ interface OoxmlPictureShapePropertiesNode extends OoxmlElementBase<readonly (OoxmlPictureTransformNode | OoxmlPicturePresetGeometryNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
507
+ readonly kind: 'pictureShapeProperties';
508
+ readonly namespaceUri: typeof PIC_NAMESPACE_URI;
509
+ readonly localName: 'spPr';
510
+ }
511
+ interface OoxmlPictureTransformNode extends OoxmlElementBase<readonly (OoxmlPictureTransformOffsetNode | OoxmlPictureTransformExtentNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
512
+ readonly kind: 'pictureTransform';
513
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
514
+ readonly localName: 'xfrm';
515
+ }
516
+ interface OoxmlPictureTransformOffsetNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
517
+ readonly kind: 'pictureTransformOffset';
518
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
519
+ readonly localName: 'off';
520
+ }
521
+ interface OoxmlPictureTransformExtentNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
522
+ readonly kind: 'pictureTransformExtent';
523
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
524
+ readonly localName: 'ext';
525
+ }
526
+ interface OoxmlPicturePresetGeometryNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
527
+ readonly kind: 'picturePresetGeometry';
528
+ readonly namespaceUri: typeof DRAWINGML_MAIN_NAMESPACE_URI;
529
+ readonly localName: 'prstGeom';
530
+ }
531
+ /**
532
+ * `w:delText` (§17.3.3.7) — the text container a run uses once its content is deleted.
533
+ *
534
+ * Structurally identical to `w:t`, and deliberately a DIFFERENT kind: it must never flow
535
+ * as ordinary text, and rejecting the deletion that contains it turns it back into `w:t`.
536
+ */
537
+ interface OoxmlDeletedTextNode extends OoxmlElementBase<readonly OoxmlTextNode[], readonly OoxmlKnownNodeAttribute[]> {
538
+ readonly kind: 'deletedText';
539
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
540
+ readonly localName: 'delText';
541
+ }
542
+ /**
543
+ * `w:rPr` — a run's character properties, whose children stay GENERIC.
544
+ *
545
+ * Deliberately unmodelled below this point: the property vocabulary is large and mostly
546
+ * uninteresting to layout, so carrying it verbatim preserves everything without the engine having
547
+ * to know what each element means.
548
+ */
549
+ interface OoxmlRunPropertiesNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
550
+ readonly kind: 'runProperties';
551
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
552
+ readonly localName: 'rPr';
553
+ }
554
+ /** `w:t` — the element holding a run's literal characters. */
555
+ interface OoxmlTextElementNode extends OoxmlElementBase<readonly OoxmlTextNode[], readonly OoxmlKnownNodeAttribute[]> {
556
+ readonly kind: 'text';
557
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
558
+ readonly localName: 't';
559
+ }
560
+ /** `w:pPr` — a paragraph's properties. Children stay generic, like `w:rPr`'s. */
561
+ interface OoxmlParagraphPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
562
+ readonly kind: 'paragraphProperties';
563
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
564
+ readonly localName: 'pPr';
565
+ }
566
+ /** `w:tab` inside a run — one tab character as its own element. */
567
+ interface OoxmlTabNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
568
+ readonly kind: 'tab';
569
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
570
+ readonly localName: 'tab';
571
+ }
572
+ /** `w:br` — a line, column or page break; `w:cr` — a manual line break. */
573
+ interface OoxmlHardBreakNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
574
+ readonly kind: 'hardBreak';
575
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
576
+ readonly localName: 'br' | 'cr';
577
+ }
578
+ /**
579
+ * Complex-field character (`w:fldChar`).
580
+ *
581
+ * Children stay generic so `w:ffData` (legacy form fields / macros) round-trips as inert
582
+ * payload and is never promoted to an executable surface. `@w:fldCharType`, `@w:dirty`,
583
+ * and `@w:fldLock` are preserved on `attributes`.
584
+ */
585
+ interface OoxmlFldCharNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]> {
586
+ readonly kind: 'fldChar';
587
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
588
+ readonly localName: 'fldChar';
589
+ }
590
+ /**
591
+ * Field instruction text (`w:instrText`), same text-carrier shape as `w:t`.
592
+ *
593
+ * Instruction strings are never executed; layout may recognize allowlisted page-number
594
+ * keywords only.
595
+ */
596
+ interface OoxmlInstrTextNode extends OoxmlElementBase<readonly OoxmlTextNode[], readonly OoxmlKnownNodeAttribute[]> {
597
+ readonly kind: 'instrText';
598
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
599
+ readonly localName: 'instrText';
600
+ }
601
+ /**
602
+ * Simple field (`w:fldSimple`) at paragraph content level.
603
+ *
604
+ * `@w:instr`, `@w:dirty`, and `@w:fldLock` round-trip on `attributes`. Cached result
605
+ * children stay structurally preserved; the field is one atomic addressable unit.
606
+ */
607
+ interface OoxmlFldSimpleNode extends OoxmlElementBase<readonly (OoxmlRunNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
608
+ readonly kind: 'fldSimple';
609
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
610
+ readonly localName: 'fldSimple';
611
+ }
612
+ /**
613
+ * Footnotes part root (`w:footnotes`). Children are typed notes or preserved generics.
614
+ * Never a story root itself — each note body is its own story for layout.
615
+ */
616
+ interface OoxmlFootnotesNode extends OoxmlElementBase<readonly (OoxmlNoteNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
617
+ readonly kind: 'footnotes';
618
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
619
+ readonly localName: 'footnotes';
620
+ }
621
+ /**
622
+ * Endnotes part root (`w:endnotes`). Same content model as {@link OoxmlFootnotesNode}.
623
+ */
624
+ interface OoxmlEndnotesNode extends OoxmlElementBase<readonly (OoxmlNoteNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
625
+ readonly kind: 'endnotes';
626
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
627
+ readonly localName: 'endnotes';
628
+ }
629
+ /**
630
+ * One footnote or endnote (`w:footnote` / `w:endnote`).
631
+ *
632
+ * Discriminated by `localName`. `@w:id` and optional `@w:type` (`ST_FtnEdn`, including
633
+ * authored `normal`) live on `attributes`. Children are ordinary block content.
634
+ */
635
+ interface OoxmlNoteNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
636
+ readonly kind: 'note';
637
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
638
+ readonly localName: 'footnote' | 'endnote';
639
+ }
640
+ /**
641
+ * Body citation (`w:footnoteReference` / `w:endnoteReference`) as a typed run child.
642
+ * Display mark is derived — never stored as text. One UTF-16 atom in addressing.
643
+ */
644
+ interface OoxmlNoteReferenceNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
645
+ readonly kind: 'noteReference';
646
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
647
+ readonly localName: 'footnoteReference' | 'endnoteReference';
648
+ }
649
+ /**
650
+ * Auto mark inside a note body (`w:footnoteRef` / `w:endnoteRef`).
651
+ * One UTF-16 atom; display digit is derived at paint time.
652
+ */
653
+ interface OoxmlNoteRefNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
654
+ readonly kind: 'noteRef';
655
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
656
+ readonly localName: 'footnoteRef' | 'endnoteRef';
657
+ }
658
+ /** Run-inner separator rule (`w:separator`). One UTF-16 atom. */
659
+ interface OoxmlSeparatorNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
660
+ readonly kind: 'separator';
661
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
662
+ readonly localName: 'separator';
663
+ }
664
+ /** Run-inner continuation separator (`w:continuationSeparator`). One UTF-16 atom. */
665
+ interface OoxmlContinuationSeparatorNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
666
+ readonly kind: 'continuationSeparator';
667
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
668
+ readonly localName: 'continuationSeparator';
669
+ }
670
+ /**
671
+ * `w:sdt` — structured document tag (content control) at block, inline, row, or cell level.
672
+ *
673
+ * Placement is not a separate kind: the same element name appears in every `EG_*Content`
674
+ * group. Child shape is the union of those placements; parents admit the control wherever
675
+ * `generic` was previously accepted (see `isPreservedChild`). Identity is the node id —
676
+ * `w:id` inside `w:sdtPr` is optional, preserved when present, never fabricated here.
677
+ */
678
+ interface OoxmlContentControlNode extends OoxmlElementBase<readonly (OoxmlContentControlPropertiesNode | OoxmlContentControlEndPropertiesNode | OoxmlContentControlContentNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
679
+ readonly kind: 'contentControl';
680
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
681
+ readonly localName: 'sdt';
682
+ }
683
+ /**
684
+ * `w:sdtPr` (`CT_SdtPr`) — schema-ordered properties. Unmodelled children (alias/tag/id/lock
685
+ * leaves with `w:val`, `w15:*`, empty type markers) stay `generic` in position. Typed
686
+ * payloads: dropdown/combo/listItem, date (+ leaves), text, dataBinding, `w14:checkbox`.
687
+ */
688
+ interface OoxmlContentControlPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlContentControlDataBindingNode | OoxmlContentControlDropDownListNode | OoxmlContentControlComboBoxNode | OoxmlContentControlDateNode | OoxmlContentControlTextNode | OoxmlContentControlCheckboxNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
689
+ readonly kind: 'contentControlProperties';
690
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
691
+ readonly localName: 'sdtPr';
692
+ }
693
+ /** `w:sdtEndPr` — end-character properties; children are `w:rPr` or generic. */
694
+ interface OoxmlContentControlEndPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
695
+ readonly kind: 'contentControlEndProperties';
696
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
697
+ readonly localName: 'sdtEndPr';
698
+ }
699
+ /**
700
+ * `w:sdtContent` — control contents for every placement. Block content is paragraphs/tables;
701
+ * inline content is runs/hyperlinks; row/cell content is rows/cells. Nested controls stay typed.
702
+ */
703
+ interface OoxmlContentControlContentNode extends OoxmlElementBase<readonly OoxmlNode[], readonly OoxmlKnownNodeAttribute[]> {
704
+ readonly kind: 'contentControlContent';
705
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
706
+ readonly localName: 'sdtContent';
707
+ }
708
+ /** `w:dropDownList` — `@w:lastValue` plus typed `w:listItem` children. */
709
+ interface OoxmlContentControlDropDownListNode extends OoxmlElementBase<readonly (OoxmlContentControlListItemNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
710
+ readonly kind: 'contentControlDropDownList';
711
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
712
+ readonly localName: 'dropDownList';
713
+ }
714
+ /** `w:comboBox` — same payload shape as dropdown; free entry is an editing concern. */
715
+ interface OoxmlContentControlComboBoxNode extends OoxmlElementBase<readonly (OoxmlContentControlListItemNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
716
+ readonly kind: 'contentControlComboBox';
717
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
718
+ readonly localName: 'comboBox';
719
+ }
720
+ /** `w:listItem` — `@w:displayText` / `@w:value` as preserved attributes (not `w:val`). */
721
+ interface OoxmlContentControlListItemNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
722
+ readonly kind: 'contentControlListItem';
723
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
724
+ readonly localName: 'listItem';
725
+ }
726
+ /**
727
+ * `w:date` — `@w:fullDate` plus typed dateFormat/lid/storeMappedDataAs/calendar leaves.
728
+ * Those leaves allow `w:val` (the only known kinds that do) so they are not demoted.
729
+ */
730
+ interface OoxmlContentControlDateNode extends OoxmlElementBase<readonly (OoxmlContentControlDateFormatNode | OoxmlContentControlLidNode | OoxmlContentControlStoreMappedDataAsNode | OoxmlContentControlCalendarNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
731
+ readonly kind: 'contentControlDate';
732
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
733
+ readonly localName: 'date';
734
+ }
735
+ /** `w:dateFormat` — the picture string a date picker formats its value with. */
736
+ interface OoxmlContentControlDateFormatNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]> {
737
+ readonly kind: 'contentControlDateFormat';
738
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
739
+ readonly localName: 'dateFormat';
740
+ }
741
+ /** `w:lid` — the language id a date picker parses and formats under. */
742
+ interface OoxmlContentControlLidNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]> {
743
+ readonly kind: 'contentControlLid';
744
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
745
+ readonly localName: 'lid';
746
+ }
747
+ /** `w:storeMappedDataAs` — which representation a bound date is written to its XML part as. */
748
+ interface OoxmlContentControlStoreMappedDataAsNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]> {
749
+ readonly kind: 'contentControlStoreMappedDataAs';
750
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
751
+ readonly localName: 'storeMappedDataAs';
752
+ }
753
+ /** `w:calendar` — which calendar system a date picker uses (Gregorian, Hijri, …). */
754
+ interface OoxmlContentControlCalendarNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]> {
755
+ readonly kind: 'contentControlCalendar';
756
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
757
+ readonly localName: 'calendar';
758
+ }
759
+ /** `w:text` (`CT_SdtText`) — distinct from `w:t` (`kind: 'text'`). `@w:multiLine` preserved. */
760
+ interface OoxmlContentControlTextNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
761
+ readonly kind: 'contentControlText';
762
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
763
+ readonly localName: 'text';
764
+ }
765
+ /**
766
+ * `w:dataBinding` — xpath / storeItemID / prefixMappings preserved as attributes.
767
+ * This tree never resolves or fetches the binding target.
768
+ */
769
+ interface OoxmlContentControlDataBindingNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
770
+ readonly kind: 'contentControlDataBinding';
771
+ readonly namespaceUri: typeof WML_NAMESPACE_URI;
772
+ readonly localName: 'dataBinding';
773
+ }
774
+ /**
775
+ * `w14:checkbox` — Microsoft extension, not an ECMA-376 type choice. Distinguishable from
776
+ * untyped rich-text controls that merely wrap a `w:sym`.
777
+ */
778
+ interface OoxmlContentControlCheckboxNode extends OoxmlElementBase<readonly (OoxmlContentControlCheckedNode | OoxmlContentControlCheckedStateNode | OoxmlContentControlUncheckedStateNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]> {
779
+ readonly kind: 'contentControlCheckbox';
780
+ readonly namespaceUri: typeof W14_NAMESPACE_URI;
781
+ readonly localName: 'checkbox';
782
+ }
783
+ /** `w14:checked` — a checkbox's recorded state, independent of the glyph drawn for it. */
784
+ interface OoxmlContentControlCheckedNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
785
+ readonly kind: 'contentControlChecked';
786
+ readonly namespaceUri: typeof W14_NAMESPACE_URI;
787
+ readonly localName: 'checked';
788
+ }
789
+ /** `w14:checkedState` — the font and code point drawn when a checkbox is checked. */
790
+ interface OoxmlContentControlCheckedStateNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
791
+ readonly kind: 'contentControlCheckedState';
792
+ readonly namespaceUri: typeof W14_NAMESPACE_URI;
793
+ readonly localName: 'checkedState';
794
+ }
795
+ /** `w14:uncheckedState` — the font and code point drawn when a checkbox is not checked. */
796
+ interface OoxmlContentControlUncheckedStateNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]> {
797
+ readonly kind: 'contentControlUncheckedState';
798
+ readonly namespaceUri: typeof W14_NAMESPACE_URI;
799
+ readonly localName: 'uncheckedState';
800
+ }
801
+ /**
802
+ * Any element the typed vocabulary does not cover — the other half of the preservation model.
803
+ *
804
+ * Also where a KNOWN element lands when it appears somewhere invalid: an element is demoted to
805
+ * generic rather than rejected, so malformed or unfamiliar content is carried losslessly and
806
+ * never locks editing.
807
+ */
808
+ interface OoxmlGenericElementNode extends OoxmlElementBase<readonly OoxmlNode[]> {
809
+ readonly kind: 'generic';
810
+ }
811
+ /** A literal text value. The only node kind with no children and no attributes. */
812
+ interface OoxmlTextNode {
813
+ readonly id: OoxmlNodeId;
814
+ readonly kind: 'textValue';
815
+ readonly value: string;
816
+ }
817
+ /** Every element node kind: the typed vocabulary plus the generic catch-all. */
818
+ type OoxmlElement = OoxmlDocumentNode | OoxmlBodyNode | OoxmlParagraphNode | OoxmlRunNode | OoxmlHyperlinkNode | OoxmlBookmarkStartNode | OoxmlBookmarkEndNode | OoxmlRunPropertiesNode | OoxmlTextElementNode | OoxmlDeletedTextNode | OoxmlParagraphPropertiesNode | OoxmlTabNode | OoxmlHardBreakNode | OoxmlFldCharNode | OoxmlInstrTextNode | OoxmlFldSimpleNode | OoxmlFootnotesNode | OoxmlEndnotesNode | OoxmlNoteNode | OoxmlNoteReferenceNode | OoxmlNoteRefNode | OoxmlSeparatorNode | OoxmlContinuationSeparatorNode | OoxmlTableNode | OoxmlTableRowNode | OoxmlTableCellNode | OoxmlTableGridNode | OoxmlTablePropertiesNode | OoxmlRevisionContentNode | OoxmlRangeMarkerNode | OoxmlCommentReferenceNode | OoxmlCommentsNode | OoxmlCommentNode | OoxmlContentControlNode | OoxmlContentControlPropertiesNode | OoxmlContentControlEndPropertiesNode | OoxmlContentControlContentNode | OoxmlContentControlDropDownListNode | OoxmlContentControlComboBoxNode | OoxmlContentControlListItemNode | OoxmlContentControlDateNode | OoxmlContentControlDateFormatNode | OoxmlContentControlLidNode | OoxmlContentControlStoreMappedDataAsNode | OoxmlContentControlCalendarNode | OoxmlContentControlTextNode | OoxmlContentControlDataBindingNode | OoxmlContentControlCheckboxNode | OoxmlContentControlCheckedNode | OoxmlContentControlCheckedStateNode | OoxmlContentControlUncheckedStateNode | OoxmlDrawingNode | OoxmlInlineDrawingNode | OoxmlAnchoredDrawingNode | OoxmlDrawingExtentNode | OoxmlDrawingEffectExtentNode | OoxmlDrawingDocPrNode | OoxmlDrawingGraphicFramePrNode | OoxmlDrawingGraphicNode | OoxmlDrawingGraphicDataNode | OoxmlDrawingSimplePosNode | OoxmlDrawingPositionHNode | OoxmlDrawingPositionVNode | OoxmlDrawingPositionAlignNode | OoxmlDrawingPositionOffsetNode | OoxmlDrawingWrapNoneNode | OoxmlDrawingWrapSquareNode | OoxmlDrawingWrapTightNode | OoxmlDrawingWrapThroughNode | OoxmlDrawingWrapTopBottomNode | OoxmlDrawingWrapPolygonNode | OoxmlDrawingWrapPolygonStartNode | OoxmlDrawingWrapPolygonLineToNode | OoxmlPictureNode | OoxmlPictureNvPicPrNode | OoxmlPictureBlipFillNode | OoxmlPictureBlipNode | OoxmlPictureSrcRectNode | OoxmlPictureStretchNode | OoxmlPictureTileNode | OoxmlPictureShapePropertiesNode | OoxmlPictureTransformNode | OoxmlPictureTransformOffsetNode | OoxmlPictureTransformExtentNode | OoxmlPicturePresetGeometryNode | OoxmlGenericElementNode;
819
+ /**
820
+ * Any node in the canonical tree.
821
+ *
822
+ * Typed where layout needs structure, generic everywhere else — one tree carries a whole document
823
+ * whether or not the engine understands every part of it.
824
+ */
825
+ type OoxmlNode = OoxmlElement | OoxmlTextNode;
826
+ /** One XML part of the package, parsed into a canonical tree. */
827
+ interface OoxmlPart {
828
+ readonly id: string;
829
+ /** Canonical part name, e.g. `/word/document.xml`. */
830
+ readonly name: string;
831
+ readonly contentType: string;
832
+ readonly root: OoxmlElement;
833
+ }
834
+ /** A part's identity without its tree — enough to enumerate a package cheaply. */
835
+ interface OoxmlPartMetadata {
836
+ readonly name: string;
837
+ readonly contentType: string;
838
+ }
839
+ /**
840
+ * Why a part could not be read into a tree.
841
+ *
842
+ * Widens the XML-level rejections with the tree-level ones. All of them describe the FILE, which
843
+ * is why reading returns a result rather than throwing.
844
+ */
845
+ type OoxmlReadRejection = XmlRejection | 'missing-root' | 'multiple-roots' | 'invalid-name' | 'invalid-namespace' | 'undeclared-prefix' | 'duplicate-expanded-attribute';
846
+ /** A parsed part, or a typed refusal. Never throws — the input is untrusted by definition. */
847
+ type OoxmlReadResult = {
848
+ readonly ok: true;
849
+ readonly part: OoxmlPart;
850
+ } | {
851
+ readonly ok: false;
852
+ readonly reason: OoxmlReadRejection;
853
+ };
854
+ /**
855
+ * The node-identity contract, written down as a type so it is checkable rather than merely
856
+ * documented.
857
+ *
858
+ * Ids are deterministic from a normalized parse, retained through structural sharing, explicit on
859
+ * replacement, and unique within a part. Everything that addresses nodes — ops, the caret, the
860
+ * paraId bimap — depends on all four holding.
861
+ */
862
+ interface OoxmlNodeIdentityRules {
863
+ readonly initial: 'deterministic-structural-path-after-normalized-parse';
864
+ readonly unchanged: 'retain-id-through-structural-sharing';
865
+ readonly replacement: 'explicitly-retain-or-allocate';
866
+ readonly uniqueness: 'unique-within-part';
867
+ }
868
+ /**
869
+ * Identity policy for future immutable tree edits. This defines the boundary
870
+ * without implementing task 2.4 edit primitives.
871
+ */
872
+ declare const OOXML_NODE_IDENTITY_RULES: OoxmlNodeIdentityRules;
873
+ /** What a tree invariant walk found wrong. Each names a rule the canonical tree must satisfy. */
874
+ type OoxmlInvariantIssueCode = 'invalid-id' | 'duplicate-id' | 'invalid-name' | 'invalid-namespace' | 'invalid-qname' | 'duplicate-expanded-attribute' | 'invalid-xml-value' | 'known-node-invariant';
875
+ /** One invariant violation, located by structural path and node id. */
876
+ interface OoxmlInvariantIssue {
877
+ readonly code: OoxmlInvariantIssueCode;
878
+ readonly path: string;
879
+ readonly nodeId?: string;
880
+ }
881
+ /** Whether a tree satisfies its invariants, listing every violation when it does not. */
882
+ type OoxmlInvariantResult = {
883
+ readonly ok: true;
884
+ } | {
885
+ readonly ok: false;
886
+ readonly issues: readonly OoxmlInvariantIssue[];
887
+ };
888
+ /**
889
+ * Read one XML part into the additive typed/generic foundation. Existing package
890
+ * parsing and DocumentStore models intentionally remain unchanged until their
891
+ * later migration tasks; this tree is not yet the repository's sole runtime authority.
892
+ * Structural-path IDs are deterministic across normalized reopen. Preserving an
893
+ * identity through moves and edits is deferred to PackageModel/DocumentStore integration.
894
+ */
895
+ declare function readOoxmlPart(xml: string, metadata: OoxmlPartMetadata, limits?: XmlLimits): OoxmlReadResult;
896
+
897
+ type AutomationTableMutation = {
898
+ readonly kind: 'insertRows';
899
+ readonly rowId: string;
900
+ readonly location: 'before' | 'after';
901
+ readonly count: number;
902
+ readonly values?: readonly (readonly string[])[];
903
+ } | {
904
+ readonly kind: 'values';
905
+ readonly values: readonly (readonly string[])[];
906
+ } | {
907
+ readonly kind: 'addRows' | 'addColumns';
908
+ readonly location: 'start' | 'end';
909
+ readonly count: number;
910
+ readonly values?: readonly (readonly string[])[];
911
+ } | {
912
+ readonly kind: 'deleteRows' | 'deleteColumns';
913
+ readonly index: number;
914
+ readonly count: number;
915
+ } | {
916
+ readonly kind: 'delete';
917
+ } | {
918
+ readonly kind: 'properties';
919
+ readonly styleId?: string;
920
+ readonly headerRowCount?: number;
921
+ } | {
922
+ readonly kind: 'cell';
923
+ readonly cellId: string;
924
+ readonly value?: string;
925
+ readonly columnWidth?: number;
926
+ readonly shadingColor?: string;
927
+ readonly verticalAlignment?: 'Top' | 'Center' | 'Bottom';
928
+ };
929
+
930
+ /** Select one declared entry of a legacy Word dropdown form field. */
931
+ interface SetLegacyDropdownOp {
932
+ readonly op: 'setLegacyDropdown';
933
+ readonly paragraphId: string;
934
+ readonly fieldNodeId: string;
935
+ readonly selectedIndex: number;
936
+ }
937
+
938
+ interface SetFieldCodeOp {
939
+ readonly op: 'setFieldCode';
940
+ readonly paragraphId: string;
941
+ readonly fieldNodeId: string;
942
+ readonly code: string;
943
+ }
944
+
945
+ type InsertTextOp = {
946
+ readonly op: 'insertText';
947
+ readonly paragraphId: string;
948
+ /** Legacy text form identity for protected filling; never an inline wrapper owner. */
949
+ readonly textFormFieldId?: string;
950
+ readonly offset: number;
951
+ readonly text: string;
952
+ /**
953
+ * Write this as a TRACKED insertion, attributed here.
954
+ *
955
+ * On the op rather than on the store, so suggesting stays a decision the surface makes
956
+ * per edit and the write vocabulary stays explicit — a global "everything is tracked
957
+ * now" flag is exactly what `DocEdits` refuses, because it makes the meaning of an op
958
+ * depend on state the op does not carry.
959
+ */
960
+ readonly revision?: RevisionAttributionInput;
961
+ /**
962
+ * When set, the text belongs INSIDE this content control, whatever sits at the offset.
963
+ *
964
+ * A boundary offset is owned by the run that starts there, which at a control's trailing
965
+ * edge is the run after the control — so an offset alone cannot say "append to this field",
966
+ * the way it cannot say which run of a field result to format (see `targetRunIds`). A
967
+ * caller that names the control gets the text in the control; one that does not gets the
968
+ * plain offset rule, which is what a keystroke beside a field means.
969
+ */
970
+ readonly inside?: string;
971
+ /**
972
+ * Which side of a run BOUNDARY the text joins. Default `'left'` — Word's typing rule:
973
+ * the next character takes the formatting of the character before the caret.
974
+ *
975
+ * `'right'` is for a caller that is not typing but placing text inside the run that
976
+ * STARTS at the offset — the hyperlink editor rewriting a link's display text, where
977
+ * landing left of the boundary would put the new text outside the link. Ignored when
978
+ * the offset falls strictly inside a run, which has no boundary to choose.
979
+ */
980
+ readonly bias?: 'left' | 'right';
981
+ };
982
+ type DeleteTextOp = {
983
+ readonly op: 'deleteText';
984
+ readonly paragraphId: string;
985
+ /** Legacy text form identity for protected filling; never an inline wrapper owner. */
986
+ readonly textFormFieldId?: string;
987
+ readonly start: number;
988
+ readonly end: number;
989
+ /** Write this as a TRACKED deletion — the characters stay, wrapped in `w:del`. */
990
+ readonly revision?: RevisionAttributionInput;
991
+ };
992
+
993
+ /** Editable legacy text input types. Other authored types remain inert. */
994
+ type TextFormFieldType = 'regular' | 'number' | 'date';
995
+ /** Options stored in the legacy field definition. Zero means unlimited length. */
996
+ interface TextFormFieldOptions {
997
+ readonly type: TextFormFieldType;
998
+ readonly maxLength: number;
999
+ readonly format: string;
1000
+ readonly enabled: boolean;
1001
+ }
1002
+ /** Supported format choices for legacy text input fields. @public */
1003
+ declare const TEXT_FORM_FORMATS: {
1004
+ readonly regular: readonly ['', 'Uppercase', 'Lowercase', 'First capital', 'Title case'];
1005
+ readonly number: readonly ['', '0', '0.00', '#,##0', '#,##0.00', '0%', '0.00%'];
1006
+ readonly date: readonly ['', 'M/d/yyyy', 'MM/dd/yyyy', 'd/M/yyyy', 'dd/MM/yyyy', 'yyyy-MM-dd', 'd MMMM yyyy', 'MMMM d, yyyy'];
1007
+ };
1008
+
1009
+ /** A legacy text input in the shared paragraph offset space. */
1010
+ interface TextFormFieldRange {
1011
+ readonly fieldNodeId: string;
1012
+ readonly start: number;
1013
+ readonly end: number;
1014
+ readonly enabled: boolean;
1015
+ readonly defaultText: string;
1016
+ readonly type: string;
1017
+ readonly maxLength: number;
1018
+ readonly format: string;
1019
+ readonly chromeIds: readonly string[];
1020
+ }
1021
+ /** Uses the field parser and offset index; never introduces another inline walk. */
1022
+ declare function textFormFieldsOf(paragraph: OoxmlParagraphNode): readonly TextFormFieldRange[];
1023
+ /** Options edit for an existing legacy text form. */
1024
+ interface SetTextFormFieldDefaultOp {
1025
+ readonly op: 'setTextFormFieldDefault';
1026
+ /** Regional conventions for new date input; defaults to en-US. */
1027
+ readonly locale?: string;
1028
+ readonly paragraphId: string;
1029
+ readonly fieldNodeId: string;
1030
+ readonly text: string;
1031
+ readonly options?: TextFormFieldOptions;
1032
+ }
1033
+ /** Validate and format the existing result when a user finishes filling a field. */
1034
+ interface CommitTextFormFieldOp {
1035
+ readonly op: 'commitTextFormField';
1036
+ /** Regional conventions for new date input; defaults to en-US. */
1037
+ readonly locale?: string;
1038
+ readonly paragraphId: string;
1039
+ readonly fieldNodeId: string;
1040
+ }
1041
+
1042
+ /** One FORMCHECKBOX in the shared paragraph offset space. */
1043
+ interface LegacyCheckboxFieldRange {
1044
+ /** The begin `w:fldChar` node: what the op addresses. */
1045
+ readonly fieldNodeId: string;
1046
+ readonly start: number;
1047
+ readonly end: number;
1048
+ readonly checked: boolean;
1049
+ /** `w:enabled` under `w:ffData`; a disabled field renders but refuses the toggle. */
1050
+ readonly enabled: boolean;
1051
+ }
1052
+ /** Flip a FORMCHECKBOX's state; the only write into `w:ffData` a checkbox permits. */
1053
+ interface SetLegacyCheckboxOp {
1054
+ readonly op: 'setLegacyCheckbox';
1055
+ readonly paragraphId: string;
1056
+ readonly fieldNodeId: string;
1057
+ readonly checked: boolean;
1058
+ }
1059
+ /** Every FORMCHECKBOX in a paragraph, in document order; uses the shared field parser. */
1060
+ declare function legacyCheckboxFieldsOf(paragraph: OoxmlParagraphNode): readonly LegacyCheckboxFieldRange[];
1061
+
1062
+ /** Replace a building block gallery control's content with one block's body. */
1063
+ interface InsertBuildingBlockOp {
1064
+ readonly op: 'insertBuildingBlock';
1065
+ readonly controlId: string;
1066
+ /** `w:docPartPr/w:name` of the picked block, for the journal and the host. */
1067
+ readonly name: string;
1068
+ /**
1069
+ * Self-contained `w:docPartBody` children, cloned with fresh ids at apply.
1070
+ * Resource, style, field, bookmark, note and revision references return `unsupported`.
1071
+ */
1072
+ readonly blocks: readonly OoxmlNode[];
1073
+ }
1074
+
1075
+ /**
1076
+ * Why a zip was refused at the trust boundary.
1077
+ *
1078
+ * `too-large` and `too-many-entries` are the zip-bomb guards; `bad-name` catches path traversal —
1079
+ * an entry with `..` or a leading `/` is rejected rather than normalized.
1080
+ */
1081
+ type ZipRejection = 'too-many-entries' | 'too-large' | 'bad-name' | 'inflate-error';
1082
+ /** Archive caps: entry count, total decompressed bytes, and the decompression ratio. */
1083
+ interface ZipLimits {
1084
+ readonly maxEntries: number;
1085
+ /** Max total UNCOMPRESSED bytes across the archive. */
1086
+ readonly maxTotalBytes: number;
1087
+ /**
1088
+ * Max ratio of the archive's total declared uncompressed bytes to the archive's own byte
1089
+ * length (zip-bomb guard). Applies once that total exceeds 8 MiB, so a small archive is
1090
+ * never refused for compressing well.
1091
+ */
1092
+ readonly maxRatio?: number;
1093
+ }
1094
+ /** The archive caps in force when a host configures none. Conservative and finite. */
1095
+ declare const DEFAULT_ZIP_LIMITS: ZipLimits;
1096
+ /** The read entries, or the typed refusal. Never throws — the bytes are untrusted. */
1097
+ type ZipReadResult = {
1098
+ readonly ok: true;
1099
+ readonly entries: ReadonlyMap<string, Uint8Array>;
1100
+ } | {
1101
+ readonly ok: false;
1102
+ readonly reason: ZipRejection;
1103
+ readonly detail?: string;
1104
+ readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
1105
+ };
1106
+ /**
1107
+ * Inflate a ZIP archive with bounds + OPC name normalization. Entry name, count, archive
1108
+ * ratio, and total-uncompressed-size limits are enforced BEFORE each entry is decompressed
1109
+ * (via fflate's pre-inflation filter), so a zip bomb or a traversal name is rejected without
1110
+ * ever being inflated. Keys are canonical part names.
1111
+ *
1112
+ * The budgets count each entry's DECLARED sizes, and the declared size is also a hard cap on
1113
+ * what the entry may produce: fflate inflates into a buffer of exactly `originalSize` bytes
1114
+ * and never grows it, so an entry whose stream holds more than it declares is truncated (or
1115
+ * refused as `inflate-error`), never expanded past its budget. A stored entry is copied at
1116
+ * its compressed size, so the larger of its two declared sizes is what counts.
1117
+ */
1118
+ declare function readZip(bytes: Uint8Array, limits?: ZipLimits): ZipReadResult;
1119
+ /** Deflate a set of canonical-part-name -> bytes into a ZIP archive. Every part name
1120
+ * is re-validated through the OPC normalization profile before writing, so a
1121
+ * traversal/encoded/normalized-alias name from an untrusted serialized model can
1122
+ * never be smuggled into a ZIP entry (write-side path-traversal guard). */
1123
+ declare function writeZip(entries: ReadonlyMap<string, Uint8Array>): Uint8Array;
1124
+
1125
+ /**
1126
+ * Why a part or relationship name was refused.
1127
+ *
1128
+ * Path traversal is the reason this exists: a name with `..` or a leading `/` is refused rather
1129
+ * than normalized, because normalizing is how a crafted package reaches outside itself.
1130
+ */
1131
+ 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';
1132
+ /** A validated OPC name, or the typed reason it was refused. */
1133
+ type NameResult = {
1134
+ readonly ok: true;
1135
+ readonly partName: string;
1136
+ } | {
1137
+ readonly ok: false;
1138
+ readonly reason: NameRejection;
1139
+ };
1140
+ /**
1141
+ * Normalize a ZIP entry name or OPC part name into a canonical part name
1142
+ * (`/word/document.xml`). Accepts leading-slash and no-leading-slash inputs;
1143
+ * rejects traversal, dot segments, and the attack surface. Duplicate detection
1144
+ * folds ASCII case (OPC part-name equivalence).
1145
+ */
1146
+ declare function normalizePartName(raw: string): NameResult;
1147
+ /**
1148
+ * ASCII-only lowercase fold. OPC part-name/extension equivalence is US-ASCII
1149
+ * case-insensitive; a locale `toLowerCase()` mis-folds e.g. Turkish `I`/`İ` and
1150
+ * could let two "equivalent" part names evade duplicate detection.
1151
+ */
1152
+ declare function asciiFold(s: string): string;
1153
+ /** Case-folded key for OPC part-name equivalence / duplicate detection. */
1154
+ declare function partNameKey(partName: string): string;
1155
+ /**
1156
+ * Detect archive entries that collide after normalization (before inflation).
1157
+ * Returns the case-folded keys that more than one raw name maps to.
1158
+ */
1159
+ declare function detectDuplicateNames(rawNames: readonly string[]): {
1160
+ readonly duplicates: readonly string[];
1161
+ readonly rejected: readonly {
1162
+ raw: string;
1163
+ reason: NameRejection;
1164
+ }[];
1165
+ };
1166
+ /**
1167
+ * Resolve an internal relationship target against its owner part, without
1168
+ * escaping the package root. `ownerPartName` is a canonical part name; the base
1169
+ * is its containing folder. A leading "/" target is package-absolute. `.`/`..`
1170
+ * segments resolve on a stack; popping above root is `traversal-escape`.
1171
+ */
1172
+ declare function resolveInternalTarget(ownerPartName: string, rawTarget: string): NameResult;
1173
+ /**
1174
+ * Validate an external-mode relationship target. It MUST be an absolute URI, is
1175
+ * retained verbatim by the caller, and is NEVER owner-resolved or fetched here.
1176
+ * Unsafe schemes (javascript/vbscript/data/file) are rejected for runtime sinks;
1177
+ * the raw lexical form is still preserved separately by the authored record.
1178
+ */
1179
+ declare function validateExternalTarget(raw: string): NameResult;
1180
+
1181
+ /** OOXML image relationship type for embedded or linked media parts. */
1182
+ declare const IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
1183
+ /**
1184
+ * Whether a relationship points inside the package or out of it.
1185
+ *
1186
+ * The security-relevant distinction: an `External` target is retained VERBATIM and never
1187
+ * owner-resolved or fetched, because auto-loading a file-supplied remote target is a zero-click
1188
+ * external fetch.
1189
+ */
1190
+ type TargetMode = 'Internal' | 'External';
1191
+ /**
1192
+ * One authored relationship, with nothing materialized away: owner part, id, type, raw target
1193
+ * lexical form, mode, and position.
1194
+ */
1195
+ interface RelationshipRecord {
1196
+ readonly ownerPart: string;
1197
+ readonly id: string;
1198
+ readonly type: string;
1199
+ readonly rawTarget: string;
1200
+ readonly targetMode: TargetMode;
1201
+ readonly order: number;
1202
+ }
1203
+ /** Why a relationship set is invalid. Duplicate ids within one owner fail closed. */
1204
+ type RelationshipError = {
1205
+ readonly code: 'duplicate-id';
1206
+ readonly ownerPart: string;
1207
+ readonly id: string;
1208
+ };
1209
+ /** The validated relationship set, or the conflict that rejected it. */
1210
+ type RelationshipSetResult = {
1211
+ readonly ok: true;
1212
+ readonly byOwner: ReadonlyMap<string, readonly RelationshipRecord[]>;
1213
+ } | {
1214
+ readonly ok: false;
1215
+ readonly error: RelationshipError;
1216
+ };
1217
+ /** Group relationships by owner in authored order; reject duplicate ids per owner. */
1218
+ declare function buildRelationshipSet(records: readonly RelationshipRecord[]): RelationshipSetResult;
1219
+ /**
1220
+ * A relationship resolved to a part, or the reason it could not be.
1221
+ *
1222
+ * External targets resolve to a refusal by design: they are never followed from a file.
1223
+ */
1224
+ type ResolvedRelationship = {
1225
+ readonly mode: 'Internal';
1226
+ readonly target: NameResult;
1227
+ readonly raw: string;
1228
+ } | {
1229
+ readonly mode: 'External';
1230
+ readonly sinkSafe: NameResult;
1231
+ readonly raw: string;
1232
+ };
1233
+ /**
1234
+ * Resolve a relationship to a runtime projection while the raw target stays
1235
+ * authored. Internal -> owner-relative part name; External -> sink-safe
1236
+ * validation only (never owner-resolved, never fetched). `raw` is always the
1237
+ * verbatim authored target.
1238
+ */
1239
+ declare function resolveRelationship(rec: RelationshipRecord): ResolvedRelationship;
1240
+ /**
1241
+ * An image relationship resolved to package bytes, or why it was refused.
1242
+ *
1243
+ * External-mode image rels are refused rather than fetched — the no-zero-click-external-fetch
1244
+ * rule applies to images exactly as it does to links.
1245
+ */
1246
+ type ImageRelationshipResolution = {
1247
+ readonly mode: 'internal';
1248
+ readonly partName: string;
1249
+ readonly raw: string;
1250
+ } | {
1251
+ readonly mode: 'external';
1252
+ readonly sinkSafe: boolean;
1253
+ readonly raw: string;
1254
+ } | {
1255
+ readonly mode: 'missing';
1256
+ };
1257
+ /**
1258
+ * Resolve an image relationship id from an owner part. Internal targets resolve
1259
+ * owner-relative; external targets are never fetched; a missing id is `missing`.
1260
+ */
1261
+ declare function resolveImageRelationship(records: readonly RelationshipRecord[] | undefined, ownerPart: string, relationshipId: string): ImageRelationshipResolution;
1262
+
1263
+ /** One `<Default>`: a file extension mapped to a content type. */
1264
+ interface DefaultRecord {
1265
+ readonly extension: string;
1266
+ readonly contentType: string;
1267
+ readonly order: number;
1268
+ }
1269
+ /** One `<Override>`: a specific part name mapped to a content type. Beats any Default. */
1270
+ interface OverrideRecord {
1271
+ readonly partName: string;
1272
+ readonly contentType: string;
1273
+ readonly order: number;
1274
+ }
1275
+ /**
1276
+ * The authored `[Content_Types].xml` records, in significant order.
1277
+ *
1278
+ * Retained rather than collapsed into a lookup, because the file's lexical form and ordering are
1279
+ * part of what a lossless save re-emits.
1280
+ */
1281
+ interface ContentTypeRecords {
1282
+ readonly defaults: readonly DefaultRecord[];
1283
+ readonly overrides: readonly OverrideRecord[];
1284
+ }
1285
+ /**
1286
+ * Why content-type records could not be indexed.
1287
+ *
1288
+ * All fail CLOSED: conflicting Defaults on one extension, duplicate normalized Override names, or
1289
+ * invalid MIME syntax are refused rather than resolved by picking one.
1290
+ */
1291
+ type ContentTypeError = {
1292
+ readonly code: 'invalid-mime';
1293
+ readonly value: string;
1294
+ } | {
1295
+ readonly code: 'conflicting-default';
1296
+ readonly extension: string;
1297
+ } | {
1298
+ readonly code: 'duplicate-override';
1299
+ readonly partName: string;
1300
+ } | {
1301
+ readonly code: 'invalid-override-name';
1302
+ readonly partName: string;
1303
+ } | {
1304
+ readonly code: 'too-many-records';
1305
+ readonly limit: number;
1306
+ };
1307
+ /** Whether a string is syntactically a MIME type. Syntax only — no registry lookup. */
1308
+ declare function isValidMime(value: string): boolean;
1309
+ /** ASCII-case-insensitive extension key (leading dot removed; ASCII-only fold). */
1310
+ declare function extensionKey(extension: string): string;
1311
+ /** The resolved lookup: Override by case-folded part name, Default by case-insensitive extension. */
1312
+ interface ContentTypeIndex {
1313
+ /** ext key -> single MIME (identical duplicates collapsed). */
1314
+ readonly defaults: ReadonlyMap<string, string>;
1315
+ /** case-folded part name -> MIME. */
1316
+ readonly overrides: ReadonlyMap<string, string>;
1317
+ }
1318
+ /** The built index, or the conflict that made it impossible. */
1319
+ type IndexResult = {
1320
+ readonly ok: true;
1321
+ readonly index: ContentTypeIndex;
1322
+ } | {
1323
+ readonly ok: false;
1324
+ readonly error: ContentTypeError;
1325
+ };
1326
+ /**
1327
+ * Build a resolved content-type index, failing closed on conflict/duplicate/MIME
1328
+ * errors. `maxRecords` bounds the combined record count (N/N+1 gate).
1329
+ */
1330
+ declare function buildContentTypeIndex(records: ContentTypeRecords, maxRecords?: number): IndexResult;
1331
+ /**
1332
+ * A part's content type, or why it has none.
1333
+ *
1334
+ * An orphan record never determines a part's type — a Default with no matching part is preserved
1335
+ * inertly rather than applied.
1336
+ */
1337
+ type ResolveResult = {
1338
+ readonly ok: true;
1339
+ readonly contentType: string;
1340
+ readonly source: 'override' | 'default';
1341
+ } | {
1342
+ readonly ok: false;
1343
+ readonly reason: 'unknown';
1344
+ };
1345
+ /** Resolve a part's content type: Override wins over Default; else unknown. */
1346
+ declare function resolveContentType(index: ContentTypeIndex, partName: string): ResolveResult;
1347
+
1348
+ type ShapeSchemeColorResolver = (scheme: string) => string | null;
1349
+ type ShapeStyleMatrixResolver = (kind: 'fill' | 'line', index: number) => OoxmlElement | null;
1350
+ /**
1351
+ * The renderable subset of a `wps:wsp` non-picture graphic, or of one bounded `wpg:wgp`
1352
+ * group of them: closed polygon subpaths (`a:custGeom` with move/line/close/cubicBezTo
1353
+ * verbs, or a supported `a:prstGeom`) with a solid fill and/or stroke. The colour may come
1354
+ * from `a:srgbClr` or from the theme, through `a:schemeClr` or a `wps:style` matrix
1355
+ * reference. Anything richer (gradient and picture fills, text bodies, rotation, a nested
1356
+ * group) projects as `null` and paints the labelled placeholder instead.
1357
+ */
1358
+ interface VectorShapeProjection {
1359
+ /** The drawing extent that frames the subpath coordinate space. */
1360
+ readonly extentEmu: Readonly<{
1361
+ cx: number;
1362
+ cy: number;
1363
+ }>;
1364
+ /**
1365
+ * Every component's subpath polygons, flattened, in extent-EMU space; fill rule is
1366
+ * even-odd. Painting reads `components`, which keeps each polygon with its own colours;
1367
+ * this stays the geometry summary (bounds, hit tests, wrap holes).
1368
+ */
1369
+ readonly subpathsEmu: readonly (readonly Readonly<{
1370
+ x: number;
1371
+ y: number;
1372
+ }>[])[];
1373
+ /**
1374
+ * Validated 6-digit sRGB hex (no `#`) of the one component, or null. A group of two or
1375
+ * more components has no single fill, so this is null there as well: null means "no one
1376
+ * fill to name", not "nothing is filled". Read `components` to paint.
1377
+ */
1378
+ readonly fillHex: string | null;
1379
+ readonly fillAlpha?: number;
1380
+ /** As `fillHex`, for the stroke: the one component's stroke, else null. */
1381
+ readonly strokeHex: string | null;
1382
+ readonly strokeAlpha?: number;
1383
+ /** The one component's stroke width in EMU; 0 when absent or when grouped. */
1384
+ readonly strokeWidthEmu: number;
1385
+ /** Independently styled paths, always non-empty. A direct shape has one component. */
1386
+ readonly components: readonly VectorShapeComponent[];
1387
+ }
1388
+ interface VectorShapeComponent {
1389
+ readonly subpathsEmu: readonly (readonly Readonly<{
1390
+ x: number;
1391
+ y: number;
1392
+ }>[])[];
1393
+ /** Authored close commands; omitted by older consumers means closed polygons. */
1394
+ readonly subpathsClosed?: readonly boolean[];
1395
+ /** Filled line-end polygons in the same projected coordinate space. */
1396
+ readonly arrowheadsEmu?: readonly (readonly Readonly<{
1397
+ x: number;
1398
+ y: number;
1399
+ }>[])[];
1400
+ readonly fillHex: string | null;
1401
+ readonly fillAlpha: number;
1402
+ readonly strokeHex: string | null;
1403
+ readonly strokeAlpha: number;
1404
+ readonly strokeWidthEmu: number;
1405
+ /**
1406
+ * The outline sits inside the closed geometry (`a:ln algn="in"`): painters draw it at twice
1407
+ * its width clipped to the path, so the authored width stays inside the shape and adds no
1408
+ * reach past the extent. Set only for a closed outline with area.
1409
+ */
1410
+ readonly strokeInset?: boolean;
1411
+ }
1412
+ /**
1413
+ * The story carried by a `wps:wsp` text box (`wps:txbx` → `w:txbxContent`).
1414
+ *
1415
+ * The projection captures only the story root and the shape chrome reads; it never walks the
1416
+ * story content, so the per-drawing element budget is not spent on paragraphs. Layout collects
1417
+ * blocks from `content` under its own caps.
1418
+ */
1419
+ interface TextboxStoryProjection {
1420
+ /** Canonical node id of the `w:txbxContent` element. */
1421
+ readonly contentNodeId: string;
1422
+ /** The `w:txbxContent` element itself; treated as an opaque story root here. */
1423
+ readonly content: OoxmlElement;
1424
+ /** `wps:bodyPr` insets with the OOXML defaults (91440 EMU l/r, 45720 EMU t/b) when absent. */
1425
+ readonly insetsEmu: Readonly<{
1426
+ top: number;
1427
+ right: number;
1428
+ bottom: number;
1429
+ left: number;
1430
+ }>;
1431
+ /** `wps:bodyPr/@anchor` collapsed to the three renderable positions; default top. */
1432
+ readonly verticalAnchor: 'top' | 'center' | 'bottom';
1433
+ /** Autofit child of `wps:bodyPr`; extent stays authoritative either way (diagnostic only). */
1434
+ readonly autofit: 'none' | 'shape' | 'normal';
1435
+ /**
1436
+ * `wps:bodyPr/@wrap="none"` (VML `mso-wrap-style:none`): lines never wrap at the box edge,
1437
+ * and the box takes the width of its widest line plus the insets. Absent for wrapped text.
1438
+ */
1439
+ readonly noWrap?: true;
1440
+ /** Solid fill of the hosting shape, painted behind the story; null for no fill. */
1441
+ readonly fillHex: string | null;
1442
+ /** Solid outline of the hosting shape; null for no outline. */
1443
+ readonly strokeHex: string | null;
1444
+ /** Outline width in EMU; 0 when absent. */
1445
+ readonly strokeWidthEmu: number;
1446
+ }
1447
+
1448
+ /** Only generated, escaped SVG and relationship slots; never authored markup. */
1449
+ type LegacyGraphicFragment = string | Readonly<{
1450
+ relationshipId: string;
1451
+ before: string;
1452
+ after: string;
1453
+ nativeCrop?: SourceCrop;
1454
+ }>;
1455
+ interface LegacyGraphicProjection {
1456
+ readonly width: number;
1457
+ readonly height: number;
1458
+ readonly fragments: readonly LegacyGraphicFragment[];
1459
+ }
1460
+
1461
+ /** Picture color adjustments shared by projection, layout, and paint.
1462
+ * @public
1463
+ */
1464
+ interface DrawingImageEffects {
1465
+ /** Fixed alpha multiplier for raster painting; omitted means opaque. */
1466
+ readonly opacity?: number;
1467
+ readonly grayscale: boolean;
1468
+ readonly brightness: number;
1469
+ readonly contrast: number;
1470
+ readonly bilevel?: number;
1471
+ }
1472
+
1473
+ /** One text box member of a drawing group. */
1474
+ interface GroupTextboxProjection {
1475
+ /** Canonical node id of the member `wps:wsp`; namespaces the story's line ids. */
1476
+ readonly memberNodeId: string;
1477
+ /** The member box in the group's extent space, in EMU (origin at the extent's top-left). */
1478
+ readonly frameEmu: Readonly<{
1479
+ x: number;
1480
+ y: number;
1481
+ cx: number;
1482
+ cy: number;
1483
+ }>;
1484
+ /** The member's story, projected at the scaled member size. */
1485
+ readonly story: TextboxStoryProjection;
1486
+ /**
1487
+ * Clockwise turn of the member's text about the member box center, in degrees [0, 360):
1488
+ * the member's `rot`, plus 180 for `flipV`. `flipH` never mirrors the text.
1489
+ */
1490
+ readonly rotationDegrees: number;
1491
+ }
1492
+
1493
+ /** The relationship namespace `r:id` lives in. */
1494
+ declare const OFFICE_RELATIONSHIP_NAMESPACE_URI = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
1495
+ /** The `Type` a hyperlink relationship declares. */
1496
+ declare const HYPERLINK_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
1497
+ /**
1498
+ * What a part's relationships answer for one `r:id`: the authored target and whether the
1499
+ * package declared it external. `null` for an id the part does not declare — a DANGLING
1500
+ * relationship, which is a real thing in real documents.
1501
+ */
1502
+ type RelationshipTargetResolver = (relationshipId: string) => {
1503
+ readonly target: string;
1504
+ readonly external: boolean;
1505
+ /**
1506
+ * The PACKAGE's own verdict on this target (`validateExternalTarget`): whether it is an
1507
+ * absolute URI with a safe scheme.
1508
+ *
1509
+ * Carried separately because `sanitizeHref` cannot answer it. That function is a SCHEME
1510
+ * allowlist and deliberately admits relative URLs — the right rule for a value the host
1511
+ * authored, and the wrong one for a value a `.docx` did. A file-supplied
1512
+ * `Target="/admin/delete-account"` has no scheme to refuse, so it would pass the
1513
+ * allowlist and resolve against the EMBEDDING APPLICATION'S origin: a link reading
1514
+ * "Company policy" that issues an authenticated same-origin request to whatever host
1515
+ * app the editor is mounted in. Absent, a target is treated as unverified.
1516
+ */
1517
+ readonly sinkSafe?: boolean;
1518
+ } | null;
1519
+ /**
1520
+ * What a hyperlink points at, which decides what activating it may do.
1521
+ *
1522
+ * The security-relevant split: an `external` link goes through `sanitizeHref` and opens only on
1523
+ * explicit user action, while an anchor merely scrolls and never navigates.
1524
+ */
1525
+ type HyperlinkKind =
1526
+ /** `r:id` → a relationship with `TargetMode="External"`. Opens somewhere else. */
1527
+ 'external'
1528
+ /** `w:anchor` → a bookmark in this document. Scrolls, never navigates. */
1529
+ | 'internal'
1530
+ /**
1531
+ * `r:id` naming a relationship the part does not declare, or one that is not external.
1532
+ *
1533
+ * The link keeps its runs — the text is never lost twice — but there is nothing to
1534
+ * activate, so it paints inert exactly like a refused scheme.
1535
+ */
1536
+ | 'unresolved';
1537
+ /** A resolved hyperlink: its kind, its target, and the tooltip Word shows on hover. */
1538
+ interface HyperlinkTarget {
1539
+ readonly kind: HyperlinkKind;
1540
+ /**
1541
+ * The authored target, verbatim: the relationship's `Target` for an `r:id` link, the
1542
+ * anchor name for an internal one. Save re-emits from the tree, never from this — it is
1543
+ * here so a UI can show what the document actually says.
1544
+ */
1545
+ readonly authored: string;
1546
+ /**
1547
+ * The sanitized runtime projection, or `null` when there is nothing safe to navigate to.
1548
+ * The ONLY value permitted in a DOM `href`, `window.open`, or a copied link.
1549
+ */
1550
+ readonly href: string | null;
1551
+ /** `w:anchor`, for an internal link. */
1552
+ readonly anchor?: string;
1553
+ /** `w:tooltip` — Word's hover text; paint puts it on the anchor's `title`. */
1554
+ readonly tooltip?: string;
1555
+ /** The authored `r:id`, so an edit can rewrite the relationship it names. */
1556
+ readonly relationshipId?: string;
1557
+ }
1558
+ /** Whether a node is a typed `w:hyperlink`. */
1559
+ declare function isHyperlinkNode(node: OoxmlNode): boolean;
1560
+ /** A typed hyperlink's `w:anchor`, or undefined. */
1561
+ declare function hyperlinkAnchorOf(link: OoxmlNode): string | undefined;
1562
+ /** A typed hyperlink's `r:id`, or undefined. */
1563
+ declare function hyperlinkRelationshipIdOf(link: OoxmlNode): string | undefined;
1564
+ /**
1565
+ * Read a typed `w:hyperlink` into its target record.
1566
+ *
1567
+ * `r:id` wins over `w:anchor` when a link carries both, matching Word: the relationship
1568
+ * names the document and the anchor names a place inside it, so the pair is a link to a
1569
+ * bookmark in ANOTHER file — which this engine will not follow, but whose external half is
1570
+ * the part that decides where it points.
1571
+ *
1572
+ * A link with neither is `unresolved`: it paints its runs and does nothing.
1573
+ */
1574
+ declare function hyperlinkTargetOf(link: OoxmlNode, resolve: RelationshipTargetResolver): HyperlinkTarget;
1575
+
1576
+ interface DrawingProjectionLimits {
1577
+ readonly maxCompatibilityBranches: number;
1578
+ readonly maxVisitedElements: number;
1579
+ readonly maxDrawingDepth: number;
1580
+ }
1581
+ interface DrawingDiagnostic {
1582
+ readonly code: 'malformed-drawing' | 'unsupported-graphic' | 'unresolvable-frame' | 'invalid-geometry' | 'resource-refused' | 'wrap-polygon-over-limit' | 'wrap-polygon-malformed';
1583
+ readonly nodeId: string;
1584
+ readonly detail: string | null;
1585
+ }
1586
+
1587
+ /** One picture painted as a member of a drawing group. */
1588
+ interface GroupPictureProjection {
1589
+ readonly embeddedRelationshipId: string | null;
1590
+ readonly linkedRelationshipId: string | null;
1591
+ readonly crop: Readonly<{
1592
+ left: number;
1593
+ top: number;
1594
+ right: number;
1595
+ bottom: number;
1596
+ }>;
1597
+ /** The picture's rectangle inside the drawing extent, in extent EMU. */
1598
+ readonly frameEmu: Readonly<{
1599
+ x: number;
1600
+ y: number;
1601
+ cx: number;
1602
+ cy: number;
1603
+ }>;
1604
+ /** Canonical node id of the `pic:pic` member. The vector projection skips it. */
1605
+ readonly memberNodeId: string;
1606
+ /**
1607
+ * Whether the group is the chosen branch of a run-level `mc:AlternateContent`. Layout then
1608
+ * drops the whole group when the picture resource fails, as the projection drops other
1609
+ * MC payloads it cannot draw.
1610
+ */
1611
+ readonly alternateContent: boolean;
1612
+ }
1613
+
1614
+ /**
1615
+ * Whether a drawing sits in the text flow or is positioned against a frame.
1616
+ *
1617
+ * The distinction that decides everything downstream: an inline drawing occupies a character
1618
+ * position, while an anchored one has offsets relative to a page, margin or column.
1619
+ */
1620
+ type DrawingKind = 'inline' | 'anchored';
1621
+ /** Nine Word wrap menu targets (inline plus eight floating modes). @public */
1622
+ type ImageWrapTarget = 'inline' | 'square' | 'squareLeft' | 'squareRight' | 'tight' | 'through' | 'topAndBottom' | 'behind' | 'inFront';
1623
+ /** Every text-wrap mode a drawing may be set to, including `inline`. */
1624
+ declare const IMAGE_WRAP_TARGETS: readonly ImageWrapTarget[];
1625
+ type DrawingWrapElement = 'none' | 'square' | 'tight' | 'through' | 'topAndBottom';
1626
+ type DrawingHorizontalReferenceFrame = 'character' | 'column' | 'insideMargin' | 'leftMargin' | 'margin' | 'outsideMargin' | 'page' | 'rightMargin';
1627
+ type DrawingVerticalReferenceFrame = 'bottomMargin' | 'insideMargin' | 'line' | 'margin' | 'outsideMargin' | 'page' | 'paragraph' | 'topMargin';
1628
+ /** `a:srcRect` — how much of each edge of the source image is cropped away, as fractions. */
1629
+ interface SourceCrop {
1630
+ readonly left: number;
1631
+ readonly top: number;
1632
+ readonly right: number;
1633
+ readonly bottom: number;
1634
+ }
1635
+ interface DrawingTransform {
1636
+ readonly rotationDegrees: number;
1637
+ readonly flipHorizontal: boolean;
1638
+ readonly flipVertical: boolean;
1639
+ /** Source `a:off` in EMU; defaults to origin when absent. */
1640
+ readonly offsetEmu: Readonly<{
1641
+ x: number;
1642
+ y: number;
1643
+ }>;
1644
+ /** Source `a:ext` in EMU; zero falls back to `wp:extent` at geometry time. */
1645
+ readonly extentEmu: Readonly<{
1646
+ cx: number;
1647
+ cy: number;
1648
+ }>;
1649
+ }
1650
+ /**
1651
+ * What a drawing refuses: selection, movement, resizing, aspect change.
1652
+ *
1653
+ * Read and honoured rather than advisory — chrome that offered a handle the store will refuse
1654
+ * would promise an edit that cannot happen.
1655
+ */
1656
+ interface DrawingLocks {
1657
+ readonly select: boolean;
1658
+ readonly move: boolean;
1659
+ readonly resize: boolean;
1660
+ readonly changeAspect: boolean;
1661
+ }
1662
+ interface DrawingLocksInput {
1663
+ readonly select?: boolean;
1664
+ readonly move?: boolean;
1665
+ readonly resize?: boolean;
1666
+ readonly changeAspect?: boolean;
1667
+ }
1668
+ /**
1669
+ * An anchored drawing's position: offsets, and the frames they are relative to.
1670
+ *
1671
+ * The relative-to bases matter as much as the offsets. Writing an offset without preserving its
1672
+ * base re-anchors the drawing against a different reference and moves it somewhere nobody asked.
1673
+ */
1674
+ interface DrawingPositionInput {
1675
+ /**
1676
+ * `'simple'` when `@simplePos="1"`: `horizontalEmu` / `verticalEmu` are authoritative
1677
+ * `wp:simplePos` x/y. `'frame'` (default) uses positionH/V relative frames.
1678
+ */
1679
+ readonly mode?: 'frame' | 'simple';
1680
+ readonly horizontalEmu?: number;
1681
+ readonly verticalEmu?: number;
1682
+ readonly relativeToH?: DrawingHorizontalReferenceFrame;
1683
+ readonly relativeToV?: DrawingVerticalReferenceFrame;
1684
+ }
1685
+ interface DrawingProjection {
1686
+ readonly drawingNodeId: string;
1687
+ readonly ownerPartName: string;
1688
+ readonly kind: DrawingKind;
1689
+ readonly relationshipId: string | null;
1690
+ readonly docPrId: number | null;
1691
+ readonly name: string;
1692
+ readonly title: string;
1693
+ readonly description: string;
1694
+ readonly hyperlinkHref: string | null;
1695
+ readonly hidden: boolean;
1696
+ readonly extentEmu: Readonly<{
1697
+ cx: number;
1698
+ cy: number;
1699
+ }>;
1700
+ readonly effectExtentEmu: Readonly<{
1701
+ top: number;
1702
+ right: number;
1703
+ bottom: number;
1704
+ left: number;
1705
+ }>;
1706
+ readonly inlineDistancesEmu: Readonly<{
1707
+ top: number;
1708
+ right: number;
1709
+ bottom: number;
1710
+ left: number;
1711
+ }>;
1712
+ readonly wrap: ImageWrapTarget;
1713
+ readonly wrapGeometry: DrawingWrapProjection | null;
1714
+ readonly position: DrawingPositionProjection | null;
1715
+ readonly anchor: Readonly<{
1716
+ simplePos: boolean;
1717
+ relativeHeight: number;
1718
+ behindDocument: boolean;
1719
+ layoutInCell: boolean;
1720
+ allowOverlap: boolean;
1721
+ }> | null;
1722
+ readonly picture: PictureProjection | null;
1723
+ readonly vectorShape: VectorShapeProjection | null;
1724
+ /** The picture member of a `wpg:wgp` group; `picture` stays null for a group. */
1725
+ readonly groupPicture: GroupPictureProjection | null;
1726
+ readonly textboxStory: TextboxStoryProjection | null;
1727
+ /** Text box members of a `wpg:wgp` group, laid out read-only; absent when none has text. */
1728
+ readonly groupTextboxes?: readonly GroupTextboxProjection[];
1729
+ /** Read-only preview of the supported native VML subset; the canonical XML is untouched. */
1730
+ readonly legacyGraphic?: LegacyGraphicProjection;
1731
+ readonly locks: DrawingLocks;
1732
+ readonly effects: DrawingImageEffects;
1733
+ readonly compatibilityBranchNodeId: string | null;
1734
+ readonly diagnostics: readonly DrawingDiagnostic[];
1735
+ /** Layout-only wrap area of an MC payload that cannot paint (`wrapFootprintProjection`). */
1736
+ readonly footprintOnly?: true;
1737
+ }
1738
+ interface DrawingAccessibility {
1739
+ /**
1740
+ * The record takes part in layout only, for example the wrap area of a payload that cannot
1741
+ * paint. Outputs must not paint, hit-test, select, link, or export it.
1742
+ */
1743
+ readonly hidden: boolean;
1744
+ readonly decorative: boolean;
1745
+ readonly label: string | null;
1746
+ }
1747
+ interface DrawingPositionProjection {
1748
+ readonly simplePosition: Readonly<{
1749
+ xEmu: number;
1750
+ yEmu: number;
1751
+ }>;
1752
+ readonly horizontal: Readonly<{
1753
+ relativeFrom: DrawingHorizontalReferenceFrame;
1754
+ align: string | null;
1755
+ offsetEmu: number | null;
1756
+ }>;
1757
+ readonly vertical: Readonly<{
1758
+ relativeFrom: DrawingVerticalReferenceFrame;
1759
+ align: string | null;
1760
+ offsetEmu: number | null;
1761
+ }>;
1762
+ }
1763
+ interface DrawingWrapProjection {
1764
+ readonly element: DrawingWrapElement;
1765
+ readonly textSide: 'bothSides' | 'left' | 'right' | 'largest';
1766
+ readonly distancesEmu: Readonly<{
1767
+ top: number;
1768
+ right: number;
1769
+ bottom: number;
1770
+ left: number;
1771
+ }>;
1772
+ readonly polygon: readonly Readonly<{
1773
+ x: number;
1774
+ y: number;
1775
+ }>[];
1776
+ }
1777
+ interface PictureProjection {
1778
+ readonly embeddedRelationshipId: string | null;
1779
+ readonly linkedRelationshipId: string | null;
1780
+ readonly crop: SourceCrop;
1781
+ readonly fillMode: 'stretch' | 'tile';
1782
+ readonly transform: DrawingTransform;
1783
+ readonly presetGeometry: string | null;
1784
+ }
1785
+ /**
1786
+ * Project one `w:drawing` into the resolved shape layout and chrome read.
1787
+ *
1788
+ * Bounded throughout: extents, crops and nesting all come from a file. Returns a projection that
1789
+ * reports `hidden` and its locks rather than throwing, so an unusable drawing degrades to
1790
+ * something the surface can skip.
1791
+ */
1792
+ declare function projectDrawing(drawing: OoxmlDrawingNode, context: Readonly<{
1793
+ ownerPartName: string;
1794
+ supportedMcRequires: ReadonlySet<string>;
1795
+ limits: DrawingProjectionLimits;
1796
+ namespaceScope?: ReadonlyMap<string, string>;
1797
+ resolveRelationship?: RelationshipTargetResolver;
1798
+ resolveSchemeColor?: ShapeSchemeColorResolver;
1799
+ resolveStyleMatrixReference?: ShapeStyleMatrixResolver;
1800
+ }>): DrawingProjection | null;
1801
+
1802
+ /** Caps applied while loading a package: zip, XML, part count and relationship count. */
1803
+ interface OoxmlPackageLimits {
1804
+ readonly zip?: ZipLimits;
1805
+ readonly xml?: XmlLimits;
1806
+ /** Cap on parts converted into canonical trees (N/N+1 gate, not a soft target). */
1807
+ readonly maxXmlParts?: number;
1808
+ /** Cap on relationship records across every rels part. */
1809
+ readonly maxRelationships?: number;
1810
+ }
1811
+ /** The limits in force when a host configures none. Conservative and finite. */
1812
+ declare const DEFAULT_OOXML_PACKAGE_LIMITS: Required<Pick<OoxmlPackageLimits, 'maxXmlParts' | 'maxRelationships'>>;
1813
+ /**
1814
+ * An external relationship target. Retained verbatim as authored evidence, with the
1815
+ * sink-safety verdict alongside it. Never resolved against the package, never fetched.
1816
+ */
1817
+ interface OoxmlExternalTarget {
1818
+ readonly ownerPart: string;
1819
+ readonly id: string;
1820
+ readonly type: string;
1821
+ readonly rawTarget: string;
1822
+ /** False when the target is not a safe sink (javascript:, file:, ...). Still not fetched. */
1823
+ readonly sinkSafe: boolean;
1824
+ }
1825
+ /**
1826
+ * A loaded package: every XML part as a canonical tree, plus the non-XML parts kept verbatim.
1827
+ *
1828
+ * The preservation model in one value. Modelled parts re-emit normalized; everything else is
1829
+ * byte-identical, which is why an unrecognized part never costs a document anything.
1830
+ */
1831
+ interface OoxmlPackage {
1832
+ /** Canonical trees, keyed by canonical part name. Non-XML parts are absent by design. */
1833
+ readonly parts: ReadonlyMap<string, OoxmlPart>;
1834
+ /** Raw bytes of every entry, including the non-XML parts that have no tree. */
1835
+ readonly partBytes: ReadonlyMap<string, Uint8Array>;
1836
+ /** Internal relationships by owner part, in authored order. */
1837
+ readonly relationships: ReadonlyMap<string, readonly RelationshipRecord[]>;
1838
+ readonly externalTargets: readonly OoxmlExternalTarget[];
1839
+ readonly contentTypes: ContentTypeIndex;
1840
+ /** Canonical name of the part the root `officeDocument` relationship points at. */
1841
+ readonly mainDocumentPart: string;
1842
+ }
1843
+ /** Why a package could not be loaded. Every code describes the FILE, not the caller. */
1844
+ type OoxmlPackageRejection = ZipRejection | OoxmlReadRejection | 'no-content-types' | 'bad-content-types' | 'no-main-document' | 'bad-relationship-target' | 'duplicate-relationship-id' | 'too-many-relationships' | 'too-many-xml-parts';
1845
+ /** A loaded package, or a typed refusal. Never throws. */
1846
+ type OoxmlPackageResult = {
1847
+ readonly ok: true;
1848
+ readonly package: OoxmlPackage;
1849
+ } | {
1850
+ readonly ok: false;
1851
+ readonly reason: OoxmlPackageRejection;
1852
+ readonly detail?: string;
1853
+ readonly limit?: 'zip.maxTotalBytes' | 'zip.maxRatio';
1854
+ };
1855
+ /**
1856
+ * Load DOCX bytes into canonical typed/generic OOXML trees, bounded at every step.
1857
+ *
1858
+ * THE trust boundary for a document. Composes the hardened primitives — zip limits and OPC name
1859
+ * normalization, content-type indexing, relationship validation, entity-free XML — into one
1860
+ * loader, and returns a typed rejection rather than throwing from inside a decoder.
1861
+ *
1862
+ * Fails closed on every limit, malformed name, unresolvable internal target, duplicate
1863
+ * relationship id, and XML rejection. An external relationship never causes a failure and
1864
+ * never causes a fetch: it is recorded with its sink-safety verdict for a later, explicitly
1865
+ * user-gated lane. A content-type record with an invalid MIME type is treated as absent,
1866
+ * unless it decides the type of the main document part, a relationships part, or a
1867
+ * non-payload part that the package root or the main document relates to.
1868
+ */
1869
+ declare function readOoxmlPackage(bytes: Uint8Array, limits?: OoxmlPackageLimits): OoxmlPackageResult;
1870
+ /**
1871
+ * Serialize a canonical package back to DOCX bytes.
1872
+ *
1873
+ * Starts from the ORIGINAL entry bytes and overwrites only the parts held as trees. A part
1874
+ * the loader did not model — media, fonts, an XML part outside the modeled set — passes
1875
+ * through untouched, so round-tripping a document cannot lose a part the engine never
1876
+ * claimed to understand.
1877
+ *
1878
+ * The modeled parts are re-emitted NORMALIZED from the tree rather than patched as text.
1879
+ * That is the whole point of the canonical tree: correctness is judged by the two D9
1880
+ * oracles (the namespace-aware fingerprint and the save/reopen semantic digest), not by
1881
+ * byte equality, so a different-but-equivalent spelling is not a defect.
1882
+ *
1883
+ * `writeZip` re-validates every part name, so a name that became unsafe between load and
1884
+ * save cannot be smuggled into the archive.
1885
+ */
1886
+ declare function writeOoxmlPackage(pkg: OoxmlPackage): Uint8Array;
1887
+ /** Replace one part's tree, returning a new package. Pure, like the tree edits themselves. */
1888
+ declare function withPart(pkg: OoxmlPackage, part: OoxmlPart): OoxmlPackage;
1889
+
1890
+ /** The `w15` namespace: `commentsExtended.xml` — thread parent and resolved state. */
1891
+ declare const W15_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2012/wordml";
1892
+ /** A position in one story: a paragraph node id plus a UTF-16 offset inside it. */
1893
+ interface CommentPosition {
1894
+ readonly paragraphId: string;
1895
+ readonly offset: number;
1896
+ }
1897
+ /**
1898
+ * Where a comment is anchored, as a range.
1899
+ *
1900
+ * `orphaned` records that the file did not give this comment a usable range — a reference with
1901
+ * no range markers, or a start with no end. The comment is still listed, marked orphaned,
1902
+ * rather than dropped: a reviewer's remark disappearing silently is worse than one that says
1903
+ * it lost its text.
1904
+ */
1905
+ interface CommentAnchor {
1906
+ readonly commentId: string;
1907
+ /** Canonical name of the part the range lives in, so a header comment is attributable. */
1908
+ readonly partName: string;
1909
+ readonly start: CommentPosition;
1910
+ readonly end: CommentPosition;
1911
+ readonly orphaned: boolean;
1912
+ }
1913
+ /** One comment as authored in `word/comments.xml`. */
1914
+ interface CommentRecord {
1915
+ readonly id: string;
1916
+ readonly author: string;
1917
+ readonly initials?: string;
1918
+ readonly date?: string;
1919
+ /** Body paragraphs, as tree nodes, so the surface renders measured text rather than a string. */
1920
+ readonly blocks: readonly OoxmlElement[];
1921
+ /** `w14:paraId` of the last body paragraph — the key thread state is stored under. */
1922
+ readonly paraId?: string;
1923
+ /** `@w16cid:parentId` — the `w:id` of the comment this replies to, when the file names it. */
1924
+ readonly parentCommentId?: string;
1925
+ }
1926
+ /** Thread state for one comment, read from `commentsExtended.xml`. */
1927
+ interface CommentThreadState {
1928
+ /** `@w15:paraIdParent` — the comment this one replies to, absent for a top-level comment. */
1929
+ readonly parentParaId?: string;
1930
+ readonly done: boolean;
1931
+ }
1932
+ /**
1933
+ * Every comment anchor in one story, in document order.
1934
+ *
1935
+ * Overlapping and nested ranges are supported because each anchor is resolved independently —
1936
+ * Word produces both, and a model that assumed ranges nest cleanly would mis-anchor them.
1937
+ *
1938
+ * A start with no matching end anchors to the end of its own paragraph and is reported orphaned
1939
+ * rather than guessed at: extending it to the next end marker would attach a reviewer's remark
1940
+ * to text they never saw.
1941
+ */
1942
+ declare function commentAnchorsOfStory(part: OoxmlPart): CommentAnchor[];
1943
+ /**
1944
+ * The comments in `word/comments.xml`, in authored order.
1945
+ *
1946
+ * Every value here comes from a file an attacker fully controls, so nothing is interpreted:
1947
+ * author, initials and date are carried verbatim for a surface that will set them as TEXT.
1948
+ */
1949
+ declare function commentsOfPart(part: OoxmlPart): CommentRecord[];
1950
+ /**
1951
+ * Thread state by `w14:paraId`, from `commentsExtended.xml`.
1952
+ *
1953
+ * The part being PRESENT is not evidence of threading. `issue-68-large-comments-suggestions.docx`
1954
+ * ships it with 212 entries carrying `@w15:done` and not one `@w15:paraIdParent`, so it records
1955
+ * resolved state for a flat list. Absent parent means top-level, and that is a fact about the
1956
+ * file rather than a default this code chose.
1957
+ */
1958
+ declare function threadStateOfPart(part: OoxmlPart): Map<string, CommentThreadState>;
1959
+ /**
1960
+ * Whether the package holds any `w:comment` record — the cheap gate before a reap.
1961
+ *
1962
+ * Overflow cannot prove the package is comment-free, so it returns true and the reap still
1963
+ * runs rather than skipping cleanup.
1964
+ */
1965
+ declare function hasAnyComment(pkg: OoxmlPackage): boolean;
1966
+
1967
+ /** A position in the model offset space of one story. */
1968
+ interface ReviewPosition {
1969
+ readonly paragraphId: string;
1970
+ readonly offset: number;
1971
+ }
1972
+ /** Where an item is anchored: a range in one story. */
1973
+ interface ReviewRange {
1974
+ readonly partName: string;
1975
+ readonly start: ReviewPosition;
1976
+ readonly end: ReviewPosition;
1977
+ }
1978
+ /**
1979
+ * What kind of decision a revision card represents.
1980
+ *
1981
+ * Wider than the four content wrappers, because a reviewer has to be shown every pending
1982
+ * decision, including the ones that decorate no characters. A card the surface cannot show is
1983
+ * a change the reviewer never learns about — and `acceptAllRevisions` refuses if ANY revision
1984
+ * in the document is one the engine cannot resolve, so an invisible one makes Accept All fail
1985
+ * for a reason nothing on screen explains.
1986
+ */
1987
+ type ReviewRevisionKind = 'insert' | 'delete'
1988
+ /**
1989
+ * A combined deletion and insertion decision. The built-in reader lists them separately,
1990
+ * unless a review query asks to pair replacements or a custom review provider combines them.
1991
+ */
1992
+ | 'replace' | 'moveFrom' | 'moveTo'
1993
+ /** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
1994
+ | 'format'
1995
+ /** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
1996
+ | 'paragraphMark'
1997
+ /** A row, cell, section or grid revision. Supported row revisions are resolvable. */
1998
+ | 'structural';
1999
+ /**
2000
+ * One tracked change as a review card.
2001
+ *
2002
+ * Keyed per DECISION rather than per site: a revision spanning three ranges is one card, because
2003
+ * accepting it accepts all three.
2004
+ */
2005
+ interface ReviewRevisionItem {
2006
+ readonly kind: 'revision';
2007
+ /** Stable across renders and unique per decision within this editor instance. */
2008
+ readonly id: string;
2009
+ /** The payload `acceptRevision` / `rejectRevision` take. */
2010
+ readonly address: RevisionAddress;
2011
+ /**
2012
+ * EVERY address this decision covers, `address` first.
2013
+ *
2014
+ * Adjacent text fragments, table fragments, and formatting changes can combine multiple
2015
+ * original revisions into one decision. Review commands resolve the complete decision
2016
+ * in one transaction while preserving independent changes outside the group.
2017
+ */
2018
+ readonly addresses: readonly RevisionAddress[];
2019
+ /** The words a replacement removes. Empty for every other kind. */
2020
+ readonly replacedText: string;
2021
+ readonly revisionKind: ReviewRevisionKind;
2022
+ /** OOXML property-change element, used to resolve independently numbered formatting kinds. */
2023
+ readonly formattingKind?: string;
2024
+ /** Distinct structural operations covered by this decision, in document order. */
2025
+ readonly structuralChanges?: readonly ('rowInsert' | 'rowDelete' | 'cellInsert' | 'cellDelete' | 'cellMerge' | 'numberingInsert')[];
2026
+ /** Changed direct formatting values, ready for localized review summaries. */
2027
+ readonly formattingChanges?: readonly {
2028
+ readonly property: 'bold' | 'italic' | 'underline' | 'strike' | 'fontFamily' | 'fontSize' | 'color' | 'alignment' | 'leftIndent' | 'rightIndent' | 'firstLineIndent' | 'hangingIndent' | 'spaceBefore' | 'spaceAfter' | 'direction';
2029
+ /**
2030
+ * New direct value; null means inherit. Sizes and distances are in points. A direction is
2031
+ * `rtl` or `ltr`.
2032
+ */
2033
+ readonly value: string | null;
2034
+ }[];
2035
+ /** Newly applied proofing language codes in a tracked formatting change. */
2036
+ readonly formattingLanguages?: readonly string[];
2037
+ /**
2038
+ * WHICH decision a `paragraphMark` records, absent for every other kind.
2039
+ *
2040
+ * `EG_ParaRPrTrackChanges` is `ins? del? moveFrom? moveTo?`, and the four say opposite
2041
+ * things about one break. Without this a card called a deleted break an inserted one, which
2042
+ * is the reverse of what Accept on that card does.
2043
+ */
2044
+ readonly markDirection?: 'insert' | 'delete' | 'moveFrom' | 'moveTo';
2045
+ readonly author: string;
2046
+ readonly date?: string;
2047
+ /** Text the revision covers, for the card summary. Empty for changes with no characters. */
2048
+ readonly text: string;
2049
+ /** Every site this decision touches, in document order. */
2050
+ readonly ranges: readonly ReviewRange[];
2051
+ /**
2052
+ * How deeply this change is NESTED inside other changes, 0 for an unenclosed one.
2053
+ *
2054
+ * `w:ins` wrapping `w:del` is content one reviewer added and another struck. Both stay
2055
+ * pending, so both are cards, over one identical range — and a range then cannot say which
2056
+ * change a caret is in. Word treats the innermost as the operative one, so it wins the caret
2057
+ * and the change enclosing it stays listed and reachable.
2058
+ */
2059
+ readonly nesting: number;
2060
+ /**
2061
+ * How many leading `ranges` are the STRUCK half of a replacement.
2062
+ *
2063
+ * A replacement's card is one decision but its ranges are two colours — red over what is
2064
+ * going, green over what takes its place. ABSENT when the halves do not split at a single
2065
+ * point, which is what a file recording both under one revision id can produce; a surface
2066
+ * then has no basis for two colours and should paint one neutral band rather than guess.
2067
+ */
2068
+ readonly replacedRangeCount?: number;
2069
+ /**
2070
+ * True when the engine cannot resolve this kind, so accept and reject must not be offered.
2071
+ *
2072
+ * Derived by the DERIVATION rather than from a caller-supplied predicate: the refusal list
2073
+ * is internal, and a surface asked to compute it would have to guess. A card that offers a
2074
+ * button the engine will refuse is worse than one that explains why it cannot.
2075
+ */
2076
+ readonly readOnly: boolean;
2077
+ /** The other half of a move, or the other side of a delete/insert replacement. */
2078
+ readonly pairedWith?: string;
2079
+ /**
2080
+ * Comments answering this change, in document order.
2081
+ *
2082
+ * A reply to a tracked change IS a comment: `w:ins` and `w:del` carry no body, so the text
2083
+ * is written as a comment over the revision's own range and the range is what links them.
2084
+ */
2085
+ readonly replyIds: readonly string[];
2086
+ }
2087
+ /**
2088
+ * One comment as a review card. A reply carries `parentId`; OOXML gives replies no separate
2089
+ * element, so threads are reconstructed from that link.
2090
+ */
2091
+ interface ReviewCommentItem {
2092
+ readonly kind: 'comment';
2093
+ readonly id: string;
2094
+ readonly comment: CommentRecord;
2095
+ readonly range: ReviewRange | null;
2096
+ readonly resolved: boolean;
2097
+ /** The comment this replies to, absent for a top-level comment. */
2098
+ readonly parentId?: string;
2099
+ /** The REVISION this comment answers, when it covers exactly that change's characters. */
2100
+ readonly parentRevisionId?: string;
2101
+ /** Replies to this comment, in document order. Empty for a reply or a childless comment. */
2102
+ readonly replyIds: readonly string[];
2103
+ /** True when the file gave this comment no usable range. */
2104
+ readonly orphaned: boolean;
2105
+ }
2106
+ /**
2107
+ * A card contributed by a recognized custom node (`defineCustomNode` with a `reviewCard`
2108
+ * hook), anchored at the node's range.
2109
+ *
2110
+ * Informational, never resolvable: there is nothing to accept or reject, so the engine
2111
+ * refuses those verbs on it. `title` and `detail` are HOST-authored (the definition's hook
2112
+ * produced them), but `attrs` and `text` originate in a file an attacker controls — a
2113
+ * surface renders every one of these as text, never markup.
2114
+ */
2115
+ interface ReviewCustomItem {
2116
+ readonly kind: 'custom';
2117
+ /** The SDT node's stable id in the canonical tree. */
2118
+ readonly id: string;
2119
+ /** The definition's `name`. */
2120
+ readonly name: string;
2121
+ /** The raw `w:tag` the node was recognized from. Untrusted input. */
2122
+ readonly tag: string;
2123
+ /** Attrs decoded from the tag, after the definition's recognition hook. Untrusted input. */
2124
+ readonly attrs: Readonly<Record<string, string>>;
2125
+ /** The SDT's literal content text. Untrusted input. */
2126
+ readonly text: string;
2127
+ /**
2128
+ * The payload the node's control binds to, after the definition validated it.
2129
+ *
2130
+ * Undefined when the node carries none or the payload did not match — see the pro package's
2131
+ * `RecognizedCustomNode.data`, which this is carried from.
2132
+ */
2133
+ readonly data?: unknown;
2134
+ /**
2135
+ * Whether this node asked for a sidebar card.
2136
+ *
2137
+ * False for a definition with no `reviewCard`: the item exists so the chip's own surfaces can
2138
+ * read `attrs`, `text` and `data` off it, and the rail leaves it out. A surface listing cards
2139
+ * filters on this rather than on an empty `title`. An uncarded node never becomes the active
2140
+ * review item, so it never shows the active highlight.
2141
+ */
2142
+ readonly carded: boolean;
2143
+ /** Card title, from the definition's `reviewCard` hook. Empty when `carded` is false. */
2144
+ readonly title: string;
2145
+ /** Card body, from the definition's `reviewCard` hook. */
2146
+ readonly detail?: string;
2147
+ /**
2148
+ * Glyph for this node in the collapsed rail, as an SVG path in a `0 -960 960 960` viewBox.
2149
+ *
2150
+ * A PATH rather than a rendered node because this item crosses core, which is DOM-free and
2151
+ * React-free — the same reason `title` and `detail` are strings. A host that wants arbitrary
2152
+ * markup overrides the `Markers` part's `icon` instead, which lives in the adapter where JSX
2153
+ * belongs. Absent falls back to the generic custom-node glyph.
2154
+ *
2155
+ * HOST-AUTHORED, never file data: it is interpolated into an SVG `d` attribute, and a path
2156
+ * taken from a document would be attacker-controlled markup.
2157
+ */
2158
+ readonly icon?: string;
2159
+ readonly range: ReviewRange | null;
2160
+ }
2161
+ /**
2162
+ * One pending decision in the review queue: a tracked change, a comment thread, or a pro
2163
+ * custom-node card. Discriminate on `kind`.
2164
+ *
2165
+ * The store's own derivation (`collectReviewItems`) only ever produces the first two; the
2166
+ * `kind: 'custom'` card is contributed by the pro review module, which recognizes the node.
2167
+ */
2168
+ type ReviewItem = ReviewRevisionItem | ReviewCommentItem | ReviewCustomItem;
2169
+ /** What the review queue derivation reads: one story part plus its comment parts. */
2170
+ interface ReviewModelInput {
2171
+ /** The story the ranges live in — the main document, a header, a note. */
2172
+ readonly storyPart: OoxmlPart;
2173
+ /**
2174
+ * Header/footer story parts, in section order. Their revisions and comment anchors join
2175
+ * the queue: a tracked change in a header is a pending decision like any other, and a
2176
+ * queue that only walked the body silently hid it from the rail AND from Accept All.
2177
+ */
2178
+ readonly furnitureParts?: readonly OoxmlPart[] | undefined;
2179
+ /** Shared style definitions. Their revisions have no paragraph range. */
2180
+ readonly stylesPart?: OoxmlPart | undefined;
2181
+ /** `word/comments.xml`, absent when the package has none. */
2182
+ readonly commentsPart?: OoxmlPart | undefined;
2183
+ /** `word/commentsExtended.xml`, absent when the package has none. */
2184
+ readonly commentsExtendedPart?: OoxmlPart | undefined;
2185
+ /**
2186
+ * Custom node definitions from the module registry, forwarded OPAQUELY.
2187
+ *
2188
+ * Core carries them the way the registry does — as unknowns — so the definition shape
2189
+ * stays a capability-package concern. The pro derivation narrows them and contributes
2190
+ * `kind: 'custom'` cards for definitions that opted in.
2191
+ */
2192
+ readonly customNodes?: readonly unknown[] | undefined;
2193
+ /**
2194
+ * Where a capability package reports a node it could not read. Supplied per editor, so a page
2195
+ * with two of them keeps their diagnostics apart.
2196
+ */
2197
+ readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
2198
+ /**
2199
+ * The payload each of the story's controls binds to, keyed by the control's node id.
2200
+ *
2201
+ * Resolved by the ENGINE and handed over, because a payload lives in a customXml data part
2202
+ * and a derivation that only receives story parts has no way to reach one. Untrusted file
2203
+ * input on both members; a capability package validates it against whatever shape it
2204
+ * declared before handing it to a host.
2205
+ */
2206
+ readonly customNodePayloads?: ReadonlyMap<string, {
2207
+ readonly nodeId: string;
2208
+ readonly label: string;
2209
+ readonly data: string;
2210
+ }> | undefined;
2211
+ }
2212
+ /** The stable key a surface uses for the active item and for a React list. */
2213
+ declare function reviewItemKey(item: ReviewItem): string;
2214
+ /** Every range a decision touches. One card can cover several, in different paragraphs. */
2215
+ declare function reviewItemRanges(item: ReviewItem): readonly ReviewRange[];
2216
+ /** The first range of an item, in authored order, or null when it has none. */
2217
+ declare function firstReviewRange(item: ReviewItem): ReviewRange | null;
2218
+ /**
2219
+ * A single comparable number for document order.
2220
+ *
2221
+ * Paragraph index dominates offset, so a revision spanning paragraphs still sorts by where it
2222
+ * STARTS. An item with no resolvable range sorts last rather than to position zero, which is
2223
+ * where an orphan used to land — tearing an orphaned reply out of its own thread.
2224
+ */
2225
+ declare function reviewItemPositionRank(item: ReviewItem, order: ReadonlyMap<string, number>): number;
2226
+ /**
2227
+ * Every item covering a position, innermost first.
2228
+ *
2229
+ * Returning the whole stack rather than one winner is what lets a surface offer cycling, a
2230
+ * stacked card, or a "1 of 3" affordance. A comment wrapping a revision used to be unreachable
2231
+ * because only the tightest range was ever returned.
2232
+ */
2233
+ declare function reviewItemsAt(items: readonly ReviewItem[], position: ReviewPosition, order: ReadonlyMap<string, number>): ReviewItem[];
2234
+ /**
2235
+ * The item the caret is in, or null.
2236
+ *
2237
+ * A resolved comment never activates: a settled thread must not reopen itself as the reviewer
2238
+ * types near it.
2239
+ *
2240
+ * A REPLY resolves to the thread it belongs to. A reply is anchored over its parent's range,
2241
+ * so both cover the caret — and the reply, being newer, wins the innermost test. It is not a
2242
+ * card of its own (it renders inside its parent's), so the thread would have gone active with
2243
+ * nothing on screen showing it: the reply box vanished from a comment the moment somebody
2244
+ * replied to it.
2245
+ */
2246
+ declare function activeReviewItem(items: readonly ReviewItem[], position: ReviewPosition, order: ReadonlyMap<string, number>): ReviewItem | null;
2247
+ /**
2248
+ * Walk a reply up to the card that heads its thread. Guarded against a cyclic file.
2249
+ *
2250
+ * The head is not always a comment. A reply to a tracked change renders inside the REVISION's
2251
+ * card, so resolving it to itself opened an item nothing on screen was drawing — the reply box
2252
+ * vanished the moment somebody answered a change.
2253
+ *
2254
+ * EXPORTED because the paginated surface answers "which card is open" itself, against its own
2255
+ * dismissed-key state, rather than through {@link activeReviewItem}. Two copies of the
2256
+ * innermost-wins rule was survivable while a reply could only be a comment — the parent came
2257
+ * first in `comments.xml` order and won the tie by accident. It stopped being survivable the
2258
+ * moment a reply could answer a revision, which outranks it outright.
2259
+ */
2260
+ declare function reviewThreadRootOf(items: readonly ReviewItem[], comment: ReviewCommentItem): ReviewItem;
2261
+
2262
+ /** How deep controls may nest before a walk stops descending. Shared by every lane. */
2263
+ declare const MAX_CONTENT_CONTROL_NESTING = 32;
2264
+ /** Cap on controls one walk reports, so a hostile file cannot make a read unbounded. */
2265
+ declare const MAX_CONTENT_CONTROLS_PER_PART = 10000;
2266
+ /** `CT_SdtPr/w:id` is `ST_DecimalNumber`; Word treats it as a signed 32-bit integer. */
2267
+ declare const CONTENT_CONTROL_ID_MAX = 2147483647;
2268
+ /** `ST_Lock` (§17.5.2.24). An absent `w:lock` is `unlocked`. */
2269
+ /**
2270
+ * `w:lock` — what a control refuses.
2271
+ *
2272
+ * `sdtLocked` protects the wrapper, `contentLocked` the text inside it, and `sdtContentLocked`
2273
+ * both. A control inside a locked one is locked in effect regardless of its own value.
2274
+ */
2275
+ type ContentControlLock = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
2276
+ /**
2277
+ * What kind of control this is.
2278
+ *
2279
+ * `checkbox` is the Microsoft `w14:checkbox` extension rather than an ECMA-376 type
2280
+ * element, and the two are not mutually exclusive with "declares no type": four controls
2281
+ * in the comprehensive fixture declare the extension and no `w:`-prefixed type, so a scan
2282
+ * that read only the ECMA-376 choice reported them untyped. `untyped` means the control
2283
+ * declares neither — a rich-text container, which is what Word treats it as.
2284
+ */
2285
+ /** Which kind of control a `w:sdt` is, and therefore what a written value must look like. */
2286
+ type ContentControlKind = 'richText' | 'plainText' | 'checkbox' | 'dropDownList' | 'comboBox' | 'date' | 'picture' | 'docPartObj' | 'docPartList' | 'group' | 'citation' | 'bibliography' | 'equation' | 'untyped';
2287
+ /** One declared option of a dropdown or combo box: its display text and its stored value. */
2288
+ interface ContentControlListItem {
2289
+ readonly displayText: string;
2290
+ readonly value: string;
2291
+ }
2292
+ /** A date picker's authored format and locale, for rendering and for parsing what it stores. */
2293
+ interface ContentControlDateFormat {
2294
+ readonly fullDate?: string;
2295
+ readonly dateFormat?: string;
2296
+ readonly lid?: string;
2297
+ readonly storeMappedDataAs?: string;
2298
+ readonly calendar?: string;
2299
+ }
2300
+ /** One of a checkbox's two glyphs: the font and code point it is drawn with. */
2301
+ interface ContentControlCheckboxState {
2302
+ /** The `w14:val` hex code point of the glyph, exactly as the control declares it. */
2303
+ readonly value: string;
2304
+ readonly font?: string;
2305
+ }
2306
+ /**
2307
+ * A checkbox's state and the two glyphs it chooses between.
2308
+ *
2309
+ * Both glyphs matter on a write: setting the value has to update `w14:checked` AND the run's
2310
+ * character, or the document's glyph and its recorded state disagree.
2311
+ */
2312
+ interface ContentControlCheckbox {
2313
+ readonly checked: boolean;
2314
+ readonly checkedState?: ContentControlCheckboxState;
2315
+ readonly uncheckedState?: ContentControlCheckboxState;
2316
+ }
2317
+ /** `CT_DataBinding` — preserved metadata. Never resolved, never fetched. */
2318
+ /** `w:dataBinding` — the custom-XML part and XPath a control's value is bound to. */
2319
+ interface ContentControlDataBinding {
2320
+ readonly xpath?: string;
2321
+ readonly storeItemID?: string;
2322
+ readonly prefixMappings?: string;
2323
+ }
2324
+ /**
2325
+ * A control's whole `w:sdtPr`, projected into one typed shape.
2326
+ *
2327
+ * What every other lane reads instead of walking `localName` strings — which also means a Word
2328
+ * re-save that demotes the properties node to generic does not break the projection.
2329
+ */
2330
+ interface ContentControlProperties {
2331
+ readonly type: ContentControlKind;
2332
+ readonly alias?: string;
2333
+ readonly tag?: string;
2334
+ /** `@w:val` of `w:id` when the file declares a parseable one. Never fabricated. */
2335
+ readonly id?: number;
2336
+ readonly lock: ContentControlLock;
2337
+ /** The glossary entry named by `w:placeholder/w:docPart`. Preserved, never loaded. */
2338
+ readonly placeholderDocPart?: string;
2339
+ readonly temporary: boolean;
2340
+ readonly showingPlaceholder: boolean;
2341
+ readonly dataBinding?: ContentControlDataBinding;
2342
+ readonly label?: string;
2343
+ readonly tabIndex?: number;
2344
+ /** Items a dropdown or combo box offers. Empty for every other type. */
2345
+ readonly listItems: readonly ContentControlListItem[];
2346
+ readonly lastValue?: string;
2347
+ readonly date?: ContentControlDateFormat;
2348
+ readonly multiLine?: boolean;
2349
+ readonly checkbox?: ContentControlCheckbox;
2350
+ }
2351
+ /** Whether a node is a `w:sdt` wrapper. */
2352
+ declare function isContentControlNode(node: OoxmlNode): node is OoxmlContentControlNode;
2353
+ /** Whether a node is a `w:sdtContent` — the container holding a control's actual content. */
2354
+ declare function isContentControlContentNode(node: OoxmlNode): node is OoxmlContentControlContentNode;
2355
+ /**
2356
+ * A `w:sdt` wrapper, TYPED or DEMOTED.
2357
+ *
2358
+ * Flattening predates typing and must not stop at a control the reader refused to type: a
2359
+ * demoted wrapper still renders its content in place in Word, so a walk that only saw the
2360
+ * typed kind would drop every paragraph inside a malformed control out of the story.
2361
+ */
2362
+ declare function isContentControlWrapper(node: OoxmlNode): boolean;
2363
+ /**
2364
+ * The children of a wrapper's `w:sdtContent`, typed or demoted, in order.
2365
+ *
2366
+ * The one place that knows a control's content is reached through an intermediate element,
2367
+ * so the four flattening walks (story blocks, layout, header/footer references, list
2368
+ * resolution) ask the same question rather than each re-deriving it.
2369
+ */
2370
+ declare function contentControlContentChildren(wrapper: OoxmlNode): readonly OoxmlNode[];
2371
+ /**
2372
+ * A container's children with every content-control wrapper flattened away, bounded in depth.
2373
+ *
2374
+ * ONE unwrap rule, for the places where a control sits between a container and the children that
2375
+ * container is defined in terms of. `CT_SdtRow` puts it between `w:tbl` and `w:tr`, `CT_SdtCell`
2376
+ * between `w:tr` and `w:tc`, and a walk that filtered on the child's kind dropped the row or cell
2377
+ * entirely: not measured, not painted, not addressable. Flattening at the point of the filter
2378
+ * means a controlled row is the same row to the grid pass, the pagination pass and the story walk.
2379
+ *
2380
+ * Returns the SAME array identity when there is nothing to unwrap, so the tables that carry no
2381
+ * controls — nearly all of them — allocate nothing and the incremental layout cache still sees
2382
+ * its own inputs.
2383
+ */
2384
+ declare function flattenContentControls(children: readonly OoxmlNode[], maxDepth?: number): readonly OoxmlNode[];
2385
+ /** A control's `w:sdtPr`, or null. Matches structurally, so a Word-demoted node still resolves. */
2386
+ declare function contentControlPropertiesNodeOf(control: OoxmlNode): OoxmlContentControlPropertiesNode | undefined;
2387
+ /** A control's `w:sdtEndPr` — the run properties applied to its closing marker. */
2388
+ declare function contentControlEndPropertiesNodeOf(control: OoxmlNode): OoxmlContentControlEndPropertiesNode | undefined;
2389
+ /** A control's `w:sdtContent`, or null when the wrapper has none. */
2390
+ declare function contentControlContentNodeOf(control: OoxmlNode): OoxmlContentControlContentNode | undefined;
2391
+ /** A signed 32-bit `ST_DecimalNumber`, or undefined when the file wrote something else. */
2392
+ declare function parseContentControlId(raw: string | undefined): number | undefined;
2393
+ /**
2394
+ * Read a control's properties.
2395
+ *
2396
+ * Total: a control with no `w:sdtPr` at all answers the same shape with the defaults an
2397
+ * absent property means, so no caller has to branch on the container's existence.
2398
+ */
2399
+ declare function contentControlPropertiesOf(control: OoxmlNode): ContentControlProperties;
2400
+ /** Where a control sits, read off what its content holds. */
2401
+ type ContentControlLevel = 'block' | 'inline' | 'row' | 'cell' | 'empty';
2402
+ /**
2403
+ * How deeply a control is nested inside other controls.
2404
+ *
2405
+ * Bounded by {@link MAX_CONTENT_CONTROL_NESTING}: nesting depth comes from a file and is a
2406
+ * recursion bound.
2407
+ */
2408
+ declare function contentControlLevelOf(control: OoxmlNode): ContentControlLevel;
2409
+ /** One control, plus how deeply it is nested and the controls that enclose it. */
2410
+ interface ContentControlEntry {
2411
+ readonly node: OoxmlContentControlNode;
2412
+ /** 0 for a top-level control; the nesting depth otherwise. */
2413
+ readonly depth: number;
2414
+ /** Enclosing controls, outermost first. Empty at depth 0. */
2415
+ readonly ancestors: readonly OoxmlContentControlNode[];
2416
+ }
2417
+ /**
2418
+ * Every control under a node, in document order, bounded in depth and in count.
2419
+ *
2420
+ * ONE walk, shared. The nesting bound is the same one layout flattens with, so a control
2421
+ * a lane can address is a control every lane can address — and a file that nests past it
2422
+ * keeps its content in the tree (the serializer never stops) while no walk recurses
2423
+ * further.
2424
+ */
2425
+ declare function contentControlsIn(root: OoxmlNode, options?: {
2426
+ readonly maxDepth?: number;
2427
+ readonly limit?: number;
2428
+ }): readonly ContentControlEntry[];
2429
+ /** Find one control by canonical node id, with the same bounded walk. */
2430
+ declare function findContentControl(root: OoxmlNode, nodeId: string): ContentControlEntry | null;
2431
+ /**
2432
+ * The plain text a control's content holds, in reading order.
2433
+ *
2434
+ * `w:delText` is excluded: struck text is not the control's value, and a dropdown whose
2435
+ * old item is still present as a tracked deletion would otherwise report both.
2436
+ *
2437
+ * A manual line break is left out unless `lineBreak` names the text to report it as.
2438
+ * With that option, column breaks report U+000E so callers cannot silently discard them.
2439
+ */
2440
+ declare function contentControlTextOf(control: OoxmlNode, lineBreak?: string): string;
2441
+ /**
2442
+ * Resolve the lock a position inherits from the controls enclosing it.
2443
+ *
2444
+ * CONSERVATIVE, because a template that says a field cannot be edited and sits inside a
2445
+ * section that says it cannot be removed means both. Each half of `ST_Lock` is taken
2446
+ * independently and the strongest wins, so an unlocked control inside a `contentLocked`
2447
+ * one is still content-locked — a nested control cannot grant a permission its parent
2448
+ * withheld, which is the only reading under which a lock is a lock.
2449
+ */
2450
+ declare function resolveContentControlLock(chain: readonly ContentControlLock[]): ContentControlLock;
2451
+ /** Whether a resolved lock forbids editing the content it covers. */
2452
+ declare function lockForbidsEdit(lock: ContentControlLock): boolean;
2453
+ /** Whether a resolved lock forbids removing the control itself. */
2454
+ declare function lockForbidsRemoval(lock: ContentControlLock): boolean;
2455
+ /**
2456
+ * `CT_SdtPr`'s declared child order (§17.5.2.38), followed by the type choice.
2457
+ *
2458
+ * Serialization re-emits children in tree order, so the ONLY way a write keeps the
2459
+ * sequence valid is to place the child it authors at its schema position — which is what
2460
+ * {@link orderedContentControlProperties} does.
2461
+ */
2462
+ declare const CONTENT_CONTROL_PROPERTY_ORDER: readonly string[];
2463
+ /**
2464
+ * Rebuild a `w:sdtPr`'s children in schema order.
2465
+ *
2466
+ * Modelled children sort to their declared position and the type element follows them,
2467
+ * as the sequence requires. Everything else — a `w15:repeatingSection`, a vendor
2468
+ * extension, the `w14:checkbox` that is not part of the ECMA-376 choice — keeps the order
2469
+ * it was authored in and follows the modelled block, so a write that touches one property
2470
+ * neither drops nor reorders anything it does not name.
2471
+ */
2472
+ declare function orderedContentControlProperties(children: readonly OoxmlNode[]): readonly OoxmlNode[];
2473
+ /**
2474
+ * The next `w:id` to write.
2475
+ *
2476
+ * Solo: one past the document's own maximum. Never a clock, a timestamp, a random source
2477
+ * or a hash: those collide with ids already in the file and produce values Word rejects.
2478
+ * Null when the document already reaches the signed 32-bit bound, so the caller refuses
2479
+ * rather than wrapping into a negative id. Hostile or out-of-range existing values are
2480
+ * ignored for seeding rather than counted past.
2481
+ *
2482
+ * When a collaboration actor is bound (explicit argument or the open store transaction),
2483
+ * the next id is the next unused value in that actor's stripe. Two peers inserting a
2484
+ * generic content control — including a custom node authored as `w:sdt` — from the same
2485
+ * snapshot then cannot share a `w:id`.
2486
+ */
2487
+ declare function allocateContentControlId(root: OoxmlNode, actorId?: string): number | null;
2488
+
2489
+ /** The value a control accepts, by what kind of control it is. */
2490
+ type ContentControlValueInput = {
2491
+ readonly kind: 'text';
2492
+ readonly text: string;
2493
+ } | {
2494
+ readonly kind: 'listItem';
2495
+ readonly value: string;
2496
+ } | {
2497
+ readonly kind: 'checkbox';
2498
+ readonly checked: boolean;
2499
+ }
2500
+ /** A calendar date, `YYYY-MM-DD` or a full ISO-8601 instant. */
2501
+ | {
2502
+ readonly kind: 'date';
2503
+ readonly iso: string;
2504
+ };
2505
+ /** The control types an insertion may author. Picture and repeating section are deferred. */
2506
+ declare const INSERTABLE_CONTENT_CONTROL_TYPES: readonly ["richText", "plainText", "dropDownList", "comboBox", "date"];
2507
+ /**
2508
+ * The OOXML spellings the store writes.
2509
+ *
2510
+ * NOT the contract's `InsertableContentControlType`, which is the same set of kinds in the
2511
+ * READ vocabulary (`dropdown`) plus this lane's spelling of it (`dropDownList`). The editor
2512
+ * maps between the two; the names differ so a reader can tell which vocabulary a value is in.
2513
+ */
2514
+ type InsertableContentControlKind = (typeof INSERTABLE_CONTENT_CONTROL_TYPES)[number];
2515
+
2516
+ /** A canonical review decision. Keys are valid only in the open document. @public */
2517
+ interface RevisionBatchEntry {
2518
+ readonly key: string;
2519
+ readonly author: string;
2520
+ readonly partName: string;
2521
+ readonly revisionKind: ReviewRevisionItem['revisionKind'];
2522
+ }
2523
+ /** Why a requested decision remains pending. @public */
2524
+ type RevisionBatchSkipReason = 'unsupported-revision' | 'incomplete-group' | 'retained-structure' | 'unknown-revision';
2525
+ /** Outcome of one selected-set decision. Counts refer to review decisions, not XML markers. @public */
2526
+ interface RevisionBatchResult {
2527
+ readonly resolved: readonly RevisionBatchEntry[];
2528
+ readonly skipped: readonly {
2529
+ readonly key: string;
2530
+ readonly reason: RevisionBatchSkipReason;
2531
+ readonly revision?: RevisionBatchEntry;
2532
+ }[];
2533
+ /** All pending decisions in the addressed scope, including excluded and unsupported changes. */
2534
+ readonly remaining: number;
2535
+ }
2536
+ /** @internal Pure preflight; callers commit its operations through their normal write guards. */
2537
+ declare function planRevisionBatch(part: OoxmlPart, action: 'accept' | 'reject', keys?: readonly string[], scopeRoot?: OoxmlNode): {
2538
+ ops: readonly TreeDocOp[];
2539
+ result: RevisionBatchResult;
2540
+ };
2541
+
2542
+ /** Why a requested change keeps its attribution. @public */
2543
+ type RevisionAuthorSkipReason = 'unknown-revision' | 'unsupported-revision';
2544
+ /**
2545
+ * One reattributed change. `key` and `author` describe the change after the update, because
2546
+ * review keys include the author. @public
2547
+ */
2548
+ interface RevisionAuthorEntry extends RevisionBatchEntry {
2549
+ /**
2550
+ * The key the caller selected the change by. It differs from `key` when the attribution
2551
+ * changed, because review keys include the author and date.
2552
+ */
2553
+ readonly previousKey: string;
2554
+ /** The author the change had before the update. */
2555
+ readonly previousAuthor: string;
2556
+ }
2557
+ /** Outcome of one attribution change. Counts refer to review decisions, not XML markers. @public */
2558
+ interface RevisionAuthorResult {
2559
+ /** Changes that now carry the requested attribution, in selection order. */
2560
+ readonly updated: readonly RevisionAuthorEntry[];
2561
+ /** Requested changes that kept their attribution. */
2562
+ readonly skipped: readonly {
2563
+ readonly key: string;
2564
+ readonly reason: RevisionAuthorSkipReason;
2565
+ readonly revision?: RevisionBatchEntry;
2566
+ }[];
2567
+ }
2568
+ /** A planned attribution change: its ops, and how to name the result once they commit. */
2569
+ interface RevisionAuthorPlan {
2570
+ readonly ops: readonly TreeDocOp[];
2571
+ /** The outcome before commit. Updated entries still carry their previous keys. */
2572
+ readonly result: RevisionAuthorResult;
2573
+ /** The outcome against the committed part, with each updated change under its new key. */
2574
+ finish(after: OoxmlPart): RevisionAuthorResult;
2575
+ }
2576
+ /**
2577
+ * Plan an attribution change for selected review keys. Omitted keys select every change.
2578
+ * `authors` keeps only the changes those authors made.
2579
+ * Callers validate `revision` with `invalidRevisionAuthorInput` first.
2580
+ * @internal
2581
+ */
2582
+ declare function planRevisionAuthorChange(part: OoxmlPart, revision: RevisionAttributionInput, keys?: readonly string[], scopeRoot?: OoxmlNode, authors?: readonly string[]): RevisionAuthorPlan;
2583
+
2584
+ /** Allowlisted OOXML table border line styles — store/layout authority. */
2585
+ declare const TABLE_BORDER_STYLES: readonly ['single', 'dashed', 'dotted', 'double', 'triple', 'thick'];
2586
+ /**
2587
+ * One of the border line styles this engine draws.
2588
+ *
2589
+ * An ALLOWLIST, not the full `ST_Border` enumeration: a file may name any of the seventy-odd
2590
+ * OOXML border styles, and anything outside this set falls back rather than being passed through
2591
+ * to paint.
2592
+ */
2593
+ type TableBorderStyle = (typeof TABLE_BORDER_STYLES)[number];
2594
+
2595
+ /**
2596
+ * Shared types for the `@docx-editor.dev/core` contract. Type-only, zero runtime.
2597
+ *
2598
+ * `@docx-editor.dev/core/contracts/types` re-exports this module verbatim, through
2599
+ * `types-barrel.ts`. There is no `@docx-editor.dev/core/types` subpath.
2600
+ */
2601
+ /** Which paragraph-level reads the selection disagrees about. @public */
2602
+ interface ParagraphDisagreements {
2603
+ readonly alignment: boolean;
2604
+ /** The selection mixes left-to-right and right-to-left paragraphs. */
2605
+ readonly direction: boolean;
2606
+ readonly spaceBeforePt: boolean;
2607
+ readonly spaceAfterPt: boolean;
2608
+ readonly lineSpacing: boolean;
2609
+ readonly tabStops: boolean;
2610
+ }
2611
+ /**
2612
+ * The five paragraph flags a Paragraph dialog shows as checkboxes.
2613
+ *
2614
+ * `contextualSpacing` is Word's "Don't add space between paragraphs of the same style";
2615
+ * the rest are its Pagination block. `null` means the selection disagrees.
2616
+ *
2617
+ * @public
2618
+ */
2619
+ interface ParagraphFlags {
2620
+ readonly contextualSpacing: boolean | null;
2621
+ readonly keepNext: boolean | null;
2622
+ readonly keepLines: boolean | null;
2623
+ readonly widowControl: boolean | null;
2624
+ readonly pageBreakBefore: boolean | null;
2625
+ }
2626
+ /**
2627
+ * Every field of the Paragraph dialog, as `setParagraphFormat` takes it.
2628
+ *
2629
+ * An omitted field is left as authored. `null` REMOVES a setting so the style supplies it
2630
+ * again — not the same as a zero, which blocks the cascade.
2631
+ *
2632
+ * @public
2633
+ */
2634
+ interface ParagraphFormatCommand {
2635
+ alignment?: 'left' | 'center' | 'right' | 'justify';
2636
+ /**
2637
+ * Paragraph base direction (`w:bidi`), Word's Direction setting. `ltr` writes an explicit
2638
+ * off value where a style would otherwise make the paragraph right-to-left.
2639
+ */
2640
+ direction?: 'ltr' | 'rtl';
2641
+ spaceBeforePt?: number | null;
2642
+ spaceAfterPt?: number | null;
2643
+ lineSpacing?: {
2644
+ rule: 'multiple' | 'exact' | 'atLeast';
2645
+ value: number;
2646
+ } | null;
2647
+ indentLeftTwips?: number | null;
2648
+ indentRightTwips?: number | null;
2649
+ /** ONE signed first-line offset: negative is a hanging indent. */
2650
+ indentFirstLineTwips?: number | null;
2651
+ contextualSpacing?: boolean;
2652
+ keepNext?: boolean;
2653
+ keepLines?: boolean;
2654
+ widowControl?: boolean;
2655
+ pageBreakBefore?: boolean;
2656
+ /**
2657
+ * Replace the paragraph's custom tab stops. An empty list CLEARS them, which is what
2658
+ * "Clear All" does; omit the field to leave them as authored.
2659
+ */
2660
+ tabStops?: readonly ParagraphTabStop[];
2661
+ }
2662
+ /** One custom tab stop, as a command states it. @public */
2663
+ interface ParagraphTabStop {
2664
+ readonly positionTwips: number;
2665
+ readonly alignment: 'left' | 'center' | 'right' | 'decimal' | 'bar';
2666
+ readonly leader?: 'none' | 'dot' | 'hyphen' | 'underscore' | 'heavy' | 'middleDot';
2667
+ }
2668
+ /** Ownership token for one retained selection highlight. @public */
2669
+ type SelectionPin = symbol;
2670
+ /**
2671
+ * The LLM- and JSON-facing address for a piece of a document.
2672
+ *
2673
+ * `paraId` is the 8-hex `w14:paraId`, matched case-insensitively. `search` is a
2674
+ * phrase that must match EXACTLY ONCE inside that paragraph; ambiguous or
2675
+ * missing matches fail with `'ambiguous'` / `'notFound'` rather than falling
2676
+ * back to first-match.
2677
+ *
2678
+ * Offset-based addressing was tried and abandoned: an agent cannot compute a
2679
+ * character offset it has not seen, and offsets do not survive concurrent
2680
+ * edits. Do not reintroduce `{ blockId, offset }`.
2681
+ */
2682
+ interface DocAnchor {
2683
+ paraId: string;
2684
+ search?: string;
2685
+ /** Opt-in disambiguation. Omit to require uniqueness. */
2686
+ occurrence?: number;
2687
+ }
2688
+ /** Structural addressing for content the paraId map cannot reach. */
2689
+ interface DocLocation {
2690
+ container: ContainerRef;
2691
+ /** Block indices, descending into tables and content controls. */
2692
+ path: number[];
2693
+ offset?: number;
2694
+ }
2695
+ /**
2696
+ * Which STORY a location belongs to.
2697
+ *
2698
+ * The body is one container; every header, footer and note is another. A path alone is
2699
+ * ambiguous without it, because block index 0 exists in every story a document has.
2700
+ */
2701
+ type ContainerRef = {
2702
+ part: 'body';
2703
+ } | {
2704
+ part: 'header' | 'footer';
2705
+ rId: string;
2706
+ } | {
2707
+ part: 'footnote' | 'endnote';
2708
+ noteId: number;
2709
+ };
2710
+ /**
2711
+ * Anything an operation can be pointed at: a paragraph-relative {@link DocAnchor}, a structural
2712
+ * {@link DocLocation}, or a {@link DocRange} spanning two of them.
2713
+ */
2714
+ type DocTarget = DocAnchor | DocLocation | DocRange;
2715
+ /** A span between two positions. The endpoints may be addressed either way, independently. */
2716
+ interface DocRange {
2717
+ from: DocAnchor | DocLocation;
2718
+ to: DocAnchor | DocLocation;
2719
+ }
2720
+ /**
2721
+ * Every write returns this rather than `boolean`.
2722
+ *
2723
+ * A bare boolean cannot distinguish "no-op" from "target not found" from
2724
+ * "content control is locked", and the editor layer already throws eight
2725
+ * distinct ContentControl error classes that a boolean would flatten.
2726
+ */
2727
+ type ExecResult = {
2728
+ ok: true;
2729
+ /** Whether the DOCUMENT changed; view-only calls (pane, activation, mode) always report `false`. */
2730
+ changed: boolean;
2731
+ revisions?: RevisionBatchResult;
2732
+ /** Present on `setReviewChangesAuthor`: the changes it updated and the ones it skipped. */
2733
+ revisionAuthors?: RevisionAuthorResult;
2734
+ history?: HistoryGroupOutcome;
2735
+ } | {
2736
+ ok: false;
2737
+ code: ExecErrorCode;
2738
+ reason: string;
2739
+ target?: DocTarget;
2740
+ revisions?: RevisionBatchResult;
2741
+ revisionAuthors?: RevisionAuthorResult;
2742
+ };
2743
+ /**
2744
+ * Why a write was refused, as a value to branch on.
2745
+ *
2746
+ * Deliberately finer-grained than a boolean: "no-op", "target not found" and "content control is
2747
+ * locked" are different outcomes, and a caller retrying the first should not retry the third.
2748
+ */
2749
+ type ExecErrorCode = 'notFound' | 'ambiguous' | 'locked' | 'bound' | 'typeMismatch' | 'kindMismatch' | 'outOfBounds' | 'unsupported' | 'invalidArgs';
2750
+ /**
2751
+ * A parsed .docx.
2752
+ *
2753
+ * NOT JSON-round-trippable: it holds `Map`s and `Date`s, plus an internal
2754
+ * side-table of verbatim XML used for lossless round-tripping. Use `toJSON` /
2755
+ * `fromJSON` before sending it over JSON-RPC or handing it to a model.
2756
+ */
2757
+ interface DocxDocument {
2758
+ readonly body: DocumentBody;
2759
+ readonly styles: StyleDefinitions;
2760
+ readonly theme?: Theme;
2761
+ readonly comments: readonly DocComment[];
2762
+ readonly revisions: readonly Revision[];
2763
+ }
2764
+ /** The main story: its blocks in reading order, plus the sections derived from them. */
2765
+ interface DocumentBody {
2766
+ readonly content: readonly Block[];
2767
+ /**
2768
+ * Derived, not stored: recomputed on read from section-break markers and
2769
+ * section inheritance. Never treat it as a spreadable field.
2770
+ */
2771
+ readonly sections: readonly Section[];
2772
+ }
2773
+ /** The JSON-safe projection of a document. */
2774
+ interface DocxDocumentJSON {
2775
+ readonly [key: string]: unknown;
2776
+ }
2777
+ /** One section: the page it lays out on, and the header/footer stories it declares. */
2778
+ interface Section {
2779
+ readonly properties: SectionProperties;
2780
+ readonly headers: HeaderFooterSet;
2781
+ readonly footers: HeaderFooterSet;
2782
+ }
2783
+ /**
2784
+ * A section's three header (or footer) variants, each a relationship id.
2785
+ *
2786
+ * All optional: a variant a section does not declare inherits the previous section's, and one
2787
+ * absent everywhere means the document simply has none.
2788
+ */
2789
+ interface HeaderFooterSet {
2790
+ readonly default?: string;
2791
+ readonly first?: string;
2792
+ readonly even?: string;
2793
+ }
2794
+ /** Anything that can sit at block level in a story. Discriminate on `kind`. */
2795
+ type Block = Paragraph | Table | ContentControl;
2796
+ /** One paragraph: its runs, the style it names, and its list membership. */
2797
+ interface Paragraph {
2798
+ readonly kind: 'paragraph';
2799
+ /** `w14:paraId`. The stable handle `DocAnchor` addresses. */
2800
+ readonly paraId?: string;
2801
+ readonly runs: readonly Run[];
2802
+ readonly styleId?: string;
2803
+ readonly numbering?: NumberingRef;
2804
+ }
2805
+ /** A stretch of text sharing one set of character properties. */
2806
+ interface Run {
2807
+ readonly text: string;
2808
+ readonly formatting?: RunFormatting;
2809
+ /** Set when the run carries a tracked change. Unique only within its part. */
2810
+ readonly revisionId?: number;
2811
+ }
2812
+ /**
2813
+ * Character formatting, and — at selection level — the paragraph properties a toolbar reads
2814
+ * alongside it.
2815
+ *
2816
+ * One type serves both roles so a toolbar reads alignment, style and script state from the same
2817
+ * object as bold and italic. On a {@link Run} the selection-level fields stay absent: a run has
2818
+ * no alignment or paragraph style of its own.
2819
+ */
2820
+ interface RunFormatting {
2821
+ readonly bold?: boolean;
2822
+ readonly italic?: boolean;
2823
+ readonly underline?: boolean;
2824
+ readonly strike?: boolean;
2825
+ readonly color?: ColorValue;
2826
+ readonly highlight?: string;
2827
+ readonly fontFamily?: string;
2828
+ readonly fontSizePt?: number;
2829
+ readonly superscript?: boolean;
2830
+ readonly subscript?: boolean;
2831
+ /**
2832
+ * Paragraph alignment at the selection, as a PHYSICAL edge. `both` is OOXML's spelling of
2833
+ * justify. A right-to-left paragraph with no `w:jc` reads `right`.
2834
+ */
2835
+ readonly alignment?: 'left' | 'center' | 'right' | 'both';
2836
+ /**
2837
+ * Paragraph base direction at the selection (`w:bidi` through the style cascade). Absent
2838
+ * when the selection's paragraphs disagree; `disagrees.direction` then says so.
2839
+ */
2840
+ readonly direction?: 'ltr' | 'rtl';
2841
+ /** Paragraph style id (`w:pStyle`) at the selection. */
2842
+ readonly styleId?: string;
2843
+ /**
2844
+ * Line spacing at the selection, in the unit its rule implies — LINES for `multiple`,
2845
+ * points for `exact` and `atLeast`. The same vocabulary `setLineSpacing` takes, so a
2846
+ * control can show what it reads and send back what it shows. Absent when the
2847
+ * selection's paragraphs disagree or state no line spacing.
2848
+ */
2849
+ readonly lineSpacing?: {
2850
+ readonly rule: 'multiple' | 'exact' | 'atLeast';
2851
+ readonly value: number;
2852
+ };
2853
+ /**
2854
+ * Space above and below the paragraph at the selection, in points.
2855
+ *
2856
+ * The measurement the cascade STATES — `w:docDefaults`, the style chain and direct
2857
+ * formatting resolved together — not the gap the page finally draws. The two differ for a
2858
+ * paragraph carrying `w:beforeAutospacing`, where Word substitutes its own value and
2859
+ * ignores the measurement, and again where two paragraphs collapse their adjacent spacing.
2860
+ * Absent when the selection's paragraphs disagree or no level states it.
2861
+ */
2862
+ readonly spaceBeforePt?: number;
2863
+ readonly spaceAfterPt?: number;
2864
+ /**
2865
+ * The paragraph flags the Paragraph dialog shows as checkboxes.
2866
+ *
2867
+ * Each is `true`, `false`, or `null` when the selection's paragraphs disagree — a
2868
+ * checkbox needs all three. Read through the cascade, so a flag a STYLE sets reads as on,
2869
+ * which is what the box has to show over a paragraph the page is visibly keeping with the
2870
+ * next. Absent on a `Run`, like every other selection-level field here.
2871
+ */
2872
+ readonly paragraphFlags?: ParagraphFlags;
2873
+ /**
2874
+ * Which paragraph-level fields above are absent because the selection DISAGREES, as
2875
+ * opposed to because nothing states them.
2876
+ *
2877
+ * A `null`/absent value alone cannot tell those apart, and both readings have shipped as
2878
+ * bugs: a disagreement rendered as a concrete value is uncorrectable, because the value
2879
+ * that would fix it is the one already on screen; an absent value rendered as "mixed"
2880
+ * tells a single paragraph it disagrees with itself.
2881
+ */
2882
+ readonly disagrees?: ParagraphDisagreements;
2883
+ /**
2884
+ * The paragraph's custom tab stops at the selection, cascade included. Absent when the
2885
+ * selection disagrees or the paragraphs have none.
2886
+ */
2887
+ readonly tabStops?: readonly ParagraphTabStop[];
2888
+ /**
2889
+ * The EFFECTIVE paragraph indent at the selection — cascade and numbering merge
2890
+ * included, so a numbered item that authors no `w:ind` reports the indent its list
2891
+ * definition gives it. Absent when nothing is loaded, or when the selection is inside a
2892
+ * table (see {@link IndentFormatting}).
2893
+ */
2894
+ readonly indent?: IndentFormatting;
2895
+ }
2896
+ /**
2897
+ * Indent at the selection, in twips.
2898
+ *
2899
+ * Unlike every other field here, this does NOT go absent when the selection's paragraphs
2900
+ * disagree. A ruler has to draw its handles somewhere, and Word draws them at the FIRST
2901
+ * selected paragraph's values — Select All is the commonest indent gesture, and hiding the
2902
+ * handles for it would be worse than showing one paragraph's truth. The values are
2903
+ * therefore always the first touched paragraph's, and {@link mixed} records per field
2904
+ * whether the rest agree.
2905
+ *
2906
+ * `firstLine` is ONE SIGNED offset: negative is a hanging indent. OOXML spells it as two
2907
+ * mutually exclusive attributes and this collapses them hanging-wins (§17.3.1.12), which
2908
+ * is the model Word itself keeps.
2909
+ *
2910
+ * Absent inside a table. The value would be correct there, but it is measured from the
2911
+ * cell's content edge while a ruler is drawn against the page's margin, and the ruler does
2912
+ * not know the cell.
2913
+ */
2914
+ interface IndentFormatting {
2915
+ /**
2916
+ * Leading indent (`w:left`), signed: the left one, or the right one in a right-to-left
2917
+ * paragraph. Negative pulls text into the margin, as Word allows.
2918
+ */
2919
+ readonly left: number;
2920
+ /** Trailing indent (`w:right`), signed: the right one, or the left one right to left. */
2921
+ readonly right: number;
2922
+ /** First-line offset from {@link left}, signed. Negative is a hanging indent. */
2923
+ readonly firstLine: number;
2924
+ /** Per field, whether the selection's paragraphs disagree about it. */
2925
+ readonly mixed: {
2926
+ readonly left: boolean;
2927
+ readonly right: boolean;
2928
+ readonly firstLine: boolean;
2929
+ };
2930
+ /**
2931
+ * The first selected paragraph reads right to left, so `left` and the first line sit on
2932
+ * the right margin. Absent for a left-to-right paragraph.
2933
+ */
2934
+ readonly rtl?: true;
2935
+ }
2936
+ /** A table: its rows, and the table style they resolve through. */
2937
+ interface Table {
2938
+ readonly kind: 'table';
2939
+ readonly rows: readonly TableRow[];
2940
+ readonly styleId?: string;
2941
+ }
2942
+ /** One table row. Cell count may vary between rows: `colSpan` and vertical merges reshape it. */
2943
+ interface TableRow {
2944
+ readonly cells: readonly TableCell[];
2945
+ }
2946
+ /**
2947
+ * One cell. Its `content` is ordinary blocks, so a cell may hold paragraphs, nested tables and
2948
+ * content controls alike.
2949
+ */
2950
+ interface TableCell {
2951
+ readonly content: readonly Block[];
2952
+ /** Vertical merge span. Absent means 1. */
2953
+ readonly rowSpan?: number;
2954
+ /** `w:gridSpan`. Absent means 1. */
2955
+ readonly colSpan?: number;
2956
+ }
2957
+ /** Structured document tag (`w:sdt`). */
2958
+ interface ContentControl {
2959
+ readonly kind: 'contentControl';
2960
+ readonly id: string;
2961
+ readonly tag?: string;
2962
+ readonly alias?: string;
2963
+ readonly controlType: ContentControlType;
2964
+ readonly locked?: boolean;
2965
+ readonly content: readonly Block[];
2966
+ }
2967
+ /** Which kind of control a `w:sdt` is, and therefore what a value written into it must be. */
2968
+ type ContentControlType = 'richText' | 'plainText' | 'checkbox' | 'dropdown' | 'comboBox' | 'date' | 'picture' | 'buildingBlockGallery' | 'repeatingSection';
2969
+ /**
2970
+ * The control kinds an insertion can author.
2971
+ *
2972
+ * A NARROWING of {@link ContentControlType}, not a separate vocabulary: a kind read off an
2973
+ * existing control can be handed straight back to `insertContentControl`. Three kinds are
2974
+ * absent because an insertion would have to invent what they carry — a checkbox needs its two
2975
+ * declared glyph states, a picture needs an image part, a building block gallery needs a
2976
+ * 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
2977
+ * kinds this cannot create.
2978
+ *
2979
+ * `dropDownList` is the same kind as `dropdown`, spelt as OOXML spells it. Both are accepted,
2980
+ * so a type read off a control can be handed back without translating it — and the OOXML
2981
+ * spelling is the one the automation protocol takes, so a caller who uses both surfaces can
2982
+ * write that one everywhere.
2983
+ */
2984
+ type InsertableContentControlType = Extract<ContentControlType, 'richText' | 'plainText' | 'dropdown' | 'comboBox' | 'date'> | 'dropDownList';
2985
+ /**
2986
+ * Narrows a content-control query. Fields combine with AND; an empty filter matches every
2987
+ * control.
2988
+ */
2989
+ interface ContentControlFilter {
2990
+ readonly tag?: string;
2991
+ readonly alias?: string;
2992
+ readonly controlType?: ContentControlType;
2993
+ }
2994
+ /**
2995
+ * A position in one story: a paragraph and a UTF-16 offset inside it.
2996
+ *
2997
+ * The same offset space the ops and the caret use, so an anchor read here can be handed
2998
+ * straight back to a selection without re-deriving anything.
2999
+ */
3000
+ interface DocAnchorRange {
3001
+ /** Canonical part name of the story the range lives in, e.g. `/word/document.xml`. */
3002
+ readonly part: string;
3003
+ readonly startParagraphId: string;
3004
+ readonly startOffset: number;
3005
+ /** May sit in a later paragraph: the range markers are independent elements. */
3006
+ readonly endParagraphId: string;
3007
+ readonly endOffset: number;
3008
+ }
3009
+ /**
3010
+ * One comment or reply, as `comments.xml` records it.
3011
+ *
3012
+ * A reply is a comment with a `parentId`; OOXML gives replies no separate element, so the thread
3013
+ * is reconstructed from that link rather than from nesting.
3014
+ */
3015
+ interface DocComment {
3016
+ readonly id: string;
3017
+ readonly author: string;
3018
+ /**
3019
+ * OPTIONAL, because `CT_Comment` makes `@w:date` optional and files omit it. A comment
3020
+ * with no date is a comment, not a defect, and fabricating one is a content change.
3021
+ */
3022
+ readonly date?: string;
3023
+ readonly text: string;
3024
+ readonly parentId?: string;
3025
+ readonly resolved?: boolean;
3026
+ /**
3027
+ * Where the comment is anchored, absent when the file gave it no usable range.
3028
+ *
3029
+ * A comment lives in `comments.xml` and is placed by markers in a STORY, so the story is
3030
+ * part of the address: a comment anchored in a header belongs to a part the body never saw.
3031
+ */
3032
+ readonly anchor?: DocAnchorRange;
3033
+ /**
3034
+ * True when the file gave this comment no usable range — a reference with no markers, or a
3035
+ * start with no end. Reported rather than dropped: a reviewer's remark vanishing silently
3036
+ * is worse than one that says it lost its text.
3037
+ */
3038
+ readonly orphaned?: boolean;
3039
+ }
3040
+ /**
3041
+ * What kind of decision a revision represents.
3042
+ *
3043
+ * Wider than insert/delete/format, and it has to be. `w:moveFrom`/`w:moveTo` are not a
3044
+ * deletion and an insertion — resolving one half alone duplicates or loses the content;
3045
+ * `w:pPr/w:rPr/w:ins|w:del` decorates no characters at all and merges paragraphs when
3046
+ * resolved; a row or cell revision is structural. A reviewer shown only three kinds is a
3047
+ * reviewer who never learns about the rest.
3048
+ */
3049
+ type RevisionType = 'insert' | 'delete'
3050
+ /** A deletion and an insertion that are one edit: text typed over a selection. */
3051
+ | 'replace' | 'moveFrom' | 'moveTo'
3052
+ /** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
3053
+ | 'format'
3054
+ /** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
3055
+ | 'paragraphMark'
3056
+ /** A row, cell, section or grid revision. */
3057
+ | 'structural';
3058
+ /**
3059
+ * One tracked change.
3060
+ *
3061
+ * Addressing needs BOTH `id` and `part`: `@w:id` is unique only within a part, so an id alone
3062
+ * names two revisions in any package that has a header or a comments part.
3063
+ */
3064
+ interface Revision {
3065
+ /** Numeric, and unique only WITHIN a part. Pair with `part` to address one. */
3066
+ readonly id: number;
3067
+ readonly type: RevisionType;
3068
+ readonly author: string;
3069
+ /**
3070
+ * OPTIONAL. `CT_TrackChange` requires `@w:id` and `@w:author` and makes `@w:date`
3071
+ * optional, and producers that omit it are ordinary. Requiring it here forced either a
3072
+ * fabricated date — a content change — or dropping the revision from the list.
3073
+ */
3074
+ readonly date?: string;
3075
+ /**
3076
+ * REQUIRED, and a canonical PART NAME rather than a three-value enum.
3077
+ *
3078
+ * `@w:id` is unique only within a part, so an address without one names two revisions in a
3079
+ * package that has both. The enum could not express the parts revisions actually occur in:
3080
+ * `header3.xml`, `footer1.xml`, `comments.xml`, and `styles.xml`, which carries
3081
+ * `w:pPrChange` inside style definitions with ids that collide with `document.xml`.
3082
+ */
3083
+ readonly part: string;
3084
+ }
3085
+ /** `w:sectPr`: the page a section lays out on. Twips throughout, as the file stores them. */
3086
+ interface SectionProperties {
3087
+ readonly pageSize: {
3088
+ widthTwips: number;
3089
+ heightTwips: number;
3090
+ };
3091
+ readonly margins: PageMargins;
3092
+ readonly columns?: {
3093
+ count: number;
3094
+ gapTwips: number;
3095
+ };
3096
+ /** `w:titlePg` — whether the section's first page takes the `first` header/footer variant. */
3097
+ readonly titlePage?: boolean;
3098
+ }
3099
+ /** Page margins in twips. */
3100
+ interface PageMargins {
3101
+ readonly topTwips: number;
3102
+ readonly rightTwips: number;
3103
+ readonly bottomTwips: number;
3104
+ readonly leftTwips: number;
3105
+ }
3106
+ /**
3107
+ * `styles.xml`, split by the three style families that address separately.
3108
+ *
3109
+ * Keyed by style ID rather than by the name a reader sees, because the ID is what a paragraph or
3110
+ * run actually references.
3111
+ */
3112
+ interface StyleDefinitions {
3113
+ readonly paragraph: ReadonlyMap<string, StyleDefinition>;
3114
+ readonly character: ReadonlyMap<string, StyleDefinition>;
3115
+ readonly table: ReadonlyMap<string, StyleDefinition>;
3116
+ }
3117
+ /** One style: the ID content references, the name a reader sees, and its inheritance link. */
3118
+ interface StyleDefinition {
3119
+ readonly id: string;
3120
+ readonly name: string;
3121
+ /** `w:basedOn` — the style this one inherits from. Absent at the root of a chain. */
3122
+ readonly basedOn?: string;
3123
+ }
3124
+ /** A paragraph's list membership: which `numbering.xml` definition, and at which level. */
3125
+ interface NumberingRef {
3126
+ readonly numId: string;
3127
+ /** Zero-based. OOXML numbering has nine levels, 0 through 8. */
3128
+ readonly level: number;
3129
+ }
3130
+ /**
3131
+ * A colour as the FILE expresses it, not as a resolved RGB string.
3132
+ *
3133
+ * A theme colour stays a theme reference — slot plus tint or shade — so that changing the theme
3134
+ * repaints the document the way Word does. Flattening to hex at read time would freeze the
3135
+ * resolved value and break that link. `auto` is Word's "let the renderer decide", usually black
3136
+ * on white.
3137
+ */
3138
+ type ColorValue = {
3139
+ readonly kind: 'hex';
3140
+ readonly value: string;
3141
+ } | {
3142
+ readonly kind: 'theme';
3143
+ readonly slot: string;
3144
+ readonly tint?: number;
3145
+ readonly shade?: number;
3146
+ } | {
3147
+ readonly kind: 'auto';
3148
+ };
3149
+ /** `theme1.xml` — what a {@link ColorValue} of kind `theme` resolves against. */
3150
+ interface Theme {
3151
+ readonly colorScheme: ThemeColorScheme;
3152
+ readonly fontScheme?: Record<string, string>;
3153
+ }
3154
+ /** Theme colour slots (`accent1`, `dk1`, `lt2`, …) to hex. */
3155
+ type ThemeColorScheme = Readonly<Record<string, string>>;
3156
+ /** A watermark, which OOXML expresses as either text or an image — never both meaningfully. */
3157
+ interface Watermark {
3158
+ readonly text?: string;
3159
+ readonly imageData?: Uint8Array;
3160
+ }
3161
+ /** A size in EMUs, the unit DrawingML stores extents in. 914400 EMU = 1 inch. */
3162
+ interface Extent {
3163
+ readonly widthEmu: number;
3164
+ readonly heightEmu: number;
3165
+ }
3166
+ /** A font the document names, and whether its bytes travel inside the package. */
3167
+ interface FontDefinition {
3168
+ readonly family: string;
3169
+ readonly embedded: boolean;
3170
+ }
3171
+ /** An axis-aligned rectangle in points, the unit layout works in throughout. */
3172
+ interface Rect {
3173
+ readonly x: number;
3174
+ readonly y: number;
3175
+ readonly width: number;
3176
+ readonly height: number;
3177
+ }
3178
+ /** A position in points. */
3179
+ interface Point {
3180
+ readonly x: number;
3181
+ readonly y: number;
3182
+ }
3183
+ /** What every subscription returns. Calling it twice is safe. */
3184
+ type Unsubscribe = () => void;
3185
+
3186
+ /**
3187
+ * A colour as an op carries it: a literal, a theme reference, or automatic.
3188
+ *
3189
+ * Theme references stay references so the document keeps following its theme; flattening one to
3190
+ * hex at write time would freeze the resolved value into the file.
3191
+ */
3192
+ type TreeDocColorValue = {
3193
+ readonly kind: 'hex';
3194
+ readonly value: string;
3195
+ } | {
3196
+ readonly kind: 'theme';
3197
+ readonly slot: string;
3198
+ readonly resolvedHex: string;
3199
+ readonly tint?: number;
3200
+ readonly shade?: number;
3201
+ } | {
3202
+ readonly kind: 'auto';
3203
+ readonly resolvedHex: string;
3204
+ };
3205
+ /** Which edges a border op addresses — the four sides, the interiors, all, or clear. */
3206
+ type TableBorderTarget = 'all' | 'outside' | 'inside' | 'none' | 'top' | 'bottom' | 'left' | 'right';
3207
+ /** A {@link TableBorderTarget} that draws something — everything except clear. */
3208
+ type TableBorderEdgeTarget = Exclude<TableBorderTarget, 'none'>;
3209
+ /** Complete border spec for non-`none` selected-cell border scopes. Size is in eighths of a point. */
3210
+ /** A complete border spec: style, width and colour. Ops carry all three, never a partial edit. */
3211
+ interface TableBorderSpecInput {
3212
+ readonly style: TableBorderStyle;
3213
+ readonly size: number;
3214
+ readonly color: TreeDocColorValue;
3215
+ }
3216
+ /**
3217
+ * The accepted RUN property boundary (design D8), as the OOXML element names that carry it.
3218
+ *
3219
+ * An explicit allowlist rather than "any `w:rPr` child": a property outside D8 has no
3220
+ * resolver, no layout behavior and no support claim, so accepting it here would let an
3221
+ * operation assert support the engine does not have. Unknown properties still ROUND-TRIP —
3222
+ * they are generic nodes in the tree — they simply cannot be authored by an op.
3223
+ */
3224
+ 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'];
3225
+ /** The accepted PARAGRAPH property boundary (design D8). */
3226
+ declare const ACCEPTED_PARAGRAPH_PROPERTIES: readonly ['pStyle', 'jc', 'spacing', 'ind', 'tabs', 'numPr', 'keepNext', 'keepLines', 'widowControl', 'pageBreakBefore', 'contextualSpacing', 'shd', 'bidi'];
3227
+ /**
3228
+ * One tab stop an op can author: where it sits, how it aligns, and what fills the gap.
3229
+ *
3230
+ * An alias, not a second declaration. The contract lane already names this shape, and two
3231
+ * public names for one shape is a trap — a caller building a stop for a read and for an op
3232
+ * would otherwise have to name it two things.
3233
+ */
3234
+ type TabStopWrite = ParagraphTabStop;
3235
+ /**
3236
+ * One authored property: an element name plus its `w:`-namespace attributes.
3237
+ *
3238
+ * Modeled as name+attributes rather than a typed record per property because that is what
3239
+ * the tree holds, so an op maps to nodes without a lossy intermediate vocabulary. Attribute
3240
+ * VALUES are validated as XML text; their meaning is the resolver's business.
3241
+ *
3242
+ * Deliberately structural rather than a typed union: the accepted property lists bound WHICH
3243
+ * properties may be written, so the shape itself does not need to enumerate them.
3244
+ */
3245
+ interface OoxmlProperty {
3246
+ readonly localName: string;
3247
+ readonly attributes?: Readonly<Record<string, string>>;
3248
+ }
3249
+
3250
+ /**
3251
+ * Every mutation the store accepts, as one JSON-safe discriminated union.
3252
+ *
3253
+ * The ONLY write path into a document. Each op addresses nodes by id plus UTF-16 offset, which is
3254
+ * what makes editing a paragraph inside a table cell no different from editing one at the top
3255
+ * level. Declarative and serializable, so the same op crosses a worker or transport boundary
3256
+ * unchanged.
3257
+ */
3258
+ type TreeDocOp = SetFieldCodeOp | {
3259
+ /**
3260
+ * Replace one story's complete block structure with fresh plain paragraphs.
3261
+ *
3262
+ * Unlike a span replacement, this removes section-ending paragraphs and content-control
3263
+ * wrappers. A body's final direct `w:sectPr` survives to retain the page setup.
3264
+ */
3265
+ readonly op: 'replaceStoryBlocks';
3266
+ readonly storyRootId: string;
3267
+ readonly paragraphs: readonly string[];
3268
+ } | {
3269
+ /**
3270
+ * Insert an SDT-wrapped TOC immediately before a body paragraph.
3271
+ * The initial cached result and any heading bookmarks land in one undo unit.
3272
+ */
3273
+ readonly op: 'insertToc';
3274
+ readonly beforeParagraphId: string;
3275
+ readonly instruction: string;
3276
+ readonly alias: string;
3277
+ readonly entries: readonly {
3278
+ readonly level: number;
3279
+ readonly text: string;
3280
+ readonly headingParagraphId: string;
3281
+ readonly bookmarkName: string;
3282
+ readonly pageNumberText: string;
3283
+ }[];
3284
+ readonly bookmarksToCreate: readonly {
3285
+ readonly paragraphId: string;
3286
+ readonly name: string;
3287
+ }[];
3288
+ } | InsertTextOp | DeleteTextOp | {
3289
+ /**
3290
+ * Mark a paragraph's own MARK as inserted or deleted (`w:pPr/w:rPr/w:ins|w:del`,
3291
+ * §17.13.5). The change is to the paragraph break itself, so no character carries it.
3292
+ */
3293
+ readonly op: 'setParagraphMarkRevision';
3294
+ readonly paragraphId: string;
3295
+ readonly kind: 'ins' | 'del';
3296
+ readonly revision: RevisionAttributionInput;
3297
+ } | {
3298
+ /**
3299
+ * Propose merging this paragraph into its PREDECESSOR by striking the predecessor's
3300
+ * mark. Addressed by the SECOND paragraph so a multi-paragraph delete marks each
3301
+ * paragraph's own predecessor rather than stamping the group head N times.
3302
+ */
3303
+ readonly op: 'proposeParagraphMerge';
3304
+ readonly paragraphId: string;
3305
+ readonly revision: RevisionAttributionInput;
3306
+ } | {
3307
+ /**
3308
+ * Place one piece of comment markup at a model offset.
3309
+ *
3310
+ * Separate from the comment BODY, which lives in another part: this op is the story half
3311
+ * of a comment write, and the two are staged in one package transaction.
3312
+ */
3313
+ readonly op: 'insertCommentMarker';
3314
+ readonly paragraphId: string;
3315
+ readonly offset: number;
3316
+ readonly commentId: string;
3317
+ readonly marker: 'start' | 'end' | 'reference';
3318
+ } | {
3319
+ /**
3320
+ * Accept one revision, resolving every site in this part that carries its triple.
3321
+ */
3322
+ readonly op: 'acceptRevision';
3323
+ readonly revision: RevisionAddress;
3324
+ /** When set, only wrappers with this element local name resolve (ins/del/moveFrom/moveTo). */
3325
+ readonly localName?: string;
3326
+ /** Internal exact-site scope used when one Word revision address names separate decisions. */
3327
+ readonly siteNodeIds?: readonly string[];
3328
+ } | {
3329
+ readonly op: 'rejectRevision';
3330
+ readonly revision: RevisionAddress;
3331
+ readonly localName?: string;
3332
+ /** Internal exact-site scope used when one Word revision address names separate decisions. */
3333
+ readonly siteNodeIds?: readonly string[];
3334
+ } | {
3335
+ /**
3336
+ * Accept every revision in the part, or in one exact note root, in ONE transaction and one
3337
+ * history entry.
3338
+ *
3339
+ * Deliberately not a loop over `acceptRevision`: a reviewer who accepts a document's
3340
+ * changes made one decision, and one undo should restore all of them.
3341
+ */
3342
+ readonly op: 'acceptAllRevisions';
3343
+ /** Exact canonical sites selected by bulk preflight. */
3344
+ readonly siteNodeIds?: readonly string[];
3345
+ /** Internal shared-notes scope. When present, this must be the canonical id of a note root. */
3346
+ readonly scopeRootId?: string;
3347
+ } | {
3348
+ /**
3349
+ * Attribute pending revisions to another author, and optionally another date, without
3350
+ * deciding them. `sites` name revision elements and move range starts. Sites sharing a
3351
+ * `renumber` label take one fresh `w:id`, so the change cannot merge with another one.
3352
+ */
3353
+ readonly op: 'setRevisionAttribution';
3354
+ readonly revision: RevisionAttributionInput;
3355
+ readonly sites: readonly {
3356
+ readonly nodeId: string;
3357
+ readonly renumber?: string;
3358
+ }[];
3359
+ } | {
3360
+ readonly op: 'rejectAllRevisions';
3361
+ /** Exact canonical sites selected by bulk preflight. */
3362
+ readonly siteNodeIds?: readonly string[];
3363
+ /** Internal shared-notes scope. When present, this must be the canonical id of a note root. */
3364
+ readonly scopeRootId?: string;
3365
+ } | {
3366
+ readonly op: 'insertTab';
3367
+ readonly paragraphId: string;
3368
+ readonly offset: number;
3369
+ /** Write this as a TRACKED insertion, on the same terms as `insertText`. */
3370
+ readonly revision?: RevisionAttributionInput;
3371
+ } | {
3372
+ readonly op: 'insertHardBreak';
3373
+ readonly paragraphId: string;
3374
+ readonly offset: number;
3375
+ /** Write this as a TRACKED insertion, on the same terms as `insertText`. */
3376
+ readonly revision?: RevisionAttributionInput;
3377
+ } | {
3378
+ readonly op: 'insertPageBreak';
3379
+ readonly paragraphId: string;
3380
+ readonly offset: number;
3381
+ /** Write this as a TRACKED insertion, on the same terms as `insertText`. */
3382
+ readonly revision?: RevisionAttributionInput;
3383
+ } | {
3384
+ /**
3385
+ * Insert an allowlisted page-number complex field at a UTF-16 offset.
3386
+ *
3387
+ * `PAGE_X_OF_Y` is PAGE + literal " of " + NUMPAGES in one undoable op. Non-page
3388
+ * instructions are refused — never authored through this path.
3389
+ */
3390
+ readonly op: 'insertPageField';
3391
+ readonly paragraphId: string;
3392
+ readonly offset: number;
3393
+ readonly field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y';
3394
+ /**
3395
+ * Write this as a TRACKED insertion, on the same terms as `insertText`.
3396
+ *
3397
+ * The whole field — every `w:fldChar`, the instruction, the `PAGE_X_OF_Y` literal —
3398
+ * goes into ONE `w:ins`, because the field is one proposal: rejecting it must take
3399
+ * the complete atom back, never leave a `begin` standing without its `end`.
3400
+ */
3401
+ readonly revision?: RevisionAttributionInput;
3402
+ } | {
3403
+ /**
3404
+ * Move a numbered paragraph to another `w:numPr/w:ilvl`.
3405
+ *
3406
+ * A list item's LEVEL is what selects its format out of `numbering.xml`, so this is
3407
+ * the op behind Increase/Decrease Indent on a list: the marker changes with it. A
3408
+ * paragraph carrying no `w:numPr` is refused rather than silently numbered.
3409
+ */
3410
+ readonly op: 'setListLevel';
3411
+ readonly paragraphId: string;
3412
+ readonly level: number;
3413
+ readonly revision?: RevisionAttributionInput;
3414
+ } | {
3415
+ /**
3416
+ * Put a paragraph in a list, or take it out of one.
3417
+ *
3418
+ * `numId` names a `w:num` in `numbering.xml`; null removes `w:numPr` entirely, which
3419
+ * is what turning a bullet off means. Everything else in `w:pPr` survives.
3420
+ */
3421
+ /**
3422
+ * Run properties of the PARAGRAPH MARK (`w:pPr/w:rPr`, ECMA-376 17.3.1.29).
3423
+ *
3424
+ * The mark carries the formatting a paragraph's own pilcrow has, and Word keeps it
3425
+ * in step whenever formatting is applied to a whole paragraph. It is what a list
3426
+ * marker inherits its face from — so without it, sizing a bulleted paragraph leaves
3427
+ * the bullet at the old size.
3428
+ */
3429
+ readonly op: 'setParagraphMarkProperties';
3430
+ readonly paragraphId: string;
3431
+ readonly properties: readonly OoxmlProperty[];
3432
+ /** Record this as a TRACKED format change (`w:pPr/w:rPr/w:rPrChange`, §17.13.5.31). */
3433
+ readonly revision?: RevisionAttributionInput;
3434
+ } | {
3435
+ readonly op: 'setListNumbering';
3436
+ readonly paragraphId: string;
3437
+ readonly numId: string | null;
3438
+ readonly level?: number;
3439
+ readonly revision?: RevisionAttributionInput;
3440
+ } | {
3441
+ /**
3442
+ * Replace a paragraph's custom tab stops, or clear them with an empty list.
3443
+ *
3444
+ * Its OWN op rather than a `w:tabs` entry in `setParagraphProperties`, because
3445
+ * `OoxmlProperty` is flat and `w:tabs` carries its meaning in `w:tab` children — the
3446
+ * same reason `setListNumbering` exists for `w:numPr`.
3447
+ */
3448
+ readonly op: 'setParagraphTabStops';
3449
+ readonly paragraphId: string;
3450
+ readonly stops: readonly TabStopWrite[];
3451
+ /**
3452
+ * Every stop position IN FORCE when the editor read the paragraph, including the
3453
+ * ones a style supplied.
3454
+ *
3455
+ * Tab stops are read through the cascade and written at the paragraph level, so a
3456
+ * replace alone cannot remove an inherited stop — the user clears a row, the style
3457
+ * puts it straight back, and the command reports success. A position that was in
3458
+ * force and is not in `stops` is suppressed with `w:val="clear"`, which is what the
3459
+ * value exists for (§17.3.1.37). Omit when the caller has no cascade to speak of;
3460
+ * the write is then a plain paragraph-level replace.
3461
+ */
3462
+ readonly inForcePositionsTwips?: readonly number[];
3463
+ } | {
3464
+ readonly op: 'splitParagraph';
3465
+ readonly paragraphId: string;
3466
+ readonly offset: number;
3467
+ /**
3468
+ * The `w:pStyle` the MINTED tail takes, instead of the head's own.
3469
+ *
3470
+ * A split otherwise clones the whole `w:pPr`, which is right for every property but
3471
+ * the style when the caller is an Enter at the end of a paragraph: Word gives that
3472
+ * new paragraph the style's `w:next`, so a heading is followed by body text rather
3473
+ * than by a second heading. `null` authors no `w:pStyle` at all, which is what the
3474
+ * document's default style is spelled as. Omit to clone the head's style unchanged.
3475
+ */
3476
+ readonly tailStyleId?: string | null;
3477
+ } | {
3478
+ /**
3479
+ * Split one `w:p` at MANY offsets in a single op.
3480
+ *
3481
+ * Equivalent to applying `splitParagraph` at each offset from the last to the first,
3482
+ * but the paragraph's content is cut in one pass and the parent's child sequence is
3483
+ * rebuilt once. A plain-text paste is a paragraph mark per line: as individual ops,
3484
+ * a large paste rebuilt the body — and re-sliced the pasted text — once per line,
3485
+ * which is quadratic in paste size.
3486
+ */
3487
+ readonly op: 'splitParagraphMany';
3488
+ readonly paragraphId: string;
3489
+ /**
3490
+ * Non-decreasing UTF-16 offsets; each produces one paragraph boundary. A repeated
3491
+ * offset produces an empty paragraph between the two boundaries — a blank line.
3492
+ */
3493
+ readonly offsets: readonly number[];
3494
+ /**
3495
+ * Propose the breaks rather than making them, exactly as the single split does.
3496
+ *
3497
+ * Every boundary is a paragraph mark this author is adding, so each paragraph that
3498
+ * PRECEDES one carries `w:rPr/w:ins`. Without it a multi-line paste in suggesting mode
3499
+ * tracked its text and not its breaks, and Reject left the extra paragraphs standing.
3500
+ */
3501
+ readonly revision?: RevisionAttributionInput;
3502
+ } | {
3503
+ readonly op: 'joinParagraphs';
3504
+ readonly firstId: string;
3505
+ readonly secondId: string;
3506
+ } | {
3507
+ readonly op: 'setRunProperties';
3508
+ readonly paragraphId: string;
3509
+ readonly start: number;
3510
+ readonly end: number;
3511
+ readonly properties: readonly OoxmlProperty[];
3512
+ /**
3513
+ * Record this as a TRACKED format change: each run keeps its new `w:rPr` and gains a
3514
+ * `w:rPrChange` (§17.13.5.30) holding the properties it had, so Reject restores them.
3515
+ */
3516
+ readonly revision?: RevisionAttributionInput;
3517
+ /**
3518
+ * When set, format only these runs (field result ownership). Offset range still
3519
+ * gates the edit and drives edge splits; without this, multi-run field results that
3520
+ * share one atom offset would homogenise under a single property bag.
3521
+ */
3522
+ readonly targetRunIds?: readonly string[];
3523
+ } | {
3524
+ readonly op: 'setParagraphProperties';
3525
+ readonly paragraphId: string;
3526
+ readonly properties: readonly OoxmlProperty[];
3527
+ /** Record this as a TRACKED format change (`w:pPrChange`, §17.13.5.29). */
3528
+ readonly revision?: RevisionAttributionInput;
3529
+ } | {
3530
+ /**
3531
+ * Set page-setup fields — page size, orientation, margins — on every targeted
3532
+ * `w:sectPr`: all of them (Word's "Apply to: Whole document", the default) or
3533
+ * only the one governing `anchorParagraphId`. A document whose write must reach
3534
+ * the implicit tail section gets a body-level `w:sectPr` minted as the body's
3535
+ * last child. Omitted fields are left exactly as authored per section. Explicit
3536
+ * dimensions are written literally; `orientation` WITHOUT dimensions swaps each
3537
+ * section's own (see `plannedSectionDimensions`), so distinct paper sizes
3538
+ * survive a whole-document flip.
3539
+ */
3540
+ readonly op: 'setSectionProperties';
3541
+ readonly pageWidthTwips?: number;
3542
+ readonly pageHeightTwips?: number;
3543
+ readonly orientation?: 'portrait' | 'landscape';
3544
+ readonly marginTopTwips?: number;
3545
+ readonly marginRightTwips?: number;
3546
+ readonly marginBottomTwips?: number;
3547
+ readonly marginLeftTwips?: number;
3548
+ /**
3549
+ * Word's "Apply to: This section": update only the section GOVERNING this
3550
+ * paragraph — the nearest mid-body `w:sectPr` at or after it, else the body-level
3551
+ * one. Absent means every section.
3552
+ */
3553
+ readonly anchorParagraphId?: string;
3554
+ } | {
3555
+ /**
3556
+ * End a section AT this paragraph: mint a `w:pPr/w:sectPr` cloning the governing
3557
+ * section's effective page setup, so the blocks up to and including this paragraph
3558
+ * become their own section. The paragraph must not already carry one.
3559
+ */
3560
+ readonly op: 'setSectionMark';
3561
+ readonly paragraphId: string;
3562
+ /**
3563
+ * Where the section that STARTS after this mark begins — Word's Breaks menu.
3564
+ *
3565
+ * `w:type` states how a section starts relative to the previous one (§17.6.22), so it
3566
+ * is written on the section FOLLOWING the mark, never on the minted one, which keeps
3567
+ * the cloned type because it starts where the section it was cut from did. `'nextPage'`
3568
+ * clears `w:type` (absent IS nextPage), so a next-page break inside a continuous
3569
+ * section really starts a page. Omitted leaves the following section untouched.
3570
+ */
3571
+ readonly breakType?: 'nextPage' | 'continuous';
3572
+ } | {
3573
+ /**
3574
+ * Wrap `[start, end)` of a paragraph in a `w:hyperlink`.
3575
+ *
3576
+ * The RANGE is the link — text and formatting inside it are untouched, and runs that
3577
+ * straddle either edge are divided so the link covers exactly the characters asked
3578
+ * for. Exactly one of `relationshipId` (an external target, already minted on the
3579
+ * package) or `anchor` (a bookmark in this document) names where it goes.
3580
+ *
3581
+ * A collapsed range is refused: a link with no text is markup with nothing to click,
3582
+ * and the caller that wants "insert a link with display text" inserts the text first.
3583
+ */
3584
+ readonly op: 'insertHyperlink';
3585
+ readonly paragraphId: string;
3586
+ readonly start: number;
3587
+ readonly end: number;
3588
+ readonly relationshipId?: string;
3589
+ readonly anchor?: string;
3590
+ readonly tooltip?: string;
3591
+ /**
3592
+ * Character style to mark the linked runs with (`w:rStyle`), normally `Hyperlink`.
3593
+ *
3594
+ * Written HERE rather than through `setRunProperties` because `w:rStyle` is preserved,
3595
+ * not accepted: it is not in the set a property write replaces, and putting it there
3596
+ * would make a later bold toggle delete it. Marking the text is part of making it a
3597
+ * link — Word does both in one operation — so the op that wraps it also styles it.
3598
+ * Omitted for a document that declares no such style.
3599
+ */
3600
+ readonly styleId?: string;
3601
+ } | {
3602
+ /**
3603
+ * Re-aim an existing link. `relationshipId` moves it to another external target,
3604
+ * `anchor` to a bookmark; supplying one CLEARS the other, so a link never ends up
3605
+ * carrying both and resolving by the wrong one.
3606
+ */
3607
+ readonly op: 'setHyperlinkTarget';
3608
+ readonly linkId: string;
3609
+ /** Optional exact paragraph offsets for an ordinary text subrange of this link. */
3610
+ readonly range?: {
3611
+ readonly start: number;
3612
+ readonly end: number;
3613
+ };
3614
+ readonly relationshipId?: string;
3615
+ readonly anchor?: string;
3616
+ readonly tooltip?: string;
3617
+ } | {
3618
+ /**
3619
+ * Unlink: splice the `w:hyperlink`'s children into the paragraph in its place.
3620
+ *
3621
+ * The runs keep their identity, their formatting and their order, and any bookmark
3622
+ * markers inside the link stay exactly where they were. Only the link element goes,
3623
+ * which is what Word's Remove Hyperlink does — the text is not the link's, it was
3624
+ * only wrapped by it.
3625
+ */
3626
+ readonly op: 'removeHyperlink';
3627
+ readonly linkId: string;
3628
+ /** Optional exact paragraph offsets for an ordinary text subrange of this link. */
3629
+ readonly range?: {
3630
+ readonly start: number;
3631
+ readonly end: number;
3632
+ };
3633
+ } | {
3634
+ /**
3635
+ * Replace one preserved `m:oMath` atom from bounded linear-math input.
3636
+ *
3637
+ * The complete equation changes as one unit. Internal OMML text never enters the
3638
+ * paragraph offset space, so callers cannot leave a partially edited math tree.
3639
+ */
3640
+ readonly op: 'setMathEquation';
3641
+ readonly equationId: string;
3642
+ readonly linear: string;
3643
+ } | {
3644
+ /** Remove one complete `m:oMath` atom. */
3645
+ readonly op: 'removeMathEquation';
3646
+ readonly equationId: string;
3647
+ } | {
3648
+ /**
3649
+ * Insert a NEW run-level content control at a text offset: `w:sdt` with a
3650
+ * `w:sdtPr` carrying the given tag (and alias/lock) and a `w:sdtContent`
3651
+ * holding one run of `text`.
3652
+ *
3653
+ * The write half of the custom-node contract (pro-review-and-custom-nodes):
3654
+ * a node's identity lives in `w:tag`, `sdtLocked` keeps Word users from
3655
+ * unwrapping the anchor, and the literal run text is what Word (and the
3656
+ * free tier) render. The TAG IS ATTACKER-ADJACENT ON READ but authored
3657
+ * here; it is written as an ordinary attribute value, so the serializer's
3658
+ * escaping covers it like every other attribute.
3659
+ */
3660
+ readonly op: 'insertInlineContentControl';
3661
+ readonly paragraphId: string;
3662
+ readonly offset: number;
3663
+ readonly tag: string;
3664
+ readonly text: string;
3665
+ readonly alias?: string;
3666
+ /** `w:lock` value; omitted writes no lock. */
3667
+ readonly lock?: 'sdtLocked' | 'sdtContentLocked' | 'contentLocked';
3668
+ /**
3669
+ * `w:dataBinding` — the customXml data part node this control mirrors.
3670
+ *
3671
+ * The payload half of the custom-node contract: `w:tag` caps at 64
3672
+ * characters, so anything larger lives in a data part and the control
3673
+ * points at it. All three attributes travel together because Word needs
3674
+ * all three — the store's `ds:itemID`, the XPath to the node's label, and
3675
+ * the prefix declaration that XPath's steps resolve through.
3676
+ *
3677
+ * A control that carries one is READ-ONLY in Word (verified against
3678
+ * `sdt-custom-node-databinding-word-roundtrip.docx`), and this engine
3679
+ * refuses content edits inside it for the same reason — see
3680
+ * `bindingRefusal`. That is what keeps the store and the page from
3681
+ * drifting: there is no edit that could move one without the other.
3682
+ *
3683
+ * Nothing here is resolved or fetched. The op writes the three strings and
3684
+ * the store lane owns the part they name.
3685
+ */
3686
+ readonly dataBinding?: {
3687
+ readonly prefixMappings: string;
3688
+ readonly xpath: string;
3689
+ readonly storeItemId: string;
3690
+ };
3691
+ } | {
3692
+ /** Repeating-section item insert — unsupported at this layer (out of scope). */
3693
+ readonly op: 'addRepeatingSectionItem';
3694
+ readonly controlId: string;
3695
+ readonly index?: number;
3696
+ } | {
3697
+ /** Repeating-section item remove — unsupported at this layer (out of scope). */
3698
+ readonly op: 'removeRepeatingSectionItem';
3699
+ readonly controlId: string;
3700
+ readonly index: number;
3701
+ } | {
3702
+ /**
3703
+ * Remove a typed block and everything under it.
3704
+ *
3705
+ * Validation restricts this structural operation to `w:p`, `w:tbl`, and `w:tr`, and
3706
+ * refuses removals that would violate required-container or section-mark invariants.
3707
+ */
3708
+ readonly op: 'deleteBlock';
3709
+ readonly blockId: string;
3710
+ } | {
3711
+ /**
3712
+ * Insert a fresh empty table immediately before a block-level paragraph.
3713
+ *
3714
+ * Before, never after, so the anchor paragraph stays as the block that follows the
3715
+ * table: a `w:tbl` is not a valid final child of a story container, and two tables
3716
+ * that end up adjacent merge into one when the file is reopened. When the anchor's
3717
+ * previous sibling is already a table, a separating empty paragraph is authored with
3718
+ * it, which is what Word does for the same reason.
3719
+ */
3720
+ readonly op: 'insertTable';
3721
+ readonly beforeParagraphId: string;
3722
+ readonly rows: number;
3723
+ readonly cols: number;
3724
+ /** Width of every grid column, in twips. The caller divides the content width. */
3725
+ readonly columnWidthTwips: number;
3726
+ /** Propose the complete table through native row and cell insertion revisions. */
3727
+ readonly revision?: RevisionAttributionInput;
3728
+ } | {
3729
+ /** Insert a fresh row above or below a canonical table row. */
3730
+ readonly op: 'insertTableRow';
3731
+ readonly tableId: string;
3732
+ readonly rowId: string;
3733
+ readonly where: 'above' | 'below';
3734
+ /** When present, author the row as a Word tracked insertion. */
3735
+ readonly revision?: RevisionAttributionInput;
3736
+ } | {
3737
+ /** Delete one canonical table row; refuses the final row. */
3738
+ readonly op: 'deleteTableRow';
3739
+ readonly tableId: string;
3740
+ readonly rowId: string;
3741
+ /** Optional anchor cell for column-aware caret recovery after deletion. */
3742
+ readonly referenceCellId?: string;
3743
+ /** When present, retain the row and author a Word tracked deletion. */
3744
+ readonly revision?: RevisionAttributionInput;
3745
+ } | {
3746
+ /** Insert one grid column left or right of a canonical `w:gridCol`. */
3747
+ readonly op: 'insertTableColumn';
3748
+ readonly tableId: string;
3749
+ readonly where: 'left' | 'right';
3750
+ readonly gridColumnId: string;
3751
+ } | {
3752
+ /**
3753
+ * Insert one grid column beside a first-row reference cell when `w:tblGrid` is absent.
3754
+ * Synthesizes a canonical grid before mutation.
3755
+ */
3756
+ readonly op: 'insertTableColumn';
3757
+ readonly tableId: string;
3758
+ readonly where: 'left' | 'right';
3759
+ readonly referenceCellId: string;
3760
+ } | {
3761
+ /** Delete one canonical grid column; refuses the final column. */
3762
+ readonly op: 'deleteTableColumn';
3763
+ readonly tableId: string;
3764
+ readonly gridColumnId: string;
3765
+ } | {
3766
+ /**
3767
+ * Resize one internal divider between two adjacent canonical grid columns.
3768
+ * Preserves the pair total and sets fixed table layout.
3769
+ */
3770
+ readonly op: 'setTableColumnWidths';
3771
+ readonly tableId: string;
3772
+ readonly leftGridColumnId: string;
3773
+ readonly rightGridColumnId: string;
3774
+ readonly leftWidthTwips: number;
3775
+ readonly rightWidthTwips: number;
3776
+ } | {
3777
+ /**
3778
+ * Resize the outer-right edge: last grid column, matching cells, and `w:tblW` total.
3779
+ */
3780
+ readonly op: 'setTableRightEdgeWidth';
3781
+ readonly tableId: string;
3782
+ readonly gridColumnId: string;
3783
+ readonly columnWidthTwips: number;
3784
+ readonly tableWidthTwips: number;
3785
+ } | {
3786
+ /** Atomic semantic table authoring. Newly created nodes never need caller-supplied IDs. */
3787
+ readonly op: 'authorTable';
3788
+ /** Native row revisions. Other structural mutations refuse this option. */
3789
+ readonly revision?: RevisionAttributionInput;
3790
+ readonly action: {
3791
+ readonly kind: 'existing';
3792
+ readonly tableId: string;
3793
+ readonly mutation: AutomationTableMutation;
3794
+ } | {
3795
+ readonly kind: 'insert';
3796
+ readonly paragraphId: string;
3797
+ readonly offset: number;
3798
+ readonly rowCount: number;
3799
+ readonly columnCount: number;
3800
+ readonly values?: readonly (readonly string[])[];
3801
+ };
3802
+ } | {
3803
+ /** Lossless direct table properties; widths are one value per rectangular grid column. */
3804
+ readonly op: 'setTableProperties';
3805
+ readonly tableId: string;
3806
+ readonly styleId?: string;
3807
+ readonly headerRowCount?: number;
3808
+ readonly columnWidthsTwips?: readonly number[];
3809
+ } | {
3810
+ /** Set one authored table row to an exact height in twips. */
3811
+ readonly op: 'setTableRowHeight';
3812
+ readonly tableId: string;
3813
+ readonly rowId: string;
3814
+ readonly heightTwips: number;
3815
+ } | {
3816
+ /** Clear the active edge target on a bounded rectangular cell selection. */
3817
+ readonly op: 'setTableCellBorders';
3818
+ readonly tableId: string;
3819
+ readonly cellIds: readonly string[];
3820
+ readonly scope: 'none';
3821
+ readonly target: TableBorderEdgeTarget;
3822
+ } | {
3823
+ /** Apply a complete border spec to the requested edge target. */
3824
+ readonly op: 'setTableCellBorders';
3825
+ readonly tableId: string;
3826
+ readonly cellIds: readonly string[];
3827
+ readonly scope: TableBorderEdgeTarget;
3828
+ readonly spec: TableBorderSpecInput;
3829
+ } | {
3830
+ /** Write or remove direct selected-cell shading (`w:tcPr/w:shd`). */
3831
+ readonly op: 'setTableCellFill';
3832
+ readonly tableId: string;
3833
+ readonly cellIds: readonly string[];
3834
+ readonly color: TreeDocColorValue | null;
3835
+ } | {
3836
+ /** Set direct selected-cell vertical alignment (`w:tcPr/w:vAlign`). */
3837
+ readonly op: 'setTableCellVerticalAlignment';
3838
+ readonly tableId: string;
3839
+ readonly cellIds: readonly string[];
3840
+ readonly alignment: 'top' | 'center' | 'bottom';
3841
+ } | {
3842
+ /** Allocate an empty header/footer part and declare it on a section. Package-level. */
3843
+ readonly op: 'createHeaderFooter';
3844
+ readonly sectionIndex: number;
3845
+ readonly kind: 'header' | 'footer';
3846
+ readonly variant: 'default' | 'first' | 'even';
3847
+ /** When true, also set section `w:titlePg` in the same package transaction. */
3848
+ readonly titlePage?: boolean;
3849
+ /** When true, also set document `w:evenAndOddHeaders` in the same package transaction. */
3850
+ readonly evenAndOddHeaders?: boolean;
3851
+ } | {
3852
+ /** Remove a section's declared header/footer reference; GC when orphaned. Package-level. */
3853
+ readonly op: 'deleteHeaderFooter';
3854
+ readonly sectionIndex: number;
3855
+ readonly kind: 'header' | 'footer';
3856
+ readonly variant: 'default' | 'first' | 'even';
3857
+ } | {
3858
+ /** Drop a declared ref so the section inherits from the previous. Package-level. */
3859
+ readonly op: 'linkToPrevious';
3860
+ readonly sectionIndex: number;
3861
+ readonly kind: 'header' | 'footer';
3862
+ readonly variant: 'default' | 'first' | 'even';
3863
+ } | {
3864
+ /** Clone an inherited part into a new declared reference. Package-level. */
3865
+ readonly op: 'unlinkFromPrevious';
3866
+ readonly sectionIndex: number;
3867
+ readonly kind: 'header' | 'footer';
3868
+ readonly variant: 'default' | 'first' | 'even';
3869
+ } | {
3870
+ /**
3871
+ * Section/document furniture options: `titlePg`, header/footer distances on the
3872
+ * section; `evenAndOddHeaders` document-wide in settings. Package-level.
3873
+ */
3874
+ readonly op: 'setSectionFurnitureOptions';
3875
+ readonly sectionIndex?: number;
3876
+ readonly titlePage?: boolean;
3877
+ readonly evenAndOddHeaders?: boolean;
3878
+ readonly headerDistanceTwips?: number;
3879
+ readonly footerDistanceTwips?: number;
3880
+ } | {
3881
+ /**
3882
+ * Word's Protect Document: enforce or lift `w:documentProtection` in `settings.xml`.
3883
+ * Enforcing writes `w:edit="forms"` (filling in forms, the one restriction the store
3884
+ * applies); lifting keeps the recorded mode and clears `w:enforcement`, as Word's Stop
3885
+ * Protection does. A password-protected file refuses to lift. Package-level.
3886
+ */
3887
+ readonly op: 'setDocumentProtection';
3888
+ readonly enforce: boolean;
3889
+ } | {
3890
+ /**
3891
+ * Insert a footnote or endnote: body reference + notes-part body (+ create the
3892
+ * notes part/rel/content-type when missing). Package-level; one ModelChange.
3893
+ */
3894
+ readonly op: 'insertNote';
3895
+ readonly noteKind: 'footnote' | 'endnote';
3896
+ readonly paragraphId: string;
3897
+ readonly offset: number;
3898
+ /**
3899
+ * Write the citing REFERENCE as a tracked insertion (`w:ins` around the reference
3900
+ * run), on the same terms as `insertText`. The note body itself is not revision
3901
+ * markup: rejecting the reference removes it, and the body cascade sweeps the
3902
+ * orphaned note exactly as an untracked reference deletion does.
3903
+ */
3904
+ readonly revision?: RevisionAttributionInput;
3905
+ } | {
3906
+ /**
3907
+ * Delete a note body and every matching reference (body, HF, other notes).
3908
+ * Package-level; one ModelChange.
3909
+ */
3910
+ readonly op: 'deleteNote';
3911
+ readonly noteKind: 'footnote' | 'endnote';
3912
+ readonly noteId: number;
3913
+ } | {
3914
+ /** Convert a footnote ↔ endnote, reallocating id in the target part. Package-level. */
3915
+ readonly op: 'convertNote';
3916
+ readonly fromKind: 'footnote' | 'endnote';
3917
+ readonly noteId: number;
3918
+ } | {
3919
+ /**
3920
+ * Convert every normal footnote↔endnote of `fromKind` in one package transaction.
3921
+ * One ModelChange / undo unit; bounded by notes-part size.
3922
+ */
3923
+ readonly op: 'convertAllNotes';
3924
+ readonly fromKind: 'footnote' | 'endnote';
3925
+ } | {
3926
+ /**
3927
+ * Write a content control's VALUE, in the vocabulary its own type accepts.
3928
+ *
3929
+ * One transaction for the whole transition: the content, `w:showingPlcHdr`, and the
3930
+ * type's own record of the value (`@w:lastValue`, `@w:fullDate`, `w14:checked`) move
3931
+ * together, because a control whose glyph says checked and whose flag says unchecked is
3932
+ * a document Word and this engine read differently.
3933
+ */
3934
+ readonly op: 'setContentControlValue';
3935
+ readonly controlId: string;
3936
+ /** String is the editor-facing v2 form; structured input is the automation form. */
3937
+ readonly value: string | ContentControlValueInput;
3938
+ } | {
3939
+ /**
3940
+ * Author the metadata a control carries: its tag, its title, its lock.
3941
+ *
3942
+ * `null` removes the property. Everything else in `CT_SdtPr` — the type payload, a data
3943
+ * binding, an extension this vocabulary does not model — survives in schema order.
3944
+ */
3945
+ readonly op: 'setContentControlProperties';
3946
+ readonly controlId: string;
3947
+ readonly tag?: string | null;
3948
+ readonly alias?: string | null;
3949
+ readonly lock?: ContentControlLock;
3950
+ } | {
3951
+ /**
3952
+ * Remove a control. `keepContent` splices its content into its place — Word's own
3953
+ * "Remove content control" — and false takes the content with it.
3954
+ */
3955
+ readonly op: 'removeContentControl';
3956
+ readonly controlId: string;
3957
+ /** Defaults to true for the editor-facing v2 operation. */
3958
+ readonly keepContent?: boolean;
3959
+ } | {
3960
+ /**
3961
+ * Wrap `[start, end)` of a paragraph in a new control of the named type.
3962
+ *
3963
+ * A control is a SIBLING of runs, never a thing inside one, so a range ending mid-run
3964
+ * splits that run at both edges first. The characters and their formatting are the ones
3965
+ * that were there; only the run boundaries move.
3966
+ */
3967
+ readonly op: 'insertContentControl';
3968
+ /** Record a wrapper over existing text as a native replacement revision. */
3969
+ readonly revision?: RevisionAttributionInput;
3970
+ readonly paragraphId: string;
3971
+ readonly start: number;
3972
+ readonly end: number;
3973
+ readonly type: InsertableContentControlKind;
3974
+ readonly tag?: string;
3975
+ readonly alias?: string;
3976
+ readonly lock?: ContentControlLock;
3977
+ } | {
3978
+ /**
3979
+ * Author `w:footnotePr` / `w:endnotePr` at document (settings) or section scope.
3980
+ * Refuse endnote `pageBottom`. Package-level; does not invent props on unedited saves.
3981
+ */
3982
+ readonly op: 'setNoteProperties';
3983
+ readonly scope: 'document' | 'section';
3984
+ readonly sectionIndex?: number;
3985
+ readonly footnote?: {
3986
+ readonly numFmt?: string;
3987
+ readonly numRestart?: string;
3988
+ readonly position?: string;
3989
+ readonly numStart?: number;
3990
+ };
3991
+ readonly endnote?: {
3992
+ readonly numFmt?: string;
3993
+ readonly numRestart?: string;
3994
+ readonly position?: string;
3995
+ readonly numStart?: number;
3996
+ };
3997
+ } | {
3998
+ /**
3999
+ * Insert clipboard-fragment blocks at a paragraph position, atomically.
4000
+ *
4001
+ * Blocks only — resources (styles, numbering, media, rels, note parts) merge through
4002
+ * the package-edit path in the same transaction, and the whole commit is promoted to
4003
+ * a package undo unit. A merged edge paragraph takes the properties of the paragraph
4004
+ * mark that ends it: the fragment's first mark leading, the host's original mark
4005
+ * trailing. Nodes receive fresh ids at apply.
4006
+ */
4007
+ readonly op: 'insertFragment';
4008
+ readonly paragraphId: string;
4009
+ readonly offset: number;
4010
+ readonly blocks: readonly OoxmlNode[];
4011
+ /** True when the fragment's last paragraph mark travelled (its paragraph stays whole). */
4012
+ readonly lastMarkCovered?: boolean;
4013
+ } | {
4014
+ readonly op: 'insertDrawing';
4015
+ readonly paragraphId: string;
4016
+ readonly offset: number;
4017
+ readonly drawing: OoxmlDrawingNode;
4018
+ /** Present in suggesting mode: the drawing's run goes into a `w:ins` as one proposal. */
4019
+ readonly revision?: RevisionAttributionInput;
4020
+ } | {
4021
+ readonly op: 'replaceDrawingResource';
4022
+ readonly drawingNodeId: string;
4023
+ readonly relationshipId: string;
4024
+ } | {
4025
+ readonly op: 'deleteDrawing';
4026
+ readonly drawingNodeId: string;
4027
+ /** Suggesting-mode tracked deletion is refused; owned by typed-revisions-and-comments. */
4028
+ readonly revision?: RevisionAttributionInput;
4029
+ } | {
4030
+ readonly op: 'resizeDrawing';
4031
+ readonly drawingNodeId: string;
4032
+ readonly extentEmu: {
4033
+ readonly cx: number;
4034
+ readonly cy: number;
4035
+ };
4036
+ } | {
4037
+ readonly op: 'cropDrawing';
4038
+ readonly drawingNodeId: string;
4039
+ readonly crop: SourceCrop;
4040
+ } | {
4041
+ readonly op: 'positionDrawing';
4042
+ readonly drawingNodeId: string;
4043
+ readonly position: DrawingPositionInput;
4044
+ } | {
4045
+ readonly op: 'setDrawingWrap';
4046
+ readonly drawingNodeId: string;
4047
+ readonly wrap: ImageWrapTarget;
4048
+ } | {
4049
+ readonly op: 'setDrawingMetadata';
4050
+ readonly drawingNodeId: string;
4051
+ readonly title: string;
4052
+ readonly description: string;
4053
+ /** Omitted preserves existing `a:hlinkClick`; null removes it; a URL needs a package transaction. */
4054
+ readonly hyperlink?: string | null;
4055
+ } | {
4056
+ readonly op: 'setDrawingLocks';
4057
+ readonly drawingNodeId: string;
4058
+ readonly locks: DrawingLocksInput;
4059
+ } | {
4060
+ readonly op: 'transformDrawing';
4061
+ readonly drawingNodeId: string;
4062
+ readonly action: 'rotateCW' | 'rotateCCW' | 'flipH' | 'flipV';
4063
+ } | {
4064
+ /**
4065
+ * Replace a detected TOC field's cached result paragraphs and ensure heading bookmarks.
4066
+ * Preserves field chrome / instruction. One undo unit (phase A of TOC refresh).
4067
+ */
4068
+ readonly op: 'replaceTocResult';
4069
+ readonly tocId: string;
4070
+ readonly entries: readonly {
4071
+ readonly level: number;
4072
+ readonly text: string;
4073
+ readonly headingParagraphId: string;
4074
+ readonly bookmarkName: string;
4075
+ readonly pageNumberText: string;
4076
+ }[];
4077
+ readonly bookmarksToCreate: readonly {
4078
+ readonly paragraphId: string;
4079
+ readonly name: string;
4080
+ }[];
4081
+ } | {
4082
+ /**
4083
+ * Rewrite page-number text runs inside existing TOC result paragraphs.
4084
+ * One undo unit (phase B of TOC refresh).
4085
+ */
4086
+ readonly op: 'rewriteTocPageNumbers';
4087
+ readonly tocId: string;
4088
+ readonly updates: readonly {
4089
+ readonly paragraphId: string;
4090
+ readonly pageNumberText: string;
4091
+ }[];
4092
+ } | SetTextFormFieldDefaultOp | CommitTextFormFieldOp | SetLegacyCheckboxOp | SetLegacyDropdownOp | InsertBuildingBlockOp | {
4093
+ /**
4094
+ * Rewrite recognized fields' cached RESULT runs in place — between the `separate` and
4095
+ * `end` fldChars, or a `w:fldSimple`'s content. The instruction is never modified; a
4096
+ * result holding anything but plain runs is skipped (see `tree-op-field-results.ts`).
4097
+ */
4098
+ readonly op: 'refreshFieldResults';
4099
+ readonly updates: readonly {
4100
+ readonly paragraphId: string;
4101
+ /** Node id of the field's begin `w:fldChar`, or of the `w:fldSimple` element. */
4102
+ readonly fieldNodeId: string;
4103
+ readonly text: string;
4104
+ }[];
4105
+ };
4106
+ /** Drawing mutation ops from typed-drawings-and-images task 11. */
4107
+ type DrawingTreeDocOp = Extract<TreeDocOp, {
4108
+ readonly op: 'insertDrawing' | 'replaceDrawingResource' | 'deleteDrawing' | 'resizeDrawing' | 'cropDrawing' | 'positionDrawing' | 'setDrawingWrap' | 'setDrawingMetadata' | 'setDrawingLocks' | 'transformDrawing';
4109
+ }>;
4110
+ /** Just the `op` discriminants, for dispatch tables and validation. */
4111
+ type TreeDocOpKind = TreeDocOp['op'];
4112
+
4113
+ /**
4114
+ * How far a committed op can reach, so layout can scope its work (task 5.2).
4115
+ *
4116
+ * `text-local` touches one paragraph's characters; `paragraph-local` changes one
4117
+ * paragraph's own properties; `flow-structural` changes the block sequence and can
4118
+ * repaginate everything after it; `global` invalidates every page that shares the
4119
+ * edited story (header/footer parts attached to many sections/pages).
4120
+ */
4121
+ /**
4122
+ * How far an op's effects reach — what layout must re-do after it.
4123
+ *
4124
+ * The knob incremental layout turns: a `text-local` edit re-breaks one paragraph, while a
4125
+ * `global` one invalidates the document.
4126
+ */
4127
+ type ImpactClass = 'text-local' | 'paragraph-local' | 'flow-structural' | 'global';
4128
+ /**
4129
+ * What one applied op changed: the ids dirtied, created and deleted.
4130
+ *
4131
+ * These ids are what let layout and paint re-do only what moved instead of the whole document.
4132
+ */
4133
+ interface TreeOpEffect {
4134
+ readonly dirty: readonly string[];
4135
+ readonly created: readonly string[];
4136
+ readonly deleted: readonly string[];
4137
+ readonly split?: {
4138
+ readonly from: string;
4139
+ readonly tail: string;
4140
+ };
4141
+ /** One entry per boundary of a many-way split, in document order. */
4142
+ readonly splits?: readonly {
4143
+ readonly from: string;
4144
+ readonly tail: string;
4145
+ }[];
4146
+ readonly join?: {
4147
+ readonly kept: string;
4148
+ readonly removed: string;
4149
+ };
4150
+ readonly dependencyKeys: readonly string[];
4151
+ readonly impact: ImpactClass;
4152
+ /** First post-edit caret paragraph for table column structural ops. */
4153
+ readonly caret?: {
4154
+ readonly paragraphId: string;
4155
+ };
4156
+ }
4157
+ /**
4158
+ * Why an op was refused.
4159
+ *
4160
+ * `not-adjacent-siblings` is the notable one: a join across table cells is refused rather than
4161
+ * silently merging content out of the cell that owned it.
4162
+ */
4163
+ 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'
4164
+ /**
4165
+ * The addressed position is strictly inside content nothing can divide: a hyperlink, an
4166
+ * inline content control, a revision wrapper, or an atomic field.
4167
+ *
4168
+ * Distinct from `invalid-range`, which is an offset the paragraph does not have. This one is
4169
+ * a real offset that is not a PLACE — refused rather than resolved to the nearest one, so a
4170
+ * caller learns the node would not have landed where they asked.
4171
+ */
4172
+ | 'indivisible-content'
4173
+ /**
4174
+ * The range has one end inside a field's editable saved result and the other outside it.
4175
+ * Deleting it would leave the field's begin, separate, and end markers unbalanced, so it is
4176
+ * refused. A range that covers the whole field removes the field.
4177
+ */
4178
+ | 'field-structure'
4179
+ /**
4180
+ * In the editable field-result mode, an op other than typing, deletion, or run formatting
4181
+ * addresses a position inside a field's saved result. Splits, tabs, links, notes, and
4182
+ * fragments there are not supported yet.
4183
+ */
4184
+ | 'field-result-unsupported' | 'unknown-block' | 'not-a-block' | 'block-required' | 'carries-section-mark'
4185
+ /** The transaction named a part the package does not hold. */
4186
+ | 'unknown-part'
4187
+ /**
4188
+ * The transaction would have published a package that does not open: a relationship
4189
+ * pointing at a part nobody created, or a part with no declared content type.
4190
+ */
4191
+ | 'package-invariant'
4192
+ /** No revision in this part carries the addressed `(id, author, date)` triple. */
4193
+ | 'unknown-revision'
4194
+ /**
4195
+ * A matched revision is a kind whose accept/reject semantics are structural and not
4196
+ * implemented. Refusing is deliberate: removing the markup alone would report the decision
4197
+ * applied while leaving the row, cell, or section it describes untouched.
4198
+ */
4199
+ | 'unsupported-revision' | 'tree-invariant'
4200
+ /** No content control in this part carries the addressed node id. */
4201
+ | 'unknown-content-control'
4202
+ /** The addressed node exists and is not a `w:sdt`. */
4203
+ | 'not-a-content-control'
4204
+ /**
4205
+ * A content control's `w:lock` — or one an enclosing control imposes — forbids this.
4206
+ *
4207
+ * The same code for an edit inside `contentLocked` content and for the removal of an
4208
+ * `sdtLocked` control: both are "the document says no", and the two halves are already
4209
+ * distinguished by which operation was refused.
4210
+ */
4211
+ | 'locked'
4212
+ /** The control declares `w:dataBinding`; its value belongs to a custom XML part. */
4213
+ | 'bound'
4214
+ /** The value offered is not one this control's type accepts. */
4215
+ | 'typeMismatch' | 'unknown-control' | 'unsupported'
4216
+ /** Malformed lifecycle args / first-section link — mirrors Editor `invalidArgs`. */
4217
+ | 'invalidArgs'
4218
+ /** The addressed table id is missing, duplicated, or not a typed table. */
4219
+ | 'unknown-table'
4220
+ /** The addressed row id is missing or not a direct child of the table. */
4221
+ | 'unknown-row'
4222
+ /** A table property container appears more than once on a typed node. */
4223
+ | 'duplicate-property-container'
4224
+ /**
4225
+ * A row holds a `w:tc` inside a cell-level wrapper such as `w:sdt`, so the row's grid
4226
+ * mapping cannot be trusted and the inserted row would not match it.
4227
+ */
4228
+ | 'row-hides-cell'
4229
+ /** Column edit refused because the table carries horizontal or vertical merges. */
4230
+ | 'table-has-merge'
4231
+ /** The addressed grid column id is missing or ambiguous without `w:tblGrid`. */
4232
+ | 'unknown-grid-column'
4233
+ /** The operation would exceed bounded table topology limits. */
4234
+ | 'resource-limit'
4235
+ /** The addressed node is not a top-level `w:drawing`. */
4236
+ | 'not-a-drawing'
4237
+ /** No `w:drawing` with this id exists in the part. */
4238
+ | 'unknown-drawing'
4239
+ /** The drawing's graphic payload is not a supported picture. */
4240
+ | 'not-a-picture-drawing'
4241
+ /** A lock flag or `@locked` forbids this mutation. */
4242
+ | 'drawing-locked'
4243
+ /** Finite EMU extent, crop, or position value is out of range. */
4244
+ | 'invalid-drawing-value'
4245
+ /** Insertion would cross a table-cell boundary or wrong story container. */
4246
+ | 'cross-cell-drawing'
4247
+ /** Suggesting-mode drawing deletion is not implemented in this change. */
4248
+ | 'trackedDrawingDeletionUnsupported'
4249
+ /** Hyperlink target creation or change needs an OPC relationship in a package transaction. */
4250
+ | 'packageTransactionRequired'
4251
+ /** A clipboard fragment block nests deeper than the recursion cap. */
4252
+ | 'fragment-too-deep'
4253
+ /** A clipboard fragment block is not a paragraph, table, or content control subtree. */
4254
+ | 'fragment-invalid-block'
4255
+ /** A clipboard fragment exceeds its block or node budget. */
4256
+ | 'fragment-resource-budget';
4257
+ /** Whether an op applied, with the effect it produced or the reason it was refused. */
4258
+ type TreeOpResult = {
4259
+ readonly ok: true;
4260
+ readonly part: OoxmlPart;
4261
+ readonly effect: TreeOpEffect;
4262
+ } | {
4263
+ readonly ok: false;
4264
+ readonly reason: TreeOpRejection;
4265
+ readonly detail?: string;
4266
+ };
4267
+
4268
+ export { CONTENT_CONTROL_ID_MAX as a$, IMAGE_WRAP_TARGETS as aH, TEXT_FORM_FORMATS as aI, ACCEPTED_PARAGRAPH_PROPERTIES as aZ, ACCEPTED_RUN_PROPERTIES as a_, CONTENT_CONTROL_PROPERTY_ORDER as b0, DEFAULT_OOXML_PACKAGE_LIMITS as bh, DEFAULT_ZIP_LIMITS as bi, HYPERLINK_RELATIONSHIP_TYPE as bl, IMAGE_RELATIONSHIP_TYPE as bo, MAX_CONTENT_CONTROLS_PER_PART as bu, MAX_CONTENT_CONTROL_NESTING as bv, OFFICE_RELATIONSHIP_NAMESPACE_URI as by, OOXML_NODE_IDENTITY_RULES as bz, hyperlinkTargetOf as c$, allocateContentControlId as cD, asciiFold as cE, buildContentTypeIndex as cF, buildRelationshipSet as cG, childElements as cH, commentAnchorsOfStory as cI, commentsOfPart as cJ, contentControlContentChildren as cK, contentControlContentNodeOf as cL, contentControlEndPropertiesNodeOf as cM, contentControlLevelOf as cN, contentControlPropertiesNodeOf as cO, contentControlPropertiesOf as cP, contentControlTextOf as cQ, contentControlsIn as cR, detectDuplicateNames as cS, extensionKey as cT, findContentControl as cU, findElement as cV, firstReviewRange as cW, flattenContentControls as cX, hasAnyComment as cY, hyperlinkAnchorOf as cZ, hyperlinkRelationshipIdOf as c_, TABLE_BORDER_STYLES as ck, W15_NAMESPACE_URI as cs, WML_NAMESPACE_URI as ct, XMLNS_NAMESPACE_URI as cu, XML_NAMESPACE_URI as cv, isContentControlContentNode as d0, isContentControlNode as d1, isContentControlWrapper as d2, isContentRevisionKind as d3, isHyperlinkNode as d4, isRangeMarkerKind as d5, isValidMime as d6, legacyCheckboxFieldsOf as d7, lockForbidsEdit as d8, lockForbidsRemoval as d9, writeZip as dA, activeReviewItem as dC, reviewItemPositionRank as dD, reviewItemsAt as dE, reviewThreadRootOf as dF, normalizePartName as da, orderedContentControlProperties as db, parseContentControlId as dc, partNameKey as dd, planRevisionAuthorChange as de, planRevisionBatch as df, projectDrawing as dg, readOnOffChild as dh, readOoxmlPackage as di, readOoxmlPart as dj, readXml as dk, readZip as dl, resolveContentControlLock as dm, resolveContentType as dn, resolveImageRelationship as dp, resolveInternalTarget as dq, resolveRelationship as dr, reviewItemKey as ds, reviewItemRanges as dt, textContent as du, textFormFieldsOf as dv, threadStateOfPart as dw, validateExternalTarget as dx, withPart as dy, writeOoxmlPackage as dz };
4269
+ export type { OoxmlContentControlContentNode as $, ParagraphTabStop as A, Block as B, CommentRecord as C, DocxDocument as D, ExecResult as E, RevisionType as F, Section as G, HeaderFooterSet as H, InsertableContentControlType as I, SectionProperties as J, StyleDefinition as K, Theme as L, ThemeColorScheme as M, OoxmlNode as N, OoxmlPart as O, Paragraph as P, OoxmlPackage as Q, ReviewModelInput as R, StyleDefinitions as S, Table as T, OoxmlNodeId as U, OoxmlGenericElementNode as V, TreeDocOp as W, OoxmlProperty as X, OoxmlPackageRejection as Y, OoxmlElement as Z, OoxmlContentControlNode as _, ReviewItem as a, DrawingProjection as a0, OoxmlPackageLimits as a1, RevisionAuthorEntry as a2, RevisionAuthorResult as a3, RevisionAuthorSkipReason as a4, RevisionBatchEntry as a5, RevisionBatchResult as a6, RevisionBatchSkipReason as a7, TreeOpRejection as a8, AutomationTableMutation as a9, PageMargins as aA, ParagraphDisagreements as aB, Point as aC, Run as aD, TableCell as aE, TableRow as aF, TreeDocColorValue as aG, TableBorderStyle as aJ, DrawingAccessibility as aK, DrawingImageEffects as aL, DrawingTransform as aM, VectorShapeProjection as aN, OoxmlDrawingNode as aO, OoxmlInvariantResult as aP, OoxmlInvariantIssue as aQ, OoxmlFldCharNode as aR, OoxmlFldSimpleNode as aS, OoxmlInstrTextNode as aT, TreeOpResult as aU, RelationshipRecord as aV, OoxmlHardBreakNode as aW, OoxmlAttribute as aX, CommentThreadState as aY, RevisionAttributionInput as aa, OoxmlParagraphNode as ab, OoxmlNoteNode as ac, OoxmlContinuationSeparatorNode as ad, OoxmlEndnotesNode as ae, OoxmlFootnotesNode as af, OoxmlNoteRefNode as ag, OoxmlNoteReferenceNode as ah, OoxmlSeparatorNode as ai, DrawingTreeDocOp as aj, ImpactClass as ak, SourceCrop as al, DrawingKind as am, ImageWrapTarget as an, DrawingPositionInput as ao, DrawingLocks as ap, ParagraphFormatCommand as aq, Watermark as ar, Rect as as, SelectionPin as at, Unsubscribe as au, DocxDocumentJSON as av, DrawingHorizontalReferenceFrame as aw, DrawingVerticalReferenceFrame as ax, FontDefinition as ay, NumberingRef as az, ReviewRevisionItem as b, OoxmlPackageResult as b$, CommentAnchor as b1, CommentPosition as b2, CommitTextFormFieldOp as b3, ContentControlCheckbox as b4, ContentControlCheckboxState as b5, ContentControlDataBinding as b6, ContentControlDateFormat as b7, ContentControlEntry as b8, ContentControlKind as b9, OoxmlBodyNode as bA, OoxmlBookmarkEndNode as bB, OoxmlBookmarkStartNode as bC, OoxmlContentControlCalendarNode as bD, OoxmlContentControlCheckboxNode as bE, OoxmlContentControlCheckedNode as bF, OoxmlContentControlCheckedStateNode as bG, OoxmlContentControlComboBoxNode as bH, OoxmlContentControlDataBindingNode as bI, OoxmlContentControlDateFormatNode as bJ, OoxmlContentControlDateNode as bK, OoxmlContentControlDropDownListNode as bL, OoxmlContentControlEndPropertiesNode as bM, OoxmlContentControlLidNode as bN, OoxmlContentControlListItemNode as bO, OoxmlContentControlPropertiesNode as bP, OoxmlContentControlStoreMappedDataAsNode as bQ, OoxmlContentControlTextNode as bR, OoxmlContentControlUncheckedStateNode as bS, OoxmlDocumentNode as bT, OoxmlExternalTarget as bU, OoxmlGenericExtensionAttribute as bV, OoxmlHyperlinkNode as bW, OoxmlInvariantIssueCode as bX, OoxmlKnownNodeAttribute as bY, OoxmlNamespaceBinding as bZ, OoxmlNodeIdentityRules as b_, ContentControlLevel as ba, ContentControlListItem as bb, ContentControlLock as bc, ContentControlProperties as bd, ContentTypeError as be, ContentTypeIndex as bf, ContentTypeRecords as bg, DefaultRecord as bj, DeleteTextOp as bk, HyperlinkKind as bm, HyperlinkTarget as bn, ImageRelationshipResolution as bp, IndexResult as bq, InsertBuildingBlockOp as br, InsertTextOp as bs, LegacyCheckboxFieldRange as bt, NameRejection as bw, NameResult as bx, ReviewCommentItem as c, OoxmlParagraphPropertiesNode as c0, OoxmlPartMetadata as c1, OoxmlReadRejection as c2, OoxmlReadResult as c3, OoxmlRunNode as c4, OoxmlRunPropertiesNode as c5, OoxmlTabNode as c6, OoxmlTextElementNode as c7, OoxmlTextNode as c8, OoxmlWmlValAttribute as c9, ZipLimits as cA, ZipReadResult as cB, ZipRejection as cC, OoxmlXmlSpaceAttribute as ca, OverrideRecord as cb, RelationshipError as cc, RelationshipSetResult as cd, RelationshipTargetResolver as ce, ResolveResult as cf, ResolvedRelationship as cg, SetLegacyCheckboxOp as ch, SetLegacyDropdownOp as ci, SetTextFormFieldDefaultOp as cj, TabStopWrite as cl, TargetMode as cm, TextFormFieldOptions as cn, TextFormFieldRange as co, TextFormFieldType as cp, TreeDocOpKind as cq, TreeOpEffect as cr, XmlLimits as cw, XmlNode as cx, XmlRejection as cy, XmlResult as cz, ReviewCustomItem as d, VectorShapeComponent as dB, ReviewPosition as e, ReviewRange as f, ReviewRevisionKind as g, RevisionAddress as h, ContentControlType as i, DocTarget as j, RunFormatting as k, Extent as l, ContainerRef as m, ContentControlFilter as n, DocRange as o, Revision as p, DocComment as q, ColorValue as r, ContentControl as s, DocAnchor as t, DocAnchorRange as u, DocLocation as v, DocumentBody as w, ExecErrorCode as x, IndentFormatting as y, ParagraphFlags as z };