docxmlater 10.0.1 → 10.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/README.md +3 -2
  2. package/dist/constants/legacyCompatFlags.d.ts.map +1 -1
  3. package/dist/constants/legacyCompatFlags.js.map +1 -1
  4. package/dist/constants/limits.d.ts +0 -27
  5. package/dist/constants/limits.d.ts.map +1 -1
  6. package/dist/constants/limits.js +13 -13
  7. package/dist/constants/limits.js.map +1 -1
  8. package/dist/core/Document.d.ts +24 -19
  9. package/dist/core/Document.d.ts.map +1 -1
  10. package/dist/core/Document.js +272 -71
  11. package/dist/core/Document.js.map +1 -1
  12. package/dist/core/DocumentContent.d.ts.map +1 -1
  13. package/dist/core/DocumentContent.js.map +1 -1
  14. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  15. package/dist/core/DocumentGenerator.js +59 -24
  16. package/dist/core/DocumentGenerator.js.map +1 -1
  17. package/dist/core/DocumentIdManager.d.ts.map +1 -1
  18. package/dist/core/DocumentIdManager.js.map +1 -1
  19. package/dist/core/DocumentParser.d.ts +6 -6
  20. package/dist/core/DocumentParser.d.ts.map +1 -1
  21. package/dist/core/DocumentParser.js +60 -54
  22. package/dist/core/DocumentParser.js.map +1 -1
  23. package/dist/core/DocumentValidator.d.ts.map +1 -1
  24. package/dist/core/DocumentValidator.js.map +1 -1
  25. package/dist/core/Relationship.d.ts.map +1 -1
  26. package/dist/core/Relationship.js +1 -1
  27. package/dist/core/Relationship.js.map +1 -1
  28. package/dist/core/RelationshipManager.js +3 -3
  29. package/dist/core/RelationshipManager.js.map +1 -1
  30. package/dist/elements/AlternateContent.js.map +1 -1
  31. package/dist/elements/Bookmark.d.ts.map +1 -1
  32. package/dist/elements/Bookmark.js.map +1 -1
  33. package/dist/elements/BookmarkManager.d.ts.map +1 -1
  34. package/dist/elements/BookmarkManager.js.map +1 -1
  35. package/dist/elements/Comment.js +1 -1
  36. package/dist/elements/Comment.js.map +1 -1
  37. package/dist/elements/CommentManager.d.ts.map +1 -1
  38. package/dist/elements/CommentManager.js +8 -2
  39. package/dist/elements/CommentManager.js.map +1 -1
  40. package/dist/elements/CommonTypes.d.ts.map +1 -1
  41. package/dist/elements/CommonTypes.js +1 -2
  42. package/dist/elements/CommonTypes.js.map +1 -1
  43. package/dist/elements/CustomXml.js.map +1 -1
  44. package/dist/elements/Endnote.d.ts.map +1 -1
  45. package/dist/elements/Endnote.js.map +1 -1
  46. package/dist/elements/EndnoteManager.d.ts.map +1 -1
  47. package/dist/elements/EndnoteManager.js.map +1 -1
  48. package/dist/elements/Field.d.ts.map +1 -1
  49. package/dist/elements/Field.js +31 -28
  50. package/dist/elements/Field.js.map +1 -1
  51. package/dist/elements/FieldHelpers.d.ts.map +1 -1
  52. package/dist/elements/FieldHelpers.js +6 -6
  53. package/dist/elements/FieldHelpers.js.map +1 -1
  54. package/dist/elements/FontManager.d.ts.map +1 -1
  55. package/dist/elements/FontManager.js.map +1 -1
  56. package/dist/elements/Footer.js.map +1 -1
  57. package/dist/elements/Footnote.d.ts.map +1 -1
  58. package/dist/elements/Footnote.js.map +1 -1
  59. package/dist/elements/FootnoteManager.d.ts.map +1 -1
  60. package/dist/elements/FootnoteManager.js.map +1 -1
  61. package/dist/elements/Header.js.map +1 -1
  62. package/dist/elements/HeaderFooterManager.js.map +1 -1
  63. package/dist/elements/Hyperlink.d.ts.map +1 -1
  64. package/dist/elements/Hyperlink.js +5 -5
  65. package/dist/elements/Hyperlink.js.map +1 -1
  66. package/dist/elements/Image.d.ts +2 -2
  67. package/dist/elements/Image.d.ts.map +1 -1
  68. package/dist/elements/Image.js +21 -5
  69. package/dist/elements/Image.js.map +1 -1
  70. package/dist/elements/ImageManager.d.ts.map +1 -1
  71. package/dist/elements/ImageManager.js +2 -2
  72. package/dist/elements/ImageManager.js.map +1 -1
  73. package/dist/elements/ImageRun.js.map +1 -1
  74. package/dist/elements/MathElement.js.map +1 -1
  75. package/dist/elements/Paragraph.d.ts.map +1 -1
  76. package/dist/elements/Paragraph.js +128 -117
  77. package/dist/elements/Paragraph.js.map +1 -1
  78. package/dist/elements/PreservedElement.js.map +1 -1
  79. package/dist/elements/PropertyChangeTypes.js.map +1 -1
  80. package/dist/elements/RangeMarker.js.map +1 -1
  81. package/dist/elements/Revision.d.ts +1 -0
  82. package/dist/elements/Revision.d.ts.map +1 -1
  83. package/dist/elements/Revision.js +44 -5
  84. package/dist/elements/Revision.js.map +1 -1
  85. package/dist/elements/RevisionContent.js.map +1 -1
  86. package/dist/elements/RevisionManager.d.ts.map +1 -1
  87. package/dist/elements/RevisionManager.js.map +1 -1
  88. package/dist/elements/Run.d.ts.map +1 -1
  89. package/dist/elements/Run.js +1 -3
  90. package/dist/elements/Run.js.map +1 -1
  91. package/dist/elements/Section.d.ts.map +1 -1
  92. package/dist/elements/Section.js +127 -118
  93. package/dist/elements/Section.js.map +1 -1
  94. package/dist/elements/Shape.d.ts.map +1 -1
  95. package/dist/elements/Shape.js +21 -0
  96. package/dist/elements/Shape.js.map +1 -1
  97. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  98. package/dist/elements/StructuredDocumentTag.js +20 -8
  99. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  100. package/dist/elements/Table.d.ts +2 -2
  101. package/dist/elements/Table.d.ts.map +1 -1
  102. package/dist/elements/Table.js +29 -35
  103. package/dist/elements/Table.js.map +1 -1
  104. package/dist/elements/TableCell.d.ts +2 -2
  105. package/dist/elements/TableCell.d.ts.map +1 -1
  106. package/dist/elements/TableCell.js +63 -67
  107. package/dist/elements/TableCell.js.map +1 -1
  108. package/dist/elements/TableGridChange.js.map +1 -1
  109. package/dist/elements/TableOfContents.d.ts +6 -6
  110. package/dist/elements/TableOfContents.d.ts.map +1 -1
  111. package/dist/elements/TableOfContents.js.map +1 -1
  112. package/dist/elements/TableOfContentsElement.js.map +1 -1
  113. package/dist/elements/TableRow.d.ts.map +1 -1
  114. package/dist/elements/TableRow.js +65 -47
  115. package/dist/elements/TableRow.js.map +1 -1
  116. package/dist/elements/TextBox.d.ts.map +1 -1
  117. package/dist/elements/TextBox.js +1 -1
  118. package/dist/elements/TextBox.js.map +1 -1
  119. package/dist/formatting/AbstractNumbering.d.ts +1 -1
  120. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  121. package/dist/formatting/AbstractNumbering.js +11 -11
  122. package/dist/formatting/AbstractNumbering.js.map +1 -1
  123. package/dist/formatting/NumberingInstance.d.ts.map +1 -1
  124. package/dist/formatting/NumberingInstance.js +4 -4
  125. package/dist/formatting/NumberingInstance.js.map +1 -1
  126. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  127. package/dist/formatting/NumberingLevel.js +26 -26
  128. package/dist/formatting/NumberingLevel.js.map +1 -1
  129. package/dist/formatting/NumberingManager.d.ts +1 -1
  130. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  131. package/dist/formatting/NumberingManager.js.map +1 -1
  132. package/dist/formatting/Style.d.ts.map +1 -1
  133. package/dist/formatting/Style.js +87 -95
  134. package/dist/formatting/Style.js.map +1 -1
  135. package/dist/formatting/StylesManager.d.ts +3 -3
  136. package/dist/formatting/StylesManager.d.ts.map +1 -1
  137. package/dist/formatting/StylesManager.js.map +1 -1
  138. package/dist/helpers/CleanupHelper.d.ts.map +1 -1
  139. package/dist/helpers/CleanupHelper.js +1 -7
  140. package/dist/helpers/CleanupHelper.js.map +1 -1
  141. package/dist/images/ImageOptimizer.js.map +1 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/managers/DrawingManager.d.ts.map +1 -1
  144. package/dist/managers/DrawingManager.js.map +1 -1
  145. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  146. package/dist/tracking/TrackingContext.js.map +1 -1
  147. package/dist/types/compatibility-types.js.map +1 -1
  148. package/dist/types/formatting.js.map +1 -1
  149. package/dist/types/list-types.d.ts +4 -4
  150. package/dist/types/list-types.d.ts.map +1 -1
  151. package/dist/types/list-types.js.map +1 -1
  152. package/dist/types/settings-types.js.map +1 -1
  153. package/dist/types/styleConfig.js.map +1 -1
  154. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  155. package/dist/utils/ChangelogGenerator.js.map +1 -1
  156. package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
  157. package/dist/utils/CompatibilityUpgrader.js +7 -7
  158. package/dist/utils/CompatibilityUpgrader.js.map +1 -1
  159. package/dist/utils/InMemoryRevisionAcceptor.js +1 -1
  160. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  161. package/dist/utils/MoveOperationHelper.js.map +1 -1
  162. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  163. package/dist/utils/RevisionWalker.js.map +1 -1
  164. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  165. package/dist/utils/ShadingResolver.js +1 -1
  166. package/dist/utils/ShadingResolver.js.map +1 -1
  167. package/dist/utils/acceptRevisions.d.ts +0 -28
  168. package/dist/utils/acceptRevisions.d.ts.map +1 -1
  169. package/dist/utils/acceptRevisions.js +5 -7
  170. package/dist/utils/acceptRevisions.js.map +1 -1
  171. package/dist/utils/cnfStyleDecoder.js +1 -1
  172. package/dist/utils/cnfStyleDecoder.js.map +1 -1
  173. package/dist/utils/corruptionDetection.js.map +1 -1
  174. package/dist/utils/dateFormatting.js.map +1 -1
  175. package/dist/utils/deepClone.d.ts +0 -1
  176. package/dist/utils/deepClone.d.ts.map +1 -1
  177. package/dist/utils/deepClone.js +0 -7
  178. package/dist/utils/deepClone.js.map +1 -1
  179. package/dist/utils/diagnostics.d.ts +2 -2
  180. package/dist/utils/diagnostics.d.ts.map +1 -1
  181. package/dist/utils/diagnostics.js.map +1 -1
  182. package/dist/utils/errorHandling.js.map +1 -1
  183. package/dist/utils/formatting.js.map +1 -1
  184. package/dist/utils/list-detection.d.ts +2 -2
  185. package/dist/utils/list-detection.d.ts.map +1 -1
  186. package/dist/utils/list-detection.js +3 -3
  187. package/dist/utils/list-detection.js.map +1 -1
  188. package/dist/utils/logger.d.ts +2 -4
  189. package/dist/utils/logger.d.ts.map +1 -1
  190. package/dist/utils/logger.js +0 -2
  191. package/dist/utils/logger.js.map +1 -1
  192. package/dist/utils/parsingHelpers.js.map +1 -1
  193. package/dist/utils/stripTrackedChanges.d.ts +0 -19
  194. package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
  195. package/dist/utils/stripTrackedChanges.js +0 -2
  196. package/dist/utils/stripTrackedChanges.js.map +1 -1
  197. package/dist/utils/textDiff.js.map +1 -1
  198. package/dist/utils/units.js.map +1 -1
  199. package/dist/utils/validation.d.ts.map +1 -1
  200. package/dist/utils/validation.js.map +1 -1
  201. package/dist/utils/xmlSanitization.js.map +1 -1
  202. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  203. package/dist/validation/RevisionValidator.js.map +1 -1
  204. package/dist/validation/ValidationRules.js.map +1 -1
  205. package/dist/validation/index.js.map +1 -1
  206. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  207. package/dist/xml/XMLBuilder.js +10 -0
  208. package/dist/xml/XMLBuilder.js.map +1 -1
  209. package/dist/xml/XMLParser.d.ts.map +1 -1
  210. package/dist/xml/XMLParser.js +4 -5
  211. package/dist/xml/XMLParser.js.map +1 -1
  212. package/dist/zip/ZipHandler.js.map +1 -1
  213. package/dist/zip/ZipReader.js.map +1 -1
  214. package/dist/zip/ZipWriter.js.map +1 -1
  215. package/dist/zip/errors.js.map +1 -1
  216. package/dist/zip/types.js.map +1 -1
  217. package/package.json +34 -4
  218. package/src/__tests__/helper-methods.test.ts +512 -0
  219. package/src/constants/legacyCompatFlags.ts +138 -0
  220. package/src/constants/limits.ts +50 -0
  221. package/src/core/CLAUDE.md +109 -0
  222. package/src/core/Document.ts +15569 -0
  223. package/src/core/DocumentContent.ts +467 -0
  224. package/src/core/DocumentGenerator.ts +1104 -0
  225. package/src/core/DocumentIdManager.ts +158 -0
  226. package/src/core/DocumentParser.ts +10107 -0
  227. package/src/core/DocumentValidator.ts +372 -0
  228. package/src/core/Relationship.ts +367 -0
  229. package/src/core/RelationshipManager.ts +428 -0
  230. package/src/elements/AlternateContent.ts +42 -0
  231. package/src/elements/Bookmark.ts +210 -0
  232. package/src/elements/BookmarkManager.ts +250 -0
  233. package/src/elements/CLAUDE.md +126 -0
  234. package/src/elements/Comment.ts +359 -0
  235. package/src/elements/CommentManager.ts +502 -0
  236. package/src/elements/CommonTypes.ts +549 -0
  237. package/src/elements/CustomXml.ts +36 -0
  238. package/src/elements/Endnote.ts +217 -0
  239. package/src/elements/EndnoteManager.ts +249 -0
  240. package/src/elements/Field.ts +1233 -0
  241. package/src/elements/FieldHelpers.ts +333 -0
  242. package/src/elements/FontManager.ts +339 -0
  243. package/src/elements/Footer.ts +269 -0
  244. package/src/elements/Footnote.ts +217 -0
  245. package/src/elements/FootnoteManager.ts +249 -0
  246. package/src/elements/Header.ts +269 -0
  247. package/src/elements/HeaderFooterManager.ts +219 -0
  248. package/src/elements/Hyperlink.ts +1146 -0
  249. package/src/elements/Image.ts +1756 -0
  250. package/src/elements/ImageManager.ts +432 -0
  251. package/src/elements/ImageRun.ts +59 -0
  252. package/src/elements/MathElement.ts +65 -0
  253. package/src/elements/Paragraph.ts +4227 -0
  254. package/src/elements/PreservedElement.ts +53 -0
  255. package/src/elements/PropertyChangeTypes.ts +442 -0
  256. package/src/elements/RangeMarker.ts +400 -0
  257. package/src/elements/Revision.ts +1217 -0
  258. package/src/elements/RevisionContent.ts +73 -0
  259. package/src/elements/RevisionManager.ts +1070 -0
  260. package/src/elements/Run.ts +3068 -0
  261. package/src/elements/Section.ts +1421 -0
  262. package/src/elements/Shape.ts +873 -0
  263. package/src/elements/StructuredDocumentTag.ts +978 -0
  264. package/src/elements/Table.ts +2524 -0
  265. package/src/elements/TableCell.ts +1586 -0
  266. package/src/elements/TableGridChange.ts +151 -0
  267. package/src/elements/TableOfContents.ts +691 -0
  268. package/src/elements/TableOfContentsElement.ts +89 -0
  269. package/src/elements/TableRow.ts +906 -0
  270. package/src/elements/TextBox.ts +768 -0
  271. package/src/formatting/AbstractNumbering.ts +548 -0
  272. package/src/formatting/CLAUDE.md +74 -0
  273. package/src/formatting/NumberingInstance.ts +212 -0
  274. package/src/formatting/NumberingLevel.ts +1006 -0
  275. package/src/formatting/NumberingManager.ts +827 -0
  276. package/src/formatting/Style.ts +1833 -0
  277. package/src/formatting/StylesManager.ts +1005 -0
  278. package/src/helpers/CleanupHelper.ts +524 -0
  279. package/src/images/ImageOptimizer.ts +274 -0
  280. package/src/index.ts +554 -0
  281. package/src/managers/CLAUDE.md +47 -0
  282. package/src/managers/DrawingManager.ts +319 -0
  283. package/src/tracking/DocumentTrackingContext.ts +643 -0
  284. package/src/tracking/TrackingContext.ts +173 -0
  285. package/src/types/compatibility-types.ts +49 -0
  286. package/src/types/formatting.ts +210 -0
  287. package/src/types/list-types.ts +152 -0
  288. package/src/types/settings-types.ts +59 -0
  289. package/src/types/styleConfig.ts +189 -0
  290. package/src/utils/CLAUDE.md +153 -0
  291. package/src/utils/ChangelogGenerator.ts +1581 -0
  292. package/src/utils/CompatibilityUpgrader.ts +237 -0
  293. package/src/utils/InMemoryRevisionAcceptor.ts +668 -0
  294. package/src/utils/MoveOperationHelper.ts +238 -0
  295. package/src/utils/RevisionAwareProcessor.ts +526 -0
  296. package/src/utils/RevisionWalker.ts +457 -0
  297. package/src/utils/SelectiveRevisionAcceptor.ts +613 -0
  298. package/src/utils/ShadingResolver.ts +107 -0
  299. package/src/utils/acceptRevisions.ts +714 -0
  300. package/src/utils/cnfStyleDecoder.ts +217 -0
  301. package/src/utils/corruptionDetection.ts +345 -0
  302. package/src/utils/dateFormatting.ts +20 -0
  303. package/src/utils/deepClone.ts +78 -0
  304. package/src/utils/diagnostics.ts +129 -0
  305. package/src/utils/errorHandling.ts +80 -0
  306. package/src/utils/formatting.ts +213 -0
  307. package/src/utils/list-detection.ts +274 -0
  308. package/src/utils/logger.ts +404 -0
  309. package/src/utils/parsingHelpers.ts +190 -0
  310. package/src/utils/stripTrackedChanges.ts +353 -0
  311. package/src/utils/textDiff.ts +100 -0
  312. package/src/utils/units.ts +421 -0
  313. package/src/utils/validation.ts +542 -0
  314. package/src/utils/xmlSanitization.ts +182 -0
  315. package/src/validation/RevisionAutoFixer.ts +542 -0
  316. package/src/validation/RevisionValidator.ts +460 -0
  317. package/src/validation/ValidationRules.ts +338 -0
  318. package/src/validation/index.ts +30 -0
  319. package/src/xml/CLAUDE.md +65 -0
  320. package/src/xml/XMLBuilder.ts +871 -0
  321. package/src/xml/XMLParser.ts +919 -0
  322. package/src/zip/CLAUDE.md +55 -0
  323. package/src/zip/ZipHandler.ts +637 -0
  324. package/src/zip/ZipReader.ts +299 -0
  325. package/src/zip/ZipWriter.ts +390 -0
  326. package/src/zip/errors.ts +69 -0
  327. package/src/zip/types.ts +116 -0
  328. package/dist/core/ListNormalizer.d.ts +0 -23
  329. package/dist/core/ListNormalizer.d.ts.map +0 -1
  330. package/dist/core/ListNormalizer.js +0 -624
  331. package/dist/core/ListNormalizer.js.map +0 -1
  332. package/dist/images/index.d.ts +0 -2
  333. package/dist/images/index.d.ts.map +0 -1
  334. package/dist/images/index.js +0 -8
  335. package/dist/images/index.js.map +0 -1
  336. package/dist/ms-doc/cfb/CFBReader.d.ts +0 -35
  337. package/dist/ms-doc/cfb/CFBReader.d.ts.map +0 -1
  338. package/dist/ms-doc/cfb/CFBReader.js +0 -360
  339. package/dist/ms-doc/cfb/CFBReader.js.map +0 -1
  340. package/dist/ms-doc/converter/DocToDocxConverter.d.ts +0 -55
  341. package/dist/ms-doc/converter/DocToDocxConverter.d.ts.map +0 -1
  342. package/dist/ms-doc/converter/DocToDocxConverter.js +0 -324
  343. package/dist/ms-doc/converter/DocToDocxConverter.js.map +0 -1
  344. package/dist/ms-doc/fib/FIB.d.ts +0 -18
  345. package/dist/ms-doc/fib/FIB.d.ts.map +0 -1
  346. package/dist/ms-doc/fib/FIB.js +0 -342
  347. package/dist/ms-doc/fib/FIB.js.map +0 -1
  348. package/dist/ms-doc/fields/FieldParser.d.ts +0 -31
  349. package/dist/ms-doc/fields/FieldParser.d.ts.map +0 -1
  350. package/dist/ms-doc/fields/FieldParser.js +0 -266
  351. package/dist/ms-doc/fields/FieldParser.js.map +0 -1
  352. package/dist/ms-doc/images/PictureExtractor.d.ts +0 -22
  353. package/dist/ms-doc/images/PictureExtractor.d.ts.map +0 -1
  354. package/dist/ms-doc/images/PictureExtractor.js +0 -233
  355. package/dist/ms-doc/images/PictureExtractor.js.map +0 -1
  356. package/dist/ms-doc/index.d.ts +0 -20
  357. package/dist/ms-doc/index.d.ts.map +0 -1
  358. package/dist/ms-doc/index.js +0 -59
  359. package/dist/ms-doc/index.js.map +0 -1
  360. package/dist/ms-doc/properties/SPRM.d.ts +0 -210
  361. package/dist/ms-doc/properties/SPRM.d.ts.map +0 -1
  362. package/dist/ms-doc/properties/SPRM.js +0 -633
  363. package/dist/ms-doc/properties/SPRM.js.map +0 -1
  364. package/dist/ms-doc/sections/SectionParser.d.ts +0 -25
  365. package/dist/ms-doc/sections/SectionParser.d.ts.map +0 -1
  366. package/dist/ms-doc/sections/SectionParser.js +0 -214
  367. package/dist/ms-doc/sections/SectionParser.js.map +0 -1
  368. package/dist/ms-doc/styles/StyleSheet.d.ts +0 -23
  369. package/dist/ms-doc/styles/StyleSheet.d.ts.map +0 -1
  370. package/dist/ms-doc/styles/StyleSheet.js +0 -268
  371. package/dist/ms-doc/styles/StyleSheet.js.map +0 -1
  372. package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts +0 -61
  373. package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts.map +0 -1
  374. package/dist/ms-doc/subdocuments/SubdocumentParser.js +0 -208
  375. package/dist/ms-doc/subdocuments/SubdocumentParser.js.map +0 -1
  376. package/dist/ms-doc/tables/TableParser.d.ts +0 -29
  377. package/dist/ms-doc/tables/TableParser.d.ts.map +0 -1
  378. package/dist/ms-doc/tables/TableParser.js +0 -176
  379. package/dist/ms-doc/tables/TableParser.js.map +0 -1
  380. package/dist/ms-doc/text/PieceTable.d.ts +0 -21
  381. package/dist/ms-doc/text/PieceTable.d.ts.map +0 -1
  382. package/dist/ms-doc/text/PieceTable.js +0 -171
  383. package/dist/ms-doc/text/PieceTable.js.map +0 -1
  384. package/dist/ms-doc/types/Constants.d.ts +0 -99
  385. package/dist/ms-doc/types/Constants.d.ts.map +0 -1
  386. package/dist/ms-doc/types/Constants.js +0 -102
  387. package/dist/ms-doc/types/Constants.js.map +0 -1
  388. package/dist/ms-doc/types/DocTypes.d.ts +0 -368
  389. package/dist/ms-doc/types/DocTypes.d.ts.map +0 -1
  390. package/dist/ms-doc/types/DocTypes.js +0 -3
  391. package/dist/ms-doc/types/DocTypes.js.map +0 -1
  392. package/dist/tracking/index.d.ts +0 -3
  393. package/dist/tracking/index.d.ts.map +0 -1
  394. package/dist/tracking/index.js +0 -6
  395. package/dist/tracking/index.js.map +0 -1
