docxmlater 10.1.4 → 10.1.6

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 (372) 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 +51 -50
  6. package/dist/core/Document.d.ts.map +1 -1
  7. package/dist/core/Document.js +486 -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 +1 -0
  146. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  147. package/dist/formatting/NumberingManager.js +27 -9
  148. package/dist/formatting/NumberingManager.js.map +1 -1
  149. package/dist/formatting/Style.d.ts +11 -11
  150. package/dist/formatting/Style.d.ts.map +1 -1
  151. package/dist/formatting/Style.js +219 -247
  152. package/dist/formatting/Style.js.map +1 -1
  153. package/dist/formatting/StylesManager.d.ts +2 -2
  154. package/dist/formatting/StylesManager.d.ts.map +1 -1
  155. package/dist/formatting/StylesManager.js +96 -102
  156. package/dist/formatting/StylesManager.js.map +1 -1
  157. package/dist/helpers/CleanupHelper.d.ts +1 -1
  158. package/dist/helpers/CleanupHelper.d.ts.map +1 -1
  159. package/dist/helpers/CleanupHelper.js +6 -6
  160. package/dist/helpers/CleanupHelper.js.map +1 -1
  161. package/dist/images/ImageOptimizer.js +7 -7
  162. package/dist/images/ImageOptimizer.js.map +1 -1
  163. package/dist/index.d.ts +9 -9
  164. package/dist/index.d.ts.map +1 -1
  165. package/dist/index.js.map +1 -1
  166. package/dist/managers/DrawingManager.js.map +1 -1
  167. package/dist/tracking/DocumentTrackingContext.d.ts.map +1 -1
  168. package/dist/tracking/DocumentTrackingContext.js +23 -7
  169. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  170. package/dist/tracking/TrackingContext.d.ts.map +1 -1
  171. package/dist/tracking/TrackingContext.js.map +1 -1
  172. package/dist/types/compatibility-types.js.map +1 -1
  173. package/dist/types/formatting.js.map +1 -1
  174. package/dist/types/list-types.d.ts +6 -6
  175. package/dist/types/list-types.js.map +1 -1
  176. package/dist/types/settings-types.js.map +1 -1
  177. package/dist/types/styleConfig.d.ts +2 -2
  178. package/dist/types/styleConfig.js.map +1 -1
  179. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  180. package/dist/utils/ChangelogGenerator.js +97 -101
  181. package/dist/utils/ChangelogGenerator.js.map +1 -1
  182. package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
  183. package/dist/utils/CompatibilityUpgrader.js +1 -1
  184. package/dist/utils/CompatibilityUpgrader.js.map +1 -1
  185. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  186. package/dist/utils/InMemoryRevisionAcceptor.js +1 -6
  187. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  188. package/dist/utils/MoveOperationHelper.d.ts.map +1 -1
  189. package/dist/utils/MoveOperationHelper.js +1 -1
  190. package/dist/utils/MoveOperationHelper.js.map +1 -1
  191. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  192. package/dist/utils/RevisionAwareProcessor.js +2 -4
  193. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  194. package/dist/utils/RevisionWalker.d.ts.map +1 -1
  195. package/dist/utils/RevisionWalker.js +4 -12
  196. package/dist/utils/RevisionWalker.js.map +1 -1
  197. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  198. package/dist/utils/SelectiveRevisionAcceptor.js +2 -6
  199. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  200. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  201. package/dist/utils/ShadingResolver.js +1 -1
  202. package/dist/utils/ShadingResolver.js.map +1 -1
  203. package/dist/utils/acceptRevisions.d.ts.map +1 -1
  204. package/dist/utils/acceptRevisions.js +23 -12
  205. package/dist/utils/acceptRevisions.js.map +1 -1
  206. package/dist/utils/cnfStyleDecoder.d.ts +1 -1
  207. package/dist/utils/cnfStyleDecoder.d.ts.map +1 -1
  208. package/dist/utils/cnfStyleDecoder.js +40 -40
  209. package/dist/utils/cnfStyleDecoder.js.map +1 -1
  210. package/dist/utils/corruptionDetection.d.ts.map +1 -1
  211. package/dist/utils/corruptionDetection.js.map +1 -1
  212. package/dist/utils/dateFormatting.js.map +1 -1
  213. package/dist/utils/deepClone.js +1 -1
  214. package/dist/utils/deepClone.js.map +1 -1
  215. package/dist/utils/diagnostics.d.ts.map +1 -1
  216. package/dist/utils/diagnostics.js +1 -1
  217. package/dist/utils/diagnostics.js.map +1 -1
  218. package/dist/utils/errorHandling.js.map +1 -1
  219. package/dist/utils/formatting.d.ts.map +1 -1
  220. package/dist/utils/formatting.js +10 -2
  221. package/dist/utils/formatting.js.map +1 -1
  222. package/dist/utils/list-detection.d.ts +2 -2
  223. package/dist/utils/list-detection.d.ts.map +1 -1
  224. package/dist/utils/list-detection.js +21 -23
  225. package/dist/utils/list-detection.js.map +1 -1
  226. package/dist/utils/logger.d.ts.map +1 -1
  227. package/dist/utils/logger.js +12 -7
  228. package/dist/utils/logger.js.map +1 -1
  229. package/dist/utils/parsingHelpers.js.map +1 -1
  230. package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
  231. package/dist/utils/stripTrackedChanges.js +3 -3
  232. package/dist/utils/stripTrackedChanges.js.map +1 -1
  233. package/dist/utils/textDiff.d.ts +1 -1
  234. package/dist/utils/textDiff.js +8 -8
  235. package/dist/utils/textDiff.js.map +1 -1
  236. package/dist/utils/units.js.map +1 -1
  237. package/dist/utils/validation.d.ts.map +1 -1
  238. package/dist/utils/validation.js +24 -7
  239. package/dist/utils/validation.js.map +1 -1
  240. package/dist/utils/xmlSanitization.d.ts.map +1 -1
  241. package/dist/utils/xmlSanitization.js +3 -3
  242. package/dist/utils/xmlSanitization.js.map +1 -1
  243. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  244. package/dist/validation/RevisionAutoFixer.js +5 -5
  245. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  246. package/dist/validation/RevisionValidator.d.ts.map +1 -1
  247. package/dist/validation/RevisionValidator.js +7 -9
  248. package/dist/validation/RevisionValidator.js.map +1 -1
  249. package/dist/validation/ValidationRules.js +3 -3
  250. package/dist/validation/ValidationRules.js.map +1 -1
  251. package/dist/validation/index.js.map +1 -1
  252. package/dist/xml/XMLBuilder.d.ts +1 -1
  253. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  254. package/dist/xml/XMLBuilder.js +98 -100
  255. package/dist/xml/XMLBuilder.js.map +1 -1
  256. package/dist/xml/XMLParser.d.ts.map +1 -1
  257. package/dist/xml/XMLParser.js +61 -66
  258. package/dist/xml/XMLParser.js.map +1 -1
  259. package/dist/zip/ZipHandler.d.ts.map +1 -1
  260. package/dist/zip/ZipHandler.js.map +1 -1
  261. package/dist/zip/ZipReader.d.ts.map +1 -1
  262. package/dist/zip/ZipReader.js +1 -3
  263. package/dist/zip/ZipReader.js.map +1 -1
  264. package/dist/zip/ZipWriter.d.ts +1 -1
  265. package/dist/zip/ZipWriter.d.ts.map +1 -1
  266. package/dist/zip/ZipWriter.js +28 -36
  267. package/dist/zip/ZipWriter.js.map +1 -1
  268. package/dist/zip/types.js +1 -1
  269. package/dist/zip/types.js.map +1 -1
  270. package/package.json +92 -92
  271. package/src/__tests__/helper-methods.test.ts +512 -512
  272. package/src/constants/legacyCompatFlags.ts +138 -138
  273. package/src/constants/limits.ts +50 -50
  274. package/src/core/Document.ts +1010 -1145
  275. package/src/core/DocumentContent.ts +461 -467
  276. package/src/core/DocumentGenerator.ts +1133 -1104
  277. package/src/core/DocumentIdManager.ts +158 -158
  278. package/src/core/DocumentParser.ts +2347 -2716
  279. package/src/core/DocumentValidator.ts +363 -372
  280. package/src/core/Relationship.ts +367 -367
  281. package/src/core/RelationshipManager.ts +429 -428
  282. package/src/elements/AlternateContent.ts +42 -42
  283. package/src/elements/Bookmark.ts +212 -210
  284. package/src/elements/BookmarkManager.ts +247 -250
  285. package/src/elements/Comment.ts +356 -359
  286. package/src/elements/CommentManager.ts +499 -502
  287. package/src/elements/CommonTypes.ts +524 -549
  288. package/src/elements/CustomXml.ts +36 -36
  289. package/src/elements/Endnote.ts +221 -217
  290. package/src/elements/EndnoteManager.ts +246 -249
  291. package/src/elements/Field.ts +1292 -1233
  292. package/src/elements/FieldHelpers.ts +329 -333
  293. package/src/elements/FontManager.ts +336 -339
  294. package/src/elements/Footer.ts +269 -269
  295. package/src/elements/Footnote.ts +221 -217
  296. package/src/elements/FootnoteManager.ts +246 -249
  297. package/src/elements/Header.ts +269 -269
  298. package/src/elements/HeaderFooterManager.ts +219 -219
  299. package/src/elements/Hyperlink.ts +1288 -1193
  300. package/src/elements/Image.ts +1982 -1756
  301. package/src/elements/ImageManager.ts +437 -432
  302. package/src/elements/ImageRun.ts +59 -59
  303. package/src/elements/MathElement.ts +65 -65
  304. package/src/elements/Paragraph.ts +4347 -4287
  305. package/src/elements/PreservedElement.ts +53 -53
  306. package/src/elements/PropertyChangeTypes.ts +458 -442
  307. package/src/elements/RangeMarker.ts +382 -400
  308. package/src/elements/Revision.ts +1198 -1217
  309. package/src/elements/RevisionContent.ts +73 -73
  310. package/src/elements/RevisionManager.ts +1070 -1070
  311. package/src/elements/Run.ts +3103 -3073
  312. package/src/elements/Section.ts +1521 -1421
  313. package/src/elements/Shape.ts +884 -873
  314. package/src/elements/StructuredDocumentTag.ts +1176 -1207
  315. package/src/elements/Table.ts +2468 -2524
  316. package/src/elements/TableCell.ts +1617 -1621
  317. package/src/elements/TableGridChange.ts +149 -151
  318. package/src/elements/TableOfContents.ts +701 -691
  319. package/src/elements/TableOfContentsElement.ts +89 -89
  320. package/src/elements/TableRow.ts +960 -929
  321. package/src/elements/TextBox.ts +766 -768
  322. package/src/formatting/AbstractNumbering.ts +580 -579
  323. package/src/formatting/NumberingInstance.ts +295 -299
  324. package/src/formatting/NumberingLevel.ts +981 -1040
  325. package/src/formatting/NumberingManager.ts +875 -827
  326. package/src/formatting/Style.ts +1785 -1879
  327. package/src/formatting/StylesManager.ts +1090 -1130
  328. package/src/helpers/CleanupHelper.ts +524 -524
  329. package/src/images/ImageOptimizer.ts +274 -274
  330. package/src/index.ts +559 -554
  331. package/src/managers/DrawingManager.ts +319 -319
  332. package/src/tracking/DocumentTrackingContext.ts +687 -674
  333. package/src/tracking/TrackingContext.ts +175 -173
  334. package/src/types/compatibility-types.ts +49 -49
  335. package/src/types/formatting.ts +210 -210
  336. package/src/types/list-types.ts +14 -14
  337. package/src/types/settings-types.ts +59 -59
  338. package/src/types/styleConfig.ts +189 -189
  339. package/src/utils/ChangelogGenerator.ts +1583 -1581
  340. package/src/utils/CompatibilityUpgrader.ts +235 -237
  341. package/src/utils/InMemoryRevisionAcceptor.ts +691 -696
  342. package/src/utils/MoveOperationHelper.ts +233 -238
  343. package/src/utils/RevisionAwareProcessor.ts +518 -526
  344. package/src/utils/RevisionWalker.ts +427 -457
  345. package/src/utils/SelectiveRevisionAcceptor.ts +662 -683
  346. package/src/utils/ShadingResolver.ts +105 -107
  347. package/src/utils/acceptRevisions.ts +723 -714
  348. package/src/utils/cnfStyleDecoder.ts +212 -217
  349. package/src/utils/corruptionDetection.ts +346 -345
  350. package/src/utils/dateFormatting.ts +20 -20
  351. package/src/utils/deepClone.ts +77 -78
  352. package/src/utils/diagnostics.ts +125 -129
  353. package/src/utils/errorHandling.ts +80 -80
  354. package/src/utils/formatting.ts +220 -213
  355. package/src/utils/list-detection.ts +32 -42
  356. package/src/utils/logger.ts +412 -404
  357. package/src/utils/parsingHelpers.ts +190 -190
  358. package/src/utils/stripTrackedChanges.ts +356 -353
  359. package/src/utils/textDiff.ts +100 -100
  360. package/src/utils/units.ts +421 -421
  361. package/src/utils/validation.ts +553 -542
  362. package/src/utils/xmlSanitization.ts +179 -182
  363. package/src/validation/RevisionAutoFixer.ts +541 -542
  364. package/src/validation/RevisionValidator.ts +470 -460
  365. package/src/validation/ValidationRules.ts +338 -338
  366. package/src/validation/index.ts +30 -30
  367. package/src/xml/XMLBuilder.ts +857 -871
  368. package/src/xml/XMLParser.ts +877 -919
  369. package/src/zip/ZipHandler.ts +629 -637
  370. package/src/zip/ZipReader.ts +295 -299
  371. package/src/zip/ZipWriter.ts +374 -390
  372. package/src/zip/types.ts +116 -116
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandling.js","sourceRoot":"","sources":["../../src/utils/errorHandling.ts"],"names":[],"mappings":";;AAUA,0BAEC;AAQD,0BAiBC;AASD,8BAUC;AASD,0CAcC;AArED,SAAgB,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC;AAQD,SAAgB,OAAO,CAAC,KAAc;IACpC,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAGD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC7D,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1C,CAAC;IAGD,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAClC,CAAC;AASD,SAAgB,SAAS,CAAC,KAAc,EAAE,OAAe;IACvD,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAGvE,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;QACxB,YAAY,CAAC,KAAK,GAAG,GAAG,YAAY,CAAC,OAAO,gBAAgB,aAAa,CAAC,KAAK,EAAE,CAAC;IACpF,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AASD,SAAgB,eAAe,CAAC,KAAc,EAAE,QAAQ,GAAG,wBAAwB;IACjF,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\r\n * Error handling utilities for consistent error processing\r\n * Ensures all caught errors are properly typed and handled\r\n */\r\n\r\n/**\r\n * Type guard to check if a value is an Error object\r\n * @param error - The value to check\r\n * @returns True if the value is an Error instance\r\n */\r\nexport function isError(error: unknown): error is Error {\r\n return error instanceof Error;\r\n}\r\n\r\n/**\r\n * Converts unknown error to Error object\r\n * Ensures we always have a proper Error with message property\r\n * @param error - The error to normalize (can be anything)\r\n * @returns Normalized Error object\r\n */\r\nexport function toError(error: unknown): Error {\r\n if (isError(error)) {\r\n return error;\r\n }\r\n\r\n // Handle string errors\r\n if (typeof error === 'string') {\r\n return new Error(error);\r\n }\r\n\r\n // Handle objects with message property\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return new Error(String(error.message));\r\n }\r\n\r\n // Fallback for any other type\r\n return new Error(String(error));\r\n}\r\n\r\n/**\r\n * Wraps an error with additional context\r\n * Useful for adding file paths, operation names, etc.\r\n * @param error - The original error\r\n * @param context - Additional context to prepend to error message\r\n * @returns New Error with combined message and original stack\r\n */\r\nexport function wrapError(error: unknown, context: string): Error {\r\n const originalError = toError(error);\r\n const wrappedError = new Error(`${context}: ${originalError.message}`);\r\n\r\n // Preserve original stack trace if available\r\n if (originalError.stack) {\r\n wrappedError.stack = `${wrappedError.message}\\nCaused by: ${originalError.stack}`;\r\n }\r\n\r\n return wrappedError;\r\n}\r\n\r\n/**\r\n * Safe error message extraction\r\n * Returns error message or generic fallback\r\n * @param error - The error to extract message from\r\n * @param fallback - Fallback message if extraction fails\r\n * @returns Error message string\r\n */\r\nexport function getErrorMessage(error: unknown, fallback = 'Unknown error occurred'): string {\r\n if (isError(error)) {\r\n return error.message;\r\n }\r\n\r\n if (typeof error === 'string') {\r\n return error;\r\n }\r\n\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return String(error.message);\r\n }\r\n\r\n return fallback;\r\n}\r\n"]}
1
+ {"version":3,"file":"errorHandling.js","sourceRoot":"","sources":["../../src/utils/errorHandling.ts"],"names":[],"mappings":";;AAUA,0BAEC;AAQD,0BAiBC;AASD,8BAUC;AASD,0CAcC;AArED,SAAgB,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC;AAQD,SAAgB,OAAO,CAAC,KAAc;IACpC,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAGD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC7D,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1C,CAAC;IAGD,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAClC,CAAC;AASD,SAAgB,SAAS,CAAC,KAAc,EAAE,OAAe;IACvD,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAGvE,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;QACxB,YAAY,CAAC,KAAK,GAAG,GAAG,YAAY,CAAC,OAAO,gBAAgB,aAAa,CAAC,KAAK,EAAE,CAAC;IACpF,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AASD,SAAgB,eAAe,CAAC,KAAc,EAAE,QAAQ,GAAG,wBAAwB;IACjF,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * Error handling utilities for consistent error processing\n * Ensures all caught errors are properly typed and handled\n */\n\n/**\n * Type guard to check if a value is an Error object\n * @param error - The value to check\n * @returns True if the value is an Error instance\n */\nexport function isError(error: unknown): error is Error {\n return error instanceof Error;\n}\n\n/**\n * Converts unknown error to Error object\n * Ensures we always have a proper Error with message property\n * @param error - The error to normalize (can be anything)\n * @returns Normalized Error object\n */\nexport function toError(error: unknown): Error {\n if (isError(error)) {\n return error;\n }\n\n // Handle string errors\n if (typeof error === 'string') {\n return new Error(error);\n }\n\n // Handle objects with message property\n if (error && typeof error === 'object' && 'message' in error) {\n return new Error(String(error.message));\n }\n\n // Fallback for any other type\n return new Error(String(error));\n}\n\n/**\n * Wraps an error with additional context\n * Useful for adding file paths, operation names, etc.\n * @param error - The original error\n * @param context - Additional context to prepend to error message\n * @returns New Error with combined message and original stack\n */\nexport function wrapError(error: unknown, context: string): Error {\n const originalError = toError(error);\n const wrappedError = new Error(`${context}: ${originalError.message}`);\n\n // Preserve original stack trace if available\n if (originalError.stack) {\n wrappedError.stack = `${wrappedError.message}\\nCaused by: ${originalError.stack}`;\n }\n\n return wrappedError;\n}\n\n/**\n * Safe error message extraction\n * Returns error message or generic fallback\n * @param error - The error to extract message from\n * @param fallback - Fallback message if extraction fails\n * @returns Error message string\n */\nexport function getErrorMessage(error: unknown, fallback = 'Unknown error occurred'): string {\n if (isError(error)) {\n return error.message;\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n if (error && typeof error === 'object' && 'message' in error) {\n return String(error.message);\n }\n\n return fallback;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../src/utils/formatting.ts"],"names":[],"mappings":"AAqBA,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3D,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GACnB,CAAC,CAmBH;AAgBD,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,CAEnD;AAeD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAO1E;AAgBD,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBxF;AAmBD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAsCT;AAiBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzD,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EACtB,QAAQ,EAAE,CAAC,GACV,CAAC,CAeH"}
1
+ {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../src/utils/formatting.ts"],"names":[],"mappings":"AAqBA,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAgB/F;AAgBD,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,CAEnD;AAeD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAO1E;AAgBD,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBxF;AAmBD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CA8CT;AAiBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzD,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EACtB,QAAQ,EAAE,CAAC,GACV,CAAC,CAoBH"}
@@ -66,7 +66,12 @@ function isEqualFormatting(format1, format2) {
66
66
  if ((val1 === undefined || val1 === null) !== (val2 === undefined || val2 === null)) {
67
67
  return false;
68
68
  }
69
- if (typeof val1 === 'object' && val1 !== null && typeof val2 === 'object' && val2 !== null && !Array.isArray(val1) && !Array.isArray(val2)) {
69
+ if (typeof val1 === 'object' &&
70
+ val1 !== null &&
71
+ typeof val2 === 'object' &&
72
+ val2 !== null &&
73
+ !Array.isArray(val1) &&
74
+ !Array.isArray(val2)) {
70
75
  if (!isEqualFormatting(val1, val2))
71
76
  return false;
72
77
  }
@@ -80,7 +85,10 @@ function applyDefaults(formatting, defaults) {
80
85
  const result = { ...defaults };
81
86
  for (const [key, value] of Object.entries(formatting)) {
82
87
  if (value !== undefined) {
83
- if (typeof value === 'object' && !Array.isArray(value) && value !== null && typeof defaults[key] === 'object') {
88
+ if (typeof value === 'object' &&
89
+ !Array.isArray(value) &&
90
+ value !== null &&
91
+ typeof defaults[key] === 'object') {
84
92
  result[key] = applyDefaults(value, defaults[key]);
85
93
  }
86
94
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"formatting.js","sourceRoot":"","sources":["../../src/utils/formatting.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Formatting utilities for deep merging and cloning formatting objects\r\n * Used for style inheritance and applying formatting\r\n */\r\n\r\n/**\r\n * Deep merges two formatting objects, with override taking precedence\r\n * Used for style inheritance and applying formatting\r\n *\r\n * @param base - Base formatting object\r\n * @param override - Override formatting object (takes precedence)\r\n * @returns Merged formatting object\r\n *\r\n * @example\r\n * ```typescript\r\n * const baseFormat = { bold: true, fontSize: 24 };\r\n * const overrideFormat = { fontSize: 28, italic: true };\r\n * const result = mergeFormatting(baseFormat, overrideFormat);\r\n * // Result: { bold: true, fontSize: 28, italic: true }\r\n * ```\r\n */\r\nexport function mergeFormatting<T extends Record<string, any>>(\r\n base: T,\r\n override: Partial<T>\r\n): T {\r\n const result = { ...base };\r\n\r\n for (const [key, value] of Object.entries(override)) {\r\n if (value === undefined) continue;\r\n\r\n if (typeof value === 'object' && !Array.isArray(value) && value !== null) {\r\n // Deep merge nested objects\r\n result[key as keyof T] = mergeFormatting(\r\n result[key as keyof T] || ({} as any),\r\n value\r\n );\r\n } else {\r\n // Direct assignment for primitives\r\n result[key as keyof T] = value;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Deep clones a formatting object\r\n * Creates a completely independent copy with no shared references\r\n *\r\n * @param formatting - Formatting object to clone\r\n * @returns Cloned formatting object\r\n *\r\n * @example\r\n * ```typescript\r\n * const original = { bold: true, indentation: { left: 100 } };\r\n * const cloned = cloneFormatting(original);\r\n * cloned.indentation.left = 200; // Doesn't affect original\r\n * ```\r\n */\r\nexport function cloneFormatting<T>(formatting: T): T {\r\n return JSON.parse(JSON.stringify(formatting));\r\n}\r\n\r\n/**\r\n * Checks if a formatting object has any defined properties\r\n *\r\n * @param formatting - Formatting object to check\r\n * @returns True if the object has at least one defined property\r\n *\r\n * @example\r\n * ```typescript\r\n * hasFormatting({}) // false\r\n * hasFormatting({ bold: true }) // true\r\n * hasFormatting({ bold: undefined }) // false\r\n * ```\r\n */\r\nexport function hasFormatting(formatting: Record<string, unknown>): boolean {\r\n for (const value of Object.values(formatting)) {\r\n if (value !== undefined && value !== null) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Removes undefined and null properties from a formatting object\r\n * Useful for cleaning up formatting before comparison or serialization\r\n *\r\n * @param formatting - Formatting object to clean\r\n * @returns Cleaned formatting object with no undefined/null values\r\n *\r\n * @example\r\n * ```typescript\r\n * const dirty = { bold: true, italic: undefined, fontSize: null, underline: false };\r\n * const clean = cleanFormatting(dirty);\r\n * // Result: { bold: true, underline: false }\r\n * ```\r\n */\r\nexport function cleanFormatting<T extends Record<string, any>>(formatting: T): Partial<T> {\r\n const cleaned: Partial<T> = {};\r\n\r\n for (const [key, value] of Object.entries(formatting)) {\r\n if (value !== undefined && value !== null) {\r\n if (typeof value === 'object' && !Array.isArray(value)) {\r\n // Recursively clean nested objects\r\n const cleanedNested = cleanFormatting(value);\r\n if (Object.keys(cleanedNested).length > 0) {\r\n cleaned[key as keyof T] = cleanedNested as any;\r\n }\r\n } else {\r\n cleaned[key as keyof T] = value;\r\n }\r\n }\r\n }\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Compares two formatting objects for equality\r\n * Performs deep comparison of all properties\r\n *\r\n * @param format1 - First formatting object\r\n * @param format2 - Second formatting object\r\n * @returns True if the formatting objects are equal\r\n *\r\n * @example\r\n * ```typescript\r\n * const a = { bold: true, fontSize: 24 };\r\n * const b = { bold: true, fontSize: 24 };\r\n * const c = { bold: true, fontSize: 28 };\r\n * isEqualFormatting(a, b) // true\r\n * isEqualFormatting(a, c) // false\r\n * ```\r\n */\r\nexport function isEqualFormatting(\r\n format1: Record<string, unknown>,\r\n format2: Record<string, unknown>\r\n): boolean {\r\n // Quick reference check\r\n if (format1 === format2) return true;\r\n\r\n // Null/undefined checks\r\n if (!format1 || !format2) return false;\r\n\r\n // Get all keys from both objects\r\n const keys1 = Object.keys(format1);\r\n const keys2 = Object.keys(format2);\r\n\r\n // Check if they have the same number of properties\r\n if (keys1.length !== keys2.length) return false;\r\n\r\n // Check all properties\r\n for (const key of keys1) {\r\n const val1 = format1[key];\r\n const val2 = format2[key];\r\n\r\n // Both undefined/null - considered equal\r\n if ((val1 === undefined || val1 === null) && (val2 === undefined || val2 === null)) {\r\n continue;\r\n }\r\n\r\n // One is undefined/null and the other isn't\r\n if ((val1 === undefined || val1 === null) !== (val2 === undefined || val2 === null)) {\r\n return false;\r\n }\r\n\r\n // Check nested objects\r\n if (typeof val1 === 'object' && val1 !== null && typeof val2 === 'object' && val2 !== null && !Array.isArray(val1) && !Array.isArray(val2)) {\r\n if (!isEqualFormatting(val1 as Record<string, unknown>, val2 as Record<string, unknown>)) return false;\r\n } else if (val1 !== val2) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Applies default values to a formatting object for any undefined properties\r\n *\r\n * @param formatting - Formatting object to apply defaults to\r\n * @param defaults - Default values\r\n * @returns Formatting object with defaults applied\r\n *\r\n * @example\r\n * ```typescript\r\n * const format = { bold: true };\r\n * const defaults = { bold: false, italic: false, fontSize: 24 };\r\n * const result = applyDefaults(format, defaults);\r\n * // Result: { bold: true, italic: false, fontSize: 24 }\r\n * ```\r\n */\r\nexport function applyDefaults<T extends Record<string, any>>(\r\n formatting: Partial<T>,\r\n defaults: T\r\n): T {\r\n const result = { ...defaults };\r\n\r\n for (const [key, value] of Object.entries(formatting)) {\r\n if (value !== undefined) {\r\n if (typeof value === 'object' && !Array.isArray(value) && value !== null && typeof defaults[key] === 'object') {\r\n // Deep merge nested objects\r\n result[key as keyof T] = applyDefaults(value, defaults[key]);\r\n } else {\r\n result[key as keyof T] = value;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n"]}
1
+ {"version":3,"file":"formatting.js","sourceRoot":"","sources":["../../src/utils/formatting.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Formatting utilities for deep merging and cloning formatting objects\n * Used for style inheritance and applying formatting\n */\n\n/**\n * Deep merges two formatting objects, with override taking precedence\n * Used for style inheritance and applying formatting\n *\n * @param base - Base formatting object\n * @param override - Override formatting object (takes precedence)\n * @returns Merged formatting object\n *\n * @example\n * ```typescript\n * const baseFormat = { bold: true, fontSize: 24 };\n * const overrideFormat = { fontSize: 28, italic: true };\n * const result = mergeFormatting(baseFormat, overrideFormat);\n * // Result: { bold: true, fontSize: 28, italic: true }\n * ```\n */\nexport function mergeFormatting<T extends Record<string, any>>(base: T, override: Partial<T>): T {\n const result = { ...base };\n\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n\n if (typeof value === 'object' && !Array.isArray(value) && value !== null) {\n // Deep merge nested objects\n result[key as keyof T] = mergeFormatting(result[key as keyof T] || ({} as any), value);\n } else {\n // Direct assignment for primitives\n result[key as keyof T] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Deep clones a formatting object\n * Creates a completely independent copy with no shared references\n *\n * @param formatting - Formatting object to clone\n * @returns Cloned formatting object\n *\n * @example\n * ```typescript\n * const original = { bold: true, indentation: { left: 100 } };\n * const cloned = cloneFormatting(original);\n * cloned.indentation.left = 200; // Doesn't affect original\n * ```\n */\nexport function cloneFormatting<T>(formatting: T): T {\n return JSON.parse(JSON.stringify(formatting));\n}\n\n/**\n * Checks if a formatting object has any defined properties\n *\n * @param formatting - Formatting object to check\n * @returns True if the object has at least one defined property\n *\n * @example\n * ```typescript\n * hasFormatting({}) // false\n * hasFormatting({ bold: true }) // true\n * hasFormatting({ bold: undefined }) // false\n * ```\n */\nexport function hasFormatting(formatting: Record<string, unknown>): boolean {\n for (const value of Object.values(formatting)) {\n if (value !== undefined && value !== null) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Removes undefined and null properties from a formatting object\n * Useful for cleaning up formatting before comparison or serialization\n *\n * @param formatting - Formatting object to clean\n * @returns Cleaned formatting object with no undefined/null values\n *\n * @example\n * ```typescript\n * const dirty = { bold: true, italic: undefined, fontSize: null, underline: false };\n * const clean = cleanFormatting(dirty);\n * // Result: { bold: true, underline: false }\n * ```\n */\nexport function cleanFormatting<T extends Record<string, any>>(formatting: T): Partial<T> {\n const cleaned: Partial<T> = {};\n\n for (const [key, value] of Object.entries(formatting)) {\n if (value !== undefined && value !== null) {\n if (typeof value === 'object' && !Array.isArray(value)) {\n // Recursively clean nested objects\n const cleanedNested = cleanFormatting(value);\n if (Object.keys(cleanedNested).length > 0) {\n cleaned[key as keyof T] = cleanedNested as any;\n }\n } else {\n cleaned[key as keyof T] = value;\n }\n }\n }\n\n return cleaned;\n}\n\n/**\n * Compares two formatting objects for equality\n * Performs deep comparison of all properties\n *\n * @param format1 - First formatting object\n * @param format2 - Second formatting object\n * @returns True if the formatting objects are equal\n *\n * @example\n * ```typescript\n * const a = { bold: true, fontSize: 24 };\n * const b = { bold: true, fontSize: 24 };\n * const c = { bold: true, fontSize: 28 };\n * isEqualFormatting(a, b) // true\n * isEqualFormatting(a, c) // false\n * ```\n */\nexport function isEqualFormatting(\n format1: Record<string, unknown>,\n format2: Record<string, unknown>\n): boolean {\n // Quick reference check\n if (format1 === format2) return true;\n\n // Null/undefined checks\n if (!format1 || !format2) return false;\n\n // Get all keys from both objects\n const keys1 = Object.keys(format1);\n const keys2 = Object.keys(format2);\n\n // Check if they have the same number of properties\n if (keys1.length !== keys2.length) return false;\n\n // Check all properties\n for (const key of keys1) {\n const val1 = format1[key];\n const val2 = format2[key];\n\n // Both undefined/null - considered equal\n if ((val1 === undefined || val1 === null) && (val2 === undefined || val2 === null)) {\n continue;\n }\n\n // One is undefined/null and the other isn't\n if ((val1 === undefined || val1 === null) !== (val2 === undefined || val2 === null)) {\n return false;\n }\n\n // Check nested objects\n if (\n typeof val1 === 'object' &&\n val1 !== null &&\n typeof val2 === 'object' &&\n val2 !== null &&\n !Array.isArray(val1) &&\n !Array.isArray(val2)\n ) {\n if (!isEqualFormatting(val1 as Record<string, unknown>, val2 as Record<string, unknown>))\n return false;\n } else if (val1 !== val2) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Applies default values to a formatting object for any undefined properties\n *\n * @param formatting - Formatting object to apply defaults to\n * @param defaults - Default values\n * @returns Formatting object with defaults applied\n *\n * @example\n * ```typescript\n * const format = { bold: true };\n * const defaults = { bold: false, italic: false, fontSize: 24 };\n * const result = applyDefaults(format, defaults);\n * // Result: { bold: true, italic: false, fontSize: 24 }\n * ```\n */\nexport function applyDefaults<T extends Record<string, any>>(\n formatting: Partial<T>,\n defaults: T\n): T {\n const result = { ...defaults };\n\n for (const [key, value] of Object.entries(formatting)) {\n if (value !== undefined) {\n if (\n typeof value === 'object' &&\n !Array.isArray(value) &&\n value !== null &&\n typeof defaults[key] === 'object'\n ) {\n // Deep merge nested objects\n result[key as keyof T] = applyDefaults(value, defaults[key]);\n } else {\n result[key as keyof T] = value;\n }\n }\n }\n\n return result;\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { Paragraph } from "../elements/Paragraph";
2
- import type { ListCategory, ListDetectionResult, NumberFormat, BulletFormat } from "../types/list-types";
1
+ import type { Paragraph } from '../elements/Paragraph';
2
+ import type { ListCategory, ListDetectionResult, NumberFormat, BulletFormat } from '../types/list-types';
3
3
  export declare const TYPED_LIST_PATTERNS: Record<string, RegExp>;
4
4
  export declare const PATTERN_TO_CATEGORY: Record<string, ListCategory>;
5
5
  export declare const FORMAT_TO_LEVEL: Record<string, number>;
@@ -1 +1 @@
1
- {"version":3,"file":"list-detection.d.ts","sourceRoot":"","sources":["../../src/utils/list-detection.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACb,MAAM,qBAAqB,CAAC;AAU7B,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWtD,CAAC;AAGF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAQ5D,CAAC;AASF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASlD,CAAC;AAMF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGhE;AAoBD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGrE;AAOD,wBAAgB,iCAAiC,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,CAGrF;AAWD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAC/C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,YAAY,GAAG,YAAY,GAAG,IAAI,CAAC;IAC3C,QAAQ,EAAE,YAAY,CAAC;CACxB,CAwBA;AAKD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAGpE;AAKD,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,mBAAmB,CA+CxE;AAMD,wBAAgB,oBAAoB,CAClC,UAAU,EAAE;IAAE,SAAS,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7D;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAqCxC;AAMD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,YAAY,CAgBd"}
1
+ {"version":3,"file":"list-detection.d.ts","sourceRoot":"","sources":["../../src/utils/list-detection.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACb,MAAM,qBAAqB,CAAC;AAU7B,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWtD,CAAC;AAGF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAQ5D,CAAC;AASF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASlD,CAAC;AAMF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGhE;AAoBD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGrE;AAOD,wBAAgB,iCAAiC,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,CAGrF;AAWD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAC/C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,YAAY,GAAG,YAAY,GAAG,IAAI,CAAC;IAC3C,QAAQ,EAAE,YAAY,CAAC;CACxB,CAwBA;AAKD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAGpE;AAKD,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,mBAAmB,CA+CxE;AAMD,wBAAgB,oBAAoB,CAClC,UAAU,EAAE;IAAE,SAAS,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7D;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAiCxC;AAMD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAYlF"}
@@ -19,13 +19,13 @@ exports.TYPED_LIST_PATTERNS = {
19
19
  arrow: /^[►▸▶→]\s+/,
20
20
  };
21
21
  exports.PATTERN_TO_CATEGORY = {
22
- decimal: "numbered",
23
- lowerLetter: "numbered",
24
- upperLetter: "numbered",
25
- lowerRoman: "numbered",
26
- bullet: "bullet",
27
- dash: "bullet",
28
- arrow: "bullet",
22
+ decimal: 'numbered',
23
+ lowerLetter: 'numbered',
24
+ upperLetter: 'numbered',
25
+ lowerRoman: 'numbered',
26
+ bullet: 'bullet',
27
+ dash: 'bullet',
28
+ arrow: 'bullet',
29
29
  };
30
30
  exports.FORMAT_TO_LEVEL = {
31
31
  decimal: 0,
@@ -58,7 +58,7 @@ function detectTypedPrefix(text) {
58
58
  for (const [format, regex] of Object.entries(exports.TYPED_LIST_PATTERNS)) {
59
59
  const match = text.match(regex);
60
60
  if (match) {
61
- if (format === "lowerLetter" || format === "upperLetter") {
61
+ if (format === 'lowerLetter' || format === 'upperLetter') {
62
62
  const remaining = text.substring(match[0].length);
63
63
  if (/^[A-Za-z]\./.test(remaining)) {
64
64
  continue;
@@ -67,11 +67,11 @@ function detectTypedPrefix(text) {
67
67
  return {
68
68
  prefix: match[0],
69
69
  format: format,
70
- category: exports.PATTERN_TO_CATEGORY[format] ?? "none",
70
+ category: exports.PATTERN_TO_CATEGORY[format] ?? 'none',
71
71
  };
72
72
  }
73
73
  }
74
- return { prefix: null, format: null, category: "none" };
74
+ return { prefix: null, format: null, category: 'none' };
75
75
  }
76
76
  function getParagraphIndentation(paragraph) {
77
77
  const formatting = paragraph.getFormatting();
@@ -83,7 +83,7 @@ function detectListType(paragraph) {
83
83
  const numbering = paragraph.getNumbering();
84
84
  if (numbering?.numId !== undefined && numbering.numId !== 0) {
85
85
  return {
86
- category: "numbered",
86
+ category: 'numbered',
87
87
  isWordList: true,
88
88
  typedPrefix: null,
89
89
  inferredLevel: numbering.level ?? 0,
@@ -107,7 +107,7 @@ function detectListType(paragraph) {
107
107
  };
108
108
  }
109
109
  return {
110
- category: "none",
110
+ category: 'none',
111
111
  isWordList: false,
112
112
  typedPrefix: null,
113
113
  inferredLevel: 0,
@@ -120,9 +120,9 @@ function detectListType(paragraph) {
120
120
  function validateListSequence(paragraphs) {
121
121
  const warnings = [];
122
122
  let lastDecimal = 0;
123
- let lastLetter = "";
123
+ let lastLetter = '';
124
124
  for (const { detection } of paragraphs) {
125
- if (!detection.typedPrefix || detection.category !== "numbered")
125
+ if (!detection.typedPrefix || detection.category !== 'numbered')
126
126
  continue;
127
127
  const match = /^(\d+|[a-zA-Z]+)/.exec(detection.typedPrefix);
128
128
  if (!match?.[1])
@@ -137,9 +137,7 @@ function validateListSequence(paragraphs) {
137
137
  }
138
138
  if (/^[a-z]$/i.test(marker)) {
139
139
  const letter = marker.toLowerCase();
140
- if (lastLetter &&
141
- letter.charCodeAt(0) !== lastLetter.charCodeAt(0) + 1 &&
142
- letter !== "a") {
140
+ if (lastLetter && letter.charCodeAt(0) !== lastLetter.charCodeAt(0) + 1 && letter !== 'a') {
143
141
  warnings.push(`Unexpected letter sequence: ${lastLetter} → ${letter}`);
144
142
  }
145
143
  lastLetter = letter;
@@ -149,13 +147,13 @@ function validateListSequence(paragraphs) {
149
147
  }
150
148
  function getListCategoryFromFormat(format) {
151
149
  if (!format)
152
- return "none";
153
- if (["bullet", "dash", "arrow"].includes(format)) {
154
- return "bullet";
150
+ return 'none';
151
+ if (['bullet', 'dash', 'arrow'].includes(format)) {
152
+ return 'bullet';
155
153
  }
156
- if (["decimal", "lowerLetter", "upperLetter", "lowerRoman", "upperRoman"].includes(format)) {
157
- return "numbered";
154
+ if (['decimal', 'lowerLetter', 'upperLetter', 'lowerRoman', 'upperRoman'].includes(format)) {
155
+ return 'numbered';
158
156
  }
159
- return "none";
157
+ return 'none';
160
158
  }
161
159
  //# sourceMappingURL=list-detection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-detection.js","sourceRoot":"","sources":["../../src/utils/list-detection.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * List Detection Utilities for docxmlater\n *\n * Provides functions to detect typed list prefixes and analyze\n * paragraph list properties.\n */\n\nimport type { Paragraph } from \"../elements/Paragraph\";\nimport type {\n ListCategory,\n ListDetectionResult,\n NumberFormat,\n BulletFormat,\n} from \"../types/list-types\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * Regex patterns for typed list prefixes.\n * Order matters: more specific patterns first.\n */\nexport const TYPED_LIST_PATTERNS: Record<string, RegExp> = {\n // Numbered patterns (capture the marker for validation)\n decimal: /^(\\d+)[.)]\\s+/,\n lowerLetter: /^([a-z])[.)]\\s+/,\n upperLetter: /^([A-Z])[.)]\\s+/,\n lowerRoman: /^((?:i{1,3}|iv|vi{0,3}|ix|x{1,3}))[.)]\\s+/i,\n\n // Bullet patterns\n bullet: /^[•●○◦▪■□]\\s+/,\n dash: /^[-–—]\\s+/,\n arrow: /^[►▸▶→]\\s+/,\n};\n\n/** Map pattern names to categories */\nexport const PATTERN_TO_CATEGORY: Record<string, ListCategory> = {\n decimal: \"numbered\",\n lowerLetter: \"numbered\",\n upperLetter: \"numbered\",\n lowerRoman: \"numbered\",\n bullet: \"bullet\",\n dash: \"bullet\",\n arrow: \"bullet\",\n};\n\n/**\n * Map typed prefix format to Word numbering level.\n * Word's default multilevel list uses:\n * Level 0: 1., 2., 3. (decimal)\n * Level 1: a., b., c. (lowerLetter)\n * Level 2: i., ii., iii. (lowerRoman)\n */\nexport const FORMAT_TO_LEVEL: Record<string, number> = {\n decimal: 0, // 1., 2., 3.\n lowerLetter: 1, // a., b., c.\n upperLetter: 1, // A., B., C.\n lowerRoman: 2, // i., ii., iii.\n upperRoman: 2, // I., II., III.\n bullet: 0, // Top-level bullet (filled circle)\n dash: 0, // Top-level dash marker\n arrow: 0, // Top-level arrow marker\n};\n\n/**\n * Get the Word numbering level for a given format.\n * Returns 0 (top level) for decimal or unknown formats.\n */\nexport function getLevelFromFormat(format: string | null): number {\n if (!format) return 0;\n return FORMAT_TO_LEVEL[format] ?? 0;\n}\n\n/**\n * Word standard indentation values in twips.\n * Level 0: 720 twips (0.5 inch) left indent\n * Level 1: 1080 twips (0.75 inch) left indent\n * Level 2: 1440 twips (1 inch) left indent\n * Each subsequent level adds 360 twips.\n */\nconst WORD_BASE_INDENT = 720;\nconst INDENT_PER_LEVEL = 360;\n\n// =============================================================================\n// CORE DETECTION FUNCTIONS\n// =============================================================================\n\n/**\n * Infer list level from indentation.\n * Uses standard Word indentation: 720 twips for level 0, +360 per level.\n */\nexport function inferLevelFromIndentation(indentTwips: number): number {\n if (indentTwips < WORD_BASE_INDENT) return 0;\n return Math.floor((indentTwips - WORD_BASE_INDENT) / INDENT_PER_LEVEL);\n}\n\n/**\n * Infer list level from relative indentation (baseline already subtracted).\n * Used when normalizing lists within a table cell where the baseline\n * indentation varies per cell.\n */\nexport function inferLevelFromRelativeIndentation(relativeIndentTwips: number): number {\n if (relativeIndentTwips <= 0) return 0;\n return Math.min(8, Math.floor(relativeIndentTwips / INDENT_PER_LEVEL));\n}\n\n/**\n * Detect typed list prefix in text.\n * Returns the matched prefix and format type.\n *\n * Special handling for abbreviations:\n * - Single letter prefixes (A., B., P.) are NOT treated as list markers\n * if the remaining text also starts with a letter+period pattern,\n * indicating an abbreviation like \"P.O. Box\", \"U.S. Army\", etc.\n */\nexport function detectTypedPrefix(text: string): {\n prefix: string | null;\n format: NumberFormat | BulletFormat | null;\n category: ListCategory;\n} {\n for (const [format, regex] of Object.entries(TYPED_LIST_PATTERNS)) {\n const match = text.match(regex);\n if (match) {\n // Special check for single-letter patterns (lowerLetter, upperLetter)\n // to avoid false positives on abbreviations like \"P.O. Box\", \"U.S.\", \"A.M.\"\n if (format === \"lowerLetter\" || format === \"upperLetter\") {\n const remaining = text.substring(match[0].length);\n // If remaining text starts with another letter followed by period,\n // this is likely an abbreviation, not a list marker\n if (/^[A-Za-z]\\./.test(remaining)) {\n continue; // Skip this pattern, try others\n }\n }\n\n return {\n prefix: match[0],\n format: format as NumberFormat | BulletFormat,\n category: PATTERN_TO_CATEGORY[format] ?? \"none\",\n };\n }\n }\n\n return { prefix: null, format: null, category: \"none\" };\n}\n\n/**\n * Get the left indentation from a paragraph in twips.\n */\nexport function getParagraphIndentation(paragraph: Paragraph): number {\n const formatting = paragraph.getFormatting();\n return formatting?.indentation?.left ?? 0;\n}\n\n/**\n * Main detection function: analyze a single paragraph for list properties.\n */\nexport function detectListType(paragraph: Paragraph): ListDetectionResult {\n const text = paragraph.getText();\n const indentation = getParagraphIndentation(paragraph);\n const numbering = paragraph.getNumbering();\n\n // Priority 1: Real Word list with <w:numPr>\n if (numbering?.numId !== undefined && numbering.numId !== 0) {\n return {\n category: \"numbered\", // Default, caller can refine with NumberingManager lookup\n isWordList: true,\n typedPrefix: null,\n inferredLevel: numbering.level ?? 0,\n format: null, // Would need numbering.xml lookup\n numId: numbering.numId,\n ilvl: numbering.level ?? 0,\n indentationTwips: indentation,\n };\n }\n\n // Priority 2: Typed prefix detection\n const typed = detectTypedPrefix(text);\n if (typed.prefix) {\n return {\n category: typed.category,\n isWordList: false,\n typedPrefix: typed.prefix,\n // Use FORMAT to determine level, not indentation!\n // decimal=0, lowerLetter=1, lowerRoman=2\n inferredLevel: getLevelFromFormat(typed.format),\n format: typed.format,\n numId: null,\n ilvl: null,\n indentationTwips: indentation,\n };\n }\n\n // Priority 3: Not a list\n return {\n category: \"none\",\n isWordList: false,\n typedPrefix: null,\n inferredLevel: 0,\n format: null,\n numId: null,\n ilvl: null,\n indentationTwips: indentation,\n };\n}\n\n/**\n * Validate that a typed prefix sequence is reasonable.\n * E.g., \"1. 2. 3.\" is valid, \"1. 5. 2.\" is suspicious.\n */\nexport function validateListSequence(\n paragraphs: { detection: ListDetectionResult; text: string }[]\n): { valid: boolean; warnings: string[] } {\n const warnings: string[] = [];\n let lastDecimal = 0;\n let lastLetter = \"\";\n\n for (const { detection } of paragraphs) {\n if (!detection.typedPrefix || detection.category !== \"numbered\") continue;\n\n const match = /^(\\d+|[a-zA-Z]+)/.exec(detection.typedPrefix);\n if (!match?.[1]) continue;\n\n const marker = match[1];\n\n // Check decimal sequence\n if (/^\\d+$/.test(marker)) {\n const num = parseInt(marker, 10);\n if (lastDecimal > 0 && num !== lastDecimal + 1 && num !== 1) {\n warnings.push(`Unexpected number sequence: ${lastDecimal} → ${num}`);\n }\n lastDecimal = num;\n }\n\n // Check letter sequence\n if (/^[a-z]$/i.test(marker)) {\n const letter = marker.toLowerCase();\n if (\n lastLetter &&\n letter.charCodeAt(0) !== lastLetter.charCodeAt(0) + 1 &&\n letter !== \"a\"\n ) {\n warnings.push(`Unexpected letter sequence: ${lastLetter} → ${letter}`);\n }\n lastLetter = letter;\n }\n }\n\n return { valid: warnings.length === 0, warnings };\n}\n\n/**\n * Determine the list category for a given numId by checking the abstractNum.\n * This requires access to the NumberingManager.\n */\nexport function getListCategoryFromFormat(\n format: string | undefined\n): ListCategory {\n if (!format) return \"none\";\n\n if ([\"bullet\", \"dash\", \"arrow\"].includes(format)) {\n return \"bullet\";\n }\n\n if (\n [\"decimal\", \"lowerLetter\", \"upperLetter\", \"lowerRoman\", \"upperRoman\"].includes(\n format\n )\n ) {\n return \"numbered\";\n }\n\n return \"none\";\n}\n"]}
1
+ {"version":3,"file":"list-detection.js","sourceRoot":"","sources":["../../src/utils/list-detection.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * List Detection Utilities for docxmlater\n *\n * Provides functions to detect typed list prefixes and analyze\n * paragraph list properties.\n */\n\nimport type { Paragraph } from '../elements/Paragraph';\nimport type {\n ListCategory,\n ListDetectionResult,\n NumberFormat,\n BulletFormat,\n} from '../types/list-types';\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * Regex patterns for typed list prefixes.\n * Order matters: more specific patterns first.\n */\nexport const TYPED_LIST_PATTERNS: Record<string, RegExp> = {\n // Numbered patterns (capture the marker for validation)\n decimal: /^(\\d+)[.)]\\s+/,\n lowerLetter: /^([a-z])[.)]\\s+/,\n upperLetter: /^([A-Z])[.)]\\s+/,\n lowerRoman: /^((?:i{1,3}|iv|vi{0,3}|ix|x{1,3}))[.)]\\s+/i,\n\n // Bullet patterns\n bullet: /^[•●○◦▪■□]\\s+/,\n dash: /^[-–—]\\s+/,\n arrow: /^[►▸▶→]\\s+/,\n};\n\n/** Map pattern names to categories */\nexport const PATTERN_TO_CATEGORY: Record<string, ListCategory> = {\n decimal: 'numbered',\n lowerLetter: 'numbered',\n upperLetter: 'numbered',\n lowerRoman: 'numbered',\n bullet: 'bullet',\n dash: 'bullet',\n arrow: 'bullet',\n};\n\n/**\n * Map typed prefix format to Word numbering level.\n * Word's default multilevel list uses:\n * Level 0: 1., 2., 3. (decimal)\n * Level 1: a., b., c. (lowerLetter)\n * Level 2: i., ii., iii. (lowerRoman)\n */\nexport const FORMAT_TO_LEVEL: Record<string, number> = {\n decimal: 0, // 1., 2., 3.\n lowerLetter: 1, // a., b., c.\n upperLetter: 1, // A., B., C.\n lowerRoman: 2, // i., ii., iii.\n upperRoman: 2, // I., II., III.\n bullet: 0, // Top-level bullet (filled circle)\n dash: 0, // Top-level dash marker\n arrow: 0, // Top-level arrow marker\n};\n\n/**\n * Get the Word numbering level for a given format.\n * Returns 0 (top level) for decimal or unknown formats.\n */\nexport function getLevelFromFormat(format: string | null): number {\n if (!format) return 0;\n return FORMAT_TO_LEVEL[format] ?? 0;\n}\n\n/**\n * Word standard indentation values in twips.\n * Level 0: 720 twips (0.5 inch) left indent\n * Level 1: 1080 twips (0.75 inch) left indent\n * Level 2: 1440 twips (1 inch) left indent\n * Each subsequent level adds 360 twips.\n */\nconst WORD_BASE_INDENT = 720;\nconst INDENT_PER_LEVEL = 360;\n\n// =============================================================================\n// CORE DETECTION FUNCTIONS\n// =============================================================================\n\n/**\n * Infer list level from indentation.\n * Uses standard Word indentation: 720 twips for level 0, +360 per level.\n */\nexport function inferLevelFromIndentation(indentTwips: number): number {\n if (indentTwips < WORD_BASE_INDENT) return 0;\n return Math.floor((indentTwips - WORD_BASE_INDENT) / INDENT_PER_LEVEL);\n}\n\n/**\n * Infer list level from relative indentation (baseline already subtracted).\n * Used when normalizing lists within a table cell where the baseline\n * indentation varies per cell.\n */\nexport function inferLevelFromRelativeIndentation(relativeIndentTwips: number): number {\n if (relativeIndentTwips <= 0) return 0;\n return Math.min(8, Math.floor(relativeIndentTwips / INDENT_PER_LEVEL));\n}\n\n/**\n * Detect typed list prefix in text.\n * Returns the matched prefix and format type.\n *\n * Special handling for abbreviations:\n * - Single letter prefixes (A., B., P.) are NOT treated as list markers\n * if the remaining text also starts with a letter+period pattern,\n * indicating an abbreviation like \"P.O. Box\", \"U.S. Army\", etc.\n */\nexport function detectTypedPrefix(text: string): {\n prefix: string | null;\n format: NumberFormat | BulletFormat | null;\n category: ListCategory;\n} {\n for (const [format, regex] of Object.entries(TYPED_LIST_PATTERNS)) {\n const match = text.match(regex);\n if (match) {\n // Special check for single-letter patterns (lowerLetter, upperLetter)\n // to avoid false positives on abbreviations like \"P.O. Box\", \"U.S.\", \"A.M.\"\n if (format === 'lowerLetter' || format === 'upperLetter') {\n const remaining = text.substring(match[0].length);\n // If remaining text starts with another letter followed by period,\n // this is likely an abbreviation, not a list marker\n if (/^[A-Za-z]\\./.test(remaining)) {\n continue; // Skip this pattern, try others\n }\n }\n\n return {\n prefix: match[0],\n format: format as NumberFormat | BulletFormat,\n category: PATTERN_TO_CATEGORY[format] ?? 'none',\n };\n }\n }\n\n return { prefix: null, format: null, category: 'none' };\n}\n\n/**\n * Get the left indentation from a paragraph in twips.\n */\nexport function getParagraphIndentation(paragraph: Paragraph): number {\n const formatting = paragraph.getFormatting();\n return formatting?.indentation?.left ?? 0;\n}\n\n/**\n * Main detection function: analyze a single paragraph for list properties.\n */\nexport function detectListType(paragraph: Paragraph): ListDetectionResult {\n const text = paragraph.getText();\n const indentation = getParagraphIndentation(paragraph);\n const numbering = paragraph.getNumbering();\n\n // Priority 1: Real Word list with <w:numPr>\n if (numbering?.numId !== undefined && numbering.numId !== 0) {\n return {\n category: 'numbered', // Default, caller can refine with NumberingManager lookup\n isWordList: true,\n typedPrefix: null,\n inferredLevel: numbering.level ?? 0,\n format: null, // Would need numbering.xml lookup\n numId: numbering.numId,\n ilvl: numbering.level ?? 0,\n indentationTwips: indentation,\n };\n }\n\n // Priority 2: Typed prefix detection\n const typed = detectTypedPrefix(text);\n if (typed.prefix) {\n return {\n category: typed.category,\n isWordList: false,\n typedPrefix: typed.prefix,\n // Use FORMAT to determine level, not indentation!\n // decimal=0, lowerLetter=1, lowerRoman=2\n inferredLevel: getLevelFromFormat(typed.format),\n format: typed.format,\n numId: null,\n ilvl: null,\n indentationTwips: indentation,\n };\n }\n\n // Priority 3: Not a list\n return {\n category: 'none',\n isWordList: false,\n typedPrefix: null,\n inferredLevel: 0,\n format: null,\n numId: null,\n ilvl: null,\n indentationTwips: indentation,\n };\n}\n\n/**\n * Validate that a typed prefix sequence is reasonable.\n * E.g., \"1. 2. 3.\" is valid, \"1. 5. 2.\" is suspicious.\n */\nexport function validateListSequence(\n paragraphs: { detection: ListDetectionResult; text: string }[]\n): { valid: boolean; warnings: string[] } {\n const warnings: string[] = [];\n let lastDecimal = 0;\n let lastLetter = '';\n\n for (const { detection } of paragraphs) {\n if (!detection.typedPrefix || detection.category !== 'numbered') continue;\n\n const match = /^(\\d+|[a-zA-Z]+)/.exec(detection.typedPrefix);\n if (!match?.[1]) continue;\n\n const marker = match[1];\n\n // Check decimal sequence\n if (/^\\d+$/.test(marker)) {\n const num = parseInt(marker, 10);\n if (lastDecimal > 0 && num !== lastDecimal + 1 && num !== 1) {\n warnings.push(`Unexpected number sequence: ${lastDecimal} → ${num}`);\n }\n lastDecimal = num;\n }\n\n // Check letter sequence\n if (/^[a-z]$/i.test(marker)) {\n const letter = marker.toLowerCase();\n if (lastLetter && letter.charCodeAt(0) !== lastLetter.charCodeAt(0) + 1 && letter !== 'a') {\n warnings.push(`Unexpected letter sequence: ${lastLetter} → ${letter}`);\n }\n lastLetter = letter;\n }\n }\n\n return { valid: warnings.length === 0, warnings };\n}\n\n/**\n * Determine the list category for a given numId by checking the abstractNum.\n * This requires access to the NumberingManager.\n */\nexport function getListCategoryFromFormat(format: string | undefined): ListCategory {\n if (!format) return 'none';\n\n if (['bullet', 'dash', 'arrow'].includes(format)) {\n return 'bullet';\n }\n\n if (['decimal', 'lowerLetter', 'upperLetter', 'lowerRoman', 'upperRoman'].includes(format)) {\n return 'numbered';\n }\n\n return 'none';\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
@@ -125,14 +125,14 @@ class CollectingLogger {
125
125
  return [...this.logs];
126
126
  }
127
127
  getLogsByLevel(level) {
128
- return this.logs.filter(log => log.level === level);
128
+ return this.logs.filter((log) => log.level === level);
129
129
  }
130
130
  clear() {
131
131
  this.logs = [];
132
132
  }
133
133
  getCount(level) {
134
134
  if (level) {
135
- return this.logs.filter(log => log.level === level).length;
135
+ return this.logs.filter((log) => log.level === level).length;
136
136
  }
137
137
  return this.logs.length;
138
138
  }
@@ -173,11 +173,16 @@ function parseLogLevel(level) {
173
173
  return undefined;
174
174
  const normalized = level.toLowerCase();
175
175
  switch (normalized) {
176
- case 'debug': return LogLevel.DEBUG;
177
- case 'info': return LogLevel.INFO;
178
- case 'warn': return LogLevel.WARN;
179
- case 'error': return LogLevel.ERROR;
180
- default: return undefined;
176
+ case 'debug':
177
+ return LogLevel.DEBUG;
178
+ case 'info':
179
+ return LogLevel.INFO;
180
+ case 'warn':
181
+ return LogLevel.WARN;
182
+ case 'error':
183
+ return LogLevel.ERROR;
184
+ default:
185
+ return undefined;
181
186
  }
182
187
  }
183
188
  function createLoggerFromEnv() {
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Logging interface for docXMLater\r\n * Allows library consumers to control logging behavior\r\n */\r\n\r\n/**\r\n * Log severity levels\r\n */\r\nexport enum LogLevel {\r\n /** Debugging information (most verbose) */\r\n DEBUG = 'debug',\r\n /** Informational messages */\r\n INFO = 'info',\r\n /** Warning messages - potential issues that don't prevent operation */\r\n WARN = 'warn',\r\n /** Error messages - serious issues that may cause failures */\r\n ERROR = 'error',\r\n}\r\n\r\n/**\r\n * Log entry structure\r\n */\r\nexport interface LogEntry {\r\n /** Timestamp when log was created */\r\n timestamp: Date;\r\n /** Severity level */\r\n level: LogLevel;\r\n /** Log message */\r\n message: string;\r\n /** Optional context data */\r\n context?: Record<string, any>;\r\n /** Source component that generated the log */\r\n source?: string;\r\n}\r\n\r\n/**\r\n * Logger interface that consumers can implement\r\n * Provides full control over how logs are handled\r\n */\r\nexport interface ILogger {\r\n /**\r\n * Log a debug message\r\n * @param message - Debug message\r\n * @param context - Optional context data\r\n */\r\n debug(message: string, context?: Record<string, any>): void;\r\n\r\n /**\r\n * Log an informational message\r\n * @param message - Info message\r\n * @param context - Optional context data\r\n */\r\n info(message: string, context?: Record<string, any>): void;\r\n\r\n /**\r\n * Log a warning message\r\n * @param message - Warning message\r\n * @param context - Optional context data\r\n */\r\n warn(message: string, context?: Record<string, any>): void;\r\n\r\n /**\r\n * Log an error message\r\n * @param message - Error message\r\n * @param context - Optional context data\r\n */\r\n error(message: string, context?: Record<string, any>): void;\r\n}\r\n\r\n/**\r\n * Console-based logger implementation\r\n * Uses standard console methods for output with timestamps and source prefixes\r\n */\r\nexport class ConsoleLogger implements ILogger {\r\n private showTimestamp: boolean;\r\n\r\n constructor(private minLevel: LogLevel = LogLevel.WARN, options?: { showTimestamp?: boolean }) {\r\n this.showTimestamp = options?.showTimestamp ?? true;\r\n }\r\n\r\n debug(message: string, context?: Record<string, any>): void {\r\n if (this.shouldLog(LogLevel.DEBUG)) {\r\n console.debug(this.formatMessage(LogLevel.DEBUG, message, context));\r\n }\r\n }\r\n\r\n info(message: string, context?: Record<string, any>): void {\r\n if (this.shouldLog(LogLevel.INFO)) {\r\n console.info(this.formatMessage(LogLevel.INFO, message, context));\r\n }\r\n }\r\n\r\n warn(message: string, context?: Record<string, any>): void {\r\n if (this.shouldLog(LogLevel.WARN)) {\r\n console.warn(this.formatMessage(LogLevel.WARN, message, context));\r\n }\r\n }\r\n\r\n error(message: string, context?: Record<string, any>): void {\r\n if (this.shouldLog(LogLevel.ERROR)) {\r\n console.error(this.formatMessage(LogLevel.ERROR, message, context));\r\n }\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n const levels = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR];\r\n const minIndex = levels.indexOf(this.minLevel);\r\n const currentIndex = levels.indexOf(level);\r\n return currentIndex >= minIndex;\r\n }\r\n\r\n private formatMessage(level: LogLevel, message: string, context?: Record<string, any>): string {\r\n const parts: string[] = [];\r\n\r\n // Add timestamp if enabled\r\n if (this.showTimestamp) {\r\n const timestamp = new Date().toISOString().slice(11, 23); // HH:mm:ss.SSS\r\n parts.push(timestamp);\r\n }\r\n\r\n // Add level tag\r\n parts.push(`[${level.toUpperCase().padEnd(5)}]`);\r\n\r\n // Add source if present\r\n if (context?.source) {\r\n parts.push(`[${context.source}]`);\r\n }\r\n\r\n // Add message\r\n parts.push(message);\r\n\r\n // Add context (excluding source which is already shown)\r\n if (context && Object.keys(context).length > 0) {\r\n const contextWithoutSource = { ...context };\r\n delete contextWithoutSource.source;\r\n if (Object.keys(contextWithoutSource).length > 0) {\r\n // Format context as key=value pairs for readability\r\n const contextStr = this.formatContext(contextWithoutSource);\r\n if (contextStr) {\r\n parts.push(contextStr);\r\n }\r\n }\r\n }\r\n\r\n return parts.join(' ');\r\n }\r\n\r\n private formatContext(context: Record<string, any>): string {\r\n const pairs: string[] = [];\r\n for (const [key, value] of Object.entries(context)) {\r\n if (value === undefined || value === null) continue;\r\n if (typeof value === 'object' && !Array.isArray(value)) {\r\n // Nested object - use compact JSON\r\n pairs.push(`${key}=${JSON.stringify(value)}`);\r\n } else if (Array.isArray(value)) {\r\n pairs.push(`${key}=[${value.length}]`);\r\n } else {\r\n pairs.push(`${key}=${value}`);\r\n }\r\n }\r\n return pairs.length > 0 ? pairs.join(' ') : '';\r\n }\r\n}\r\n\r\n/**\r\n * Silent logger that discards all log messages\r\n * Useful for testing or when logging is not desired\r\n */\r\nexport class SilentLogger implements ILogger {\r\n debug(): void {\r\n // No-op\r\n }\r\n\r\n info(): void {\r\n // No-op\r\n }\r\n\r\n warn(): void {\r\n // No-op\r\n }\r\n\r\n error(): void {\r\n // No-op\r\n }\r\n}\r\n\r\n/**\r\n * Collecting logger that stores log entries in memory\r\n * Useful for testing and diagnostics\r\n */\r\nexport class CollectingLogger implements ILogger {\r\n private logs: LogEntry[] = [];\r\n\r\n debug(message: string, context?: Record<string, any>): void {\r\n this.addLog(LogLevel.DEBUG, message, context);\r\n }\r\n\r\n info(message: string, context?: Record<string, any>): void {\r\n this.addLog(LogLevel.INFO, message, context);\r\n }\r\n\r\n warn(message: string, context?: Record<string, any>): void {\r\n this.addLog(LogLevel.WARN, message, context);\r\n }\r\n\r\n error(message: string, context?: Record<string, any>): void {\r\n this.addLog(LogLevel.ERROR, message, context);\r\n }\r\n\r\n private addLog(level: LogLevel, message: string, context?: Record<string, any>): void {\r\n this.logs.push({\r\n timestamp: new Date(),\r\n level,\r\n message,\r\n context,\r\n });\r\n }\r\n\r\n /**\r\n * Get all collected log entries\r\n */\r\n getLogs(): readonly LogEntry[] {\r\n return [...this.logs];\r\n }\r\n\r\n /**\r\n * Get logs filtered by level\r\n */\r\n getLogsByLevel(level: LogLevel): readonly LogEntry[] {\r\n return this.logs.filter(log => log.level === level);\r\n }\r\n\r\n /**\r\n * Clear all collected logs\r\n */\r\n clear(): void {\r\n this.logs = [];\r\n }\r\n\r\n /**\r\n * Get count of logs by level\r\n */\r\n getCount(level?: LogLevel): number {\r\n if (level) {\r\n return this.logs.filter(log => log.level === level).length;\r\n }\r\n return this.logs.length;\r\n }\r\n}\r\n\r\n/**\r\n * Default logger instance\r\n * Delegates to the global logger, respecting setGlobalLogger() and environment variables\r\n */\r\nexport const defaultLogger: ILogger = {\r\n debug(message: string, context?: Record<string, any>): void {\r\n getGlobalLogger().debug(message, context);\r\n },\r\n info(message: string, context?: Record<string, any>): void {\r\n getGlobalLogger().info(message, context);\r\n },\r\n warn(message: string, context?: Record<string, any>): void {\r\n getGlobalLogger().warn(message, context);\r\n },\r\n error(message: string, context?: Record<string, any>): void {\r\n getGlobalLogger().error(message, context);\r\n },\r\n};\r\n\r\n/**\r\n * Creates a scoped logger that adds source information\r\n * @param logger - Base logger\r\n * @param source - Source component name\r\n * @returns Scoped logger with source context\r\n */\r\nexport function createScopedLogger(logger: ILogger, source: string): ILogger {\r\n return {\r\n debug(message: string, context?: Record<string, any>): void {\r\n logger.debug(message, { ...context, source });\r\n },\r\n info(message: string, context?: Record<string, any>): void {\r\n logger.info(message, { ...context, source });\r\n },\r\n warn(message: string, context?: Record<string, any>): void {\r\n logger.warn(message, { ...context, source });\r\n },\r\n error(message: string, context?: Record<string, any>): void {\r\n logger.error(message, { ...context, source });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Parse log level from string\r\n * @param level - Log level string (case-insensitive)\r\n * @returns LogLevel or undefined if invalid\r\n */\r\nfunction parseLogLevel(level: string | undefined): LogLevel | undefined {\r\n if (!level) return undefined;\r\n const normalized = level.toLowerCase();\r\n switch (normalized) {\r\n case 'debug': return LogLevel.DEBUG;\r\n case 'info': return LogLevel.INFO;\r\n case 'warn': return LogLevel.WARN;\r\n case 'error': return LogLevel.ERROR;\r\n default: return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Create a logger based on environment variables\r\n *\r\n * Environment variables (in order of precedence):\r\n * - DEBUG=docxmlater or DEBUG=docxmlater:* - Enables DEBUG level\r\n * - DOCXMLATER_LOG_LEVEL=debug|info|warn|error|silent - Sets specific level\r\n *\r\n * @returns Logger configured from environment, or SilentLogger if not configured\r\n */\r\nfunction createLoggerFromEnv(): ILogger {\r\n // Check DEBUG environment variable first (highest precedence for debug mode)\r\n const debugEnv = process.env.DEBUG || '';\r\n if (debugEnv.includes('docxmlater')) {\r\n return new ConsoleLogger(LogLevel.DEBUG);\r\n }\r\n\r\n // Check DOCXMLATER_LOG_LEVEL environment variable\r\n const envLevel = process.env.DOCXMLATER_LOG_LEVEL?.toLowerCase();\r\n if (envLevel === 'silent') {\r\n return new SilentLogger();\r\n }\r\n\r\n const parsedLevel = parseLogLevel(envLevel);\r\n if (parsedLevel) {\r\n return new ConsoleLogger(parsedLevel);\r\n }\r\n\r\n // Default: silent (no logging unless explicitly enabled)\r\n return new SilentLogger();\r\n}\r\n\r\n// Global logger instance - initialized from environment\r\nlet globalLogger: ILogger = createLoggerFromEnv();\r\n\r\n/**\r\n * Set the global logger instance\r\n * Use this to configure logging programmatically\r\n *\r\n * @example\r\n * ```typescript\r\n * import { setGlobalLogger, ConsoleLogger, LogLevel } from 'docxmlater';\r\n *\r\n * // Enable info-level logging\r\n * setGlobalLogger(new ConsoleLogger(LogLevel.INFO));\r\n * ```\r\n *\r\n * @param logger - Logger instance to use globally\r\n */\r\nexport function setGlobalLogger(logger: ILogger): void {\r\n globalLogger = logger;\r\n}\r\n\r\n/**\r\n * Get the global logger instance\r\n * Used internally by framework components\r\n *\r\n * @returns Current global logger\r\n */\r\nexport function getGlobalLogger(): ILogger {\r\n return globalLogger;\r\n}\r\n\r\n/**\r\n * Reset the global logger to its default (environment-based) configuration\r\n * Useful for testing cleanup\r\n */\r\nexport function resetGlobalLogger(): void {\r\n globalLogger = createLoggerFromEnv();\r\n}\r\n\r\n/**\r\n * Creates a component-scoped logger using the global logger.\r\n * This is a convenience function that combines getGlobalLogger() and createScopedLogger()\r\n * into a single call, reducing boilerplate in component files.\r\n *\r\n * @param componentName - Name of the component (appears in log output)\r\n * @returns Scoped logger instance\r\n *\r\n * @example\r\n * ```typescript\r\n * // Instead of:\r\n * function getLogger(): ILogger {\r\n * return createScopedLogger(getGlobalLogger(), 'MyComponent');\r\n * }\r\n *\r\n * // You can use:\r\n * const logger = createComponentLogger('MyComponent');\r\n *\r\n * // Or for lazy initialization:\r\n * const getLogger = () => createComponentLogger('MyComponent');\r\n * ```\r\n */\r\nexport function createComponentLogger(componentName: string): ILogger {\r\n return createScopedLogger(getGlobalLogger(), componentName);\r\n}\r\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Logging interface for docXMLater\n * Allows library consumers to control logging behavior\n */\n\n/**\n * Log severity levels\n */\nexport enum LogLevel {\n /** Debugging information (most verbose) */\n DEBUG = 'debug',\n /** Informational messages */\n INFO = 'info',\n /** Warning messages - potential issues that don't prevent operation */\n WARN = 'warn',\n /** Error messages - serious issues that may cause failures */\n ERROR = 'error',\n}\n\n/**\n * Log entry structure\n */\nexport interface LogEntry {\n /** Timestamp when log was created */\n timestamp: Date;\n /** Severity level */\n level: LogLevel;\n /** Log message */\n message: string;\n /** Optional context data */\n context?: Record<string, any>;\n /** Source component that generated the log */\n source?: string;\n}\n\n/**\n * Logger interface that consumers can implement\n * Provides full control over how logs are handled\n */\nexport interface ILogger {\n /**\n * Log a debug message\n * @param message - Debug message\n * @param context - Optional context data\n */\n debug(message: string, context?: Record<string, any>): void;\n\n /**\n * Log an informational message\n * @param message - Info message\n * @param context - Optional context data\n */\n info(message: string, context?: Record<string, any>): void;\n\n /**\n * Log a warning message\n * @param message - Warning message\n * @param context - Optional context data\n */\n warn(message: string, context?: Record<string, any>): void;\n\n /**\n * Log an error message\n * @param message - Error message\n * @param context - Optional context data\n */\n error(message: string, context?: Record<string, any>): void;\n}\n\n/**\n * Console-based logger implementation\n * Uses standard console methods for output with timestamps and source prefixes\n */\nexport class ConsoleLogger implements ILogger {\n private showTimestamp: boolean;\n\n constructor(\n private minLevel: LogLevel = LogLevel.WARN,\n options?: { showTimestamp?: boolean }\n ) {\n this.showTimestamp = options?.showTimestamp ?? true;\n }\n\n debug(message: string, context?: Record<string, any>): void {\n if (this.shouldLog(LogLevel.DEBUG)) {\n console.debug(this.formatMessage(LogLevel.DEBUG, message, context));\n }\n }\n\n info(message: string, context?: Record<string, any>): void {\n if (this.shouldLog(LogLevel.INFO)) {\n console.info(this.formatMessage(LogLevel.INFO, message, context));\n }\n }\n\n warn(message: string, context?: Record<string, any>): void {\n if (this.shouldLog(LogLevel.WARN)) {\n console.warn(this.formatMessage(LogLevel.WARN, message, context));\n }\n }\n\n error(message: string, context?: Record<string, any>): void {\n if (this.shouldLog(LogLevel.ERROR)) {\n console.error(this.formatMessage(LogLevel.ERROR, message, context));\n }\n }\n\n private shouldLog(level: LogLevel): boolean {\n const levels = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR];\n const minIndex = levels.indexOf(this.minLevel);\n const currentIndex = levels.indexOf(level);\n return currentIndex >= minIndex;\n }\n\n private formatMessage(level: LogLevel, message: string, context?: Record<string, any>): string {\n const parts: string[] = [];\n\n // Add timestamp if enabled\n if (this.showTimestamp) {\n const timestamp = new Date().toISOString().slice(11, 23); // HH:mm:ss.SSS\n parts.push(timestamp);\n }\n\n // Add level tag\n parts.push(`[${level.toUpperCase().padEnd(5)}]`);\n\n // Add source if present\n if (context?.source) {\n parts.push(`[${context.source}]`);\n }\n\n // Add message\n parts.push(message);\n\n // Add context (excluding source which is already shown)\n if (context && Object.keys(context).length > 0) {\n const contextWithoutSource = { ...context };\n delete contextWithoutSource.source;\n if (Object.keys(contextWithoutSource).length > 0) {\n // Format context as key=value pairs for readability\n const contextStr = this.formatContext(contextWithoutSource);\n if (contextStr) {\n parts.push(contextStr);\n }\n }\n }\n\n return parts.join(' ');\n }\n\n private formatContext(context: Record<string, any>): string {\n const pairs: string[] = [];\n for (const [key, value] of Object.entries(context)) {\n if (value === undefined || value === null) continue;\n if (typeof value === 'object' && !Array.isArray(value)) {\n // Nested object - use compact JSON\n pairs.push(`${key}=${JSON.stringify(value)}`);\n } else if (Array.isArray(value)) {\n pairs.push(`${key}=[${value.length}]`);\n } else {\n pairs.push(`${key}=${value}`);\n }\n }\n return pairs.length > 0 ? pairs.join(' ') : '';\n }\n}\n\n/**\n * Silent logger that discards all log messages\n * Useful for testing or when logging is not desired\n */\nexport class SilentLogger implements ILogger {\n debug(): void {\n // No-op\n }\n\n info(): void {\n // No-op\n }\n\n warn(): void {\n // No-op\n }\n\n error(): void {\n // No-op\n }\n}\n\n/**\n * Collecting logger that stores log entries in memory\n * Useful for testing and diagnostics\n */\nexport class CollectingLogger implements ILogger {\n private logs: LogEntry[] = [];\n\n debug(message: string, context?: Record<string, any>): void {\n this.addLog(LogLevel.DEBUG, message, context);\n }\n\n info(message: string, context?: Record<string, any>): void {\n this.addLog(LogLevel.INFO, message, context);\n }\n\n warn(message: string, context?: Record<string, any>): void {\n this.addLog(LogLevel.WARN, message, context);\n }\n\n error(message: string, context?: Record<string, any>): void {\n this.addLog(LogLevel.ERROR, message, context);\n }\n\n private addLog(level: LogLevel, message: string, context?: Record<string, any>): void {\n this.logs.push({\n timestamp: new Date(),\n level,\n message,\n context,\n });\n }\n\n /**\n * Get all collected log entries\n */\n getLogs(): readonly LogEntry[] {\n return [...this.logs];\n }\n\n /**\n * Get logs filtered by level\n */\n getLogsByLevel(level: LogLevel): readonly LogEntry[] {\n return this.logs.filter((log) => log.level === level);\n }\n\n /**\n * Clear all collected logs\n */\n clear(): void {\n this.logs = [];\n }\n\n /**\n * Get count of logs by level\n */\n getCount(level?: LogLevel): number {\n if (level) {\n return this.logs.filter((log) => log.level === level).length;\n }\n return this.logs.length;\n }\n}\n\n/**\n * Default logger instance\n * Delegates to the global logger, respecting setGlobalLogger() and environment variables\n */\nexport const defaultLogger: ILogger = {\n debug(message: string, context?: Record<string, any>): void {\n getGlobalLogger().debug(message, context);\n },\n info(message: string, context?: Record<string, any>): void {\n getGlobalLogger().info(message, context);\n },\n warn(message: string, context?: Record<string, any>): void {\n getGlobalLogger().warn(message, context);\n },\n error(message: string, context?: Record<string, any>): void {\n getGlobalLogger().error(message, context);\n },\n};\n\n/**\n * Creates a scoped logger that adds source information\n * @param logger - Base logger\n * @param source - Source component name\n * @returns Scoped logger with source context\n */\nexport function createScopedLogger(logger: ILogger, source: string): ILogger {\n return {\n debug(message: string, context?: Record<string, any>): void {\n logger.debug(message, { ...context, source });\n },\n info(message: string, context?: Record<string, any>): void {\n logger.info(message, { ...context, source });\n },\n warn(message: string, context?: Record<string, any>): void {\n logger.warn(message, { ...context, source });\n },\n error(message: string, context?: Record<string, any>): void {\n logger.error(message, { ...context, source });\n },\n };\n}\n\n/**\n * Parse log level from string\n * @param level - Log level string (case-insensitive)\n * @returns LogLevel or undefined if invalid\n */\nfunction parseLogLevel(level: string | undefined): LogLevel | undefined {\n if (!level) return undefined;\n const normalized = level.toLowerCase();\n switch (normalized) {\n case 'debug':\n return LogLevel.DEBUG;\n case 'info':\n return LogLevel.INFO;\n case 'warn':\n return LogLevel.WARN;\n case 'error':\n return LogLevel.ERROR;\n default:\n return undefined;\n }\n}\n\n/**\n * Create a logger based on environment variables\n *\n * Environment variables (in order of precedence):\n * - DEBUG=docxmlater or DEBUG=docxmlater:* - Enables DEBUG level\n * - DOCXMLATER_LOG_LEVEL=debug|info|warn|error|silent - Sets specific level\n *\n * @returns Logger configured from environment, or SilentLogger if not configured\n */\nfunction createLoggerFromEnv(): ILogger {\n // Check DEBUG environment variable first (highest precedence for debug mode)\n const debugEnv = process.env.DEBUG || '';\n if (debugEnv.includes('docxmlater')) {\n return new ConsoleLogger(LogLevel.DEBUG);\n }\n\n // Check DOCXMLATER_LOG_LEVEL environment variable\n const envLevel = process.env.DOCXMLATER_LOG_LEVEL?.toLowerCase();\n if (envLevel === 'silent') {\n return new SilentLogger();\n }\n\n const parsedLevel = parseLogLevel(envLevel);\n if (parsedLevel) {\n return new ConsoleLogger(parsedLevel);\n }\n\n // Default: silent (no logging unless explicitly enabled)\n return new SilentLogger();\n}\n\n// Global logger instance - initialized from environment\nlet globalLogger: ILogger = createLoggerFromEnv();\n\n/**\n * Set the global logger instance\n * Use this to configure logging programmatically\n *\n * @example\n * ```typescript\n * import { setGlobalLogger, ConsoleLogger, LogLevel } from 'docxmlater';\n *\n * // Enable info-level logging\n * setGlobalLogger(new ConsoleLogger(LogLevel.INFO));\n * ```\n *\n * @param logger - Logger instance to use globally\n */\nexport function setGlobalLogger(logger: ILogger): void {\n globalLogger = logger;\n}\n\n/**\n * Get the global logger instance\n * Used internally by framework components\n *\n * @returns Current global logger\n */\nexport function getGlobalLogger(): ILogger {\n return globalLogger;\n}\n\n/**\n * Reset the global logger to its default (environment-based) configuration\n * Useful for testing cleanup\n */\nexport function resetGlobalLogger(): void {\n globalLogger = createLoggerFromEnv();\n}\n\n/**\n * Creates a component-scoped logger using the global logger.\n * This is a convenience function that combines getGlobalLogger() and createScopedLogger()\n * into a single call, reducing boilerplate in component files.\n *\n * @param componentName - Name of the component (appears in log output)\n * @returns Scoped logger instance\n *\n * @example\n * ```typescript\n * // Instead of:\n * function getLogger(): ILogger {\n * return createScopedLogger(getGlobalLogger(), 'MyComponent');\n * }\n *\n * // You can use:\n * const logger = createComponentLogger('MyComponent');\n *\n * // Or for lazy initialization:\n * const getLogger = () => createComponentLogger('MyComponent');\n * ```\n */\nexport function createComponentLogger(componentName: string): ILogger {\n return createScopedLogger(getGlobalLogger(), componentName);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"parsingHelpers.js","sourceRoot":"","sources":["../../src/utils/parsingHelpers.ts"],"names":[],"mappings":";;AA4BA,oCAYC;AA+BD,8CAiCC;AA0BD,0CAEC;AAkBD,sDAKC;AAeD,kDAmBC;AAjKD,SAAgB,YAAY,CAAC,KAAc,EAAE,YAAY,GAAG,CAAC;IAC3D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,YAAY,CAAC;IACtB,CAAC;IAGD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/C,CAAC;AA+BD,SAAgB,iBAAiB,CAAC,IAAa;IAE7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,MAAM,GAAG,GAAI,IAAgC,CAAC,SAAS,CAAC,CAAC;IAIzD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,OAAO,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,IAAI,CAAC;IACtE,CAAC;IAGD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,KAAK,CAAC,CAAC;IACnB,CAAC;IAGD,IAAI,OAAO,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IAGD,OAAO,KAAK,CAAC;AACf,CAAC;AA0BD,SAAgB,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;AAC/C,CAAC;AAkBD,SAAgB,qBAAqB,CAAC,KAAc,EAAE,YAAoB;IACxE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAeD,SAAgB,mBAAmB,CAAC,KAAc,EAAE,YAAY,GAAG,KAAK;IACtE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,IAAI,CAAC;IACtE,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["/**\r\n * Parsing Helper Functions\r\n *\r\n * Utility functions for safely parsing OOXML values from XML attributes.\r\n * These helpers address common parsing issues:\r\n * - Zero-value handling (0 should not be treated as falsy)\r\n * - NaN validation (malformed values should fall back to defaults)\r\n * - ECMA-376 boolean parsing (self-closing tags, val=\"1\", val=\"true\")\r\n *\r\n * @see https://ecma-international.org/publications-and-standards/standards/ecma-376/\r\n */\r\n\r\n/**\r\n * Safely parse an integer value with NaN handling.\r\n *\r\n * Addresses the issue where parseInt() can return NaN for malformed input,\r\n * which then propagates through the document model causing issues.\r\n *\r\n * @param value - The value to parse (string, number, or any)\r\n * @param defaultValue - Default value if parsing fails (default: 0)\r\n * @returns Parsed integer or default value\r\n *\r\n * @example\r\n * safeParseInt(\"42\") // 42\r\n * safeParseInt(\"invalid\") // 0\r\n * safeParseInt(undefined) // 0\r\n * safeParseInt(\"\", 100) // 100\r\n */\r\nexport function safeParseInt(value: unknown, defaultValue = 0): number {\r\n if (value === undefined || value === null) {\r\n return defaultValue;\r\n }\r\n\r\n // If already a number, return it (handle NaN case)\r\n if (typeof value === 'number') {\r\n return isNaN(value) ? defaultValue : Math.floor(value);\r\n }\r\n\r\n const parsed = parseInt(String(value), 10);\r\n return isNaN(parsed) ? defaultValue : parsed;\r\n}\r\n\r\n/**\r\n * Parse OOXML boolean value per ECMA-376 specification.\r\n *\r\n * OOXML boolean properties follow these rules:\r\n * - Self-closing tag `<w:bold/>` (no w:val attribute) = true\r\n * - `<w:bold w:val=\"1\"/>` = true\r\n * - `<w:bold w:val=\"true\"/>` = true\r\n * - `<w:bold w:val=\"on\"/>` = true\r\n * - `<w:bold w:val=\"0\"/>` = false\r\n * - `<w:bold w:val=\"false\"/>` = false\r\n * - `<w:bold w:val=\"off\"/>` = false\r\n * - Absent element = false (handled by caller checking for property existence)\r\n *\r\n * @param prop - The parsed XML property object (e.g., pPrObj[\"w:bold\"])\r\n * @returns Boolean value\r\n *\r\n * @example\r\n * // For XML: <w:bold/>\r\n * parseOoxmlBoolean({}) // true (self-closing, no @_w:val)\r\n *\r\n * // For XML: <w:bold w:val=\"1\"/>\r\n * parseOoxmlBoolean({ \"@_w:val\": \"1\" }) // true\r\n *\r\n * // For XML: <w:bold w:val=\"0\"/>\r\n * parseOoxmlBoolean({ \"@_w:val\": \"0\" }) // false\r\n *\r\n * // For absent element\r\n * parseOoxmlBoolean(undefined) // false\r\n */\r\nexport function parseOoxmlBoolean(prop: unknown): boolean {\r\n // Absent element = false\r\n if (!prop) {\r\n return false;\r\n }\r\n\r\n // Get the w:val attribute value\r\n const val = (prop as Record<string, unknown>)['@_w:val'];\r\n\r\n // Self-closing tag without w:val attribute = true\r\n // Per ECMA-376, presence of element without val means \"on\"\r\n if (val === undefined) {\r\n return true;\r\n }\r\n\r\n // Handle string values\r\n if (typeof val === 'string') {\r\n const lowerVal = val.toLowerCase();\r\n return lowerVal === '1' || lowerVal === 'true' || lowerVal === 'on';\r\n }\r\n\r\n // Handle numeric values\r\n if (typeof val === 'number') {\r\n return val === 1;\r\n }\r\n\r\n // Handle boolean values (already parsed by XML parser)\r\n if (typeof val === 'boolean') {\r\n return val;\r\n }\r\n\r\n // Unknown type - default to false\r\n return false;\r\n}\r\n\r\n/**\r\n * Check if a value is explicitly set (not undefined or null).\r\n *\r\n * This helper addresses the zero-value handling bug where truthy checks\r\n * incorrectly treat 0 as falsy:\r\n *\r\n * ```typescript\r\n * // WRONG - treats 0 as falsy\r\n * const width = val ? parseInt(val) : defaultWidth;\r\n *\r\n * // CORRECT - only checks for undefined/null\r\n * const width = isExplicitlySet(val) ? parseInt(val) : defaultWidth;\r\n * ```\r\n *\r\n * @param value - The value to check\r\n * @returns true if value is not undefined and not null\r\n *\r\n * @example\r\n * isExplicitlySet(0) // true\r\n * isExplicitlySet(\"\") // true\r\n * isExplicitlySet(false) // true\r\n * isExplicitlySet(undefined) // false\r\n * isExplicitlySet(null) // false\r\n */\r\nexport function isExplicitlySet(value: unknown): boolean {\r\n return value !== undefined && value !== null;\r\n}\r\n\r\n/**\r\n * Parse an OOXML numeric attribute with proper handling of zero values.\r\n *\r\n * Combines isExplicitlySet() and safeParseInt() for common use case\r\n * of parsing numeric attributes from XML.\r\n *\r\n * @param value - The attribute value to parse\r\n * @param defaultValue - Default value if attribute is not set\r\n * @returns Parsed integer or default value\r\n *\r\n * @example\r\n * parseNumericAttribute(\"100\", 50) // 100\r\n * parseNumericAttribute(\"0\", 50) // 0 (not 50!)\r\n * parseNumericAttribute(undefined, 50) // 50\r\n * parseNumericAttribute(\"invalid\", 50) // 50\r\n */\r\nexport function parseNumericAttribute(value: unknown, defaultValue: number): number {\r\n if (!isExplicitlySet(value)) {\r\n return defaultValue;\r\n }\r\n return safeParseInt(value, defaultValue);\r\n}\r\n\r\n/**\r\n * Parse OOXML \"on/off\" attribute (ST_OnOff type).\r\n *\r\n * Some OOXML attributes use the ST_OnOff simple type which can be:\r\n * - \"on\", \"1\", \"true\" = true\r\n * - \"off\", \"0\", \"false\" = false\r\n *\r\n * This is similar to parseOoxmlBoolean but works on attribute values directly.\r\n *\r\n * @param value - The attribute value\r\n * @param defaultValue - Default if value is not set\r\n * @returns Boolean value\r\n */\r\nexport function parseOnOffAttribute(value: unknown, defaultValue = false): boolean {\r\n if (!isExplicitlySet(value)) {\r\n return defaultValue;\r\n }\r\n\r\n if (typeof value === 'string') {\r\n const lowerVal = value.toLowerCase();\r\n return lowerVal === '1' || lowerVal === 'true' || lowerVal === 'on';\r\n }\r\n\r\n if (typeof value === 'number') {\r\n return value === 1;\r\n }\r\n\r\n if (typeof value === 'boolean') {\r\n return value;\r\n }\r\n\r\n return defaultValue;\r\n}\r\n"]}
1
+ {"version":3,"file":"parsingHelpers.js","sourceRoot":"","sources":["../../src/utils/parsingHelpers.ts"],"names":[],"mappings":";;AA4BA,oCAYC;AA+BD,8CAiCC;AA0BD,0CAEC;AAkBD,sDAKC;AAeD,kDAmBC;AAjKD,SAAgB,YAAY,CAAC,KAAc,EAAE,YAAY,GAAG,CAAC;IAC3D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,YAAY,CAAC;IACtB,CAAC;IAGD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/C,CAAC;AA+BD,SAAgB,iBAAiB,CAAC,IAAa;IAE7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,MAAM,GAAG,GAAI,IAAgC,CAAC,SAAS,CAAC,CAAC;IAIzD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,OAAO,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,IAAI,CAAC;IACtE,CAAC;IAGD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,KAAK,CAAC,CAAC;IACnB,CAAC;IAGD,IAAI,OAAO,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IAGD,OAAO,KAAK,CAAC;AACf,CAAC;AA0BD,SAAgB,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;AAC/C,CAAC;AAkBD,SAAgB,qBAAqB,CAAC,KAAc,EAAE,YAAoB;IACxE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAeD,SAAgB,mBAAmB,CAAC,KAAc,EAAE,YAAY,GAAG,KAAK;IACtE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,IAAI,CAAC;IACtE,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["/**\n * Parsing Helper Functions\n *\n * Utility functions for safely parsing OOXML values from XML attributes.\n * These helpers address common parsing issues:\n * - Zero-value handling (0 should not be treated as falsy)\n * - NaN validation (malformed values should fall back to defaults)\n * - ECMA-376 boolean parsing (self-closing tags, val=\"1\", val=\"true\")\n *\n * @see https://ecma-international.org/publications-and-standards/standards/ecma-376/\n */\n\n/**\n * Safely parse an integer value with NaN handling.\n *\n * Addresses the issue where parseInt() can return NaN for malformed input,\n * which then propagates through the document model causing issues.\n *\n * @param value - The value to parse (string, number, or any)\n * @param defaultValue - Default value if parsing fails (default: 0)\n * @returns Parsed integer or default value\n *\n * @example\n * safeParseInt(\"42\") // 42\n * safeParseInt(\"invalid\") // 0\n * safeParseInt(undefined) // 0\n * safeParseInt(\"\", 100) // 100\n */\nexport function safeParseInt(value: unknown, defaultValue = 0): number {\n if (value === undefined || value === null) {\n return defaultValue;\n }\n\n // If already a number, return it (handle NaN case)\n if (typeof value === 'number') {\n return isNaN(value) ? defaultValue : Math.floor(value);\n }\n\n const parsed = parseInt(String(value), 10);\n return isNaN(parsed) ? defaultValue : parsed;\n}\n\n/**\n * Parse OOXML boolean value per ECMA-376 specification.\n *\n * OOXML boolean properties follow these rules:\n * - Self-closing tag `<w:bold/>` (no w:val attribute) = true\n * - `<w:bold w:val=\"1\"/>` = true\n * - `<w:bold w:val=\"true\"/>` = true\n * - `<w:bold w:val=\"on\"/>` = true\n * - `<w:bold w:val=\"0\"/>` = false\n * - `<w:bold w:val=\"false\"/>` = false\n * - `<w:bold w:val=\"off\"/>` = false\n * - Absent element = false (handled by caller checking for property existence)\n *\n * @param prop - The parsed XML property object (e.g., pPrObj[\"w:bold\"])\n * @returns Boolean value\n *\n * @example\n * // For XML: <w:bold/>\n * parseOoxmlBoolean({}) // true (self-closing, no @_w:val)\n *\n * // For XML: <w:bold w:val=\"1\"/>\n * parseOoxmlBoolean({ \"@_w:val\": \"1\" }) // true\n *\n * // For XML: <w:bold w:val=\"0\"/>\n * parseOoxmlBoolean({ \"@_w:val\": \"0\" }) // false\n *\n * // For absent element\n * parseOoxmlBoolean(undefined) // false\n */\nexport function parseOoxmlBoolean(prop: unknown): boolean {\n // Absent element = false\n if (!prop) {\n return false;\n }\n\n // Get the w:val attribute value\n const val = (prop as Record<string, unknown>)['@_w:val'];\n\n // Self-closing tag without w:val attribute = true\n // Per ECMA-376, presence of element without val means \"on\"\n if (val === undefined) {\n return true;\n }\n\n // Handle string values\n if (typeof val === 'string') {\n const lowerVal = val.toLowerCase();\n return lowerVal === '1' || lowerVal === 'true' || lowerVal === 'on';\n }\n\n // Handle numeric values\n if (typeof val === 'number') {\n return val === 1;\n }\n\n // Handle boolean values (already parsed by XML parser)\n if (typeof val === 'boolean') {\n return val;\n }\n\n // Unknown type - default to false\n return false;\n}\n\n/**\n * Check if a value is explicitly set (not undefined or null).\n *\n * This helper addresses the zero-value handling bug where truthy checks\n * incorrectly treat 0 as falsy:\n *\n * ```typescript\n * // WRONG - treats 0 as falsy\n * const width = val ? parseInt(val) : defaultWidth;\n *\n * // CORRECT - only checks for undefined/null\n * const width = isExplicitlySet(val) ? parseInt(val) : defaultWidth;\n * ```\n *\n * @param value - The value to check\n * @returns true if value is not undefined and not null\n *\n * @example\n * isExplicitlySet(0) // true\n * isExplicitlySet(\"\") // true\n * isExplicitlySet(false) // true\n * isExplicitlySet(undefined) // false\n * isExplicitlySet(null) // false\n */\nexport function isExplicitlySet(value: unknown): boolean {\n return value !== undefined && value !== null;\n}\n\n/**\n * Parse an OOXML numeric attribute with proper handling of zero values.\n *\n * Combines isExplicitlySet() and safeParseInt() for common use case\n * of parsing numeric attributes from XML.\n *\n * @param value - The attribute value to parse\n * @param defaultValue - Default value if attribute is not set\n * @returns Parsed integer or default value\n *\n * @example\n * parseNumericAttribute(\"100\", 50) // 100\n * parseNumericAttribute(\"0\", 50) // 0 (not 50!)\n * parseNumericAttribute(undefined, 50) // 50\n * parseNumericAttribute(\"invalid\", 50) // 50\n */\nexport function parseNumericAttribute(value: unknown, defaultValue: number): number {\n if (!isExplicitlySet(value)) {\n return defaultValue;\n }\n return safeParseInt(value, defaultValue);\n}\n\n/**\n * Parse OOXML \"on/off\" attribute (ST_OnOff type).\n *\n * Some OOXML attributes use the ST_OnOff simple type which can be:\n * - \"on\", \"1\", \"true\" = true\n * - \"off\", \"0\", \"false\" = false\n *\n * This is similar to parseOoxmlBoolean but works on attribute values directly.\n *\n * @param value - The attribute value\n * @param defaultValue - Default if value is not set\n * @returns Boolean value\n */\nexport function parseOnOffAttribute(value: unknown, defaultValue = false): boolean {\n if (!isExplicitlySet(value)) {\n return defaultValue;\n }\n\n if (typeof value === 'string') {\n const lowerVal = value.toLowerCase();\n return lowerVal === '1' || lowerVal === 'true' || lowerVal === 'on';\n }\n\n if (typeof value === 'number') {\n return value === 1;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n return defaultValue;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stripTrackedChanges.d.ts","sourceRoot":"","sources":["../../src/utils/stripTrackedChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AA6V/C,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/E"}
1
+ {"version":3,"file":"stripTrackedChanges.d.ts","sourceRoot":"","sources":["../../src/utils/stripTrackedChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAgW/C,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/E"}
@@ -40,7 +40,7 @@ class TrackedChangesStripper {
40
40
  /<w:customXmlMoveFromRangeStart[^>]*\/>/g,
41
41
  /<w:customXmlMoveFromRangeEnd[^>]*\/>/g,
42
42
  /<w:customXmlMoveToRangeStart[^>]*\/>/g,
43
- /<w:customXmlMoveToRangeEnd[^>]*\/>/g
43
+ /<w:customXmlMoveToRangeEnd[^>]*\/>/g,
44
44
  ];
45
45
  let result = xml;
46
46
  for (const pattern of patterns) {
@@ -102,7 +102,7 @@ class TrackedChangesStripper {
102
102
  /<w:trPrChange[^>]*>.*?<\/w:trPrChange>/gs,
103
103
  /<w:sectPrChange[^>]*>.*?<\/w:sectPrChange>/gs,
104
104
  /<w:tblGridChange[^>]*>.*?<\/w:tblGridChange>/gs,
105
- /<w:numberingChange[^>]*>.*?<\/w:numberingChange>/gs
105
+ /<w:numberingChange[^>]*>.*?<\/w:numberingChange>/gs,
106
106
  ];
107
107
  let result = xml;
108
108
  for (const pattern of patterns) {
@@ -115,7 +115,7 @@ class TrackedChangesStripper {
115
115
  /<w:ins\s+[^>]*\/>/g,
116
116
  /<w:del\s+[^>]*\/>/g,
117
117
  /<w:moveFrom\s+[^>]*\/>/g,
118
- /<w:moveTo\s+[^>]*\/>/g
118
+ /<w:moveTo\s+[^>]*\/>/g,
119
119
  ];
120
120
  let result = xml;
121
121
  for (const pattern of patterns) {