docxmlater 10.0.2 → 10.0.3

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 (393) hide show
  1. package/README.md +2 -2
  2. package/dist/constants/legacyCompatFlags.d.ts.map +1 -1
  3. package/dist/constants/legacyCompatFlags.js.map +1 -1
  4. package/dist/constants/limits.d.ts +0 -27
  5. package/dist/constants/limits.d.ts.map +1 -1
  6. package/dist/constants/limits.js +13 -13
  7. package/dist/constants/limits.js.map +1 -1
  8. package/dist/core/Document.d.ts +23 -19
  9. package/dist/core/Document.d.ts.map +1 -1
  10. package/dist/core/Document.js +197 -63
  11. package/dist/core/Document.js.map +1 -1
  12. package/dist/core/DocumentContent.d.ts.map +1 -1
  13. package/dist/core/DocumentContent.js.map +1 -1
  14. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  15. package/dist/core/DocumentGenerator.js +59 -24
  16. package/dist/core/DocumentGenerator.js.map +1 -1
  17. package/dist/core/DocumentIdManager.d.ts.map +1 -1
  18. package/dist/core/DocumentIdManager.js.map +1 -1
  19. package/dist/core/DocumentParser.d.ts +6 -6
  20. package/dist/core/DocumentParser.d.ts.map +1 -1
  21. package/dist/core/DocumentParser.js +60 -54
  22. package/dist/core/DocumentParser.js.map +1 -1
  23. package/dist/core/DocumentValidator.d.ts.map +1 -1
  24. package/dist/core/DocumentValidator.js.map +1 -1
  25. package/dist/core/Relationship.d.ts.map +1 -1
  26. package/dist/core/Relationship.js +1 -1
  27. package/dist/core/Relationship.js.map +1 -1
  28. package/dist/core/RelationshipManager.js +3 -3
  29. package/dist/core/RelationshipManager.js.map +1 -1
  30. package/dist/elements/AlternateContent.js.map +1 -1
  31. package/dist/elements/Bookmark.d.ts.map +1 -1
  32. package/dist/elements/Bookmark.js.map +1 -1
  33. package/dist/elements/BookmarkManager.d.ts.map +1 -1
  34. package/dist/elements/BookmarkManager.js.map +1 -1
  35. package/dist/elements/Comment.js +1 -1
  36. package/dist/elements/Comment.js.map +1 -1
  37. package/dist/elements/CommentManager.d.ts.map +1 -1
  38. package/dist/elements/CommentManager.js +8 -2
  39. package/dist/elements/CommentManager.js.map +1 -1
  40. package/dist/elements/CommonTypes.d.ts.map +1 -1
  41. package/dist/elements/CommonTypes.js +1 -2
  42. package/dist/elements/CommonTypes.js.map +1 -1
  43. package/dist/elements/CustomXml.js.map +1 -1
  44. package/dist/elements/Endnote.d.ts.map +1 -1
  45. package/dist/elements/Endnote.js.map +1 -1
  46. package/dist/elements/EndnoteManager.d.ts.map +1 -1
  47. package/dist/elements/EndnoteManager.js.map +1 -1
  48. package/dist/elements/Field.d.ts.map +1 -1
  49. package/dist/elements/Field.js +31 -28
  50. package/dist/elements/Field.js.map +1 -1
  51. package/dist/elements/FieldHelpers.d.ts.map +1 -1
  52. package/dist/elements/FieldHelpers.js +6 -6
  53. package/dist/elements/FieldHelpers.js.map +1 -1
  54. package/dist/elements/FontManager.d.ts.map +1 -1
  55. package/dist/elements/FontManager.js.map +1 -1
  56. package/dist/elements/Footer.js.map +1 -1
  57. package/dist/elements/Footnote.d.ts.map +1 -1
  58. package/dist/elements/Footnote.js.map +1 -1
  59. package/dist/elements/FootnoteManager.d.ts.map +1 -1
  60. package/dist/elements/FootnoteManager.js.map +1 -1
  61. package/dist/elements/Header.js.map +1 -1
  62. package/dist/elements/HeaderFooterManager.js.map +1 -1
  63. package/dist/elements/Hyperlink.d.ts.map +1 -1
  64. package/dist/elements/Hyperlink.js +5 -5
  65. package/dist/elements/Hyperlink.js.map +1 -1
  66. package/dist/elements/Image.d.ts +2 -2
  67. package/dist/elements/Image.d.ts.map +1 -1
  68. package/dist/elements/Image.js +21 -5
  69. package/dist/elements/Image.js.map +1 -1
  70. package/dist/elements/ImageManager.d.ts.map +1 -1
  71. package/dist/elements/ImageManager.js +2 -2
  72. package/dist/elements/ImageManager.js.map +1 -1
  73. package/dist/elements/ImageRun.js.map +1 -1
  74. package/dist/elements/MathElement.js.map +1 -1
  75. package/dist/elements/Paragraph.d.ts.map +1 -1
  76. package/dist/elements/Paragraph.js +128 -117
  77. package/dist/elements/Paragraph.js.map +1 -1
  78. package/dist/elements/PreservedElement.js.map +1 -1
  79. package/dist/elements/PropertyChangeTypes.js.map +1 -1
  80. package/dist/elements/RangeMarker.js.map +1 -1
  81. package/dist/elements/Revision.d.ts +1 -0
  82. package/dist/elements/Revision.d.ts.map +1 -1
  83. package/dist/elements/Revision.js +44 -5
  84. package/dist/elements/Revision.js.map +1 -1
  85. package/dist/elements/RevisionContent.js.map +1 -1
  86. package/dist/elements/RevisionManager.d.ts.map +1 -1
  87. package/dist/elements/RevisionManager.js.map +1 -1
  88. package/dist/elements/Run.d.ts.map +1 -1
  89. package/dist/elements/Run.js +1 -3
  90. package/dist/elements/Run.js.map +1 -1
  91. package/dist/elements/Section.d.ts.map +1 -1
  92. package/dist/elements/Section.js +127 -118
  93. package/dist/elements/Section.js.map +1 -1
  94. package/dist/elements/Shape.d.ts.map +1 -1
  95. package/dist/elements/Shape.js +21 -0
  96. package/dist/elements/Shape.js.map +1 -1
  97. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  98. package/dist/elements/StructuredDocumentTag.js +20 -8
  99. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  100. package/dist/elements/Table.d.ts +2 -2
  101. package/dist/elements/Table.d.ts.map +1 -1
  102. package/dist/elements/Table.js +29 -35
  103. package/dist/elements/Table.js.map +1 -1
  104. package/dist/elements/TableCell.d.ts +2 -2
  105. package/dist/elements/TableCell.d.ts.map +1 -1
  106. package/dist/elements/TableCell.js +63 -67
  107. package/dist/elements/TableCell.js.map +1 -1
  108. package/dist/elements/TableGridChange.js.map +1 -1
  109. package/dist/elements/TableOfContents.d.ts +6 -6
  110. package/dist/elements/TableOfContents.d.ts.map +1 -1
  111. package/dist/elements/TableOfContents.js.map +1 -1
  112. package/dist/elements/TableOfContentsElement.js.map +1 -1
  113. package/dist/elements/TableRow.d.ts.map +1 -1
  114. package/dist/elements/TableRow.js +65 -47
  115. package/dist/elements/TableRow.js.map +1 -1
  116. package/dist/elements/TextBox.d.ts.map +1 -1
  117. package/dist/elements/TextBox.js +1 -1
  118. package/dist/elements/TextBox.js.map +1 -1
  119. package/dist/formatting/AbstractNumbering.d.ts +1 -1
  120. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  121. package/dist/formatting/AbstractNumbering.js +11 -11
  122. package/dist/formatting/AbstractNumbering.js.map +1 -1
  123. package/dist/formatting/NumberingInstance.d.ts.map +1 -1
  124. package/dist/formatting/NumberingInstance.js +4 -4
  125. package/dist/formatting/NumberingInstance.js.map +1 -1
  126. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  127. package/dist/formatting/NumberingLevel.js +26 -26
  128. package/dist/formatting/NumberingLevel.js.map +1 -1
  129. package/dist/formatting/NumberingManager.d.ts +1 -1
  130. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  131. package/dist/formatting/NumberingManager.js.map +1 -1
  132. package/dist/formatting/Style.d.ts.map +1 -1
  133. package/dist/formatting/Style.js +87 -95
  134. package/dist/formatting/Style.js.map +1 -1
  135. package/dist/formatting/StylesManager.d.ts +3 -3
  136. package/dist/formatting/StylesManager.d.ts.map +1 -1
  137. package/dist/formatting/StylesManager.js.map +1 -1
  138. package/dist/helpers/CleanupHelper.js.map +1 -1
  139. package/dist/images/ImageOptimizer.js.map +1 -1
  140. package/dist/index.js.map +1 -1
  141. package/dist/managers/DrawingManager.d.ts.map +1 -1
  142. package/dist/managers/DrawingManager.js.map +1 -1
  143. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  144. package/dist/tracking/TrackingContext.js.map +1 -1
  145. package/dist/types/compatibility-types.js.map +1 -1
  146. package/dist/types/formatting.js.map +1 -1
  147. package/dist/types/list-types.d.ts +4 -4
  148. package/dist/types/list-types.d.ts.map +1 -1
  149. package/dist/types/list-types.js.map +1 -1
  150. package/dist/types/settings-types.js.map +1 -1
  151. package/dist/types/styleConfig.js.map +1 -1
  152. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  153. package/dist/utils/ChangelogGenerator.js.map +1 -1
  154. package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
  155. package/dist/utils/CompatibilityUpgrader.js +7 -7
  156. package/dist/utils/CompatibilityUpgrader.js.map +1 -1
  157. package/dist/utils/InMemoryRevisionAcceptor.js +1 -1
  158. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  159. package/dist/utils/MoveOperationHelper.js.map +1 -1
  160. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  161. package/dist/utils/RevisionWalker.js.map +1 -1
  162. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  163. package/dist/utils/ShadingResolver.js +1 -1
  164. package/dist/utils/ShadingResolver.js.map +1 -1
  165. package/dist/utils/acceptRevisions.d.ts +0 -28
  166. package/dist/utils/acceptRevisions.d.ts.map +1 -1
  167. package/dist/utils/acceptRevisions.js +5 -7
  168. package/dist/utils/acceptRevisions.js.map +1 -1
  169. package/dist/utils/cnfStyleDecoder.js +1 -1
  170. package/dist/utils/cnfStyleDecoder.js.map +1 -1
  171. package/dist/utils/corruptionDetection.js.map +1 -1
  172. package/dist/utils/dateFormatting.js.map +1 -1
  173. package/dist/utils/deepClone.d.ts +0 -1
  174. package/dist/utils/deepClone.d.ts.map +1 -1
  175. package/dist/utils/deepClone.js +0 -7
  176. package/dist/utils/deepClone.js.map +1 -1
  177. package/dist/utils/diagnostics.d.ts +2 -2
  178. package/dist/utils/diagnostics.d.ts.map +1 -1
  179. package/dist/utils/diagnostics.js.map +1 -1
  180. package/dist/utils/errorHandling.js.map +1 -1
  181. package/dist/utils/formatting.js.map +1 -1
  182. package/dist/utils/list-detection.d.ts +2 -2
  183. package/dist/utils/list-detection.d.ts.map +1 -1
  184. package/dist/utils/list-detection.js +3 -3
  185. package/dist/utils/list-detection.js.map +1 -1
  186. package/dist/utils/logger.d.ts +2 -4
  187. package/dist/utils/logger.d.ts.map +1 -1
  188. package/dist/utils/logger.js +0 -2
  189. package/dist/utils/logger.js.map +1 -1
  190. package/dist/utils/parsingHelpers.js.map +1 -1
  191. package/dist/utils/stripTrackedChanges.d.ts +0 -19
  192. package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
  193. package/dist/utils/stripTrackedChanges.js +0 -2
  194. package/dist/utils/stripTrackedChanges.js.map +1 -1
  195. package/dist/utils/textDiff.js.map +1 -1
  196. package/dist/utils/units.js.map +1 -1
  197. package/dist/utils/validation.d.ts.map +1 -1
  198. package/dist/utils/validation.js.map +1 -1
  199. package/dist/utils/xmlSanitization.js.map +1 -1
  200. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  201. package/dist/validation/RevisionValidator.js.map +1 -1
  202. package/dist/validation/ValidationRules.js.map +1 -1
  203. package/dist/validation/index.js.map +1 -1
  204. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  205. package/dist/xml/XMLBuilder.js +10 -0
  206. package/dist/xml/XMLBuilder.js.map +1 -1
  207. package/dist/xml/XMLParser.d.ts.map +1 -1
  208. package/dist/xml/XMLParser.js +4 -5
  209. package/dist/xml/XMLParser.js.map +1 -1
  210. package/dist/zip/ZipHandler.js.map +1 -1
  211. package/dist/zip/ZipReader.js.map +1 -1
  212. package/dist/zip/ZipWriter.js.map +1 -1
  213. package/dist/zip/errors.js.map +1 -1
  214. package/dist/zip/types.js.map +1 -1
  215. package/package.json +34 -4
  216. package/src/__tests__/helper-methods.test.ts +512 -0
  217. package/src/constants/legacyCompatFlags.ts +138 -0
  218. package/src/constants/limits.ts +50 -0
  219. package/src/core/CLAUDE.md +109 -0
  220. package/src/core/Document.ts +15569 -0
  221. package/src/core/DocumentContent.ts +467 -0
  222. package/src/core/DocumentGenerator.ts +1104 -0
  223. package/src/core/DocumentIdManager.ts +158 -0
  224. package/src/core/DocumentParser.ts +10107 -0
  225. package/src/core/DocumentValidator.ts +372 -0
  226. package/src/core/Relationship.ts +367 -0
  227. package/src/core/RelationshipManager.ts +428 -0
  228. package/src/elements/AlternateContent.ts +42 -0
  229. package/src/elements/Bookmark.ts +210 -0
  230. package/src/elements/BookmarkManager.ts +250 -0
  231. package/src/elements/CLAUDE.md +126 -0
  232. package/src/elements/Comment.ts +359 -0
  233. package/src/elements/CommentManager.ts +502 -0
  234. package/src/elements/CommonTypes.ts +549 -0
  235. package/src/elements/CustomXml.ts +36 -0
  236. package/src/elements/Endnote.ts +217 -0
  237. package/src/elements/EndnoteManager.ts +249 -0
  238. package/src/elements/Field.ts +1233 -0
  239. package/src/elements/FieldHelpers.ts +333 -0
  240. package/src/elements/FontManager.ts +339 -0
  241. package/src/elements/Footer.ts +269 -0
  242. package/src/elements/Footnote.ts +217 -0
  243. package/src/elements/FootnoteManager.ts +249 -0
  244. package/src/elements/Header.ts +269 -0
  245. package/src/elements/HeaderFooterManager.ts +219 -0
  246. package/src/elements/Hyperlink.ts +1146 -0
  247. package/src/elements/Image.ts +1756 -0
  248. package/src/elements/ImageManager.ts +432 -0
  249. package/src/elements/ImageRun.ts +59 -0
  250. package/src/elements/MathElement.ts +65 -0
  251. package/src/elements/Paragraph.ts +4227 -0
  252. package/src/elements/PreservedElement.ts +53 -0
  253. package/src/elements/PropertyChangeTypes.ts +442 -0
  254. package/src/elements/RangeMarker.ts +400 -0
  255. package/src/elements/Revision.ts +1217 -0
  256. package/src/elements/RevisionContent.ts +73 -0
  257. package/src/elements/RevisionManager.ts +1070 -0
  258. package/src/elements/Run.ts +3068 -0
  259. package/src/elements/Section.ts +1421 -0
  260. package/src/elements/Shape.ts +873 -0
  261. package/src/elements/StructuredDocumentTag.ts +978 -0
  262. package/src/elements/Table.ts +2524 -0
  263. package/src/elements/TableCell.ts +1586 -0
  264. package/src/elements/TableGridChange.ts +151 -0
  265. package/src/elements/TableOfContents.ts +691 -0
  266. package/src/elements/TableOfContentsElement.ts +89 -0
  267. package/src/elements/TableRow.ts +906 -0
  268. package/src/elements/TextBox.ts +768 -0
  269. package/src/formatting/AbstractNumbering.ts +548 -0
  270. package/src/formatting/CLAUDE.md +74 -0
  271. package/src/formatting/NumberingInstance.ts +212 -0
  272. package/src/formatting/NumberingLevel.ts +1006 -0
  273. package/src/formatting/NumberingManager.ts +827 -0
  274. package/src/formatting/Style.ts +1833 -0
  275. package/src/formatting/StylesManager.ts +1005 -0
  276. package/src/helpers/CleanupHelper.ts +524 -0
  277. package/src/images/ImageOptimizer.ts +274 -0
  278. package/src/index.ts +554 -0
  279. package/src/managers/CLAUDE.md +47 -0
  280. package/src/managers/DrawingManager.ts +319 -0
  281. package/src/tracking/DocumentTrackingContext.ts +643 -0
  282. package/src/tracking/TrackingContext.ts +173 -0
  283. package/src/types/compatibility-types.ts +49 -0
  284. package/src/types/formatting.ts +210 -0
  285. package/src/types/list-types.ts +152 -0
  286. package/src/types/settings-types.ts +59 -0
  287. package/src/types/styleConfig.ts +189 -0
  288. package/src/utils/CLAUDE.md +153 -0
  289. package/src/utils/ChangelogGenerator.ts +1581 -0
  290. package/src/utils/CompatibilityUpgrader.ts +237 -0
  291. package/src/utils/InMemoryRevisionAcceptor.ts +668 -0
  292. package/src/utils/MoveOperationHelper.ts +238 -0
  293. package/src/utils/RevisionAwareProcessor.ts +526 -0
  294. package/src/utils/RevisionWalker.ts +457 -0
  295. package/src/utils/SelectiveRevisionAcceptor.ts +613 -0
  296. package/src/utils/ShadingResolver.ts +107 -0
  297. package/src/utils/acceptRevisions.ts +714 -0
  298. package/src/utils/cnfStyleDecoder.ts +217 -0
  299. package/src/utils/corruptionDetection.ts +345 -0
  300. package/src/utils/dateFormatting.ts +20 -0
  301. package/src/utils/deepClone.ts +78 -0
  302. package/src/utils/diagnostics.ts +129 -0
  303. package/src/utils/errorHandling.ts +80 -0
  304. package/src/utils/formatting.ts +213 -0
  305. package/src/utils/list-detection.ts +274 -0
  306. package/src/utils/logger.ts +404 -0
  307. package/src/utils/parsingHelpers.ts +190 -0
  308. package/src/utils/stripTrackedChanges.ts +353 -0
  309. package/src/utils/textDiff.ts +100 -0
  310. package/src/utils/units.ts +421 -0
  311. package/src/utils/validation.ts +542 -0
  312. package/src/utils/xmlSanitization.ts +182 -0
  313. package/src/validation/RevisionAutoFixer.ts +542 -0
  314. package/src/validation/RevisionValidator.ts +460 -0
  315. package/src/validation/ValidationRules.ts +338 -0
  316. package/src/validation/index.ts +30 -0
  317. package/src/xml/CLAUDE.md +65 -0
  318. package/src/xml/XMLBuilder.ts +871 -0
  319. package/src/xml/XMLParser.ts +919 -0
  320. package/src/zip/CLAUDE.md +55 -0
  321. package/src/zip/ZipHandler.ts +637 -0
  322. package/src/zip/ZipReader.ts +299 -0
  323. package/src/zip/ZipWriter.ts +390 -0
  324. package/src/zip/errors.ts +69 -0
  325. package/src/zip/types.ts +116 -0
  326. package/dist/core/ListNormalizer.d.ts +0 -23
  327. package/dist/core/ListNormalizer.d.ts.map +0 -1
  328. package/dist/core/ListNormalizer.js +0 -624
  329. package/dist/core/ListNormalizer.js.map +0 -1
  330. package/dist/images/index.d.ts +0 -2
  331. package/dist/images/index.d.ts.map +0 -1
  332. package/dist/images/index.js +0 -8
  333. package/dist/images/index.js.map +0 -1
  334. package/dist/ms-doc/cfb/CFBReader.d.ts +0 -35
  335. package/dist/ms-doc/cfb/CFBReader.d.ts.map +0 -1
  336. package/dist/ms-doc/cfb/CFBReader.js +0 -360
  337. package/dist/ms-doc/cfb/CFBReader.js.map +0 -1
  338. package/dist/ms-doc/converter/DocToDocxConverter.d.ts +0 -55
  339. package/dist/ms-doc/converter/DocToDocxConverter.d.ts.map +0 -1
  340. package/dist/ms-doc/converter/DocToDocxConverter.js +0 -324
  341. package/dist/ms-doc/converter/DocToDocxConverter.js.map +0 -1
  342. package/dist/ms-doc/fib/FIB.d.ts +0 -18
  343. package/dist/ms-doc/fib/FIB.d.ts.map +0 -1
  344. package/dist/ms-doc/fib/FIB.js +0 -342
  345. package/dist/ms-doc/fib/FIB.js.map +0 -1
  346. package/dist/ms-doc/fields/FieldParser.d.ts +0 -31
  347. package/dist/ms-doc/fields/FieldParser.d.ts.map +0 -1
  348. package/dist/ms-doc/fields/FieldParser.js +0 -266
  349. package/dist/ms-doc/fields/FieldParser.js.map +0 -1
  350. package/dist/ms-doc/images/PictureExtractor.d.ts +0 -22
  351. package/dist/ms-doc/images/PictureExtractor.d.ts.map +0 -1
  352. package/dist/ms-doc/images/PictureExtractor.js +0 -233
  353. package/dist/ms-doc/images/PictureExtractor.js.map +0 -1
  354. package/dist/ms-doc/index.d.ts +0 -20
  355. package/dist/ms-doc/index.d.ts.map +0 -1
  356. package/dist/ms-doc/index.js +0 -59
  357. package/dist/ms-doc/index.js.map +0 -1
  358. package/dist/ms-doc/properties/SPRM.d.ts +0 -210
  359. package/dist/ms-doc/properties/SPRM.d.ts.map +0 -1
  360. package/dist/ms-doc/properties/SPRM.js +0 -633
  361. package/dist/ms-doc/properties/SPRM.js.map +0 -1
  362. package/dist/ms-doc/sections/SectionParser.d.ts +0 -25
  363. package/dist/ms-doc/sections/SectionParser.d.ts.map +0 -1
  364. package/dist/ms-doc/sections/SectionParser.js +0 -214
  365. package/dist/ms-doc/sections/SectionParser.js.map +0 -1
  366. package/dist/ms-doc/styles/StyleSheet.d.ts +0 -23
  367. package/dist/ms-doc/styles/StyleSheet.d.ts.map +0 -1
  368. package/dist/ms-doc/styles/StyleSheet.js +0 -268
  369. package/dist/ms-doc/styles/StyleSheet.js.map +0 -1
  370. package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts +0 -61
  371. package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts.map +0 -1
  372. package/dist/ms-doc/subdocuments/SubdocumentParser.js +0 -208
  373. package/dist/ms-doc/subdocuments/SubdocumentParser.js.map +0 -1
  374. package/dist/ms-doc/tables/TableParser.d.ts +0 -29
  375. package/dist/ms-doc/tables/TableParser.d.ts.map +0 -1
  376. package/dist/ms-doc/tables/TableParser.js +0 -176
  377. package/dist/ms-doc/tables/TableParser.js.map +0 -1
  378. package/dist/ms-doc/text/PieceTable.d.ts +0 -21
  379. package/dist/ms-doc/text/PieceTable.d.ts.map +0 -1
  380. package/dist/ms-doc/text/PieceTable.js +0 -171
  381. package/dist/ms-doc/text/PieceTable.js.map +0 -1
  382. package/dist/ms-doc/types/Constants.d.ts +0 -99
  383. package/dist/ms-doc/types/Constants.d.ts.map +0 -1
  384. package/dist/ms-doc/types/Constants.js +0 -102
  385. package/dist/ms-doc/types/Constants.js.map +0 -1
  386. package/dist/ms-doc/types/DocTypes.d.ts +0 -368
  387. package/dist/ms-doc/types/DocTypes.d.ts.map +0 -1
  388. package/dist/ms-doc/types/DocTypes.js +0 -3
  389. package/dist/ms-doc/types/DocTypes.js.map +0 -1
  390. package/dist/tracking/index.d.ts +0 -3
  391. package/dist/tracking/index.d.ts.map +0 -1
  392. package/dist/tracking/index.js +0 -6
  393. package/dist/tracking/index.js.map +0 -1