@@ -0,0 +1,55 @@
1
+ # ZIP Module
2
+
3
+ `src/zip/` — DOCX/ZIP archive handling (5 files). Dependency: JSZip.
4
+
5
+ ## Classes
6
+
7
+ ### ZipHandler (`ZipHandler.ts`)
8
+
9
+ High-level facade combining ZipReader/ZipWriter. Used by Document for all file I/O.
10
+
11
+ ```typescript
12
+ await zipHandler.loadFromFile(filepath) / loadFromBuffer(buffer)
13
+ await zipHandler.saveToFile(filepath) / toBuffer()
14
+ zipHandler.addFile(path, content) // string or Buffer
15
+ zipHandler.getFile(path) // returns string | undefined
16
+ zipHandler.hasFile(path) / getFileNames()
17
+ ```
18
+
19
+ ### ZipReader (`ZipReader.ts`)
20
+
21
+ Reads/extracts from DOCX/ZIP. UTF-8 text extraction, binary file extraction, size validation.
22
+
23
+ ### ZipWriter (`ZipWriter.ts`)
24
+
25
+ Creates DOCX/ZIP archives. UTF-8 string → Buffer conversion, compression control.
26
+
27
+ ## Types and Constants (`types.ts`)
28
+
29
+ `DOCX_PATHS` — Standard file paths (`CONTENT_TYPES`, `RELS`, `DOCUMENT`, `STYLES`, `NUMBERING`, `SETTINGS`, `FONT_TABLE`, `THEME`, `CORE_PROPS`, `APP_PROPS`, `FOOTNOTES`, `ENDNOTES`, etc.).
30
+
31
+ `REQUIRED_DOCX_FILES` — Files required for valid DOCX.
32
+
33
+ `SizeLimitOptions` — Warning (50MB) and max (150MB) size limits.
34
+
35
+ ## Error Types (`errors.ts`)
36
+
37
+ `DocxError` (base) → `DocxNotFoundError`, `InvalidDocxError`, `CorruptedArchiveError`, `MissingRequiredFileError`, `FileOperationError`.
38
+
39
+ ## UTF-8 Encoding
40
+
41
+ All text is UTF-8 per ECMA-376:
42
+ - `ZipWriter.addFile()` converts strings to UTF-8 Buffers
43
+ - `ZipReader` extracts text as UTF-8 strings
44
+ - Binary files (images) preserved as-is
45
+ - XML declarations include `encoding="UTF-8"`
46
+
47
+ Supports: ASCII, Latin diacritics, Greek, Cyrillic, Arabic, Hebrew, Devanagari, CJK, emoji, RTL.
48
+
49
+ ## Security
50
+
51
+ File paths validated against path traversal (`../`, absolute paths, URL-encoded sequences).
52
+
53
+ ## Testing
54
+
55
+ `tests/zip/ZipHandler.test.ts` — 62 tests including 11 UTF-8 encoding tests.
@@ -0,0 +1,637 @@
1
+ /**
2
+ * ZipHandler - Main facade for ZIP archive operations
3
+ * Provides a unified interface for reading and writing DOCX files
4
+ */
5
+
6
+ import { ZipReader } from './ZipReader';
7
+ import { ZipWriter } from './ZipWriter';
8
+ import {
9
+ ZipFile,
10
+ FileMap,
11
+ LoadOptions,
12
+ SaveOptions,
13
+ AddFileOptions,
14
+ SizeLimitOptions,
15
+ DEFAULT_SIZE_LIMITS,
16
+ } from './types';
17
+ import { getGlobalLogger, createScopedLogger, ILogger } from '../utils/logger';
18
+
19
+ // Create scoped logger for ZipHandler operations
20
+ function getLogger(): ILogger {
21
+ return createScopedLogger(getGlobalLogger(), 'ZipHandler');
22
+ }
23
+
24
+ /**
25
+ * Main class for handling ZIP archives (DOCX files)
26
+ * Combines reading and writing operations into a single interface
27
+ */
28
+ export class ZipHandler {
29
+ private reader: ZipReader;
30
+ private writer: ZipWriter;
31
+ private mode: 'read' | 'write' | 'modify' = 'write';
32
+
33
+ constructor() {
34
+ this.reader = new ZipReader();
35
+ this.writer = new ZipWriter();
36
+ }
37
+
38
+ // ==================== SIZE VALIDATION ====================
39
+
40
+ /**
41
+ * Validates document size against configured limits
42
+ * @param sizeMB - Size in megabytes
43
+ * @param limits - Size limit options (merged with defaults)
44
+ * @throws Error if size exceeds maximum
45
+ */
46
+ private validateDocumentSize(sizeMB: number, limits: Required<SizeLimitOptions>): void {
47
+ const logger = getLogger();
48
+ const { warningSizeMB, maxSizeMB } = limits;
49
+
50
+ // Check maximum size (if enabled)
51
+ if (maxSizeMB > 0 && sizeMB > maxSizeMB) {
52
+ logger.error('Document exceeds maximum size', { sizeMB: sizeMB.toFixed(1), maxSizeMB });
53
+ throw new Error(
54
+ `Document size (${sizeMB.toFixed(1)}MB) exceeds maximum supported size (${maxSizeMB}MB). ` +
55
+ `This would likely cause out-of-memory errors. Consider:\n` +
56
+ `- Compressing/optimizing images\n` +
57
+ `- Splitting into multiple documents\n` +
58
+ `- Processing on a machine with more memory\n` +
59
+ `- Increasing maxSizeMB via LoadOptions.sizeLimits (not recommended)`
60
+ );
61
+ }
62
+
63
+ // Warn on large files (if enabled)
64
+ if (warningSizeMB > 0 && sizeMB > warningSizeMB) {
65
+ logger.warn('Large document detected', { sizeMB: sizeMB.toFixed(1), warningSizeMB });
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Gets merged size limits from options and defaults
71
+ * @param options - Load options that may contain size limits
72
+ * @returns Merged size limits with all values defined
73
+ */
74
+ private getSizeLimits(options: LoadOptions): Required<SizeLimitOptions> {
75
+ return {
76
+ ...DEFAULT_SIZE_LIMITS,
77
+ ...options.sizeLimits,
78
+ };
79
+ }
80
+
81
+ // ==================== LOADING ====================
82
+
83
+ /**
84
+ * Loads a DOCX file from the filesystem
85
+ * @param filePath - Path to the DOCX file
86
+ * @param options - Load options (including configurable size limits)
87
+ */
88
+ async load(filePath: string, options: LoadOptions = {}): Promise<void> {
89
+ const logger = getLogger();
90
+ logger.info('Loading DOCX file', { path: filePath });
91
+
92
+ // Check file size before loading
93
+ const { promises: fs } = await import('fs');
94
+ const stats = await fs.stat(filePath);
95
+ const sizeMB = stats.size / (1024 * 1024);
96
+
97
+ // Validate against configurable limits
98
+ const limits = this.getSizeLimits(options);
99
+ this.validateDocumentSize(sizeMB, limits);
100
+
101
+ await this.reader.loadFromFile(filePath, options);
102
+
103
+ // Copy all files from reader to writer for modification
104
+ const files = this.reader.getAllFiles();
105
+ this.writer.clear();
106
+ this.writer.addFiles(files);
107
+
108
+ this.mode = 'modify';
109
+ logger.info('DOCX file loaded', { fileCount: files.size, sizeMB: sizeMB.toFixed(2) });
110
+ }
111
+
112
+ /**
113
+ * Loads a DOCX file from a buffer
114
+ * @param buffer - Buffer containing the DOCX data
115
+ * @param options - Load options (including configurable size limits)
116
+ */
117
+ async loadFromBuffer(buffer: Buffer, options: LoadOptions = {}): Promise<void> {
118
+ const logger = getLogger();
119
+ logger.info('Loading DOCX from buffer', { bufferSize: buffer.length });
120
+
121
+ // Check buffer size before loading
122
+ const sizeMB = buffer.length / (1024 * 1024);
123
+
124
+ // Validate against configurable limits
125
+ const limits = this.getSizeLimits(options);
126
+ this.validateDocumentSize(sizeMB, limits);
127
+
128
+ await this.reader.loadFromBuffer(buffer, options);
129
+
130
+ // Copy all files from reader to writer for modification
131
+ const files = this.reader.getAllFiles();
132
+ this.writer.clear();
133
+ this.writer.addFiles(files);
134
+
135
+ this.mode = 'modify';
136
+ logger.info('DOCX buffer loaded', { fileCount: files.size, sizeMB: sizeMB.toFixed(2) });
137
+ }
138
+
139
+ // ==================== FILE OPERATIONS ====================
140
+
141
+ /**
142
+ * Adds a file to the archive
143
+ * @param filePath - Path where the file will be stored in the archive
144
+ * @param content - File content (string or Buffer)
145
+ * @param options - Options for adding the file
146
+ */
147
+ addFile(
148
+ filePath: string,
149
+ content: string | Buffer,
150
+ options: AddFileOptions = {}
151
+ ): void {
152
+ this.writer.addFile(filePath, content, options);
153
+ }
154
+
155
+ /**
156
+ * Adds multiple files to the archive
157
+ * @param files - Map of file paths to contents
158
+ * @param options - Options for adding files
159
+ */
160
+ addFiles(files: FileMap, options: AddFileOptions = {}): void {
161
+ this.writer.addFiles(files, options);
162
+ }
163
+
164
+ /**
165
+ * Updates an existing file in the archive
166
+ * @param filePath - Path to the file to update
167
+ * @param content - New content
168
+ * @param options - Options for updating the file
169
+ * @returns True if the file was updated, false if it didn't exist
170
+ */
171
+ updateFile(
172
+ filePath: string,
173
+ content: string | Buffer,
174
+ options: AddFileOptions = {}
175
+ ): boolean {
176
+ if (!this.hasFile(filePath)) {
177
+ return false;
178
+ }
179
+ this.addFile(filePath, content, options);
180
+ return true;
181
+ }
182
+
183
+ /**
184
+ * Removes a file from the archive
185
+ * @param filePath - Path to the file to remove
186
+ * @returns True if the file was removed, false if it didn't exist
187
+ */
188
+ removeFile(filePath: string): boolean {
189
+ return this.writer.removeFile(filePath);
190
+ }
191
+
192
+ /**
193
+ * Gets a specific file from the archive
194
+ * @param filePath - Path to the file within the archive
195
+ * @returns The file data, or undefined if not found
196
+ */
197
+ getFile(filePath: string): ZipFile | undefined {
198
+ return this.writer.getFile(filePath);
199
+ }
200
+
201
+ /**
202
+ * Gets the content of a specific file as a string
203
+ * @param filePath - Path to the file within the archive
204
+ * @returns The file content as a UTF-8 string, or undefined if not found
205
+ * @throws Error if attempting to convert a binary file to string (Issue #12 fix)
206
+ *
207
+ * **Encoding Note:**
208
+ * - Returns UTF-8 decoded string content for text files
209
+ * - All text content in DOCX files must be UTF-8 per OpenXML specification
210
+ * - For binary files (images, fonts), throws an error to prevent garbage output
211
+ * - Use getFileAsBuffer() for binary files instead
212
+ */
213
+ getFileAsString(filePath: string): string | undefined {
214
+ const file = this.getFile(filePath);
215
+ if (!file) {
216
+ return undefined;
217
+ }
218
+
219
+ // Issue #12 fix: Prevent converting binary files to UTF-8 strings
220
+ // This produces garbage output for images, fonts, etc.
221
+ if (file.isBinary) {
222
+ throw new Error(
223
+ `Cannot convert binary file "${filePath}" to string. ` +
224
+ `Binary files (images, fonts, etc.) cannot be safely converted to UTF-8 strings. ` +
225
+ `Use getFileAsBuffer() instead to access the raw bytes.`
226
+ );
227
+ }
228
+
229
+ // After ZipWriter fix (Issue #4), check actual content type instead of flag
230
+ // Content from ZipWriter is always Buffer, content from ZipReader may be string
231
+ if (Buffer.isBuffer(file.content)) {
232
+ // Convert buffer to UTF-8 string
233
+ return file.content.toString('utf8');
234
+ }
235
+
236
+ return file.content;
237
+ }
238
+
239
+ /**
240
+ * Gets the content of a specific file as a buffer
241
+ * @param filePath - Path to the file within the archive
242
+ * @returns The file content as a Buffer, or undefined if not found
243
+ *
244
+ * **Encoding Note:**
245
+ * - Returns Buffer with UTF-8 encoded content for text files
246
+ * - For binary files, returns raw bytes unchanged
247
+ * - All text content is guaranteed to be UTF-8 encoded
248
+ */
249
+ getFileAsBuffer(filePath: string): Buffer | undefined {
250
+ const file = this.getFile(filePath);
251
+ if (!file) {
252
+ return undefined;
253
+ }
254
+
255
+ // After ZipWriter fix (Issue #4), check actual content type instead of flag
256
+ // Content from ZipWriter is always Buffer, content from ZipReader may be string
257
+ if (Buffer.isBuffer(file.content)) {
258
+ return file.content;
259
+ }
260
+
261
+ // Encode string content as UTF-8 Buffer (for content from ZipReader)
262
+ return Buffer.from(file.content, 'utf8');
263
+ }
264
+
265
+ /**
266
+ * Gets all files from the archive
267
+ * @returns Map of file paths to file data
268
+ */
269
+ getAllFiles(): FileMap {
270
+ return this.writer.getAllFiles();
271
+ }
272
+
273
+ /**
274
+ * Gets a list of all file paths in the archive
275
+ * @returns Array of file paths
276
+ */
277
+ getFilePaths(): string[] {
278
+ return this.writer.getFilePaths();
279
+ }
280
+
281
+ /**
282
+ * Checks if a file exists in the archive
283
+ * @param filePath - Path to check
284
+ * @returns True if the file exists
285
+ */
286
+ hasFile(filePath: string): boolean {
287
+ return this.writer.hasFile(filePath);
288
+ }
289
+
290
+ /**
291
+ * Gets the number of files in the archive
292
+ * @returns Number of files
293
+ */
294
+ getFileCount(): number {
295
+ return this.writer.getFileCount();
296
+ }
297
+
298
+ // ==================== HELPER METHODS ====================
299
+
300
+ /**
301
+ * Renames a file in the archive
302
+ * @param oldPath - Current path of the file
303
+ * @param newPath - New path for the file
304
+ * @returns True if the file was renamed, false if it didn't exist
305
+ */
306
+ renameFile(oldPath: string, newPath: string): boolean {
307
+ const file = this.getFile(oldPath);
308
+ if (!file) {
309
+ return false;
310
+ }
311
+ this.addFile(newPath, file.content, {
312
+ binary: file.isBinary,
313
+ date: file.date,
314
+ });
315
+ this.removeFile(oldPath);
316
+ return true;
317
+ }
318
+
319
+ /**
320
+ * Copies a file within the archive
321
+ * @param srcPath - Source file path
322
+ * @param destPath - Destination file path
323
+ * @returns True if the file was copied, false if source didn't exist
324
+ */
325
+ copyFile(srcPath: string, destPath: string): boolean {
326
+ const file = this.getFile(srcPath);
327
+ if (!file) {
328
+ return false;
329
+ }
330
+ this.addFile(destPath, file.content, {
331
+ binary: file.isBinary,
332
+ date: file.date,
333
+ });
334
+ return true;
335
+ }
336
+
337
+ /**
338
+ * Moves a file within the archive (copy and delete)
339
+ * @param srcPath - Source file path
340
+ * @param destPath - Destination file path
341
+ * @returns True if the file was moved, false if source didn't exist
342
+ */
343
+ moveFile(srcPath: string, destPath: string): boolean {
344
+ if (!this.copyFile(srcPath, destPath)) {
345
+ return false;
346
+ }
347
+ this.removeFile(srcPath);
348
+ return true;
349
+ }
350
+
351
+ /**
352
+ * Checks if a file exists, throws if it doesn't
353
+ * @param filePath - Path to check
354
+ * @throws {Error} If file doesn't exist
355
+ */
356
+ existsOrThrow(filePath: string): void {
357
+ if (!this.hasFile(filePath)) {
358
+ throw new Error(`File not found in archive: ${filePath}`);
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Removes multiple files from the archive
364
+ * @param filePaths - Array of file paths to remove
365
+ * @returns Number of files successfully removed
366
+ */
367
+ removeFiles(filePaths: string[]): number {
368
+ let count = 0;
369
+ for (const filePath of filePaths) {
370
+ if (this.removeFile(filePath)) {
371
+ count++;
372
+ }
373
+ }
374
+ return count;
375
+ }
376
+
377
+ /**
378
+ * Gets all files with a specific extension
379
+ * @param extension - File extension (with or without leading dot)
380
+ * @returns Array of files with the specified extension
381
+ */
382
+ getFilesByExtension(extension: string): ZipFile[] {
383
+ const ext = extension.startsWith('.') ? extension : `.${extension}`;
384
+ const files: ZipFile[] = [];
385
+ for (const [path, file] of this.getAllFiles()) {
386
+ if (path.toLowerCase().endsWith(ext.toLowerCase())) {
387
+ files.push(file);
388
+ }
389
+ }
390
+ return files;
391
+ }
392
+
393
+ /**
394
+ * Gets the total uncompressed size of all files in the archive
395
+ * @returns Total size in bytes
396
+ */
397
+ getTotalSize(): number {
398
+ let totalSize = 0;
399
+ for (const file of this.getAllFiles().values()) {
400
+ totalSize += file.size;
401
+ }
402
+ return totalSize;
403
+ }
404
+
405
+ /**
406
+ * Gets comprehensive statistics about the archive
407
+ * @returns Statistics object
408
+ */
409
+ getStats(): {
410
+ fileCount: number;
411
+ totalSize: number;
412
+ textFileCount: number;
413
+ binaryFileCount: number;
414
+ avgFileSize: number;
415
+ } {
416
+ let textCount = 0;
417
+ let binaryCount = 0;
418
+ const totalSize = this.getTotalSize();
419
+ const fileCount = this.getFileCount();
420
+
421
+ for (const file of this.getAllFiles().values()) {
422
+ if (file.isBinary) {
423
+ binaryCount++;
424
+ } else {
425
+ textCount++;
426
+ }
427
+ }
428
+
429
+ return {
430
+ fileCount,
431
+ totalSize,
432
+ textFileCount: textCount,
433
+ binaryFileCount: binaryCount,
434
+ avgFileSize: fileCount > 0 ? Math.round(totalSize / fileCount) : 0,
435
+ };
436
+ }
437
+
438
+ /**
439
+ * Checks if the archive is empty
440
+ * @returns True if the archive has no files
441
+ */
442
+ isEmpty(): boolean {
443
+ return this.getFileCount() === 0;
444
+ }
445
+
446
+ /**
447
+ * Gets all text (non-binary) files from the archive
448
+ * @returns Array of text files
449
+ */
450
+ getTextFiles(): ZipFile[] {
451
+ const files: ZipFile[] = [];
452
+ for (const file of this.getAllFiles().values()) {
453
+ if (!file.isBinary) {
454
+ files.push(file);
455
+ }
456
+ }
457
+ return files;
458
+ }
459
+
460
+ /**
461
+ * Gets all binary files from the archive
462
+ * @returns Array of binary files
463
+ */
464
+ getBinaryFiles(): ZipFile[] {
465
+ const files: ZipFile[] = [];
466
+ for (const file of this.getAllFiles().values()) {
467
+ if (file.isBinary) {
468
+ files.push(file);
469
+ }
470
+ }
471
+ return files;
472
+ }
473
+
474
+ /**
475
+ * Gets all media files from the word/media/ directory
476
+ * @returns Array of media files
477
+ */
478
+ getMediaFiles(): ZipFile[] {
479
+ const files: ZipFile[] = [];
480
+ for (const [path, file] of this.getAllFiles()) {
481
+ if (path.startsWith('word/media/')) {
482
+ files.push(file);
483
+ }
484
+ }
485
+ return files;
486
+ }
487
+
488
+ /**
489
+ * Exports a file from the archive to the filesystem
490
+ * @param internalPath - Path of the file within the archive
491
+ * @param outputPath - Path where the file will be saved
492
+ */
493
+ async exportFile(internalPath: string, outputPath: string): Promise<void> {
494
+ const { promises: fs } = await import('fs');
495
+ const content = this.getFileAsBuffer(internalPath);
496
+ if (!content) {
497
+ throw new Error(`File not found in archive: ${internalPath}`);
498
+ }
499
+ await fs.writeFile(outputPath, content);
500
+ }
501
+
502
+ /**
503
+ * Imports a file from the filesystem into the archive
504
+ * @param sourcePath - Path to the file on filesystem
505
+ * @param internalPath - Path where the file will be stored in archive
506
+ * @param options - Options for adding the file
507
+ */
508
+ async importFile(
509
+ sourcePath: string,
510
+ internalPath: string,
511
+ options: AddFileOptions = {}
512
+ ): Promise<void> {
513
+ const { promises: fs } = await import('fs');
514
+ const content = await fs.readFile(sourcePath);
515
+ this.addFile(internalPath, content, {
516
+ ...options,
517
+ binary: options.binary !== undefined ? options.binary : true,
518
+ });
519
+ }
520
+
521
+ // ==================== SAVING ====================
522
+
523
+ /**
524
+ * Saves the archive to a file
525
+ * @param filePath - Path where the file will be saved
526
+ * @param options - Save options
527
+ */
528
+ async save(filePath: string, options: SaveOptions = {}): Promise<void> {
529
+ const logger = getLogger();
530
+ logger.info('Saving DOCX file', { path: filePath, fileCount: this.getFileCount() });
531
+ await this.writer.saveToFile(filePath, options);
532
+ logger.info('DOCX file saved', { path: filePath });
533
+ }
534
+
535
+ /**
536
+ * Generates the ZIP archive as a buffer
537
+ * @param options - Save options
538
+ * @returns Buffer containing the ZIP archive
539
+ */
540
+ async toBuffer(options: SaveOptions = {}): Promise<Buffer> {
541
+ const logger = getLogger();
542
+ logger.info('Generating DOCX buffer', { fileCount: this.getFileCount() });
543
+ const buffer = await this.writer.toBuffer(options);
544
+ logger.info('DOCX buffer generated', { bufferSize: buffer.length });
545
+ return buffer;
546
+ }
547
+
548
+ // ==================== VALIDATION ====================
549
+
550
+ /**
551
+ * Validates the DOCX structure
552
+ * @throws {MissingRequiredFileError} If required files are missing
553
+ */
554
+ validate(): void {
555
+ const logger = getLogger();
556
+ logger.info('Validating DOCX structure');
557
+ this.writer.validate();
558
+ logger.info('DOCX structure valid');
559
+ }
560
+
561
+ // ==================== UTILITY ====================
562
+
563
+ /**
564
+ * Creates a new empty archive
565
+ */
566
+ clear(): void {
567
+ this.reader.clear();
568
+ this.writer.clear();
569
+ this.mode = 'write';
570
+ }
571
+
572
+ /**
573
+ * Gets the current mode of the handler
574
+ * @returns Current mode ('read', 'write', or 'modify')
575
+ */
576
+ getMode(): 'read' | 'write' | 'modify' {
577
+ return this.mode;
578
+ }
579
+
580
+ /**
581
+ * Checks if the archive has been loaded
582
+ * @returns True if loaded
583
+ */
584
+ isLoaded(): boolean {
585
+ return this.reader.isLoaded();
586
+ }
587
+
588
+ /**
589
+ * Creates a clone of this handler with all its files
590
+ * @returns A new ZipHandler instance with the same files
591
+ */
592
+ clone(): ZipHandler {
593
+ const newHandler = new ZipHandler();
594
+ newHandler.writer = this.writer.clone();
595
+ newHandler.mode = this.mode;
596
+ return newHandler;
597
+ }
598
+
599
+ // ==================== CONVENIENCE METHODS ====================
600
+
601
+ /**
602
+ * Reads a DOCX file, modifies it, and saves it back
603
+ * @param inputPath - Path to the input DOCX file
604
+ * @param outputPath - Path to save the modified file
605
+ * @param modifier - Function that modifies the handler
606
+ * @param loadOptions - Options for loading
607
+ * @param saveOptions - Options for saving
608
+ */
609
+ static async modify(
610
+ inputPath: string,
611
+ outputPath: string,
612
+ modifier: (handler: ZipHandler) => void | Promise<void>,
613
+ loadOptions: LoadOptions = {},
614
+ saveOptions: SaveOptions = {}
615
+ ): Promise<void> {
616
+ const handler = new ZipHandler();
617
+ await handler.load(inputPath, loadOptions);
618
+ await modifier(handler);
619
+ await handler.save(outputPath, saveOptions);
620
+ }
621
+
622
+ /**
623
+ * Creates a new DOCX file with the provided files
624
+ * @param outputPath - Path to save the new file
625
+ * @param files - Map of file paths to contents
626
+ * @param saveOptions - Options for saving
627
+ */
628
+ static async create(
629
+ outputPath: string,
630
+ files: FileMap,
631
+ saveOptions: SaveOptions = {}
632
+ ): Promise<void> {
633
+ const handler = new ZipHandler();
634
+ handler.addFiles(files);
635
+ await handler.save(outputPath, saveOptions);
636
+ }
637
+ }