docxmlater 10.1.3 → 10.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/README.md +759 -754
  2. package/dist/constants/legacyCompatFlags.js +1 -1
  3. package/dist/constants/legacyCompatFlags.js.map +1 -1
  4. package/dist/constants/limits.js.map +1 -1
  5. package/dist/core/Document.d.ts +50 -50
  6. package/dist/core/Document.d.ts.map +1 -1
  7. package/dist/core/Document.js +483 -471
  8. package/dist/core/Document.js.map +1 -1
  9. package/dist/core/DocumentContent.d.ts +9 -9
  10. package/dist/core/DocumentContent.d.ts.map +1 -1
  11. package/dist/core/DocumentContent.js +1 -1
  12. package/dist/core/DocumentContent.js.map +1 -1
  13. package/dist/core/DocumentGenerator.d.ts +11 -11
  14. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  15. package/dist/core/DocumentGenerator.js +251 -251
  16. package/dist/core/DocumentGenerator.js.map +1 -1
  17. package/dist/core/DocumentIdManager.js.map +1 -1
  18. package/dist/core/DocumentParser.d.ts +15 -15
  19. package/dist/core/DocumentParser.d.ts.map +1 -1
  20. package/dist/core/DocumentParser.js +2123 -2155
  21. package/dist/core/DocumentParser.js.map +1 -1
  22. package/dist/core/DocumentValidator.d.ts.map +1 -1
  23. package/dist/core/DocumentValidator.js +2 -5
  24. package/dist/core/DocumentValidator.js.map +1 -1
  25. package/dist/core/Relationship.js.map +1 -1
  26. package/dist/core/RelationshipManager.d.ts.map +1 -1
  27. package/dist/core/RelationshipManager.js +3 -3
  28. package/dist/core/RelationshipManager.js.map +1 -1
  29. package/dist/elements/AlternateContent.js.map +1 -1
  30. package/dist/elements/Bookmark.d.ts.map +1 -1
  31. package/dist/elements/Bookmark.js +3 -1
  32. package/dist/elements/Bookmark.js.map +1 -1
  33. package/dist/elements/BookmarkManager.d.ts.map +1 -1
  34. package/dist/elements/BookmarkManager.js.map +1 -1
  35. package/dist/elements/Comment.d.ts.map +1 -1
  36. package/dist/elements/Comment.js +9 -6
  37. package/dist/elements/Comment.js.map +1 -1
  38. package/dist/elements/CommentManager.d.ts.map +1 -1
  39. package/dist/elements/CommentManager.js +18 -17
  40. package/dist/elements/CommentManager.js.map +1 -1
  41. package/dist/elements/CommonTypes.d.ts +21 -21
  42. package/dist/elements/CommonTypes.d.ts.map +1 -1
  43. package/dist/elements/CommonTypes.js +56 -56
  44. package/dist/elements/CommonTypes.js.map +1 -1
  45. package/dist/elements/CustomXml.js.map +1 -1
  46. package/dist/elements/Endnote.d.ts.map +1 -1
  47. package/dist/elements/Endnote.js +6 -6
  48. package/dist/elements/Endnote.js.map +1 -1
  49. package/dist/elements/EndnoteManager.d.ts.map +1 -1
  50. package/dist/elements/EndnoteManager.js +6 -7
  51. package/dist/elements/EndnoteManager.js.map +1 -1
  52. package/dist/elements/Field.d.ts.map +1 -1
  53. package/dist/elements/Field.js +82 -25
  54. package/dist/elements/Field.js.map +1 -1
  55. package/dist/elements/FieldHelpers.d.ts.map +1 -1
  56. package/dist/elements/FieldHelpers.js.map +1 -1
  57. package/dist/elements/FontManager.d.ts.map +1 -1
  58. package/dist/elements/FontManager.js +1 -1
  59. package/dist/elements/FontManager.js.map +1 -1
  60. package/dist/elements/Footer.js +2 -2
  61. package/dist/elements/Footer.js.map +1 -1
  62. package/dist/elements/Footnote.d.ts.map +1 -1
  63. package/dist/elements/Footnote.js +6 -6
  64. package/dist/elements/Footnote.js.map +1 -1
  65. package/dist/elements/FootnoteManager.d.ts.map +1 -1
  66. package/dist/elements/FootnoteManager.js +6 -7
  67. package/dist/elements/FootnoteManager.js.map +1 -1
  68. package/dist/elements/Header.js +2 -2
  69. package/dist/elements/Header.js.map +1 -1
  70. package/dist/elements/HeaderFooterManager.js.map +1 -1
  71. package/dist/elements/Hyperlink.d.ts +5 -3
  72. package/dist/elements/Hyperlink.d.ts.map +1 -1
  73. package/dist/elements/Hyperlink.js +134 -76
  74. package/dist/elements/Hyperlink.js.map +1 -1
  75. package/dist/elements/Image.d.ts.map +1 -1
  76. package/dist/elements/Image.js +238 -106
  77. package/dist/elements/Image.js.map +1 -1
  78. package/dist/elements/ImageManager.d.ts.map +1 -1
  79. package/dist/elements/ImageManager.js +1 -1
  80. package/dist/elements/ImageManager.js.map +1 -1
  81. package/dist/elements/ImageRun.js +1 -1
  82. package/dist/elements/ImageRun.js.map +1 -1
  83. package/dist/elements/MathElement.js.map +1 -1
  84. package/dist/elements/Paragraph.d.ts +24 -24
  85. package/dist/elements/Paragraph.d.ts.map +1 -1
  86. package/dist/elements/Paragraph.js +181 -188
  87. package/dist/elements/Paragraph.js.map +1 -1
  88. package/dist/elements/PreservedElement.js.map +1 -1
  89. package/dist/elements/PropertyChangeTypes.d.ts.map +1 -1
  90. package/dist/elements/PropertyChangeTypes.js +6 -6
  91. package/dist/elements/PropertyChangeTypes.js.map +1 -1
  92. package/dist/elements/RangeMarker.d.ts.map +1 -1
  93. package/dist/elements/RangeMarker.js.map +1 -1
  94. package/dist/elements/Revision.d.ts.map +1 -1
  95. package/dist/elements/Revision.js +4 -5
  96. package/dist/elements/Revision.js.map +1 -1
  97. package/dist/elements/RevisionContent.js.map +1 -1
  98. package/dist/elements/RevisionManager.d.ts.map +1 -1
  99. package/dist/elements/RevisionManager.js +40 -48
  100. package/dist/elements/RevisionManager.js.map +1 -1
  101. package/dist/elements/Run.d.ts +16 -16
  102. package/dist/elements/Run.d.ts.map +1 -1
  103. package/dist/elements/Run.js +256 -238
  104. package/dist/elements/Run.js.map +1 -1
  105. package/dist/elements/Section.d.ts.map +1 -1
  106. package/dist/elements/Section.js +36 -11
  107. package/dist/elements/Section.js.map +1 -1
  108. package/dist/elements/Shape.d.ts.map +1 -1
  109. package/dist/elements/Shape.js.map +1 -1
  110. package/dist/elements/StructuredDocumentTag.d.ts +6 -6
  111. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  112. package/dist/elements/StructuredDocumentTag.js +99 -104
  113. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  114. package/dist/elements/Table.d.ts +11 -11
  115. package/dist/elements/Table.d.ts.map +1 -1
  116. package/dist/elements/Table.js +102 -107
  117. package/dist/elements/Table.js.map +1 -1
  118. package/dist/elements/TableCell.d.ts +10 -10
  119. package/dist/elements/TableCell.d.ts.map +1 -1
  120. package/dist/elements/TableCell.js +105 -106
  121. package/dist/elements/TableCell.js.map +1 -1
  122. package/dist/elements/TableGridChange.d.ts.map +1 -1
  123. package/dist/elements/TableGridChange.js.map +1 -1
  124. package/dist/elements/TableOfContents.d.ts.map +1 -1
  125. package/dist/elements/TableOfContents.js +4 -4
  126. package/dist/elements/TableOfContents.js.map +1 -1
  127. package/dist/elements/TableOfContentsElement.js.map +1 -1
  128. package/dist/elements/TableRow.d.ts.map +1 -1
  129. package/dist/elements/TableRow.js +13 -6
  130. package/dist/elements/TableRow.js.map +1 -1
  131. package/dist/elements/TextBox.d.ts.map +1 -1
  132. package/dist/elements/TextBox.js +3 -5
  133. package/dist/elements/TextBox.js.map +1 -1
  134. package/dist/formatting/AbstractNumbering.d.ts +4 -4
  135. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  136. package/dist/formatting/AbstractNumbering.js +54 -49
  137. package/dist/formatting/AbstractNumbering.js.map +1 -1
  138. package/dist/formatting/NumberingInstance.d.ts.map +1 -1
  139. package/dist/formatting/NumberingInstance.js +1 -3
  140. package/dist/formatting/NumberingInstance.js.map +1 -1
  141. package/dist/formatting/NumberingLevel.d.ts +5 -5
  142. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  143. package/dist/formatting/NumberingLevel.js +119 -125
  144. package/dist/formatting/NumberingLevel.js.map +1 -1
  145. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  146. package/dist/formatting/NumberingManager.js +9 -9
  147. package/dist/formatting/NumberingManager.js.map +1 -1
  148. package/dist/formatting/Style.d.ts +11 -11
  149. package/dist/formatting/Style.d.ts.map +1 -1
  150. package/dist/formatting/Style.js +219 -247
  151. package/dist/formatting/Style.js.map +1 -1
  152. package/dist/formatting/StylesManager.d.ts +2 -2
  153. package/dist/formatting/StylesManager.d.ts.map +1 -1
  154. package/dist/formatting/StylesManager.js +96 -102
  155. package/dist/formatting/StylesManager.js.map +1 -1
  156. package/dist/helpers/CleanupHelper.d.ts +1 -1
  157. package/dist/helpers/CleanupHelper.d.ts.map +1 -1
  158. package/dist/helpers/CleanupHelper.js +6 -6
  159. package/dist/helpers/CleanupHelper.js.map +1 -1
  160. package/dist/images/ImageOptimizer.js +7 -7
  161. package/dist/images/ImageOptimizer.js.map +1 -1
  162. package/dist/index.d.ts +9 -9
  163. package/dist/index.d.ts.map +1 -1
  164. package/dist/index.js.map +1 -1
  165. package/dist/managers/DrawingManager.js.map +1 -1
  166. package/dist/tracking/DocumentTrackingContext.d.ts.map +1 -1
  167. package/dist/tracking/DocumentTrackingContext.js +23 -7
  168. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  169. package/dist/tracking/TrackingContext.d.ts.map +1 -1
  170. package/dist/tracking/TrackingContext.js.map +1 -1
  171. package/dist/types/compatibility-types.js.map +1 -1
  172. package/dist/types/formatting.js.map +1 -1
  173. package/dist/types/list-types.d.ts +6 -6
  174. package/dist/types/list-types.js.map +1 -1
  175. package/dist/types/settings-types.js.map +1 -1
  176. package/dist/types/styleConfig.d.ts +2 -2
  177. package/dist/types/styleConfig.js.map +1 -1
  178. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  179. package/dist/utils/ChangelogGenerator.js +97 -101
  180. package/dist/utils/ChangelogGenerator.js.map +1 -1
  181. package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
  182. package/dist/utils/CompatibilityUpgrader.js +1 -1
  183. package/dist/utils/CompatibilityUpgrader.js.map +1 -1
  184. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  185. package/dist/utils/InMemoryRevisionAcceptor.js +1 -6
  186. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  187. package/dist/utils/MoveOperationHelper.d.ts.map +1 -1
  188. package/dist/utils/MoveOperationHelper.js +1 -1
  189. package/dist/utils/MoveOperationHelper.js.map +1 -1
  190. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  191. package/dist/utils/RevisionAwareProcessor.js +2 -4
  192. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  193. package/dist/utils/RevisionWalker.d.ts.map +1 -1
  194. package/dist/utils/RevisionWalker.js +4 -12
  195. package/dist/utils/RevisionWalker.js.map +1 -1
  196. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  197. package/dist/utils/SelectiveRevisionAcceptor.js +2 -6
  198. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  199. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  200. package/dist/utils/ShadingResolver.js +1 -1
  201. package/dist/utils/ShadingResolver.js.map +1 -1
  202. package/dist/utils/acceptRevisions.d.ts.map +1 -1
  203. package/dist/utils/acceptRevisions.js +23 -12
  204. package/dist/utils/acceptRevisions.js.map +1 -1
  205. package/dist/utils/cnfStyleDecoder.d.ts +1 -1
  206. package/dist/utils/cnfStyleDecoder.d.ts.map +1 -1
  207. package/dist/utils/cnfStyleDecoder.js +40 -40
  208. package/dist/utils/cnfStyleDecoder.js.map +1 -1
  209. package/dist/utils/corruptionDetection.d.ts.map +1 -1
  210. package/dist/utils/corruptionDetection.js.map +1 -1
  211. package/dist/utils/dateFormatting.js.map +1 -1
  212. package/dist/utils/deepClone.js +1 -1
  213. package/dist/utils/deepClone.js.map +1 -1
  214. package/dist/utils/diagnostics.d.ts.map +1 -1
  215. package/dist/utils/diagnostics.js +1 -1
  216. package/dist/utils/diagnostics.js.map +1 -1
  217. package/dist/utils/errorHandling.js.map +1 -1
  218. package/dist/utils/formatting.d.ts.map +1 -1
  219. package/dist/utils/formatting.js +10 -2
  220. package/dist/utils/formatting.js.map +1 -1
  221. package/dist/utils/list-detection.d.ts +2 -2
  222. package/dist/utils/list-detection.d.ts.map +1 -1
  223. package/dist/utils/list-detection.js +21 -23
  224. package/dist/utils/list-detection.js.map +1 -1
  225. package/dist/utils/logger.d.ts.map +1 -1
  226. package/dist/utils/logger.js +12 -7
  227. package/dist/utils/logger.js.map +1 -1
  228. package/dist/utils/parsingHelpers.js.map +1 -1
  229. package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
  230. package/dist/utils/stripTrackedChanges.js +3 -3
  231. package/dist/utils/stripTrackedChanges.js.map +1 -1
  232. package/dist/utils/textDiff.d.ts +1 -1
  233. package/dist/utils/textDiff.js +8 -8
  234. package/dist/utils/textDiff.js.map +1 -1
  235. package/dist/utils/units.js.map +1 -1
  236. package/dist/utils/validation.d.ts.map +1 -1
  237. package/dist/utils/validation.js +24 -7
  238. package/dist/utils/validation.js.map +1 -1
  239. package/dist/utils/xmlSanitization.d.ts.map +1 -1
  240. package/dist/utils/xmlSanitization.js +3 -3
  241. package/dist/utils/xmlSanitization.js.map +1 -1
  242. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  243. package/dist/validation/RevisionAutoFixer.js +5 -5
  244. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  245. package/dist/validation/RevisionValidator.d.ts.map +1 -1
  246. package/dist/validation/RevisionValidator.js +7 -9
  247. package/dist/validation/RevisionValidator.js.map +1 -1
  248. package/dist/validation/ValidationRules.js +3 -3
  249. package/dist/validation/ValidationRules.js.map +1 -1
  250. package/dist/validation/index.js.map +1 -1
  251. package/dist/xml/XMLBuilder.d.ts +1 -1
  252. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  253. package/dist/xml/XMLBuilder.js +98 -100
  254. package/dist/xml/XMLBuilder.js.map +1 -1
  255. package/dist/xml/XMLParser.d.ts.map +1 -1
  256. package/dist/xml/XMLParser.js +61 -66
  257. package/dist/xml/XMLParser.js.map +1 -1
  258. package/dist/zip/ZipHandler.d.ts.map +1 -1
  259. package/dist/zip/ZipHandler.js.map +1 -1
  260. package/dist/zip/ZipReader.d.ts.map +1 -1
  261. package/dist/zip/ZipReader.js +1 -3
  262. package/dist/zip/ZipReader.js.map +1 -1
  263. package/dist/zip/ZipWriter.d.ts +1 -1
  264. package/dist/zip/ZipWriter.d.ts.map +1 -1
  265. package/dist/zip/ZipWriter.js +28 -36
  266. package/dist/zip/ZipWriter.js.map +1 -1
  267. package/dist/zip/types.js +1 -1
  268. package/dist/zip/types.js.map +1 -1
  269. package/package.json +92 -92
  270. package/src/__tests__/helper-methods.test.ts +512 -512
  271. package/src/constants/legacyCompatFlags.ts +138 -138
  272. package/src/constants/limits.ts +50 -50
  273. package/src/core/Document.ts +985 -1145
  274. package/src/core/DocumentContent.ts +461 -467
  275. package/src/core/DocumentGenerator.ts +1133 -1104
  276. package/src/core/DocumentIdManager.ts +158 -158
  277. package/src/core/DocumentParser.ts +2347 -2716
  278. package/src/core/DocumentValidator.ts +363 -372
  279. package/src/core/Relationship.ts +367 -367
  280. package/src/core/RelationshipManager.ts +429 -428
  281. package/src/elements/AlternateContent.ts +42 -42
  282. package/src/elements/Bookmark.ts +212 -210
  283. package/src/elements/BookmarkManager.ts +247 -250
  284. package/src/elements/Comment.ts +356 -359
  285. package/src/elements/CommentManager.ts +499 -502
  286. package/src/elements/CommonTypes.ts +524 -549
  287. package/src/elements/CustomXml.ts +36 -36
  288. package/src/elements/Endnote.ts +221 -217
  289. package/src/elements/EndnoteManager.ts +246 -249
  290. package/src/elements/Field.ts +1292 -1233
  291. package/src/elements/FieldHelpers.ts +329 -333
  292. package/src/elements/FontManager.ts +336 -339
  293. package/src/elements/Footer.ts +269 -269
  294. package/src/elements/Footnote.ts +221 -217
  295. package/src/elements/FootnoteManager.ts +246 -249
  296. package/src/elements/Header.ts +269 -269
  297. package/src/elements/HeaderFooterManager.ts +219 -219
  298. package/src/elements/Hyperlink.ts +1288 -1193
  299. package/src/elements/Image.ts +1982 -1756
  300. package/src/elements/ImageManager.ts +437 -432
  301. package/src/elements/ImageRun.ts +59 -59
  302. package/src/elements/MathElement.ts +65 -65
  303. package/src/elements/Paragraph.ts +4347 -4287
  304. package/src/elements/PreservedElement.ts +53 -53
  305. package/src/elements/PropertyChangeTypes.ts +458 -442
  306. package/src/elements/RangeMarker.ts +382 -400
  307. package/src/elements/Revision.ts +1198 -1217
  308. package/src/elements/RevisionContent.ts +73 -73
  309. package/src/elements/RevisionManager.ts +1070 -1070
  310. package/src/elements/Run.ts +3103 -3073
  311. package/src/elements/Section.ts +1521 -1421
  312. package/src/elements/Shape.ts +884 -873
  313. package/src/elements/StructuredDocumentTag.ts +1176 -1207
  314. package/src/elements/Table.ts +2468 -2524
  315. package/src/elements/TableCell.ts +1617 -1621
  316. package/src/elements/TableGridChange.ts +149 -151
  317. package/src/elements/TableOfContents.ts +701 -691
  318. package/src/elements/TableOfContentsElement.ts +89 -89
  319. package/src/elements/TableRow.ts +960 -929
  320. package/src/elements/TextBox.ts +766 -768
  321. package/src/formatting/AbstractNumbering.ts +580 -579
  322. package/src/formatting/NumberingInstance.ts +295 -299
  323. package/src/formatting/NumberingLevel.ts +981 -1040
  324. package/src/formatting/NumberingManager.ts +833 -827
  325. package/src/formatting/Style.ts +1785 -1879
  326. package/src/formatting/StylesManager.ts +1090 -1130
  327. package/src/helpers/CleanupHelper.ts +524 -524
  328. package/src/images/ImageOptimizer.ts +274 -274
  329. package/src/index.ts +559 -554
  330. package/src/managers/DrawingManager.ts +319 -319
  331. package/src/tracking/DocumentTrackingContext.ts +687 -674
  332. package/src/tracking/TrackingContext.ts +175 -173
  333. package/src/types/compatibility-types.ts +49 -49
  334. package/src/types/formatting.ts +210 -210
  335. package/src/types/list-types.ts +14 -14
  336. package/src/types/settings-types.ts +59 -59
  337. package/src/types/styleConfig.ts +189 -189
  338. package/src/utils/ChangelogGenerator.ts +1583 -1581
  339. package/src/utils/CompatibilityUpgrader.ts +235 -237
  340. package/src/utils/InMemoryRevisionAcceptor.ts +691 -696
  341. package/src/utils/MoveOperationHelper.ts +233 -238
  342. package/src/utils/RevisionAwareProcessor.ts +518 -526
  343. package/src/utils/RevisionWalker.ts +427 -457
  344. package/src/utils/SelectiveRevisionAcceptor.ts +662 -683
  345. package/src/utils/ShadingResolver.ts +105 -107
  346. package/src/utils/acceptRevisions.ts +723 -714
  347. package/src/utils/cnfStyleDecoder.ts +212 -217
  348. package/src/utils/corruptionDetection.ts +346 -345
  349. package/src/utils/dateFormatting.ts +20 -20
  350. package/src/utils/deepClone.ts +77 -78
  351. package/src/utils/diagnostics.ts +125 -129
  352. package/src/utils/errorHandling.ts +80 -80
  353. package/src/utils/formatting.ts +220 -213
  354. package/src/utils/list-detection.ts +32 -42
  355. package/src/utils/logger.ts +412 -404
  356. package/src/utils/parsingHelpers.ts +190 -190
  357. package/src/utils/stripTrackedChanges.ts +356 -353
  358. package/src/utils/textDiff.ts +100 -100
  359. package/src/utils/units.ts +421 -421
  360. package/src/utils/validation.ts +553 -542
  361. package/src/utils/xmlSanitization.ts +179 -182
  362. package/src/validation/RevisionAutoFixer.ts +541 -542
  363. package/src/validation/RevisionValidator.ts +470 -460
  364. package/src/validation/ValidationRules.ts +338 -338
  365. package/src/validation/index.ts +30 -30
  366. package/src/xml/XMLBuilder.ts +857 -871
  367. package/src/xml/XMLParser.ts +877 -919
  368. package/src/zip/ZipHandler.ts +629 -637
  369. package/src/zip/ZipReader.ts +295 -299
  370. package/src/zip/ZipWriter.ts +374 -390
  371. package/src/zip/types.ts +116 -116