@@ -0,0 +1,668 @@
1
+ /**
2
+ * InMemoryRevisionAcceptor - Accept revisions by transforming the in-memory object model
3
+ *
4
+ * This approach follows the industry standard (OpenXML PowerTools, Aspose.Words):
5
+ * - Transforms Revision objects in paragraph.content[] to their "accepted" state
6
+ * - For insertions: Unwrap - extract child Runs/Hyperlinks into parent paragraph
7
+ * - For deletions: Remove - delete the revision and its content from the model
8
+ * - For property changes: Remove the change metadata, keep the current formatting
9
+ *
10
+ * Unlike the raw XML approach (acceptRevisions.ts), this allows subsequent modifications
11
+ * to the in-memory model to be correctly serialized on save().
12
+ *
13
+ * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs
14
+ * @see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/ee836138(v=office.12)
15
+ */
16
+
17
+ import type { Document } from '../core/Document';
18
+ import { Paragraph } from '../elements/Paragraph';
19
+ import type { ParagraphContent } from '../elements/Paragraph';
20
+ import { Revision, RevisionType } from '../elements/Revision';
21
+ import type { Run } from '../elements/Run';
22
+ import type { Hyperlink } from '../elements/Hyperlink';
23
+ import { isRunContent, isHyperlinkContent, isImageRunContent } from '../elements/RevisionContent';
24
+ import type { ImageRun } from '../elements/ImageRun';
25
+ import { Table } from '../elements/Table';
26
+ import { Section } from '../elements/Section';
27
+ import { getGlobalLogger, createScopedLogger, ILogger } from './logger';
28
+
29
+ /**
30
+ * Get scoped logger for this module
31
+ */
32
+ function getLogger(): ILogger {
33
+ return createScopedLogger(getGlobalLogger(), 'InMemoryRevisionAcceptor');
34
+ }
35
+
36
+ /**
37
+ * Options for accepting revisions
38
+ */
39
+ export interface AcceptRevisionsOptions {
40
+ /** Accept insertion revisions (w:ins) - default: true */
41
+ acceptInsertions?: boolean;
42
+ /** Accept deletion revisions (w:del) - default: true */
43
+ acceptDeletions?: boolean;
44
+ /** Accept move operations (w:moveFrom, w:moveTo) - default: true */
45
+ acceptMoves?: boolean;
46
+ /** Accept property change revisions (rPrChange, pPrChange, etc.) - default: true */
47
+ acceptPropertyChanges?: boolean;
48
+ /** Remove empty tables after revision acceptance - default: true */
49
+ cleanupEmptyTables?: boolean;
50
+ }
51
+
52
+ /**
53
+ * Result of accepting revisions
54
+ */
55
+ export interface AcceptRevisionsResult {
56
+ /** Number of insertions accepted */
57
+ insertionsAccepted: number;
58
+ /** Number of deletions accepted */
59
+ deletionsAccepted: number;
60
+ /** Number of move operations accepted */
61
+ movesAccepted: number;
62
+ /** Number of property changes accepted */
63
+ propertyChangesAccepted: number;
64
+ /** Total revisions processed */
65
+ totalAccepted: number;
66
+ /** Number of empty tables removed during cleanup */
67
+ emptyTablesRemoved: number;
68
+ }
69
+
70
+ /**
71
+ * Revision types that represent content changes (contain actual text/runs)
72
+ */
73
+ const CONTENT_REVISION_TYPES: RevisionType[] = [
74
+ 'insert',
75
+ 'delete',
76
+ 'moveFrom',
77
+ 'moveTo',
78
+ ];
79
+
80
+ /**
81
+ * Revision types that represent property/formatting changes
82
+ */
83
+ const PROPERTY_REVISION_TYPES: RevisionType[] = [
84
+ 'runPropertiesChange',
85
+ 'paragraphPropertiesChange',
86
+ 'tablePropertiesChange',
87
+ 'tableExceptionPropertiesChange',
88
+ 'tableRowPropertiesChange',
89
+ 'tableCellPropertiesChange',
90
+ 'sectionPropertiesChange',
91
+ 'numberingChange',
92
+ ];
93
+
94
+ /**
95
+ * Strip revision markup from raw XML string.
96
+ * Used for nested tables stored as raw XML that cannot be processed via the in-memory model.
97
+ *
98
+ * Follows the same rules as the main revision acceptor:
99
+ * - Insertions: Keep content, remove wrapper tags
100
+ * - Deletions: Remove entirely (content and tags)
101
+ * - MoveFrom: Remove entirely (source of move)
102
+ * - MoveTo: Keep content, remove wrapper
103
+ * - Property changes: Remove change tracking elements
104
+ * - Range markers: Remove boundary markers
105
+ *
106
+ * @param xml - Raw XML string containing revision markup
107
+ * @returns Cleaned XML with revisions accepted
108
+ */
109
+ export function stripRevisionsFromXml(xml: string): string {
110
+ let result = xml;
111
+
112
+ // Step 1: Remove range markers (must be done first)
113
+ const rangePatterns = [
114
+ /<w:moveFromRangeStart[^>]*(?:\/>|>.*?<\/w:moveFromRangeStart>)/gs,
115
+ /<w:moveFromRangeEnd[^>]*(?:\/>|>.*?<\/w:moveFromRangeEnd>)/gs,
116
+ /<w:moveToRangeStart[^>]*(?:\/>|>.*?<\/w:moveToRangeStart>)/gs,
117
+ /<w:moveToRangeEnd[^>]*(?:\/>|>.*?<\/w:moveToRangeEnd>)/gs,
118
+ /<w:customXmlInsRangeStart[^>]*(?:\/>|>.*?<\/w:customXmlInsRangeStart>)/gs,
119
+ /<w:customXmlInsRangeEnd[^>]*(?:\/>|>.*?<\/w:customXmlInsRangeEnd>)/gs,
120
+ /<w:customXmlDelRangeStart[^>]*(?:\/>|>.*?<\/w:customXmlDelRangeStart>)/gs,
121
+ /<w:customXmlDelRangeEnd[^>]*(?:\/>|>.*?<\/w:customXmlDelRangeEnd>)/gs,
122
+ ];
123
+ for (const pattern of rangePatterns) {
124
+ result = result.replace(pattern, '');
125
+ }
126
+
127
+ // Step 2: Remove property change elements
128
+ const propChangePatterns = [
129
+ /<w:rPrChange[^>]*>[\s\S]*?<\/w:rPrChange>/g,
130
+ /<w:pPrChange[^>]*>[\s\S]*?<\/w:pPrChange>/g,
131
+ /<w:tblPrChange[^>]*>[\s\S]*?<\/w:tblPrChange>/g,
132
+ /<w:tblPrExChange[^>]*>[\s\S]*?<\/w:tblPrExChange>/g,
133
+ /<w:tcPrChange[^>]*>[\s\S]*?<\/w:tcPrChange>/g,
134
+ /<w:trPrChange[^>]*>[\s\S]*?<\/w:trPrChange>/g,
135
+ /<w:sectPrChange[^>]*>[\s\S]*?<\/w:sectPrChange>/g,
136
+ /<w:tblGridChange[^>]*>[\s\S]*?<\/w:tblGridChange>/g,
137
+ /<w:numberingChange[^>]*>[\s\S]*?<\/w:numberingChange>/g,
138
+ ];
139
+ for (const pattern of propChangePatterns) {
140
+ result = result.replace(pattern, '');
141
+ }
142
+
143
+ // Step 3: Remove deletions entirely (including content)
144
+ // Iterate until no more deletions (handles nested cases)
145
+ let prevLen = 0;
146
+ while (result.length !== prevLen) {
147
+ prevLen = result.length;
148
+ result = result.replace(/<w:del\b[^>]*>[\s\S]*?<\/w:del>/g, '');
149
+ }
150
+ result = result.replace(/<w:del\b[^>]*\/>/g, '');
151
+
152
+ // Step 4: Remove moveFrom entirely (source of moved content)
153
+ prevLen = 0;
154
+ while (result.length !== prevLen) {
155
+ prevLen = result.length;
156
+ result = result.replace(/<w:moveFrom\b[^>]*>[\s\S]*?<\/w:moveFrom>/g, '');
157
+ }
158
+ result = result.replace(/<w:moveFrom\b[^>]*\/>/g, '');
159
+
160
+ // Step 5: Unwrap moveTo (keep content, remove wrapper)
161
+ result = result.replace(/<\/w:moveTo>/g, '');
162
+ result = result.replace(/<w:moveTo\b[^>]*>/g, '');
163
+
164
+ // Step 6: Unwrap insertions (keep content, remove wrapper)
165
+ result = result.replace(/<\/w:ins>/g, '');
166
+ result = result.replace(/<w:ins\b[^>]*>/g, '');
167
+
168
+ // Step 7: Clean up orphaned tags
169
+ result = result.replace(/<w:ins\b[^>]*\/>/g, '');
170
+ result = result.replace(/<w:del\b[^>]*\/>/g, '');
171
+ result = result.replace(/<w:moveFrom\b[^>]*\/>/g, '');
172
+ result = result.replace(/<w:moveTo\b[^>]*\/>/g, '');
173
+
174
+ return result;
175
+ }
176
+
177
+ /**
178
+ * Accept all revisions in the document by transforming the in-memory model.
179
+ *
180
+ * This is the industry-standard approach used by OpenXML PowerTools, Aspose.Words,
181
+ * and other production DOCX libraries. It allows subsequent modifications to the
182
+ * document to work correctly.
183
+ *
184
+ * @param doc - Document to process
185
+ * @param options - Options for which revision types to accept
186
+ * @returns Result with counts of accepted revisions
187
+ */
188
+ export function acceptRevisionsInMemory(
189
+ doc: Document,
190
+ options: AcceptRevisionsOptions = {}
191
+ ): AcceptRevisionsResult {
192
+ const logger = getLogger();
193
+ const opts: Required<AcceptRevisionsOptions> = {
194
+ acceptInsertions: options.acceptInsertions ?? true,
195
+ acceptDeletions: options.acceptDeletions ?? true,
196
+ acceptMoves: options.acceptMoves ?? true,
197
+ acceptPropertyChanges: options.acceptPropertyChanges ?? true,
198
+ cleanupEmptyTables: options.cleanupEmptyTables ?? true,
199
+ };
200
+
201
+ const result: AcceptRevisionsResult = {
202
+ insertionsAccepted: 0,
203
+ deletionsAccepted: 0,
204
+ movesAccepted: 0,
205
+ propertyChangesAccepted: 0,
206
+ totalAccepted: 0,
207
+ emptyTablesRemoved: 0,
208
+ };
209
+
210
+ logger.info('Accepting revisions in-memory', { options: opts });
211
+
212
+ // Validate move pairs before accepting if moves are being accepted
213
+ // Orphaned moves could result in content loss (moveFrom without moveTo = content deleted)
214
+ if (opts.acceptMoves) {
215
+ const revisionManager = doc.getRevisionManager();
216
+ if (revisionManager) {
217
+ const movePairValidation = revisionManager.validateMovePairs();
218
+ if (!movePairValidation.valid) {
219
+ if (movePairValidation.orphanedMoveFrom.length > 0) {
220
+ logger.warn(
221
+ 'Orphaned moveFrom revisions detected - accepting these will DELETE content permanently ' +
222
+ '(content was moved from here but no moveTo destination exists)',
223
+ { orphanedMoveIds: movePairValidation.orphanedMoveFrom }
224
+ );
225
+ }
226
+ if (movePairValidation.orphanedMoveTo.length > 0) {
227
+ logger.warn(
228
+ 'Orphaned moveTo revisions detected - content may be duplicated ' +
229
+ '(content moved to here but no moveFrom source exists)',
230
+ { orphanedMoveIds: movePairValidation.orphanedMoveTo }
231
+ );
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ // Process all paragraphs in the document body
238
+ const paragraphs = doc.getAllParagraphs();
239
+ for (const paragraph of paragraphs) {
240
+ const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);
241
+ result.insertionsAccepted += paragraphResult.insertionsAccepted;
242
+ result.deletionsAccepted += paragraphResult.deletionsAccepted;
243
+ result.movesAccepted += paragraphResult.movesAccepted;
244
+ result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;
245
+ }
246
+
247
+ // Process paragraphs in tables and clear table/row/cell property changes
248
+ const tables = doc.getTables();
249
+ for (const table of tables) {
250
+ // Clear tblPrChange on table
251
+ if (opts.acceptPropertyChanges && table.getTblPrChange()) {
252
+ table.clearTblPrChange();
253
+ result.propertyChangesAccepted++;
254
+ }
255
+
256
+ for (const row of table.getRows()) {
257
+ // Clear trPrChange on row
258
+ if (opts.acceptPropertyChanges && row.getTrPrChange()) {
259
+ row.clearTrPrChange();
260
+ result.propertyChangesAccepted++;
261
+ }
262
+
263
+ for (const cell of row.getCells()) {
264
+ // Clear tcPrChange on cell
265
+ if (opts.acceptPropertyChanges && cell.getTcPrChange()) {
266
+ cell.clearTcPrChange();
267
+ result.propertyChangesAccepted++;
268
+ }
269
+
270
+ // Clear cell structural revision markers (cellIns/cellDel/cellMerge)
271
+ if (opts.acceptPropertyChanges && cell.getCellRevision()) {
272
+ cell.clearCellRevision();
273
+ result.propertyChangesAccepted++;
274
+ }
275
+
276
+ // Process paragraphs in the cell
277
+ for (const paragraph of cell.getParagraphs()) {
278
+ const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);
279
+ result.insertionsAccepted += paragraphResult.insertionsAccepted;
280
+ result.deletionsAccepted += paragraphResult.deletionsAccepted;
281
+ result.movesAccepted += paragraphResult.movesAccepted;
282
+ result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;
283
+ }
284
+
285
+ // Process raw nested content (nested tables stored as XML)
286
+ // These cannot be processed via the in-memory model, so we use XML-based stripping
287
+ if (cell.hasRawNestedContent()) {
288
+ const rawContent = cell.getRawNestedContent();
289
+ for (let i = 0; i < rawContent.length; i++) {
290
+ const item = rawContent[i];
291
+ if (item) {
292
+ const cleanedXml = stripRevisionsFromXml(item.xml);
293
+ if (cleanedXml !== item.xml) {
294
+ cell.updateRawNestedContent(i, cleanedXml);
295
+ // Count revisions stripped from nested content
296
+ // We can't distinguish types in raw XML, so count as property changes
297
+ result.propertyChangesAccepted++;
298
+ logger.debug('Stripped revisions from nested content', {
299
+ type: item.type,
300
+ position: item.position,
301
+ originalLength: item.xml.length,
302
+ cleanedLength: cleanedXml.length,
303
+ });
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+ }
311
+
312
+ // Process paragraphs in headers
313
+ const headerFooterManager = doc.getHeaderFooterManager();
314
+ if (headerFooterManager) {
315
+ const headers = headerFooterManager.getAllHeaders();
316
+ for (const headerEntry of headers) {
317
+ const elements = headerEntry.header.getElements();
318
+ for (const element of elements) {
319
+ // Element can be Paragraph or Table - use instanceof for type safety
320
+ if (element instanceof Paragraph) {
321
+ const paragraphResult = acceptRevisionsInParagraph(element, opts);
322
+ result.insertionsAccepted += paragraphResult.insertionsAccepted;
323
+ result.deletionsAccepted += paragraphResult.deletionsAccepted;
324
+ result.movesAccepted += paragraphResult.movesAccepted;
325
+ result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;
326
+ } else if (element instanceof Table) {
327
+ // It's a Table - process its cells
328
+ for (const row of element.getRows()) {
329
+ for (const cell of row.getCells()) {
330
+ for (const paragraph of cell.getParagraphs()) {
331
+ const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);
332
+ result.insertionsAccepted += paragraphResult.insertionsAccepted;
333
+ result.deletionsAccepted += paragraphResult.deletionsAccepted;
334
+ result.movesAccepted += paragraphResult.movesAccepted;
335
+ result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;
336
+ }
337
+ // Process raw nested content in header tables
338
+ if (cell.hasRawNestedContent()) {
339
+ const rawContent = cell.getRawNestedContent();
340
+ for (let i = 0; i < rawContent.length; i++) {
341
+ const item = rawContent[i];
342
+ if (item) {
343
+ const cleanedXml = stripRevisionsFromXml(item.xml);
344
+ if (cleanedXml !== item.xml) {
345
+ cell.updateRawNestedContent(i, cleanedXml);
346
+ result.propertyChangesAccepted++;
347
+ }
348
+ }
349
+ }
350
+ }
351
+ }
352
+ }
353
+ }
354
+ }
355
+ }
356
+
357
+ // Process paragraphs in footers
358
+ const footers = headerFooterManager.getAllFooters();
359
+ for (const footerEntry of footers) {
360
+ const elements = footerEntry.footer.getElements();
361
+ for (const element of elements) {
362
+ // Element can be Paragraph or Table - use instanceof for type safety
363
+ if (element instanceof Paragraph) {
364
+ const paragraphResult = acceptRevisionsInParagraph(element, opts);
365
+ result.insertionsAccepted += paragraphResult.insertionsAccepted;
366
+ result.deletionsAccepted += paragraphResult.deletionsAccepted;
367
+ result.movesAccepted += paragraphResult.movesAccepted;
368
+ result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;
369
+ } else if (element instanceof Table) {
370
+ // It's a Table - process its cells
371
+ for (const row of element.getRows()) {
372
+ for (const cell of row.getCells()) {
373
+ for (const paragraph of cell.getParagraphs()) {
374
+ const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);
375
+ result.insertionsAccepted += paragraphResult.insertionsAccepted;
376
+ result.deletionsAccepted += paragraphResult.deletionsAccepted;
377
+ result.movesAccepted += paragraphResult.movesAccepted;
378
+ result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;
379
+ }
380
+ // Process raw nested content in footer tables
381
+ if (cell.hasRawNestedContent()) {
382
+ const rawContent = cell.getRawNestedContent();
383
+ for (let i = 0; i < rawContent.length; i++) {
384
+ const item = rawContent[i];
385
+ if (item) {
386
+ const cleanedXml = stripRevisionsFromXml(item.xml);
387
+ if (cleanedXml !== item.xml) {
388
+ cell.updateRawNestedContent(i, cleanedXml);
389
+ result.propertyChangesAccepted++;
390
+ }
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ // Clear sectPrChange on document section
402
+ if (opts.acceptPropertyChanges) {
403
+ const section = doc.getSection();
404
+ if (section?.getSectPrChange()) {
405
+ section.clearSectPrChange();
406
+ result.propertyChangesAccepted++;
407
+ }
408
+ }
409
+
410
+ // Clear revision manager
411
+ const revisionManager = doc.getRevisionManager();
412
+ if (revisionManager) {
413
+ revisionManager.clear();
414
+ }
415
+
416
+ // Disable track changes setting
417
+ doc.disableTrackChanges();
418
+
419
+ // Cleanup empty tables if enabled
420
+ // This removes tables that have no visible content after revision acceptance
421
+ // (e.g., tables where all content was deleted via tracked changes)
422
+ if (opts.cleanupEmptyTables) {
423
+ result.emptyTablesRemoved = cleanupEmptyTables(doc, logger);
424
+ }
425
+
426
+ result.totalAccepted =
427
+ result.insertionsAccepted +
428
+ result.deletionsAccepted +
429
+ result.movesAccepted +
430
+ result.propertyChangesAccepted;
431
+
432
+ logger.info('Revisions accepted in-memory', {
433
+ insertions: result.insertionsAccepted,
434
+ deletions: result.deletionsAccepted,
435
+ moves: result.movesAccepted,
436
+ propertyChanges: result.propertyChangesAccepted,
437
+ total: result.totalAccepted,
438
+ emptyTablesRemoved: result.emptyTablesRemoved,
439
+ });
440
+
441
+ return result;
442
+ }
443
+
444
+ /**
445
+ * Accept revisions in a single paragraph by transforming its content array.
446
+ *
447
+ * The transformation follows these rules:
448
+ * - Insertions (w:ins): Unwrap - extract child content into parent position
449
+ * - Deletions (w:del): Remove - delete revision and its content
450
+ * - MoveFrom (w:moveFrom): Remove - content exists at moveTo destination
451
+ * - MoveTo (w:moveTo): Unwrap - keep content, remove wrapper
452
+ * - Property changes: Remove from model (current formatting is kept)
453
+ *
454
+ * @param paragraph - Paragraph to process
455
+ * @param options - Options for which revision types to accept
456
+ * @returns Result with counts of accepted revisions
457
+ */
458
+ function acceptRevisionsInParagraph(
459
+ paragraph: Paragraph,
460
+ options: Required<AcceptRevisionsOptions>
461
+ ): AcceptRevisionsResult {
462
+ const result: AcceptRevisionsResult = {
463
+ insertionsAccepted: 0,
464
+ deletionsAccepted: 0,
465
+ movesAccepted: 0,
466
+ propertyChangesAccepted: 0,
467
+ totalAccepted: 0,
468
+ emptyTablesRemoved: 0,
469
+ };
470
+
471
+ const content = paragraph.getContent();
472
+ const newContent: ParagraphContent[] = [];
473
+
474
+ for (const item of content) {
475
+ if (item instanceof Revision) {
476
+ const revisionType = item.getType();
477
+
478
+ // Handle insertion revisions (w:ins)
479
+ if (revisionType === 'insert' && options.acceptInsertions) {
480
+ // Unwrap: Extract child content into parent position
481
+ const childContent = item.getContent();
482
+ for (const child of childContent) {
483
+ // Check ImageRun FIRST since ImageRun extends Run
484
+ if (isImageRunContent(child)) {
485
+ newContent.push(child);
486
+ } else if (isRunContent(child)) {
487
+ newContent.push(child);
488
+ } else if (isHyperlinkContent(child)) {
489
+ newContent.push(child);
490
+ }
491
+ }
492
+ result.insertionsAccepted++;
493
+ continue;
494
+ }
495
+
496
+ // Handle deletion revisions (w:del)
497
+ if (revisionType === 'delete' && options.acceptDeletions) {
498
+ // Remove: Don't add to newContent - content is deleted
499
+ result.deletionsAccepted++;
500
+ continue;
501
+ }
502
+
503
+ // Handle moveFrom revisions (source of moved content)
504
+ if (revisionType === 'moveFrom' && options.acceptMoves) {
505
+ // Remove: Content exists at moveTo destination
506
+ result.movesAccepted++;
507
+ continue;
508
+ }
509
+
510
+ // Handle moveTo revisions (destination of moved content)
511
+ if (revisionType === 'moveTo' && options.acceptMoves) {
512
+ // Unwrap: Keep content, remove wrapper
513
+ const childContent = item.getContent();
514
+ for (const child of childContent) {
515
+ // Check ImageRun FIRST since ImageRun extends Run
516
+ if (isImageRunContent(child)) {
517
+ newContent.push(child);
518
+ } else if (isRunContent(child)) {
519
+ newContent.push(child);
520
+ } else if (isHyperlinkContent(child)) {
521
+ newContent.push(child);
522
+ }
523
+ }
524
+ result.movesAccepted++;
525
+ continue;
526
+ }
527
+
528
+ // Handle property change revisions
529
+ if (PROPERTY_REVISION_TYPES.includes(revisionType) && options.acceptPropertyChanges) {
530
+ // For property changes, the revision is metadata attached to runs
531
+ // The current formatting (newProperties) is already applied to the run
532
+ // We just need to remove the change tracking metadata
533
+ // The content inside should be preserved
534
+ const childContent = item.getContent();
535
+ for (const child of childContent) {
536
+ // Check ImageRun FIRST since ImageRun extends Run
537
+ if (isImageRunContent(child)) {
538
+ newContent.push(child);
539
+ } else if (isRunContent(child)) {
540
+ newContent.push(child);
541
+ } else if (isHyperlinkContent(child)) {
542
+ newContent.push(child);
543
+ }
544
+ }
545
+ result.propertyChangesAccepted++;
546
+ continue;
547
+ }
548
+
549
+ // If we reach here, this revision type is not being accepted
550
+ // Keep it in the content
551
+ newContent.push(item);
552
+ } else {
553
+ // Non-revision content - keep as-is
554
+ newContent.push(item);
555
+ }
556
+ }
557
+
558
+ // Replace paragraph content with the transformed content
559
+ paragraph.setContent(newContent);
560
+
561
+ // Clear paragraph property change tracking (pPrChange) if accepting property changes
562
+ // This removes the w:pPrChange element from the paragraph's formatting
563
+ if (options.acceptPropertyChanges) {
564
+ const formatting = paragraph.getFormatting();
565
+ if (formatting.pPrChange) {
566
+ paragraph.clearParagraphPropertiesChange();
567
+ result.propertyChangesAccepted++;
568
+ }
569
+ }
570
+
571
+ return result;
572
+ }
573
+
574
+ /**
575
+ * Check if a paragraph has any revisions
576
+ */
577
+ export function paragraphHasRevisions(paragraph: Paragraph): boolean {
578
+ const content = paragraph.getContent();
579
+ return content.some((item) => item instanceof Revision);
580
+ }
581
+
582
+ /**
583
+ * Get all revisions from a paragraph
584
+ */
585
+ export function getRevisionsFromParagraph(paragraph: Paragraph): Revision[] {
586
+ const content = paragraph.getContent();
587
+ return content.filter((item): item is Revision => item instanceof Revision);
588
+ }
589
+
590
+ /**
591
+ * Count revisions by type in a document
592
+ */
593
+ export function countRevisionsByType(doc: Document): Map<RevisionType, number> {
594
+ const counts = new Map<RevisionType, number>();
595
+
596
+ const paragraphs = doc.getAllParagraphs();
597
+ for (const paragraph of paragraphs) {
598
+ const revisions = getRevisionsFromParagraph(paragraph);
599
+ for (const revision of revisions) {
600
+ const type = revision.getType();
601
+ counts.set(type, (counts.get(type) || 0) + 1);
602
+ }
603
+ }
604
+
605
+ return counts;
606
+ }
607
+
608
+ /**
609
+ * Remove tables that have no visible content after revision acceptance.
610
+ *
611
+ * A table is considered empty if ALL cells in ALL rows have no text content.
612
+ * This handles cases where all table content was deleted via tracked changes -
613
+ * the deletion markers are stripped but the empty table structure remains.
614
+ *
615
+ * @param doc - Document to clean up
616
+ * @param logger - Logger instance for debug output
617
+ * @returns Number of empty tables removed
618
+ */
619
+ function cleanupEmptyTables(doc: Document, logger: ILogger): number {
620
+ const tables = doc.getTables();
621
+ let removedCount = 0;
622
+ const tablesToRemove: number[] = [];
623
+
624
+ for (let tableIndex = 0; tableIndex < tables.length; tableIndex++) {
625
+ const table = tables[tableIndex];
626
+ if (!table) continue;
627
+
628
+ let hasContent = false;
629
+ const rows = table.getRows();
630
+
631
+ for (const row of rows) {
632
+ const cells = row.getCells();
633
+ for (const cell of cells) {
634
+ const paragraphs = cell.getParagraphs();
635
+ for (const para of paragraphs) {
636
+ const text = para.getText().trim();
637
+ if (text.length > 0) {
638
+ hasContent = true;
639
+ break;
640
+ }
641
+ }
642
+ if (hasContent) break;
643
+ }
644
+ if (hasContent) break;
645
+ }
646
+
647
+ if (!hasContent) {
648
+ // Mark this table for removal (store index)
649
+ tablesToRemove.push(tableIndex);
650
+ logger.debug('Found empty table for removal', { tableIndex });
651
+ }
652
+ }
653
+
654
+ // Remove tables in reverse order to preserve indices
655
+ for (let i = tablesToRemove.length - 1; i >= 0; i--) {
656
+ const tableIndex = tablesToRemove[i];
657
+ if (tableIndex !== undefined && doc.removeTable(tableIndex)) {
658
+ removedCount++;
659
+ logger.debug('Removed empty table', { tableIndex });
660
+ }
661
+ }
662
+
663
+ if (removedCount > 0) {
664
+ logger.info('Empty table cleanup complete', { tablesRemoved: removedCount });
665
+ }
666
+
667
+ return removedCount;
668
+ }