@usejunior/docx-core 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/LICENSE +202 -21
  2. package/NOTICE +2 -0
  3. package/README.md +2 -2
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/atomizer.d.ts +13 -7
  6. package/dist/atomizer.d.ts.map +1 -1
  7. package/dist/atomizer.js +59 -24
  8. package/dist/atomizer.js.map +1 -1
  9. package/dist/baselines/atomizer/auxiliaryIdCollision.d.ts +99 -0
  10. package/dist/baselines/atomizer/auxiliaryIdCollision.d.ts.map +1 -0
  11. package/dist/baselines/atomizer/auxiliaryIdCollision.js +415 -0
  12. package/dist/baselines/atomizer/auxiliaryIdCollision.js.map +1 -0
  13. package/dist/baselines/atomizer/documentReconstructor.d.ts.map +1 -1
  14. package/dist/baselines/atomizer/documentReconstructor.js +120 -27
  15. package/dist/baselines/atomizer/documentReconstructor.js.map +1 -1
  16. package/dist/baselines/atomizer/inPlaceModifier-wrappers.d.ts +9 -0
  17. package/dist/baselines/atomizer/inPlaceModifier-wrappers.d.ts.map +1 -1
  18. package/dist/baselines/atomizer/inPlaceModifier-wrappers.js +52 -4
  19. package/dist/baselines/atomizer/inPlaceModifier-wrappers.js.map +1 -1
  20. package/dist/baselines/atomizer/pipeline.d.ts +12 -53
  21. package/dist/baselines/atomizer/pipeline.d.ts.map +1 -1
  22. package/dist/baselines/atomizer/pipeline.js +126 -231
  23. package/dist/baselines/atomizer/pipeline.js.map +1 -1
  24. package/dist/baselines/atomizer/trackChangesAcceptorAst.d.ts.map +1 -1
  25. package/dist/baselines/atomizer/trackChangesAcceptorAst.js +153 -23
  26. package/dist/baselines/atomizer/trackChangesAcceptorAst.js.map +1 -1
  27. package/dist/baselines/wmlcomparer/DotnetCli.d.ts.map +1 -1
  28. package/dist/baselines/wmlcomparer/DotnetCli.js +7 -0
  29. package/dist/baselines/wmlcomparer/DotnetCli.js.map +1 -1
  30. package/dist/cli/compare-two.d.ts.map +1 -1
  31. package/dist/cli/compare-two.js +3 -1
  32. package/dist/cli/compare-two.js.map +1 -1
  33. package/dist/cli/conformance-adapter.d.ts +3 -0
  34. package/dist/cli/conformance-adapter.d.ts.map +1 -0
  35. package/dist/cli/conformance-adapter.js +93 -0
  36. package/dist/cli/conformance-adapter.js.map +1 -0
  37. package/dist/cli/index.d.ts.map +1 -1
  38. package/dist/cli/index.js +5 -1
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/compare-types.d.ts +46 -0
  41. package/dist/compare-types.d.ts.map +1 -1
  42. package/dist/generation/compile.d.ts +22 -0
  43. package/dist/generation/compile.d.ts.map +1 -0
  44. package/dist/generation/compile.js +58 -0
  45. package/dist/generation/compile.js.map +1 -0
  46. package/dist/generation/context.d.ts +42 -0
  47. package/dist/generation/context.d.ts.map +1 -0
  48. package/dist/generation/context.js +65 -0
  49. package/dist/generation/context.js.map +1 -0
  50. package/dist/generation/emit/comments-part.d.ts +36 -0
  51. package/dist/generation/emit/comments-part.d.ts.map +1 -0
  52. package/dist/generation/emit/comments-part.js +116 -0
  53. package/dist/generation/emit/comments-part.js.map +1 -0
  54. package/dist/generation/emit/document-part.d.ts +24 -0
  55. package/dist/generation/emit/document-part.d.ts.map +1 -0
  56. package/dist/generation/emit/document-part.js +60 -0
  57. package/dist/generation/emit/document-part.js.map +1 -0
  58. package/dist/generation/emit/emit-context.d.ts +28 -0
  59. package/dist/generation/emit/emit-context.d.ts.map +1 -0
  60. package/dist/generation/emit/emit-context.js +19 -0
  61. package/dist/generation/emit/emit-context.js.map +1 -0
  62. package/dist/generation/emit/font-table-part.d.ts +16 -0
  63. package/dist/generation/emit/font-table-part.d.ts.map +1 -0
  64. package/dist/generation/emit/font-table-part.js +74 -0
  65. package/dist/generation/emit/font-table-part.js.map +1 -0
  66. package/dist/generation/emit/header-footer-part.d.ts +23 -0
  67. package/dist/generation/emit/header-footer-part.d.ts.map +1 -0
  68. package/dist/generation/emit/header-footer-part.js +57 -0
  69. package/dist/generation/emit/header-footer-part.js.map +1 -0
  70. package/dist/generation/emit/numbering-part.d.ts +29 -0
  71. package/dist/generation/emit/numbering-part.d.ts.map +1 -0
  72. package/dist/generation/emit/numbering-part.js +102 -0
  73. package/dist/generation/emit/numbering-part.js.map +1 -0
  74. package/dist/generation/emit/package-parts.d.ts +24 -0
  75. package/dist/generation/emit/package-parts.d.ts.map +1 -0
  76. package/dist/generation/emit/package-parts.js +121 -0
  77. package/dist/generation/emit/package-parts.js.map +1 -0
  78. package/dist/generation/emit/paragraph.d.ts +24 -0
  79. package/dist/generation/emit/paragraph.d.ts.map +1 -0
  80. package/dist/generation/emit/paragraph.js +63 -0
  81. package/dist/generation/emit/paragraph.js.map +1 -0
  82. package/dist/generation/emit/properties.d.ts +36 -0
  83. package/dist/generation/emit/properties.d.ts.map +1 -0
  84. package/dist/generation/emit/properties.js +154 -0
  85. package/dist/generation/emit/properties.js.map +1 -0
  86. package/dist/generation/emit/run.d.ts +16 -0
  87. package/dist/generation/emit/run.d.ts.map +1 -0
  88. package/dist/generation/emit/run.js +71 -0
  89. package/dist/generation/emit/run.js.map +1 -0
  90. package/dist/generation/emit/section.d.ts +29 -0
  91. package/dist/generation/emit/section.d.ts.map +1 -0
  92. package/dist/generation/emit/section.js +117 -0
  93. package/dist/generation/emit/section.js.map +1 -0
  94. package/dist/generation/emit/settings-part.d.ts +13 -0
  95. package/dist/generation/emit/settings-part.d.ts.map +1 -0
  96. package/dist/generation/emit/settings-part.js +68 -0
  97. package/dist/generation/emit/settings-part.js.map +1 -0
  98. package/dist/generation/emit/styles-part.d.ts +16 -0
  99. package/dist/generation/emit/styles-part.d.ts.map +1 -0
  100. package/dist/generation/emit/styles-part.js +82 -0
  101. package/dist/generation/emit/styles-part.js.map +1 -0
  102. package/dist/generation/emit/table.d.ts +26 -0
  103. package/dist/generation/emit/table.d.ts.map +1 -0
  104. package/dist/generation/emit/table.js +209 -0
  105. package/dist/generation/emit/table.js.map +1 -0
  106. package/dist/generation/emit/theme-part.d.ts +21 -0
  107. package/dist/generation/emit/theme-part.d.ts.map +1 -0
  108. package/dist/generation/emit/theme-part.js +151 -0
  109. package/dist/generation/emit/theme-part.js.map +1 -0
  110. package/dist/generation/emit/web-settings-part.d.ts +12 -0
  111. package/dist/generation/emit/web-settings-part.d.ts.map +1 -0
  112. package/dist/generation/emit/web-settings-part.js +19 -0
  113. package/dist/generation/emit/web-settings-part.js.map +1 -0
  114. package/dist/generation/errors.d.ts +22 -0
  115. package/dist/generation/errors.d.ts.map +1 -0
  116. package/dist/generation/errors.js +29 -0
  117. package/dist/generation/errors.js.map +1 -0
  118. package/dist/generation/index.d.ts +13 -0
  119. package/dist/generation/index.d.ts.map +1 -0
  120. package/dist/generation/index.js +12 -0
  121. package/dist/generation/index.js.map +1 -0
  122. package/dist/generation/ordering.d.ts +46 -0
  123. package/dist/generation/ordering.d.ts.map +1 -0
  124. package/dist/generation/ordering.js +119 -0
  125. package/dist/generation/ordering.js.map +1 -0
  126. package/dist/generation/recipes.d.ts +70 -0
  127. package/dist/generation/recipes.d.ts.map +1 -0
  128. package/dist/generation/recipes.js +149 -0
  129. package/dist/generation/recipes.js.map +1 -0
  130. package/dist/generation/structural-checks.d.ts +24 -0
  131. package/dist/generation/structural-checks.d.ts.map +1 -0
  132. package/dist/generation/structural-checks.js +318 -0
  133. package/dist/generation/structural-checks.js.map +1 -0
  134. package/dist/generation/theme-colors.d.ts +4 -0
  135. package/dist/generation/theme-colors.d.ts.map +1 -0
  136. package/dist/generation/theme-colors.js +18 -0
  137. package/dist/generation/theme-colors.js.map +1 -0
  138. package/dist/generation/types.d.ts +249 -0
  139. package/dist/generation/types.d.ts.map +1 -0
  140. package/dist/generation/types.js +54 -0
  141. package/dist/generation/types.js.map +1 -0
  142. package/dist/generation/validate-spec.d.ts +27 -0
  143. package/dist/generation/validate-spec.d.ts.map +1 -0
  144. package/dist/generation/validate-spec.js +359 -0
  145. package/dist/generation/validate-spec.js.map +1 -0
  146. package/dist/index.d.ts +3 -0
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +8 -0
  149. package/dist/index.js.map +1 -1
  150. package/dist/integration/generation-probes.d.ts +15 -0
  151. package/dist/integration/generation-probes.d.ts.map +1 -0
  152. package/dist/integration/generation-probes.js +84 -0
  153. package/dist/integration/generation-probes.js.map +1 -0
  154. package/dist/integration/libreoffice-oracle.d.ts +8 -0
  155. package/dist/integration/libreoffice-oracle.d.ts.map +1 -1
  156. package/dist/integration/libreoffice-oracle.js +14 -6
  157. package/dist/integration/libreoffice-oracle.js.map +1 -1
  158. package/dist/integration/synthetic-docx-fixture.d.ts +72 -0
  159. package/dist/integration/synthetic-docx-fixture.d.ts.map +1 -1
  160. package/dist/integration/synthetic-docx-fixture.js +131 -4
  161. package/dist/integration/synthetic-docx-fixture.js.map +1 -1
  162. package/dist/primitives/accept_changes.d.ts +2 -1
  163. package/dist/primitives/accept_changes.d.ts.map +1 -1
  164. package/dist/primitives/accept_changes.js +153 -12
  165. package/dist/primitives/accept_changes.js.map +1 -1
  166. package/dist/primitives/document.d.ts +38 -0
  167. package/dist/primitives/document.d.ts.map +1 -1
  168. package/dist/primitives/document.js +75 -9
  169. package/dist/primitives/document.js.map +1 -1
  170. package/dist/primitives/document_view-comments.d.ts.map +1 -1
  171. package/dist/primitives/document_view-comments.js +4 -3
  172. package/dist/primitives/document_view-comments.js.map +1 -1
  173. package/dist/primitives/document_view-types.d.ts +15 -0
  174. package/dist/primitives/document_view-types.d.ts.map +1 -1
  175. package/dist/primitives/document_view.d.ts.map +1 -1
  176. package/dist/primitives/document_view.js +21 -13
  177. package/dist/primitives/document_view.js.map +1 -1
  178. package/dist/primitives/formatting_tags.d.ts +1 -0
  179. package/dist/primitives/formatting_tags.d.ts.map +1 -1
  180. package/dist/primitives/formatting_tags.js +16 -10
  181. package/dist/primitives/formatting_tags.js.map +1 -1
  182. package/dist/primitives/index.d.ts +4 -0
  183. package/dist/primitives/index.d.ts.map +1 -1
  184. package/dist/primitives/index.js +4 -0
  185. package/dist/primitives/index.js.map +1 -1
  186. package/dist/primitives/layout.d.ts.map +1 -1
  187. package/dist/primitives/layout.js +13 -0
  188. package/dist/primitives/layout.js.map +1 -1
  189. package/dist/primitives/minimal_save.d.ts +38 -0
  190. package/dist/primitives/minimal_save.d.ts.map +1 -0
  191. package/dist/primitives/minimal_save.js +323 -0
  192. package/dist/primitives/minimal_save.js.map +1 -0
  193. package/dist/primitives/namespaces.d.ts +46 -0
  194. package/dist/primitives/namespaces.d.ts.map +1 -1
  195. package/dist/primitives/namespaces.js +49 -0
  196. package/dist/primitives/namespaces.js.map +1 -1
  197. package/dist/primitives/reject_changes.d.ts +4 -2
  198. package/dist/primitives/reject_changes.d.ts.map +1 -1
  199. package/dist/primitives/reject_changes.js +177 -24
  200. package/dist/primitives/reject_changes.js.map +1 -1
  201. package/dist/primitives/revision-parts.d.ts +7 -0
  202. package/dist/primitives/revision-parts.d.ts.map +1 -0
  203. package/dist/primitives/revision-parts.js +27 -0
  204. package/dist/primitives/revision-parts.js.map +1 -0
  205. package/dist/primitives/revision-vocabulary.d.ts +7 -0
  206. package/dist/primitives/revision-vocabulary.d.ts.map +1 -0
  207. package/dist/primitives/revision-vocabulary.js +39 -0
  208. package/dist/primitives/revision-vocabulary.js.map +1 -0
  209. package/dist/primitives/schema-corpus-capture.d.ts +19 -0
  210. package/dist/primitives/schema-corpus-capture.d.ts.map +1 -0
  211. package/dist/primitives/schema-corpus-capture.js +29 -0
  212. package/dist/primitives/schema-corpus-capture.js.map +1 -0
  213. package/dist/primitives/sectPrAudit.d.ts +19 -0
  214. package/dist/primitives/sectPrAudit.d.ts.map +1 -0
  215. package/dist/primitives/sectPrAudit.js +165 -0
  216. package/dist/primitives/sectPrAudit.js.map +1 -0
  217. package/dist/primitives/semantic_tags.d.ts.map +1 -1
  218. package/dist/primitives/semantic_tags.js +2 -1
  219. package/dist/primitives/semantic_tags.js.map +1 -1
  220. package/dist/primitives/serialize_html.d.ts +1 -0
  221. package/dist/primitives/serialize_html.d.ts.map +1 -1
  222. package/dist/primitives/serialize_html.js +4 -2
  223. package/dist/primitives/serialize_html.js.map +1 -1
  224. package/dist/primitives/styles.d.ts +15 -0
  225. package/dist/primitives/styles.d.ts.map +1 -1
  226. package/dist/primitives/styles.js +11 -0
  227. package/dist/primitives/styles.js.map +1 -1
  228. package/dist/primitives/track-changes-emitter.d.ts +9 -0
  229. package/dist/primitives/track-changes-emitter.d.ts.map +1 -1
  230. package/dist/primitives/track-changes-emitter.js +54 -4
  231. package/dist/primitives/track-changes-emitter.js.map +1 -1
  232. package/dist/primitives/validate_ai_revisions.d.ts +35 -0
  233. package/dist/primitives/validate_ai_revisions.d.ts.map +1 -0
  234. package/dist/primitives/validate_ai_revisions.js +323 -0
  235. package/dist/primitives/validate_ai_revisions.js.map +1 -0
  236. package/dist/primitives/xml.d.ts +5 -0
  237. package/dist/primitives/xml.d.ts.map +1 -1
  238. package/dist/primitives/xml.js +5 -0
  239. package/dist/primitives/xml.js.map +1 -1
  240. package/dist/primitives/zip.d.ts +1 -0
  241. package/dist/primitives/zip.d.ts.map +1 -1
  242. package/dist/primitives/zip.js +21 -3
  243. package/dist/primitives/zip.js.map +1 -1
  244. package/dist/shared/field-structure.d.ts +14 -0
  245. package/dist/shared/field-structure.d.ts.map +1 -0
  246. package/dist/shared/field-structure.js +166 -0
  247. package/dist/shared/field-structure.js.map +1 -0
  248. package/package.json +7 -4