@@ -1,1207 +1,1176 @@
1
- /**
2
- * Structured Document Tag (SDT) - Content control wrapper
3
- *
4
- * SDTs are used by applications like Google Docs to wrap content
5
- * with metadata and control settings. They can contain paragraphs,
6
- * tables, or other block-level elements.
7
- */
8
-
9
- import { XMLBuilder, XMLElement } from "../xml/XMLBuilder";
10
- import { Paragraph } from "./Paragraph";
11
- import { Table } from "./Table";
12
-
13
- /**
14
- * Type of content lock for SDT
15
- */
16
- export type SDTLockType =
17
- | "unlocked"
18
- | "sdtLocked"
19
- | "contentLocked"
20
- | "sdtContentLocked";
21
-
22
- /**
23
- * Content control type
24
- */
25
- export type ContentControlType =
26
- | "richText"
27
- | "plainText"
28
- | "comboBox"
29
- | "dropDownList"
30
- | "datePicker"
31
- | "checkbox"
32
- | "picture"
33
- | "buildingBlock"
34
- | "group"
35
- | "citation"
36
- | "bibliography"
37
- | "docPartList"
38
- | "equation";
39
-
40
- /**
41
- * List item for combo box or dropdown
42
- */
43
- export interface ListItem {
44
- /** Display text shown to user */
45
- displayText: string;
46
- /** Internal value */
47
- value: string;
48
- }
49
-
50
- /**
51
- * Plain text control properties
52
- */
53
- export interface PlainTextProperties {
54
- /** Allow multiple lines */
55
- multiLine?: boolean;
56
- }
57
-
58
- /**
59
- * Combo box control properties
60
- */
61
- export interface ComboBoxProperties {
62
- /** List of items */
63
- items: ListItem[];
64
- /** Last selected value */
65
- lastValue?: string;
66
- }
67
-
68
- /**
69
- * Dropdown list control properties
70
- */
71
- export interface DropDownListProperties {
72
- /** List of items */
73
- items: ListItem[];
74
- /** Last selected value */
75
- lastValue?: string;
76
- }
77
-
78
- /**
79
- * Date picker control properties
80
- */
81
- export interface DatePickerProperties {
82
- /** Date format string (e.g., 'M/d/yyyy') */
83
- dateFormat?: string;
84
- /** Full date value */
85
- fullDate?: Date;
86
- /** Locale ID */
87
- lid?: string;
88
- /** Calendar type */
89
- calendar?:
90
- | "gregorian"
91
- | "hijri"
92
- | "hebrew"
93
- | "taiwan"
94
- | "japan"
95
- | "thai"
96
- | "korean";
97
- }
98
-
99
- /**
100
- * Checkbox control properties
101
- */
102
- export interface CheckboxProperties {
103
- /** Whether the checkbox is checked */
104
- checked?: boolean;
105
- /** Character code for checked state (default: '2612' - ☒) */
106
- checkedState?: string;
107
- /** Character code for unchecked state (default: '2610' - ☐) */
108
- uncheckedState?: string;
109
- }
110
-
111
- /**
112
- * Building block control properties
113
- */
114
- export interface BuildingBlockProperties {
115
- /** Building block gallery name */
116
- gallery?: string;
117
- /** Building block category */
118
- category?: string;
119
- /** Whether to use docPartList (true) or docPartObj (false, default) */
120
- isList?: boolean;
121
- }
122
-
123
- /**
124
- * Placeholder properties for SDT
125
- */
126
- export interface SDTPlaceholder {
127
- /** Name of the document part to use as placeholder */
128
- docPart: string;
129
- }
130
-
131
- /**
132
- * Data binding properties for SDT
133
- */
134
- export interface SDTDataBinding {
135
- /** XPath expression for the data binding */
136
- xpath: string;
137
- /** Namespace prefix mappings */
138
- prefixMappings?: string;
139
- /** Custom XML data store item ID */
140
- storeItemId?: string;
141
- }
142
-
143
- /**
144
- * Properties for a Structured Document Tag
145
- */
146
- export interface SDTProperties {
147
- /** Unique ID for this SDT */
148
- id?: number;
149
- /** Tag value (used by applications) */
150
- tag?: string;
151
- /** Lock type */
152
- lock?: SDTLockType;
153
- /** Alias (display name) */
154
- alias?: string;
155
- /** Temporary placeholder (removed when content is edited) */
156
- temporary?: boolean;
157
- /** Content control type */
158
- controlType?: ContentControlType;
159
- /** Plain text properties */
160
- plainText?: PlainTextProperties;
161
- /** Combo box properties */
162
- comboBox?: ComboBoxProperties;
163
- /** Dropdown list properties */
164
- dropDownList?: DropDownListProperties;
165
- /** Date picker properties */
166
- datePicker?: DatePickerProperties;
167
- /** Checkbox properties */
168
- checkbox?: CheckboxProperties;
169
- /** Building block properties */
170
- buildingBlock?: BuildingBlockProperties;
171
- /** Placeholder (w:placeholder) */
172
- placeholder?: SDTPlaceholder;
173
- /** Data binding (w:dataBinding) */
174
- dataBinding?: SDTDataBinding;
175
- /** Whether SDT is currently showing placeholder content */
176
- showingPlcHdr?: boolean;
177
- }
178
-
179
- /**
180
- * Content that can be wrapped by an SDT
181
- */
182
- export type SDTContent = Table | Paragraph | StructuredDocumentTag;
183
-
184
- /**
185
- * Structured Document Tag class
186
- * Wraps content with metadata and control settings
187
- *
188
- * Example XML:
189
- * ```xml
190
- * <w:sdt>
191
- * <w:sdtPr>
192
- * <w:lock w:val="contentLocked"/>
193
- * <w:id w:val="-258490443"/>
194
- * <w:tag w:val="goog_rdk_0"/>
195
- * </w:sdtPr>
196
- * <w:sdtContent>
197
- * <!-- content here -->
198
- * </w:sdtContent>
199
- * </w:sdt>
200
- * ```
201
- */
202
- export class StructuredDocumentTag {
203
- private properties: SDTProperties;
204
- private content: SDTContent[];
205
-
206
- /**
207
- * Create a new Structured Document Tag
208
- * @param properties - SDT properties
209
- * @param content - Content elements to wrap
210
- */
211
- constructor(properties: SDTProperties = {}, content: SDTContent[] = []) {
212
- this.properties = properties;
213
- this.content = content;
214
- }
215
-
216
- /**
217
- * Get the SDT ID
218
- * @returns SDT ID or undefined
219
- */
220
- getId(): number | undefined {
221
- return this.properties.id;
222
- }
223
-
224
- /**
225
- * Set the SDT ID
226
- * @param id - Unique ID
227
- */
228
- setId(id: number): this {
229
- this.properties.id = id;
230
- return this;
231
- }
232
-
233
- /**
234
- * Get the SDT tag
235
- * @returns Tag value or undefined
236
- */
237
- getTag(): string | undefined {
238
- return this.properties.tag;
239
- }
240
-
241
- /**
242
- * Set the SDT tag
243
- * @param tag - Tag value
244
- */
245
- setTag(tag: string): this {
246
- this.properties.tag = tag;
247
- return this;
248
- }
249
-
250
- /**
251
- * Get the lock type
252
- * @returns Lock type or undefined
253
- */
254
- getLock(): SDTLockType | undefined {
255
- return this.properties.lock;
256
- }
257
-
258
- /**
259
- * Set the lock type
260
- * @param lock - Lock type
261
- */
262
- setLock(lock: SDTLockType): this {
263
- this.properties.lock = lock;
264
- return this;
265
- }
266
-
267
- /**
268
- * Get the alias (display name)
269
- * @returns Alias or undefined
270
- */
271
- getAlias(): string | undefined {
272
- return this.properties.alias;
273
- }
274
-
275
- /**
276
- * Set the alias (display name)
277
- * @param alias - Display name
278
- */
279
- setAlias(alias: string): this {
280
- this.properties.alias = alias;
281
- return this;
282
- }
283
-
284
- /**
285
- * Get the content control type
286
- * @returns Control type or undefined
287
- */
288
- getControlType(): ContentControlType | undefined {
289
- return this.properties.controlType;
290
- }
291
-
292
- /**
293
- * Set the content control type
294
- * @param type - Control type
295
- */
296
- setControlType(type: ContentControlType): this {
297
- this.properties.controlType = type;
298
- return this;
299
- }
300
-
301
- /**
302
- * Get plain text properties
303
- * @returns Plain text properties or undefined
304
- */
305
- getPlainTextProperties(): PlainTextProperties | undefined {
306
- return this.properties.plainText;
307
- }
308
-
309
- /**
310
- * Set plain text properties
311
- * @param properties - Plain text properties
312
- */
313
- setPlainTextProperties(properties: PlainTextProperties): this {
314
- this.properties.controlType = "plainText";
315
- this.properties.plainText = properties;
316
- return this;
317
- }
318
-
319
- /**
320
- * Get combo box properties
321
- * @returns Combo box properties or undefined
322
- */
323
- getComboBoxProperties(): ComboBoxProperties | undefined {
324
- return this.properties.comboBox;
325
- }
326
-
327
- /**
328
- * Set combo box properties
329
- * @param properties - Combo box properties
330
- */
331
- setComboBoxProperties(properties: ComboBoxProperties): this {
332
- this.properties.controlType = "comboBox";
333
- this.properties.comboBox = properties;
334
- return this;
335
- }
336
-
337
- /**
338
- * Get dropdown list properties
339
- * @returns Dropdown list properties or undefined
340
- */
341
- getDropDownListProperties(): DropDownListProperties | undefined {
342
- return this.properties.dropDownList;
343
- }
344
-
345
- /**
346
- * Set dropdown list properties
347
- * @param properties - Dropdown list properties
348
- */
349
- setDropDownListProperties(properties: DropDownListProperties): this {
350
- this.properties.controlType = "dropDownList";
351
- this.properties.dropDownList = properties;
352
- return this;
353
- }
354
-
355
- /**
356
- * Get date picker properties
357
- * @returns Date picker properties or undefined
358
- */
359
- getDatePickerProperties(): DatePickerProperties | undefined {
360
- return this.properties.datePicker;
361
- }
362
-
363
- /**
364
- * Set date picker properties
365
- * @param properties - Date picker properties
366
- */
367
- setDatePickerProperties(properties: DatePickerProperties): this {
368
- this.properties.controlType = "datePicker";
369
- this.properties.datePicker = properties;
370
- return this;
371
- }
372
-
373
- /**
374
- * Get checkbox properties
375
- * @returns Checkbox properties or undefined
376
- */
377
- getCheckboxProperties(): CheckboxProperties | undefined {
378
- return this.properties.checkbox;
379
- }
380
-
381
- /**
382
- * Set checkbox properties
383
- * @param properties - Checkbox properties
384
- */
385
- setCheckboxProperties(properties: CheckboxProperties): this {
386
- this.properties.controlType = "checkbox";
387
- this.properties.checkbox = properties;
388
- return this;
389
- }
390
-
391
- /**
392
- * Get building block properties
393
- * @returns Building block properties or undefined
394
- */
395
- getBuildingBlockProperties(): BuildingBlockProperties | undefined {
396
- return this.properties.buildingBlock;
397
- }
398
-
399
- /**
400
- * Alias for getBuildingBlockProperties() for backward compatibility
401
- * @returns Building block properties or undefined
402
- */
403
- getBuildingBlock(): BuildingBlockProperties | undefined {
404
- return this.getBuildingBlockProperties();
405
- }
406
-
407
- /**
408
- * Set building block properties
409
- * @param properties - Building block properties
410
- */
411
- setBuildingBlockProperties(properties: BuildingBlockProperties): this {
412
- this.properties.controlType = "buildingBlock";
413
- this.properties.buildingBlock = properties;
414
- return this;
415
- }
416
-
417
- /**
418
- * Get list items from combo box or dropdown list
419
- * @returns List items or undefined if not a list control
420
- */
421
- getListItems(): ListItem[] | undefined {
422
- if (this.properties.comboBox) {
423
- return this.properties.comboBox.items;
424
- }
425
- if (this.properties.dropDownList) {
426
- return this.properties.dropDownList.items;
427
- }
428
- return undefined;
429
- }
430
-
431
- /**
432
- * Get date format from date picker
433
- * @returns Date format string or undefined
434
- */
435
- getDateFormat(): string | undefined {
436
- return this.properties.datePicker?.dateFormat;
437
- }
438
-
439
- /**
440
- * Get checked state from checkbox
441
- * @returns True if checkbox is checked, false otherwise
442
- */
443
- isChecked(): boolean {
444
- return this.properties.checkbox?.checked ?? false;
445
- }
446
-
447
- /**
448
- * Get temporary state
449
- * Temporary SDTs are placeholders removed when content is edited
450
- * @returns True if SDT is temporary (placeholder), false otherwise
451
- */
452
- isTemporary(): boolean {
453
- return this.properties.temporary === true;
454
- }
455
-
456
- /**
457
- * Set whether SDT is temporary
458
- * @param temporary - Whether SDT is temporary
459
- * @returns This instance for chaining
460
- */
461
- setTemporary(temporary: boolean): this {
462
- this.properties.temporary = temporary;
463
- return this;
464
- }
465
-
466
- /**
467
- * Get all content elements
468
- * @returns Array of content elements
469
- */
470
- getContent(): SDTContent[] {
471
- return [...this.content];
472
- }
473
-
474
- /**
475
- * Add content element
476
- * @param element - Element to add
477
- */
478
- addContent(element: SDTContent): this {
479
- this.content.push(element);
480
- return this;
481
- }
482
-
483
- /**
484
- * Clear all content
485
- */
486
- clearContent(): this {
487
- this.content = [];
488
- return this;
489
- }
490
-
491
- /**
492
- * Generate XML for this SDT
493
- * @returns XML element
494
- */
495
- toXML(): XMLElement {
496
- const children: XMLElement[] = [];
497
-
498
- // Build sdtPr (properties)
499
- const sdtPrChildren: XMLElement[] = [];
500
-
501
- if (this.properties.lock) {
502
- sdtPrChildren.push(
503
- XMLBuilder.wSelf("lock", { "w:val": this.properties.lock })
504
- );
505
- }
506
-
507
- if (this.properties.id !== undefined) {
508
- sdtPrChildren.push(
509
- XMLBuilder.wSelf("id", { "w:val": this.properties.id.toString() })
510
- );
511
- }
512
-
513
- if (this.properties.tag) {
514
- sdtPrChildren.push(
515
- XMLBuilder.wSelf("tag", { "w:val": this.properties.tag })
516
- );
517
- }
518
-
519
- if (this.properties.alias) {
520
- sdtPrChildren.push(
521
- XMLBuilder.wSelf("alias", { "w:val": this.properties.alias })
522
- );
523
- }
524
-
525
- // Add placeholder
526
- if (this.properties.placeholder) {
527
- sdtPrChildren.push(
528
- XMLBuilder.w("placeholder", {}, [
529
- XMLBuilder.wSelf("docPart", { "w:val": this.properties.placeholder.docPart }),
530
- ])
531
- );
532
- }
533
-
534
- // Add showing placeholder flag
535
- if (this.properties.showingPlcHdr !== undefined) {
536
- sdtPrChildren.push(
537
- XMLBuilder.wSelf("showingPlcHdr", {
538
- "w:val": this.properties.showingPlcHdr ? "true" : "false",
539
- })
540
- );
541
- }
542
-
543
- // Add data binding
544
- if (this.properties.dataBinding) {
545
- const dbAttrs: Record<string, string> = {
546
- "w:xpath": this.properties.dataBinding.xpath,
547
- };
548
- if (this.properties.dataBinding.prefixMappings) {
549
- dbAttrs["w:prefixMappings"] = this.properties.dataBinding.prefixMappings;
550
- }
551
- if (this.properties.dataBinding.storeItemId) {
552
- dbAttrs["w:storeItemID"] = this.properties.dataBinding.storeItemId;
553
- }
554
- sdtPrChildren.push(XMLBuilder.wSelf("dataBinding", dbAttrs));
555
- }
556
-
557
- // Add control type-specific XML
558
- if (this.properties.controlType) {
559
- switch (this.properties.controlType) {
560
- case "richText":
561
- sdtPrChildren.push(XMLBuilder.wSelf("richText", {}));
562
- break;
563
-
564
- case "plainText":
565
- if (this.properties.plainText) {
566
- const attrs: Record<string, string> = {};
567
- if (this.properties.plainText.multiLine !== undefined) {
568
- attrs["w:multiLine"] = this.properties.plainText.multiLine
569
- ? "1"
570
- : "0";
571
- }
572
- sdtPrChildren.push(XMLBuilder.wSelf("text", attrs));
573
- } else {
574
- sdtPrChildren.push(XMLBuilder.wSelf("text", {}));
575
- }
576
- break;
577
-
578
- case "comboBox":
579
- if (this.properties.comboBox) {
580
- const comboBoxChildren: XMLElement[] = [];
581
- for (const item of this.properties.comboBox.items) {
582
- comboBoxChildren.push(
583
- XMLBuilder.wSelf("listItem", {
584
- "w:displayText": item.displayText,
585
- "w:value": item.value,
586
- })
587
- );
588
- }
589
- sdtPrChildren.push(XMLBuilder.w("comboBox", {}, comboBoxChildren));
590
- }
591
- break;
592
-
593
- case "dropDownList":
594
- if (this.properties.dropDownList) {
595
- const dropDownChildren: XMLElement[] = [];
596
- for (const item of this.properties.dropDownList.items) {
597
- dropDownChildren.push(
598
- XMLBuilder.wSelf("listItem", {
599
- "w:displayText": item.displayText,
600
- "w:value": item.value,
601
- })
602
- );
603
- }
604
- sdtPrChildren.push(
605
- XMLBuilder.w("dropDownList", {}, dropDownChildren)
606
- );
607
- }
608
- break;
609
-
610
- case "datePicker":
611
- if (this.properties.datePicker) {
612
- // Per ECMA-376, w:date has w:fullDate as attribute; dateFormat, lid,
613
- // storeMappedDataAs, and calendar are child elements with w:val
614
- const dateAttrs: Record<string, string> = {};
615
- if (this.properties.datePicker.fullDate) {
616
- dateAttrs["w:fullDate"] =
617
- this.properties.datePicker.fullDate.toISOString();
618
- }
619
- const dateChildren: XMLElement[] = [];
620
- if (this.properties.datePicker.dateFormat) {
621
- dateChildren.push(XMLBuilder.wSelf("dateFormat", {
622
- "w:val": this.properties.datePicker.dateFormat,
623
- }));
624
- }
625
- if (this.properties.datePicker.lid) {
626
- dateChildren.push(XMLBuilder.wSelf("lid", {
627
- "w:val": this.properties.datePicker.lid,
628
- }));
629
- }
630
- if (this.properties.datePicker.calendar) {
631
- dateChildren.push(XMLBuilder.wSelf("calendar", {
632
- "w:val": this.properties.datePicker.calendar,
633
- }));
634
- }
635
- if (dateChildren.length > 0) {
636
- sdtPrChildren.push(XMLBuilder.w("date", dateAttrs, dateChildren));
637
- } else {
638
- sdtPrChildren.push(XMLBuilder.wSelf("date", dateAttrs));
639
- }
640
- }
641
- break;
642
-
643
- case "checkbox":
644
- if (this.properties.checkbox) {
645
- const checkboxChildren: XMLElement[] = [];
646
-
647
- // Add checked state - use w14 namespace per OOXML spec
648
- if (this.properties.checkbox.checked !== undefined) {
649
- checkboxChildren.push(
650
- XMLBuilder.w14Self("checked", {
651
- "w14:val": this.properties.checkbox.checked ? "1" : "0",
652
- })
653
- );
654
- }
655
-
656
- // Add checked state symbol - use w14 namespace per OOXML spec
657
- if (this.properties.checkbox.checkedState) {
658
- checkboxChildren.push(
659
- XMLBuilder.w14Self("checkedState", {
660
- "w14:val": this.properties.checkbox.checkedState,
661
- "w14:font": "MS Gothic",
662
- })
663
- );
664
- }
665
-
666
- // Add unchecked state symbol - use w14 namespace per OOXML spec
667
- if (this.properties.checkbox.uncheckedState) {
668
- checkboxChildren.push(
669
- XMLBuilder.w14Self("uncheckedState", {
670
- "w14:val": this.properties.checkbox.uncheckedState,
671
- "w14:font": "MS Gothic",
672
- })
673
- );
674
- }
675
-
676
- sdtPrChildren.push(
677
- XMLBuilder.w14("checkbox", {}, checkboxChildren)
678
- );
679
- }
680
- break;
681
-
682
- case "picture":
683
- sdtPrChildren.push(XMLBuilder.wSelf("picture", {}));
684
- break;
685
-
686
- case "buildingBlock":
687
- if (this.properties.buildingBlock) {
688
- const bbChildren: XMLElement[] = [];
689
- if (this.properties.buildingBlock.gallery) {
690
- bbChildren.push(
691
- XMLBuilder.wSelf("docPartGallery", {
692
- "w:val": this.properties.buildingBlock.gallery,
693
- })
694
- );
695
- }
696
- if (this.properties.buildingBlock.category) {
697
- bbChildren.push(
698
- XMLBuilder.wSelf("docPartCategory", {
699
- "w:val": this.properties.buildingBlock.category,
700
- })
701
- );
702
- }
703
- sdtPrChildren.push(XMLBuilder.w("docPartObj", {}, bbChildren));
704
- }
705
- break;
706
-
707
- case "group":
708
- sdtPrChildren.push(XMLBuilder.wSelf("group", {}));
709
- break;
710
-
711
- case "citation":
712
- sdtPrChildren.push(XMLBuilder.wSelf("citation", {}));
713
- break;
714
-
715
- case "bibliography":
716
- sdtPrChildren.push(XMLBuilder.wSelf("bibliography", {}));
717
- break;
718
-
719
- case "equation":
720
- sdtPrChildren.push(XMLBuilder.wSelf("equation", {}));
721
- break;
722
-
723
- case "docPartList":
724
- if (this.properties.buildingBlock) {
725
- const dplChildren: XMLElement[] = [];
726
- if (this.properties.buildingBlock.gallery) {
727
- dplChildren.push(
728
- XMLBuilder.wSelf("docPartGallery", {
729
- "w:val": this.properties.buildingBlock.gallery,
730
- })
731
- );
732
- }
733
- if (this.properties.buildingBlock.category) {
734
- dplChildren.push(
735
- XMLBuilder.wSelf("docPartCategory", {
736
- "w:val": this.properties.buildingBlock.category,
737
- })
738
- );
739
- }
740
- sdtPrChildren.push(XMLBuilder.w("docPartList", {}, dplChildren));
741
- }
742
- break;
743
- }
744
- }
745
-
746
- if (sdtPrChildren.length > 0) {
747
- children.push(XMLBuilder.w("sdtPr", {}, sdtPrChildren));
748
- }
749
-
750
- // Build sdtContent
751
- const sdtContentChildren: XMLElement[] = [];
752
- for (const element of this.content) {
753
- sdtContentChildren.push(element.toXML());
754
- }
755
-
756
- children.push(XMLBuilder.w("sdtContent", {}, sdtContentChildren));
757
-
758
- return XMLBuilder.w("sdt", {}, children);
759
- }
760
-
761
- /**
762
- * Create an SDT wrapping a table (common for Google Docs)
763
- * @param table - Table to wrap
764
- * @param tag - Optional tag value
765
- * @param lock - Optional lock type (default: unlocked for editability)
766
- * @returns New SDT instance
767
- * @example
768
- * ```typescript
769
- * // Unlocked table (editable in Word) - RECOMMENDED
770
- * const sdt = StructuredDocumentTag.wrapTable(table);
771
- *
772
- * // Locked table (read-only in Word)
773
- * const lockedSdt = StructuredDocumentTag.wrapTable(table, 'my-table', 'contentLocked');
774
- * ```
775
- */
776
- static wrapTable(
777
- table: Table,
778
- tag = "goog_rdk_0",
779
- lock?: SDTLockType
780
- ): StructuredDocumentTag {
781
- return new StructuredDocumentTag(
782
- {
783
- id: Date.now() % 1000000000, // Generate a reasonable ID
784
- tag,
785
- lock, // Only set if provided - defaults to unlocked
786
- },
787
- [table]
788
- );
789
- }
790
-
791
- /**
792
- * Create an SDT wrapping a paragraph
793
- * @param paragraph - Paragraph to wrap
794
- * @param tag - Optional tag value
795
- * @returns New SDT instance
796
- */
797
- static wrapParagraph(
798
- paragraph: Paragraph,
799
- tag?: string
800
- ): StructuredDocumentTag {
801
- return new StructuredDocumentTag(
802
- {
803
- id: Date.now() % 1000000000,
804
- tag,
805
- },
806
- [paragraph]
807
- );
808
- }
809
-
810
- /**
811
- * Create an empty SDT
812
- * @param properties - SDT properties
813
- * @returns New SDT instance
814
- */
815
- static create(properties: SDTProperties = {}): StructuredDocumentTag {
816
- return new StructuredDocumentTag(properties);
817
- }
818
-
819
- /**
820
- * Create a rich text content control
821
- * @param content - Initial content
822
- * @param properties - Additional SDT properties
823
- * @returns New SDT instance
824
- */
825
- static createRichText(
826
- content: SDTContent[] = [],
827
- properties: Partial<SDTProperties> = {}
828
- ): StructuredDocumentTag {
829
- return new StructuredDocumentTag(
830
- {
831
- id: Date.now() % 1000000000,
832
- controlType: "richText",
833
- ...properties,
834
- },
835
- content
836
- );
837
- }
838
-
839
- /**
840
- * Create a plain text content control
841
- * @param content - Initial content
842
- * @param multiLine - Allow multiple lines
843
- * @param properties - Additional SDT properties
844
- * @returns New SDT instance
845
- */
846
- static createPlainText(
847
- content: SDTContent[] = [],
848
- multiLine = false,
849
- properties: Partial<SDTProperties> = {}
850
- ): StructuredDocumentTag {
851
- return new StructuredDocumentTag(
852
- {
853
- id: Date.now() % 1000000000,
854
- controlType: "plainText",
855
- plainText: { multiLine },
856
- ...properties,
857
- },
858
- content
859
- );
860
- }
861
-
862
- /**
863
- * Create a combo box content control
864
- * @param items - List items
865
- * @param content - Initial content
866
- * @param properties - Additional SDT properties
867
- * @returns New SDT instance
868
- */
869
- static createComboBox(
870
- items: ListItem[],
871
- content: SDTContent[] = [],
872
- properties: Partial<SDTProperties> = {}
873
- ): StructuredDocumentTag {
874
- return new StructuredDocumentTag(
875
- {
876
- id: Date.now() % 1000000000,
877
- controlType: "comboBox",
878
- comboBox: { items },
879
- ...properties,
880
- },
881
- content
882
- );
883
- }
884
-
885
- /**
886
- * Create a dropdown list content control
887
- * @param items - List items
888
- * @param content - Initial content
889
- * @param properties - Additional SDT properties
890
- * @returns New SDT instance
891
- */
892
- static createDropDownList(
893
- items: ListItem[],
894
- content: SDTContent[] = [],
895
- properties: Partial<SDTProperties> = {}
896
- ): StructuredDocumentTag {
897
- return new StructuredDocumentTag(
898
- {
899
- id: Date.now() % 1000000000,
900
- controlType: "dropDownList",
901
- dropDownList: { items },
902
- ...properties,
903
- },
904
- content
905
- );
906
- }
907
-
908
- /**
909
- * Create a date picker content control
910
- * @param dateFormat - Date format string (e.g., 'M/d/yyyy')
911
- * @param content - Initial content
912
- * @param properties - Additional SDT properties
913
- * @returns New SDT instance
914
- */
915
- static createDatePicker(
916
- dateFormat = "M/d/yyyy",
917
- content: SDTContent[] = [],
918
- properties: Partial<SDTProperties> = {}
919
- ): StructuredDocumentTag {
920
- return new StructuredDocumentTag(
921
- {
922
- id: Date.now() % 1000000000,
923
- controlType: "datePicker",
924
- datePicker: { dateFormat },
925
- ...properties,
926
- },
927
- content
928
- );
929
- }
930
-
931
- /**
932
- * Create a checkbox content control
933
- * @param checked - Initial checked state
934
- * @param content - Initial content
935
- * @param properties - Additional SDT properties
936
- * @returns New SDT instance
937
- */
938
- static createCheckbox(
939
- checked = false,
940
- content: SDTContent[] = [],
941
- properties: Partial<SDTProperties> = {}
942
- ): StructuredDocumentTag {
943
- return new StructuredDocumentTag(
944
- {
945
- id: Date.now() % 1000000000,
946
- controlType: "checkbox",
947
- checkbox: {
948
- checked,
949
- checkedState: "2612", // ☒
950
- uncheckedState: "2610", // ☐
951
- },
952
- ...properties,
953
- },
954
- content
955
- );
956
- }
957
-
958
- /**
959
- * Create a picture content control
960
- * @param content - Initial content (typically contains an image)
961
- * @param properties - Additional SDT properties
962
- * @returns New SDT instance
963
- */
964
- static createPicture(
965
- content: SDTContent[] = [],
966
- properties: Partial<SDTProperties> = {}
967
- ): StructuredDocumentTag {
968
- return new StructuredDocumentTag(
969
- {
970
- id: Date.now() % 1000000000,
971
- controlType: "picture",
972
- ...properties,
973
- },
974
- content
975
- );
976
- }
977
-
978
- /**
979
- * Create a building block content control
980
- * @param gallery - Building block gallery name
981
- * @param category - Building block category
982
- * @param content - Initial content
983
- * @param properties - Additional SDT properties
984
- * @returns New SDT instance
985
- */
986
- static createBuildingBlock(
987
- gallery: string,
988
- category: string,
989
- content: SDTContent[] = [],
990
- properties: Partial<SDTProperties> = {}
991
- ): StructuredDocumentTag {
992
- return new StructuredDocumentTag(
993
- {
994
- id: Date.now() % 1000000000,
995
- controlType: "buildingBlock",
996
- buildingBlock: { gallery, category },
997
- ...properties,
998
- },
999
- content
1000
- );
1001
- }
1002
-
1003
- /**
1004
- * Create a group content control
1005
- * @param content - Initial content
1006
- * @param properties - Additional SDT properties
1007
- * @returns New SDT instance
1008
- */
1009
- static createGroup(
1010
- content: SDTContent[] = [],
1011
- properties: Partial<SDTProperties> = {}
1012
- ): StructuredDocumentTag {
1013
- return new StructuredDocumentTag(
1014
- {
1015
- id: Date.now() % 1000000000,
1016
- controlType: "group",
1017
- lock: "sdtContentLocked", // Groups typically lock content
1018
- ...properties,
1019
- },
1020
- content
1021
- );
1022
- }
1023
-
1024
- /**
1025
- * Unlocks the SDT content (allows editing)
1026
- * Removes any lock that prevents content modification
1027
- * @returns This SDT for chaining
1028
- * @example
1029
- * ```typescript
1030
- * // Unlock a locked SDT to enable editing
1031
- * sdt.unlock();
1032
- *
1033
- * // Chain with other modifications
1034
- * sdt.unlock().setTag('editable-content');
1035
- * ```
1036
- */
1037
- unlock(): this {
1038
- delete this.properties.lock;
1039
- return this;
1040
- }
1041
-
1042
- /**
1043
- * Checks if SDT content is locked in any way
1044
- * @returns True if content is locked (contentLocked, sdtLocked, or sdtContentLocked)
1045
- * @example
1046
- * ```typescript
1047
- * if (sdt.isLocked()) {
1048
- * console.log('SDT is locked - unlocking for editing');
1049
- * sdt.unlock();
1050
- * }
1051
- * ```
1052
- */
1053
- isLocked(): boolean {
1054
- const lock = this.properties.lock;
1055
- return (
1056
- lock === "contentLocked" ||
1057
- lock === "sdtContentLocked" ||
1058
- lock === "sdtLocked"
1059
- );
1060
- }
1061
-
1062
- /**
1063
- * Checks if SDT content can be edited by users
1064
- * @returns True if content can be modified (not locked by contentLocked or sdtContentLocked)
1065
- * @example
1066
- * ```typescript
1067
- * const editable = sdt.isContentEditable();
1068
- * console.log(editable ? 'Can edit' : 'Cannot edit');
1069
- * ```
1070
- */
1071
- isContentEditable(): boolean {
1072
- const lock = this.properties.lock;
1073
- return lock !== "contentLocked" && lock !== "sdtContentLocked";
1074
- }
1075
-
1076
- /**
1077
- * Get the placeholder configuration
1078
- */
1079
- getPlaceholder(): SDTPlaceholder | undefined {
1080
- return this.properties.placeholder;
1081
- }
1082
-
1083
- /**
1084
- * Set the placeholder (w:placeholder/w:docPart)
1085
- * @param docPart - Name of the document part to use as placeholder
1086
- */
1087
- setPlaceholder(docPart: string): this {
1088
- this.properties.placeholder = { docPart };
1089
- return this;
1090
- }
1091
-
1092
- /**
1093
- * Get the data binding configuration
1094
- */
1095
- getDataBinding(): SDTDataBinding | undefined {
1096
- return this.properties.dataBinding;
1097
- }
1098
-
1099
- /**
1100
- * Set the data binding (w:dataBinding)
1101
- * @param xpath - XPath expression
1102
- * @param prefixMappings - Namespace prefix mappings
1103
- * @param storeItemId - Custom XML data store item ID
1104
- */
1105
- setDataBinding(xpath: string, prefixMappings?: string, storeItemId?: string): this {
1106
- this.properties.dataBinding = { xpath, prefixMappings, storeItemId };
1107
- return this;
1108
- }
1109
-
1110
- /**
1111
- * Get whether the SDT is currently showing placeholder content
1112
- */
1113
- isShowingPlaceholder(): boolean {
1114
- return this.properties.showingPlcHdr === true;
1115
- }
1116
-
1117
- /**
1118
- * Set whether the SDT is showing placeholder content
1119
- * @param val - Whether placeholder is showing
1120
- */
1121
- setShowingPlaceholder(val: boolean): this {
1122
- this.properties.showingPlcHdr = val;
1123
- return this;
1124
- }
1125
-
1126
- /**
1127
- * Create a citation content control
1128
- * @param content - Initial content
1129
- * @param properties - Additional SDT properties
1130
- */
1131
- static createCitation(
1132
- content: SDTContent[] = [],
1133
- properties: Partial<SDTProperties> = {}
1134
- ): StructuredDocumentTag {
1135
- return new StructuredDocumentTag(
1136
- {
1137
- id: Date.now() % 1000000000,
1138
- controlType: "citation",
1139
- ...properties,
1140
- },
1141
- content
1142
- );
1143
- }
1144
-
1145
- /**
1146
- * Create a bibliography content control
1147
- * @param content - Initial content
1148
- * @param properties - Additional SDT properties
1149
- */
1150
- static createBibliography(
1151
- content: SDTContent[] = [],
1152
- properties: Partial<SDTProperties> = {}
1153
- ): StructuredDocumentTag {
1154
- return new StructuredDocumentTag(
1155
- {
1156
- id: Date.now() % 1000000000,
1157
- controlType: "bibliography",
1158
- ...properties,
1159
- },
1160
- content
1161
- );
1162
- }
1163
-
1164
- /**
1165
- * Create a document part list content control
1166
- * Uses w:docPartList instead of w:docPartObj
1167
- * @param gallery - Building block gallery name
1168
- * @param category - Building block category
1169
- * @param content - Initial content
1170
- * @param properties - Additional SDT properties
1171
- */
1172
- static createDocPartList(
1173
- gallery: string,
1174
- category: string,
1175
- content: SDTContent[] = [],
1176
- properties: Partial<SDTProperties> = {}
1177
- ): StructuredDocumentTag {
1178
- return new StructuredDocumentTag(
1179
- {
1180
- id: Date.now() % 1000000000,
1181
- controlType: "docPartList",
1182
- buildingBlock: { gallery, category, isList: true },
1183
- ...properties,
1184
- },
1185
- content
1186
- );
1187
- }
1188
-
1189
- /**
1190
- * Create an equation content control
1191
- * @param content - Initial content
1192
- * @param properties - Additional SDT properties
1193
- */
1194
- static createEquation(
1195
- content: SDTContent[] = [],
1196
- properties: Partial<SDTProperties> = {}
1197
- ): StructuredDocumentTag {
1198
- return new StructuredDocumentTag(
1199
- {
1200
- id: Date.now() % 1000000000,
1201
- controlType: "equation",
1202
- ...properties,
1203
- },
1204
- content
1205
- );
1206
- }
1207
- }
1
+ /**
2
+ * Structured Document Tag (SDT) - Content control wrapper
3
+ *
4
+ * SDTs are used by applications like Google Docs to wrap content
5
+ * with metadata and control settings. They can contain paragraphs,
6
+ * tables, or other block-level elements.
7
+ */
8
+
9
+ import { XMLBuilder, XMLElement } from '../xml/XMLBuilder';
10
+ import { Paragraph } from './Paragraph';
11
+ import { Table } from './Table';
12
+
13
+ /**
14
+ * Type of content lock for SDT
15
+ */
16
+ export type SDTLockType = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
17
+
18
+ /**
19
+ * Content control type
20
+ */
21
+ export type ContentControlType =
22
+ | 'richText'
23
+ | 'plainText'
24
+ | 'comboBox'
25
+ | 'dropDownList'
26
+ | 'datePicker'
27
+ | 'checkbox'
28
+ | 'picture'
29
+ | 'buildingBlock'
30
+ | 'group'
31
+ | 'citation'
32
+ | 'bibliography'
33
+ | 'docPartList'
34
+ | 'equation';
35
+
36
+ /**
37
+ * List item for combo box or dropdown
38
+ */
39
+ export interface ListItem {
40
+ /** Display text shown to user */
41
+ displayText: string;
42
+ /** Internal value */
43
+ value: string;
44
+ }
45
+
46
+ /**
47
+ * Plain text control properties
48
+ */
49
+ export interface PlainTextProperties {
50
+ /** Allow multiple lines */
51
+ multiLine?: boolean;
52
+ }
53
+
54
+ /**
55
+ * Combo box control properties
56
+ */
57
+ export interface ComboBoxProperties {
58
+ /** List of items */
59
+ items: ListItem[];
60
+ /** Last selected value */
61
+ lastValue?: string;
62
+ }
63
+
64
+ /**
65
+ * Dropdown list control properties
66
+ */
67
+ export interface DropDownListProperties {
68
+ /** List of items */
69
+ items: ListItem[];
70
+ /** Last selected value */
71
+ lastValue?: string;
72
+ }
73
+
74
+ /**
75
+ * Date picker control properties
76
+ */
77
+ export interface DatePickerProperties {
78
+ /** Date format string (e.g., 'M/d/yyyy') */
79
+ dateFormat?: string;
80
+ /** Full date value */
81
+ fullDate?: Date;
82
+ /** Locale ID */
83
+ lid?: string;
84
+ /** Calendar type */
85
+ calendar?: 'gregorian' | 'hijri' | 'hebrew' | 'taiwan' | 'japan' | 'thai' | 'korean';
86
+ }
87
+
88
+ /**
89
+ * Checkbox control properties
90
+ */
91
+ export interface CheckboxProperties {
92
+ /** Whether the checkbox is checked */
93
+ checked?: boolean;
94
+ /** Character code for checked state (default: '2612' - ☒) */
95
+ checkedState?: string;
96
+ /** Character code for unchecked state (default: '2610' - ☐) */
97
+ uncheckedState?: string;
98
+ }
99
+
100
+ /**
101
+ * Building block control properties
102
+ */
103
+ export interface BuildingBlockProperties {
104
+ /** Building block gallery name */
105
+ gallery?: string;
106
+ /** Building block category */
107
+ category?: string;
108
+ /** Whether to use docPartList (true) or docPartObj (false, default) */
109
+ isList?: boolean;
110
+ }
111
+
112
+ /**
113
+ * Placeholder properties for SDT
114
+ */
115
+ export interface SDTPlaceholder {
116
+ /** Name of the document part to use as placeholder */
117
+ docPart: string;
118
+ }
119
+
120
+ /**
121
+ * Data binding properties for SDT
122
+ */
123
+ export interface SDTDataBinding {
124
+ /** XPath expression for the data binding */
125
+ xpath: string;
126
+ /** Namespace prefix mappings */
127
+ prefixMappings?: string;
128
+ /** Custom XML data store item ID */
129
+ storeItemId?: string;
130
+ }
131
+
132
+ /**
133
+ * Properties for a Structured Document Tag
134
+ */
135
+ export interface SDTProperties {
136
+ /** Unique ID for this SDT */
137
+ id?: number;
138
+ /** Tag value (used by applications) */
139
+ tag?: string;
140
+ /** Lock type */
141
+ lock?: SDTLockType;
142
+ /** Alias (display name) */
143
+ alias?: string;
144
+ /** Temporary placeholder (removed when content is edited) */
145
+ temporary?: boolean;
146
+ /** Content control type */
147
+ controlType?: ContentControlType;
148
+ /** Plain text properties */
149
+ plainText?: PlainTextProperties;
150
+ /** Combo box properties */
151
+ comboBox?: ComboBoxProperties;
152
+ /** Dropdown list properties */
153
+ dropDownList?: DropDownListProperties;
154
+ /** Date picker properties */
155
+ datePicker?: DatePickerProperties;
156
+ /** Checkbox properties */
157
+ checkbox?: CheckboxProperties;
158
+ /** Building block properties */
159
+ buildingBlock?: BuildingBlockProperties;
160
+ /** Placeholder (w:placeholder) */
161
+ placeholder?: SDTPlaceholder;
162
+ /** Data binding (w:dataBinding) */
163
+ dataBinding?: SDTDataBinding;
164
+ /** Whether SDT is currently showing placeholder content */
165
+ showingPlcHdr?: boolean;
166
+ }
167
+
168
+ /**
169
+ * Content that can be wrapped by an SDT
170
+ */
171
+ export type SDTContent = Table | Paragraph | StructuredDocumentTag;
172
+
173
+ /**
174
+ * Structured Document Tag class
175
+ * Wraps content with metadata and control settings
176
+ *
177
+ * Example XML:
178
+ * ```xml
179
+ * <w:sdt>
180
+ * <w:sdtPr>
181
+ * <w:lock w:val="contentLocked"/>
182
+ * <w:id w:val="-258490443"/>
183
+ * <w:tag w:val="goog_rdk_0"/>
184
+ * </w:sdtPr>
185
+ * <w:sdtContent>
186
+ * <!-- content here -->
187
+ * </w:sdtContent>
188
+ * </w:sdt>
189
+ * ```
190
+ */
191
+ export class StructuredDocumentTag {
192
+ private properties: SDTProperties;
193
+ private content: SDTContent[];
194
+
195
+ /**
196
+ * Create a new Structured Document Tag
197
+ * @param properties - SDT properties
198
+ * @param content - Content elements to wrap
199
+ */
200
+ constructor(properties: SDTProperties = {}, content: SDTContent[] = []) {
201
+ this.properties = properties;
202
+ this.content = content;
203
+ }
204
+
205
+ /**
206
+ * Get the SDT ID
207
+ * @returns SDT ID or undefined
208
+ */
209
+ getId(): number | undefined {
210
+ return this.properties.id;
211
+ }
212
+
213
+ /**
214
+ * Set the SDT ID
215
+ * @param id - Unique ID
216
+ */
217
+ setId(id: number): this {
218
+ this.properties.id = id;
219
+ return this;
220
+ }
221
+
222
+ /**
223
+ * Get the SDT tag
224
+ * @returns Tag value or undefined
225
+ */
226
+ getTag(): string | undefined {
227
+ return this.properties.tag;
228
+ }
229
+
230
+ /**
231
+ * Set the SDT tag
232
+ * @param tag - Tag value
233
+ */
234
+ setTag(tag: string): this {
235
+ this.properties.tag = tag;
236
+ return this;
237
+ }
238
+
239
+ /**
240
+ * Get the lock type
241
+ * @returns Lock type or undefined
242
+ */
243
+ getLock(): SDTLockType | undefined {
244
+ return this.properties.lock;
245
+ }
246
+
247
+ /**
248
+ * Set the lock type
249
+ * @param lock - Lock type
250
+ */
251
+ setLock(lock: SDTLockType): this {
252
+ this.properties.lock = lock;
253
+ return this;
254
+ }
255
+
256
+ /**
257
+ * Get the alias (display name)
258
+ * @returns Alias or undefined
259
+ */
260
+ getAlias(): string | undefined {
261
+ return this.properties.alias;
262
+ }
263
+
264
+ /**
265
+ * Set the alias (display name)
266
+ * @param alias - Display name
267
+ */
268
+ setAlias(alias: string): this {
269
+ this.properties.alias = alias;
270
+ return this;
271
+ }
272
+
273
+ /**
274
+ * Get the content control type
275
+ * @returns Control type or undefined
276
+ */
277
+ getControlType(): ContentControlType | undefined {
278
+ return this.properties.controlType;
279
+ }
280
+
281
+ /**
282
+ * Set the content control type
283
+ * @param type - Control type
284
+ */
285
+ setControlType(type: ContentControlType): this {
286
+ this.properties.controlType = type;
287
+ return this;
288
+ }
289
+
290
+ /**
291
+ * Get plain text properties
292
+ * @returns Plain text properties or undefined
293
+ */
294
+ getPlainTextProperties(): PlainTextProperties | undefined {
295
+ return this.properties.plainText;
296
+ }
297
+
298
+ /**
299
+ * Set plain text properties
300
+ * @param properties - Plain text properties
301
+ */
302
+ setPlainTextProperties(properties: PlainTextProperties): this {
303
+ this.properties.controlType = 'plainText';
304
+ this.properties.plainText = properties;
305
+ return this;
306
+ }
307
+
308
+ /**
309
+ * Get combo box properties
310
+ * @returns Combo box properties or undefined
311
+ */
312
+ getComboBoxProperties(): ComboBoxProperties | undefined {
313
+ return this.properties.comboBox;
314
+ }
315
+
316
+ /**
317
+ * Set combo box properties
318
+ * @param properties - Combo box properties
319
+ */
320
+ setComboBoxProperties(properties: ComboBoxProperties): this {
321
+ this.properties.controlType = 'comboBox';
322
+ this.properties.comboBox = properties;
323
+ return this;
324
+ }
325
+
326
+ /**
327
+ * Get dropdown list properties
328
+ * @returns Dropdown list properties or undefined
329
+ */
330
+ getDropDownListProperties(): DropDownListProperties | undefined {
331
+ return this.properties.dropDownList;
332
+ }
333
+
334
+ /**
335
+ * Set dropdown list properties
336
+ * @param properties - Dropdown list properties
337
+ */
338
+ setDropDownListProperties(properties: DropDownListProperties): this {
339
+ this.properties.controlType = 'dropDownList';
340
+ this.properties.dropDownList = properties;
341
+ return this;
342
+ }
343
+
344
+ /**
345
+ * Get date picker properties
346
+ * @returns Date picker properties or undefined
347
+ */
348
+ getDatePickerProperties(): DatePickerProperties | undefined {
349
+ return this.properties.datePicker;
350
+ }
351
+
352
+ /**
353
+ * Set date picker properties
354
+ * @param properties - Date picker properties
355
+ */
356
+ setDatePickerProperties(properties: DatePickerProperties): this {
357
+ this.properties.controlType = 'datePicker';
358
+ this.properties.datePicker = properties;
359
+ return this;
360
+ }
361
+
362
+ /**
363
+ * Get checkbox properties
364
+ * @returns Checkbox properties or undefined
365
+ */
366
+ getCheckboxProperties(): CheckboxProperties | undefined {
367
+ return this.properties.checkbox;
368
+ }
369
+
370
+ /**
371
+ * Set checkbox properties
372
+ * @param properties - Checkbox properties
373
+ */
374
+ setCheckboxProperties(properties: CheckboxProperties): this {
375
+ this.properties.controlType = 'checkbox';
376
+ this.properties.checkbox = properties;
377
+ return this;
378
+ }
379
+
380
+ /**
381
+ * Get building block properties
382
+ * @returns Building block properties or undefined
383
+ */
384
+ getBuildingBlockProperties(): BuildingBlockProperties | undefined {
385
+ return this.properties.buildingBlock;
386
+ }
387
+
388
+ /**
389
+ * Alias for getBuildingBlockProperties() for backward compatibility
390
+ * @returns Building block properties or undefined
391
+ */
392
+ getBuildingBlock(): BuildingBlockProperties | undefined {
393
+ return this.getBuildingBlockProperties();
394
+ }
395
+
396
+ /**
397
+ * Set building block properties
398
+ * @param properties - Building block properties
399
+ */
400
+ setBuildingBlockProperties(properties: BuildingBlockProperties): this {
401
+ this.properties.controlType = 'buildingBlock';
402
+ this.properties.buildingBlock = properties;
403
+ return this;
404
+ }
405
+
406
+ /**
407
+ * Get list items from combo box or dropdown list
408
+ * @returns List items or undefined if not a list control
409
+ */
410
+ getListItems(): ListItem[] | undefined {
411
+ if (this.properties.comboBox) {
412
+ return this.properties.comboBox.items;
413
+ }
414
+ if (this.properties.dropDownList) {
415
+ return this.properties.dropDownList.items;
416
+ }
417
+ return undefined;
418
+ }
419
+
420
+ /**
421
+ * Get date format from date picker
422
+ * @returns Date format string or undefined
423
+ */
424
+ getDateFormat(): string | undefined {
425
+ return this.properties.datePicker?.dateFormat;
426
+ }
427
+
428
+ /**
429
+ * Get checked state from checkbox
430
+ * @returns True if checkbox is checked, false otherwise
431
+ */
432
+ isChecked(): boolean {
433
+ return this.properties.checkbox?.checked ?? false;
434
+ }
435
+
436
+ /**
437
+ * Get temporary state
438
+ * Temporary SDTs are placeholders removed when content is edited
439
+ * @returns True if SDT is temporary (placeholder), false otherwise
440
+ */
441
+ isTemporary(): boolean {
442
+ return this.properties.temporary === true;
443
+ }
444
+
445
+ /**
446
+ * Set whether SDT is temporary
447
+ * @param temporary - Whether SDT is temporary
448
+ * @returns This instance for chaining
449
+ */
450
+ setTemporary(temporary: boolean): this {
451
+ this.properties.temporary = temporary;
452
+ return this;
453
+ }
454
+
455
+ /**
456
+ * Get all content elements
457
+ * @returns Array of content elements
458
+ */
459
+ getContent(): SDTContent[] {
460
+ return [...this.content];
461
+ }
462
+
463
+ /**
464
+ * Add content element
465
+ * @param element - Element to add
466
+ */
467
+ addContent(element: SDTContent): this {
468
+ this.content.push(element);
469
+ return this;
470
+ }
471
+
472
+ /**
473
+ * Clear all content
474
+ */
475
+ clearContent(): this {
476
+ this.content = [];
477
+ return this;
478
+ }
479
+
480
+ /**
481
+ * Generate XML for this SDT
482
+ * @returns XML element
483
+ */
484
+ toXML(): XMLElement {
485
+ const children: XMLElement[] = [];
486
+
487
+ // Build sdtPr (properties)
488
+ const sdtPrChildren: XMLElement[] = [];
489
+
490
+ if (this.properties.lock) {
491
+ sdtPrChildren.push(XMLBuilder.wSelf('lock', { 'w:val': this.properties.lock }));
492
+ }
493
+
494
+ if (this.properties.id !== undefined) {
495
+ sdtPrChildren.push(XMLBuilder.wSelf('id', { 'w:val': this.properties.id.toString() }));
496
+ }
497
+
498
+ if (this.properties.tag) {
499
+ sdtPrChildren.push(XMLBuilder.wSelf('tag', { 'w:val': this.properties.tag }));
500
+ }
501
+
502
+ if (this.properties.alias) {
503
+ sdtPrChildren.push(XMLBuilder.wSelf('alias', { 'w:val': this.properties.alias }));
504
+ }
505
+
506
+ // Add placeholder
507
+ if (this.properties.placeholder) {
508
+ sdtPrChildren.push(
509
+ XMLBuilder.w('placeholder', {}, [
510
+ XMLBuilder.wSelf('docPart', { 'w:val': this.properties.placeholder.docPart }),
511
+ ])
512
+ );
513
+ }
514
+
515
+ // Add showing placeholder flag
516
+ if (this.properties.showingPlcHdr !== undefined) {
517
+ sdtPrChildren.push(
518
+ XMLBuilder.wSelf('showingPlcHdr', {
519
+ 'w:val': this.properties.showingPlcHdr ? 'true' : 'false',
520
+ })
521
+ );
522
+ }
523
+
524
+ // Add data binding
525
+ if (this.properties.dataBinding) {
526
+ const dbAttrs: Record<string, string> = {
527
+ 'w:xpath': this.properties.dataBinding.xpath,
528
+ };
529
+ if (this.properties.dataBinding.prefixMappings) {
530
+ dbAttrs['w:prefixMappings'] = this.properties.dataBinding.prefixMappings;
531
+ }
532
+ if (this.properties.dataBinding.storeItemId) {
533
+ dbAttrs['w:storeItemID'] = this.properties.dataBinding.storeItemId;
534
+ }
535
+ sdtPrChildren.push(XMLBuilder.wSelf('dataBinding', dbAttrs));
536
+ }
537
+
538
+ // Add control type-specific XML
539
+ if (this.properties.controlType) {
540
+ switch (this.properties.controlType) {
541
+ case 'richText':
542
+ sdtPrChildren.push(XMLBuilder.wSelf('richText', {}));
543
+ break;
544
+
545
+ case 'plainText':
546
+ if (this.properties.plainText) {
547
+ const attrs: Record<string, string> = {};
548
+ if (this.properties.plainText.multiLine !== undefined) {
549
+ attrs['w:multiLine'] = this.properties.plainText.multiLine ? '1' : '0';
550
+ }
551
+ sdtPrChildren.push(XMLBuilder.wSelf('text', attrs));
552
+ } else {
553
+ sdtPrChildren.push(XMLBuilder.wSelf('text', {}));
554
+ }
555
+ break;
556
+
557
+ case 'comboBox':
558
+ if (this.properties.comboBox) {
559
+ const comboBoxChildren: XMLElement[] = [];
560
+ for (const item of this.properties.comboBox.items) {
561
+ comboBoxChildren.push(
562
+ XMLBuilder.wSelf('listItem', {
563
+ 'w:displayText': item.displayText,
564
+ 'w:value': item.value,
565
+ })
566
+ );
567
+ }
568
+ sdtPrChildren.push(XMLBuilder.w('comboBox', {}, comboBoxChildren));
569
+ }
570
+ break;
571
+
572
+ case 'dropDownList':
573
+ if (this.properties.dropDownList) {
574
+ const dropDownChildren: XMLElement[] = [];
575
+ for (const item of this.properties.dropDownList.items) {
576
+ dropDownChildren.push(
577
+ XMLBuilder.wSelf('listItem', {
578
+ 'w:displayText': item.displayText,
579
+ 'w:value': item.value,
580
+ })
581
+ );
582
+ }
583
+ sdtPrChildren.push(XMLBuilder.w('dropDownList', {}, dropDownChildren));
584
+ }
585
+ break;
586
+
587
+ case 'datePicker':
588
+ if (this.properties.datePicker) {
589
+ // Per ECMA-376, w:date has w:fullDate as attribute; dateFormat, lid,
590
+ // storeMappedDataAs, and calendar are child elements with w:val
591
+ const dateAttrs: Record<string, string> = {};
592
+ if (this.properties.datePicker.fullDate) {
593
+ dateAttrs['w:fullDate'] = this.properties.datePicker.fullDate.toISOString();
594
+ }
595
+ const dateChildren: XMLElement[] = [];
596
+ if (this.properties.datePicker.dateFormat) {
597
+ dateChildren.push(
598
+ XMLBuilder.wSelf('dateFormat', {
599
+ 'w:val': this.properties.datePicker.dateFormat,
600
+ })
601
+ );
602
+ }
603
+ if (this.properties.datePicker.lid) {
604
+ dateChildren.push(
605
+ XMLBuilder.wSelf('lid', {
606
+ 'w:val': this.properties.datePicker.lid,
607
+ })
608
+ );
609
+ }
610
+ if (this.properties.datePicker.calendar) {
611
+ dateChildren.push(
612
+ XMLBuilder.wSelf('calendar', {
613
+ 'w:val': this.properties.datePicker.calendar,
614
+ })
615
+ );
616
+ }
617
+ if (dateChildren.length > 0) {
618
+ sdtPrChildren.push(XMLBuilder.w('date', dateAttrs, dateChildren));
619
+ } else {
620
+ sdtPrChildren.push(XMLBuilder.wSelf('date', dateAttrs));
621
+ }
622
+ }
623
+ break;
624
+
625
+ case 'checkbox':
626
+ if (this.properties.checkbox) {
627
+ const checkboxChildren: XMLElement[] = [];
628
+
629
+ // Add checked state - use w14 namespace per OOXML spec
630
+ if (this.properties.checkbox.checked !== undefined) {
631
+ checkboxChildren.push(
632
+ XMLBuilder.w14Self('checked', {
633
+ 'w14:val': this.properties.checkbox.checked ? '1' : '0',
634
+ })
635
+ );
636
+ }
637
+
638
+ // Add checked state symbol - use w14 namespace per OOXML spec
639
+ if (this.properties.checkbox.checkedState) {
640
+ checkboxChildren.push(
641
+ XMLBuilder.w14Self('checkedState', {
642
+ 'w14:val': this.properties.checkbox.checkedState,
643
+ 'w14:font': 'MS Gothic',
644
+ })
645
+ );
646
+ }
647
+
648
+ // Add unchecked state symbol - use w14 namespace per OOXML spec
649
+ if (this.properties.checkbox.uncheckedState) {
650
+ checkboxChildren.push(
651
+ XMLBuilder.w14Self('uncheckedState', {
652
+ 'w14:val': this.properties.checkbox.uncheckedState,
653
+ 'w14:font': 'MS Gothic',
654
+ })
655
+ );
656
+ }
657
+
658
+ sdtPrChildren.push(XMLBuilder.w14('checkbox', {}, checkboxChildren));
659
+ }
660
+ break;
661
+
662
+ case 'picture':
663
+ sdtPrChildren.push(XMLBuilder.wSelf('picture', {}));
664
+ break;
665
+
666
+ case 'buildingBlock':
667
+ if (this.properties.buildingBlock) {
668
+ const bbChildren: XMLElement[] = [];
669
+ if (this.properties.buildingBlock.gallery) {
670
+ bbChildren.push(
671
+ XMLBuilder.wSelf('docPartGallery', {
672
+ 'w:val': this.properties.buildingBlock.gallery,
673
+ })
674
+ );
675
+ }
676
+ if (this.properties.buildingBlock.category) {
677
+ bbChildren.push(
678
+ XMLBuilder.wSelf('docPartCategory', {
679
+ 'w:val': this.properties.buildingBlock.category,
680
+ })
681
+ );
682
+ }
683
+ sdtPrChildren.push(XMLBuilder.w('docPartObj', {}, bbChildren));
684
+ }
685
+ break;
686
+
687
+ case 'group':
688
+ sdtPrChildren.push(XMLBuilder.wSelf('group', {}));
689
+ break;
690
+
691
+ case 'citation':
692
+ sdtPrChildren.push(XMLBuilder.wSelf('citation', {}));
693
+ break;
694
+
695
+ case 'bibliography':
696
+ sdtPrChildren.push(XMLBuilder.wSelf('bibliography', {}));
697
+ break;
698
+
699
+ case 'equation':
700
+ sdtPrChildren.push(XMLBuilder.wSelf('equation', {}));
701
+ break;
702
+
703
+ case 'docPartList':
704
+ if (this.properties.buildingBlock) {
705
+ const dplChildren: XMLElement[] = [];
706
+ if (this.properties.buildingBlock.gallery) {
707
+ dplChildren.push(
708
+ XMLBuilder.wSelf('docPartGallery', {
709
+ 'w:val': this.properties.buildingBlock.gallery,
710
+ })
711
+ );
712
+ }
713
+ if (this.properties.buildingBlock.category) {
714
+ dplChildren.push(
715
+ XMLBuilder.wSelf('docPartCategory', {
716
+ 'w:val': this.properties.buildingBlock.category,
717
+ })
718
+ );
719
+ }
720
+ sdtPrChildren.push(XMLBuilder.w('docPartList', {}, dplChildren));
721
+ }
722
+ break;
723
+ }
724
+ }
725
+
726
+ if (sdtPrChildren.length > 0) {
727
+ children.push(XMLBuilder.w('sdtPr', {}, sdtPrChildren));
728
+ }
729
+
730
+ // Build sdtContent
731
+ const sdtContentChildren: XMLElement[] = [];
732
+ for (const element of this.content) {
733
+ sdtContentChildren.push(element.toXML());
734
+ }
735
+
736
+ children.push(XMLBuilder.w('sdtContent', {}, sdtContentChildren));
737
+
738
+ return XMLBuilder.w('sdt', {}, children);
739
+ }
740
+
741
+ /**
742
+ * Create an SDT wrapping a table (common for Google Docs)
743
+ * @param table - Table to wrap
744
+ * @param tag - Optional tag value
745
+ * @param lock - Optional lock type (default: unlocked for editability)
746
+ * @returns New SDT instance
747
+ * @example
748
+ * ```typescript
749
+ * // Unlocked table (editable in Word) - RECOMMENDED
750
+ * const sdt = StructuredDocumentTag.wrapTable(table);
751
+ *
752
+ * // Locked table (read-only in Word)
753
+ * const lockedSdt = StructuredDocumentTag.wrapTable(table, 'my-table', 'contentLocked');
754
+ * ```
755
+ */
756
+ static wrapTable(table: Table, tag = 'goog_rdk_0', lock?: SDTLockType): StructuredDocumentTag {
757
+ return new StructuredDocumentTag(
758
+ {
759
+ id: Date.now() % 1000000000, // Generate a reasonable ID
760
+ tag,
761
+ lock, // Only set if provided - defaults to unlocked
762
+ },
763
+ [table]
764
+ );
765
+ }
766
+
767
+ /**
768
+ * Create an SDT wrapping a paragraph
769
+ * @param paragraph - Paragraph to wrap
770
+ * @param tag - Optional tag value
771
+ * @returns New SDT instance
772
+ */
773
+ static wrapParagraph(paragraph: Paragraph, tag?: string): StructuredDocumentTag {
774
+ return new StructuredDocumentTag(
775
+ {
776
+ id: Date.now() % 1000000000,
777
+ tag,
778
+ },
779
+ [paragraph]
780
+ );
781
+ }
782
+
783
+ /**
784
+ * Create an empty SDT
785
+ * @param properties - SDT properties
786
+ * @returns New SDT instance
787
+ */
788
+ static create(properties: SDTProperties = {}): StructuredDocumentTag {
789
+ return new StructuredDocumentTag(properties);
790
+ }
791
+
792
+ /**
793
+ * Create a rich text content control
794
+ * @param content - Initial content
795
+ * @param properties - Additional SDT properties
796
+ * @returns New SDT instance
797
+ */
798
+ static createRichText(
799
+ content: SDTContent[] = [],
800
+ properties: Partial<SDTProperties> = {}
801
+ ): StructuredDocumentTag {
802
+ return new StructuredDocumentTag(
803
+ {
804
+ id: Date.now() % 1000000000,
805
+ controlType: 'richText',
806
+ ...properties,
807
+ },
808
+ content
809
+ );
810
+ }
811
+
812
+ /**
813
+ * Create a plain text content control
814
+ * @param content - Initial content
815
+ * @param multiLine - Allow multiple lines
816
+ * @param properties - Additional SDT properties
817
+ * @returns New SDT instance
818
+ */
819
+ static createPlainText(
820
+ content: SDTContent[] = [],
821
+ multiLine = false,
822
+ properties: Partial<SDTProperties> = {}
823
+ ): StructuredDocumentTag {
824
+ return new StructuredDocumentTag(
825
+ {
826
+ id: Date.now() % 1000000000,
827
+ controlType: 'plainText',
828
+ plainText: { multiLine },
829
+ ...properties,
830
+ },
831
+ content
832
+ );
833
+ }
834
+
835
+ /**
836
+ * Create a combo box content control
837
+ * @param items - List items
838
+ * @param content - Initial content
839
+ * @param properties - Additional SDT properties
840
+ * @returns New SDT instance
841
+ */
842
+ static createComboBox(
843
+ items: ListItem[],
844
+ content: SDTContent[] = [],
845
+ properties: Partial<SDTProperties> = {}
846
+ ): StructuredDocumentTag {
847
+ return new StructuredDocumentTag(
848
+ {
849
+ id: Date.now() % 1000000000,
850
+ controlType: 'comboBox',
851
+ comboBox: { items },
852
+ ...properties,
853
+ },
854
+ content
855
+ );
856
+ }
857
+
858
+ /**
859
+ * Create a dropdown list content control
860
+ * @param items - List items
861
+ * @param content - Initial content
862
+ * @param properties - Additional SDT properties
863
+ * @returns New SDT instance
864
+ */
865
+ static createDropDownList(
866
+ items: ListItem[],
867
+ content: SDTContent[] = [],
868
+ properties: Partial<SDTProperties> = {}
869
+ ): StructuredDocumentTag {
870
+ return new StructuredDocumentTag(
871
+ {
872
+ id: Date.now() % 1000000000,
873
+ controlType: 'dropDownList',
874
+ dropDownList: { items },
875
+ ...properties,
876
+ },
877
+ content
878
+ );
879
+ }
880
+
881
+ /**
882
+ * Create a date picker content control
883
+ * @param dateFormat - Date format string (e.g., 'M/d/yyyy')
884
+ * @param content - Initial content
885
+ * @param properties - Additional SDT properties
886
+ * @returns New SDT instance
887
+ */
888
+ static createDatePicker(
889
+ dateFormat = 'M/d/yyyy',
890
+ content: SDTContent[] = [],
891
+ properties: Partial<SDTProperties> = {}
892
+ ): StructuredDocumentTag {
893
+ return new StructuredDocumentTag(
894
+ {
895
+ id: Date.now() % 1000000000,
896
+ controlType: 'datePicker',
897
+ datePicker: { dateFormat },
898
+ ...properties,
899
+ },
900
+ content
901
+ );
902
+ }
903
+
904
+ /**
905
+ * Create a checkbox content control
906
+ * @param checked - Initial checked state
907
+ * @param content - Initial content
908
+ * @param properties - Additional SDT properties
909
+ * @returns New SDT instance
910
+ */
911
+ static createCheckbox(
912
+ checked = false,
913
+ content: SDTContent[] = [],
914
+ properties: Partial<SDTProperties> = {}
915
+ ): StructuredDocumentTag {
916
+ return new StructuredDocumentTag(
917
+ {
918
+ id: Date.now() % 1000000000,
919
+ controlType: 'checkbox',
920
+ checkbox: {
921
+ checked,
922
+ checkedState: '2612', //
923
+ uncheckedState: '2610', // ☐
924
+ },
925
+ ...properties,
926
+ },
927
+ content
928
+ );
929
+ }
930
+
931
+ /**
932
+ * Create a picture content control
933
+ * @param content - Initial content (typically contains an image)
934
+ * @param properties - Additional SDT properties
935
+ * @returns New SDT instance
936
+ */
937
+ static createPicture(
938
+ content: SDTContent[] = [],
939
+ properties: Partial<SDTProperties> = {}
940
+ ): StructuredDocumentTag {
941
+ return new StructuredDocumentTag(
942
+ {
943
+ id: Date.now() % 1000000000,
944
+ controlType: 'picture',
945
+ ...properties,
946
+ },
947
+ content
948
+ );
949
+ }
950
+
951
+ /**
952
+ * Create a building block content control
953
+ * @param gallery - Building block gallery name
954
+ * @param category - Building block category
955
+ * @param content - Initial content
956
+ * @param properties - Additional SDT properties
957
+ * @returns New SDT instance
958
+ */
959
+ static createBuildingBlock(
960
+ gallery: string,
961
+ category: string,
962
+ content: SDTContent[] = [],
963
+ properties: Partial<SDTProperties> = {}
964
+ ): StructuredDocumentTag {
965
+ return new StructuredDocumentTag(
966
+ {
967
+ id: Date.now() % 1000000000,
968
+ controlType: 'buildingBlock',
969
+ buildingBlock: { gallery, category },
970
+ ...properties,
971
+ },
972
+ content
973
+ );
974
+ }
975
+
976
+ /**
977
+ * Create a group content control
978
+ * @param content - Initial content
979
+ * @param properties - Additional SDT properties
980
+ * @returns New SDT instance
981
+ */
982
+ static createGroup(
983
+ content: SDTContent[] = [],
984
+ properties: Partial<SDTProperties> = {}
985
+ ): StructuredDocumentTag {
986
+ return new StructuredDocumentTag(
987
+ {
988
+ id: Date.now() % 1000000000,
989
+ controlType: 'group',
990
+ lock: 'sdtContentLocked', // Groups typically lock content
991
+ ...properties,
992
+ },
993
+ content
994
+ );
995
+ }
996
+
997
+ /**
998
+ * Unlocks the SDT content (allows editing)
999
+ * Removes any lock that prevents content modification
1000
+ * @returns This SDT for chaining
1001
+ * @example
1002
+ * ```typescript
1003
+ * // Unlock a locked SDT to enable editing
1004
+ * sdt.unlock();
1005
+ *
1006
+ * // Chain with other modifications
1007
+ * sdt.unlock().setTag('editable-content');
1008
+ * ```
1009
+ */
1010
+ unlock(): this {
1011
+ delete this.properties.lock;
1012
+ return this;
1013
+ }
1014
+
1015
+ /**
1016
+ * Checks if SDT content is locked in any way
1017
+ * @returns True if content is locked (contentLocked, sdtLocked, or sdtContentLocked)
1018
+ * @example
1019
+ * ```typescript
1020
+ * if (sdt.isLocked()) {
1021
+ * console.log('SDT is locked - unlocking for editing');
1022
+ * sdt.unlock();
1023
+ * }
1024
+ * ```
1025
+ */
1026
+ isLocked(): boolean {
1027
+ const lock = this.properties.lock;
1028
+ return lock === 'contentLocked' || lock === 'sdtContentLocked' || lock === 'sdtLocked';
1029
+ }
1030
+
1031
+ /**
1032
+ * Checks if SDT content can be edited by users
1033
+ * @returns True if content can be modified (not locked by contentLocked or sdtContentLocked)
1034
+ * @example
1035
+ * ```typescript
1036
+ * const editable = sdt.isContentEditable();
1037
+ * console.log(editable ? 'Can edit' : 'Cannot edit');
1038
+ * ```
1039
+ */
1040
+ isContentEditable(): boolean {
1041
+ const lock = this.properties.lock;
1042
+ return lock !== 'contentLocked' && lock !== 'sdtContentLocked';
1043
+ }
1044
+
1045
+ /**
1046
+ * Get the placeholder configuration
1047
+ */
1048
+ getPlaceholder(): SDTPlaceholder | undefined {
1049
+ return this.properties.placeholder;
1050
+ }
1051
+
1052
+ /**
1053
+ * Set the placeholder (w:placeholder/w:docPart)
1054
+ * @param docPart - Name of the document part to use as placeholder
1055
+ */
1056
+ setPlaceholder(docPart: string): this {
1057
+ this.properties.placeholder = { docPart };
1058
+ return this;
1059
+ }
1060
+
1061
+ /**
1062
+ * Get the data binding configuration
1063
+ */
1064
+ getDataBinding(): SDTDataBinding | undefined {
1065
+ return this.properties.dataBinding;
1066
+ }
1067
+
1068
+ /**
1069
+ * Set the data binding (w:dataBinding)
1070
+ * @param xpath - XPath expression
1071
+ * @param prefixMappings - Namespace prefix mappings
1072
+ * @param storeItemId - Custom XML data store item ID
1073
+ */
1074
+ setDataBinding(xpath: string, prefixMappings?: string, storeItemId?: string): this {
1075
+ this.properties.dataBinding = { xpath, prefixMappings, storeItemId };
1076
+ return this;
1077
+ }
1078
+
1079
+ /**
1080
+ * Get whether the SDT is currently showing placeholder content
1081
+ */
1082
+ isShowingPlaceholder(): boolean {
1083
+ return this.properties.showingPlcHdr === true;
1084
+ }
1085
+
1086
+ /**
1087
+ * Set whether the SDT is showing placeholder content
1088
+ * @param val - Whether placeholder is showing
1089
+ */
1090
+ setShowingPlaceholder(val: boolean): this {
1091
+ this.properties.showingPlcHdr = val;
1092
+ return this;
1093
+ }
1094
+
1095
+ /**
1096
+ * Create a citation content control
1097
+ * @param content - Initial content
1098
+ * @param properties - Additional SDT properties
1099
+ */
1100
+ static createCitation(
1101
+ content: SDTContent[] = [],
1102
+ properties: Partial<SDTProperties> = {}
1103
+ ): StructuredDocumentTag {
1104
+ return new StructuredDocumentTag(
1105
+ {
1106
+ id: Date.now() % 1000000000,
1107
+ controlType: 'citation',
1108
+ ...properties,
1109
+ },
1110
+ content
1111
+ );
1112
+ }
1113
+
1114
+ /**
1115
+ * Create a bibliography content control
1116
+ * @param content - Initial content
1117
+ * @param properties - Additional SDT properties
1118
+ */
1119
+ static createBibliography(
1120
+ content: SDTContent[] = [],
1121
+ properties: Partial<SDTProperties> = {}
1122
+ ): StructuredDocumentTag {
1123
+ return new StructuredDocumentTag(
1124
+ {
1125
+ id: Date.now() % 1000000000,
1126
+ controlType: 'bibliography',
1127
+ ...properties,
1128
+ },
1129
+ content
1130
+ );
1131
+ }
1132
+
1133
+ /**
1134
+ * Create a document part list content control
1135
+ * Uses w:docPartList instead of w:docPartObj
1136
+ * @param gallery - Building block gallery name
1137
+ * @param category - Building block category
1138
+ * @param content - Initial content
1139
+ * @param properties - Additional SDT properties
1140
+ */
1141
+ static createDocPartList(
1142
+ gallery: string,
1143
+ category: string,
1144
+ content: SDTContent[] = [],
1145
+ properties: Partial<SDTProperties> = {}
1146
+ ): StructuredDocumentTag {
1147
+ return new StructuredDocumentTag(
1148
+ {
1149
+ id: Date.now() % 1000000000,
1150
+ controlType: 'docPartList',
1151
+ buildingBlock: { gallery, category, isList: true },
1152
+ ...properties,
1153
+ },
1154
+ content
1155
+ );
1156
+ }
1157
+
1158
+ /**
1159
+ * Create an equation content control
1160
+ * @param content - Initial content
1161
+ * @param properties - Additional SDT properties
1162
+ */
1163
+ static createEquation(
1164
+ content: SDTContent[] = [],
1165
+ properties: Partial<SDTProperties> = {}
1166
+ ): StructuredDocumentTag {
1167
+ return new StructuredDocumentTag(
1168
+ {
1169
+ id: Date.now() % 1000000000,
1170
+ controlType: 'equation',
1171
+ ...properties,
1172
+ },
1173
+ content
1174
+ );
1175
+ }
1176
+ }