docxmlater 10.1.3 → 10.1.5

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 (371) hide show
  1. package/README.md +759 -754
  2. package/dist/constants/legacyCompatFlags.js +1 -1
  3. package/dist/constants/legacyCompatFlags.js.map +1 -1
  4. package/dist/constants/limits.js.map +1 -1
  5. package/dist/core/Document.d.ts +50 -50
  6. package/dist/core/Document.d.ts.map +1 -1
  7. package/dist/core/Document.js +483 -471
  8. package/dist/core/Document.js.map +1 -1
  9. package/dist/core/DocumentContent.d.ts +9 -9
  10. package/dist/core/DocumentContent.d.ts.map +1 -1
  11. package/dist/core/DocumentContent.js +1 -1
  12. package/dist/core/DocumentContent.js.map +1 -1
  13. package/dist/core/DocumentGenerator.d.ts +11 -11
  14. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  15. package/dist/core/DocumentGenerator.js +251 -251
  16. package/dist/core/DocumentGenerator.js.map +1 -1
  17. package/dist/core/DocumentIdManager.js.map +1 -1
  18. package/dist/core/DocumentParser.d.ts +15 -15
  19. package/dist/core/DocumentParser.d.ts.map +1 -1
  20. package/dist/core/DocumentParser.js +2123 -2155
  21. package/dist/core/DocumentParser.js.map +1 -1
  22. package/dist/core/DocumentValidator.d.ts.map +1 -1
  23. package/dist/core/DocumentValidator.js +2 -5
  24. package/dist/core/DocumentValidator.js.map +1 -1
  25. package/dist/core/Relationship.js.map +1 -1
  26. package/dist/core/RelationshipManager.d.ts.map +1 -1
  27. package/dist/core/RelationshipManager.js +3 -3
  28. package/dist/core/RelationshipManager.js.map +1 -1
  29. package/dist/elements/AlternateContent.js.map +1 -1
  30. package/dist/elements/Bookmark.d.ts.map +1 -1
  31. package/dist/elements/Bookmark.js +3 -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.d.ts.map +1 -1
  36. package/dist/elements/Comment.js +9 -6
  37. package/dist/elements/Comment.js.map +1 -1
  38. package/dist/elements/CommentManager.d.ts.map +1 -1
  39. package/dist/elements/CommentManager.js +18 -17
  40. package/dist/elements/CommentManager.js.map +1 -1
  41. package/dist/elements/CommonTypes.d.ts +21 -21
  42. package/dist/elements/CommonTypes.d.ts.map +1 -1
  43. package/dist/elements/CommonTypes.js +56 -56
  44. package/dist/elements/CommonTypes.js.map +1 -1
  45. package/dist/elements/CustomXml.js.map +1 -1
  46. package/dist/elements/Endnote.d.ts.map +1 -1
  47. package/dist/elements/Endnote.js +6 -6
  48. package/dist/elements/Endnote.js.map +1 -1
  49. package/dist/elements/EndnoteManager.d.ts.map +1 -1
  50. package/dist/elements/EndnoteManager.js +6 -7
  51. package/dist/elements/EndnoteManager.js.map +1 -1
  52. package/dist/elements/Field.d.ts.map +1 -1
  53. package/dist/elements/Field.js +82 -25
  54. package/dist/elements/Field.js.map +1 -1
  55. package/dist/elements/FieldHelpers.d.ts.map +1 -1
  56. package/dist/elements/FieldHelpers.js.map +1 -1
  57. package/dist/elements/FontManager.d.ts.map +1 -1
  58. package/dist/elements/FontManager.js +1 -1
  59. package/dist/elements/FontManager.js.map +1 -1
  60. package/dist/elements/Footer.js +2 -2
  61. package/dist/elements/Footer.js.map +1 -1
  62. package/dist/elements/Footnote.d.ts.map +1 -1
  63. package/dist/elements/Footnote.js +6 -6
  64. package/dist/elements/Footnote.js.map +1 -1
  65. package/dist/elements/FootnoteManager.d.ts.map +1 -1
  66. package/dist/elements/FootnoteManager.js +6 -7
  67. package/dist/elements/FootnoteManager.js.map +1 -1
  68. package/dist/elements/Header.js +2 -2
  69. package/dist/elements/Header.js.map +1 -1
  70. package/dist/elements/HeaderFooterManager.js.map +1 -1
  71. package/dist/elements/Hyperlink.d.ts +5 -3
  72. package/dist/elements/Hyperlink.d.ts.map +1 -1
  73. package/dist/elements/Hyperlink.js +134 -76
  74. package/dist/elements/Hyperlink.js.map +1 -1
  75. package/dist/elements/Image.d.ts.map +1 -1
  76. package/dist/elements/Image.js +238 -106
  77. package/dist/elements/Image.js.map +1 -1
  78. package/dist/elements/ImageManager.d.ts.map +1 -1
  79. package/dist/elements/ImageManager.js +1 -1
  80. package/dist/elements/ImageManager.js.map +1 -1
  81. package/dist/elements/ImageRun.js +1 -1
  82. package/dist/elements/ImageRun.js.map +1 -1
  83. package/dist/elements/MathElement.js.map +1 -1
  84. package/dist/elements/Paragraph.d.ts +24 -24
  85. package/dist/elements/Paragraph.d.ts.map +1 -1
  86. package/dist/elements/Paragraph.js +181 -188
  87. package/dist/elements/Paragraph.js.map +1 -1
  88. package/dist/elements/PreservedElement.js.map +1 -1
  89. package/dist/elements/PropertyChangeTypes.d.ts.map +1 -1
  90. package/dist/elements/PropertyChangeTypes.js +6 -6
  91. package/dist/elements/PropertyChangeTypes.js.map +1 -1
  92. package/dist/elements/RangeMarker.d.ts.map +1 -1
  93. package/dist/elements/RangeMarker.js.map +1 -1
  94. package/dist/elements/Revision.d.ts.map +1 -1
  95. package/dist/elements/Revision.js +4 -5
  96. package/dist/elements/Revision.js.map +1 -1
  97. package/dist/elements/RevisionContent.js.map +1 -1
  98. package/dist/elements/RevisionManager.d.ts.map +1 -1
  99. package/dist/elements/RevisionManager.js +40 -48
  100. package/dist/elements/RevisionManager.js.map +1 -1
  101. package/dist/elements/Run.d.ts +16 -16
  102. package/dist/elements/Run.d.ts.map +1 -1
  103. package/dist/elements/Run.js +256 -238
  104. package/dist/elements/Run.js.map +1 -1
  105. package/dist/elements/Section.d.ts.map +1 -1
  106. package/dist/elements/Section.js +36 -11
  107. package/dist/elements/Section.js.map +1 -1
  108. package/dist/elements/Shape.d.ts.map +1 -1
  109. package/dist/elements/Shape.js.map +1 -1
  110. package/dist/elements/StructuredDocumentTag.d.ts +6 -6
  111. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  112. package/dist/elements/StructuredDocumentTag.js +99 -104
  113. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  114. package/dist/elements/Table.d.ts +11 -11
  115. package/dist/elements/Table.d.ts.map +1 -1
  116. package/dist/elements/Table.js +102 -107
  117. package/dist/elements/Table.js.map +1 -1
  118. package/dist/elements/TableCell.d.ts +10 -10
  119. package/dist/elements/TableCell.d.ts.map +1 -1
  120. package/dist/elements/TableCell.js +105 -106
  121. package/dist/elements/TableCell.js.map +1 -1
  122. package/dist/elements/TableGridChange.d.ts.map +1 -1
  123. package/dist/elements/TableGridChange.js.map +1 -1
  124. package/dist/elements/TableOfContents.d.ts.map +1 -1
  125. package/dist/elements/TableOfContents.js +4 -4
  126. package/dist/elements/TableOfContents.js.map +1 -1
  127. package/dist/elements/TableOfContentsElement.js.map +1 -1
  128. package/dist/elements/TableRow.d.ts.map +1 -1
  129. package/dist/elements/TableRow.js +13 -6
  130. package/dist/elements/TableRow.js.map +1 -1
  131. package/dist/elements/TextBox.d.ts.map +1 -1
  132. package/dist/elements/TextBox.js +3 -5
  133. package/dist/elements/TextBox.js.map +1 -1
  134. package/dist/formatting/AbstractNumbering.d.ts +4 -4
  135. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  136. package/dist/formatting/AbstractNumbering.js +54 -49
  137. package/dist/formatting/AbstractNumbering.js.map +1 -1
  138. package/dist/formatting/NumberingInstance.d.ts.map +1 -1
  139. package/dist/formatting/NumberingInstance.js +1 -3
  140. package/dist/formatting/NumberingInstance.js.map +1 -1
  141. package/dist/formatting/NumberingLevel.d.ts +5 -5
  142. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  143. package/dist/formatting/NumberingLevel.js +119 -125
  144. package/dist/formatting/NumberingLevel.js.map +1 -1
  145. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  146. package/dist/formatting/NumberingManager.js +9 -9
  147. package/dist/formatting/NumberingManager.js.map +1 -1
  148. package/dist/formatting/Style.d.ts +11 -11
  149. package/dist/formatting/Style.d.ts.map +1 -1
  150. package/dist/formatting/Style.js +219 -247
  151. package/dist/formatting/Style.js.map +1 -1
  152. package/dist/formatting/StylesManager.d.ts +2 -2
  153. package/dist/formatting/StylesManager.d.ts.map +1 -1
  154. package/dist/formatting/StylesManager.js +96 -102
  155. package/dist/formatting/StylesManager.js.map +1 -1
  156. package/dist/helpers/CleanupHelper.d.ts +1 -1
  157. package/dist/helpers/CleanupHelper.d.ts.map +1 -1
  158. package/dist/helpers/CleanupHelper.js +6 -6
  159. package/dist/helpers/CleanupHelper.js.map +1 -1
  160. package/dist/images/ImageOptimizer.js +7 -7
  161. package/dist/images/ImageOptimizer.js.map +1 -1
  162. package/dist/index.d.ts +9 -9
  163. package/dist/index.d.ts.map +1 -1
  164. package/dist/index.js.map +1 -1
  165. package/dist/managers/DrawingManager.js.map +1 -1
  166. package/dist/tracking/DocumentTrackingContext.d.ts.map +1 -1
  167. package/dist/tracking/DocumentTrackingContext.js +23 -7
  168. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  169. package/dist/tracking/TrackingContext.d.ts.map +1 -1
  170. package/dist/tracking/TrackingContext.js.map +1 -1
  171. package/dist/types/compatibility-types.js.map +1 -1
  172. package/dist/types/formatting.js.map +1 -1
  173. package/dist/types/list-types.d.ts +6 -6
  174. package/dist/types/list-types.js.map +1 -1
  175. package/dist/types/settings-types.js.map +1 -1
  176. package/dist/types/styleConfig.d.ts +2 -2
  177. package/dist/types/styleConfig.js.map +1 -1
  178. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  179. package/dist/utils/ChangelogGenerator.js +97 -101
  180. package/dist/utils/ChangelogGenerator.js.map +1 -1
  181. package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
  182. package/dist/utils/CompatibilityUpgrader.js +1 -1
  183. package/dist/utils/CompatibilityUpgrader.js.map +1 -1
  184. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  185. package/dist/utils/InMemoryRevisionAcceptor.js +1 -6
  186. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  187. package/dist/utils/MoveOperationHelper.d.ts.map +1 -1
  188. package/dist/utils/MoveOperationHelper.js +1 -1
  189. package/dist/utils/MoveOperationHelper.js.map +1 -1
  190. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  191. package/dist/utils/RevisionAwareProcessor.js +2 -4
  192. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  193. package/dist/utils/RevisionWalker.d.ts.map +1 -1
  194. package/dist/utils/RevisionWalker.js +4 -12
  195. package/dist/utils/RevisionWalker.js.map +1 -1
  196. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  197. package/dist/utils/SelectiveRevisionAcceptor.js +2 -6
  198. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  199. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  200. package/dist/utils/ShadingResolver.js +1 -1
  201. package/dist/utils/ShadingResolver.js.map +1 -1
  202. package/dist/utils/acceptRevisions.d.ts.map +1 -1
  203. package/dist/utils/acceptRevisions.js +23 -12
  204. package/dist/utils/acceptRevisions.js.map +1 -1
  205. package/dist/utils/cnfStyleDecoder.d.ts +1 -1
  206. package/dist/utils/cnfStyleDecoder.d.ts.map +1 -1
  207. package/dist/utils/cnfStyleDecoder.js +40 -40
  208. package/dist/utils/cnfStyleDecoder.js.map +1 -1
  209. package/dist/utils/corruptionDetection.d.ts.map +1 -1
  210. package/dist/utils/corruptionDetection.js.map +1 -1
  211. package/dist/utils/dateFormatting.js.map +1 -1
  212. package/dist/utils/deepClone.js +1 -1
  213. package/dist/utils/deepClone.js.map +1 -1
  214. package/dist/utils/diagnostics.d.ts.map +1 -1
  215. package/dist/utils/diagnostics.js +1 -1
  216. package/dist/utils/diagnostics.js.map +1 -1
  217. package/dist/utils/errorHandling.js.map +1 -1
  218. package/dist/utils/formatting.d.ts.map +1 -1
  219. package/dist/utils/formatting.js +10 -2
  220. package/dist/utils/formatting.js.map +1 -1
  221. package/dist/utils/list-detection.d.ts +2 -2
  222. package/dist/utils/list-detection.d.ts.map +1 -1
  223. package/dist/utils/list-detection.js +21 -23
  224. package/dist/utils/list-detection.js.map +1 -1
  225. package/dist/utils/logger.d.ts.map +1 -1
  226. package/dist/utils/logger.js +12 -7
  227. package/dist/utils/logger.js.map +1 -1
  228. package/dist/utils/parsingHelpers.js.map +1 -1
  229. package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
  230. package/dist/utils/stripTrackedChanges.js +3 -3
  231. package/dist/utils/stripTrackedChanges.js.map +1 -1
  232. package/dist/utils/textDiff.d.ts +1 -1
  233. package/dist/utils/textDiff.js +8 -8
  234. package/dist/utils/textDiff.js.map +1 -1
  235. package/dist/utils/units.js.map +1 -1
  236. package/dist/utils/validation.d.ts.map +1 -1
  237. package/dist/utils/validation.js +24 -7
  238. package/dist/utils/validation.js.map +1 -1
  239. package/dist/utils/xmlSanitization.d.ts.map +1 -1
  240. package/dist/utils/xmlSanitization.js +3 -3
  241. package/dist/utils/xmlSanitization.js.map +1 -1
  242. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  243. package/dist/validation/RevisionAutoFixer.js +5 -5
  244. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  245. package/dist/validation/RevisionValidator.d.ts.map +1 -1
  246. package/dist/validation/RevisionValidator.js +7 -9
  247. package/dist/validation/RevisionValidator.js.map +1 -1
  248. package/dist/validation/ValidationRules.js +3 -3
  249. package/dist/validation/ValidationRules.js.map +1 -1
  250. package/dist/validation/index.js.map +1 -1
  251. package/dist/xml/XMLBuilder.d.ts +1 -1
  252. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  253. package/dist/xml/XMLBuilder.js +98 -100
  254. package/dist/xml/XMLBuilder.js.map +1 -1
  255. package/dist/xml/XMLParser.d.ts.map +1 -1
  256. package/dist/xml/XMLParser.js +61 -66
  257. package/dist/xml/XMLParser.js.map +1 -1
  258. package/dist/zip/ZipHandler.d.ts.map +1 -1
  259. package/dist/zip/ZipHandler.js.map +1 -1
  260. package/dist/zip/ZipReader.d.ts.map +1 -1
  261. package/dist/zip/ZipReader.js +1 -3
  262. package/dist/zip/ZipReader.js.map +1 -1
  263. package/dist/zip/ZipWriter.d.ts +1 -1
  264. package/dist/zip/ZipWriter.d.ts.map +1 -1
  265. package/dist/zip/ZipWriter.js +28 -36
  266. package/dist/zip/ZipWriter.js.map +1 -1
  267. package/dist/zip/types.js +1 -1
  268. package/dist/zip/types.js.map +1 -1
  269. package/package.json +92 -92
  270. package/src/__tests__/helper-methods.test.ts +512 -512
  271. package/src/constants/legacyCompatFlags.ts +138 -138
  272. package/src/constants/limits.ts +50 -50
  273. package/src/core/Document.ts +985 -1145
  274. package/src/core/DocumentContent.ts +461 -467
  275. package/src/core/DocumentGenerator.ts +1133 -1104
  276. package/src/core/DocumentIdManager.ts +158 -158
  277. package/src/core/DocumentParser.ts +2347 -2716
  278. package/src/core/DocumentValidator.ts +363 -372
  279. package/src/core/Relationship.ts +367 -367
  280. package/src/core/RelationshipManager.ts +429 -428
  281. package/src/elements/AlternateContent.ts +42 -42
  282. package/src/elements/Bookmark.ts +212 -210
  283. package/src/elements/BookmarkManager.ts +247 -250
  284. package/src/elements/Comment.ts +356 -359
  285. package/src/elements/CommentManager.ts +499 -502
  286. package/src/elements/CommonTypes.ts +524 -549
  287. package/src/elements/CustomXml.ts +36 -36
  288. package/src/elements/Endnote.ts +221 -217
  289. package/src/elements/EndnoteManager.ts +246 -249
  290. package/src/elements/Field.ts +1292 -1233
  291. package/src/elements/FieldHelpers.ts +329 -333
  292. package/src/elements/FontManager.ts +336 -339
  293. package/src/elements/Footer.ts +269 -269
  294. package/src/elements/Footnote.ts +221 -217
  295. package/src/elements/FootnoteManager.ts +246 -249
  296. package/src/elements/Header.ts +269 -269
  297. package/src/elements/HeaderFooterManager.ts +219 -219
  298. package/src/elements/Hyperlink.ts +1288 -1193
  299. package/src/elements/Image.ts +1982 -1756
  300. package/src/elements/ImageManager.ts +437 -432
  301. package/src/elements/ImageRun.ts +59 -59
  302. package/src/elements/MathElement.ts +65 -65
  303. package/src/elements/Paragraph.ts +4347 -4287
  304. package/src/elements/PreservedElement.ts +53 -53
  305. package/src/elements/PropertyChangeTypes.ts +458 -442
  306. package/src/elements/RangeMarker.ts +382 -400
  307. package/src/elements/Revision.ts +1198 -1217
  308. package/src/elements/RevisionContent.ts +73 -73
  309. package/src/elements/RevisionManager.ts +1070 -1070
  310. package/src/elements/Run.ts +3103 -3073
  311. package/src/elements/Section.ts +1521 -1421
  312. package/src/elements/Shape.ts +884 -873
  313. package/src/elements/StructuredDocumentTag.ts +1176 -1207
  314. package/src/elements/Table.ts +2468 -2524
  315. package/src/elements/TableCell.ts +1617 -1621
  316. package/src/elements/TableGridChange.ts +149 -151
  317. package/src/elements/TableOfContents.ts +701 -691
  318. package/src/elements/TableOfContentsElement.ts +89 -89
  319. package/src/elements/TableRow.ts +960 -929
  320. package/src/elements/TextBox.ts +766 -768
  321. package/src/formatting/AbstractNumbering.ts +580 -579
  322. package/src/formatting/NumberingInstance.ts +295 -299
  323. package/src/formatting/NumberingLevel.ts +981 -1040
  324. package/src/formatting/NumberingManager.ts +833 -827
  325. package/src/formatting/Style.ts +1785 -1879
  326. package/src/formatting/StylesManager.ts +1090 -1130
  327. package/src/helpers/CleanupHelper.ts +524 -524
  328. package/src/images/ImageOptimizer.ts +274 -274
  329. package/src/index.ts +559 -554
  330. package/src/managers/DrawingManager.ts +319 -319
  331. package/src/tracking/DocumentTrackingContext.ts +687 -674
  332. package/src/tracking/TrackingContext.ts +175 -173
  333. package/src/types/compatibility-types.ts +49 -49
  334. package/src/types/formatting.ts +210 -210
  335. package/src/types/list-types.ts +14 -14
  336. package/src/types/settings-types.ts +59 -59
  337. package/src/types/styleConfig.ts +189 -189
  338. package/src/utils/ChangelogGenerator.ts +1583 -1581
  339. package/src/utils/CompatibilityUpgrader.ts +235 -237
  340. package/src/utils/InMemoryRevisionAcceptor.ts +691 -696
  341. package/src/utils/MoveOperationHelper.ts +233 -238
  342. package/src/utils/RevisionAwareProcessor.ts +518 -526
  343. package/src/utils/RevisionWalker.ts +427 -457
  344. package/src/utils/SelectiveRevisionAcceptor.ts +662 -683
  345. package/src/utils/ShadingResolver.ts +105 -107
  346. package/src/utils/acceptRevisions.ts +723 -714
  347. package/src/utils/cnfStyleDecoder.ts +212 -217
  348. package/src/utils/corruptionDetection.ts +346 -345
  349. package/src/utils/dateFormatting.ts +20 -20
  350. package/src/utils/deepClone.ts +77 -78
  351. package/src/utils/diagnostics.ts +125 -129
  352. package/src/utils/errorHandling.ts +80 -80
  353. package/src/utils/formatting.ts +220 -213
  354. package/src/utils/list-detection.ts +32 -42
  355. package/src/utils/logger.ts +412 -404
  356. package/src/utils/parsingHelpers.ts +190 -190
  357. package/src/utils/stripTrackedChanges.ts +356 -353
  358. package/src/utils/textDiff.ts +100 -100
  359. package/src/utils/units.ts +421 -421
  360. package/src/utils/validation.ts +553 -542
  361. package/src/utils/xmlSanitization.ts +179 -182
  362. package/src/validation/RevisionAutoFixer.ts +541 -542
  363. package/src/validation/RevisionValidator.ts +470 -460
  364. package/src/validation/ValidationRules.ts +338 -338
  365. package/src/validation/index.ts +30 -30
  366. package/src/xml/XMLBuilder.ts +857 -871
  367. package/src/xml/XMLParser.ts +877 -919
  368. package/src/zip/ZipHandler.ts +629 -637
  369. package/src/zip/ZipReader.ts +295 -299
  370. package/src/zip/ZipWriter.ts +374 -390
  371. package/src/zip/types.ts +116 -116
