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":"stripTrackedChanges.js","sourceRoot":"","sources":["../../src/utils/stripTrackedChanges.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler';\r\n\r\n/**\r\n * Strips all tracked changes markup from a Word document\r\n * This includes insertions, deletions, move operations, and property changes\r\n * Also cleans up related metadata in people.xml, settings.xml, and core.xml\r\n */\r\nclass TrackedChangesStripper {\r\n private zipHandler: ZipHandler;\r\n\r\n constructor(zipHandler: ZipHandler) {\r\n this.zipHandler = zipHandler;\r\n }\r\n\r\n /**\r\n * Main method to strip all tracked changes from the document\r\n */\r\n public async stripTrackedChanges(): Promise<void> {\r\n // Strip revision elements from document.xml\r\n await this.stripDocumentRevisions();\r\n\r\n // Clean up metadata files\r\n await this.cleanupPeopleXml();\r\n await this.cleanupSettingsXml();\r\n await this.cleanupCorePropsXml();\r\n }\r\n\r\n /**\r\n * Strip ALL revision elements from word/document.xml\r\n */\r\n private async stripDocumentRevisions(): Promise<void> {\r\n const documentXml = this.zipHandler.getFileAsString('word/document.xml');\r\n if (!documentXml) {\r\n return;\r\n }\r\n\r\n let content = documentXml;\r\n\r\n // STEP 1: Remove all range markers (boundary markers for tracked changes)\r\n content = this.removeRangeMarkers(content);\r\n\r\n // STEP 2: Process insertions - keep content, remove wrapper\r\n content = this.processInsertions(content);\r\n\r\n // STEP 3: Process deletions - remove entirely\r\n content = this.processDeletions(content);\r\n\r\n // STEP 4: Process move operations\r\n content = this.processMoveFrom(content);\r\n content = this.processMoveTo(content);\r\n\r\n // STEP 5: Remove all property change tracking elements\r\n content = this.removePropertyChanges(content);\r\n\r\n // STEP 6: Remove any remaining self-closing revision tags\r\n content = this.removeSelfClosingRevisionTags(content);\r\n\r\n // Update the file in the zip\r\n this.zipHandler.updateFile('word/document.xml', content);\r\n }\r\n\r\n /**\r\n * Remove all range marker elements\r\n */\r\n private removeRangeMarkers(xml: string): string {\r\n const patterns = [\r\n /<w:moveFromRangeStart[^>]*\\/>/g,\r\n /<w:moveFromRangeEnd[^>]*\\/>/g,\r\n /<w:moveToRangeStart[^>]*\\/>/g,\r\n /<w:moveToRangeEnd[^>]*\\/>/g,\r\n /<w:customXmlInsRangeStart[^>]*\\/>/g,\r\n /<w:customXmlInsRangeEnd[^>]*\\/>/g,\r\n /<w:customXmlDelRangeStart[^>]*\\/>/g,\r\n /<w:customXmlDelRangeEnd[^>]*\\/>/g,\r\n /<w:customXmlMoveFromRangeStart[^>]*\\/>/g,\r\n /<w:customXmlMoveFromRangeEnd[^>]*\\/>/g,\r\n /<w:customXmlMoveToRangeStart[^>]*\\/>/g,\r\n /<w:customXmlMoveToRangeEnd[^>]*\\/>/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\r\n return result;\r\n }\r\n\r\n /**\r\n * Process <w:ins> elements - keep inner content, remove wrapper\r\n * Handles orphaned tags by removing opening and closing tags separately\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 processInsertions(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 // First, remove all closing tags\r\n result = result.replace(/<\\/w:ins>/g, '');\r\n\r\n // Then, remove all opening tags (keeping any content that follows)\r\n result = result.replace(/<w:ins[\\s>][^>]*>/g, '');\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Process <w:del> elements - remove entire element\r\n * Uses iterative replacement to handle nested deletions\r\n */\r\n private processDeletions(xml: string): string {\r\n let result = xml;\r\n let previousLength = 0;\r\n \r\n // Keep replacing until no more changes (handles nested revisions)\r\n while (result.length !== previousLength) {\r\n previousLength = result.length;\r\n \r\n // Match entire deletion element and remove it\r\n // Use [\\s>] to match either space or closing bracket\r\n result = result.replace(/<w:del[\\s>][^>]*>.*?<\\/w:del>/gs, '');\r\n }\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Process <w:moveFrom> elements - remove entire element (source of move)\r\n * Uses iterative replacement to handle nested moves\r\n */\r\n private processMoveFrom(xml: string): string {\r\n let result = xml;\r\n let previousLength = 0;\r\n \r\n // Keep replacing until no more changes\r\n while (result.length !== previousLength) {\r\n previousLength = result.length;\r\n \r\n // Use [\\s>] to match either space or closing bracket\r\n result = result.replace(/<w:moveFrom[\\s>][^>]*>.*?<\\/w:moveFrom>/gs, '');\r\n }\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Process <w:moveTo> elements - keep inner content (destination of move)\r\n * Handles orphaned tags by removing opening and closing tags separately\r\n */\r\n private processMoveTo(xml: string): string {\r\n let result = xml;\r\n \r\n // First, remove all closing tags\r\n result = result.replace(/<\\/w:moveTo>/g, '');\r\n \r\n // Then, remove all opening tags (keeping any content that follows)\r\n result = result.replace(/<w:moveTo[\\s>][^>]*>/g, '');\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Remove all property change tracking elements\r\n */\r\n private removePropertyChanges(xml: string): string {\r\n const patterns = [\r\n /<w:rPrChange[^>]*>.*?<\\/w:rPrChange>/gs, // Run property changes\r\n /<w:pPrChange[^>]*>.*?<\\/w:pPrChange>/gs, // Paragraph property changes\r\n /<w:tblPrChange[^>]*>.*?<\\/w:tblPrChange>/gs, // Table property changes\r\n /<w:tblPrExChange[^>]*>.*?<\\/w:tblPrExChange>/gs, // Table property exception changes\r\n /<w:tcPrChange[^>]*>.*?<\\/w:tcPrChange>/gs, // Table cell property changes\r\n /<w:trPrChange[^>]*>.*?<\\/w:trPrChange>/gs, // Table row property changes\r\n /<w:sectPrChange[^>]*>.*?<\\/w:sectPrChange>/gs, // Section property changes\r\n /<w:tblGridChange[^>]*>.*?<\\/w:tblGridChange>/gs, // Table grid changes\r\n /<w:numberingChange[^>]*>.*?<\\/w:numberingChange>/gs // Numbering changes\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\r\n return result;\r\n }\r\n\r\n /**\r\n * Remove self-closing revision tags\r\n */\r\n private removeSelfClosingRevisionTags(xml: string): string {\r\n const patterns = [\r\n /<w:ins\\s+[^>]*\\/>/g,\r\n /<w:del\\s+[^>]*\\/>/g,\r\n /<w:moveFrom\\s+[^>]*\\/>/g,\r\n /<w:moveTo\\s+[^>]*\\/>/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\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 word/people.xml - remove revision authors\r\n */\r\n private async cleanupPeopleXml(): Promise<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 <w:person> elements (standard namespace)\r\n content = content.replace(/<w:person[^>]*>.*?<\\/w:person>/gs, '');\r\n\r\n // Remove all <w15:person> elements (Word 2013+ namespace)\r\n content = content.replace(/<w15:person[^>]*>.*?<\\/w15:person>/gs, '');\r\n\r\n // Remove any other namespace variants of person elements\r\n content = content.replace(/<w\\d*:person[^>]*>.*?<\\/w\\d*:person>/gs, '');\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 async cleanupSettingsXml(): Promise<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 track changes settings\r\n content = content.replace(/<w:trackRevisions[^>]*\\/>/g, '');\r\n content = content.replace(/<w:trackRevisions[^>]*>.*?<\\/w:trackRevisions>/gs, '');\r\n\r\n // Remove revision view settings\r\n content = content.replace(/<w:revisionView[^>]*\\/>/g, '');\r\n content = content.replace(/<w:revisionView[^>]*>.*?<\\/w:revisionView>/gs, '');\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 async cleanupCorePropsXml(): Promise<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(/<cp:revision>\\d+<\\/cp:revision>/g, '<cp:revision>1</cp:revision>');\r\n\r\n this.zipHandler.updateFile('docProps/core.xml', content);\r\n }\r\n}\r\n\r\n/**\r\n * Convenience function to strip tracked changes from a ZipHandler\r\n */\r\nexport async function stripTrackedChanges(zipHandler: ZipHandler): Promise<void> {\r\n const stripper = new TrackedChangesStripper(zipHandler);\r\n await stripper.stripTrackedChanges();\r\n}\r\n"]}
1
+ {"version":3,"file":"stripTrackedChanges.js","sourceRoot":"","sources":["../../src/utils/stripTrackedChanges.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler';\n\n/**\n * Strips all tracked changes markup from a Word document\n * This includes insertions, deletions, move operations, and property changes\n * Also cleans up related metadata in people.xml, settings.xml, and core.xml\n */\nclass TrackedChangesStripper {\n private zipHandler: ZipHandler;\n\n constructor(zipHandler: ZipHandler) {\n this.zipHandler = zipHandler;\n }\n\n /**\n * Main method to strip all tracked changes from the document\n */\n public async stripTrackedChanges(): Promise<void> {\n // Strip revision elements from document.xml\n await this.stripDocumentRevisions();\n\n // Clean up metadata files\n await this.cleanupPeopleXml();\n await this.cleanupSettingsXml();\n await this.cleanupCorePropsXml();\n }\n\n /**\n * Strip ALL revision elements from word/document.xml\n */\n private async stripDocumentRevisions(): Promise<void> {\n const documentXml = this.zipHandler.getFileAsString('word/document.xml');\n if (!documentXml) {\n return;\n }\n\n let content = documentXml;\n\n // STEP 1: Remove all range markers (boundary markers for tracked changes)\n content = this.removeRangeMarkers(content);\n\n // STEP 2: Process insertions - keep content, remove wrapper\n content = this.processInsertions(content);\n\n // STEP 3: Process deletions - remove entirely\n content = this.processDeletions(content);\n\n // STEP 4: Process move operations\n content = this.processMoveFrom(content);\n content = this.processMoveTo(content);\n\n // STEP 5: Remove all property change tracking elements\n content = this.removePropertyChanges(content);\n\n // STEP 6: Remove any remaining self-closing revision tags\n content = this.removeSelfClosingRevisionTags(content);\n\n // Update the file in the zip\n this.zipHandler.updateFile('word/document.xml', content);\n }\n\n /**\n * Remove all range marker elements\n */\n private removeRangeMarkers(xml: string): string {\n const patterns = [\n /<w:moveFromRangeStart[^>]*\\/>/g,\n /<w:moveFromRangeEnd[^>]*\\/>/g,\n /<w:moveToRangeStart[^>]*\\/>/g,\n /<w:moveToRangeEnd[^>]*\\/>/g,\n /<w:customXmlInsRangeStart[^>]*\\/>/g,\n /<w:customXmlInsRangeEnd[^>]*\\/>/g,\n /<w:customXmlDelRangeStart[^>]*\\/>/g,\n /<w:customXmlDelRangeEnd[^>]*\\/>/g,\n /<w:customXmlMoveFromRangeStart[^>]*\\/>/g,\n /<w:customXmlMoveFromRangeEnd[^>]*\\/>/g,\n /<w:customXmlMoveToRangeStart[^>]*\\/>/g,\n /<w:customXmlMoveToRangeEnd[^>]*\\/>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:ins> elements - keep inner content, remove wrapper\n * Handles orphaned tags by removing opening and closing tags separately\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 processInsertions(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 // First, remove all closing tags\n result = result.replace(/<\\/w:ins>/g, '');\n\n // Then, remove all opening tags (keeping any content that follows)\n result = result.replace(/<w:ins[\\s>][^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Process <w:del> elements - remove entire element\n * Uses iterative replacement to handle nested deletions\n */\n private processDeletions(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Keep replacing until no more changes (handles nested revisions)\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Match entire deletion element and remove it\n // Use [\\s>] to match either space or closing bracket\n result = result.replace(/<w:del[\\s>][^>]*>.*?<\\/w:del>/gs, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:moveFrom> elements - remove entire element (source of move)\n * Uses iterative replacement to handle nested moves\n */\n private processMoveFrom(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Keep replacing until no more changes\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Use [\\s>] to match either space or closing bracket\n result = result.replace(/<w:moveFrom[\\s>][^>]*>.*?<\\/w:moveFrom>/gs, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:moveTo> elements - keep inner content (destination of move)\n * Handles orphaned tags by removing opening and closing tags separately\n */\n private processMoveTo(xml: string): string {\n let result = xml;\n\n // First, remove all closing tags\n result = result.replace(/<\\/w:moveTo>/g, '');\n\n // Then, remove all opening tags (keeping any content that follows)\n result = result.replace(/<w:moveTo[\\s>][^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Remove all property change tracking elements\n */\n private removePropertyChanges(xml: string): string {\n const patterns = [\n /<w:rPrChange[^>]*>.*?<\\/w:rPrChange>/gs, // Run property changes\n /<w:pPrChange[^>]*>.*?<\\/w:pPrChange>/gs, // Paragraph property changes\n /<w:tblPrChange[^>]*>.*?<\\/w:tblPrChange>/gs, // Table property changes\n /<w:tblPrExChange[^>]*>.*?<\\/w:tblPrExChange>/gs, // Table property exception changes\n /<w:tcPrChange[^>]*>.*?<\\/w:tcPrChange>/gs, // Table cell property changes\n /<w:trPrChange[^>]*>.*?<\\/w:trPrChange>/gs, // Table row property changes\n /<w:sectPrChange[^>]*>.*?<\\/w:sectPrChange>/gs, // Section property changes\n /<w:tblGridChange[^>]*>.*?<\\/w:tblGridChange>/gs, // Table grid changes\n /<w:numberingChange[^>]*>.*?<\\/w:numberingChange>/gs, // Numbering changes\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n\n return result;\n }\n\n /**\n * Remove self-closing revision tags\n */\n private removeSelfClosingRevisionTags(xml: string): string {\n const patterns = [\n /<w:ins\\s+[^>]*\\/>/g,\n /<w:del\\s+[^>]*\\/>/g,\n /<w:moveFrom\\s+[^>]*\\/>/g,\n /<w:moveTo\\s+[^>]*\\/>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\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 word/people.xml - remove revision authors\n */\n private async cleanupPeopleXml(): Promise<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 <w:person> elements (standard namespace)\n content = content.replace(/<w:person[^>]*>.*?<\\/w:person>/gs, '');\n\n // Remove all <w15:person> elements (Word 2013+ namespace)\n content = content.replace(/<w15:person[^>]*>.*?<\\/w15:person>/gs, '');\n\n // Remove any other namespace variants of person elements\n content = content.replace(/<w\\d*:person[^>]*>.*?<\\/w\\d*:person>/gs, '');\n\n this.zipHandler.updateFile('word/people.xml', content);\n }\n\n /**\n * Clean up word/settings.xml - disable track changes\n */\n private async cleanupSettingsXml(): Promise<void> {\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\n if (!settingsXml) {\n return;\n }\n\n let content = settingsXml;\n\n // Remove track changes settings\n content = content.replace(/<w:trackRevisions[^>]*\\/>/g, '');\n content = content.replace(/<w:trackRevisions[^>]*>.*?<\\/w:trackRevisions>/gs, '');\n\n // Remove revision view settings\n content = content.replace(/<w:revisionView[^>]*\\/>/g, '');\n content = content.replace(/<w:revisionView[^>]*>.*?<\\/w:revisionView>/gs, '');\n\n this.zipHandler.updateFile('word/settings.xml', content);\n }\n\n /**\n * Clean up docProps/core.xml - reset revision count\n */\n private async cleanupCorePropsXml(): Promise<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/**\n * Convenience function to strip tracked changes from a ZipHandler\n */\nexport async function stripTrackedChanges(zipHandler: ZipHandler): Promise<void> {\n const stripper = new TrackedChangesStripper(zipHandler);\n await stripper.stripTrackedChanges();\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  export interface DiffSegment {
2
- type: "equal" | "delete" | "insert";
2
+ type: 'equal' | 'delete' | 'insert';
3
3
  text: string;
4
4
  }
5
5
  export declare function diffText(oldText: string, newText: string): DiffSegment[];
@@ -4,13 +4,13 @@ exports.diffText = diffText;
4
4
  exports.diffHasUnchangedParts = diffHasUnchangedParts;
5
5
  function diffText(oldText, newText) {
6
6
  if (oldText === newText) {
7
- return oldText.length > 0 ? [{ type: "equal", text: oldText }] : [];
7
+ return oldText.length > 0 ? [{ type: 'equal', text: oldText }] : [];
8
8
  }
9
9
  if (oldText.length === 0) {
10
- return newText.length > 0 ? [{ type: "insert", text: newText }] : [];
10
+ return newText.length > 0 ? [{ type: 'insert', text: newText }] : [];
11
11
  }
12
12
  if (newText.length === 0) {
13
- return [{ type: "delete", text: oldText }];
13
+ return [{ type: 'delete', text: oldText }];
14
14
  }
15
15
  let prefixLen = 0;
16
16
  const minLen = Math.min(oldText.length, newText.length);
@@ -25,22 +25,22 @@ function diffText(oldText, newText) {
25
25
  }
26
26
  const segments = [];
27
27
  if (prefixLen > 0) {
28
- segments.push({ type: "equal", text: oldText.slice(0, prefixLen) });
28
+ segments.push({ type: 'equal', text: oldText.slice(0, prefixLen) });
29
29
  }
30
30
  const oldMiddle = oldText.slice(prefixLen, oldText.length - suffixLen);
31
31
  const newMiddle = newText.slice(prefixLen, newText.length - suffixLen);
32
32
  if (oldMiddle.length > 0) {
33
- segments.push({ type: "delete", text: oldMiddle });
33
+ segments.push({ type: 'delete', text: oldMiddle });
34
34
  }
35
35
  if (newMiddle.length > 0) {
36
- segments.push({ type: "insert", text: newMiddle });
36
+ segments.push({ type: 'insert', text: newMiddle });
37
37
  }
38
38
  if (suffixLen > 0) {
39
- segments.push({ type: "equal", text: oldText.slice(oldText.length - suffixLen) });
39
+ segments.push({ type: 'equal', text: oldText.slice(oldText.length - suffixLen) });
40
40
  }
41
41
  return segments;
42
42
  }
43
43
  function diffHasUnchangedParts(segments) {
44
- return segments.some(s => s.type === "equal");
44
+ return segments.some((s) => s.type === 'equal');
45
45
  }
46
46
  //# sourceMappingURL=textDiff.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"textDiff.js","sourceRoot":"","sources":["../../src/utils/textDiff.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Text diff utility for character-level granular tracked changes.\r\n *\r\n * Uses a prefix/suffix diff algorithm to compute minimal edit operations\r\n * between two strings. This allows tracked changes to show only the\r\n * actual differences instead of marking entire runs as deleted/inserted.\r\n */\r\n\r\n/**\r\n * Represents a segment of a diff result.\r\n */\r\nexport interface DiffSegment {\r\n /** Whether this segment is unchanged, deleted, or inserted */\r\n type: \"equal\" | \"delete\" | \"insert\";\r\n /** The text content of this segment */\r\n text: string;\r\n}\r\n\r\n/**\r\n * Computes minimal diff segments between two strings.\r\n *\r\n * Algorithm: Find common prefix, then common suffix from the remaining text,\r\n * then the middle portion is a delete (from old) + insert (from new).\r\n *\r\n * This handles the most common edit patterns optimally:\r\n * - Space removal: \"word word\" → \"word word\" → [equal \"word \", delete \" \", equal \"word\"]\r\n * - Word replacement: \"The quick fox\" → \"The slow fox\" → [equal \"The \", delete \"quick\", insert \"slow\", equal \" fox\"]\r\n * - Prefix change: \"Hello World\" → \"Goodbye World\" → [delete \"Hello\", insert \"Goodbye\", equal \" World\"]\r\n * - Suffix change: \"Hello World\" → \"Hello Earth\" → [equal \"Hello \", delete \"World\", insert \"Earth\"]\r\n *\r\n * @param oldText - The original text\r\n * @param newText - The new text\r\n * @returns Array of diff segments\r\n */\r\nexport function diffText(oldText: string, newText: string): DiffSegment[] {\r\n // Identical strings — no changes\r\n if (oldText === newText) {\r\n return oldText.length > 0 ? [{ type: \"equal\", text: oldText }] : [];\r\n }\r\n\r\n // Empty old — entire new text is an insertion\r\n if (oldText.length === 0) {\r\n return newText.length > 0 ? [{ type: \"insert\", text: newText }] : [];\r\n }\r\n\r\n // Empty new — entire old text is a deletion\r\n if (newText.length === 0) {\r\n return [{ type: \"delete\", text: oldText }];\r\n }\r\n\r\n // Find common prefix length\r\n let prefixLen = 0;\r\n const minLen = Math.min(oldText.length, newText.length);\r\n while (prefixLen < minLen && oldText[prefixLen] === newText[prefixLen]) {\r\n prefixLen++;\r\n }\r\n\r\n // Find common suffix length (not overlapping with prefix)\r\n let suffixLen = 0;\r\n const maxSuffix = minLen - prefixLen;\r\n while (\r\n suffixLen < maxSuffix &&\r\n oldText[oldText.length - 1 - suffixLen] === newText[newText.length - 1 - suffixLen]\r\n ) {\r\n suffixLen++;\r\n }\r\n\r\n const segments: DiffSegment[] = [];\r\n\r\n // Common prefix\r\n if (prefixLen > 0) {\r\n segments.push({ type: \"equal\", text: oldText.slice(0, prefixLen) });\r\n }\r\n\r\n // Middle portion — what changed\r\n const oldMiddle = oldText.slice(prefixLen, oldText.length - suffixLen);\r\n const newMiddle = newText.slice(prefixLen, newText.length - suffixLen);\r\n\r\n if (oldMiddle.length > 0) {\r\n segments.push({ type: \"delete\", text: oldMiddle });\r\n }\r\n if (newMiddle.length > 0) {\r\n segments.push({ type: \"insert\", text: newMiddle });\r\n }\r\n\r\n // Common suffix\r\n if (suffixLen > 0) {\r\n segments.push({ type: \"equal\", text: oldText.slice(oldText.length - suffixLen) });\r\n }\r\n\r\n return segments;\r\n}\r\n\r\n/**\r\n * Checks whether a diff result has any unchanged (equal) portions.\r\n * If false, the entire text was replaced (no benefit from granular tracking).\r\n */\r\nexport function diffHasUnchangedParts(segments: DiffSegment[]): boolean {\r\n return segments.some(s => s.type === \"equal\");\r\n}\r\n"]}
1
+ {"version":3,"file":"textDiff.js","sourceRoot":"","sources":["../../src/utils/textDiff.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Text diff utility for character-level granular tracked changes.\n *\n * Uses a prefix/suffix diff algorithm to compute minimal edit operations\n * between two strings. This allows tracked changes to show only the\n * actual differences instead of marking entire runs as deleted/inserted.\n */\n\n/**\n * Represents a segment of a diff result.\n */\nexport interface DiffSegment {\n /** Whether this segment is unchanged, deleted, or inserted */\n type: 'equal' | 'delete' | 'insert';\n /** The text content of this segment */\n text: string;\n}\n\n/**\n * Computes minimal diff segments between two strings.\n *\n * Algorithm: Find common prefix, then common suffix from the remaining text,\n * then the middle portion is a delete (from old) + insert (from new).\n *\n * This handles the most common edit patterns optimally:\n * - Space removal: \"word word\" → \"word word\" → [equal \"word \", delete \" \", equal \"word\"]\n * - Word replacement: \"The quick fox\" → \"The slow fox\" → [equal \"The \", delete \"quick\", insert \"slow\", equal \" fox\"]\n * - Prefix change: \"Hello World\" → \"Goodbye World\" → [delete \"Hello\", insert \"Goodbye\", equal \" World\"]\n * - Suffix change: \"Hello World\" → \"Hello Earth\" → [equal \"Hello \", delete \"World\", insert \"Earth\"]\n *\n * @param oldText - The original text\n * @param newText - The new text\n * @returns Array of diff segments\n */\nexport function diffText(oldText: string, newText: string): DiffSegment[] {\n // Identical strings — no changes\n if (oldText === newText) {\n return oldText.length > 0 ? [{ type: 'equal', text: oldText }] : [];\n }\n\n // Empty old — entire new text is an insertion\n if (oldText.length === 0) {\n return newText.length > 0 ? [{ type: 'insert', text: newText }] : [];\n }\n\n // Empty new — entire old text is a deletion\n if (newText.length === 0) {\n return [{ type: 'delete', text: oldText }];\n }\n\n // Find common prefix length\n let prefixLen = 0;\n const minLen = Math.min(oldText.length, newText.length);\n while (prefixLen < minLen && oldText[prefixLen] === newText[prefixLen]) {\n prefixLen++;\n }\n\n // Find common suffix length (not overlapping with prefix)\n let suffixLen = 0;\n const maxSuffix = minLen - prefixLen;\n while (\n suffixLen < maxSuffix &&\n oldText[oldText.length - 1 - suffixLen] === newText[newText.length - 1 - suffixLen]\n ) {\n suffixLen++;\n }\n\n const segments: DiffSegment[] = [];\n\n // Common prefix\n if (prefixLen > 0) {\n segments.push({ type: 'equal', text: oldText.slice(0, prefixLen) });\n }\n\n // Middle portion — what changed\n const oldMiddle = oldText.slice(prefixLen, oldText.length - suffixLen);\n const newMiddle = newText.slice(prefixLen, newText.length - suffixLen);\n\n if (oldMiddle.length > 0) {\n segments.push({ type: 'delete', text: oldMiddle });\n }\n if (newMiddle.length > 0) {\n segments.push({ type: 'insert', text: newMiddle });\n }\n\n // Common suffix\n if (suffixLen > 0) {\n segments.push({ type: 'equal', text: oldText.slice(oldText.length - suffixLen) });\n }\n\n return segments;\n}\n\n/**\n * Checks whether a diff result has any unchanged (equal) portions.\n * If false, the entire text was replaced (no benefit from granular tracking).\n */\nexport function diffHasUnchangedParts(segments: DiffSegment[]): boolean {\n return segments.some((s) => s.type === 'equal');\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Unit Conversion Utilities\r\n *\r\n * Word documents use multiple measurement units:\r\n * - Twips: 1/20th of a point (used for most measurements like margins, indents)\r\n * - EMUs: English Metric Units (used for DrawingML, images)\r\n * - Points: Typography unit (72 points = 1 inch)\r\n * - Pixels: Screen measurement (depends on DPI)\r\n * - Inches/Centimeters: Human-readable units\r\n *\r\n * Conversion factors:\r\n * - 1 inch = 72 points = 1440 twips = 914,400 EMUs\r\n * - 1 cm = 0.393701 inches = 360,000 EMUs\r\n * - 1 point = 20 twips = 12,700 EMUs\r\n */\r\n\r\n/**\r\n * Standard DPI (dots per inch) for screen displays\r\n */\r\nexport const STANDARD_DPI = 96;\r\n\r\n/**\r\n * Conversion constants\r\n */\r\nexport const UNITS = {\r\n /** EMUs per inch */\r\n EMUS_PER_INCH: 914400,\r\n /** Twips per inch */\r\n TWIPS_PER_INCH: 1440,\r\n /** Points per inch */\r\n POINTS_PER_INCH: 72,\r\n /** Twips per point */\r\n TWIPS_PER_POINT: 20,\r\n /** EMUs per twip */\r\n EMUS_PER_TWIP: 635,\r\n /** EMUs per point */\r\n EMUS_PER_POINT: 12700,\r\n /** EMUs per centimeter */\r\n EMUS_PER_CM: 360000,\r\n /** Inches per centimeter */\r\n INCHES_PER_CM: 0.393701,\r\n /** Centimeters per inch */\r\n CM_PER_INCH: 2.54,\r\n /** Half-points per point (Word uses half-points for font sizes) */\r\n HALF_POINTS_PER_POINT: 2,\r\n} as const;\r\n\r\n// ============================================================================\r\n// Twips Conversions\r\n// ============================================================================\r\n\r\n/**\r\n * Converts twips to points\r\n * @param twips Value in twips\r\n * @returns Value in points\r\n */\r\nexport function twipsToPoints(twips: number): number {\r\n return twips / UNITS.TWIPS_PER_POINT;\r\n}\r\n\r\n/**\r\n * Converts twips to inches\r\n * @param twips Value in twips\r\n * @returns Value in inches\r\n */\r\nexport function twipsToInches(twips: number): number {\r\n return twips / UNITS.TWIPS_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts twips to centimeters\r\n * @param twips Value in twips\r\n * @returns Value in centimeters\r\n */\r\nexport function twipsToCm(twips: number): number {\r\n return twipsToInches(twips) * UNITS.CM_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts twips to EMUs\r\n * @param twips Value in twips\r\n * @returns Value in EMUs\r\n */\r\nexport function twipsToEmus(twips: number): number {\r\n return Math.round(twips * UNITS.EMUS_PER_TWIP);\r\n}\r\n\r\n// ============================================================================\r\n// EMUs Conversions\r\n// ============================================================================\r\n\r\n/**\r\n * Converts EMUs to twips\r\n * @param emus Value in EMUs\r\n * @returns Value in twips\r\n */\r\nexport function emusToTwips(emus: number): number {\r\n return Math.round(emus / UNITS.EMUS_PER_TWIP);\r\n}\r\n\r\n/**\r\n * Converts EMUs to inches\r\n * @param emus Value in EMUs\r\n * @returns Value in inches\r\n */\r\nexport function emusToInches(emus: number): number {\r\n return emus / UNITS.EMUS_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts EMUs to centimeters\r\n * @param emus Value in EMUs\r\n * @returns Value in centimeters\r\n */\r\nexport function emusToCm(emus: number): number {\r\n return emus / UNITS.EMUS_PER_CM;\r\n}\r\n\r\n/**\r\n * Converts EMUs to points\r\n * @param emus Value in EMUs\r\n * @returns Value in points\r\n */\r\nexport function emusToPoints(emus: number): number {\r\n return emus / UNITS.EMUS_PER_POINT;\r\n}\r\n\r\n/**\r\n * Converts EMUs to pixels\r\n * @param emus Value in EMUs\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in pixels\r\n */\r\nexport function emusToPixels(emus: number, dpi: number = STANDARD_DPI): number {\r\n return Math.round((emus / UNITS.EMUS_PER_INCH) * dpi);\r\n}\r\n\r\n// ============================================================================\r\n// Points Conversions\r\n// ============================================================================\r\n\r\n/**\r\n * Converts points to twips\r\n * @param points Value in points\r\n * @returns Value in twips\r\n */\r\nexport function pointsToTwips(points: number): number {\r\n return points * UNITS.TWIPS_PER_POINT;\r\n}\r\n\r\n/**\r\n * Converts points to EMUs\r\n * @param points Value in points\r\n * @returns Value in EMUs\r\n */\r\nexport function pointsToEmus(points: number): number {\r\n return Math.round(points * UNITS.EMUS_PER_POINT);\r\n}\r\n\r\n/**\r\n * Converts points to inches\r\n * @param points Value in points\r\n * @returns Value in inches\r\n */\r\nexport function pointsToInches(points: number): number {\r\n return points / UNITS.POINTS_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts points to centimeters\r\n * @param points Value in points\r\n * @returns Value in centimeters\r\n */\r\nexport function pointsToCm(points: number): number {\r\n return pointsToInches(points) * UNITS.CM_PER_INCH;\r\n}\r\n\r\n// ============================================================================\r\n// Half-Points Conversions (Word uses half-points for font sizes)\r\n// ============================================================================\r\n\r\n/**\r\n * Converts points to half-points (for Word font size storage)\r\n * @param points Value in points\r\n * @returns Value in half-points\r\n */\r\nexport function pointsToHalfPoints(points: number): number {\r\n return points * UNITS.HALF_POINTS_PER_POINT;\r\n}\r\n\r\n/**\r\n * Converts half-points to points (from Word font size storage)\r\n * @param halfPoints Value in half-points\r\n * @returns Value in points\r\n */\r\nexport function halfPointsToPoints(halfPoints: number): number {\r\n return halfPoints / UNITS.HALF_POINTS_PER_POINT;\r\n}\r\n\r\n// ============================================================================\r\n// Inches Conversions\r\n// ============================================================================\r\n\r\n/**\r\n * Converts inches to twips\r\n * @param inches Value in inches\r\n * @returns Value in twips\r\n */\r\nexport function inchesToTwips(inches: number): number {\r\n return Math.round(inches * UNITS.TWIPS_PER_INCH);\r\n}\r\n\r\n/**\r\n * Converts inches to EMUs\r\n * @param inches Value in inches\r\n * @returns Value in EMUs\r\n */\r\nexport function inchesToEmus(inches: number): number {\r\n return Math.round(inches * UNITS.EMUS_PER_INCH);\r\n}\r\n\r\n/**\r\n * Converts inches to points\r\n * @param inches Value in inches\r\n * @returns Value in points\r\n */\r\nexport function inchesToPoints(inches: number): number {\r\n return inches * UNITS.POINTS_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts inches to centimeters\r\n * @param inches Value in inches\r\n * @returns Value in centimeters\r\n */\r\nexport function inchesToCm(inches: number): number {\r\n return inches * UNITS.CM_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts inches to pixels\r\n * @param inches Value in inches\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in pixels\r\n */\r\nexport function inchesToPixels(inches: number, dpi: number = STANDARD_DPI): number {\r\n return Math.round(inches * dpi);\r\n}\r\n\r\n// ============================================================================\r\n// Centimeters Conversions\r\n// ============================================================================\r\n\r\n/**\r\n * Converts centimeters to twips\r\n * @param cm Value in centimeters\r\n * @returns Value in twips\r\n */\r\nexport function cmToTwips(cm: number): number {\r\n return inchesToTwips(cm * UNITS.INCHES_PER_CM);\r\n}\r\n\r\n/**\r\n * Converts centimeters to EMUs\r\n * @param cm Value in centimeters\r\n * @returns Value in EMUs\r\n */\r\nexport function cmToEmus(cm: number): number {\r\n return Math.round(cm * UNITS.EMUS_PER_CM);\r\n}\r\n\r\n/**\r\n * Converts centimeters to inches\r\n * @param cm Value in centimeters\r\n * @returns Value in inches\r\n */\r\nexport function cmToInches(cm: number): number {\r\n return cm * UNITS.INCHES_PER_CM;\r\n}\r\n\r\n/**\r\n * Converts centimeters to points\r\n * @param cm Value in centimeters\r\n * @returns Value in points\r\n */\r\nexport function cmToPoints(cm: number): number {\r\n return inchesToPoints(cmToInches(cm));\r\n}\r\n\r\n/**\r\n * Converts centimeters to pixels\r\n * @param cm Value in centimeters\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in pixels\r\n */\r\nexport function cmToPixels(cm: number, dpi: number = STANDARD_DPI): number {\r\n return inchesToPixels(cmToInches(cm), dpi);\r\n}\r\n\r\n// ============================================================================\r\n// Pixels Conversions\r\n// ============================================================================\r\n\r\n/**\r\n * Converts pixels to EMUs\r\n * @param pixels Value in pixels\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in EMUs\r\n */\r\nexport function pixelsToEmus(pixels: number, dpi: number = STANDARD_DPI): number {\r\n return Math.round((pixels / dpi) * UNITS.EMUS_PER_INCH);\r\n}\r\n\r\n/**\r\n * Converts pixels to inches\r\n * @param pixels Value in pixels\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in inches\r\n */\r\nexport function pixelsToInches(pixels: number, dpi: number = STANDARD_DPI): number {\r\n return pixels / dpi;\r\n}\r\n\r\n/**\r\n * Converts pixels to twips\r\n * @param pixels Value in pixels\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in twips\r\n */\r\nexport function pixelsToTwips(pixels: number, dpi: number = STANDARD_DPI): number {\r\n return inchesToTwips(pixelsToInches(pixels, dpi));\r\n}\r\n\r\n/**\r\n * Converts pixels to centimeters\r\n * @param pixels Value in pixels\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in centimeters\r\n */\r\nexport function pixelsToCm(pixels: number, dpi: number = STANDARD_DPI): number {\r\n return pixelsToInches(pixels, dpi) * UNITS.CM_PER_INCH;\r\n}\r\n\r\n/**\r\n * Converts pixels to points\r\n * @param pixels Value in pixels\r\n * @param dpi Dots per inch (default: 96)\r\n * @returns Value in points\r\n */\r\nexport function pixelsToPoints(pixels: number, dpi: number = STANDARD_DPI): number {\r\n return inchesToPoints(pixelsToInches(pixels, dpi));\r\n}\r\n\r\n// ============================================================================\r\n// Common Document Sizes (in twips)\r\n// ============================================================================\r\n\r\n/**\r\n * Common page sizes in twips\r\n */\r\nexport const PAGE_SIZES = {\r\n /** Letter (8.5\" x 11\") */\r\n LETTER: {\r\n width: 12240, // 8.5 inches\r\n height: 15840, // 11 inches\r\n },\r\n /** A4 (21cm x 29.7cm) */\r\n A4: {\r\n width: 11906, // 21cm\r\n height: 16838, // 29.7cm\r\n },\r\n /** Legal (8.5\" x 14\") */\r\n LEGAL: {\r\n width: 12240, // 8.5 inches\r\n height: 20160, // 14 inches\r\n },\r\n /** Tabloid (11\" x 17\") */\r\n TABLOID: {\r\n width: 15840, // 11 inches\r\n height: 24480, // 17 inches\r\n },\r\n /** A3 (29.7cm x 42cm) */\r\n A3: {\r\n width: 16838, // 29.7cm\r\n height: 23811, // 42cm\r\n },\r\n} as const;\r\n\r\n/**\r\n * Common margin sizes in twips\r\n */\r\nexport const COMMON_MARGINS = {\r\n /** Normal margins (1 inch all around) */\r\n NORMAL: {\r\n top: 1440,\r\n bottom: 1440,\r\n left: 1440,\r\n right: 1440,\r\n },\r\n /** Narrow margins (0.5 inch all around) */\r\n NARROW: {\r\n top: 720,\r\n bottom: 720,\r\n left: 720,\r\n right: 720,\r\n },\r\n /** Wide margins (2 inches left/right, 1 inch top/bottom) */\r\n WIDE: {\r\n top: 1440,\r\n bottom: 1440,\r\n left: 2880,\r\n right: 2880,\r\n },\r\n /** Moderate margins (1 inch top/bottom, 0.75 inch left/right) */\r\n MODERATE: {\r\n top: 1440,\r\n bottom: 1440,\r\n left: 1080,\r\n right: 1080,\r\n },\r\n} as const;\r\n"]}
1
+ {"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unit Conversion Utilities\n *\n * Word documents use multiple measurement units:\n * - Twips: 1/20th of a point (used for most measurements like margins, indents)\n * - EMUs: English Metric Units (used for DrawingML, images)\n * - Points: Typography unit (72 points = 1 inch)\n * - Pixels: Screen measurement (depends on DPI)\n * - Inches/Centimeters: Human-readable units\n *\n * Conversion factors:\n * - 1 inch = 72 points = 1440 twips = 914,400 EMUs\n * - 1 cm = 0.393701 inches = 360,000 EMUs\n * - 1 point = 20 twips = 12,700 EMUs\n */\n\n/**\n * Standard DPI (dots per inch) for screen displays\n */\nexport const STANDARD_DPI = 96;\n\n/**\n * Conversion constants\n */\nexport const UNITS = {\n /** EMUs per inch */\n EMUS_PER_INCH: 914400,\n /** Twips per inch */\n TWIPS_PER_INCH: 1440,\n /** Points per inch */\n POINTS_PER_INCH: 72,\n /** Twips per point */\n TWIPS_PER_POINT: 20,\n /** EMUs per twip */\n EMUS_PER_TWIP: 635,\n /** EMUs per point */\n EMUS_PER_POINT: 12700,\n /** EMUs per centimeter */\n EMUS_PER_CM: 360000,\n /** Inches per centimeter */\n INCHES_PER_CM: 0.393701,\n /** Centimeters per inch */\n CM_PER_INCH: 2.54,\n /** Half-points per point (Word uses half-points for font sizes) */\n HALF_POINTS_PER_POINT: 2,\n} as const;\n\n// ============================================================================\n// Twips Conversions\n// ============================================================================\n\n/**\n * Converts twips to points\n * @param twips Value in twips\n * @returns Value in points\n */\nexport function twipsToPoints(twips: number): number {\n return twips / UNITS.TWIPS_PER_POINT;\n}\n\n/**\n * Converts twips to inches\n * @param twips Value in twips\n * @returns Value in inches\n */\nexport function twipsToInches(twips: number): number {\n return twips / UNITS.TWIPS_PER_INCH;\n}\n\n/**\n * Converts twips to centimeters\n * @param twips Value in twips\n * @returns Value in centimeters\n */\nexport function twipsToCm(twips: number): number {\n return twipsToInches(twips) * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts twips to EMUs\n * @param twips Value in twips\n * @returns Value in EMUs\n */\nexport function twipsToEmus(twips: number): number {\n return Math.round(twips * UNITS.EMUS_PER_TWIP);\n}\n\n// ============================================================================\n// EMUs Conversions\n// ============================================================================\n\n/**\n * Converts EMUs to twips\n * @param emus Value in EMUs\n * @returns Value in twips\n */\nexport function emusToTwips(emus: number): number {\n return Math.round(emus / UNITS.EMUS_PER_TWIP);\n}\n\n/**\n * Converts EMUs to inches\n * @param emus Value in EMUs\n * @returns Value in inches\n */\nexport function emusToInches(emus: number): number {\n return emus / UNITS.EMUS_PER_INCH;\n}\n\n/**\n * Converts EMUs to centimeters\n * @param emus Value in EMUs\n * @returns Value in centimeters\n */\nexport function emusToCm(emus: number): number {\n return emus / UNITS.EMUS_PER_CM;\n}\n\n/**\n * Converts EMUs to points\n * @param emus Value in EMUs\n * @returns Value in points\n */\nexport function emusToPoints(emus: number): number {\n return emus / UNITS.EMUS_PER_POINT;\n}\n\n/**\n * Converts EMUs to pixels\n * @param emus Value in EMUs\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function emusToPixels(emus: number, dpi: number = STANDARD_DPI): number {\n return Math.round((emus / UNITS.EMUS_PER_INCH) * dpi);\n}\n\n// ============================================================================\n// Points Conversions\n// ============================================================================\n\n/**\n * Converts points to twips\n * @param points Value in points\n * @returns Value in twips\n */\nexport function pointsToTwips(points: number): number {\n return points * UNITS.TWIPS_PER_POINT;\n}\n\n/**\n * Converts points to EMUs\n * @param points Value in points\n * @returns Value in EMUs\n */\nexport function pointsToEmus(points: number): number {\n return Math.round(points * UNITS.EMUS_PER_POINT);\n}\n\n/**\n * Converts points to inches\n * @param points Value in points\n * @returns Value in inches\n */\nexport function pointsToInches(points: number): number {\n return points / UNITS.POINTS_PER_INCH;\n}\n\n/**\n * Converts points to centimeters\n * @param points Value in points\n * @returns Value in centimeters\n */\nexport function pointsToCm(points: number): number {\n return pointsToInches(points) * UNITS.CM_PER_INCH;\n}\n\n// ============================================================================\n// Half-Points Conversions (Word uses half-points for font sizes)\n// ============================================================================\n\n/**\n * Converts points to half-points (for Word font size storage)\n * @param points Value in points\n * @returns Value in half-points\n */\nexport function pointsToHalfPoints(points: number): number {\n return points * UNITS.HALF_POINTS_PER_POINT;\n}\n\n/**\n * Converts half-points to points (from Word font size storage)\n * @param halfPoints Value in half-points\n * @returns Value in points\n */\nexport function halfPointsToPoints(halfPoints: number): number {\n return halfPoints / UNITS.HALF_POINTS_PER_POINT;\n}\n\n// ============================================================================\n// Inches Conversions\n// ============================================================================\n\n/**\n * Converts inches to twips\n * @param inches Value in inches\n * @returns Value in twips\n */\nexport function inchesToTwips(inches: number): number {\n return Math.round(inches * UNITS.TWIPS_PER_INCH);\n}\n\n/**\n * Converts inches to EMUs\n * @param inches Value in inches\n * @returns Value in EMUs\n */\nexport function inchesToEmus(inches: number): number {\n return Math.round(inches * UNITS.EMUS_PER_INCH);\n}\n\n/**\n * Converts inches to points\n * @param inches Value in inches\n * @returns Value in points\n */\nexport function inchesToPoints(inches: number): number {\n return inches * UNITS.POINTS_PER_INCH;\n}\n\n/**\n * Converts inches to centimeters\n * @param inches Value in inches\n * @returns Value in centimeters\n */\nexport function inchesToCm(inches: number): number {\n return inches * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts inches to pixels\n * @param inches Value in inches\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function inchesToPixels(inches: number, dpi: number = STANDARD_DPI): number {\n return Math.round(inches * dpi);\n}\n\n// ============================================================================\n// Centimeters Conversions\n// ============================================================================\n\n/**\n * Converts centimeters to twips\n * @param cm Value in centimeters\n * @returns Value in twips\n */\nexport function cmToTwips(cm: number): number {\n return inchesToTwips(cm * UNITS.INCHES_PER_CM);\n}\n\n/**\n * Converts centimeters to EMUs\n * @param cm Value in centimeters\n * @returns Value in EMUs\n */\nexport function cmToEmus(cm: number): number {\n return Math.round(cm * UNITS.EMUS_PER_CM);\n}\n\n/**\n * Converts centimeters to inches\n * @param cm Value in centimeters\n * @returns Value in inches\n */\nexport function cmToInches(cm: number): number {\n return cm * UNITS.INCHES_PER_CM;\n}\n\n/**\n * Converts centimeters to points\n * @param cm Value in centimeters\n * @returns Value in points\n */\nexport function cmToPoints(cm: number): number {\n return inchesToPoints(cmToInches(cm));\n}\n\n/**\n * Converts centimeters to pixels\n * @param cm Value in centimeters\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function cmToPixels(cm: number, dpi: number = STANDARD_DPI): number {\n return inchesToPixels(cmToInches(cm), dpi);\n}\n\n// ============================================================================\n// Pixels Conversions\n// ============================================================================\n\n/**\n * Converts pixels to EMUs\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in EMUs\n */\nexport function pixelsToEmus(pixels: number, dpi: number = STANDARD_DPI): number {\n return Math.round((pixels / dpi) * UNITS.EMUS_PER_INCH);\n}\n\n/**\n * Converts pixels to inches\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in inches\n */\nexport function pixelsToInches(pixels: number, dpi: number = STANDARD_DPI): number {\n return pixels / dpi;\n}\n\n/**\n * Converts pixels to twips\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in twips\n */\nexport function pixelsToTwips(pixels: number, dpi: number = STANDARD_DPI): number {\n return inchesToTwips(pixelsToInches(pixels, dpi));\n}\n\n/**\n * Converts pixels to centimeters\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in centimeters\n */\nexport function pixelsToCm(pixels: number, dpi: number = STANDARD_DPI): number {\n return pixelsToInches(pixels, dpi) * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts pixels to points\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in points\n */\nexport function pixelsToPoints(pixels: number, dpi: number = STANDARD_DPI): number {\n return inchesToPoints(pixelsToInches(pixels, dpi));\n}\n\n// ============================================================================\n// Common Document Sizes (in twips)\n// ============================================================================\n\n/**\n * Common page sizes in twips\n */\nexport const PAGE_SIZES = {\n /** Letter (8.5\" x 11\") */\n LETTER: {\n width: 12240, // 8.5 inches\n height: 15840, // 11 inches\n },\n /** A4 (21cm x 29.7cm) */\n A4: {\n width: 11906, // 21cm\n height: 16838, // 29.7cm\n },\n /** Legal (8.5\" x 14\") */\n LEGAL: {\n width: 12240, // 8.5 inches\n height: 20160, // 14 inches\n },\n /** Tabloid (11\" x 17\") */\n TABLOID: {\n width: 15840, // 11 inches\n height: 24480, // 17 inches\n },\n /** A3 (29.7cm x 42cm) */\n A3: {\n width: 16838, // 29.7cm\n height: 23811, // 42cm\n },\n} as const;\n\n/**\n * Common margin sizes in twips\n */\nexport const COMMON_MARGINS = {\n /** Normal margins (1 inch all around) */\n NORMAL: {\n top: 1440,\n bottom: 1440,\n left: 1440,\n right: 1440,\n },\n /** Narrow margins (0.5 inch all around) */\n NARROW: {\n top: 720,\n bottom: 720,\n left: 720,\n right: 720,\n },\n /** Wide margins (2 inches left/right, 1 inch top/bottom) */\n WIDE: {\n top: 1440,\n bottom: 1440,\n left: 2880,\n right: 2880,\n },\n /** Moderate margins (1 inch top/bottom, 0.75 inch left/right) */\n MODERATE: {\n top: 1440,\n bottom: 1440,\n left: 1080,\n right: 1080,\n },\n} as const;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ/D;AAOD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQtD;AAgBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA6ClD;AAQD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAWxD;AAOD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAa/D;AAUD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CActE;AAmBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBpD;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAatE;AAKD,eAAO,MAAM,gBAAgB,sBAAgB,CAAC;AAQ9C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAiB,GAAG,IAAI,CAcnF;AASD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,SAAS,SAAU,EACnB,QAAQ,SAAI,GACX,IAAI,CAQN;AASD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,SAAS,SAAc,GACtB,IAAI,CAUN;AASD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAc,GAAG,IAAI,CAkB5E;AAQD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAQ/E;AAQD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAe,GAAG,IAAI,CAQhF;AAUD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,IAAI,CAoBpE;AAKD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAaD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAuDpF;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAyBzE;AAaD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,oBAAoB,CA0BtB"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ/D;AAOD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAoBtD;AAgBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA6ClD;AAQD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAWxD;AAOD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAa/D;AAUD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CActE;AAmBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwBpD;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAatE;AAKD,eAAO,MAAM,gBAAgB,sBAAgB,CAAC;AAQ9C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAiB,GAAG,IAAI,CAcnF;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,EAAE,QAAQ,SAAI,GAAG,IAAI,CAQpF;AASD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,SAAS,SAAc,GACtB,IAAI,CAQN;AASD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAc,GAAG,IAAI,CAkB5E;AAQD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAQ/E;AAQD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAe,GAAG,IAAI,CAQhF;AAUD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,IAAI,CAkBpE;AAKD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAaD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAuDpF;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAyBzE;AAaD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,oBAAoB,CA0BtB"}
@@ -32,8 +32,20 @@ function validateDocxStructure(filePaths) {
32
32
  }
33
33
  function isBinaryFile(filePath) {
34
34
  const binaryExtensions = [
35
- '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.ico',
36
- '.emf', '.wmf', '.bin', '.dat', '.ttf', '.otf', '.woff',
35
+ '.png',
36
+ '.jpg',
37
+ '.jpeg',
38
+ '.gif',
39
+ '.bmp',
40
+ '.tiff',
41
+ '.ico',
42
+ '.emf',
43
+ '.wmf',
44
+ '.bin',
45
+ '.dat',
46
+ '.ttf',
47
+ '.otf',
48
+ '.woff',
37
49
  ];
38
50
  const extension = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
39
51
  return binaryExtensions.includes(extension);
@@ -65,9 +77,9 @@ function isValidZipBuffer(buffer) {
65
77
  if (buffer.length < 4) {
66
78
  return false;
67
79
  }
68
- return ((buffer[0] === 0x50 && buffer[1] === 0x4B) &&
69
- ((buffer[2] === 0x03 && buffer[3] === 0x04) ||
70
- (buffer[2] === 0x05 && buffer[3] === 0x06)));
80
+ return (buffer[0] === 0x50 &&
81
+ buffer[1] === 0x4b &&
82
+ ((buffer[2] === 0x03 && buffer[3] === 0x04) || (buffer[2] === 0x05 && buffer[3] === 0x06)));
71
83
  }
72
84
  function isTextContent(content) {
73
85
  if (typeof content === 'string') {
@@ -98,7 +110,12 @@ function normalizeColor(color) {
98
110
  `(e.g., "FF0000", "#FF0000", "F00", or "#F00")`);
99
111
  }
100
112
  if (hex.length === 3) {
101
- return (hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2)).toUpperCase();
113
+ return (hex.charAt(0) +
114
+ hex.charAt(0) +
115
+ hex.charAt(1) +
116
+ hex.charAt(1) +
117
+ hex.charAt(2) +
118
+ hex.charAt(2)).toUpperCase();
102
119
  }
103
120
  return hex.toUpperCase();
104
121
  }
@@ -251,7 +268,7 @@ function validateRunText(text, options = {}) {
251
268
  if (warnToConsole && result.warnings.length > 0 && typeof console !== 'undefined') {
252
269
  const contextStr = context ? ` [${context}]` : '';
253
270
  logger_1.defaultLogger.warn(`DocXML Text Validation Warning${contextStr}:`);
254
- result.warnings.forEach(warning => logger_1.defaultLogger.warn(` - ${warning}`));
271
+ result.warnings.forEach((warning) => logger_1.defaultLogger.warn(` - ${warning}`));
255
272
  }
256
273
  return result;
257
274
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Validation utilities for DOCX files\r\n */\r\n\r\nimport { REQUIRED_DOCX_FILES } from '../zip/types';\r\nimport { MissingRequiredFileError } from '../zip/errors';\r\nimport { defaultLogger } from './logger';\r\n\r\n/**\r\n * Validates that all required DOCX files are present\r\n * @param filePaths - Array of file paths in the archive\r\n * @throws {MissingRequiredFileError} If a required file is missing\r\n */\r\nexport function validateDocxStructure(filePaths: string[]): void {\r\n const fileSet = new Set(filePaths);\r\n\r\n for (const requiredFile of REQUIRED_DOCX_FILES) {\r\n if (!fileSet.has(requiredFile)) {\r\n throw new MissingRequiredFileError(requiredFile);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Checks if a file path represents a binary file based on extension\r\n * @param filePath - The file path to check\r\n * @returns True if the file is likely binary\r\n */\r\nexport function isBinaryFile(filePath: string): boolean {\r\n const binaryExtensions = [\r\n '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.ico',\r\n '.emf', '.wmf', '.bin', '.dat', '.ttf', '.otf', '.woff',\r\n ];\r\n\r\n const extension = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();\r\n return binaryExtensions.includes(extension);\r\n}\r\n\r\n/**\r\n * Normalizes a file path for consistent comparisons\r\n * Converts backslashes to forward slashes and removes leading slashes\r\n * Also validates against path traversal attacks\r\n *\r\n * **Security:** This function validates paths to prevent:\r\n * - Path traversal attacks (../, ..\\, URL-encoded variants)\r\n * - Absolute paths (C:\\, /etc/, etc.)\r\n * - Malicious DOCX files attempting directory escape\r\n *\r\n * @param path - The path to normalize\r\n * @returns Normalized path\r\n * @throws {Error} If path contains path traversal sequences, absolute paths, or URL-encoded attacks\r\n */\r\nexport function normalizePath(path: string): string {\r\n // First convert all backslashes to forward slashes for consistent checking\r\n const normalized = path.replace(/\\\\/g, '/').replace(/^\\/+/, '');\r\n\r\n // Security: Reject URL-encoded path traversal attempts\r\n // Attackers might try: %2e%2e%2f (%2e = . and %2f = /)\r\n if (/%2[eE]|%2[fF]|%5[cC]/.test(path)) {\r\n throw new Error(\r\n `Invalid file path: \"${path}\" contains URL-encoded characters (%2E, %2F, %5C). ` +\r\n `This could be an attempt to bypass path validation. ` +\r\n `Only plain characters are allowed in DOCX file paths.`\r\n );\r\n }\r\n\r\n // Security: Prevent path traversal attacks\r\n // Check AFTER normalization when all paths use forward slashes\r\n // This catches: ../, /.., or standalone \"..\"\r\n if (normalized.includes('../') || normalized.includes('/..') || normalized === '..') {\r\n throw new Error(\r\n `Invalid file path: \"${path}\" contains path traversal sequence (..). ` +\r\n `This could be a malicious DOCX file attempting directory traversal. ` +\r\n `DOCX archives must only contain relative paths within the archive.`\r\n );\r\n }\r\n\r\n // Security: Prevent absolute paths (Windows drive letters)\r\n // Examples: C:/, C:\\, D:, etc.\r\n if (/^[a-zA-Z]:/.test(normalized)) {\r\n throw new Error(\r\n `Invalid file path: \"${path}\" appears to be an absolute Windows path. ` +\r\n `Absolute paths are not allowed in DOCX archives. ` +\r\n `Only relative paths within the archive are permitted.`\r\n );\r\n }\r\n\r\n // Security: Prevent Unix absolute paths\r\n // After removing leading slashes, if it starts with / it's suspicious\r\n if (path.startsWith('/') && normalized.startsWith('/')) {\r\n throw new Error(\r\n `Invalid file path: \"${path}\" appears to be an absolute Unix path. ` +\r\n `Only relative paths are allowed in DOCX archives.`\r\n );\r\n }\r\n\r\n return normalized;\r\n}\r\n\r\n/**\r\n * Validates that a buffer contains a valid ZIP file signature\r\n * ZIP files start with the signature 'PK' (0x50 0x4B)\r\n * @param buffer - The buffer to validate\r\n * @returns True if the buffer appears to be a ZIP file\r\n */\r\nexport function isValidZipBuffer(buffer: Buffer): boolean {\r\n if (buffer.length < 4) {\r\n return false;\r\n }\r\n\r\n // Check for ZIP signature: PK\\x03\\x04 or PK\\x05\\x06 (for empty archives)\r\n return (\r\n (buffer[0] === 0x50 && buffer[1] === 0x4B) &&\r\n ((buffer[2] === 0x03 && buffer[3] === 0x04) ||\r\n (buffer[2] === 0x05 && buffer[3] === 0x06))\r\n );\r\n}\r\n\r\n/**\r\n * Checks if a string is valid UTF-8 text\r\n * @param content - The content to check\r\n * @returns True if the content is valid text\r\n */\r\nexport function isTextContent(content: Buffer | string): boolean {\r\n if (typeof content === 'string') {\r\n return true;\r\n }\r\n\r\n // Try to decode as UTF-8 and check for null bytes\r\n try {\r\n const text = content.toString('utf8');\r\n // Binary files often contain null bytes\r\n return !text.includes('\\0');\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Validates a twips value (used for spacing, indentation, margins)\r\n * Twips: 1/20th of a point, 1440 twips = 1 inch\r\n * Reasonable range: -31680 to 31680 (±22 inches)\r\n * @param value - The twips value to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the value is invalid\r\n */\r\nexport function validateTwips(value: number, fieldName = 'value'): void {\r\n if (!Number.isFinite(value)) {\r\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\r\n }\r\n\r\n // Reasonable range: ±22 inches (31680 twips)\r\n const MIN_TWIPS = -31680;\r\n const MAX_TWIPS = 31680;\r\n\r\n if (value < MIN_TWIPS || value > MAX_TWIPS) {\r\n throw new Error(\r\n `${fieldName} out of range: ${value} twips (allowed: ${MIN_TWIPS} to ${MAX_TWIPS}, ±22 inches)`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Normalizes a color to uppercase 6-character hex format\r\n * Accepts 3-character or 6-character hex colors with or without '#' prefix\r\n * Follows Microsoft Word convention of uppercase hex colors\r\n *\r\n * @param color - Color to normalize (e.g., '#F00', 'FF0000', '#FF0000', 'f00')\r\n * @returns Normalized color (e.g., 'FF0000')\r\n * @throws Error if color format is invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * normalizeColor('#F00') // Returns: 'FF0000'\r\n * normalizeColor('FF0000') // Returns: 'FF0000'\r\n * normalizeColor('#ff0000') // Returns: 'FF0000'\r\n * normalizeColor('f00') // Returns: 'FF0000'\r\n * ```\r\n */\r\nexport function normalizeColor(color: string): string {\r\n const hex = color.replace(/^#/, '');\r\n\r\n // Validate hex format\r\n if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(hex)) {\r\n throw new Error(\r\n `Invalid color format: \"${color}\". Expected 3 or 6-character hex ` +\r\n `(e.g., \"FF0000\", \"#FF0000\", \"F00\", or \"#F00\")`\r\n );\r\n }\r\n\r\n // Expand 3-character to 6-character\r\n if (hex.length === 3) {\r\n return (hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2)).toUpperCase();\r\n }\r\n\r\n return hex.toUpperCase();\r\n}\r\n\r\n/**\r\n * Validates a hexadecimal color value\r\n * Must be 6 characters (RRGGBB format)\r\n * @param color - The color hex string to validate (without #)\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the color is invalid\r\n */\r\nexport function validateColor(color: string, fieldName = 'color'): void {\r\n if (typeof color !== 'string') {\r\n throw new Error(`${fieldName} must be a string, got ${typeof color}`);\r\n }\r\n\r\n // Allow both with and without # prefix\r\n const cleanColor = color.startsWith('#') ? color.substring(1) : color;\r\n\r\n if (!/^[0-9A-Fa-f]{6}$/.test(cleanColor)) {\r\n throw new Error(\r\n `${fieldName} must be a 6-digit hex color (e.g., 'FF0000' or '#FF0000'), got '${color}'`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Alias for validateColor for backwards compatibility\r\n */\r\nexport const validateHexColor = validateColor;\r\n\r\n/**\r\n * Validates a numbering ID (must be non-negative integer)\r\n * @param numId - The numbering ID to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the ID is invalid\r\n */\r\nexport function validateNumberingId(numId: number, fieldName = 'numbering ID'): void {\r\n if (!Number.isInteger(numId)) {\r\n throw new Error(`${fieldName} must be an integer, got ${numId}`);\r\n }\r\n\r\n if (numId < 0) {\r\n throw new Error(`${fieldName} must be non-negative, got ${numId}`);\r\n }\r\n\r\n // Word supports numbering IDs up to 2147483647\r\n const MAX_NUM_ID = 2147483647;\r\n if (numId > MAX_NUM_ID) {\r\n throw new Error(`${fieldName} exceeds maximum value ${MAX_NUM_ID}, got ${numId}`);\r\n }\r\n}\r\n\r\n/**\r\n * Validates a numbering level (0-8 for Word)\r\n * @param level - The level to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @param maxLevel - Maximum allowed level (default 8)\r\n * @throws {Error} If the level is invalid\r\n */\r\nexport function validateLevel(\r\n level: number,\r\n fieldName = 'level',\r\n maxLevel = 8\r\n): void {\r\n if (!Number.isInteger(level)) {\r\n throw new Error(`${fieldName} must be an integer, got ${level}`);\r\n }\r\n\r\n if (level < 0 || level > maxLevel) {\r\n throw new Error(`${fieldName} must be between 0 and ${maxLevel}, got ${level}`);\r\n }\r\n}\r\n\r\n/**\r\n * Validates an alignment value against allowed values\r\n * @param alignment - The alignment value to validate\r\n * @param allowed - Array of allowed alignment values\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the alignment is invalid\r\n */\r\nexport function validateAlignment(\r\n alignment: string,\r\n allowed: readonly string[],\r\n fieldName = 'alignment'\r\n): void {\r\n if (typeof alignment !== 'string') {\r\n throw new Error(`${fieldName} must be a string, got ${typeof alignment}`);\r\n }\r\n\r\n if (!allowed.includes(alignment)) {\r\n throw new Error(\r\n `Invalid ${fieldName}: '${alignment}' (allowed: ${allowed.join(', ')})`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Validates a font size (in half-points for Word)\r\n * Reasonable range: 2-1638 (1-819 points)\r\n * @param size - The font size in half-points to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the size is invalid\r\n */\r\nexport function validateFontSize(size: number, fieldName = 'font size'): void {\r\n if (!Number.isFinite(size)) {\r\n throw new Error(`${fieldName} must be a finite number, got ${size}`);\r\n }\r\n\r\n if (!Number.isInteger(size)) {\r\n throw new Error(`${fieldName} must be an integer (in half-points), got ${size}`);\r\n }\r\n\r\n // Reasonable range: 2-1638 half-points (1-819 points)\r\n const MIN_SIZE = 2;\r\n const MAX_SIZE = 1638;\r\n\r\n if (size < MIN_SIZE || size > MAX_SIZE) {\r\n throw new Error(\r\n `${fieldName} out of range: ${size} half-points (allowed: ${MIN_SIZE}-${MAX_SIZE}, or ${MIN_SIZE / 2}-${MAX_SIZE / 2} points)`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Validates that a string is not empty\r\n * @param value - The string to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the string is empty or not a string\r\n */\r\nexport function validateNonEmptyString(value: string, fieldName = 'value'): void {\r\n if (typeof value !== 'string') {\r\n throw new Error(`${fieldName} must be a string, got ${typeof value}`);\r\n }\r\n\r\n if (value.trim().length === 0) {\r\n throw new Error(`${fieldName} cannot be empty`);\r\n }\r\n}\r\n\r\n/**\r\n * Validates a percentage value (0-100)\r\n * @param value - The percentage to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the percentage is invalid\r\n */\r\nexport function validatePercentage(value: number, fieldName = 'percentage'): void {\r\n if (!Number.isFinite(value)) {\r\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\r\n }\r\n\r\n if (value < 0 || value > 100) {\r\n throw new Error(`${fieldName} must be between 0 and 100, got ${value}`);\r\n }\r\n}\r\n\r\n/**\r\n * Validates EMUs (English Metric Units) value\r\n * Used for image dimensions: 914400 EMUs = 1 inch\r\n * Reasonable range: 0 to 50 million (about 55 inches)\r\n * @param value - The EMUs value to validate\r\n * @param fieldName - Name of the field (for error messages)\r\n * @throws {Error} If the value is invalid\r\n */\r\nexport function validateEmus(value: number, fieldName = 'EMUs'): void {\r\n if (!Number.isFinite(value)) {\r\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\r\n }\r\n\r\n if (!Number.isInteger(value)) {\r\n throw new Error(`${fieldName} must be an integer, got ${value}`);\r\n }\r\n\r\n if (value < 0) {\r\n throw new Error(`${fieldName} must be non-negative, got ${value}`);\r\n }\r\n\r\n // Reasonable maximum: 50 million EMUs (about 55 inches)\r\n const MAX_EMUS = 50000000;\r\n if (value > MAX_EMUS) {\r\n throw new Error(\r\n `${fieldName} exceeds maximum ${MAX_EMUS} (about 55 inches), got ${value}`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Result of text validation for XML-like content\r\n */\r\nexport interface TextValidationResult {\r\n isValid: boolean;\r\n hasXmlPatterns: boolean;\r\n warnings: string[];\r\n cleanedText?: string;\r\n}\r\n\r\n/**\r\n * Detects XML-like patterns in text that might cause display issues\r\n *\r\n * This function checks for patterns that look like XML markup which,\r\n * when properly escaped in XML output, will display as literal text\r\n * in Word documents rather than being interpreted as markup.\r\n *\r\n * @param text - The text to validate\r\n * @param context - Optional context for better warning messages (e.g., \"hyperlink text\")\r\n * @returns Validation result with warnings and optional cleaned text\r\n */\r\nexport function detectXmlInText(text: string, context?: string): TextValidationResult {\r\n const warnings: string[] = [];\r\n let hasXmlPatterns = false;\r\n\r\n // Check for common XML element patterns\r\n const xmlElementPattern = /<\\/?w:[^>]+>|<w:[^>]+\\/>/g;\r\n const escapedXmlPattern = /&lt;.*?&gt;|&quot;|&apos;/g;\r\n\r\n // Check for specific problematic patterns we've seen\r\n const problematicPatterns = [\r\n /<w:t\\s+xml:space=\"preserve\">/,\r\n /<w:t\\s+xml:space=[\"']preserve[\"']>/,\r\n /<\\/w:t>/,\r\n /&lt;w:t\\s+xml:space=&quot;preserve&quot;&gt;/,\r\n ];\r\n\r\n // Check for any XML-like tags\r\n if (xmlElementPattern.test(text)) {\r\n hasXmlPatterns = true;\r\n const contextStr = context ? ` in ${context}` : '';\r\n warnings.push(\r\n `Text${contextStr} contains XML-like markup: \"${text.substring(0, 100)}${text.length > 100 ? '...' : ''}\". ` +\r\n `This will be displayed as literal text in the document. ` +\r\n `If you intended to add formatting, use the appropriate API methods instead.`\r\n );\r\n }\r\n\r\n // Check for already-escaped XML entities\r\n if (escapedXmlPattern.test(text)) {\r\n hasXmlPatterns = true;\r\n const contextStr = context ? ` in ${context}` : '';\r\n warnings.push(\r\n `Text${contextStr} contains escaped XML entities (e.g., &lt;, &gt;, &quot;). ` +\r\n `These will appear as literal characters in the document.`\r\n );\r\n }\r\n\r\n // Check for specific known problematic patterns\r\n for (const pattern of problematicPatterns) {\r\n if (pattern.test(text)) {\r\n hasXmlPatterns = true;\r\n const contextStr = context ? ` in ${context}` : '';\r\n warnings.push(\r\n `Text${contextStr} contains a known problematic XML pattern that suggests ` +\r\n `the text may have been corrupted by previous processing.`\r\n );\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n isValid: true, // Text is always \"valid\" - we just warn about potential issues\r\n hasXmlPatterns,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Cleans XML-like patterns from text\r\n *\r\n * This function removes or cleans various XML patterns that might\r\n * appear in text content, typically from corrupted or improperly\r\n * processed documents.\r\n *\r\n * @param text - The text to clean\r\n * @param aggressive - If true, removes all angle brackets; if false, only removes clear XML tags\r\n * @returns Cleaned text with XML patterns removed\r\n */\r\nexport function cleanXmlFromText(text: string, aggressive = false): string {\r\n let cleaned = text;\r\n\r\n // First, unescape any HTML/XML entities\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 // Remove specific Word XML patterns\r\n // This targets patterns like <w:t xml:space=\"preserve\">\r\n cleaned = cleaned.replace(/<w:[^>]+>/g, '');\r\n cleaned = cleaned.replace(/<\\/w:[^>]+>/g, '');\r\n\r\n // Remove any remaining XML-like tags if aggressive mode\r\n if (aggressive) {\r\n cleaned = cleaned.replace(/<[^>]+>/g, '');\r\n }\r\n\r\n // Clean up any double spaces left behind\r\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Validates text for use in Run or Hyperlink elements\r\n *\r\n * This is the main validation function that should be called when\r\n * setting text content in Run or Hyperlink elements. It provides\r\n * warnings about problematic content and optionally cleans the text.\r\n *\r\n * @param text - The text to validate\r\n * @param options - Validation options\r\n * @returns Validation result with warnings and optionally cleaned text\r\n */\r\nexport function validateRunText(\r\n text: string,\r\n options: {\r\n context?: string;\r\n autoClean?: boolean;\r\n aggressive?: boolean;\r\n warnToConsole?: boolean;\r\n } = {}\r\n): TextValidationResult {\r\n const { context, autoClean = false, aggressive = false, warnToConsole = true } = options;\r\n\r\n // Detect XML patterns\r\n const result = detectXmlInText(text, context);\r\n\r\n // If auto-cleaning is enabled and XML patterns were found\r\n if (autoClean && result.hasXmlPatterns) {\r\n result.cleanedText = cleanXmlFromText(text, aggressive);\r\n\r\n // Add a note about cleaning\r\n result.warnings.push(\r\n `Text has been automatically cleaned. ` +\r\n `Original: \"${text.substring(0, 50)}${text.length > 50 ? '...' : ''}\" ` +\r\n `Cleaned: \"${result.cleanedText.substring(0, 50)}${result.cleanedText.length > 50 ? '...' : ''}\"`\r\n );\r\n }\r\n\r\n // Log warnings to console in development if requested\r\n if (warnToConsole && result.warnings.length > 0 && typeof console !== 'undefined') {\r\n const contextStr = context ? ` [${context}]` : '';\r\n defaultLogger.warn(`DocXML Text Validation Warning${contextStr}:`);\r\n result.warnings.forEach(warning => defaultLogger.warn(` - ${warning}`));\r\n }\r\n\r\n return result;\r\n}\r\n"]}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validation utilities for DOCX files\n */\n\nimport { REQUIRED_DOCX_FILES } from '../zip/types';\nimport { MissingRequiredFileError } from '../zip/errors';\nimport { defaultLogger } from './logger';\n\n/**\n * Validates that all required DOCX files are present\n * @param filePaths - Array of file paths in the archive\n * @throws {MissingRequiredFileError} If a required file is missing\n */\nexport function validateDocxStructure(filePaths: string[]): void {\n const fileSet = new Set(filePaths);\n\n for (const requiredFile of REQUIRED_DOCX_FILES) {\n if (!fileSet.has(requiredFile)) {\n throw new MissingRequiredFileError(requiredFile);\n }\n }\n}\n\n/**\n * Checks if a file path represents a binary file based on extension\n * @param filePath - The file path to check\n * @returns True if the file is likely binary\n */\nexport function isBinaryFile(filePath: string): boolean {\n const binaryExtensions = [\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.tiff',\n '.ico',\n '.emf',\n '.wmf',\n '.bin',\n '.dat',\n '.ttf',\n '.otf',\n '.woff',\n ];\n\n const extension = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();\n return binaryExtensions.includes(extension);\n}\n\n/**\n * Normalizes a file path for consistent comparisons\n * Converts backslashes to forward slashes and removes leading slashes\n * Also validates against path traversal attacks\n *\n * **Security:** This function validates paths to prevent:\n * - Path traversal attacks (../, ..\\, URL-encoded variants)\n * - Absolute paths (C:\\, /etc/, etc.)\n * - Malicious DOCX files attempting directory escape\n *\n * @param path - The path to normalize\n * @returns Normalized path\n * @throws {Error} If path contains path traversal sequences, absolute paths, or URL-encoded attacks\n */\nexport function normalizePath(path: string): string {\n // First convert all backslashes to forward slashes for consistent checking\n const normalized = path.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n\n // Security: Reject URL-encoded path traversal attempts\n // Attackers might try: %2e%2e%2f (%2e = . and %2f = /)\n if (/%2[eE]|%2[fF]|%5[cC]/.test(path)) {\n throw new Error(\n `Invalid file path: \"${path}\" contains URL-encoded characters (%2E, %2F, %5C). ` +\n `This could be an attempt to bypass path validation. ` +\n `Only plain characters are allowed in DOCX file paths.`\n );\n }\n\n // Security: Prevent path traversal attacks\n // Check AFTER normalization when all paths use forward slashes\n // This catches: ../, /.., or standalone \"..\"\n if (normalized.includes('../') || normalized.includes('/..') || normalized === '..') {\n throw new Error(\n `Invalid file path: \"${path}\" contains path traversal sequence (..). ` +\n `This could be a malicious DOCX file attempting directory traversal. ` +\n `DOCX archives must only contain relative paths within the archive.`\n );\n }\n\n // Security: Prevent absolute paths (Windows drive letters)\n // Examples: C:/, C:\\, D:, etc.\n if (/^[a-zA-Z]:/.test(normalized)) {\n throw new Error(\n `Invalid file path: \"${path}\" appears to be an absolute Windows path. ` +\n `Absolute paths are not allowed in DOCX archives. ` +\n `Only relative paths within the archive are permitted.`\n );\n }\n\n // Security: Prevent Unix absolute paths\n // After removing leading slashes, if it starts with / it's suspicious\n if (path.startsWith('/') && normalized.startsWith('/')) {\n throw new Error(\n `Invalid file path: \"${path}\" appears to be an absolute Unix path. ` +\n `Only relative paths are allowed in DOCX archives.`\n );\n }\n\n return normalized;\n}\n\n/**\n * Validates that a buffer contains a valid ZIP file signature\n * ZIP files start with the signature 'PK' (0x50 0x4B)\n * @param buffer - The buffer to validate\n * @returns True if the buffer appears to be a ZIP file\n */\nexport function isValidZipBuffer(buffer: Buffer): boolean {\n if (buffer.length < 4) {\n return false;\n }\n\n // Check for ZIP signature: PK\\x03\\x04 or PK\\x05\\x06 (for empty archives)\n return (\n buffer[0] === 0x50 &&\n buffer[1] === 0x4b &&\n ((buffer[2] === 0x03 && buffer[3] === 0x04) || (buffer[2] === 0x05 && buffer[3] === 0x06))\n );\n}\n\n/**\n * Checks if a string is valid UTF-8 text\n * @param content - The content to check\n * @returns True if the content is valid text\n */\nexport function isTextContent(content: Buffer | string): boolean {\n if (typeof content === 'string') {\n return true;\n }\n\n // Try to decode as UTF-8 and check for null bytes\n try {\n const text = content.toString('utf8');\n // Binary files often contain null bytes\n return !text.includes('\\0');\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a twips value (used for spacing, indentation, margins)\n * Twips: 1/20th of a point, 1440 twips = 1 inch\n * Reasonable range: -31680 to 31680 (±22 inches)\n * @param value - The twips value to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the value is invalid\n */\nexport function validateTwips(value: number, fieldName = 'value'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n // Reasonable range: ±22 inches (31680 twips)\n const MIN_TWIPS = -31680;\n const MAX_TWIPS = 31680;\n\n if (value < MIN_TWIPS || value > MAX_TWIPS) {\n throw new Error(\n `${fieldName} out of range: ${value} twips (allowed: ${MIN_TWIPS} to ${MAX_TWIPS}, ±22 inches)`\n );\n }\n}\n\n/**\n * Normalizes a color to uppercase 6-character hex format\n * Accepts 3-character or 6-character hex colors with or without '#' prefix\n * Follows Microsoft Word convention of uppercase hex colors\n *\n * @param color - Color to normalize (e.g., '#F00', 'FF0000', '#FF0000', 'f00')\n * @returns Normalized color (e.g., 'FF0000')\n * @throws Error if color format is invalid\n *\n * @example\n * ```typescript\n * normalizeColor('#F00') // Returns: 'FF0000'\n * normalizeColor('FF0000') // Returns: 'FF0000'\n * normalizeColor('#ff0000') // Returns: 'FF0000'\n * normalizeColor('f00') // Returns: 'FF0000'\n * ```\n */\nexport function normalizeColor(color: string): string {\n const hex = color.replace(/^#/, '');\n\n // Validate hex format\n if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(hex)) {\n throw new Error(\n `Invalid color format: \"${color}\". Expected 3 or 6-character hex ` +\n `(e.g., \"FF0000\", \"#FF0000\", \"F00\", or \"#F00\")`\n );\n }\n\n // Expand 3-character to 6-character\n if (hex.length === 3) {\n return (\n hex.charAt(0) +\n hex.charAt(0) +\n hex.charAt(1) +\n hex.charAt(1) +\n hex.charAt(2) +\n hex.charAt(2)\n ).toUpperCase();\n }\n\n return hex.toUpperCase();\n}\n\n/**\n * Validates a hexadecimal color value\n * Must be 6 characters (RRGGBB format)\n * @param color - The color hex string to validate (without #)\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the color is invalid\n */\nexport function validateColor(color: string, fieldName = 'color'): void {\n if (typeof color !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof color}`);\n }\n\n // Allow both with and without # prefix\n const cleanColor = color.startsWith('#') ? color.substring(1) : color;\n\n if (!/^[0-9A-Fa-f]{6}$/.test(cleanColor)) {\n throw new Error(\n `${fieldName} must be a 6-digit hex color (e.g., 'FF0000' or '#FF0000'), got '${color}'`\n );\n }\n}\n\n/**\n * Alias for validateColor for backwards compatibility\n */\nexport const validateHexColor = validateColor;\n\n/**\n * Validates a numbering ID (must be non-negative integer)\n * @param numId - The numbering ID to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the ID is invalid\n */\nexport function validateNumberingId(numId: number, fieldName = 'numbering ID'): void {\n if (!Number.isInteger(numId)) {\n throw new Error(`${fieldName} must be an integer, got ${numId}`);\n }\n\n if (numId < 0) {\n throw new Error(`${fieldName} must be non-negative, got ${numId}`);\n }\n\n // Word supports numbering IDs up to 2147483647\n const MAX_NUM_ID = 2147483647;\n if (numId > MAX_NUM_ID) {\n throw new Error(`${fieldName} exceeds maximum value ${MAX_NUM_ID}, got ${numId}`);\n }\n}\n\n/**\n * Validates a numbering level (0-8 for Word)\n * @param level - The level to validate\n * @param fieldName - Name of the field (for error messages)\n * @param maxLevel - Maximum allowed level (default 8)\n * @throws {Error} If the level is invalid\n */\nexport function validateLevel(level: number, fieldName = 'level', maxLevel = 8): void {\n if (!Number.isInteger(level)) {\n throw new Error(`${fieldName} must be an integer, got ${level}`);\n }\n\n if (level < 0 || level > maxLevel) {\n throw new Error(`${fieldName} must be between 0 and ${maxLevel}, got ${level}`);\n }\n}\n\n/**\n * Validates an alignment value against allowed values\n * @param alignment - The alignment value to validate\n * @param allowed - Array of allowed alignment values\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the alignment is invalid\n */\nexport function validateAlignment(\n alignment: string,\n allowed: readonly string[],\n fieldName = 'alignment'\n): void {\n if (typeof alignment !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof alignment}`);\n }\n\n if (!allowed.includes(alignment)) {\n throw new Error(`Invalid ${fieldName}: '${alignment}' (allowed: ${allowed.join(', ')})`);\n }\n}\n\n/**\n * Validates a font size (in half-points for Word)\n * Reasonable range: 2-1638 (1-819 points)\n * @param size - The font size in half-points to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the size is invalid\n */\nexport function validateFontSize(size: number, fieldName = 'font size'): void {\n if (!Number.isFinite(size)) {\n throw new Error(`${fieldName} must be a finite number, got ${size}`);\n }\n\n if (!Number.isInteger(size)) {\n throw new Error(`${fieldName} must be an integer (in half-points), got ${size}`);\n }\n\n // Reasonable range: 2-1638 half-points (1-819 points)\n const MIN_SIZE = 2;\n const MAX_SIZE = 1638;\n\n if (size < MIN_SIZE || size > MAX_SIZE) {\n throw new Error(\n `${fieldName} out of range: ${size} half-points (allowed: ${MIN_SIZE}-${MAX_SIZE}, or ${MIN_SIZE / 2}-${MAX_SIZE / 2} points)`\n );\n }\n}\n\n/**\n * Validates that a string is not empty\n * @param value - The string to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the string is empty or not a string\n */\nexport function validateNonEmptyString(value: string, fieldName = 'value'): void {\n if (typeof value !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof value}`);\n }\n\n if (value.trim().length === 0) {\n throw new Error(`${fieldName} cannot be empty`);\n }\n}\n\n/**\n * Validates a percentage value (0-100)\n * @param value - The percentage to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the percentage is invalid\n */\nexport function validatePercentage(value: number, fieldName = 'percentage'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n if (value < 0 || value > 100) {\n throw new Error(`${fieldName} must be between 0 and 100, got ${value}`);\n }\n}\n\n/**\n * Validates EMUs (English Metric Units) value\n * Used for image dimensions: 914400 EMUs = 1 inch\n * Reasonable range: 0 to 50 million (about 55 inches)\n * @param value - The EMUs value to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the value is invalid\n */\nexport function validateEmus(value: number, fieldName = 'EMUs'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n if (!Number.isInteger(value)) {\n throw new Error(`${fieldName} must be an integer, got ${value}`);\n }\n\n if (value < 0) {\n throw new Error(`${fieldName} must be non-negative, got ${value}`);\n }\n\n // Reasonable maximum: 50 million EMUs (about 55 inches)\n const MAX_EMUS = 50000000;\n if (value > MAX_EMUS) {\n throw new Error(`${fieldName} exceeds maximum ${MAX_EMUS} (about 55 inches), got ${value}`);\n }\n}\n\n/**\n * Result of text validation for XML-like content\n */\nexport interface TextValidationResult {\n isValid: boolean;\n hasXmlPatterns: boolean;\n warnings: string[];\n cleanedText?: string;\n}\n\n/**\n * Detects XML-like patterns in text that might cause display issues\n *\n * This function checks for patterns that look like XML markup which,\n * when properly escaped in XML output, will display as literal text\n * in Word documents rather than being interpreted as markup.\n *\n * @param text - The text to validate\n * @param context - Optional context for better warning messages (e.g., \"hyperlink text\")\n * @returns Validation result with warnings and optional cleaned text\n */\nexport function detectXmlInText(text: string, context?: string): TextValidationResult {\n const warnings: string[] = [];\n let hasXmlPatterns = false;\n\n // Check for common XML element patterns\n const xmlElementPattern = /<\\/?w:[^>]+>|<w:[^>]+\\/>/g;\n const escapedXmlPattern = /&lt;.*?&gt;|&quot;|&apos;/g;\n\n // Check for specific problematic patterns we've seen\n const problematicPatterns = [\n /<w:t\\s+xml:space=\"preserve\">/,\n /<w:t\\s+xml:space=[\"']preserve[\"']>/,\n /<\\/w:t>/,\n /&lt;w:t\\s+xml:space=&quot;preserve&quot;&gt;/,\n ];\n\n // Check for any XML-like tags\n if (xmlElementPattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains XML-like markup: \"${text.substring(0, 100)}${text.length > 100 ? '...' : ''}\". ` +\n `This will be displayed as literal text in the document. ` +\n `If you intended to add formatting, use the appropriate API methods instead.`\n );\n }\n\n // Check for already-escaped XML entities\n if (escapedXmlPattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains escaped XML entities (e.g., &lt;, &gt;, &quot;). ` +\n `These will appear as literal characters in the document.`\n );\n }\n\n // Check for specific known problematic patterns\n for (const pattern of problematicPatterns) {\n if (pattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains a known problematic XML pattern that suggests ` +\n `the text may have been corrupted by previous processing.`\n );\n break;\n }\n }\n\n return {\n isValid: true, // Text is always \"valid\" - we just warn about potential issues\n hasXmlPatterns,\n warnings,\n };\n}\n\n/**\n * Cleans XML-like patterns from text\n *\n * This function removes or cleans various XML patterns that might\n * appear in text content, typically from corrupted or improperly\n * processed documents.\n *\n * @param text - The text to clean\n * @param aggressive - If true, removes all angle brackets; if false, only removes clear XML tags\n * @returns Cleaned text with XML patterns removed\n */\nexport function cleanXmlFromText(text: string, aggressive = false): string {\n let cleaned = text;\n\n // First, unescape any HTML/XML entities\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 // Remove specific Word XML patterns\n // This targets patterns like <w:t xml:space=\"preserve\">\n cleaned = cleaned.replace(/<w:[^>]+>/g, '');\n cleaned = cleaned.replace(/<\\/w:[^>]+>/g, '');\n\n // Remove any remaining XML-like tags if aggressive mode\n if (aggressive) {\n cleaned = cleaned.replace(/<[^>]+>/g, '');\n }\n\n // Clean up any double spaces left behind\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\n\n return cleaned;\n}\n\n/**\n * Validates text for use in Run or Hyperlink elements\n *\n * This is the main validation function that should be called when\n * setting text content in Run or Hyperlink elements. It provides\n * warnings about problematic content and optionally cleans the text.\n *\n * @param text - The text to validate\n * @param options - Validation options\n * @returns Validation result with warnings and optionally cleaned text\n */\nexport function validateRunText(\n text: string,\n options: {\n context?: string;\n autoClean?: boolean;\n aggressive?: boolean;\n warnToConsole?: boolean;\n } = {}\n): TextValidationResult {\n const { context, autoClean = false, aggressive = false, warnToConsole = true } = options;\n\n // Detect XML patterns\n const result = detectXmlInText(text, context);\n\n // If auto-cleaning is enabled and XML patterns were found\n if (autoClean && result.hasXmlPatterns) {\n result.cleanedText = cleanXmlFromText(text, aggressive);\n\n // Add a note about cleaning\n result.warnings.push(\n `Text has been automatically cleaned. ` +\n `Original: \"${text.substring(0, 50)}${text.length > 50 ? '...' : ''}\" ` +\n `Cleaned: \"${result.cleanedText.substring(0, 50)}${result.cleanedText.length > 50 ? '...' : ''}\"`\n );\n }\n\n // Log warnings to console in development if requested\n if (warnToConsole && result.warnings.length > 0 && typeof console !== 'undefined') {\n const contextStr = context ? ` [${context}]` : '';\n defaultLogger.warn(`DocXML Text Validation Warning${contextStr}:`);\n result.warnings.forEach((warning) => defaultLogger.warn(` - ${warning}`));\n }\n\n return result;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"xmlSanitization.d.ts","sourceRoot":"","sources":["../../src/utils/xmlSanitization.ts"],"names":[],"mappings":"AAuDA,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,UAAU,UAAO,GAChB,MAAM,CAoBR;AAoBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB1D;AAkBD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIxD;AAKD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CAmCpB,CAAC"}
1
+ {"version":3,"file":"xmlSanitization.d.ts","sourceRoot":"","sources":["../../src/utils/xmlSanitization.ts"],"names":[],"mappings":"AAuDA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,MAAM,CAoB7E;AAoBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB1D;AAkBD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIxD;AAKD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CAmCpB,CAAC"}
@@ -12,12 +12,12 @@ function removeInvalidXmlChars(text, logWarning = true) {
12
12
  INVALID_XML_CHAR_REGEX.lastIndex = 0;
13
13
  const invalidChars = findInvalidXmlChars(text);
14
14
  const hexCodes = invalidChars
15
- .map((c) => `0x${c.toString(16).toUpperCase().padStart(2, "0")}`)
16
- .join(", ");
15
+ .map((c) => `0x${c.toString(16).toUpperCase().padStart(2, '0')}`)
16
+ .join(', ');
17
17
  (0, logger_1.getGlobalLogger)().warn(`[XMLSanitization] Removing invalid XML control characters: ${hexCodes}`);
18
18
  }
19
19
  INVALID_XML_CHAR_REGEX.lastIndex = 0;
20
- return text.replace(INVALID_XML_CHAR_REGEX, "");
20
+ return text.replace(INVALID_XML_CHAR_REGEX, '');
21
21
  }
22
22
  function findInvalidXmlChars(text) {
23
23
  const invalid = [];
@@ -1 +1 @@
1
- {"version":3,"file":"xmlSanitization.js","sourceRoot":"","sources":["../../src/utils/xmlSanitization.ts"],"names":[],"mappings":";;;AAuDA,sDAuBC;AAoBD,kDAqBC;AAkBD,gDAIC;AAzHD,qCAA2C;AAO3C,MAAM,sBAAsB,GAAG,mCAAmC,CAAC;AA4BnE,SAAgB,qBAAqB,CACnC,IAAY,EACZ,UAAU,GAAG,IAAI;IAGjB,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;IAErC,IAAI,UAAU,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAEpD,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;QAErC,MAAM,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,YAAY;aAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;aAChE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,IAAA,wBAAe,GAAE,CAAC,IAAI,CACpB,8DAA8D,QAAQ,EAAE,CACzE,CAAC;IACJ,CAAC;IAGD,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAoBD,SAAgB,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAGhC,IACE,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;YAC9B,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;YAC9B,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;YAC9B,IAAI,KAAK,IAAI,EACb,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAkBD,SAAgB,kBAAkB,CAAC,IAAY;IAE7C,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;IACrC,OAAO,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC;AAKY,QAAA,iBAAiB,GAAG;IAE/B,IAAI,EAAE,IAAI;IAEV,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,EAAE,EAAE,IAAI;IAER,GAAG,EAAE,IAAI;IAET,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,GAAG,EAAE,IAAI;CACD,CAAC","sourcesContent":["/**\r\n * XML Sanitization Utilities\r\n *\r\n * Provides functions for validating and sanitizing text content per XML 1.0 specification.\r\n * Per XML 1.0, certain control characters are invalid and must be removed before\r\n * including text in XML documents.\r\n *\r\n * Valid characters in XML 1.0:\r\n * - 0x09 (tab), 0x0A (newline), 0x0D (carriage return)\r\n * - 0x20-0xD7FF, 0xE000-0xFFFD, 0x10000-0x10FFFF\r\n *\r\n * Invalid characters (control characters that must be removed):\r\n * - 0x00-0x08 (NULL through BACKSPACE)\r\n * - 0x0B-0x0C (VERTICAL TAB and FORM FEED)\r\n * - 0x0E-0x1F (SHIFT OUT through UNIT SEPARATOR)\r\n * - 0x7F (DELETE)\r\n *\r\n * @module xmlSanitization\r\n */\r\n\r\nimport { getGlobalLogger } from \"./logger\";\r\n\r\n/**\r\n * Regular expression matching invalid XML 1.0 control characters.\r\n * Matches: 0x00-0x08, 0x0B-0x0C, 0x0E-0x1F, 0x7F\r\n * Does NOT match valid chars: 0x09 (tab), 0x0A (newline), 0x0D (CR)\r\n */\r\nconst INVALID_XML_CHAR_REGEX = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g;\r\n\r\n/**\r\n * Removes invalid XML 1.0 control characters from text.\r\n *\r\n * Per XML 1.0 spec, characters 0x00-0x08, 0x0B-0x0C, 0x0E-0x1F, 0x7F are invalid\r\n * and cannot appear in XML documents. This function removes them.\r\n *\r\n * Valid control characters are preserved:\r\n * - Tab (0x09)\r\n * - Line Feed / Newline (0x0A)\r\n * - Carriage Return (0x0D)\r\n *\r\n * @param text - Input text to sanitize\r\n * @param logWarning - If true, logs a warning when invalid chars are found (default: true)\r\n * @returns Sanitized text with invalid control characters removed\r\n *\r\n * @example\r\n * ```typescript\r\n * // Remove NULL byte from text\r\n * const clean = removeInvalidXmlChars(\"Hello\\x00World\");\r\n * // Returns: \"HelloWorld\"\r\n *\r\n * // Tab and newline are preserved\r\n * const preserved = removeInvalidXmlChars(\"Hello\\tWorld\\n\");\r\n * // Returns: \"Hello\\tWorld\\n\"\r\n * ```\r\n */\r\nexport function removeInvalidXmlChars(\r\n text: string,\r\n logWarning = true\r\n): string {\r\n // Reset regex lastIndex for global regex\r\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\r\n\r\n if (logWarning && INVALID_XML_CHAR_REGEX.test(text)) {\r\n // Reset regex lastIndex after test\r\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\r\n\r\n const invalidChars = findInvalidXmlChars(text);\r\n const hexCodes = invalidChars\r\n .map((c) => `0x${c.toString(16).toUpperCase().padStart(2, \"0\")}`)\r\n .join(\", \");\r\n getGlobalLogger().warn(\r\n `[XMLSanitization] Removing invalid XML control characters: ${hexCodes}`\r\n );\r\n }\r\n\r\n // Reset regex lastIndex before replace\r\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\r\n return text.replace(INVALID_XML_CHAR_REGEX, \"\");\r\n}\r\n\r\n/**\r\n * Finds all invalid XML 1.0 control characters in text.\r\n *\r\n * Returns an array of unique character codes that are invalid per XML 1.0 spec.\r\n * This is useful for diagnostics and error reporting.\r\n *\r\n * @param text - Text to scan for invalid characters\r\n * @returns Array of unique invalid character codes found, or empty array if text is valid\r\n *\r\n * @example\r\n * ```typescript\r\n * const invalid = findInvalidXmlChars(\"Hello\\x00\\x08World\");\r\n * // Returns: [0, 8] - NULL and BACKSPACE codes\r\n *\r\n * const valid = findInvalidXmlChars(\"Hello\\tWorld\");\r\n * // Returns: [] - tab is valid\r\n * ```\r\n */\r\nexport function findInvalidXmlChars(text: string): number[] {\r\n const invalid: number[] = [];\r\n\r\n for (let i = 0; i < text.length; i++) {\r\n const code = text.charCodeAt(i);\r\n\r\n // Check if character is in invalid ranges\r\n if (\r\n (code >= 0x00 && code <= 0x08) || // NULL through BACKSPACE\r\n (code >= 0x0b && code <= 0x0c) || // VERTICAL TAB and FORM FEED\r\n (code >= 0x0e && code <= 0x1f) || // SHIFT OUT through UNIT SEPARATOR\r\n code === 0x7f // DELETE\r\n ) {\r\n // Only add unique codes\r\n if (!invalid.includes(code)) {\r\n invalid.push(code);\r\n }\r\n }\r\n }\r\n\r\n return invalid;\r\n}\r\n\r\n/**\r\n * Checks if text contains any invalid XML 1.0 control characters.\r\n *\r\n * This is a fast check that returns true/false without identifying specific characters.\r\n * Use `findInvalidXmlChars()` if you need to know which characters are invalid.\r\n *\r\n * @param text - Text to check\r\n * @returns true if text contains invalid characters, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * hasInvalidXmlChars(\"Hello\\x00World\"); // true - NULL byte\r\n * hasInvalidXmlChars(\"Hello\\tWorld\"); // false - tab is valid\r\n * hasInvalidXmlChars(\"Normal text\"); // false\r\n * ```\r\n */\r\nexport function hasInvalidXmlChars(text: string): boolean {\r\n // Reset regex lastIndex for global regex\r\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\r\n return INVALID_XML_CHAR_REGEX.test(text);\r\n}\r\n\r\n/**\r\n * Character code constants for documentation and testing.\r\n */\r\nexport const XML_CONTROL_CHARS = {\r\n /** NULL (0x00) - Invalid */\r\n NULL: 0x00,\r\n /** Start of Heading (0x01) - Invalid */\r\n SOH: 0x01,\r\n /** Start of Text (0x02) - Invalid */\r\n STX: 0x02,\r\n /** End of Text (0x03) - Invalid */\r\n ETX: 0x03,\r\n /** End of Transmission (0x04) - Invalid */\r\n EOT: 0x04,\r\n /** Enquiry (0x05) - Invalid */\r\n ENQ: 0x05,\r\n /** Acknowledge (0x06) - Invalid */\r\n ACK: 0x06,\r\n /** Bell (0x07) - Invalid */\r\n BEL: 0x07,\r\n /** Backspace (0x08) - Invalid */\r\n BS: 0x08,\r\n /** Horizontal Tab (0x09) - VALID */\r\n TAB: 0x09,\r\n /** Line Feed / Newline (0x0A) - VALID */\r\n LF: 0x0a,\r\n /** Vertical Tab (0x0B) - Invalid */\r\n VT: 0x0b,\r\n /** Form Feed (0x0C) - Invalid */\r\n FF: 0x0c,\r\n /** Carriage Return (0x0D) - VALID */\r\n CR: 0x0d,\r\n /** Shift Out (0x0E) - Invalid */\r\n SO: 0x0e,\r\n /** Unit Separator (0x1F) - Invalid */\r\n US: 0x1f,\r\n /** Delete (0x7F) - Invalid */\r\n DEL: 0x7f,\r\n} as const;\r\n"]}
1
+ {"version":3,"file":"xmlSanitization.js","sourceRoot":"","sources":["../../src/utils/xmlSanitization.ts"],"names":[],"mappings":";;;AAuDA,sDAoBC;AAoBD,kDAqBC;AAkBD,gDAIC;AAtHD,qCAA2C;AAO3C,MAAM,sBAAsB,GAAG,mCAAmC,CAAC;AA4BnE,SAAgB,qBAAqB,CAAC,IAAY,EAAE,UAAU,GAAG,IAAI;IAEnE,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;IAErC,IAAI,UAAU,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAEpD,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;QAErC,MAAM,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,YAAY;aAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;aAChE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,IAAA,wBAAe,GAAE,CAAC,IAAI,CACpB,8DAA8D,QAAQ,EAAE,CACzE,CAAC;IACJ,CAAC;IAGD,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAoBD,SAAgB,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAGhC,IACE,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;YAC9B,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;YAC9B,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;YAC9B,IAAI,KAAK,IAAI,EACb,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAkBD,SAAgB,kBAAkB,CAAC,IAAY;IAE7C,sBAAsB,CAAC,SAAS,GAAG,CAAC,CAAC;IACrC,OAAO,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC;AAKY,QAAA,iBAAiB,GAAG;IAE/B,IAAI,EAAE,IAAI;IAEV,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,GAAG,EAAE,IAAI;IAET,EAAE,EAAE,IAAI;IAER,GAAG,EAAE,IAAI;IAET,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,EAAE,EAAE,IAAI;IAER,GAAG,EAAE,IAAI;CACD,CAAC","sourcesContent":["/**\n * XML Sanitization Utilities\n *\n * Provides functions for validating and sanitizing text content per XML 1.0 specification.\n * Per XML 1.0, certain control characters are invalid and must be removed before\n * including text in XML documents.\n *\n * Valid characters in XML 1.0:\n * - 0x09 (tab), 0x0A (newline), 0x0D (carriage return)\n * - 0x20-0xD7FF, 0xE000-0xFFFD, 0x10000-0x10FFFF\n *\n * Invalid characters (control characters that must be removed):\n * - 0x00-0x08 (NULL through BACKSPACE)\n * - 0x0B-0x0C (VERTICAL TAB and FORM FEED)\n * - 0x0E-0x1F (SHIFT OUT through UNIT SEPARATOR)\n * - 0x7F (DELETE)\n *\n * @module xmlSanitization\n */\n\nimport { getGlobalLogger } from './logger';\n\n/**\n * Regular expression matching invalid XML 1.0 control characters.\n * Matches: 0x00-0x08, 0x0B-0x0C, 0x0E-0x1F, 0x7F\n * Does NOT match valid chars: 0x09 (tab), 0x0A (newline), 0x0D (CR)\n */\nconst INVALID_XML_CHAR_REGEX = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g;\n\n/**\n * Removes invalid XML 1.0 control characters from text.\n *\n * Per XML 1.0 spec, characters 0x00-0x08, 0x0B-0x0C, 0x0E-0x1F, 0x7F are invalid\n * and cannot appear in XML documents. This function removes them.\n *\n * Valid control characters are preserved:\n * - Tab (0x09)\n * - Line Feed / Newline (0x0A)\n * - Carriage Return (0x0D)\n *\n * @param text - Input text to sanitize\n * @param logWarning - If true, logs a warning when invalid chars are found (default: true)\n * @returns Sanitized text with invalid control characters removed\n *\n * @example\n * ```typescript\n * // Remove NULL byte from text\n * const clean = removeInvalidXmlChars(\"Hello\\x00World\");\n * // Returns: \"HelloWorld\"\n *\n * // Tab and newline are preserved\n * const preserved = removeInvalidXmlChars(\"Hello\\tWorld\\n\");\n * // Returns: \"Hello\\tWorld\\n\"\n * ```\n */\nexport function removeInvalidXmlChars(text: string, logWarning = true): string {\n // Reset regex lastIndex for global regex\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\n\n if (logWarning && INVALID_XML_CHAR_REGEX.test(text)) {\n // Reset regex lastIndex after test\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\n\n const invalidChars = findInvalidXmlChars(text);\n const hexCodes = invalidChars\n .map((c) => `0x${c.toString(16).toUpperCase().padStart(2, '0')}`)\n .join(', ');\n getGlobalLogger().warn(\n `[XMLSanitization] Removing invalid XML control characters: ${hexCodes}`\n );\n }\n\n // Reset regex lastIndex before replace\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\n return text.replace(INVALID_XML_CHAR_REGEX, '');\n}\n\n/**\n * Finds all invalid XML 1.0 control characters in text.\n *\n * Returns an array of unique character codes that are invalid per XML 1.0 spec.\n * This is useful for diagnostics and error reporting.\n *\n * @param text - Text to scan for invalid characters\n * @returns Array of unique invalid character codes found, or empty array if text is valid\n *\n * @example\n * ```typescript\n * const invalid = findInvalidXmlChars(\"Hello\\x00\\x08World\");\n * // Returns: [0, 8] - NULL and BACKSPACE codes\n *\n * const valid = findInvalidXmlChars(\"Hello\\tWorld\");\n * // Returns: [] - tab is valid\n * ```\n */\nexport function findInvalidXmlChars(text: string): number[] {\n const invalid: number[] = [];\n\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n\n // Check if character is in invalid ranges\n if (\n (code >= 0x00 && code <= 0x08) || // NULL through BACKSPACE\n (code >= 0x0b && code <= 0x0c) || // VERTICAL TAB and FORM FEED\n (code >= 0x0e && code <= 0x1f) || // SHIFT OUT through UNIT SEPARATOR\n code === 0x7f // DELETE\n ) {\n // Only add unique codes\n if (!invalid.includes(code)) {\n invalid.push(code);\n }\n }\n }\n\n return invalid;\n}\n\n/**\n * Checks if text contains any invalid XML 1.0 control characters.\n *\n * This is a fast check that returns true/false without identifying specific characters.\n * Use `findInvalidXmlChars()` if you need to know which characters are invalid.\n *\n * @param text - Text to check\n * @returns true if text contains invalid characters, false otherwise\n *\n * @example\n * ```typescript\n * hasInvalidXmlChars(\"Hello\\x00World\"); // true - NULL byte\n * hasInvalidXmlChars(\"Hello\\tWorld\"); // false - tab is valid\n * hasInvalidXmlChars(\"Normal text\"); // false\n * ```\n */\nexport function hasInvalidXmlChars(text: string): boolean {\n // Reset regex lastIndex for global regex\n INVALID_XML_CHAR_REGEX.lastIndex = 0;\n return INVALID_XML_CHAR_REGEX.test(text);\n}\n\n/**\n * Character code constants for documentation and testing.\n */\nexport const XML_CONTROL_CHARS = {\n /** NULL (0x00) - Invalid */\n NULL: 0x00,\n /** Start of Heading (0x01) - Invalid */\n SOH: 0x01,\n /** Start of Text (0x02) - Invalid */\n STX: 0x02,\n /** End of Text (0x03) - Invalid */\n ETX: 0x03,\n /** End of Transmission (0x04) - Invalid */\n EOT: 0x04,\n /** Enquiry (0x05) - Invalid */\n ENQ: 0x05,\n /** Acknowledge (0x06) - Invalid */\n ACK: 0x06,\n /** Bell (0x07) - Invalid */\n BEL: 0x07,\n /** Backspace (0x08) - Invalid */\n BS: 0x08,\n /** Horizontal Tab (0x09) - VALID */\n TAB: 0x09,\n /** Line Feed / Newline (0x0A) - VALID */\n LF: 0x0a,\n /** Vertical Tab (0x0B) - Invalid */\n VT: 0x0b,\n /** Form Feed (0x0C) - Invalid */\n FF: 0x0c,\n /** Carriage Return (0x0D) - VALID */\n CR: 0x0d,\n /** Shift Out (0x0E) - Invalid */\n SO: 0x0e,\n /** Unit Separator (0x1F) - Invalid */\n US: 0x1f,\n /** Delete (0x7F) - Invalid */\n DEL: 0x7f,\n} as const;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"RevisionAutoFixer.d.ts","sourceRoot":"","sources":["../../src/validation/RevisionAutoFixer.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAEL,cAAc,EACd,aAAa,EACb,SAAS,EAEV,MAAM,mBAAmB,CAAC;AAmB3B,qBAAa,iBAAiB;IAQ5B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,aAAa;IA+FlE,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IA4C5E,MAAM,CAAC,iBAAiB,CACtB,SAAS,EAAE,QAAQ,EAAE,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,OAAO,GACf,SAAS,EAAE;IAuCd,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IAwC5E,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IAyC5E,MAAM,CAAC,sBAAsB,CAC3B,eAAe,EAAE;QAAE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,EACpD,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,CAAC,EAAE,OAAO,GACf,SAAS,EAAE;IA8Ed,MAAM,CAAC,iBAAiB,CACtB,eAAe,EAAE,GAAG,EACpB,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,CAAC,EAAE,OAAO,GACf,SAAS,EAAE;IA0Dd,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IAyDhF,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,GAAG,aAAa;IAUtF,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;CAuBnD"}
1
+ {"version":3,"file":"RevisionAutoFixer.d.ts","sourceRoot":"","sources":["../../src/validation/RevisionAutoFixer.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAEL,cAAc,EACd,aAAa,EACb,SAAS,EAEV,MAAM,mBAAmB,CAAC;AAmB3B,qBAAa,iBAAiB;IAQ5B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,aAAa;IA8FlE,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IA4C5E,MAAM,CAAC,iBAAiB,CACtB,SAAS,EAAE,QAAQ,EAAE,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,OAAO,GACf,SAAS,EAAE;IAuCd,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IAwC5E,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IAyC5E,MAAM,CAAC,sBAAsB,CAC3B,eAAe,EAAE;QAAE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,EACpD,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,CAAC,EAAE,OAAO,GACf,SAAS,EAAE;IA8Ed,MAAM,CAAC,iBAAiB,CACtB,eAAe,EAAE,GAAG,EACpB,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,CAAC,EAAE,OAAO,GACf,SAAS,EAAE;IA0Dd,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE;IAyDhF,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,GAAG,aAAa;IAUtF,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;CAuBnD"}