@@ -6,7 +6,8 @@
6
6
  * - Unwrapping w:ins elements (promoting children)
7
7
  * - Removing w:moveFrom (source), unwrapping w:moveTo (destination)
8
8
  * - Removing all *PrChange property change records
9
- * - Stripping paragraph-level revision markers
9
+ * - Stripping paragraph-level revision markers, merging a paragraph whose
10
+ * mark was a tracked deletion into the following paragraph
10
11
  * - Cleaning up move range markers and rsidDel attributes
11
12
  *
12
13
  * Operates on the W3C DOM (`@xmldom/xmldom`) — the same API used
@@ -89,6 +90,144 @@ const PR_CHANGE_LOCALS = [
89
90
  'rPrChange', 'pPrChange', 'sectPrChange',
90
91
  'tblPrChange', 'trPrChange', 'tcPrChange',
91
92
  ];
93
+ // Marker-ish elements that may sit between two paragraphs at block level
94
+ // without ending the search for a merge target: the full EG_RangeMarkupElements
95
+ // schema group (wml.xsd), plus permStart/permEnd range markers and proofErr
96
+ // proofing anchors.
97
+ const RANGE_MARKUP_BLOCK_SIBLING_LOCALS = new Set([
98
+ 'bookmarkStart', 'bookmarkEnd',
99
+ 'commentRangeStart', 'commentRangeEnd',
100
+ 'moveFromRangeStart', 'moveFromRangeEnd',
101
+ 'moveToRangeStart', 'moveToRangeEnd',
102
+ 'customXmlInsRangeStart', 'customXmlInsRangeEnd',
103
+ 'customXmlDelRangeStart', 'customXmlDelRangeEnd',
104
+ 'customXmlMoveFromRangeStart', 'customXmlMoveFromRangeEnd',
105
+ 'customXmlMoveToRangeStart', 'customXmlMoveToRangeEnd',
106
+ 'permStart', 'permEnd',
107
+ 'proofErr',
108
+ ]);
109
+ /**
110
+ * Find the next sibling paragraph a paragraph-mark revision can merge into,
111
+ * skipping block-level range/annotation markers. Returns null when the next
112
+ * block is not a paragraph (table, sdt, sectPr, end of parent).
113
+ */
114
+ function findFollowingSiblingParagraph(p) {
115
+ let sibling = p.nextSibling;
116
+ while (sibling) {
117
+ if (sibling.nodeType === 1) {
118
+ if (isW(sibling, 'p'))
119
+ return sibling;
120
+ const el = sibling;
121
+ if (el.namespaceURI === W_NS && RANGE_MARKUP_BLOCK_SIBLING_LOCALS.has(el.localName ?? '')) {
122
+ sibling = sibling.nextSibling;
123
+ continue;
124
+ }
125
+ return null;
126
+ }
127
+ sibling = sibling.nextSibling;
128
+ }
129
+ return null;
130
+ }
131
+ /** True iff the paragraph still holds content beyond w:pPr and bare annotation markers. */
132
+ function paragraphHasContent(p) {
133
+ for (let i = 0; i < p.childNodes.length; i++) {
134
+ const child = p.childNodes[i];
135
+ if (child.nodeType !== 1)
136
+ continue;
137
+ if (isW(child, 'pPr'))
138
+ continue;
139
+ const el = child;
140
+ if (el.namespaceURI === W_NS && RANGE_MARKUP_BLOCK_SIBLING_LOCALS.has(el.localName ?? ''))
141
+ continue;
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+ /**
147
+ * True iff removing an emptied mark-revised paragraph keeps its parent
148
+ * structurally valid for Word: the parent must retain at least one block
149
+ * element, must not end on a w:tbl (a trailing table needs a following
150
+ * paragraph), and two tables must not become adjacent (Word merges
151
+ * back-to-back tables). w:sectPr is ignored — a trailing body sectPr is not a
152
+ * block element.
153
+ */
154
+ function canSafelyRemoveEmptyParagraph(p) {
155
+ const blockSibling = (start, dir) => {
156
+ let sibling = start;
157
+ while (sibling) {
158
+ if (sibling.nodeType === 1) {
159
+ const el = sibling;
160
+ if ((el.namespaceURI === W_NS && RANGE_MARKUP_BLOCK_SIBLING_LOCALS.has(el.localName ?? '')) ||
161
+ isW(el, 'sectPr')) {
162
+ sibling = sibling[dir];
163
+ continue;
164
+ }
165
+ return el;
166
+ }
167
+ sibling = sibling[dir];
168
+ }
169
+ return null;
170
+ };
171
+ const prev = blockSibling(p.previousSibling, 'previousSibling');
172
+ const next = blockSibling(p.nextSibling, 'nextSibling');
173
+ if (!prev && !next)
174
+ return false;
175
+ if (prev && isW(prev, 'tbl') && !next)
176
+ return false;
177
+ if (prev && next && isW(prev, 'tbl') && isW(next, 'tbl'))
178
+ return false;
179
+ return true;
180
+ }
181
+ /**
182
+ * Resolve a paragraph whose paragraph MARK revision was applied (deleted mark
183
+ * accepted): the paragraph break disappears, so the paragraph's remaining
184
+ * content merges into the FOLLOWING paragraph. The surviving (following)
185
+ * paragraph keeps its own w:pPr — formatting follows the surviving paragraph
186
+ * mark — and the merged-away paragraph's w:pPr is dropped.
187
+ *
188
+ * The revision targets only the mark, never the paragraph's contents, so the
189
+ * contents must not be dropped wholesale. When no following sibling paragraph
190
+ * exists (last block, or the next block is a table), there is no break to
191
+ * remove into: content-bearing paragraphs are kept, and emptied ones are
192
+ * removed only where removal keeps the parent structurally valid
193
+ * (canSafelyRemoveEmptyParagraph).
194
+ *
195
+ * @conformance ECMA-376 edition 5, Part 1 § 17.13.5.15
196
+ * @see https://github.com/UseJunior/safe-docx/issues/431
197
+ */
198
+ function resolveParagraphMarkRevision(p) {
199
+ const parent = p.parentNode;
200
+ if (!parent)
201
+ return;
202
+ const target = findFollowingSiblingParagraph(p);
203
+ if (!target) {
204
+ if (!paragraphHasContent(p) && canSafelyRemoveEmptyParagraph(p)) {
205
+ parent.removeChild(p);
206
+ }
207
+ return;
208
+ }
209
+ // Insertion point: before the target's first non-pPr child (the merged
210
+ // content precedes the target's own content in document order).
211
+ let ref = null;
212
+ for (let i = 0; i < target.childNodes.length; i++) {
213
+ const c = target.childNodes[i];
214
+ if (c.nodeType === 1 && isW(c, 'pPr'))
215
+ continue;
216
+ ref = c;
217
+ break;
218
+ }
219
+ const toMove = [];
220
+ for (let i = 0; i < p.childNodes.length; i++) {
221
+ const c = p.childNodes[i];
222
+ if (c.nodeType === 1 && isW(c, 'pPr'))
223
+ continue;
224
+ toMove.push(c);
225
+ }
226
+ for (const c of toMove) {
227
+ target.insertBefore(c, ref);
228
+ }
229
+ parent.removeChild(p);
230
+ }
92
231
  // ── Public API ──────────────────────────────────────────────────────
93
232
  /**
94
233
  * Accept all tracked changes in the document body or story root, producing a
@@ -102,20 +241,22 @@ export function acceptChanges(doc) {
102
241
  if (!root) {
103
242
  return { insertionsAccepted: 0, deletionsAccepted: 0, movesResolved: 0, propertyChangesResolved: 0 };
104
243
  }
105
- // Phase A — Identify paragraphs to remove
106
- const paragraphsToRemove = new Set();
244
+ // Phase A — Identify paragraphs whose MARK is a tracked deletion
245
+ const markDeletedParagraphs = [];
107
246
  const allParagraphs = collectByLocalName(root, 'p');
108
247
  for (const p of allParagraphs) {
109
- // Remove a paragraph iff its paragraph MARK is a tracked deletion
110
- // (w:p > w:pPr > w:rPr > w:del) — the paragraph break itself was deleted.
111
- // We deliberately do NOT drop a paragraph based on content ("all runs inside
248
+ // A paragraph-mark deletion (w:p > w:pPr > w:rPr > w:del) means the
249
+ // paragraph BREAK was deleted — accepting it merges the paragraph into the
250
+ // following one (resolveParagraphMarkRevision); the contents are deleted
251
+ // only via their own run-level w:del wrappers.
252
+ // We deliberately do NOT touch a paragraph based on content ("all runs inside
112
253
  // w:del/w:moveFrom"): a run-level deletion under an untracked mark means text was
113
254
  // deleted from a pre-existing paragraph, which Word/LibreOffice keep (empty) on
114
255
  // accept. safe-docx's deleted paragraphs always carry the mark now, so the
115
256
  // mark-based rule suffices and is Word-faithful. (Mirrors acceptAllChanges and the
116
257
  // reject-side rule.)
117
258
  if (paragraphHasParaMarker(p, 'del')) {
118
- paragraphsToRemove.add(p);
259
+ markDeletedParagraphs.push(p);
119
260
  }
120
261
  }
121
262
  // Phase B — Remove deletions and move sources
@@ -158,11 +299,11 @@ export function acceptChanges(doc) {
158
299
  }
159
300
  }
160
301
  }
161
- // Remove paragraphs collected in Phase A (check parentNode still exists)
162
- for (const p of paragraphsToRemove) {
163
- if (p.parentNode) {
164
- p.parentNode.removeChild(p);
165
- }
302
+ // Resolve paragraphs collected in Phase A: merge each into its following
303
+ // paragraph (document order, so consecutive mark-deleted paragraphs cascade
304
+ // forward into the first surviving one).
305
+ for (const p of markDeletedParagraphs) {
306
+ resolveParagraphMarkRevision(p);
166
307
  }
167
308
  // Strip w:rsidDel attributes on remaining elements
168
309
  const allElements = root.getElementsByTagNameNS(W_NS, '*');
@@ -1 +1 @@
1
- {"version":3,"file":"accept_changes.js","sourceRoot":"","sources":["../../src/primitives/accept_changes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AASxB,uEAAuE;AAEvE,SAAS,GAAG,CAAC,IAAU,EAAE,SAAiB;IACxC,OAAO,CACL,IAAI,CAAC,QAAQ,KAAK,CAAC;QAClB,IAAgB,CAAC,YAAY,KAAK,IAAI;QACtC,IAAgB,CAAC,SAAS,KAAK,SAAS,CAC1C,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAU;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAgB,IAAI,CAAC,UAAU,CAAC;IACvC,OAAO,GAAG,EAAE,CAAC;QACX,KAAK,EAAE,CAAC;QACR,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,SAA6B,EAAE,SAAiB;IAC1E,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,oBAAoB,CAAC,SAA6B,EAAE,SAAiB;IAC5E,MAAM,QAAQ,GAAG,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC1D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;YAClB,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YAC9B,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAAC,SAA6B,EAAE,SAAiB;IAC5E,MAAM,QAAQ,GAAG,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC1D,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC;QAC7B,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,qCAAqC;QACrC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACvB,KAAK,EAAE,CAAC;IACV,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAAC,CAAU,EAAE,eAAuB;IACjE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;YAAE,SAAS;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;gBAAE,SAAS;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpD,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;gBACzC,IAAI,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC;oBAAE,OAAO,IAAI,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oDAAoD;AACpD,MAAM,gBAAgB,GAAG;IACvB,WAAW,EAAE,WAAW,EAAE,cAAc;IACxC,aAAa,EAAE,YAAY,EAAE,YAAY;CAC1C,CAAC;AAEF,uEAAuE;AAEvE;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,GAAa;IACzC,MAAM,IAAI,GAAG,GAAG,CAAC,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,eAAe,CAAC;IACrF,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,kBAAkB,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,uBAAuB,EAAE,CAAC,EAAE,CAAC;IACvG,CAAC;IAED,0CAA0C;IAC1C,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAW,CAAC;IAC9C,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAEpD,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,kEAAkE;QAClE,0EAA0E;QAC1E,6EAA6E;QAC7E,kFAAkF;QAClF,gFAAgF;QAChF,2EAA2E;QAC3E,mFAAmF;QACnF,qBAAqB;QACrB,IAAI,sBAAsB,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;YACrC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5D,MAAM,eAAe,GAAG,oBAAoB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/D,oBAAoB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IACjD,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAC/C,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAC/C,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAE7C,mEAAmE;IACnE,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE7D,2CAA2C;IAC3C,IAAI,uBAAuB,GAAG,CAAC,CAAC;IAChC,KAAK,MAAM,SAAS,IAAI,gBAAgB,EAAE,CAAC;QACzC,uBAAuB,IAAI,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnE,CAAC;IAED,oBAAoB;IACpB,0DAA0D;IAC1D,KAAK,MAAM,CAAC,IAAI,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;gBAAE,SAAS;YACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;gBACtC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;oBAAE,SAAS;gBACpC,0DAA0D;gBAC1D,MAAM,QAAQ,GAAc,EAAE,CAAC;gBAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACpD,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;oBACzC,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;wBACjD,QAAQ,CAAC,IAAI,CAAC,QAAmB,CAAC,CAAC;oBACrC,CAAC;gBACH,CAAC;gBACD,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;oBAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,KAAK,MAAM,CAAC,IAAI,kBAAkB,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;YACjB,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,WAAW,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;YACvC,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QACD,2BAA2B;QAC3B,IAAI,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;YACjC,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO;QACL,kBAAkB;QAClB,iBAAiB;QACjB,aAAa,EAAE,eAAe,GAAG,eAAe;QAChD,uBAAuB;KACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"accept_changes.js","sourceRoot":"","sources":["../../src/primitives/accept_changes.ts"],"names":[],"mappings":"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"}
@@ -5,10 +5,13 @@ import { type SerializeMarkdownOptions } from './serialize_markdown.js';
5
5
  import { type SerializeHtmlOptions } from './serialize_html.js';
6
6
  import { type SerializePlainTextOptions } from './serialize_plaintext.js';
7
7
  import type { FormattingMode } from './formatting_tags.js';
8
+ import { type StylesModel } from './styles.js';
9
+ import { type NumberingModel } from './numbering.js';
8
10
  import { type ParagraphSpacingMutation, type ParagraphSpacingMutationResult, type TableCellPaddingMutation, type TableCellPaddingMutationResult, type TableRowHeightMutation, type TableRowHeightMutationResult } from './layout.js';
9
11
  import { type ExtractTablesOptions, type ExtractTablesResult } from './tables.js';
10
12
  import { type MergeRunsOptions, type MergeRunsResult } from './merge_runs.js';
11
13
  import { type ValidateDocumentResult } from './validate_document.js';
14
+ import { type AiRevisionValidationTouchedContext, type ValidateAiRevisionsResult } from './validate_ai_revisions.js';
12
15
  import { type AcceptChangesResult } from './accept_changes.js';
13
16
  import { type RejectChangesResult } from './reject_changes.js';
14
17
  import { type AddCommentResult, type AddCommentReplyResult, type Comment } from './comments.js';
@@ -32,6 +35,12 @@ export declare class DocxDocument {
32
35
  private relsMap;
33
36
  private dirty;
34
37
  private documentViewCache;
38
+ /**
39
+ * Raw document.xml text as loaded, before normalize()/edits mutate the DOM.
40
+ * Reference for minimal re-serialization in toBuffer(); null for instances
41
+ * not created via load().
42
+ */
43
+ private originalDocumentXmlText;
35
44
  private constructor();
36
45
  static load(buffer: Buffer): Promise<DocxDocument>;
37
46
  getParagraphs(): Element[];
@@ -51,6 +60,7 @@ export declare class DocxDocument {
51
60
  * Non-destructive, read-only check.
52
61
  */
53
62
  validate(): ValidateDocumentResult;
63
+ validateAiRevisions(aiAuthor: string, touched?: AiRevisionValidationTouchedContext): Promise<ValidateAiRevisionsResult>;
54
64
  /**
55
65
  * Accept all tracked changes in document.xml plus supported revisionable
56
66
  * side-story parts, producing clean XML with no revision markup.
@@ -70,6 +80,19 @@ export declare class DocxDocument {
70
80
  paragraphs: ParagraphRef[];
71
81
  totalParagraphs: number;
72
82
  };
83
+ /**
84
+ * Parsed `word/numbering.xml` model (abstract numberings + instances), or null when the
85
+ * document has no numbering part. The document view's `numbering` field only carries
86
+ * `num_id`/`ilvl`; semantic converters (DOCX → ODT) need `numFmt`/`lvlText`/`start` to
87
+ * synthesize target-format list styles, so the full model is exposed here.
88
+ */
89
+ getNumberingModel(): NumberingModel | null;
90
+ /**
91
+ * Parsed named-style model of the loaded document (empty when the package has no
92
+ * `word/styles.xml`). Semantic converters (DOCX → ODT) resolve heading/body style chains
93
+ * through it to seed their own style templates from the source's definitions.
94
+ */
95
+ getStylesModel(): StylesModel;
73
96
  buildDocumentView(opts?: {
74
97
  includeSemanticTags?: boolean;
75
98
  showFormatting?: boolean;
@@ -217,11 +240,26 @@ export declare class DocxDocument {
217
240
  * has no comments part.
218
241
  */
219
242
  getCommentsXmlClone(): Promise<Document | null>;
243
+ /**
244
+ * Serialize the document to a .docx buffer.
245
+ *
246
+ * With `minimalReserialization` (requires `cleanBookmarks`), top-level body
247
+ * blocks that no edit touched are restored element-for-element from the
248
+ * original document.xml instead of carrying the open-time normalization
249
+ * (proofErr stripping, run merging) to disk — so output diffs reflect the
250
+ * actual edit blast radius. Edited/inserted blocks are emitted as-is.
251
+ * Falls back to full re-serialization (blocksRestored: 0) when no original
252
+ * text was captured or reconciliation fails.
253
+ *
254
+ * @see https://github.com/UseJunior/safe-docx/issues/408
255
+ */
220
256
  toBuffer(opts?: {
221
257
  cleanBookmarks?: boolean;
258
+ minimalReserialization?: boolean;
222
259
  }): Promise<{
223
260
  buffer: Buffer;
224
261
  bookmarksRemoved: number;
262
+ blocksRestored: number;
225
263
  }>;
226
264
  }
227
265
  //# sourceMappingURL=document.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/primitives/document.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/primitives/document.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { DocxZip } from './zip.js';
2
2
  import { parseXml, serializeXml } from './xml.js';
3
+ import { maybeCaptureEmittedDocumentXml } from './schema-corpus-capture.js';
3
4
  import { OOXML, W } from './namespaces.js';
4
5
  import { createWmlElement, isW, getDirectChildrenByName } from './dom-helpers.js';
5
6
  import { findParagraphByBookmarkId, insertParagraphBookmarks, cleanupInternalBookmarks, getParagraphBookmarkId, insertSingleParagraphBookmark, } from './bookmarks.js';
@@ -9,23 +10,23 @@ import { buildNodesForDocumentView } from './document_view.js';
9
10
  import { serializeToMarkdown } from './serialize_markdown.js';
10
11
  import { serializeToHtml } from './serialize_html.js';
11
12
  import { serializeToPlainText } from './serialize_plaintext.js';
13
+ import { parseStylesXml } from './styles.js';
14
+ import { parseNumberingXml } from './numbering.js';
12
15
  import { findUniqueSubstringMatch } from './matching.js';
13
16
  import { parseDocumentRels } from './relationships.js';
14
17
  import { setParagraphSpacing, setTableCellPadding, setTableRowHeight, } from './layout.js';
15
18
  import { extractTables, } from './tables.js';
16
19
  import { mergeRuns } from './merge_runs.js';
20
+ import { restoreUntouchedBlocks } from './minimal_save.js';
17
21
  import { simplifyRedlines } from './simplify_redlines.js';
18
22
  import { preventDoubleElevation } from './prevent_double_elevation.js';
19
23
  import { validateDocument } from './validate_document.js';
24
+ import { validateAiRevisions as validateAiRevisionsImpl, } from './validate_ai_revisions.js';
25
+ import { enumerateRevisionStoryPartPaths, REVISION_STORY_PART_PATHS, } from './revision-parts.js';
20
26
  import { acceptChanges as acceptChangesImpl } from './accept_changes.js';
21
27
  import { rejectChanges as rejectChangesImpl } from './reject_changes.js';
22
28
  import { bootstrapCommentParts, addComment as addCommentImpl, addCommentReply as addCommentReplyImpl, getComments as getCommentsImpl, getComment as getCommentImpl, deleteComment as deleteCommentImpl, } from './comments.js';
23
29
  import { bootstrapFootnoteParts, getFootnotes as getFootnotesImpl, getFootnote as getFootnoteImpl, addFootnote as addFootnoteImpl, updateFootnoteText as updateFootnoteTextImpl, deleteFootnote as deleteFootnoteImpl, } from './footnotes.js';
24
- const REVISION_STORY_PART_PATHS = [
25
- 'word/footnotes.xml',
26
- 'word/endnotes.xml',
27
- 'word/comments.xml',
28
- ];
29
30
  function emptyAcceptChangesResult() {
30
31
  return { insertionsAccepted: 0, deletionsAccepted: 0, movesResolved: 0, propertyChangesResolved: 0 };
31
32
  }
@@ -307,7 +308,13 @@ export class DocxDocument {
307
308
  relsMap;
308
309
  dirty;
309
310
  documentViewCache;
310
- constructor(zip, documentXml, stylesXml, numberingXml, footnotesXml, relsMap) {
311
+ /**
312
+ * Raw document.xml text as loaded, before normalize()/edits mutate the DOM.
313
+ * Reference for minimal re-serialization in toBuffer(); null for instances
314
+ * not created via load().
315
+ */
316
+ originalDocumentXmlText;
317
+ constructor(zip, documentXml, stylesXml, numberingXml, footnotesXml, relsMap, originalDocumentXmlText = null) {
311
318
  this.zip = zip;
312
319
  this.documentXml = documentXml;
313
320
  this.stylesXml = stylesXml;
@@ -316,6 +323,7 @@ export class DocxDocument {
316
323
  this.relsMap = relsMap;
317
324
  this.dirty = false;
318
325
  this.documentViewCache = null;
326
+ this.originalDocumentXmlText = originalDocumentXmlText;
319
327
  }
320
328
  static async load(buffer) {
321
329
  const zip = await DocxZip.load(buffer);
@@ -332,7 +340,7 @@ export class DocxDocument {
332
340
  // Load document relationships for hyperlink resolution.
333
341
  const relsText = await zip.readTextOrNull('word/_rels/document.xml.rels');
334
342
  const relsMap = relsText ? parseDocumentRels(parseXml(relsText)) : new Map();
335
- return new DocxDocument(zip, doc, stylesXml, numberingXml, footnotesXml, relsMap);
343
+ return new DocxDocument(zip, doc, stylesXml, numberingXml, footnotesXml, relsMap, xml);
336
344
  }
337
345
  getParagraphs() {
338
346
  const body = this.documentXml.getElementsByTagNameNS(OOXML.W_NS, W.body).item(0);
@@ -389,6 +397,21 @@ export class DocxDocument {
389
397
  validate() {
390
398
  return validateDocument(this.documentXml);
391
399
  }
400
+ async validateAiRevisions(aiAuthor, touched) {
401
+ const stories = [{ part: 'word/document.xml', doc: this.documentXml }];
402
+ for (const partPath of enumerateRevisionStoryPartPaths(this.zip)) {
403
+ const xml = await this.zip.readTextOrNull(partPath);
404
+ if (!xml)
405
+ continue;
406
+ stories.push({ part: partPath, doc: parseXml(xml) });
407
+ }
408
+ return validateAiRevisionsImpl({
409
+ aiAuthor,
410
+ stories,
411
+ packageZip: this.zip,
412
+ touched,
413
+ });
414
+ }
392
415
  /**
393
416
  * Accept all tracked changes in document.xml plus supported revisionable
394
417
  * side-story parts, producing clean XML with no revision markup.
@@ -500,6 +523,23 @@ export class DocxDocument {
500
523
  const endIdx = typeof limit === 'number' ? Math.min(total, startIdx + limit) : total;
501
524
  return { paragraphs: all.slice(startIdx, endIdx), totalParagraphs: total };
502
525
  }
526
+ /**
527
+ * Parsed `word/numbering.xml` model (abstract numberings + instances), or null when the
528
+ * document has no numbering part. The document view's `numbering` field only carries
529
+ * `num_id`/`ilvl`; semantic converters (DOCX → ODT) need `numFmt`/`lvlText`/`start` to
530
+ * synthesize target-format list styles, so the full model is exposed here.
531
+ */
532
+ getNumberingModel() {
533
+ return this.numberingXml ? parseNumberingXml(this.numberingXml) : null;
534
+ }
535
+ /**
536
+ * Parsed named-style model of the loaded document (empty when the package has no
537
+ * `word/styles.xml`). Semantic converters (DOCX → ODT) resolve heading/body style chains
538
+ * through it to seed their own style templates from the source's definitions.
539
+ */
540
+ getStylesModel() {
541
+ return parseStylesXml(this.stylesXml);
542
+ }
503
543
  buildDocumentView(opts) {
504
544
  const includeSemanticTags = opts?.includeSemanticTags ?? true;
505
545
  const showFormatting = opts?.showFormatting ?? false;
@@ -991,23 +1031,49 @@ export class DocxDocument {
991
1031
  return null;
992
1032
  return parseXml(commentsText);
993
1033
  }
1034
+ /**
1035
+ * Serialize the document to a .docx buffer.
1036
+ *
1037
+ * With `minimalReserialization` (requires `cleanBookmarks`), top-level body
1038
+ * blocks that no edit touched are restored element-for-element from the
1039
+ * original document.xml instead of carrying the open-time normalization
1040
+ * (proofErr stripping, run merging) to disk — so output diffs reflect the
1041
+ * actual edit blast radius. Edited/inserted blocks are emitted as-is.
1042
+ * Falls back to full re-serialization (blocksRestored: 0) when no original
1043
+ * text was captured or reconciliation fails.
1044
+ *
1045
+ * @see https://github.com/UseJunior/safe-docx/issues/408
1046
+ */
994
1047
  async toBuffer(opts) {
995
1048
  // Always write the latest document.xml when saving.
996
1049
  // Important: when cleanBookmarks=true (download), we must NOT mutate session state.
997
1050
  const xmlWithBookmarks = serializeXml(this.documentXml);
1051
+ maybeCaptureEmittedDocumentXml(xmlWithBookmarks);
998
1052
  this.zip.writeText('word/document.xml', xmlWithBookmarks);
999
1053
  if (opts?.cleanBookmarks) {
1000
1054
  const cloned = parseXml(xmlWithBookmarks);
1001
1055
  const bookmarksRemoved = cleanupInternalBookmarks(cloned);
1056
+ let blocksRestored = 0;
1057
+ if (opts.minimalReserialization && this.originalDocumentXmlText !== null) {
1058
+ try {
1059
+ blocksRestored = restoreUntouchedBlocks(cloned, this.originalDocumentXmlText);
1060
+ }
1061
+ catch {
1062
+ // Reconciliation is best-effort; the fully re-serialized DOM is
1063
+ // always a correct (if non-minimal) save.
1064
+ blocksRestored = 0;
1065
+ }
1066
+ }
1002
1067
  const cleanedXml = serializeXml(cloned);
1003
1068
  // Temporarily swap document.xml in the zip for output, then restore.
1069
+ maybeCaptureEmittedDocumentXml(cleanedXml);
1004
1070
  this.zip.writeText('word/document.xml', cleanedXml);
1005
1071
  const buffer = await this.zip.toBuffer();
1006
1072
  this.zip.writeText('word/document.xml', xmlWithBookmarks);
1007
- return { buffer, bookmarksRemoved };
1073
+ return { buffer, bookmarksRemoved, blocksRestored };
1008
1074
  }
1009
1075
  const buffer = await this.zip.toBuffer();
1010
- return { buffer, bookmarksRemoved: 0 };
1076
+ return { buffer, bookmarksRemoved: 0, blocksRestored: 0 };
1011
1077
  }
1012
1078
  }
1013
1079
  //# sourceMappingURL=document.js.map