@@ -1 +1 @@
1
- {"version":3,"file":"acceptRevisions.js","sourceRoot":"","sources":["../../src/utils/acceptRevisions.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler';\r\nimport { XMLParser } from '../xml/XMLParser';\r\nimport { RevisionWalker } from './RevisionWalker';\r\n\r\n/**\r\n * Accepts all tracked changes in a Word document per Microsoft's OpenXML SDK pattern\r\n *\r\n * This implementation uses DOM-based tree walking for reliability:\r\n * 1. Insertions (<w:ins>): Keep content, remove wrapper tags\r\n * 2. Deletions (<w:del>): Remove entirely (content and tags)\r\n * 3. Move From (<w:moveFrom>): Remove entirely (source of move)\r\n * 4. Move To (<w:moveTo>): Keep content, remove wrapper (destination of move)\r\n * 5. Property changes: Remove all *Change elements\r\n * 6. Range markers: Remove all boundary markers\r\n *\r\n * Also cleans up metadata in people.xml, settings.xml, and core.xml\r\n *\r\n * @see https://learn.microsoft.com/en-us/office/open-xml/how-to-accept-all-revisions\r\n */\r\nclass RevisionAcceptor {\r\n private zipHandler: ZipHandler;\r\n /** Feature flag for DOM-based processing (default: true) */\r\n private useDomBasedProcessing = true;\r\n\r\n constructor(zipHandler: ZipHandler) {\r\n this.zipHandler = zipHandler;\r\n }\r\n\r\n /**\r\n * Enable or disable DOM-based processing (for testing/migration)\r\n */\r\n setUseDomBasedProcessing(enabled: boolean): void {\r\n this.useDomBasedProcessing = enabled;\r\n }\r\n\r\n /**\r\n * Main method to accept all revisions in the document\r\n */\r\n public async acceptAllRevisions(): Promise<void> {\r\n // Process document.xml\r\n await this.processDocumentPart('word/document.xml');\r\n \r\n // Process headers\r\n const files = this.zipHandler.getFilePaths();\r\n for (const file of files) {\r\n if (/^word\\/header\\d+\\.xml$/.exec(file)) {\r\n await this.processDocumentPart(file);\r\n }\r\n if (/^word\\/footer\\d+\\.xml$/.exec(file)) {\r\n await this.processDocumentPart(file);\r\n }\r\n }\r\n\r\n // Clean up metadata files\r\n this.cleanupPeopleXml();\r\n this.cleanupSettingsXml();\r\n this.cleanupCorePropsXml();\r\n }\r\n\r\n /**\r\n * Process a document part (document.xml, header, footer) to accept revisions\r\n */\r\n private async processDocumentPart(partPath: string): Promise<void> {\r\n if (this.useDomBasedProcessing) {\r\n return this.processDocumentPartDOM(partPath);\r\n }\r\n return this.processDocumentPartRegex(partPath);\r\n }\r\n\r\n /**\r\n * DOM-based implementation of revision acceptance\r\n * Uses XMLParser and RevisionWalker for reliable processing\r\n */\r\n private processDocumentPartDOM(partPath: string): void {\r\n const xml = this.zipHandler.getFileAsString(partPath);\r\n if (!xml) {\r\n return;\r\n }\r\n\r\n // Step 1: Parse XML to object tree\r\n // IMPORTANT: trimValues: false preserves whitespace from xml:space=\"preserve\" attributes\r\n const parsed = XMLParser.parseToObject(xml, { trimValues: false });\r\n\r\n // Step 2: Process revisions using DOM walker\r\n const processed = RevisionWalker.processTree(parsed, {\r\n acceptInsertions: true,\r\n acceptDeletions: true,\r\n acceptMoves: true,\r\n acceptPropertyChanges: true,\r\n });\r\n\r\n // Step 3: Handle image relationship ID remapping\r\n this.remapImageRelationshipsInTree(processed);\r\n\r\n // Step 4: Convert back to XML\r\n const outputXml =\r\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n' +\r\n this.objectToXml(processed);\r\n\r\n // Step 5: Update file\r\n this.zipHandler.updateFile(partPath, outputXml);\r\n }\r\n\r\n /**\r\n * Legacy RegEx-based implementation (kept as fallback)\r\n */\r\n private processDocumentPartRegex(partPath: string): void {\r\n const xml = this.zipHandler.getFileAsString(partPath);\r\n if (!xml) {\r\n return;\r\n }\r\n\r\n let content = xml;\r\n\r\n // Step 1: Remove all range markers FIRST (before processing revisions)\r\n // This prevents orphaned references when revision content is modified\r\n content = this.removeAllRangeMarkers(content);\r\n\r\n // Step 2: Remove all property change elements\r\n // These track formatting changes and must be removed before other processing\r\n content = this.removeAllPropertyChanges(content);\r\n\r\n // Step 3: Process deletions - remove entire element INCLUDING content\r\n // Must be done before insertions to handle nested scenarios\r\n content = this.acceptDeletions(content);\r\n\r\n // Step 4: Process move operations\r\n // Remove moveFrom entirely (source), unwrap moveTo (destination)\r\n content = this.acceptMoveFrom(content);\r\n content = this.acceptMoveTo(content);\r\n\r\n // Step 5: Process insertions - keep content, remove wrapper\r\n content = this.acceptInsertions(content);\r\n\r\n // Step 6: Final cleanup - remove any remaining orphaned tags\r\n content = this.cleanupOrphanedTags(content);\r\n\r\n // Update the file\r\n this.zipHandler.updateFile(partPath, content);\r\n }\r\n\r\n /**\r\n * Remove all range marker elements\r\n * These are boundary markers for tracked changes and moves\r\n */\r\n private removeAllRangeMarkers(xml: string): string {\r\n const patterns = [\r\n // Move range markers\r\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\r\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\r\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\r\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\r\n // Custom XML range markers\r\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\r\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\r\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\r\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\r\n /<w:customXmlMoveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeStart>)/gs,\r\n /<w:customXmlMoveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeEnd>)/gs,\r\n /<w:customXmlMoveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeStart>)/gs,\r\n /<w:customXmlMoveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeEnd>)/gs,\r\n ];\r\n\r\n let result = xml;\r\n for (const pattern of patterns) {\r\n result = result.replace(pattern, '');\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Remove all property change tracking elements\r\n * Per ECMA-376, these track previous state of formatting\r\n */\r\n private removeAllPropertyChanges(xml: string): string {\r\n const patterns = [\r\n // Run property changes\r\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\r\n // Paragraph property changes \r\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\r\n // Table property changes\r\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\r\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\r\n // Table cell property changes\r\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\r\n // Table row property changes\r\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\r\n // Section property changes\r\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\r\n // Table grid changes\r\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\r\n // Numbering changes\r\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\r\n ];\r\n\r\n let result = xml;\r\n for (const pattern of patterns) {\r\n result = result.replace(pattern, '');\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Accept deletions - remove the entire <w:del> element including its content\r\n * \r\n * Per Microsoft SDK: \"DeletedRun elements should be removed along with their content\"\r\n */\r\n private acceptDeletions(xml: string): string {\r\n let result = xml;\r\n let previousLength = 0;\r\n \r\n // Iterate until no more deletions (handles nested cases)\r\n while (result.length !== previousLength) {\r\n previousLength = result.length;\r\n \r\n // Match complete <w:del ...>...</w:del> elements and remove entirely\r\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\r\n }\r\n \r\n // Also remove self-closing deletion tags\r\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Accept moveFrom - remove the entire element (source of moved content)\r\n * \r\n * The content exists at the moveTo destination, so we discard the source\r\n */\r\n private acceptMoveFrom(xml: string): string {\r\n let result = xml;\r\n let previousLength = 0;\r\n \r\n while (result.length !== previousLength) {\r\n previousLength = result.length;\r\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\r\n }\r\n \r\n // Also remove self-closing tags\r\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Accept moveTo - keep the content, remove the wrapper tags\r\n * \r\n * The moveTo location is where the content should remain\r\n */\r\n private acceptMoveTo(xml: string): string {\r\n let result = xml;\r\n \r\n // Remove closing tags first (prevents issues with regex matching)\r\n result = result.replace(/<\\/w:moveTo>/g, '');\r\n \r\n // Remove opening tags (keeps content that was inside)\r\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Accept insertions - keep the content, remove the wrapper tags\r\n *\r\n * Per Microsoft SDK: \"InsertedRun elements should be unwrapped, keeping their content\"\r\n *\r\n * IMPORTANT: This method now handles relationship ID remapping for images inside insertions.\r\n * When Word tracks changes with images, it can reuse relationship IDs (like rId5) because\r\n * they're in separate tracked change contexts. But when we unwrap them, duplicate IDs\r\n * cause corruption. This method assigns new unique IDs to images inside insertions.\r\n */\r\n private acceptInsertions(xml: string): string {\r\n let result = xml;\r\n\r\n // Parse existing relationships\r\n const relationships = this.parseRelationships();\r\n const existingIds = new Set(relationships.keys());\r\n\r\n // Process each w:ins element and remap images one by one\r\n const insRegex = /<w:ins\\b[^>]*>[\\s\\S]*?<\\/w:ins>/g;\r\n\r\n result = result.replace(insRegex, (insMatch) => {\r\n // For each image reference inside this insertion, generate a unique new ID\r\n return insMatch.replace(/r:embed=\"(rId\\d+)\"/g, (embedMatch, oldId) => {\r\n // Generate new unique ID for THIS occurrence\r\n const newId = this.getNextRelationshipId(existingIds);\r\n existingIds.add(newId);\r\n\r\n // Add relationship with same target as original\r\n const target = relationships.get(oldId);\r\n if (target) {\r\n this.addRelationship(\r\n newId,\r\n target,\r\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\r\n );\r\n }\r\n\r\n return `r:embed=\"${newId}\"`;\r\n });\r\n });\r\n\r\n // Now unwrap the w:ins tags (content has unique remapped IDs)\r\n result = result.replace(/<\\/w:ins>/g, '');\r\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Final cleanup to remove any orphaned or malformed revision-related tags\r\n */\r\n private cleanupOrphanedTags(xml: string): string {\r\n let result = xml;\r\n\r\n // Remove any remaining self-closing revision tags\r\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\r\n\r\n // Remove empty w:r elements that might be left after removing deletions\r\n result = result.replace(/<w:r\\b[^>]*>\\s*<\\/w:r>/g, '');\r\n\r\n // Remove empty w:p elements (but preserve those with properties)\r\n // We keep <w:p><w:pPr>...</w:pPr></w:p> as those are intentional empty paragraphs with styling\r\n result = result.replace(/<w:p>\\s*<\\/w:p>/g, '');\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Parse relationship IDs from word/_rels/document.xml.rels\r\n * Returns a map of relationship ID to target path\r\n */\r\n private parseRelationships(): Map<string, string> {\r\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\r\n if (!relsXml) return new Map();\r\n\r\n const map = new Map<string, string>();\r\n const relationshipRegex = /<Relationship[^>]*Id=\"([^\"]+)\"[^>]*Target=\"([^\"]+)\"[^>]*\\/>/g;\r\n let match;\r\n\r\n while ((match = relationshipRegex.exec(relsXml)) !== null) {\r\n if (match[1] && match[2]) {\r\n map.set(match[1], match[2]); // rId -> target path\r\n }\r\n }\r\n\r\n return map;\r\n }\r\n\r\n /**\r\n * Get the next available relationship ID\r\n * Finds the highest numeric ID and increments it\r\n */\r\n private getNextRelationshipId(existingIds: Set<string>): string {\r\n let maxId = 0;\r\n for (const id of existingIds) {\r\n const num = parseInt(id.replace('rId', ''));\r\n if (!isNaN(num) && num > maxId) {\r\n maxId = num;\r\n }\r\n }\r\n return `rId${maxId + 1}`;\r\n }\r\n\r\n /**\r\n * Add a new relationship to word/_rels/document.xml.rels\r\n */\r\n private addRelationship(rId: string, target: string, type: string): void {\r\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\r\n if (!relsXml) return;\r\n\r\n // Insert new relationship before closing tag\r\n const newRel = `<Relationship Id=\"${rId}\" Type=\"${type}\" Target=\"${target}\"/>`;\r\n const updated = relsXml.replace('</Relationships>', `${newRel}\\n</Relationships>`);\r\n\r\n this.zipHandler.updateFile('word/_rels/document.xml.rels', updated);\r\n }\r\n\r\n /**\r\n * Clean up all revision metadata files (people.xml, settings.xml, core.xml).\r\n *\r\n * This removes:\r\n * - All revision authors from people.xml\r\n * - Track changes settings from settings.xml\r\n * - Resets revision count in core.xml\r\n *\r\n * Called as part of acceptAllRevisions() but can also be called separately\r\n * when using in-memory revision acceptance.\r\n */\r\n public cleanupMetadata(): void {\r\n this.cleanupPeopleXml();\r\n this.cleanupSettingsXml();\r\n this.cleanupCorePropsXml();\r\n }\r\n\r\n /**\r\n * Clean up word/people.xml - remove all revision authors\r\n *\r\n * Handles both w: and w15: namespace variants\r\n */\r\n private cleanupPeopleXml(): void {\r\n const peopleXml = this.zipHandler.getFileAsString('word/people.xml');\r\n if (!peopleXml) {\r\n return;\r\n }\r\n\r\n let content = peopleXml;\r\n\r\n // Remove all person elements in any namespace variant\r\n content = content.replace(/<w:person\\b[^>]*>[\\s\\S]*?<\\/w:person>/g, '');\r\n content = content.replace(/<w15:person\\b[^>]*>[\\s\\S]*?<\\/w15:person>/g, '');\r\n \r\n // Handle any namespace-prefixed variants (w1:, w2:, etc.)\r\n content = content.replace(/<w\\d+:person\\b[^>]*>[\\s\\S]*?<\\/w\\d+:person>/g, '');\r\n \r\n // Also remove self-closing person elements\r\n content = content.replace(/<w:person\\b[^>]*\\/>/g, '');\r\n content = content.replace(/<w15:person\\b[^>]*\\/>/g, '');\r\n content = content.replace(/<w\\d+:person\\b[^>]*\\/>/g, '');\r\n\r\n this.zipHandler.updateFile('word/people.xml', content);\r\n }\r\n\r\n /**\r\n * Clean up word/settings.xml - disable track changes\r\n */\r\n private cleanupSettingsXml(): void {\r\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\r\n if (!settingsXml) {\r\n return;\r\n }\r\n\r\n let content = settingsXml;\r\n\r\n // Remove trackRevisions element (enables tracking)\r\n content = content.replace(/<w:trackRevisions\\b[^>]*\\/>/g, '');\r\n content = content.replace(/<w:trackRevisions\\b[^>]*>[\\s\\S]*?<\\/w:trackRevisions>/g, '');\r\n\r\n // Remove revisionView element (controls which revisions are visible)\r\n content = content.replace(/<w:revisionView\\b[^>]*\\/>/g, '');\r\n content = content.replace(/<w:revisionView\\b[^>]*>[\\s\\S]*?<\\/w:revisionView>/g, '');\r\n\r\n // Remove doNotTrackMoves (prevents move tracking)\r\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*\\/>/g, '');\r\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackMoves>/g, '');\r\n\r\n // Remove doNotTrackFormatting\r\n content = content.replace(/<w:doNotTrackFormatting\\b[^>]*\\/>/g, '');\r\n content = content.replace(/<w:doNotTrackFormatting\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackFormatting>/g, '');\r\n\r\n this.zipHandler.updateFile('word/settings.xml', content);\r\n }\r\n\r\n /**\r\n * Clean up docProps/core.xml - reset revision count\r\n */\r\n private cleanupCorePropsXml(): void {\r\n const coreXml = this.zipHandler.getFileAsString('docProps/core.xml');\r\n if (!coreXml) {\r\n return;\r\n }\r\n\r\n // Reset revision count to 1\r\n const content = coreXml.replace(\r\n /<cp:revision>\\d+<\\/cp:revision>/g,\r\n '<cp:revision>1</cp:revision>'\r\n );\r\n\r\n this.zipHandler.updateFile('docProps/core.xml', content);\r\n }\r\n\r\n // =========================================================================\r\n // DOM-based processing helper methods\r\n // =========================================================================\r\n\r\n /**\r\n * Convert parsed XML object back to XML string\r\n * Preserves element order using _orderedChildren metadata\r\n *\r\n * Based on DocumentParser.objectToXml() implementation\r\n */\r\n private objectToXml(obj: any): string {\r\n const buildXml = (o: any, name?: string): string => {\r\n // Handle simple string/number with a tag name: <tagName>value</tagName>\r\n if (name && (typeof o === 'string' || typeof o === 'number')) {\r\n return `<${name}>${this.escapeXml(String(o))}</${name}>`;\r\n }\r\n if (typeof o === 'string') return this.escapeXml(o);\r\n if (typeof o !== 'object' || o === null) return String(o ?? '');\r\n\r\n const keys = Object.keys(o);\r\n\r\n // If a name is provided, we're building a specific element\r\n // Don't return empty string for empty objects with a name - they become self-closing tags\r\n if (keys.length === 0 && !name) return '';\r\n\r\n const tagName = name || keys[0]!;\r\n const element = name ? o : o[tagName];\r\n\r\n let xml = `<${tagName}`;\r\n\r\n // Add attributes (keys starting with @_)\r\n if (element && typeof element === 'object') {\r\n for (const key of Object.keys(element)) {\r\n if (key.startsWith('@_')) {\r\n const attrName = key.substring(2);\r\n xml += ` ${attrName}=\"${this.escapeXml(String(element[key]))}\"`;\r\n }\r\n }\r\n }\r\n\r\n // Check for children (non-attribute, non-text, non-metadata keys)\r\n const hasChildren =\r\n element &&\r\n typeof element === 'object' &&\r\n Object.keys(element).some(\r\n (k) =>\r\n !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\r\n );\r\n\r\n // Per ECMA-376, certain elements MUST NOT be self-closing (e.g., <w:p/> is invalid).\r\n // This mirrors the CANNOT_SELF_CLOSE list in XMLBuilder.ts.\r\n const CANNOT_SELF_CLOSE = [\r\n 'w:t', 'w:r', 'w:p', 'w:tbl', 'w:tr', 'w:tc', 'w:body',\r\n 'w:document', 'w:hyperlink', 'w:sdt', 'w:sdtContent', 'w:sdtPr',\r\n 'w:pPr', 'w:rPr', 'w:sectPr', 'w:del', 'w:ins', 'w:moveFrom', 'w:moveTo',\r\n ];\r\n\r\n if (!hasChildren && (!element?.['#text'])) {\r\n if (CANNOT_SELF_CLOSE.includes(tagName)) {\r\n xml += `></${tagName}>`;\r\n } else {\r\n xml += '/>';\r\n }\r\n } else {\r\n xml += '>';\r\n\r\n // Add text content\r\n if (element?.['#text']) {\r\n xml += this.escapeXml(String(element['#text']));\r\n }\r\n\r\n // Add child elements using _orderedChildren if available\r\n if (element && typeof element === 'object') {\r\n const orderedChildren = element._orderedChildren as\r\n | { type: string; index: number }[]\r\n | undefined;\r\n\r\n if (orderedChildren && orderedChildren.length > 0) {\r\n // Use _orderedChildren to preserve element order\r\n for (const childInfo of orderedChildren) {\r\n const childType = childInfo.type;\r\n const childIndex = childInfo.index;\r\n\r\n if (element[childType] !== undefined) {\r\n const children = element[childType];\r\n\r\n if (Array.isArray(children)) {\r\n if (childIndex < children.length) {\r\n const childXml = buildXml(children[childIndex], childType);\r\n xml += childXml;\r\n }\r\n } else {\r\n // Single child element\r\n if (childIndex === 0) {\r\n const childXml = buildXml(children, childType);\r\n xml += childXml;\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Fallback: iterate through keys if no _orderedChildren\r\n for (const key of Object.keys(element)) {\r\n if (\r\n !key.startsWith('@_') &&\r\n key !== '#text' &&\r\n key !== '_orderedChildren'\r\n ) {\r\n const children = element[key];\r\n if (Array.isArray(children)) {\r\n for (const child of children) {\r\n xml += buildXml(child, key);\r\n }\r\n } else {\r\n xml += buildXml(children, key);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n xml += `</${tagName}>`;\r\n }\r\n\r\n return xml;\r\n };\r\n\r\n return buildXml(obj);\r\n }\r\n\r\n /**\r\n * Escape special XML characters\r\n */\r\n private escapeXml(str: string): string {\r\n return str\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&apos;');\r\n }\r\n\r\n /**\r\n * Remap image relationship IDs in the parsed tree to prevent duplicates\r\n * Walks the tree looking for r:embed attributes and assigns unique IDs\r\n */\r\n private remapImageRelationshipsInTree(obj: any): void {\r\n const relationships = this.parseRelationships();\r\n const existingIds = new Set(relationships.keys());\r\n const remappedIds = new Map<string, string>();\r\n\r\n // Walk the tree and find all r:embed attributes\r\n this.walkTreeForEmbeds(obj, (embedId: string, parent: any, key: string) => {\r\n // Check if this ID has already been remapped\r\n if (remappedIds.has(embedId)) {\r\n parent[key] = remappedIds.get(embedId);\r\n return;\r\n }\r\n\r\n // Check if this ID needs remapping (duplicate)\r\n // For DOM-based processing, we check if we've seen this ID before in this pass\r\n const target = relationships.get(embedId);\r\n if (target) {\r\n // Generate new unique ID\r\n const newId = this.getNextRelationshipId(existingIds);\r\n existingIds.add(newId);\r\n remappedIds.set(embedId, newId);\r\n\r\n // Add relationship with same target\r\n this.addRelationship(\r\n newId,\r\n target,\r\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\r\n );\r\n\r\n // Update the attribute\r\n parent[key] = newId;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Walk the tree looking for r:embed attributes\r\n */\r\n private walkTreeForEmbeds(\r\n obj: any,\r\n callback: (embedId: string, parent: any, key: string) => void\r\n ): void {\r\n if (!obj || typeof obj !== 'object') {\r\n return;\r\n }\r\n\r\n for (const key of Object.keys(obj)) {\r\n // Check for r:embed attribute\r\n if (key === '@_r:embed') {\r\n callback(obj[key], obj, key);\r\n } else if (\r\n !key.startsWith('@_') &&\r\n key !== '#text' &&\r\n key !== '_orderedChildren'\r\n ) {\r\n const value = obj[key];\r\n if (Array.isArray(value)) {\r\n for (const item of value) {\r\n this.walkTreeForEmbeds(item, callback);\r\n }\r\n } else if (typeof value === 'object') {\r\n this.walkTreeForEmbeds(value, callback);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Convenience function to accept all revisions in a document\r\n */\r\nexport async function acceptAllRevisions(zipHandler: ZipHandler): Promise<void> {\r\n const acceptor = new RevisionAcceptor(zipHandler);\r\n await acceptor.acceptAllRevisions();\r\n}\r\n\r\n/**\r\n * Convenience function to clean up revision metadata files.\r\n *\r\n * This removes:\r\n * - All revision authors from people.xml\r\n * - Track changes settings from settings.xml\r\n * - Resets revision count in core.xml\r\n *\r\n * Use this after in-memory revision acceptance to ensure metadata is also cleaned.\r\n * The raw XML acceptAllRevisions() function calls this automatically.\r\n *\r\n * @param zipHandler - The ZipHandler containing the DOCX package\r\n */\r\nexport function cleanupRevisionMetadata(zipHandler: ZipHandler): void {\r\n const acceptor = new RevisionAcceptor(zipHandler);\r\n acceptor.cleanupMetadata();\r\n}\r\n"]}
1
+ {"version":3,"file":"acceptRevisions.js","sourceRoot":"","sources":["../../src/utils/acceptRevisions.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler';\nimport { XMLParser } from '../xml/XMLParser';\nimport { RevisionWalker } from './RevisionWalker';\n\n/**\n * Accepts all tracked changes in a Word document per Microsoft's OpenXML SDK pattern\n *\n * This implementation uses DOM-based tree walking for reliability:\n * 1. Insertions (<w:ins>): Keep content, remove wrapper tags\n * 2. Deletions (<w:del>): Remove entirely (content and tags)\n * 3. Move From (<w:moveFrom>): Remove entirely (source of move)\n * 4. Move To (<w:moveTo>): Keep content, remove wrapper (destination of move)\n * 5. Property changes: Remove all *Change elements\n * 6. Range markers: Remove all boundary markers\n *\n * Also cleans up metadata in people.xml, settings.xml, and core.xml\n *\n * @see https://learn.microsoft.com/en-us/office/open-xml/how-to-accept-all-revisions\n */\nclass RevisionAcceptor {\n private zipHandler: ZipHandler;\n /** Feature flag for DOM-based processing (default: true) */\n private useDomBasedProcessing = true;\n\n constructor(zipHandler: ZipHandler) {\n this.zipHandler = zipHandler;\n }\n\n /**\n * Enable or disable DOM-based processing (for testing/migration)\n */\n setUseDomBasedProcessing(enabled: boolean): void {\n this.useDomBasedProcessing = enabled;\n }\n\n /**\n * Main method to accept all revisions in the document\n */\n public async acceptAllRevisions(): Promise<void> {\n // Process document.xml\n await this.processDocumentPart('word/document.xml');\n\n // Process headers\n const files = this.zipHandler.getFilePaths();\n for (const file of files) {\n if (/^word\\/header\\d+\\.xml$/.exec(file)) {\n await this.processDocumentPart(file);\n }\n if (/^word\\/footer\\d+\\.xml$/.exec(file)) {\n await this.processDocumentPart(file);\n }\n }\n\n // Clean up metadata files\n this.cleanupPeopleXml();\n this.cleanupSettingsXml();\n this.cleanupCorePropsXml();\n }\n\n /**\n * Process a document part (document.xml, header, footer) to accept revisions\n */\n private async processDocumentPart(partPath: string): Promise<void> {\n if (this.useDomBasedProcessing) {\n return this.processDocumentPartDOM(partPath);\n }\n return this.processDocumentPartRegex(partPath);\n }\n\n /**\n * DOM-based implementation of revision acceptance\n * Uses XMLParser and RevisionWalker for reliable processing\n */\n private processDocumentPartDOM(partPath: string): void {\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml) {\n return;\n }\n\n // Step 1: Parse XML to object tree\n // IMPORTANT: trimValues: false preserves whitespace from xml:space=\"preserve\" attributes\n const parsed = XMLParser.parseToObject(xml, { trimValues: false });\n\n // Step 2: Process revisions using DOM walker\n const processed = RevisionWalker.processTree(parsed, {\n acceptInsertions: true,\n acceptDeletions: true,\n acceptMoves: true,\n acceptPropertyChanges: true,\n });\n\n // Step 3: Handle image relationship ID remapping\n this.remapImageRelationshipsInTree(processed);\n\n // Step 4: Convert back to XML\n const outputXml =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n' + this.objectToXml(processed);\n\n // Step 5: Update file\n this.zipHandler.updateFile(partPath, outputXml);\n }\n\n /**\n * Legacy RegEx-based implementation (kept as fallback)\n */\n private processDocumentPartRegex(partPath: string): void {\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml) {\n return;\n }\n\n let content = xml;\n\n // Step 1: Remove all range markers FIRST (before processing revisions)\n // This prevents orphaned references when revision content is modified\n content = this.removeAllRangeMarkers(content);\n\n // Step 2: Remove all property change elements\n // These track formatting changes and must be removed before other processing\n content = this.removeAllPropertyChanges(content);\n\n // Step 3: Process deletions - remove entire element INCLUDING content\n // Must be done before insertions to handle nested scenarios\n content = this.acceptDeletions(content);\n\n // Step 4: Process move operations\n // Remove moveFrom entirely (source), unwrap moveTo (destination)\n content = this.acceptMoveFrom(content);\n content = this.acceptMoveTo(content);\n\n // Step 5: Process insertions - keep content, remove wrapper\n content = this.acceptInsertions(content);\n\n // Step 6: Final cleanup - remove any remaining orphaned tags\n content = this.cleanupOrphanedTags(content);\n\n // Update the file\n this.zipHandler.updateFile(partPath, content);\n }\n\n /**\n * Remove all range marker elements\n * These are boundary markers for tracked changes and moves\n */\n private removeAllRangeMarkers(xml: string): string {\n const patterns = [\n // Move range markers\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\n // Custom XML range markers\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\n /<w:customXmlMoveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeStart>)/gs,\n /<w:customXmlMoveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeEnd>)/gs,\n /<w:customXmlMoveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeStart>)/gs,\n /<w:customXmlMoveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeEnd>)/gs,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n return result;\n }\n\n /**\n * Remove all property change tracking elements\n * Per ECMA-376, these track previous state of formatting\n */\n private removeAllPropertyChanges(xml: string): string {\n const patterns = [\n // Run property changes\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\n // Paragraph property changes\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\n // Table property changes\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\n // Table cell property changes\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\n // Table row property changes\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\n // Section property changes\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\n // Table grid changes\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\n // Numbering changes\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n return result;\n }\n\n /**\n * Accept deletions - remove the entire <w:del> element including its content\n *\n * Per Microsoft SDK: \"DeletedRun elements should be removed along with their content\"\n */\n private acceptDeletions(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Iterate until no more deletions (handles nested cases)\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Match complete <w:del ...>...</w:del> elements and remove entirely\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\n }\n\n // Also remove self-closing deletion tags\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n\n return result;\n }\n\n /**\n * Accept moveFrom - remove the entire element (source of moved content)\n *\n * The content exists at the moveTo destination, so we discard the source\n */\n private acceptMoveFrom(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\n }\n\n // Also remove self-closing tags\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n\n return result;\n }\n\n /**\n * Accept moveTo - keep the content, remove the wrapper tags\n *\n * The moveTo location is where the content should remain\n */\n private acceptMoveTo(xml: string): string {\n let result = xml;\n\n // Remove closing tags first (prevents issues with regex matching)\n result = result.replace(/<\\/w:moveTo>/g, '');\n\n // Remove opening tags (keeps content that was inside)\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Accept insertions - keep the content, remove the wrapper tags\n *\n * Per Microsoft SDK: \"InsertedRun elements should be unwrapped, keeping their content\"\n *\n * IMPORTANT: This method now handles relationship ID remapping for images inside insertions.\n * When Word tracks changes with images, it can reuse relationship IDs (like rId5) because\n * they're in separate tracked change contexts. But when we unwrap them, duplicate IDs\n * cause corruption. This method assigns new unique IDs to images inside insertions.\n */\n private acceptInsertions(xml: string): string {\n let result = xml;\n\n // Parse existing relationships\n const relationships = this.parseRelationships();\n const existingIds = new Set(relationships.keys());\n\n // Process each w:ins element and remap images one by one\n const insRegex = /<w:ins\\b[^>]*>[\\s\\S]*?<\\/w:ins>/g;\n\n result = result.replace(insRegex, (insMatch) => {\n // For each image reference inside this insertion, generate a unique new ID\n return insMatch.replace(/r:embed=\"(rId\\d+)\"/g, (embedMatch, oldId) => {\n // Generate new unique ID for THIS occurrence\n const newId = this.getNextRelationshipId(existingIds);\n existingIds.add(newId);\n\n // Add relationship with same target as original\n const target = relationships.get(oldId);\n if (target) {\n this.addRelationship(\n newId,\n target,\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\n );\n }\n\n return `r:embed=\"${newId}\"`;\n });\n });\n\n // Now unwrap the w:ins tags (content has unique remapped IDs)\n result = result.replace(/<\\/w:ins>/g, '');\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Final cleanup to remove any orphaned or malformed revision-related tags\n */\n private cleanupOrphanedTags(xml: string): string {\n let result = xml;\n\n // Remove any remaining self-closing revision tags\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\n\n // Remove empty w:r elements that might be left after removing deletions\n result = result.replace(/<w:r\\b[^>]*>\\s*<\\/w:r>/g, '');\n\n // Remove empty w:p elements (but preserve those with properties)\n // We keep <w:p><w:pPr>...</w:pPr></w:p> as those are intentional empty paragraphs with styling\n result = result.replace(/<w:p>\\s*<\\/w:p>/g, '');\n\n return result;\n }\n\n /**\n * Parse relationship IDs from word/_rels/document.xml.rels\n * Returns a map of relationship ID to target path\n */\n private parseRelationships(): Map<string, string> {\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\n if (!relsXml) return new Map();\n\n const map = new Map<string, string>();\n const relationshipRegex = /<Relationship[^>]*Id=\"([^\"]+)\"[^>]*Target=\"([^\"]+)\"[^>]*\\/>/g;\n let match;\n\n while ((match = relationshipRegex.exec(relsXml)) !== null) {\n if (match[1] && match[2]) {\n map.set(match[1], match[2]); // rId -> target path\n }\n }\n\n return map;\n }\n\n /**\n * Get the next available relationship ID\n * Finds the highest numeric ID and increments it\n */\n private getNextRelationshipId(existingIds: Set<string>): string {\n let maxId = 0;\n for (const id of existingIds) {\n const num = parseInt(id.replace('rId', ''));\n if (!isNaN(num) && num > maxId) {\n maxId = num;\n }\n }\n return `rId${maxId + 1}`;\n }\n\n /**\n * Add a new relationship to word/_rels/document.xml.rels\n */\n private addRelationship(rId: string, target: string, type: string): void {\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\n if (!relsXml) return;\n\n // Insert new relationship before closing tag\n const newRel = `<Relationship Id=\"${rId}\" Type=\"${type}\" Target=\"${target}\"/>`;\n const updated = relsXml.replace('</Relationships>', `${newRel}\\n</Relationships>`);\n\n this.zipHandler.updateFile('word/_rels/document.xml.rels', updated);\n }\n\n /**\n * Clean up all revision metadata files (people.xml, settings.xml, core.xml).\n *\n * This removes:\n * - All revision authors from people.xml\n * - Track changes settings from settings.xml\n * - Resets revision count in core.xml\n *\n * Called as part of acceptAllRevisions() but can also be called separately\n * when using in-memory revision acceptance.\n */\n public cleanupMetadata(): void {\n this.cleanupPeopleXml();\n this.cleanupSettingsXml();\n this.cleanupCorePropsXml();\n }\n\n /**\n * Clean up word/people.xml - remove all revision authors\n *\n * Handles both w: and w15: namespace variants\n */\n private cleanupPeopleXml(): void {\n const peopleXml = this.zipHandler.getFileAsString('word/people.xml');\n if (!peopleXml) {\n return;\n }\n\n let content = peopleXml;\n\n // Remove all person elements in any namespace variant\n content = content.replace(/<w:person\\b[^>]*>[\\s\\S]*?<\\/w:person>/g, '');\n content = content.replace(/<w15:person\\b[^>]*>[\\s\\S]*?<\\/w15:person>/g, '');\n\n // Handle any namespace-prefixed variants (w1:, w2:, etc.)\n content = content.replace(/<w\\d+:person\\b[^>]*>[\\s\\S]*?<\\/w\\d+:person>/g, '');\n\n // Also remove self-closing person elements\n content = content.replace(/<w:person\\b[^>]*\\/>/g, '');\n content = content.replace(/<w15:person\\b[^>]*\\/>/g, '');\n content = content.replace(/<w\\d+:person\\b[^>]*\\/>/g, '');\n\n this.zipHandler.updateFile('word/people.xml', content);\n }\n\n /**\n * Clean up word/settings.xml - disable track changes\n */\n private cleanupSettingsXml(): void {\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\n if (!settingsXml) {\n return;\n }\n\n let content = settingsXml;\n\n // Remove trackRevisions element (enables tracking)\n content = content.replace(/<w:trackRevisions\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:trackRevisions\\b[^>]*>[\\s\\S]*?<\\/w:trackRevisions>/g, '');\n\n // Remove revisionView element (controls which revisions are visible)\n content = content.replace(/<w:revisionView\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:revisionView\\b[^>]*>[\\s\\S]*?<\\/w:revisionView>/g, '');\n\n // Remove doNotTrackMoves (prevents move tracking)\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackMoves>/g, '');\n\n // Remove doNotTrackFormatting\n content = content.replace(/<w:doNotTrackFormatting\\b[^>]*\\/>/g, '');\n content = content.replace(\n /<w:doNotTrackFormatting\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackFormatting>/g,\n ''\n );\n\n this.zipHandler.updateFile('word/settings.xml', content);\n }\n\n /**\n * Clean up docProps/core.xml - reset revision count\n */\n private cleanupCorePropsXml(): void {\n const coreXml = this.zipHandler.getFileAsString('docProps/core.xml');\n if (!coreXml) {\n return;\n }\n\n // Reset revision count to 1\n const content = coreXml.replace(\n /<cp:revision>\\d+<\\/cp:revision>/g,\n '<cp:revision>1</cp:revision>'\n );\n\n this.zipHandler.updateFile('docProps/core.xml', content);\n }\n\n // =========================================================================\n // DOM-based processing helper methods\n // =========================================================================\n\n /**\n * Convert parsed XML object back to XML string\n * Preserves element order using _orderedChildren metadata\n *\n * Based on DocumentParser.objectToXml() implementation\n */\n private objectToXml(obj: any): string {\n const buildXml = (o: any, name?: string): string => {\n // Handle simple string/number with a tag name: <tagName>value</tagName>\n if (name && (typeof o === 'string' || typeof o === 'number')) {\n return `<${name}>${this.escapeXml(String(o))}</${name}>`;\n }\n if (typeof o === 'string') return this.escapeXml(o);\n if (typeof o !== 'object' || o === null) return String(o ?? '');\n\n const keys = Object.keys(o);\n\n // If a name is provided, we're building a specific element\n // Don't return empty string for empty objects with a name - they become self-closing tags\n if (keys.length === 0 && !name) return '';\n\n const tagName = name || keys[0]!;\n const element = name ? o : o[tagName];\n\n let xml = `<${tagName}`;\n\n // Add attributes (keys starting with @_)\n if (element && typeof element === 'object') {\n for (const key of Object.keys(element)) {\n if (key.startsWith('@_')) {\n const attrName = key.substring(2);\n xml += ` ${attrName}=\"${this.escapeXml(String(element[key]))}\"`;\n }\n }\n }\n\n // Check for children (non-attribute, non-text, non-metadata keys)\n const hasChildren =\n element &&\n typeof element === 'object' &&\n Object.keys(element).some(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n // Per ECMA-376, certain elements MUST NOT be self-closing (e.g., <w:p/> is invalid).\n // This mirrors the CANNOT_SELF_CLOSE list in XMLBuilder.ts.\n const CANNOT_SELF_CLOSE = [\n 'w:t',\n 'w:r',\n 'w:p',\n 'w:tbl',\n 'w:tr',\n 'w:tc',\n 'w:body',\n 'w:document',\n 'w:hyperlink',\n 'w:sdt',\n 'w:sdtContent',\n 'w:sdtPr',\n 'w:pPr',\n 'w:rPr',\n 'w:sectPr',\n 'w:del',\n 'w:ins',\n 'w:moveFrom',\n 'w:moveTo',\n ];\n\n if (!hasChildren && !element?.['#text']) {\n if (CANNOT_SELF_CLOSE.includes(tagName)) {\n xml += `></${tagName}>`;\n } else {\n xml += '/>';\n }\n } else {\n xml += '>';\n\n // Add text content\n if (element?.['#text']) {\n xml += this.escapeXml(String(element['#text']));\n }\n\n // Add child elements using _orderedChildren if available\n if (element && typeof element === 'object') {\n const orderedChildren = element._orderedChildren as\n | { type: string; index: number }[]\n | undefined;\n\n if (orderedChildren && orderedChildren.length > 0) {\n // Use _orderedChildren to preserve element order\n for (const childInfo of orderedChildren) {\n const childType = childInfo.type;\n const childIndex = childInfo.index;\n\n if (element[childType] !== undefined) {\n const children = element[childType];\n\n if (Array.isArray(children)) {\n if (childIndex < children.length) {\n const childXml = buildXml(children[childIndex], childType);\n xml += childXml;\n }\n } else {\n // Single child element\n if (childIndex === 0) {\n const childXml = buildXml(children, childType);\n xml += childXml;\n }\n }\n }\n }\n } else {\n // Fallback: iterate through keys if no _orderedChildren\n for (const key of Object.keys(element)) {\n if (!key.startsWith('@_') && key !== '#text' && key !== '_orderedChildren') {\n const children = element[key];\n if (Array.isArray(children)) {\n for (const child of children) {\n xml += buildXml(child, key);\n }\n } else {\n xml += buildXml(children, key);\n }\n }\n }\n }\n }\n\n xml += `</${tagName}>`;\n }\n\n return xml;\n };\n\n return buildXml(obj);\n }\n\n /**\n * Escape special XML characters\n */\n private escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n /**\n * Remap image relationship IDs in the parsed tree to prevent duplicates\n * Walks the tree looking for r:embed attributes and assigns unique IDs\n */\n private remapImageRelationshipsInTree(obj: any): void {\n const relationships = this.parseRelationships();\n const existingIds = new Set(relationships.keys());\n const remappedIds = new Map<string, string>();\n\n // Walk the tree and find all r:embed attributes\n this.walkTreeForEmbeds(obj, (embedId: string, parent: any, key: string) => {\n // Check if this ID has already been remapped\n if (remappedIds.has(embedId)) {\n parent[key] = remappedIds.get(embedId);\n return;\n }\n\n // Check if this ID needs remapping (duplicate)\n // For DOM-based processing, we check if we've seen this ID before in this pass\n const target = relationships.get(embedId);\n if (target) {\n // Generate new unique ID\n const newId = this.getNextRelationshipId(existingIds);\n existingIds.add(newId);\n remappedIds.set(embedId, newId);\n\n // Add relationship with same target\n this.addRelationship(\n newId,\n target,\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\n );\n\n // Update the attribute\n parent[key] = newId;\n }\n });\n }\n\n /**\n * Walk the tree looking for r:embed attributes\n */\n private walkTreeForEmbeds(\n obj: any,\n callback: (embedId: string, parent: any, key: string) => void\n ): void {\n if (!obj || typeof obj !== 'object') {\n return;\n }\n\n for (const key of Object.keys(obj)) {\n // Check for r:embed attribute\n if (key === '@_r:embed') {\n callback(obj[key], obj, key);\n } else if (!key.startsWith('@_') && key !== '#text' && key !== '_orderedChildren') {\n const value = obj[key];\n if (Array.isArray(value)) {\n for (const item of value) {\n this.walkTreeForEmbeds(item, callback);\n }\n } else if (typeof value === 'object') {\n this.walkTreeForEmbeds(value, callback);\n }\n }\n }\n }\n}\n\n/**\n * Convenience function to accept all revisions in a document\n */\nexport async function acceptAllRevisions(zipHandler: ZipHandler): Promise<void> {\n const acceptor = new RevisionAcceptor(zipHandler);\n await acceptor.acceptAllRevisions();\n}\n\n/**\n * Convenience function to clean up revision metadata files.\n *\n * This removes:\n * - All revision authors from people.xml\n * - Track changes settings from settings.xml\n * - Resets revision count in core.xml\n *\n * Use this after in-memory revision acceptance to ensure metadata is also cleaned.\n * The raw XML acceptAllRevisions() function calls this automatically.\n *\n * @param zipHandler - The ZipHandler containing the DOCX package\n */\nexport function cleanupRevisionMetadata(zipHandler: ZipHandler): void {\n const acceptor = new RevisionAcceptor(zipHandler);\n acceptor.cleanupMetadata();\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { ConditionalFormattingType } from "../formatting/Style";
1
+ import { ConditionalFormattingType } from '../formatting/Style';
2
2
  export interface CnfStyleFlags {
3
3
  firstRow: boolean;
4
4
  lastRow: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"cnfStyleDecoder.d.ts","sourceRoot":"","sources":["../../src/utils/cnfStyleDecoder.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAMhE,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,OAAO,CAAC;IAElB,OAAO,EAAE,OAAO,CAAC;IAEjB,QAAQ,EAAE,OAAO,CAAC;IAElB,OAAO,EAAE,OAAO,CAAC;IAEjB,SAAS,EAAE,OAAO,CAAC;IAEnB,SAAS,EAAE,OAAO,CAAC;IAEnB,SAAS,EAAE,OAAO,CAAC;IAEnB,SAAS,EAAE,OAAO,CAAC;IAEnB,MAAM,EAAE,OAAO,CAAC;IAEhB,MAAM,EAAE,OAAO,CAAC;IAEhB,MAAM,EAAE,OAAO,CAAC;IAEhB,MAAM,EAAE,OAAO,CAAC;CACjB;AAKD,eAAO,MAAM,sBAAsB,EAAE,MAAM,CACzC,MAAM,aAAa,EACnB,yBAAyB,CAc1B,CAAC;AA0BF,eAAO,MAAM,0BAA0B,EAAE,CAAC,MAAM,aAAa,CAAC,EAgB7D,CAAC;AAeF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAmB9D;AAcD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAUpE;AAcD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GACf,yBAAyB,EAAE,CAW7B;AAgBD,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,MAAM,GACf,yBAAyB,EAAE,CAW7B"}
1
+ {"version":3,"file":"cnfStyleDecoder.d.ts","sourceRoot":"","sources":["../../src/utils/cnfStyleDecoder.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAMhE,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,OAAO,CAAC;IAElB,OAAO,EAAE,OAAO,CAAC;IAEjB,QAAQ,EAAE,OAAO,CAAC;IAElB,OAAO,EAAE,OAAO,CAAC;IAEjB,SAAS,EAAE,OAAO,CAAC;IAEnB,SAAS,EAAE,OAAO,CAAC;IAEnB,SAAS,EAAE,OAAO,CAAC;IAEnB,SAAS,EAAE,OAAO,CAAC;IAEnB,MAAM,EAAE,OAAO,CAAC;IAEhB,MAAM,EAAE,OAAO,CAAC;IAEhB,MAAM,EAAE,OAAO,CAAC;IAEhB,MAAM,EAAE,OAAO,CAAC;CACjB;AAKD,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,aAAa,EAAE,yBAAyB,CAazF,CAAC;AA0BF,eAAO,MAAM,0BAA0B,EAAE,CAAC,MAAM,aAAa,CAAC,EAgB7D,CAAC;AAeF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAmB9D;AAcD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAUpE;AAcD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,yBAAyB,EAAE,CAWnF;AAgBD,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,MAAM,GACf,yBAAyB,EAAE,CAW7B"}
@@ -6,18 +6,18 @@ exports.encodeCnfStyle = encodeCnfStyle;
6
6
  exports.getActiveConditionals = getActiveConditionals;
7
7
  exports.getActiveConditionalsInPriorityOrder = getActiveConditionalsInPriorityOrder;
8
8
  exports.CNF_TO_CONDITIONAL_MAP = {
9
- firstRow: "firstRow",
10
- lastRow: "lastRow",
11
- firstCol: "firstCol",
12
- lastCol: "lastCol",
13
- band1Vert: "band1Vert",
14
- band2Vert: "band2Vert",
15
- band1Horz: "band1Horz",
16
- band2Horz: "band2Horz",
17
- neCell: "neCell",
18
- nwCell: "nwCell",
19
- seCell: "seCell",
20
- swCell: "swCell",
9
+ firstRow: 'firstRow',
10
+ lastRow: 'lastRow',
11
+ firstCol: 'firstCol',
12
+ lastCol: 'lastCol',
13
+ band1Vert: 'band1Vert',
14
+ band2Vert: 'band2Vert',
15
+ band1Horz: 'band1Horz',
16
+ band2Horz: 'band2Horz',
17
+ neCell: 'neCell',
18
+ nwCell: 'nwCell',
19
+ seCell: 'seCell',
20
+ swCell: 'swCell',
21
21
  };
22
22
  const BIT_POSITIONS = {
23
23
  firstRow: 0,
@@ -34,44 +34,44 @@ const BIT_POSITIONS = {
34
34
  swCell: 11,
35
35
  };
36
36
  exports.CONDITIONAL_PRIORITY_ORDER = [
37
- "nwCell",
38
- "neCell",
39
- "swCell",
40
- "seCell",
41
- "firstRow",
42
- "lastRow",
43
- "firstCol",
44
- "lastCol",
45
- "band1Horz",
46
- "band2Horz",
47
- "band1Vert",
48
- "band2Vert",
37
+ 'nwCell',
38
+ 'neCell',
39
+ 'swCell',
40
+ 'seCell',
41
+ 'firstRow',
42
+ 'lastRow',
43
+ 'firstCol',
44
+ 'lastCol',
45
+ 'band1Horz',
46
+ 'band2Horz',
47
+ 'band1Vert',
48
+ 'band2Vert',
49
49
  ];
50
50
  function decodeCnfStyle(cnfStyle) {
51
- const normalized = cnfStyle.padEnd(12, "0");
51
+ const normalized = cnfStyle.padEnd(12, '0');
52
52
  return {
53
- firstRow: normalized.startsWith("1"),
54
- lastRow: normalized[BIT_POSITIONS.lastRow] === "1",
55
- firstCol: normalized[BIT_POSITIONS.firstCol] === "1",
56
- lastCol: normalized[BIT_POSITIONS.lastCol] === "1",
57
- band1Vert: normalized[BIT_POSITIONS.band1Vert] === "1",
58
- band2Vert: normalized[BIT_POSITIONS.band2Vert] === "1",
59
- band1Horz: normalized[BIT_POSITIONS.band1Horz] === "1",
60
- band2Horz: normalized[BIT_POSITIONS.band2Horz] === "1",
61
- neCell: normalized[BIT_POSITIONS.neCell] === "1",
62
- nwCell: normalized[BIT_POSITIONS.nwCell] === "1",
63
- seCell: normalized[BIT_POSITIONS.seCell] === "1",
64
- swCell: normalized[BIT_POSITIONS.swCell] === "1",
53
+ firstRow: normalized.startsWith('1'),
54
+ lastRow: normalized[BIT_POSITIONS.lastRow] === '1',
55
+ firstCol: normalized[BIT_POSITIONS.firstCol] === '1',
56
+ lastCol: normalized[BIT_POSITIONS.lastCol] === '1',
57
+ band1Vert: normalized[BIT_POSITIONS.band1Vert] === '1',
58
+ band2Vert: normalized[BIT_POSITIONS.band2Vert] === '1',
59
+ band1Horz: normalized[BIT_POSITIONS.band1Horz] === '1',
60
+ band2Horz: normalized[BIT_POSITIONS.band2Horz] === '1',
61
+ neCell: normalized[BIT_POSITIONS.neCell] === '1',
62
+ nwCell: normalized[BIT_POSITIONS.nwCell] === '1',
63
+ seCell: normalized[BIT_POSITIONS.seCell] === '1',
64
+ swCell: normalized[BIT_POSITIONS.swCell] === '1',
65
65
  };
66
66
  }
67
67
  function encodeCnfStyle(flags) {
68
- const bits = new Array(12).fill("0");
68
+ const bits = new Array(12).fill('0');
69
69
  for (const [key, position] of Object.entries(BIT_POSITIONS)) {
70
70
  if (flags[key]) {
71
- bits[position] = "1";
71
+ bits[position] = '1';
72
72
  }
73
73
  }
74
- return bits.join("");
74
+ return bits.join('');
75
75
  }
76
76
  function getActiveConditionals(cnfStyle) {
77
77
  const flags = decodeCnfStyle(cnfStyle);
@@ -1 +1 @@
1
- {"version":3,"file":"cnfStyleDecoder.js","sourceRoot":"","sources":["../../src/utils/cnfStyleDecoder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * cnfStyle Decoder - Decodes the conditional formatting style bitmask\r\n * Per ECMA-376 Part 1 Section 17.4.7 (w:cnfStyle)\r\n *\r\n * The cnfStyle is a 12-character string where each character is '0' or '1'\r\n * representing whether a particular conditional format applies.\r\n */\r\n\r\nimport { ConditionalFormattingType } from \"../formatting/Style\";\r\n\r\n/**\r\n * Decoded cnfStyle flags\r\n * Each flag corresponds to a conditional formatting type that may apply to a cell\r\n */\r\nexport interface CnfStyleFlags {\r\n /** First row of table (header row) */\r\n firstRow: boolean;\r\n /** Last row of table */\r\n lastRow: boolean;\r\n /** First column of table */\r\n firstCol: boolean;\r\n /** Last column of table */\r\n lastCol: boolean;\r\n /** Odd vertical band (column banding) */\r\n band1Vert: boolean;\r\n /** Even vertical band (column banding) */\r\n band2Vert: boolean;\r\n /** Odd horizontal band (row banding) */\r\n band1Horz: boolean;\r\n /** Even horizontal band (row banding) */\r\n band2Horz: boolean;\r\n /** Northeast cell (top-right corner) */\r\n neCell: boolean;\r\n /** Northwest cell (top-left corner) */\r\n nwCell: boolean;\r\n /** Southeast cell (bottom-right corner) */\r\n seCell: boolean;\r\n /** Southwest cell (bottom-left corner) */\r\n swCell: boolean;\r\n}\r\n\r\n/**\r\n * Maps flag names to ConditionalFormattingType values\r\n */\r\nexport const CNF_TO_CONDITIONAL_MAP: Record<\r\n keyof CnfStyleFlags,\r\n ConditionalFormattingType\r\n> = {\r\n firstRow: \"firstRow\",\r\n lastRow: \"lastRow\",\r\n firstCol: \"firstCol\",\r\n lastCol: \"lastCol\",\r\n band1Vert: \"band1Vert\",\r\n band2Vert: \"band2Vert\",\r\n band1Horz: \"band1Horz\",\r\n band2Horz: \"band2Horz\",\r\n neCell: \"neCell\",\r\n nwCell: \"nwCell\",\r\n seCell: \"seCell\",\r\n swCell: \"swCell\",\r\n};\r\n\r\n/**\r\n * Bit positions in the cnfStyle string (0-indexed from left)\r\n * Per ECMA-376 Part 1 Section 17.4.7\r\n */\r\nconst BIT_POSITIONS: Record<keyof CnfStyleFlags, number> = {\r\n firstRow: 0,\r\n lastRow: 1,\r\n firstCol: 2,\r\n lastCol: 3,\r\n band1Vert: 4,\r\n band2Vert: 5,\r\n band1Horz: 6,\r\n band2Horz: 7,\r\n neCell: 8,\r\n nwCell: 9,\r\n seCell: 10,\r\n swCell: 11,\r\n};\r\n\r\n/**\r\n * Priority order for conditional formatting resolution\r\n * More specific conditions (corners) override less specific (edges, banding)\r\n * Per ECMA-376, this is the order in which conditionals should be applied\r\n */\r\nexport const CONDITIONAL_PRIORITY_ORDER: (keyof CnfStyleFlags)[] = [\r\n // Corner cells (most specific)\r\n \"nwCell\",\r\n \"neCell\",\r\n \"swCell\",\r\n \"seCell\",\r\n // Edge rows/columns\r\n \"firstRow\",\r\n \"lastRow\",\r\n \"firstCol\",\r\n \"lastCol\",\r\n // Banding (least specific)\r\n \"band1Horz\",\r\n \"band2Horz\",\r\n \"band1Vert\",\r\n \"band2Vert\",\r\n];\r\n\r\n/**\r\n * Decodes a cnfStyle string into individual flags\r\n *\r\n * @param cnfStyle - 12-character binary string (e.g., \"100000000000\" for firstRow)\r\n * @returns Decoded flags object\r\n *\r\n * @example\r\n * ```typescript\r\n * const flags = decodeCnfStyle('100000000000');\r\n * console.log(flags.firstRow); // true\r\n * console.log(flags.lastRow); // false\r\n * ```\r\n */\r\nexport function decodeCnfStyle(cnfStyle: string): CnfStyleFlags {\r\n // Pad to 12 characters if shorter (handles legacy or truncated values)\r\n // Use padEnd because the string represents left-to-right bit positions\r\n const normalized = cnfStyle.padEnd(12, \"0\");\r\n\r\n return {\r\n firstRow: normalized.startsWith(\"1\"),\r\n lastRow: normalized[BIT_POSITIONS.lastRow] === \"1\",\r\n firstCol: normalized[BIT_POSITIONS.firstCol] === \"1\",\r\n lastCol: normalized[BIT_POSITIONS.lastCol] === \"1\",\r\n band1Vert: normalized[BIT_POSITIONS.band1Vert] === \"1\",\r\n band2Vert: normalized[BIT_POSITIONS.band2Vert] === \"1\",\r\n band1Horz: normalized[BIT_POSITIONS.band1Horz] === \"1\",\r\n band2Horz: normalized[BIT_POSITIONS.band2Horz] === \"1\",\r\n neCell: normalized[BIT_POSITIONS.neCell] === \"1\",\r\n nwCell: normalized[BIT_POSITIONS.nwCell] === \"1\",\r\n seCell: normalized[BIT_POSITIONS.seCell] === \"1\",\r\n swCell: normalized[BIT_POSITIONS.swCell] === \"1\",\r\n };\r\n}\r\n\r\n/**\r\n * Encodes CnfStyleFlags back to a binary string\r\n *\r\n * @param flags - Flags to encode\r\n * @returns 12-character binary string\r\n *\r\n * @example\r\n * ```typescript\r\n * const cnfStyle = encodeCnfStyle({ firstRow: true, lastCol: true });\r\n * console.log(cnfStyle); // '100100000000'\r\n * ```\r\n */\r\nexport function encodeCnfStyle(flags: Partial<CnfStyleFlags>): string {\r\n const bits = new Array(12).fill(\"0\");\r\n\r\n for (const [key, position] of Object.entries(BIT_POSITIONS)) {\r\n if (flags[key as keyof CnfStyleFlags]) {\r\n bits[position] = \"1\";\r\n }\r\n }\r\n\r\n return bits.join(\"\");\r\n}\r\n\r\n/**\r\n * Gets the active conditional formatting types from a cnfStyle\r\n *\r\n * @param cnfStyle - The cnfStyle string to decode\r\n * @returns Array of active ConditionalFormattingType values\r\n *\r\n * @example\r\n * ```typescript\r\n * const types = getActiveConditionals('110000000000');\r\n * console.log(types); // ['firstRow', 'lastRow']\r\n * ```\r\n */\r\nexport function getActiveConditionals(\r\n cnfStyle: string\r\n): ConditionalFormattingType[] {\r\n const flags = decodeCnfStyle(cnfStyle);\r\n const active: ConditionalFormattingType[] = [];\r\n\r\n for (const [key, isActive] of Object.entries(flags)) {\r\n if (isActive) {\r\n active.push(CNF_TO_CONDITIONAL_MAP[key as keyof CnfStyleFlags]);\r\n }\r\n }\r\n\r\n return active;\r\n}\r\n\r\n/**\r\n * Gets the active conditional formatting types in priority order\r\n * More specific conditions come first (corners before edges before banding)\r\n *\r\n * @param cnfStyle - The cnfStyle string to decode\r\n * @returns Array of active ConditionalFormattingType values in priority order\r\n *\r\n * @example\r\n * ```typescript\r\n * // Cell is both in first row and is the nwCell (top-left corner)\r\n * const types = getActiveConditionalsInPriorityOrder('100000000100');\r\n * console.log(types); // ['nwCell', 'firstRow'] - corner takes priority\r\n * ```\r\n */\r\nexport function getActiveConditionalsInPriorityOrder(\r\n cnfStyle: string\r\n): ConditionalFormattingType[] {\r\n const flags = decodeCnfStyle(cnfStyle);\r\n const active: ConditionalFormattingType[] = [];\r\n\r\n for (const flagName of CONDITIONAL_PRIORITY_ORDER) {\r\n if (flags[flagName]) {\r\n active.push(CNF_TO_CONDITIONAL_MAP[flagName]);\r\n }\r\n }\r\n\r\n return active;\r\n}\r\n"]}
1
+ {"version":3,"file":"cnfStyleDecoder.js","sourceRoot":"","sources":["../../src/utils/cnfStyleDecoder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * cnfStyle Decoder - Decodes the conditional formatting style bitmask\n * Per ECMA-376 Part 1 Section 17.4.7 (w:cnfStyle)\n *\n * The cnfStyle is a 12-character string where each character is '0' or '1'\n * representing whether a particular conditional format applies.\n */\n\nimport { ConditionalFormattingType } from '../formatting/Style';\n\n/**\n * Decoded cnfStyle flags\n * Each flag corresponds to a conditional formatting type that may apply to a cell\n */\nexport interface CnfStyleFlags {\n /** First row of table (header row) */\n firstRow: boolean;\n /** Last row of table */\n lastRow: boolean;\n /** First column of table */\n firstCol: boolean;\n /** Last column of table */\n lastCol: boolean;\n /** Odd vertical band (column banding) */\n band1Vert: boolean;\n /** Even vertical band (column banding) */\n band2Vert: boolean;\n /** Odd horizontal band (row banding) */\n band1Horz: boolean;\n /** Even horizontal band (row banding) */\n band2Horz: boolean;\n /** Northeast cell (top-right corner) */\n neCell: boolean;\n /** Northwest cell (top-left corner) */\n nwCell: boolean;\n /** Southeast cell (bottom-right corner) */\n seCell: boolean;\n /** Southwest cell (bottom-left corner) */\n swCell: boolean;\n}\n\n/**\n * Maps flag names to ConditionalFormattingType values\n */\nexport const CNF_TO_CONDITIONAL_MAP: Record<keyof CnfStyleFlags, ConditionalFormattingType> = {\n firstRow: 'firstRow',\n lastRow: 'lastRow',\n firstCol: 'firstCol',\n lastCol: 'lastCol',\n band1Vert: 'band1Vert',\n band2Vert: 'band2Vert',\n band1Horz: 'band1Horz',\n band2Horz: 'band2Horz',\n neCell: 'neCell',\n nwCell: 'nwCell',\n seCell: 'seCell',\n swCell: 'swCell',\n};\n\n/**\n * Bit positions in the cnfStyle string (0-indexed from left)\n * Per ECMA-376 Part 1 Section 17.4.7\n */\nconst BIT_POSITIONS: Record<keyof CnfStyleFlags, number> = {\n firstRow: 0,\n lastRow: 1,\n firstCol: 2,\n lastCol: 3,\n band1Vert: 4,\n band2Vert: 5,\n band1Horz: 6,\n band2Horz: 7,\n neCell: 8,\n nwCell: 9,\n seCell: 10,\n swCell: 11,\n};\n\n/**\n * Priority order for conditional formatting resolution\n * More specific conditions (corners) override less specific (edges, banding)\n * Per ECMA-376, this is the order in which conditionals should be applied\n */\nexport const CONDITIONAL_PRIORITY_ORDER: (keyof CnfStyleFlags)[] = [\n // Corner cells (most specific)\n 'nwCell',\n 'neCell',\n 'swCell',\n 'seCell',\n // Edge rows/columns\n 'firstRow',\n 'lastRow',\n 'firstCol',\n 'lastCol',\n // Banding (least specific)\n 'band1Horz',\n 'band2Horz',\n 'band1Vert',\n 'band2Vert',\n];\n\n/**\n * Decodes a cnfStyle string into individual flags\n *\n * @param cnfStyle - 12-character binary string (e.g., \"100000000000\" for firstRow)\n * @returns Decoded flags object\n *\n * @example\n * ```typescript\n * const flags = decodeCnfStyle('100000000000');\n * console.log(flags.firstRow); // true\n * console.log(flags.lastRow); // false\n * ```\n */\nexport function decodeCnfStyle(cnfStyle: string): CnfStyleFlags {\n // Pad to 12 characters if shorter (handles legacy or truncated values)\n // Use padEnd because the string represents left-to-right bit positions\n const normalized = cnfStyle.padEnd(12, '0');\n\n return {\n firstRow: normalized.startsWith('1'),\n lastRow: normalized[BIT_POSITIONS.lastRow] === '1',\n firstCol: normalized[BIT_POSITIONS.firstCol] === '1',\n lastCol: normalized[BIT_POSITIONS.lastCol] === '1',\n band1Vert: normalized[BIT_POSITIONS.band1Vert] === '1',\n band2Vert: normalized[BIT_POSITIONS.band2Vert] === '1',\n band1Horz: normalized[BIT_POSITIONS.band1Horz] === '1',\n band2Horz: normalized[BIT_POSITIONS.band2Horz] === '1',\n neCell: normalized[BIT_POSITIONS.neCell] === '1',\n nwCell: normalized[BIT_POSITIONS.nwCell] === '1',\n seCell: normalized[BIT_POSITIONS.seCell] === '1',\n swCell: normalized[BIT_POSITIONS.swCell] === '1',\n };\n}\n\n/**\n * Encodes CnfStyleFlags back to a binary string\n *\n * @param flags - Flags to encode\n * @returns 12-character binary string\n *\n * @example\n * ```typescript\n * const cnfStyle = encodeCnfStyle({ firstRow: true, lastCol: true });\n * console.log(cnfStyle); // '100100000000'\n * ```\n */\nexport function encodeCnfStyle(flags: Partial<CnfStyleFlags>): string {\n const bits = new Array(12).fill('0');\n\n for (const [key, position] of Object.entries(BIT_POSITIONS)) {\n if (flags[key as keyof CnfStyleFlags]) {\n bits[position] = '1';\n }\n }\n\n return bits.join('');\n}\n\n/**\n * Gets the active conditional formatting types from a cnfStyle\n *\n * @param cnfStyle - The cnfStyle string to decode\n * @returns Array of active ConditionalFormattingType values\n *\n * @example\n * ```typescript\n * const types = getActiveConditionals('110000000000');\n * console.log(types); // ['firstRow', 'lastRow']\n * ```\n */\nexport function getActiveConditionals(cnfStyle: string): ConditionalFormattingType[] {\n const flags = decodeCnfStyle(cnfStyle);\n const active: ConditionalFormattingType[] = [];\n\n for (const [key, isActive] of Object.entries(flags)) {\n if (isActive) {\n active.push(CNF_TO_CONDITIONAL_MAP[key as keyof CnfStyleFlags]);\n }\n }\n\n return active;\n}\n\n/**\n * Gets the active conditional formatting types in priority order\n * More specific conditions come first (corners before edges before banding)\n *\n * @param cnfStyle - The cnfStyle string to decode\n * @returns Array of active ConditionalFormattingType values in priority order\n *\n * @example\n * ```typescript\n * // Cell is both in first row and is the nwCell (top-left corner)\n * const types = getActiveConditionalsInPriorityOrder('100000000100');\n * console.log(types); // ['nwCell', 'firstRow'] - corner takes priority\n * ```\n */\nexport function getActiveConditionalsInPriorityOrder(\n cnfStyle: string\n): ConditionalFormattingType[] {\n const flags = decodeCnfStyle(cnfStyle);\n const active: ConditionalFormattingType[] = [];\n\n for (const flagName of CONDITIONAL_PRIORITY_ORDER) {\n if (flags[flagName]) {\n active.push(CNF_TO_CONDITIONAL_MAP[flagName]);\n }\n }\n\n return active;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"corruptionDetection.d.ts","sourceRoot":"","sources":["../../src/utils/corruptionDetection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIlD,UAAU,YAAY;IACpB,gBAAgB,CAAC,IAAI,SAAS,EAAE,CAAC;CAClC;AAKD,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,UAAU,GACV,UAAU,GACV,OAAO,CAAC;AAKZ,MAAM,WAAW,kBAAkB;IAEjC,cAAc,EAAE,MAAM,CAAC;IAEvB,QAAQ,EAAE,MAAM,CAAC;IAEjB,IAAI,EAAE,MAAM,CAAC;IAEb,cAAc,EAAE,cAAc,CAAC;IAE/B,YAAY,EAAE,MAAM,CAAC;IAErB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,MAAM,WAAW,gBAAgB;IAE/B,WAAW,EAAE,OAAO,CAAC;IAErB,cAAc,EAAE,MAAM,CAAC;IAEvB,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAEhC,OAAO,EAAE,MAAM,CAAC;IAEhB,UAAU,EAAE;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAwBD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,CAkE9E;AAKD,UAAU,oBAAoB;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAoBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA2DzE;AAiBD,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CA2BxD;AAiDD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWpD"}
1
+ {"version":3,"file":"corruptionDetection.d.ts","sourceRoot":"","sources":["../../src/utils/corruptionDetection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIlD,UAAU,YAAY;IACpB,gBAAgB,CAAC,IAAI,SAAS,EAAE,CAAC;CAClC;AAKD,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,UAAU,GACV,UAAU,GACV,OAAO,CAAC;AAKZ,MAAM,WAAW,kBAAkB;IAEjC,cAAc,EAAE,MAAM,CAAC;IAEvB,QAAQ,EAAE,MAAM,CAAC;IAEjB,IAAI,EAAE,MAAM,CAAC;IAEb,cAAc,EAAE,cAAc,CAAC;IAE/B,YAAY,EAAE,MAAM,CAAC;IAErB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,MAAM,WAAW,gBAAgB;IAE/B,WAAW,EAAE,OAAO,CAAC;IAErB,cAAc,EAAE,MAAM,CAAC;IAEvB,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAEhC,OAAO,EAAE,MAAM,CAAC;IAEhB,UAAU,EAAE;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAwBD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,CAkE9E;AAKD,UAAU,oBAAoB;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAoBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA4DzE;AAiBD,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CA2BxD;AAiDD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"corruptionDetection.js","sourceRoot":"","sources":["../../src/utils/corruptionDetection.ts"],"names":[],"mappings":";;AAsFA,gEAkEC;AA6BD,wDA2DC;AAiBD,gCA2BC;AAiDD,wCAWC;AAhVD,qDAAkD;AAClD,yCAAsC;AA6EtC,SAAgB,0BAA0B,CAAC,GAAiB;IAC1D,MAAM,SAAS,GAAyB,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG;QACZ,UAAU,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,CAAC;KACT,CAAC;IAGF,MAAM,UAAU,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAGtE,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,YAAY,qBAAS,CAAC,EAAE,CAAC;YACpD,SAAS;QACX,CAAC;QAGD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;QAGjC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,YAAY,SAAG,CAAC,EAAE,CAAC;gBAClC,SAAS;YACX,CAAC;YAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,SAAS;YACX,CAAC;YAGD,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;YAEhD,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;gBAC3B,SAAS,CAAC,IAAI,CAAC;oBACb,cAAc,EAAE,IAAI;oBACpB,QAAQ,EAAE,IAAI;oBACd,IAAI,EAAE,IAAI;oBACV,cAAc,EAAE,UAAU,CAAC,IAAI;oBAC/B,YAAY,EAAE,UAAU,CAAC,YAAY;oBACrC,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,CAAC;gBAGH,IAAI,UAAU,CAAC,IAAI,KAAK,aAAa;oBAAE,KAAK,CAAC,UAAU,EAAE,CAAC;qBACrD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU;oBAAE,KAAK,CAAC,OAAO,EAAE,CAAC;qBACpD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU;oBAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;qBACrD,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO;oBAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IAGD,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAElD,OAAO;QACL,WAAW,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;QACjC,cAAc,EAAE,SAAS,CAAC,MAAM;QAChC,SAAS;QACT,OAAO;QACP,UAAU,EAAE,KAAK;KAClB,CAAC;AACJ,CAAC;AA6BD,SAAgB,sBAAsB,CAAC,IAAY;IACjD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC;IAED,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,WAAW,GAAG,KAAK,CAAC;IAIxB,MAAM,iBAAiB,GAAG,2BAA2B,CAAC;IACtD,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IAID,MAAM,aAAa,GAAG,qBAAqB,CAAC;IAC5C,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;IAMD,MAAM,uBAAuB,GAAG,oFAAoF,CAAC;IACrH,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAGD,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAExF,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACnE,CAAC;IAGD,IAAI,IAAoB,CAAC;IACzB,IAAI,aAAa,IAAI,CAAC,WAAW,IAAI,UAAU,CAAC,EAAE,CAAC;QAEjD,IAAI,GAAG,aAAa,CAAC;IACvB,CAAC;SAAM,IAAI,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,GAAG,UAAU,CAAC;IACpB,CAAC;SAAM,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;QAC/B,IAAI,GAAG,OAAO,CAAC;IACjB,CAAC;SAAM,IAAI,aAAa,EAAE,CAAC;QACzB,IAAI,GAAG,aAAa,CAAC;IACvB,CAAC;SAAM,IAAI,UAAU,EAAE,CAAC;QACtB,IAAI,GAAG,UAAU,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAEtC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AACnD,CAAC;AAiBD,SAAgB,UAAU,CAAC,aAAqB;IAC9C,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,IAAI,OAAO,GAAG,aAAa,CAAC;IAG5B,OAAO,GAAG,OAAO;SACd,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAI1B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAG9C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAG1C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAE9C,OAAO,OAAO,CAAC;AACjB,CAAC;AAKD,SAAS,eAAe,CACtB,SAA+B,EAC/B,KAA+E;IAE/E,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,4CAA4C,CAAC;IACtD,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,8CAA8C,CAAC,CAAC;IACpF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAEpC,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,oBAAoB,KAAK,CAAC,UAAU,cAAc,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,iBAAiB,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,QAAQ,cAAc,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,KAAK,cAAc,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;IAC5F,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IACtE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;IAE1F,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAUD,SAAgB,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,OAAO,CACL,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC;QACnC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;QAChC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/B,CAAC;AACJ,CAAC","sourcesContent":["/**\r\n * Corruption Detection - Utilities to detect and diagnose XML corruption in documents\r\n *\r\n * This module helps users identify when they've accidentally passed XML-like strings\r\n * to text methods instead of using the proper API. This is a common mistake that\r\n * results in escaped XML tags being displayed as literal text in Word.\r\n */\r\n\r\nimport { Paragraph } from '../elements/Paragraph';\r\nimport { Run } from '../elements/Run';\r\n\r\n/** Minimal interface for document corruption scanning (avoids circular import) */\r\ninterface DocumentLike {\r\n getAllParagraphs?(): Paragraph[];\r\n}\r\n\r\n/**\r\n * Types of corruption that can be detected\r\n */\r\nexport type CorruptionType =\r\n | 'escaped-xml' // &lt;w:t&gt; style escaping\r\n | 'xml-tags' // <w:t> tags in text\r\n | 'entities' // &quot; &apos; etc.\r\n | 'mixed'; // Multiple types\r\n\r\n/**\r\n * Location of corruption within a document\r\n */\r\nexport interface CorruptionLocation {\r\n /** Index of the paragraph containing corruption */\r\n paragraphIndex: number;\r\n /** Index of the run within the paragraph */\r\n runIndex: number;\r\n /** The corrupted text content */\r\n text: string;\r\n /** Type of corruption detected */\r\n corruptionType: CorruptionType;\r\n /** Suggested fix for the corruption */\r\n suggestedFix: string;\r\n /** Length of corrupted text */\r\n length: number;\r\n}\r\n\r\n/**\r\n * Comprehensive corruption report for a document\r\n */\r\nexport interface CorruptionReport {\r\n /** Whether any corruption was found */\r\n isCorrupted: boolean;\r\n /** Total number of corrupted locations */\r\n totalLocations: number;\r\n /** Detailed list of corruption locations */\r\n locations: CorruptionLocation[];\r\n /** Human-readable summary */\r\n summary: string;\r\n /** Statistics about corruption types */\r\n statistics: {\r\n escapedXml: number;\r\n xmlTags: number;\r\n entities: number;\r\n mixed: number;\r\n };\r\n}\r\n\r\n/**\r\n * Detects XML corruption in a document\r\n *\r\n * Scans all paragraphs and runs to find text that contains escaped XML\r\n * or XML-like patterns that suggest the user passed XML strings to text methods.\r\n *\r\n * @param doc - The document to scan\r\n * @returns Corruption report with locations and suggested fixes\r\n *\r\n * @example\r\n * ```typescript\r\n * const doc = await Document.load('corrupted.docx');\r\n * const report = detectCorruptionInDocument(doc);\r\n *\r\n * if (report.isCorrupted) {\r\n * console.log(report.summary);\r\n * report.locations.forEach(loc => {\r\n * console.log(`Paragraph ${loc.paragraphIndex}, Run ${loc.runIndex}: ${loc.suggestedFix}`);\r\n * });\r\n * }\r\n * ```\r\n */\r\nexport function detectCorruptionInDocument(doc: DocumentLike): CorruptionReport {\r\n const locations: CorruptionLocation[] = [];\r\n const stats = {\r\n escapedXml: 0,\r\n xmlTags: 0,\r\n entities: 0,\r\n mixed: 0,\r\n };\r\n\r\n // Get all paragraphs from the document\r\n const paragraphs = doc.getAllParagraphs ? doc.getAllParagraphs() : [];\r\n\r\n // Scan each paragraph\r\n for (let pIdx = 0; pIdx < paragraphs.length; pIdx++) {\r\n const paragraph = paragraphs[pIdx];\r\n if (!paragraph || !(paragraph instanceof Paragraph)) {\r\n continue;\r\n }\r\n\r\n // Get runs from paragraph\r\n const runs = paragraph.getRuns();\r\n\r\n // Scan each run\r\n for (let rIdx = 0; rIdx < runs.length; rIdx++) {\r\n const run = runs[rIdx];\r\n if (!run || !(run instanceof Run)) {\r\n continue;\r\n }\r\n\r\n const text = run.getText();\r\n if (!text || text.length === 0) {\r\n continue;\r\n }\r\n\r\n // Check for corruption in this text\r\n const corruption = detectCorruptionInText(text);\r\n\r\n if (corruption.isCorrupted) {\r\n locations.push({\r\n paragraphIndex: pIdx,\r\n runIndex: rIdx,\r\n text: text,\r\n corruptionType: corruption.type,\r\n suggestedFix: corruption.suggestedFix,\r\n length: text.length,\r\n });\r\n\r\n // Update statistics\r\n if (corruption.type === 'escaped-xml') stats.escapedXml++;\r\n else if (corruption.type === 'xml-tags') stats.xmlTags++;\r\n else if (corruption.type === 'entities') stats.entities++;\r\n else if (corruption.type === 'mixed') stats.mixed++;\r\n }\r\n }\r\n }\r\n\r\n // Generate summary\r\n const summary = generateSummary(locations, stats);\r\n\r\n return {\r\n isCorrupted: locations.length > 0,\r\n totalLocations: locations.length,\r\n locations,\r\n summary,\r\n statistics: stats,\r\n };\r\n}\r\n\r\n/**\r\n * Internal result from text corruption detection\r\n */\r\ninterface TextCorruptionResult {\r\n isCorrupted: boolean;\r\n type: CorruptionType;\r\n suggestedFix: string;\r\n}\r\n\r\n/**\r\n * Detects XML corruption in a single text string\r\n *\r\n * Checks for common patterns that indicate the user passed XML strings\r\n * instead of plain text.\r\n *\r\n * @param text - Text to check\r\n * @returns True if corruption detected\r\n *\r\n * @example\r\n * ```typescript\r\n * const corrupted = detectCorruptionInText('Hello &lt;w:t&gt;World');\r\n * // Returns: true\r\n *\r\n * const clean = detectCorruptionInText('Hello World');\r\n * // Returns: false\r\n * ```\r\n */\r\nexport function detectCorruptionInText(text: string): TextCorruptionResult {\r\n if (!text || typeof text !== 'string') {\r\n return { isCorrupted: false, type: 'mixed', suggestedFix: String(text || '') };\r\n }\r\n\r\n let hasEscapedXml = false;\r\n let hasXmlTags = false;\r\n let hasEntities = false;\r\n\r\n // Pattern 1: Escaped XML tags (most common corruption)\r\n // Matches: &lt;w:t&gt;, &lt;/w:t&gt;, &lt;w:r&gt;, etc.\r\n const escapedXmlPattern = /&lt;\\/?w:[a-z]+[^&]*&gt;/i;\r\n if (escapedXmlPattern.test(text)) {\r\n hasEscapedXml = true;\r\n }\r\n\r\n // Pattern 2: Raw XML tags (less common, but possible)\r\n // Matches: <w:t>, </w:t>, <w:r>, etc.\r\n const xmlTagPattern = /<\\/?w:[a-z]+[^>]*>/i;\r\n if (xmlTagPattern.test(text)) {\r\n hasXmlTags = true;\r\n }\r\n\r\n // Pattern 3: Escaped entities combined with Word XML attributes\r\n // ONLY flag if we see Word-specific patterns, not just any entities\r\n // This avoids false positives from legitimate escaped characters\r\n // Matches all OOXML namespaces: w: (word), a: (drawingML), pic: (picture), r: (relationships), wp: (word drawing)\r\n const wordXmlAttributePattern = /(&lt;(?:w|a|r|pic|wp|m|mc|wpc|wps|wpg|c|dgm|o|v):|xml:space=&quot;preserve&quot;)/i;\r\n if (wordXmlAttributePattern.test(text)) {\r\n hasEntities = true;\r\n }\r\n\r\n // Determine corruption type\r\n const corruptionCount = [hasEscapedXml, hasXmlTags, hasEntities].filter(Boolean).length;\r\n\r\n if (corruptionCount === 0) {\r\n return { isCorrupted: false, type: 'mixed', suggestedFix: text };\r\n }\r\n\r\n // More precise type detection - check primary indicator first\r\n let type: CorruptionType;\r\n if (hasEscapedXml && (hasEntities || hasXmlTags)) {\r\n // Escaped XML combined with other patterns - this is the classic corruption case\r\n type = 'escaped-xml';\r\n } else if (hasXmlTags && hasEntities) {\r\n type = 'xml-tags';\r\n } else if (corruptionCount > 1) {\r\n type = 'mixed';\r\n } else if (hasEscapedXml) {\r\n type = 'escaped-xml';\r\n } else if (hasXmlTags) {\r\n type = 'xml-tags';\r\n } else {\r\n type = 'entities';\r\n }\r\n\r\n const suggestedFix = suggestFix(text);\r\n\r\n return { isCorrupted: true, type, suggestedFix };\r\n}\r\n\r\n/**\r\n * Suggests a fix for corrupted text\r\n *\r\n * Attempts to clean XML patterns from text to restore the intended content.\r\n * Uses the same cleaning logic as cleanXmlFromText() from validation.ts.\r\n *\r\n * @param corruptedText - Text containing XML corruption\r\n * @returns Cleaned text with XML patterns removed\r\n *\r\n * @example\r\n * ```typescript\r\n * const fixed = suggestFix('Hello &lt;w:t&gt;World&lt;/w:t&gt;');\r\n * // Returns: 'Hello World'\r\n * ```\r\n */\r\nexport function suggestFix(corruptedText: string): string {\r\n if (!corruptedText || typeof corruptedText !== 'string') {\r\n return corruptedText;\r\n }\r\n\r\n let cleaned = corruptedText;\r\n\r\n // Step 1: Unescape XML entities first\r\n cleaned = cleaned\r\n .replace(/&lt;/g, '<')\r\n .replace(/&gt;/g, '>')\r\n .replace(/&quot;/g, '\"')\r\n .replace(/&apos;/g, \"'\")\r\n .replace(/&amp;/g, '&');\r\n\r\n // Step 2: Remove Word XML tags\r\n // Matches: <w:t xml:space=\"preserve\">, </w:t>, <w:r>, etc.\r\n cleaned = cleaned.replace(/<w:[^>]+>/g, '');\r\n cleaned = cleaned.replace(/<\\/w:[^>]+>/g, '');\r\n\r\n // Step 3: Remove any remaining XML-like tags\r\n cleaned = cleaned.replace(/<[^>]+>/g, '');\r\n\r\n // Step 4: Clean up whitespace\r\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Generates a human-readable summary of corruption\r\n */\r\nfunction generateSummary(\r\n locations: CorruptionLocation[],\r\n stats: { escapedXml: number; xmlTags: number; entities: number; mixed: number }\r\n): string {\r\n if (locations.length === 0) {\r\n return 'No corruption detected. Document is clean.';\r\n }\r\n\r\n const lines: string[] = [];\r\n lines.push(`Found ${locations.length} corrupted text location(s) in the document.`);\r\n lines.push('');\r\n lines.push('Corruption breakdown:');\r\n\r\n if (stats.escapedXml > 0) {\r\n lines.push(` - Escaped XML: ${stats.escapedXml} location(s)`);\r\n }\r\n if (stats.xmlTags > 0) {\r\n lines.push(` - XML Tags: ${stats.xmlTags} location(s)`);\r\n }\r\n if (stats.entities > 0) {\r\n lines.push(` - XML Entities: ${stats.entities} location(s)`);\r\n }\r\n if (stats.mixed > 0) {\r\n lines.push(` - Mixed: ${stats.mixed} location(s)`);\r\n }\r\n\r\n lines.push('');\r\n lines.push('This corruption typically occurs when XML strings are passed to text methods.');\r\n lines.push('Instead of: paragraph.addText(\"Text<w:t>1</w:t>\")');\r\n lines.push('Use: paragraph.addText(\"Text\"); paragraph.addText(\"1\");');\r\n lines.push('');\r\n lines.push('To automatically clean text, use: new Run(text, { cleanXmlFromText: true })');\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\n/**\r\n * Checks if text looks like it might be corrupted (less strict check)\r\n *\r\n * This is a quick check that can be used for warnings without full analysis.\r\n *\r\n * @param text - Text to check\r\n * @returns True if text might be corrupted\r\n */\r\nexport function looksCorrupted(text: string): boolean {\r\n if (!text || typeof text !== 'string') {\r\n return false;\r\n }\r\n\r\n // Quick regex checks for common corruption patterns\r\n return (\r\n /&lt;\\/?(w|r|p):[a-z]+/i.test(text) ||\r\n /<\\/?(w|r|p):[a-z]+/i.test(text) ||\r\n /xml:space=&quot;/i.test(text)\r\n );\r\n}\r\n"]}
1
+ {"version":3,"file":"corruptionDetection.js","sourceRoot":"","sources":["../../src/utils/corruptionDetection.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Corruption Detection - Utilities to detect and diagnose XML corruption in documents\n *\n * This module helps users identify when they've accidentally passed XML-like strings\n * to text methods instead of using the proper API. This is a common mistake that\n * results in escaped XML tags being displayed as literal text in Word.\n */\n\nimport { Paragraph } from '../elements/Paragraph';\nimport { Run } from '../elements/Run';\n\n/** Minimal interface for document corruption scanning (avoids circular import) */\ninterface DocumentLike {\n getAllParagraphs?(): Paragraph[];\n}\n\n/**\n * Types of corruption that can be detected\n */\nexport type CorruptionType =\n | 'escaped-xml' // &lt;w:t&gt; style escaping\n | 'xml-tags' // <w:t> tags in text\n | 'entities' // &quot; &apos; etc.\n | 'mixed'; // Multiple types\n\n/**\n * Location of corruption within a document\n */\nexport interface CorruptionLocation {\n /** Index of the paragraph containing corruption */\n paragraphIndex: number;\n /** Index of the run within the paragraph */\n runIndex: number;\n /** The corrupted text content */\n text: string;\n /** Type of corruption detected */\n corruptionType: CorruptionType;\n /** Suggested fix for the corruption */\n suggestedFix: string;\n /** Length of corrupted text */\n length: number;\n}\n\n/**\n * Comprehensive corruption report for a document\n */\nexport interface CorruptionReport {\n /** Whether any corruption was found */\n isCorrupted: boolean;\n /** Total number of corrupted locations */\n totalLocations: number;\n /** Detailed list of corruption locations */\n locations: CorruptionLocation[];\n /** Human-readable summary */\n summary: string;\n /** Statistics about corruption types */\n statistics: {\n escapedXml: number;\n xmlTags: number;\n entities: number;\n mixed: number;\n };\n}\n\n/**\n * Detects XML corruption in a document\n *\n * Scans all paragraphs and runs to find text that contains escaped XML\n * or XML-like patterns that suggest the user passed XML strings to text methods.\n *\n * @param doc - The document to scan\n * @returns Corruption report with locations and suggested fixes\n *\n * @example\n * ```typescript\n * const doc = await Document.load('corrupted.docx');\n * const report = detectCorruptionInDocument(doc);\n *\n * if (report.isCorrupted) {\n * console.log(report.summary);\n * report.locations.forEach(loc => {\n * console.log(`Paragraph ${loc.paragraphIndex}, Run ${loc.runIndex}: ${loc.suggestedFix}`);\n * });\n * }\n * ```\n */\nexport function detectCorruptionInDocument(doc: DocumentLike): CorruptionReport {\n const locations: CorruptionLocation[] = [];\n const stats = {\n escapedXml: 0,\n xmlTags: 0,\n entities: 0,\n mixed: 0,\n };\n\n // Get all paragraphs from the document\n const paragraphs = doc.getAllParagraphs ? doc.getAllParagraphs() : [];\n\n // Scan each paragraph\n for (let pIdx = 0; pIdx < paragraphs.length; pIdx++) {\n const paragraph = paragraphs[pIdx];\n if (!paragraph || !(paragraph instanceof Paragraph)) {\n continue;\n }\n\n // Get runs from paragraph\n const runs = paragraph.getRuns();\n\n // Scan each run\n for (let rIdx = 0; rIdx < runs.length; rIdx++) {\n const run = runs[rIdx];\n if (!run || !(run instanceof Run)) {\n continue;\n }\n\n const text = run.getText();\n if (!text || text.length === 0) {\n continue;\n }\n\n // Check for corruption in this text\n const corruption = detectCorruptionInText(text);\n\n if (corruption.isCorrupted) {\n locations.push({\n paragraphIndex: pIdx,\n runIndex: rIdx,\n text: text,\n corruptionType: corruption.type,\n suggestedFix: corruption.suggestedFix,\n length: text.length,\n });\n\n // Update statistics\n if (corruption.type === 'escaped-xml') stats.escapedXml++;\n else if (corruption.type === 'xml-tags') stats.xmlTags++;\n else if (corruption.type === 'entities') stats.entities++;\n else if (corruption.type === 'mixed') stats.mixed++;\n }\n }\n }\n\n // Generate summary\n const summary = generateSummary(locations, stats);\n\n return {\n isCorrupted: locations.length > 0,\n totalLocations: locations.length,\n locations,\n summary,\n statistics: stats,\n };\n}\n\n/**\n * Internal result from text corruption detection\n */\ninterface TextCorruptionResult {\n isCorrupted: boolean;\n type: CorruptionType;\n suggestedFix: string;\n}\n\n/**\n * Detects XML corruption in a single text string\n *\n * Checks for common patterns that indicate the user passed XML strings\n * instead of plain text.\n *\n * @param text - Text to check\n * @returns True if corruption detected\n *\n * @example\n * ```typescript\n * const corrupted = detectCorruptionInText('Hello &lt;w:t&gt;World');\n * // Returns: true\n *\n * const clean = detectCorruptionInText('Hello World');\n * // Returns: false\n * ```\n */\nexport function detectCorruptionInText(text: string): TextCorruptionResult {\n if (!text || typeof text !== 'string') {\n return { isCorrupted: false, type: 'mixed', suggestedFix: String(text || '') };\n }\n\n let hasEscapedXml = false;\n let hasXmlTags = false;\n let hasEntities = false;\n\n // Pattern 1: Escaped XML tags (most common corruption)\n // Matches: &lt;w:t&gt;, &lt;/w:t&gt;, &lt;w:r&gt;, etc.\n const escapedXmlPattern = /&lt;\\/?w:[a-z]+[^&]*&gt;/i;\n if (escapedXmlPattern.test(text)) {\n hasEscapedXml = true;\n }\n\n // Pattern 2: Raw XML tags (less common, but possible)\n // Matches: <w:t>, </w:t>, <w:r>, etc.\n const xmlTagPattern = /<\\/?w:[a-z]+[^>]*>/i;\n if (xmlTagPattern.test(text)) {\n hasXmlTags = true;\n }\n\n // Pattern 3: Escaped entities combined with Word XML attributes\n // ONLY flag if we see Word-specific patterns, not just any entities\n // This avoids false positives from legitimate escaped characters\n // Matches all OOXML namespaces: w: (word), a: (drawingML), pic: (picture), r: (relationships), wp: (word drawing)\n const wordXmlAttributePattern =\n /(&lt;(?:w|a|r|pic|wp|m|mc|wpc|wps|wpg|c|dgm|o|v):|xml:space=&quot;preserve&quot;)/i;\n if (wordXmlAttributePattern.test(text)) {\n hasEntities = true;\n }\n\n // Determine corruption type\n const corruptionCount = [hasEscapedXml, hasXmlTags, hasEntities].filter(Boolean).length;\n\n if (corruptionCount === 0) {\n return { isCorrupted: false, type: 'mixed', suggestedFix: text };\n }\n\n // More precise type detection - check primary indicator first\n let type: CorruptionType;\n if (hasEscapedXml && (hasEntities || hasXmlTags)) {\n // Escaped XML combined with other patterns - this is the classic corruption case\n type = 'escaped-xml';\n } else if (hasXmlTags && hasEntities) {\n type = 'xml-tags';\n } else if (corruptionCount > 1) {\n type = 'mixed';\n } else if (hasEscapedXml) {\n type = 'escaped-xml';\n } else if (hasXmlTags) {\n type = 'xml-tags';\n } else {\n type = 'entities';\n }\n\n const suggestedFix = suggestFix(text);\n\n return { isCorrupted: true, type, suggestedFix };\n}\n\n/**\n * Suggests a fix for corrupted text\n *\n * Attempts to clean XML patterns from text to restore the intended content.\n * Uses the same cleaning logic as cleanXmlFromText() from validation.ts.\n *\n * @param corruptedText - Text containing XML corruption\n * @returns Cleaned text with XML patterns removed\n *\n * @example\n * ```typescript\n * const fixed = suggestFix('Hello &lt;w:t&gt;World&lt;/w:t&gt;');\n * // Returns: 'Hello World'\n * ```\n */\nexport function suggestFix(corruptedText: string): string {\n if (!corruptedText || typeof corruptedText !== 'string') {\n return corruptedText;\n }\n\n let cleaned = corruptedText;\n\n // Step 1: Unescape XML entities first\n cleaned = cleaned\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, \"'\")\n .replace(/&amp;/g, '&');\n\n // Step 2: Remove Word XML tags\n // Matches: <w:t xml:space=\"preserve\">, </w:t>, <w:r>, etc.\n cleaned = cleaned.replace(/<w:[^>]+>/g, '');\n cleaned = cleaned.replace(/<\\/w:[^>]+>/g, '');\n\n // Step 3: Remove any remaining XML-like tags\n cleaned = cleaned.replace(/<[^>]+>/g, '');\n\n // Step 4: Clean up whitespace\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\n\n return cleaned;\n}\n\n/**\n * Generates a human-readable summary of corruption\n */\nfunction generateSummary(\n locations: CorruptionLocation[],\n stats: { escapedXml: number; xmlTags: number; entities: number; mixed: number }\n): string {\n if (locations.length === 0) {\n return 'No corruption detected. Document is clean.';\n }\n\n const lines: string[] = [];\n lines.push(`Found ${locations.length} corrupted text location(s) in the document.`);\n lines.push('');\n lines.push('Corruption breakdown:');\n\n if (stats.escapedXml > 0) {\n lines.push(` - Escaped XML: ${stats.escapedXml} location(s)`);\n }\n if (stats.xmlTags > 0) {\n lines.push(` - XML Tags: ${stats.xmlTags} location(s)`);\n }\n if (stats.entities > 0) {\n lines.push(` - XML Entities: ${stats.entities} location(s)`);\n }\n if (stats.mixed > 0) {\n lines.push(` - Mixed: ${stats.mixed} location(s)`);\n }\n\n lines.push('');\n lines.push('This corruption typically occurs when XML strings are passed to text methods.');\n lines.push('Instead of: paragraph.addText(\"Text<w:t>1</w:t>\")');\n lines.push('Use: paragraph.addText(\"Text\"); paragraph.addText(\"1\");');\n lines.push('');\n lines.push('To automatically clean text, use: new Run(text, { cleanXmlFromText: true })');\n\n return lines.join('\\n');\n}\n\n/**\n * Checks if text looks like it might be corrupted (less strict check)\n *\n * This is a quick check that can be used for warnings without full analysis.\n *\n * @param text - Text to check\n * @returns True if text might be corrupted\n */\nexport function looksCorrupted(text: string): boolean {\n if (!text || typeof text !== 'string') {\n return false;\n }\n\n // Quick regex checks for common corruption patterns\n return (\n /&lt;\\/?(w|r|p):[a-z]+/i.test(text) ||\n /<\\/?(w|r|p):[a-z]+/i.test(text) ||\n /xml:space=&quot;/i.test(text)\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dateFormatting.js","sourceRoot":"","sources":["../../src/utils/dateFormatting.ts"],"names":[],"mappings":";;AAiBA,4CAEC;AAFD,SAAgB,gBAAgB,CAAC,IAAU;IACzC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC","sourcesContent":["/**\r\n * Date formatting utilities for OOXML XML generation\r\n *\r\n * ECMA-376 requires dates in ISO 8601 format WITHOUT milliseconds:\r\n * Valid: \"2024-01-01T12:00:00Z\"\r\n * Invalid: \"2024-01-01T12:00:00.000Z\" (Word rejects milliseconds in w:date attributes)\r\n *\r\n * JavaScript's Date.toISOString() always includes milliseconds (YYYY-MM-DDTHH:mm:ss.sssZ),\r\n * so we must strip the .sss portion for all w:date attributes in tracked changes.\r\n */\r\n\r\n/**\r\n * Formats a Date to ISO 8601 without milliseconds for OOXML w:date attributes.\r\n *\r\n * @param date - Date to format\r\n * @returns ISO 8601 date string without milliseconds (e.g., \"2024-01-01T12:00:00Z\")\r\n */\r\nexport function formatDateForXml(date: Date): string {\r\n return date.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\r\n}\r\n"]}
1
+ {"version":3,"file":"dateFormatting.js","sourceRoot":"","sources":["../../src/utils/dateFormatting.ts"],"names":[],"mappings":";;AAiBA,4CAEC;AAFD,SAAgB,gBAAgB,CAAC,IAAU;IACzC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC","sourcesContent":["/**\n * Date formatting utilities for OOXML XML generation\n *\n * ECMA-376 requires dates in ISO 8601 format WITHOUT milliseconds:\n * Valid: \"2024-01-01T12:00:00Z\"\n * Invalid: \"2024-01-01T12:00:00.000Z\" (Word rejects milliseconds in w:date attributes)\n *\n * JavaScript's Date.toISOString() always includes milliseconds (YYYY-MM-DDTHH:mm:ss.sssZ),\n * so we must strip the .sss portion for all w:date attributes in tracked changes.\n */\n\n/**\n * Formats a Date to ISO 8601 without milliseconds for OOXML w:date attributes.\n *\n * @param date - Date to format\n * @returns ISO 8601 date string without milliseconds (e.g., \"2024-01-01T12:00:00Z\")\n */\nexport function formatDateForXml(date: Date): string {\n return date.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n"]}
@@ -24,7 +24,7 @@ function deepClone(obj) {
24
24
  }
25
25
  if (obj instanceof Set) {
26
26
  const setCopy = new Set();
27
- obj.forEach(value => {
27
+ obj.forEach((value) => {
28
28
  setCopy.add(deepClone(value));
29
29
  });
30
30
  return setCopy;
@@ -1 +1 @@
1
- {"version":3,"file":"deepClone.js","sourceRoot":"","sources":["../../src/utils/deepClone.ts"],"names":[],"mappings":";;AAwBA,8BAoDC;AApDD,SAAgB,SAAS,CAAI,GAAM;IAEjC,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,GAAG,CAAC;IACb,CAAC;IAGD,IAAI,GAAG,YAAY,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAM,CAAC;IACtC,CAAC;IAGD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,OAAO,GAAc,EAAE,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,IAAI,GAAG,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACzB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QACH,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,IAAI,GAAG,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAClB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,IAAI,GAAG,YAAY,MAAM,EAAE,CAAC;QAC1B,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAM,CAAC;IAChD,CAAC;IAGD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAA4B,CAAC;IACrF,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,OAAO,OAAY,CAAC;AACtB,CAAC","sourcesContent":["/**\r\n * Deep clone utility for safely cloning objects\r\n * More efficient and type-safe than JSON.parse(JSON.stringify())\r\n */\r\n\r\n/**\r\n * Deep clone an object using structured cloning\r\n * Preserves most object types including Date, RegExp, Map, Set, etc.\r\n *\r\n * For simple objects (like formatting options), this is more efficient\r\n * than JSON.parse(JSON.stringify()) and doesn't lose non-serializable values.\r\n *\r\n * @param obj - Object to clone\r\n * @returns Deep cloned copy of the object\r\n *\r\n * @example\r\n * ```typescript\r\n * const original = { bold: true, color: \"FF0000\", date: new Date() };\r\n * const cloned = deepClone(original);\r\n * cloned.bold = false;\r\n * console.log(original.bold); // true (unchanged)\r\n * console.log(cloned.date instanceof Date); // true (preserved)\r\n * ```\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n // Handle primitive types and null\r\n if (obj === null || typeof obj !== 'object') {\r\n return obj;\r\n }\r\n\r\n // Handle Date\r\n if (obj instanceof Date) {\r\n return new Date(obj.getTime()) as T;\r\n }\r\n\r\n // Handle Array\r\n if (Array.isArray(obj)) {\r\n const arrCopy: unknown[] = [];\r\n for (let i = 0; i < obj.length; i++) {\r\n arrCopy[i] = deepClone(obj[i]);\r\n }\r\n return arrCopy as T;\r\n }\r\n\r\n // Handle Map\r\n if (obj instanceof Map) {\r\n const mapCopy = new Map();\r\n obj.forEach((value, key) => {\r\n mapCopy.set(deepClone(key), deepClone(value));\r\n });\r\n return mapCopy as T;\r\n }\r\n\r\n // Handle Set\r\n if (obj instanceof Set) {\r\n const setCopy = new Set();\r\n obj.forEach(value => {\r\n setCopy.add(deepClone(value));\r\n });\r\n return setCopy as T;\r\n }\r\n\r\n // Handle RegExp\r\n if (obj instanceof RegExp) {\r\n return new RegExp(obj.source, obj.flags) as T;\r\n }\r\n\r\n // Handle plain objects\r\n const objCopy = Object.create(Object.getPrototypeOf(obj)) as Record<string, unknown>;\r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n objCopy[key] = deepClone((obj as Record<string, unknown>)[key]);\r\n }\r\n }\r\n\r\n return objCopy as T;\r\n}\r\n\r\n"]}
1
+ {"version":3,"file":"deepClone.js","sourceRoot":"","sources":["../../src/utils/deepClone.ts"],"names":[],"mappings":";;AAwBA,8BAoDC;AApDD,SAAgB,SAAS,CAAI,GAAM;IAEjC,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,GAAG,CAAC;IACb,CAAC;IAGD,IAAI,GAAG,YAAY,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAM,CAAC;IACtC,CAAC;IAGD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,OAAO,GAAc,EAAE,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,IAAI,GAAG,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACzB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QACH,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,IAAI,GAAG,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,IAAI,GAAG,YAAY,MAAM,EAAE,CAAC;QAC1B,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAM,CAAC;IAChD,CAAC;IAGD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAA4B,CAAC;IACrF,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,OAAO,OAAY,CAAC;AACtB,CAAC","sourcesContent":["/**\n * Deep clone utility for safely cloning objects\n * More efficient and type-safe than JSON.parse(JSON.stringify())\n */\n\n/**\n * Deep clone an object using structured cloning\n * Preserves most object types including Date, RegExp, Map, Set, etc.\n *\n * For simple objects (like formatting options), this is more efficient\n * than JSON.parse(JSON.stringify()) and doesn't lose non-serializable values.\n *\n * @param obj - Object to clone\n * @returns Deep cloned copy of the object\n *\n * @example\n * ```typescript\n * const original = { bold: true, color: \"FF0000\", date: new Date() };\n * const cloned = deepClone(original);\n * cloned.bold = false;\n * console.log(original.bold); // true (unchanged)\n * console.log(cloned.date instanceof Date); // true (preserved)\n * ```\n */\nexport function deepClone<T>(obj: T): T {\n // Handle primitive types and null\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Handle Date\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n\n // Handle Array\n if (Array.isArray(obj)) {\n const arrCopy: unknown[] = [];\n for (let i = 0; i < obj.length; i++) {\n arrCopy[i] = deepClone(obj[i]);\n }\n return arrCopy as T;\n }\n\n // Handle Map\n if (obj instanceof Map) {\n const mapCopy = new Map();\n obj.forEach((value, key) => {\n mapCopy.set(deepClone(key), deepClone(value));\n });\n return mapCopy as T;\n }\n\n // Handle Set\n if (obj instanceof Set) {\n const setCopy = new Set();\n obj.forEach((value) => {\n setCopy.add(deepClone(value));\n });\n return setCopy as T;\n }\n\n // Handle RegExp\n if (obj instanceof RegExp) {\n return new RegExp(obj.source, obj.flags) as T;\n }\n\n // Handle plain objects\n const objCopy = Object.create(Object.getPrototypeOf(obj)) as Record<string, unknown>;\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n objCopy[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n }\n\n return objCopy as T;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/utils/diagnostics.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAeD,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,IAAI,CAM/E;AAKD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAKD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAKD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAIhE;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAItE;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAItE;AAKD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAIhE;AAKD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,GAAG,eAAe,EACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,EACvC,IAAI,CAAC,EAAE,OAAO,GACb,IAAI,CAgBN;AAKD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAWN"}
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/utils/diagnostics.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAeD,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,IAAI,CAM/E;AAKD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAKD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAKD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAIhE;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAItE;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAItE;AAKD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAIhE;AAKD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,GAAG,eAAe,EACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,EACvC,IAAI,CAAC,EAAE,OAAO,GACb,IAAI,CAgBN;AAKD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAWpF"}
@@ -61,7 +61,7 @@ function logParagraphContent(source, paraIndex, runs, bidi) {
61
61
  const rtlStatus = run.rtl ? ' [RTL]' : '';
62
62
  logger(` ${idx + 1}. "${run.text}"${rtlStatus}`);
63
63
  });
64
- const fullText = runs.map(r => r.text).join('');
64
+ const fullText = runs.map((r) => r.text).join('');
65
65
  logger(` Combined text: "${fullText}"`);
66
66
  }
67
67
  function logTextComparison(label, before, after) {
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/utils/diagnostics.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Diagnostic logging utilities for debugging document processing\r\n * @module diagnostics\r\n */\r\n\r\nexport interface DiagnosticConfig {\r\n enabled: boolean;\r\n logParsing: boolean;\r\n logSerialization: boolean;\r\n logTextDirection: boolean;\r\n verbose: boolean;\r\n}\r\n\r\nconst defaultConfig: DiagnosticConfig = {\r\n enabled: false,\r\n logParsing: false,\r\n logSerialization: false,\r\n logTextDirection: false,\r\n verbose: false,\r\n};\r\n\r\nlet config: DiagnosticConfig = { ...defaultConfig };\r\n\r\n/**\r\n * Enable diagnostic logging\r\n */\r\nexport function enableDiagnostics(options: Partial<DiagnosticConfig> = {}): void {\r\n config = {\r\n ...defaultConfig,\r\n enabled: true,\r\n ...options,\r\n };\r\n}\r\n\r\n/**\r\n * Disable diagnostic logging\r\n */\r\nexport function disableDiagnostics(): void {\r\n config = { ...defaultConfig };\r\n}\r\n\r\n/**\r\n * Get current diagnostic configuration\r\n */\r\nexport function getDiagnosticConfig(): DiagnosticConfig {\r\n return { ...config };\r\n}\r\n\r\n/**\r\n * Log parsing activity\r\n */\r\nexport function logParsing(message: string, data?: unknown): void {\r\n if (config.enabled && config.logParsing) {\r\n console.log(`[PARSE] ${message}`, data !== undefined ? data : '');\r\n }\r\n}\r\n\r\n/**\r\n * Log serialization activity\r\n */\r\nexport function logSerialization(message: string, data?: unknown): void {\r\n if (config.enabled && config.logSerialization) {\r\n console.log(`[SERIALIZE] ${message}`, data !== undefined ? data : '');\r\n }\r\n}\r\n\r\n/**\r\n * Log text direction properties\r\n */\r\nexport function logTextDirection(message: string, data?: unknown): void {\r\n if (config.enabled && config.logTextDirection) {\r\n console.log(`[TEXT-DIR] ${message}`, data !== undefined ? data : '');\r\n }\r\n}\r\n\r\n/**\r\n * Log verbose details\r\n */\r\nexport function logVerbose(message: string, data?: unknown): void {\r\n if (config.enabled && config.verbose) {\r\n console.log(`[VERBOSE] ${message}`, data !== undefined ? data : '');\r\n }\r\n}\r\n\r\n/**\r\n * Log paragraph content summary\r\n */\r\nexport function logParagraphContent(\r\n source: 'parsing' | 'serialization',\r\n paraIndex: number,\r\n runs: { text: string; rtl?: boolean }[],\r\n bidi?: boolean\r\n): void {\r\n if (!config.enabled) return;\r\n\r\n const logger = source === 'parsing' ? logParsing : logSerialization;\r\n\r\n logger(`Paragraph ${paraIndex}:`);\r\n logger(` BiDi: ${bidi !== undefined ? bidi : 'not set'}`);\r\n logger(` Runs (${runs.length}):`);\r\n\r\n runs.forEach((run, idx) => {\r\n const rtlStatus = run.rtl ? ' [RTL]' : '';\r\n logger(` ${idx + 1}. \"${run.text}\"${rtlStatus}`);\r\n });\r\n\r\n const fullText = runs.map(r => r.text).join('');\r\n logger(` Combined text: \"${fullText}\"`);\r\n}\r\n\r\n/**\r\n * Compare text before and after processing\r\n */\r\nexport function logTextComparison(\r\n label: string,\r\n before: string,\r\n after: string\r\n): void {\r\n if (!config.enabled) return;\r\n\r\n if (before !== after) {\r\n console.log(`[TEXT-CHANGE] ${label}:`);\r\n console.log(` Before: \"${before}\"`);\r\n console.log(` After: \"${after}\"`);\r\n console.log(` MISMATCH DETECTED!`);\r\n } else if (config.verbose) {\r\n logVerbose(`${label}: Text preserved correctly`);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/utils/diagnostics.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Diagnostic logging utilities for debugging document processing\n * @module diagnostics\n */\n\nexport interface DiagnosticConfig {\n enabled: boolean;\n logParsing: boolean;\n logSerialization: boolean;\n logTextDirection: boolean;\n verbose: boolean;\n}\n\nconst defaultConfig: DiagnosticConfig = {\n enabled: false,\n logParsing: false,\n logSerialization: false,\n logTextDirection: false,\n verbose: false,\n};\n\nlet config: DiagnosticConfig = { ...defaultConfig };\n\n/**\n * Enable diagnostic logging\n */\nexport function enableDiagnostics(options: Partial<DiagnosticConfig> = {}): void {\n config = {\n ...defaultConfig,\n enabled: true,\n ...options,\n };\n}\n\n/**\n * Disable diagnostic logging\n */\nexport function disableDiagnostics(): void {\n config = { ...defaultConfig };\n}\n\n/**\n * Get current diagnostic configuration\n */\nexport function getDiagnosticConfig(): DiagnosticConfig {\n return { ...config };\n}\n\n/**\n * Log parsing activity\n */\nexport function logParsing(message: string, data?: unknown): void {\n if (config.enabled && config.logParsing) {\n console.log(`[PARSE] ${message}`, data !== undefined ? data : '');\n }\n}\n\n/**\n * Log serialization activity\n */\nexport function logSerialization(message: string, data?: unknown): void {\n if (config.enabled && config.logSerialization) {\n console.log(`[SERIALIZE] ${message}`, data !== undefined ? data : '');\n }\n}\n\n/**\n * Log text direction properties\n */\nexport function logTextDirection(message: string, data?: unknown): void {\n if (config.enabled && config.logTextDirection) {\n console.log(`[TEXT-DIR] ${message}`, data !== undefined ? data : '');\n }\n}\n\n/**\n * Log verbose details\n */\nexport function logVerbose(message: string, data?: unknown): void {\n if (config.enabled && config.verbose) {\n console.log(`[VERBOSE] ${message}`, data !== undefined ? data : '');\n }\n}\n\n/**\n * Log paragraph content summary\n */\nexport function logParagraphContent(\n source: 'parsing' | 'serialization',\n paraIndex: number,\n runs: { text: string; rtl?: boolean }[],\n bidi?: boolean\n): void {\n if (!config.enabled) return;\n\n const logger = source === 'parsing' ? logParsing : logSerialization;\n\n logger(`Paragraph ${paraIndex}:`);\n logger(` BiDi: ${bidi !== undefined ? bidi : 'not set'}`);\n logger(` Runs (${runs.length}):`);\n\n runs.forEach((run, idx) => {\n const rtlStatus = run.rtl ? ' [RTL]' : '';\n logger(` ${idx + 1}. \"${run.text}\"${rtlStatus}`);\n });\n\n const fullText = runs.map((r) => r.text).join('');\n logger(` Combined text: \"${fullText}\"`);\n}\n\n/**\n * Compare text before and after processing\n */\nexport function logTextComparison(label: string, before: string, after: string): void {\n if (!config.enabled) return;\n\n if (before !== after) {\n console.log(`[TEXT-CHANGE] ${label}:`);\n console.log(` Before: \"${before}\"`);\n console.log(` After: \"${after}\"`);\n console.log(` MISMATCH DETECTED!`);\n } else if (config.verbose) {\n logVerbose(`${label}: Text preserved correctly`);\n }\n}\n"]}