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,217 @@
1
+ /**
2
+ * cnfStyle Decoder - Decodes the conditional formatting style bitmask
3
+ * Per ECMA-376 Part 1 Section 17.4.7 (w:cnfStyle)
4
+ *
5
+ * The cnfStyle is a 12-character string where each character is '0' or '1'
6
+ * representing whether a particular conditional format applies.
7
+ */
8
+
9
+ import { ConditionalFormattingType } from "../formatting/Style";
10
+
11
+ /**
12
+ * Decoded cnfStyle flags
13
+ * Each flag corresponds to a conditional formatting type that may apply to a cell
14
+ */
15
+ export interface CnfStyleFlags {
16
+ /** First row of table (header row) */
17
+ firstRow: boolean;
18
+ /** Last row of table */
19
+ lastRow: boolean;
20
+ /** First column of table */
21
+ firstCol: boolean;
22
+ /** Last column of table */
23
+ lastCol: boolean;
24
+ /** Odd vertical band (column banding) */
25
+ band1Vert: boolean;
26
+ /** Even vertical band (column banding) */
27
+ band2Vert: boolean;
28
+ /** Odd horizontal band (row banding) */
29
+ band1Horz: boolean;
30
+ /** Even horizontal band (row banding) */
31
+ band2Horz: boolean;
32
+ /** Northeast cell (top-right corner) */
33
+ neCell: boolean;
34
+ /** Northwest cell (top-left corner) */
35
+ nwCell: boolean;
36
+ /** Southeast cell (bottom-right corner) */
37
+ seCell: boolean;
38
+ /** Southwest cell (bottom-left corner) */
39
+ swCell: boolean;
40
+ }
41
+
42
+ /**
43
+ * Maps flag names to ConditionalFormattingType values
44
+ */
45
+ export const CNF_TO_CONDITIONAL_MAP: Record<
46
+ keyof CnfStyleFlags,
47
+ ConditionalFormattingType
48
+ > = {
49
+ firstRow: "firstRow",
50
+ lastRow: "lastRow",
51
+ firstCol: "firstCol",
52
+ lastCol: "lastCol",
53
+ band1Vert: "band1Vert",
54
+ band2Vert: "band2Vert",
55
+ band1Horz: "band1Horz",
56
+ band2Horz: "band2Horz",
57
+ neCell: "neCell",
58
+ nwCell: "nwCell",
59
+ seCell: "seCell",
60
+ swCell: "swCell",
61
+ };
62
+
63
+ /**
64
+ * Bit positions in the cnfStyle string (0-indexed from left)
65
+ * Per ECMA-376 Part 1 Section 17.4.7
66
+ */
67
+ const BIT_POSITIONS: Record<keyof CnfStyleFlags, number> = {
68
+ firstRow: 0,
69
+ lastRow: 1,
70
+ firstCol: 2,
71
+ lastCol: 3,
72
+ band1Vert: 4,
73
+ band2Vert: 5,
74
+ band1Horz: 6,
75
+ band2Horz: 7,
76
+ neCell: 8,
77
+ nwCell: 9,
78
+ seCell: 10,
79
+ swCell: 11,
80
+ };
81
+
82
+ /**
83
+ * Priority order for conditional formatting resolution
84
+ * More specific conditions (corners) override less specific (edges, banding)
85
+ * Per ECMA-376, this is the order in which conditionals should be applied
86
+ */
87
+ export const CONDITIONAL_PRIORITY_ORDER: (keyof CnfStyleFlags)[] = [
88
+ // Corner cells (most specific)
89
+ "nwCell",
90
+ "neCell",
91
+ "swCell",
92
+ "seCell",
93
+ // Edge rows/columns
94
+ "firstRow",
95
+ "lastRow",
96
+ "firstCol",
97
+ "lastCol",
98
+ // Banding (least specific)
99
+ "band1Horz",
100
+ "band2Horz",
101
+ "band1Vert",
102
+ "band2Vert",
103
+ ];
104
+
105
+ /**
106
+ * Decodes a cnfStyle string into individual flags
107
+ *
108
+ * @param cnfStyle - 12-character binary string (e.g., "100000000000" for firstRow)
109
+ * @returns Decoded flags object
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const flags = decodeCnfStyle('100000000000');
114
+ * console.log(flags.firstRow); // true
115
+ * console.log(flags.lastRow); // false
116
+ * ```
117
+ */
118
+ export function decodeCnfStyle(cnfStyle: string): CnfStyleFlags {
119
+ // Pad to 12 characters if shorter (handles legacy or truncated values)
120
+ // Use padEnd because the string represents left-to-right bit positions
121
+ const normalized = cnfStyle.padEnd(12, "0");
122
+
123
+ return {
124
+ firstRow: normalized.startsWith("1"),
125
+ lastRow: normalized[BIT_POSITIONS.lastRow] === "1",
126
+ firstCol: normalized[BIT_POSITIONS.firstCol] === "1",
127
+ lastCol: normalized[BIT_POSITIONS.lastCol] === "1",
128
+ band1Vert: normalized[BIT_POSITIONS.band1Vert] === "1",
129
+ band2Vert: normalized[BIT_POSITIONS.band2Vert] === "1",
130
+ band1Horz: normalized[BIT_POSITIONS.band1Horz] === "1",
131
+ band2Horz: normalized[BIT_POSITIONS.band2Horz] === "1",
132
+ neCell: normalized[BIT_POSITIONS.neCell] === "1",
133
+ nwCell: normalized[BIT_POSITIONS.nwCell] === "1",
134
+ seCell: normalized[BIT_POSITIONS.seCell] === "1",
135
+ swCell: normalized[BIT_POSITIONS.swCell] === "1",
136
+ };
137
+ }
138
+
139
+ /**
140
+ * Encodes CnfStyleFlags back to a binary string
141
+ *
142
+ * @param flags - Flags to encode
143
+ * @returns 12-character binary string
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const cnfStyle = encodeCnfStyle({ firstRow: true, lastCol: true });
148
+ * console.log(cnfStyle); // '100100000000'
149
+ * ```
150
+ */
151
+ export function encodeCnfStyle(flags: Partial<CnfStyleFlags>): string {
152
+ const bits = new Array(12).fill("0");
153
+
154
+ for (const [key, position] of Object.entries(BIT_POSITIONS)) {
155
+ if (flags[key as keyof CnfStyleFlags]) {
156
+ bits[position] = "1";
157
+ }
158
+ }
159
+
160
+ return bits.join("");
161
+ }
162
+
163
+ /**
164
+ * Gets the active conditional formatting types from a cnfStyle
165
+ *
166
+ * @param cnfStyle - The cnfStyle string to decode
167
+ * @returns Array of active ConditionalFormattingType values
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const types = getActiveConditionals('110000000000');
172
+ * console.log(types); // ['firstRow', 'lastRow']
173
+ * ```
174
+ */
175
+ export function getActiveConditionals(
176
+ cnfStyle: string
177
+ ): ConditionalFormattingType[] {
178
+ const flags = decodeCnfStyle(cnfStyle);
179
+ const active: ConditionalFormattingType[] = [];
180
+
181
+ for (const [key, isActive] of Object.entries(flags)) {
182
+ if (isActive) {
183
+ active.push(CNF_TO_CONDITIONAL_MAP[key as keyof CnfStyleFlags]);
184
+ }
185
+ }
186
+
187
+ return active;
188
+ }
189
+
190
+ /**
191
+ * Gets the active conditional formatting types in priority order
192
+ * More specific conditions come first (corners before edges before banding)
193
+ *
194
+ * @param cnfStyle - The cnfStyle string to decode
195
+ * @returns Array of active ConditionalFormattingType values in priority order
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * // Cell is both in first row and is the nwCell (top-left corner)
200
+ * const types = getActiveConditionalsInPriorityOrder('100000000100');
201
+ * console.log(types); // ['nwCell', 'firstRow'] - corner takes priority
202
+ * ```
203
+ */
204
+ export function getActiveConditionalsInPriorityOrder(
205
+ cnfStyle: string
206
+ ): ConditionalFormattingType[] {
207
+ const flags = decodeCnfStyle(cnfStyle);
208
+ const active: ConditionalFormattingType[] = [];
209
+
210
+ for (const flagName of CONDITIONAL_PRIORITY_ORDER) {
211
+ if (flags[flagName]) {
212
+ active.push(CNF_TO_CONDITIONAL_MAP[flagName]);
213
+ }
214
+ }
215
+
216
+ return active;
217
+ }
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Corruption Detection - Utilities to detect and diagnose XML corruption in documents
3
+ *
4
+ * This module helps users identify when they've accidentally passed XML-like strings
5
+ * to text methods instead of using the proper API. This is a common mistake that
6
+ * results in escaped XML tags being displayed as literal text in Word.
7
+ */
8
+
9
+ import { Paragraph } from '../elements/Paragraph';
10
+ import { Run } from '../elements/Run';
11
+
12
+ /** Minimal interface for document corruption scanning (avoids circular import) */
13
+ interface DocumentLike {
14
+ getAllParagraphs?(): Paragraph[];
15
+ }
16
+
17
+ /**
18
+ * Types of corruption that can be detected
19
+ */
20
+ export type CorruptionType =
21
+ | 'escaped-xml' // &lt;w:t&gt; style escaping
22
+ | 'xml-tags' // <w:t> tags in text
23
+ | 'entities' // &quot; &apos; etc.
24
+ | 'mixed'; // Multiple types
25
+
26
+ /**
27
+ * Location of corruption within a document
28
+ */
29
+ export interface CorruptionLocation {
30
+ /** Index of the paragraph containing corruption */
31
+ paragraphIndex: number;
32
+ /** Index of the run within the paragraph */
33
+ runIndex: number;
34
+ /** The corrupted text content */
35
+ text: string;
36
+ /** Type of corruption detected */
37
+ corruptionType: CorruptionType;
38
+ /** Suggested fix for the corruption */
39
+ suggestedFix: string;
40
+ /** Length of corrupted text */
41
+ length: number;
42
+ }
43
+
44
+ /**
45
+ * Comprehensive corruption report for a document
46
+ */
47
+ export interface CorruptionReport {
48
+ /** Whether any corruption was found */
49
+ isCorrupted: boolean;
50
+ /** Total number of corrupted locations */
51
+ totalLocations: number;
52
+ /** Detailed list of corruption locations */
53
+ locations: CorruptionLocation[];
54
+ /** Human-readable summary */
55
+ summary: string;
56
+ /** Statistics about corruption types */
57
+ statistics: {
58
+ escapedXml: number;
59
+ xmlTags: number;
60
+ entities: number;
61
+ mixed: number;
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Detects XML corruption in a document
67
+ *
68
+ * Scans all paragraphs and runs to find text that contains escaped XML
69
+ * or XML-like patterns that suggest the user passed XML strings to text methods.
70
+ *
71
+ * @param doc - The document to scan
72
+ * @returns Corruption report with locations and suggested fixes
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const doc = await Document.load('corrupted.docx');
77
+ * const report = detectCorruptionInDocument(doc);
78
+ *
79
+ * if (report.isCorrupted) {
80
+ * console.log(report.summary);
81
+ * report.locations.forEach(loc => {
82
+ * console.log(`Paragraph ${loc.paragraphIndex}, Run ${loc.runIndex}: ${loc.suggestedFix}`);
83
+ * });
84
+ * }
85
+ * ```
86
+ */
87
+ export function detectCorruptionInDocument(doc: DocumentLike): CorruptionReport {
88
+ const locations: CorruptionLocation[] = [];
89
+ const stats = {
90
+ escapedXml: 0,
91
+ xmlTags: 0,
92
+ entities: 0,
93
+ mixed: 0,
94
+ };
95
+
96
+ // Get all paragraphs from the document
97
+ const paragraphs = doc.getAllParagraphs ? doc.getAllParagraphs() : [];
98
+
99
+ // Scan each paragraph
100
+ for (let pIdx = 0; pIdx < paragraphs.length; pIdx++) {
101
+ const paragraph = paragraphs[pIdx];
102
+ if (!paragraph || !(paragraph instanceof Paragraph)) {
103
+ continue;
104
+ }
105
+
106
+ // Get runs from paragraph
107
+ const runs = paragraph.getRuns();
108
+
109
+ // Scan each run
110
+ for (let rIdx = 0; rIdx < runs.length; rIdx++) {
111
+ const run = runs[rIdx];
112
+ if (!run || !(run instanceof Run)) {
113
+ continue;
114
+ }
115
+
116
+ const text = run.getText();
117
+ if (!text || text.length === 0) {
118
+ continue;
119
+ }
120
+
121
+ // Check for corruption in this text
122
+ const corruption = detectCorruptionInText(text);
123
+
124
+ if (corruption.isCorrupted) {
125
+ locations.push({
126
+ paragraphIndex: pIdx,
127
+ runIndex: rIdx,
128
+ text: text,
129
+ corruptionType: corruption.type,
130
+ suggestedFix: corruption.suggestedFix,
131
+ length: text.length,
132
+ });
133
+
134
+ // Update statistics
135
+ if (corruption.type === 'escaped-xml') stats.escapedXml++;
136
+ else if (corruption.type === 'xml-tags') stats.xmlTags++;
137
+ else if (corruption.type === 'entities') stats.entities++;
138
+ else if (corruption.type === 'mixed') stats.mixed++;
139
+ }
140
+ }
141
+ }
142
+
143
+ // Generate summary
144
+ const summary = generateSummary(locations, stats);
145
+
146
+ return {
147
+ isCorrupted: locations.length > 0,
148
+ totalLocations: locations.length,
149
+ locations,
150
+ summary,
151
+ statistics: stats,
152
+ };
153
+ }
154
+
155
+ /**
156
+ * Internal result from text corruption detection
157
+ */
158
+ interface TextCorruptionResult {
159
+ isCorrupted: boolean;
160
+ type: CorruptionType;
161
+ suggestedFix: string;
162
+ }
163
+
164
+ /**
165
+ * Detects XML corruption in a single text string
166
+ *
167
+ * Checks for common patterns that indicate the user passed XML strings
168
+ * instead of plain text.
169
+ *
170
+ * @param text - Text to check
171
+ * @returns True if corruption detected
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const corrupted = detectCorruptionInText('Hello &lt;w:t&gt;World');
176
+ * // Returns: true
177
+ *
178
+ * const clean = detectCorruptionInText('Hello World');
179
+ * // Returns: false
180
+ * ```
181
+ */
182
+ export function detectCorruptionInText(text: string): TextCorruptionResult {
183
+ if (!text || typeof text !== 'string') {
184
+ return { isCorrupted: false, type: 'mixed', suggestedFix: String(text || '') };
185
+ }
186
+
187
+ let hasEscapedXml = false;
188
+ let hasXmlTags = false;
189
+ let hasEntities = false;
190
+
191
+ // Pattern 1: Escaped XML tags (most common corruption)
192
+ // Matches: &lt;w:t&gt;, &lt;/w:t&gt;, &lt;w:r&gt;, etc.
193
+ const escapedXmlPattern = /&lt;\/?w:[a-z]+[^&]*&gt;/i;
194
+ if (escapedXmlPattern.test(text)) {
195
+ hasEscapedXml = true;
196
+ }
197
+
198
+ // Pattern 2: Raw XML tags (less common, but possible)
199
+ // Matches: <w:t>, </w:t>, <w:r>, etc.
200
+ const xmlTagPattern = /<\/?w:[a-z]+[^>]*>/i;
201
+ if (xmlTagPattern.test(text)) {
202
+ hasXmlTags = true;
203
+ }
204
+
205
+ // Pattern 3: Escaped entities combined with Word XML attributes
206
+ // ONLY flag if we see Word-specific patterns, not just any entities
207
+ // This avoids false positives from legitimate escaped characters
208
+ // Matches all OOXML namespaces: w: (word), a: (drawingML), pic: (picture), r: (relationships), wp: (word drawing)
209
+ const wordXmlAttributePattern = /(&lt;(?:w|a|r|pic|wp|m|mc|wpc|wps|wpg|c|dgm|o|v):|xml:space=&quot;preserve&quot;)/i;
210
+ if (wordXmlAttributePattern.test(text)) {
211
+ hasEntities = true;
212
+ }
213
+
214
+ // Determine corruption type
215
+ const corruptionCount = [hasEscapedXml, hasXmlTags, hasEntities].filter(Boolean).length;
216
+
217
+ if (corruptionCount === 0) {
218
+ return { isCorrupted: false, type: 'mixed', suggestedFix: text };
219
+ }
220
+
221
+ // More precise type detection - check primary indicator first
222
+ let type: CorruptionType;
223
+ if (hasEscapedXml && (hasEntities || hasXmlTags)) {
224
+ // Escaped XML combined with other patterns - this is the classic corruption case
225
+ type = 'escaped-xml';
226
+ } else if (hasXmlTags && hasEntities) {
227
+ type = 'xml-tags';
228
+ } else if (corruptionCount > 1) {
229
+ type = 'mixed';
230
+ } else if (hasEscapedXml) {
231
+ type = 'escaped-xml';
232
+ } else if (hasXmlTags) {
233
+ type = 'xml-tags';
234
+ } else {
235
+ type = 'entities';
236
+ }
237
+
238
+ const suggestedFix = suggestFix(text);
239
+
240
+ return { isCorrupted: true, type, suggestedFix };
241
+ }
242
+
243
+ /**
244
+ * Suggests a fix for corrupted text
245
+ *
246
+ * Attempts to clean XML patterns from text to restore the intended content.
247
+ * Uses the same cleaning logic as cleanXmlFromText() from validation.ts.
248
+ *
249
+ * @param corruptedText - Text containing XML corruption
250
+ * @returns Cleaned text with XML patterns removed
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const fixed = suggestFix('Hello &lt;w:t&gt;World&lt;/w:t&gt;');
255
+ * // Returns: 'Hello World'
256
+ * ```
257
+ */
258
+ export function suggestFix(corruptedText: string): string {
259
+ if (!corruptedText || typeof corruptedText !== 'string') {
260
+ return corruptedText;
261
+ }
262
+
263
+ let cleaned = corruptedText;
264
+
265
+ // Step 1: Unescape XML entities first
266
+ cleaned = cleaned
267
+ .replace(/&lt;/g, '<')
268
+ .replace(/&gt;/g, '>')
269
+ .replace(/&quot;/g, '"')
270
+ .replace(/&apos;/g, "'")
271
+ .replace(/&amp;/g, '&');
272
+
273
+ // Step 2: Remove Word XML tags
274
+ // Matches: <w:t xml:space="preserve">, </w:t>, <w:r>, etc.
275
+ cleaned = cleaned.replace(/<w:[^>]+>/g, '');
276
+ cleaned = cleaned.replace(/<\/w:[^>]+>/g, '');
277
+
278
+ // Step 3: Remove any remaining XML-like tags
279
+ cleaned = cleaned.replace(/<[^>]+>/g, '');
280
+
281
+ // Step 4: Clean up whitespace
282
+ cleaned = cleaned.replace(/\s+/g, ' ').trim();
283
+
284
+ return cleaned;
285
+ }
286
+
287
+ /**
288
+ * Generates a human-readable summary of corruption
289
+ */
290
+ function generateSummary(
291
+ locations: CorruptionLocation[],
292
+ stats: { escapedXml: number; xmlTags: number; entities: number; mixed: number }
293
+ ): string {
294
+ if (locations.length === 0) {
295
+ return 'No corruption detected. Document is clean.';
296
+ }
297
+
298
+ const lines: string[] = [];
299
+ lines.push(`Found ${locations.length} corrupted text location(s) in the document.`);
300
+ lines.push('');
301
+ lines.push('Corruption breakdown:');
302
+
303
+ if (stats.escapedXml > 0) {
304
+ lines.push(` - Escaped XML: ${stats.escapedXml} location(s)`);
305
+ }
306
+ if (stats.xmlTags > 0) {
307
+ lines.push(` - XML Tags: ${stats.xmlTags} location(s)`);
308
+ }
309
+ if (stats.entities > 0) {
310
+ lines.push(` - XML Entities: ${stats.entities} location(s)`);
311
+ }
312
+ if (stats.mixed > 0) {
313
+ lines.push(` - Mixed: ${stats.mixed} location(s)`);
314
+ }
315
+
316
+ lines.push('');
317
+ lines.push('This corruption typically occurs when XML strings are passed to text methods.');
318
+ lines.push('Instead of: paragraph.addText("Text<w:t>1</w:t>")');
319
+ lines.push('Use: paragraph.addText("Text"); paragraph.addText("1");');
320
+ lines.push('');
321
+ lines.push('To automatically clean text, use: new Run(text, { cleanXmlFromText: true })');
322
+
323
+ return lines.join('\n');
324
+ }
325
+
326
+ /**
327
+ * Checks if text looks like it might be corrupted (less strict check)
328
+ *
329
+ * This is a quick check that can be used for warnings without full analysis.
330
+ *
331
+ * @param text - Text to check
332
+ * @returns True if text might be corrupted
333
+ */
334
+ export function looksCorrupted(text: string): boolean {
335
+ if (!text || typeof text !== 'string') {
336
+ return false;
337
+ }
338
+
339
+ // Quick regex checks for common corruption patterns
340
+ return (
341
+ /&lt;\/?(w|r|p):[a-z]+/i.test(text) ||
342
+ /<\/?(w|r|p):[a-z]+/i.test(text) ||
343
+ /xml:space=&quot;/i.test(text)
344
+ );
345
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Date formatting utilities for OOXML XML generation
3
+ *
4
+ * ECMA-376 requires dates in ISO 8601 format WITHOUT milliseconds:
5
+ * Valid: "2024-01-01T12:00:00Z"
6
+ * Invalid: "2024-01-01T12:00:00.000Z" (Word rejects milliseconds in w:date attributes)
7
+ *
8
+ * JavaScript's Date.toISOString() always includes milliseconds (YYYY-MM-DDTHH:mm:ss.sssZ),
9
+ * so we must strip the .sss portion for all w:date attributes in tracked changes.
10
+ */
11
+
12
+ /**
13
+ * Formats a Date to ISO 8601 without milliseconds for OOXML w:date attributes.
14
+ *
15
+ * @param date - Date to format
16
+ * @returns ISO 8601 date string without milliseconds (e.g., "2024-01-01T12:00:00Z")
17
+ */
18
+ export function formatDateForXml(date: Date): string {
19
+ return date.toISOString().replace(/\.\d{3}Z$/, 'Z');
20
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Deep clone utility for safely cloning objects
3
+ * More efficient and type-safe than JSON.parse(JSON.stringify())
4
+ */
5
+
6
+ /**
7
+ * Deep clone an object using structured cloning
8
+ * Preserves most object types including Date, RegExp, Map, Set, etc.
9
+ *
10
+ * For simple objects (like formatting options), this is more efficient
11
+ * than JSON.parse(JSON.stringify()) and doesn't lose non-serializable values.
12
+ *
13
+ * @param obj - Object to clone
14
+ * @returns Deep cloned copy of the object
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const original = { bold: true, color: "FF0000", date: new Date() };
19
+ * const cloned = deepClone(original);
20
+ * cloned.bold = false;
21
+ * console.log(original.bold); // true (unchanged)
22
+ * console.log(cloned.date instanceof Date); // true (preserved)
23
+ * ```
24
+ */
25
+ export function deepClone<T>(obj: T): T {
26
+ // Handle primitive types and null
27
+ if (obj === null || typeof obj !== 'object') {
28
+ return obj;
29
+ }
30
+
31
+ // Handle Date
32
+ if (obj instanceof Date) {
33
+ return new Date(obj.getTime()) as T;
34
+ }
35
+
36
+ // Handle Array
37
+ if (Array.isArray(obj)) {
38
+ const arrCopy: unknown[] = [];
39
+ for (let i = 0; i < obj.length; i++) {
40
+ arrCopy[i] = deepClone(obj[i]);
41
+ }
42
+ return arrCopy as T;
43
+ }
44
+
45
+ // Handle Map
46
+ if (obj instanceof Map) {
47
+ const mapCopy = new Map();
48
+ obj.forEach((value, key) => {
49
+ mapCopy.set(deepClone(key), deepClone(value));
50
+ });
51
+ return mapCopy as T;
52
+ }
53
+
54
+ // Handle Set
55
+ if (obj instanceof Set) {
56
+ const setCopy = new Set();
57
+ obj.forEach(value => {
58
+ setCopy.add(deepClone(value));
59
+ });
60
+ return setCopy as T;
61
+ }
62
+
63
+ // Handle RegExp
64
+ if (obj instanceof RegExp) {
65
+ return new RegExp(obj.source, obj.flags) as T;
66
+ }
67
+
68
+ // Handle plain objects
69
+ const objCopy = Object.create(Object.getPrototypeOf(obj)) as Record<string, unknown>;
70
+ for (const key in obj) {
71
+ if (obj.hasOwnProperty(key)) {
72
+ objCopy[key] = deepClone((obj as Record<string, unknown>)[key]);
73
+ }
74
+ }
75
+
76
+ return objCopy as T;
77
+ }
78
+