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,333 +1,329 @@
1
- /**
2
- * Helper functions for creating complex and nested fields
3
- */
4
-
5
- import { ComplexField } from './Field';
6
- import { defaultLogger } from '../utils/logger';
7
-
8
- /**
9
- * Parsed components of a HYPERLINK field instruction
10
- */
11
- export interface ParsedHyperlinkInstruction {
12
- /** Base URL (with encoded characters decoded) */
13
- url: string;
14
- /** Anchor/fragment from \l switch (decoded) */
15
- anchor?: string;
16
- /** Tooltip text from \o switch */
17
- tooltip?: string;
18
- /** Whether \h switch is present (creates hyperlink) */
19
- hasHSwitch: boolean;
20
- /** Combined full URL (url + "#" + anchor if both present) */
21
- fullUrl: string;
22
- /** Original raw instruction string */
23
- rawInstruction: string;
24
- }
25
-
26
- /**
27
- * Parses a HYPERLINK field instruction string into its components
28
- *
29
- * HYPERLINK field syntax per ECMA-376:
30
- * - HYPERLINK "url" - basic external hyperlink
31
- * - HYPERLINK \l "anchor" - anchor-only internal hyperlink (no URL)
32
- * - \l "anchor" - specifies a location (anchor/fragment) within the target
33
- * - \o "tooltip" - specifies the tooltip/screentip text
34
- * - \h - creates a hyperlink (always present for clickable links)
35
- * - \n - opens link in new window
36
- * - \t "target" - specifies target frame
37
- *
38
- * @param instruction The raw field instruction string (e.g., 'HYPERLINK "url" \l "anchor" \h')
39
- * @returns Parsed components or null if not a valid HYPERLINK instruction
40
- *
41
- * @example
42
- * ```typescript
43
- * // External hyperlink with anchor
44
- * const result = parseHyperlinkInstruction('HYPERLINK "https://example.com/" \\l "section1" \\h');
45
- * // result.url = "https://example.com/"
46
- * // result.anchor = "section1"
47
- * // result.fullUrl = "https://example.com/#section1"
48
- *
49
- * // Anchor-only internal hyperlink (e.g., "Top of the Document")
50
- * const result2 = parseHyperlinkInstruction('HYPERLINK \\l "_top" \\h');
51
- * // result2.url = ""
52
- * // result2.anchor = "_top"
53
- * // result2.fullUrl = "#_top"
54
- * ```
55
- */
56
- export function parseHyperlinkInstruction(instruction: string): ParsedHyperlinkInstruction | null {
57
- if (!instruction) {
58
- return null;
59
- }
60
-
61
- // Normalize whitespace and trim
62
- const normalized = instruction.trim();
63
-
64
- // Check if this is a HYPERLINK instruction
65
- if (!normalized.toUpperCase().startsWith('HYPERLINK')) {
66
- return null;
67
- }
68
-
69
- // Extract the URL (first quoted string after HYPERLINK, before any switches)
70
- // URL is optional - anchor-only hyperlinks like 'HYPERLINK \l "_top"' are valid
71
- let url = '';
72
- const urlMatch = /HYPERLINK\s+"([^"]*)"/i.exec(normalized);
73
- if (urlMatch?.[1] !== undefined) {
74
- url = urlMatch[1];
75
- // Decode URL-encoded characters
76
- try {
77
- url = decodeURIComponent(url);
78
- } catch (e) {
79
- defaultLogger.debug(`[FieldHelpers] Failed to decode URL: ${url}`);
80
- }
81
- }
82
-
83
- // Extract \l switch (anchor/fragment)
84
- let anchor: string | undefined;
85
- const anchorMatch = /\\l\s+"([^"]*)"/i.exec(normalized);
86
- if (anchorMatch?.[1] !== undefined) {
87
- anchor = anchorMatch[1];
88
- // Decode anchor as well
89
- try {
90
- anchor = decodeURIComponent(anchor);
91
- } catch (e) {
92
- defaultLogger.debug(`[FieldHelpers] Failed to decode anchor: ${anchor}`);
93
- }
94
- }
95
-
96
- // Must have either URL or anchor to be valid
97
- if (!url && !anchor) {
98
- return null;
99
- }
100
-
101
- // Extract \o switch (tooltip)
102
- let tooltip: string | undefined;
103
- const tooltipMatch = /\\o\s+"([^"]*)"/i.exec(normalized);
104
- if (tooltipMatch?.[1] !== undefined) {
105
- tooltip = tooltipMatch[1];
106
- }
107
-
108
- // Check for \h switch
109
- const hasHSwitch = /\\h(?:\s|$)/i.test(normalized);
110
-
111
- // Build full URL by combining base URL and anchor
112
- let fullUrl: string = url;
113
- if (anchor) {
114
- // If URL already has a fragment, replace it; otherwise append
115
- const hashIndex = url.indexOf('#');
116
- if (hashIndex >= 0) {
117
- fullUrl = url.substring(0, hashIndex) + '#' + anchor;
118
- } else if (url) {
119
- fullUrl = url + '#' + anchor;
120
- } else {
121
- // Anchor-only: just use #anchor
122
- fullUrl = '#' + anchor;
123
- }
124
- }
125
-
126
- return {
127
- url,
128
- anchor,
129
- tooltip,
130
- hasHSwitch,
131
- fullUrl,
132
- rawInstruction: instruction,
133
- };
134
- }
135
-
136
- /**
137
- * Creates a HYPERLINK field instruction string from components
138
- *
139
- * @param url The target URL
140
- * @param anchor Optional anchor/fragment (will use \l switch)
141
- * @param tooltip Optional tooltip text (will use \o switch)
142
- * @returns Properly formatted HYPERLINK instruction string
143
- *
144
- * @example
145
- * ```typescript
146
- * const instr = buildHyperlinkInstruction('https://example.com/', 'section1', 'Click here');
147
- * // Returns: 'HYPERLINK "https://example.com/" \\l "section1" \\o "Click here" \\h'
148
- * ```
149
- */
150
- export function buildHyperlinkInstruction(
151
- url: string,
152
- anchor?: string,
153
- tooltip?: string
154
- ): string {
155
- let instruction = `HYPERLINK "${url}"`;
156
-
157
- if (anchor) {
158
- instruction += ` \\l "${anchor}"`;
159
- }
160
-
161
- if (tooltip) {
162
- instruction += ` \\o "${tooltip}"`;
163
- }
164
-
165
- // Always add \h switch for clickable hyperlinks
166
- instruction += ' \\h';
167
-
168
- return instruction;
169
- }
170
-
171
- /**
172
- * Checks if a field instruction is a HYPERLINK field
173
- *
174
- * @param instruction The field instruction to check
175
- * @returns True if the instruction is a HYPERLINK field
176
- */
177
- export function isHyperlinkInstruction(instruction: string): boolean {
178
- if (!instruction) {
179
- return false;
180
- }
181
- return instruction.trim().toUpperCase().startsWith('HYPERLINK');
182
- }
183
-
184
- /**
185
- * Creates a nested IF field containing a MERGEFIELD
186
- * This is a common pattern for conditional mail merge
187
- *
188
- * @param condition The IF condition (e.g., 'Status = "Active"')
189
- * @param mergeFieldName The merge field name to include
190
- * @param trueText Text to show when condition is true
191
- * @param falseText Text to show when condition is false
192
- * @returns ComplexField with nested MERGEFIELD
193
- *
194
- * @example
195
- * ```typescript
196
- * const field = createNestedIFMergeField('Status = "Active"', 'Name', 'Active: ', 'Inactive');
197
- * // Result: IF field that shows "Active: [Name]" if Status is Active, otherwise "Inactive"
198
- * ```
199
- */
200
- export function createNestedIFMergeField(
201
- condition: string,
202
- mergeFieldName: string,
203
- trueText = '',
204
- falseText = ''
205
- ): ComplexField {
206
- // Create the nested MERGEFIELD
207
- const mergeField = new ComplexField({
208
- instruction: ` MERGEFIELD ${mergeFieldName} `,
209
- result: `[${mergeFieldName}]`,
210
- });
211
-
212
- // Create the IF field with nested MERGEFIELD
213
- const ifField = new ComplexField({
214
- instruction: ` IF ${condition} "${trueText}" "${falseText}" `,
215
- result: trueText || falseText,
216
- });
217
-
218
- ifField.addNestedField(mergeField);
219
-
220
- return ifField;
221
- }
222
-
223
- /**
224
- * Creates a MERGEFIELD with custom formatting
225
- *
226
- * @param fieldName The merge field name
227
- * @param format Optional format switches
228
- * @returns ComplexField for MERGEFIELD
229
- *
230
- * @example
231
- * ```typescript
232
- * const field = createMergeField('Date', '\\@ "MMMM d, yyyy"');
233
- * ```
234
- */
235
- export function createMergeField(fieldName: string, format?: string): ComplexField {
236
- let instruction = ` MERGEFIELD ${fieldName}`;
237
-
238
- if (format) {
239
- instruction += ` ${format}`;
240
- }
241
-
242
- instruction += ' \\* MERGEFORMAT ';
243
-
244
- return new ComplexField({
245
- instruction,
246
- result: `[${fieldName}]`,
247
- });
248
- }
249
-
250
- /**
251
- * Creates a REF field with a nested field in the bookmark reference
252
- * Used for complex cross-references
253
- *
254
- * @param bookmarkName The bookmark to reference
255
- * @param format Optional format switches
256
- * @returns ComplexField for REF
257
- *
258
- * @example
259
- * ```typescript
260
- * const field = createRefField('Chapter1', '\\h');
261
- * ```
262
- */
263
- export function createRefField(bookmarkName: string, format?: string): ComplexField {
264
- let instruction = ` REF ${bookmarkName}`;
265
-
266
- if (format) {
267
- instruction += ` ${format}`;
268
- } else {
269
- instruction += ' \\h'; // Hyperlink by default
270
- }
271
-
272
- instruction += ' \\* MERGEFORMAT ';
273
-
274
- return new ComplexField({
275
- instruction,
276
- result: `[${bookmarkName}]`,
277
- });
278
- }
279
-
280
- /**
281
- * Creates an IF field with custom true/false branches
282
- *
283
- * @param condition The condition to evaluate
284
- * @param trueContent Content to show when true
285
- * @param falseContent Content to show when false
286
- * @returns ComplexField for IF
287
- *
288
- * @example
289
- * ```typescript
290
- * const field = createIFField('Amount > 1000', 'High Value', 'Normal');
291
- * ```
292
- */
293
- export function createIFField(
294
- condition: string,
295
- trueContent: string,
296
- falseContent = ''
297
- ): ComplexField {
298
- const instruction = ` IF ${condition} "${trueContent}" "${falseContent}" `;
299
-
300
- return new ComplexField({
301
- instruction,
302
- result: trueContent,
303
- });
304
- }
305
-
306
- /**
307
- * Creates a complex nested field structure with multiple levels
308
- * Useful for advanced scenarios like nested IF statements
309
- *
310
- * @param outerInstruction The outer field instruction
311
- * @param nestedFields Array of nested fields to include
312
- * @returns ComplexField with nested structure
313
- *
314
- * @example
315
- * ```typescript
316
- * const innerField = createMergeField('Amount');
317
- * const field = createNestedField('IF Amount > 0', [innerField]);
318
- * ```
319
- */
320
- export function createNestedField(
321
- outerInstruction: string,
322
- nestedFields: ComplexField[]
323
- ): ComplexField {
324
- const field = new ComplexField({
325
- instruction: outerInstruction,
326
- });
327
-
328
- for (const nested of nestedFields) {
329
- field.addNestedField(nested);
330
- }
331
-
332
- return field;
333
- }
1
+ /**
2
+ * Helper functions for creating complex and nested fields
3
+ */
4
+
5
+ import { ComplexField } from './Field';
6
+ import { defaultLogger } from '../utils/logger';
7
+
8
+ /**
9
+ * Parsed components of a HYPERLINK field instruction
10
+ */
11
+ export interface ParsedHyperlinkInstruction {
12
+ /** Base URL (with encoded characters decoded) */
13
+ url: string;
14
+ /** Anchor/fragment from \l switch (decoded) */
15
+ anchor?: string;
16
+ /** Tooltip text from \o switch */
17
+ tooltip?: string;
18
+ /** Whether \h switch is present (creates hyperlink) */
19
+ hasHSwitch: boolean;
20
+ /** Combined full URL (url + "#" + anchor if both present) */
21
+ fullUrl: string;
22
+ /** Original raw instruction string */
23
+ rawInstruction: string;
24
+ }
25
+
26
+ /**
27
+ * Parses a HYPERLINK field instruction string into its components
28
+ *
29
+ * HYPERLINK field syntax per ECMA-376:
30
+ * - HYPERLINK "url" - basic external hyperlink
31
+ * - HYPERLINK \l "anchor" - anchor-only internal hyperlink (no URL)
32
+ * - \l "anchor" - specifies a location (anchor/fragment) within the target
33
+ * - \o "tooltip" - specifies the tooltip/screentip text
34
+ * - \h - creates a hyperlink (always present for clickable links)
35
+ * - \n - opens link in new window
36
+ * - \t "target" - specifies target frame
37
+ *
38
+ * @param instruction The raw field instruction string (e.g., 'HYPERLINK "url" \l "anchor" \h')
39
+ * @returns Parsed components or null if not a valid HYPERLINK instruction
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // External hyperlink with anchor
44
+ * const result = parseHyperlinkInstruction('HYPERLINK "https://example.com/" \\l "section1" \\h');
45
+ * // result.url = "https://example.com/"
46
+ * // result.anchor = "section1"
47
+ * // result.fullUrl = "https://example.com/#section1"
48
+ *
49
+ * // Anchor-only internal hyperlink (e.g., "Top of the Document")
50
+ * const result2 = parseHyperlinkInstruction('HYPERLINK \\l "_top" \\h');
51
+ * // result2.url = ""
52
+ * // result2.anchor = "_top"
53
+ * // result2.fullUrl = "#_top"
54
+ * ```
55
+ */
56
+ export function parseHyperlinkInstruction(instruction: string): ParsedHyperlinkInstruction | null {
57
+ if (!instruction) {
58
+ return null;
59
+ }
60
+
61
+ // Normalize whitespace and trim
62
+ const normalized = instruction.trim();
63
+
64
+ // Check if this is a HYPERLINK instruction
65
+ if (!normalized.toUpperCase().startsWith('HYPERLINK')) {
66
+ return null;
67
+ }
68
+
69
+ // Extract the URL (first quoted string after HYPERLINK, before any switches)
70
+ // URL is optional - anchor-only hyperlinks like 'HYPERLINK \l "_top"' are valid
71
+ let url = '';
72
+ const urlMatch = /HYPERLINK\s+"([^"]*)"/i.exec(normalized);
73
+ if (urlMatch?.[1] !== undefined) {
74
+ url = urlMatch[1];
75
+ // Decode URL-encoded characters
76
+ try {
77
+ url = decodeURIComponent(url);
78
+ } catch (e) {
79
+ defaultLogger.debug(`[FieldHelpers] Failed to decode URL: ${url}`);
80
+ }
81
+ }
82
+
83
+ // Extract \l switch (anchor/fragment)
84
+ let anchor: string | undefined;
85
+ const anchorMatch = /\\l\s+"([^"]*)"/i.exec(normalized);
86
+ if (anchorMatch?.[1] !== undefined) {
87
+ anchor = anchorMatch[1];
88
+ // Decode anchor as well
89
+ try {
90
+ anchor = decodeURIComponent(anchor);
91
+ } catch (e) {
92
+ defaultLogger.debug(`[FieldHelpers] Failed to decode anchor: ${anchor}`);
93
+ }
94
+ }
95
+
96
+ // Must have either URL or anchor to be valid
97
+ if (!url && !anchor) {
98
+ return null;
99
+ }
100
+
101
+ // Extract \o switch (tooltip)
102
+ let tooltip: string | undefined;
103
+ const tooltipMatch = /\\o\s+"([^"]*)"/i.exec(normalized);
104
+ if (tooltipMatch?.[1] !== undefined) {
105
+ tooltip = tooltipMatch[1];
106
+ }
107
+
108
+ // Check for \h switch
109
+ const hasHSwitch = /\\h(?:\s|$)/i.test(normalized);
110
+
111
+ // Build full URL by combining base URL and anchor
112
+ let fullUrl: string = url;
113
+ if (anchor) {
114
+ // If URL already has a fragment, replace it; otherwise append
115
+ const hashIndex = url.indexOf('#');
116
+ if (hashIndex >= 0) {
117
+ fullUrl = url.substring(0, hashIndex) + '#' + anchor;
118
+ } else if (url) {
119
+ fullUrl = url + '#' + anchor;
120
+ } else {
121
+ // Anchor-only: just use #anchor
122
+ fullUrl = '#' + anchor;
123
+ }
124
+ }
125
+
126
+ return {
127
+ url,
128
+ anchor,
129
+ tooltip,
130
+ hasHSwitch,
131
+ fullUrl,
132
+ rawInstruction: instruction,
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Creates a HYPERLINK field instruction string from components
138
+ *
139
+ * @param url The target URL
140
+ * @param anchor Optional anchor/fragment (will use \l switch)
141
+ * @param tooltip Optional tooltip text (will use \o switch)
142
+ * @returns Properly formatted HYPERLINK instruction string
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const instr = buildHyperlinkInstruction('https://example.com/', 'section1', 'Click here');
147
+ * // Returns: 'HYPERLINK "https://example.com/" \\l "section1" \\o "Click here" \\h'
148
+ * ```
149
+ */
150
+ export function buildHyperlinkInstruction(url: string, anchor?: string, tooltip?: string): string {
151
+ let instruction = `HYPERLINK "${url}"`;
152
+
153
+ if (anchor) {
154
+ instruction += ` \\l "${anchor}"`;
155
+ }
156
+
157
+ if (tooltip) {
158
+ instruction += ` \\o "${tooltip}"`;
159
+ }
160
+
161
+ // Always add \h switch for clickable hyperlinks
162
+ instruction += ' \\h';
163
+
164
+ return instruction;
165
+ }
166
+
167
+ /**
168
+ * Checks if a field instruction is a HYPERLINK field
169
+ *
170
+ * @param instruction The field instruction to check
171
+ * @returns True if the instruction is a HYPERLINK field
172
+ */
173
+ export function isHyperlinkInstruction(instruction: string): boolean {
174
+ if (!instruction) {
175
+ return false;
176
+ }
177
+ return instruction.trim().toUpperCase().startsWith('HYPERLINK');
178
+ }
179
+
180
+ /**
181
+ * Creates a nested IF field containing a MERGEFIELD
182
+ * This is a common pattern for conditional mail merge
183
+ *
184
+ * @param condition The IF condition (e.g., 'Status = "Active"')
185
+ * @param mergeFieldName The merge field name to include
186
+ * @param trueText Text to show when condition is true
187
+ * @param falseText Text to show when condition is false
188
+ * @returns ComplexField with nested MERGEFIELD
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * const field = createNestedIFMergeField('Status = "Active"', 'Name', 'Active: ', 'Inactive');
193
+ * // Result: IF field that shows "Active: [Name]" if Status is Active, otherwise "Inactive"
194
+ * ```
195
+ */
196
+ export function createNestedIFMergeField(
197
+ condition: string,
198
+ mergeFieldName: string,
199
+ trueText = '',
200
+ falseText = ''
201
+ ): ComplexField {
202
+ // Create the nested MERGEFIELD
203
+ const mergeField = new ComplexField({
204
+ instruction: ` MERGEFIELD ${mergeFieldName} `,
205
+ result: `[${mergeFieldName}]`,
206
+ });
207
+
208
+ // Create the IF field with nested MERGEFIELD
209
+ const ifField = new ComplexField({
210
+ instruction: ` IF ${condition} "${trueText}" "${falseText}" `,
211
+ result: trueText || falseText,
212
+ });
213
+
214
+ ifField.addNestedField(mergeField);
215
+
216
+ return ifField;
217
+ }
218
+
219
+ /**
220
+ * Creates a MERGEFIELD with custom formatting
221
+ *
222
+ * @param fieldName The merge field name
223
+ * @param format Optional format switches
224
+ * @returns ComplexField for MERGEFIELD
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * const field = createMergeField('Date', '\\@ "MMMM d, yyyy"');
229
+ * ```
230
+ */
231
+ export function createMergeField(fieldName: string, format?: string): ComplexField {
232
+ let instruction = ` MERGEFIELD ${fieldName}`;
233
+
234
+ if (format) {
235
+ instruction += ` ${format}`;
236
+ }
237
+
238
+ instruction += ' \\* MERGEFORMAT ';
239
+
240
+ return new ComplexField({
241
+ instruction,
242
+ result: `[${fieldName}]`,
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Creates a REF field with a nested field in the bookmark reference
248
+ * Used for complex cross-references
249
+ *
250
+ * @param bookmarkName The bookmark to reference
251
+ * @param format Optional format switches
252
+ * @returns ComplexField for REF
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * const field = createRefField('Chapter1', '\\h');
257
+ * ```
258
+ */
259
+ export function createRefField(bookmarkName: string, format?: string): ComplexField {
260
+ let instruction = ` REF ${bookmarkName}`;
261
+
262
+ if (format) {
263
+ instruction += ` ${format}`;
264
+ } else {
265
+ instruction += ' \\h'; // Hyperlink by default
266
+ }
267
+
268
+ instruction += ' \\* MERGEFORMAT ';
269
+
270
+ return new ComplexField({
271
+ instruction,
272
+ result: `[${bookmarkName}]`,
273
+ });
274
+ }
275
+
276
+ /**
277
+ * Creates an IF field with custom true/false branches
278
+ *
279
+ * @param condition The condition to evaluate
280
+ * @param trueContent Content to show when true
281
+ * @param falseContent Content to show when false
282
+ * @returns ComplexField for IF
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * const field = createIFField('Amount > 1000', 'High Value', 'Normal');
287
+ * ```
288
+ */
289
+ export function createIFField(
290
+ condition: string,
291
+ trueContent: string,
292
+ falseContent = ''
293
+ ): ComplexField {
294
+ const instruction = ` IF ${condition} "${trueContent}" "${falseContent}" `;
295
+
296
+ return new ComplexField({
297
+ instruction,
298
+ result: trueContent,
299
+ });
300
+ }
301
+
302
+ /**
303
+ * Creates a complex nested field structure with multiple levels
304
+ * Useful for advanced scenarios like nested IF statements
305
+ *
306
+ * @param outerInstruction The outer field instruction
307
+ * @param nestedFields Array of nested fields to include
308
+ * @returns ComplexField with nested structure
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * const innerField = createMergeField('Amount');
313
+ * const field = createNestedField('IF Amount > 0', [innerField]);
314
+ * ```
315
+ */
316
+ export function createNestedField(
317
+ outerInstruction: string,
318
+ nestedFields: ComplexField[]
319
+ ): ComplexField {
320
+ const field = new ComplexField({
321
+ instruction: outerInstruction,
322
+ });
323
+
324
+ for (const nested of nestedFields) {
325
+ field.addNestedField(nested);
326
+ }
327
+
328
+ return field;
329
+ }