docxmlater 10.0.1 → 10.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/README.md +3 -2
  2. package/dist/constants/legacyCompatFlags.d.ts.map +1 -1
  3. package/dist/constants/legacyCompatFlags.js.map +1 -1
  4. package/dist/constants/limits.d.ts +0 -27
  5. package/dist/constants/limits.d.ts.map +1 -1
  6. package/dist/constants/limits.js +13 -13
  7. package/dist/constants/limits.js.map +1 -1
  8. package/dist/core/Document.d.ts +24 -19
  9. package/dist/core/Document.d.ts.map +1 -1
  10. package/dist/core/Document.js +272 -71
  11. package/dist/core/Document.js.map +1 -1
  12. package/dist/core/DocumentContent.d.ts.map +1 -1
  13. package/dist/core/DocumentContent.js.map +1 -1
  14. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  15. package/dist/core/DocumentGenerator.js +59 -24
  16. package/dist/core/DocumentGenerator.js.map +1 -1
  17. package/dist/core/DocumentIdManager.d.ts.map +1 -1
  18. package/dist/core/DocumentIdManager.js.map +1 -1
  19. package/dist/core/DocumentParser.d.ts +6 -6
  20. package/dist/core/DocumentParser.d.ts.map +1 -1
  21. package/dist/core/DocumentParser.js +60 -54
  22. package/dist/core/DocumentParser.js.map +1 -1
  23. package/dist/core/DocumentValidator.d.ts.map +1 -1
  24. package/dist/core/DocumentValidator.js.map +1 -1
  25. package/dist/core/Relationship.d.ts.map +1 -1
  26. package/dist/core/Relationship.js +1 -1
  27. package/dist/core/Relationship.js.map +1 -1
  28. package/dist/core/RelationshipManager.js +3 -3
  29. package/dist/core/RelationshipManager.js.map +1 -1
  30. package/dist/elements/AlternateContent.js.map +1 -1
  31. package/dist/elements/Bookmark.d.ts.map +1 -1
  32. package/dist/elements/Bookmark.js.map +1 -1
  33. package/dist/elements/BookmarkManager.d.ts.map +1 -1
  34. package/dist/elements/BookmarkManager.js.map +1 -1
  35. package/dist/elements/Comment.js +1 -1
  36. package/dist/elements/Comment.js.map +1 -1
  37. package/dist/elements/CommentManager.d.ts.map +1 -1
  38. package/dist/elements/CommentManager.js +8 -2
  39. package/dist/elements/CommentManager.js.map +1 -1
  40. package/dist/elements/CommonTypes.d.ts.map +1 -1
  41. package/dist/elements/CommonTypes.js +1 -2
  42. package/dist/elements/CommonTypes.js.map +1 -1
  43. package/dist/elements/CustomXml.js.map +1 -1
  44. package/dist/elements/Endnote.d.ts.map +1 -1
  45. package/dist/elements/Endnote.js.map +1 -1
  46. package/dist/elements/EndnoteManager.d.ts.map +1 -1
  47. package/dist/elements/EndnoteManager.js.map +1 -1
  48. package/dist/elements/Field.d.ts.map +1 -1
  49. package/dist/elements/Field.js +31 -28
  50. package/dist/elements/Field.js.map +1 -1
  51. package/dist/elements/FieldHelpers.d.ts.map +1 -1
  52. package/dist/elements/FieldHelpers.js +6 -6
  53. package/dist/elements/FieldHelpers.js.map +1 -1
  54. package/dist/elements/FontManager.d.ts.map +1 -1
  55. package/dist/elements/FontManager.js.map +1 -1
  56. package/dist/elements/Footer.js.map +1 -1
  57. package/dist/elements/Footnote.d.ts.map +1 -1
  58. package/dist/elements/Footnote.js.map +1 -1
  59. package/dist/elements/FootnoteManager.d.ts.map +1 -1
  60. package/dist/elements/FootnoteManager.js.map +1 -1
  61. package/dist/elements/Header.js.map +1 -1
  62. package/dist/elements/HeaderFooterManager.js.map +1 -1
  63. package/dist/elements/Hyperlink.d.ts.map +1 -1
  64. package/dist/elements/Hyperlink.js +5 -5
  65. package/dist/elements/Hyperlink.js.map +1 -1
  66. package/dist/elements/Image.d.ts +2 -2
  67. package/dist/elements/Image.d.ts.map +1 -1
  68. package/dist/elements/Image.js +21 -5
  69. package/dist/elements/Image.js.map +1 -1
  70. package/dist/elements/ImageManager.d.ts.map +1 -1
  71. package/dist/elements/ImageManager.js +2 -2
  72. package/dist/elements/ImageManager.js.map +1 -1
  73. package/dist/elements/ImageRun.js.map +1 -1
  74. package/dist/elements/MathElement.js.map +1 -1
  75. package/dist/elements/Paragraph.d.ts.map +1 -1
  76. package/dist/elements/Paragraph.js +128 -117
  77. package/dist/elements/Paragraph.js.map +1 -1
  78. package/dist/elements/PreservedElement.js.map +1 -1
  79. package/dist/elements/PropertyChangeTypes.js.map +1 -1
  80. package/dist/elements/RangeMarker.js.map +1 -1
  81. package/dist/elements/Revision.d.ts +1 -0
  82. package/dist/elements/Revision.d.ts.map +1 -1
  83. package/dist/elements/Revision.js +44 -5
  84. package/dist/elements/Revision.js.map +1 -1
  85. package/dist/elements/RevisionContent.js.map +1 -1
  86. package/dist/elements/RevisionManager.d.ts.map +1 -1
  87. package/dist/elements/RevisionManager.js.map +1 -1
  88. package/dist/elements/Run.d.ts.map +1 -1
  89. package/dist/elements/Run.js +1 -3
  90. package/dist/elements/Run.js.map +1 -1
  91. package/dist/elements/Section.d.ts.map +1 -1
  92. package/dist/elements/Section.js +127 -118
  93. package/dist/elements/Section.js.map +1 -1
  94. package/dist/elements/Shape.d.ts.map +1 -1
  95. package/dist/elements/Shape.js +21 -0
  96. package/dist/elements/Shape.js.map +1 -1
  97. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  98. package/dist/elements/StructuredDocumentTag.js +20 -8
  99. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  100. package/dist/elements/Table.d.ts +2 -2
  101. package/dist/elements/Table.d.ts.map +1 -1
  102. package/dist/elements/Table.js +29 -35
  103. package/dist/elements/Table.js.map +1 -1
  104. package/dist/elements/TableCell.d.ts +2 -2
  105. package/dist/elements/TableCell.d.ts.map +1 -1
  106. package/dist/elements/TableCell.js +63 -67
  107. package/dist/elements/TableCell.js.map +1 -1
  108. package/dist/elements/TableGridChange.js.map +1 -1
  109. package/dist/elements/TableOfContents.d.ts +6 -6
  110. package/dist/elements/TableOfContents.d.ts.map +1 -1
  111. package/dist/elements/TableOfContents.js.map +1 -1
  112. package/dist/elements/TableOfContentsElement.js.map +1 -1
  113. package/dist/elements/TableRow.d.ts.map +1 -1
  114. package/dist/elements/TableRow.js +65 -47
  115. package/dist/elements/TableRow.js.map +1 -1
  116. package/dist/elements/TextBox.d.ts.map +1 -1
  117. package/dist/elements/TextBox.js +1 -1
  118. package/dist/elements/TextBox.js.map +1 -1
  119. package/dist/formatting/AbstractNumbering.d.ts +1 -1
  120. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  121. package/dist/formatting/AbstractNumbering.js +11 -11
  122. package/dist/formatting/AbstractNumbering.js.map +1 -1
  123. package/dist/formatting/NumberingInstance.d.ts.map +1 -1
  124. package/dist/formatting/NumberingInstance.js +4 -4
  125. package/dist/formatting/NumberingInstance.js.map +1 -1
  126. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  127. package/dist/formatting/NumberingLevel.js +26 -26
  128. package/dist/formatting/NumberingLevel.js.map +1 -1
  129. package/dist/formatting/NumberingManager.d.ts +1 -1
  130. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  131. package/dist/formatting/NumberingManager.js.map +1 -1
  132. package/dist/formatting/Style.d.ts.map +1 -1
  133. package/dist/formatting/Style.js +87 -95
  134. package/dist/formatting/Style.js.map +1 -1
  135. package/dist/formatting/StylesManager.d.ts +3 -3
  136. package/dist/formatting/StylesManager.d.ts.map +1 -1
  137. package/dist/formatting/StylesManager.js.map +1 -1
  138. package/dist/helpers/CleanupHelper.d.ts.map +1 -1
  139. package/dist/helpers/CleanupHelper.js +1 -7
  140. package/dist/helpers/CleanupHelper.js.map +1 -1
  141. package/dist/images/ImageOptimizer.js.map +1 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/managers/DrawingManager.d.ts.map +1 -1
  144. package/dist/managers/DrawingManager.js.map +1 -1
  145. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  146. package/dist/tracking/TrackingContext.js.map +1 -1
  147. package/dist/types/compatibility-types.js.map +1 -1
  148. package/dist/types/formatting.js.map +1 -1
  149. package/dist/types/list-types.d.ts +4 -4
  150. package/dist/types/list-types.d.ts.map +1 -1
  151. package/dist/types/list-types.js.map +1 -1
  152. package/dist/types/settings-types.js.map +1 -1
  153. package/dist/types/styleConfig.js.map +1 -1
  154. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  155. package/dist/utils/ChangelogGenerator.js.map +1 -1
  156. package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
  157. package/dist/utils/CompatibilityUpgrader.js +7 -7
  158. package/dist/utils/CompatibilityUpgrader.js.map +1 -1
  159. package/dist/utils/InMemoryRevisionAcceptor.js +1 -1
  160. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  161. package/dist/utils/MoveOperationHelper.js.map +1 -1
  162. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  163. package/dist/utils/RevisionWalker.js.map +1 -1
  164. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  165. package/dist/utils/ShadingResolver.js +1 -1
  166. package/dist/utils/ShadingResolver.js.map +1 -1
  167. package/dist/utils/acceptRevisions.d.ts +0 -28
  168. package/dist/utils/acceptRevisions.d.ts.map +1 -1
  169. package/dist/utils/acceptRevisions.js +5 -7
  170. package/dist/utils/acceptRevisions.js.map +1 -1
  171. package/dist/utils/cnfStyleDecoder.js +1 -1
  172. package/dist/utils/cnfStyleDecoder.js.map +1 -1
  173. package/dist/utils/corruptionDetection.js.map +1 -1
  174. package/dist/utils/dateFormatting.js.map +1 -1
  175. package/dist/utils/deepClone.d.ts +0 -1
  176. package/dist/utils/deepClone.d.ts.map +1 -1
  177. package/dist/utils/deepClone.js +0 -7
  178. package/dist/utils/deepClone.js.map +1 -1
  179. package/dist/utils/diagnostics.d.ts +2 -2
  180. package/dist/utils/diagnostics.d.ts.map +1 -1
  181. package/dist/utils/diagnostics.js.map +1 -1
  182. package/dist/utils/errorHandling.js.map +1 -1
  183. package/dist/utils/formatting.js.map +1 -1
  184. package/dist/utils/list-detection.d.ts +2 -2
  185. package/dist/utils/list-detection.d.ts.map +1 -1
  186. package/dist/utils/list-detection.js +3 -3
  187. package/dist/utils/list-detection.js.map +1 -1
  188. package/dist/utils/logger.d.ts +2 -4
  189. package/dist/utils/logger.d.ts.map +1 -1
  190. package/dist/utils/logger.js +0 -2
  191. package/dist/utils/logger.js.map +1 -1
  192. package/dist/utils/parsingHelpers.js.map +1 -1
  193. package/dist/utils/stripTrackedChanges.d.ts +0 -19
  194. package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
  195. package/dist/utils/stripTrackedChanges.js +0 -2
  196. package/dist/utils/stripTrackedChanges.js.map +1 -1
  197. package/dist/utils/textDiff.js.map +1 -1
  198. package/dist/utils/units.js.map +1 -1
  199. package/dist/utils/validation.d.ts.map +1 -1
  200. package/dist/utils/validation.js.map +1 -1
  201. package/dist/utils/xmlSanitization.js.map +1 -1
  202. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  203. package/dist/validation/RevisionValidator.js.map +1 -1
  204. package/dist/validation/ValidationRules.js.map +1 -1
  205. package/dist/validation/index.js.map +1 -1
  206. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  207. package/dist/xml/XMLBuilder.js +10 -0
  208. package/dist/xml/XMLBuilder.js.map +1 -1
  209. package/dist/xml/XMLParser.d.ts.map +1 -1
  210. package/dist/xml/XMLParser.js +4 -5
  211. package/dist/xml/XMLParser.js.map +1 -1
  212. package/dist/zip/ZipHandler.js.map +1 -1
  213. package/dist/zip/ZipReader.js.map +1 -1
  214. package/dist/zip/ZipWriter.js.map +1 -1
  215. package/dist/zip/errors.js.map +1 -1
  216. package/dist/zip/types.js.map +1 -1
  217. package/package.json +34 -4
  218. package/src/__tests__/helper-methods.test.ts +512 -0
  219. package/src/constants/legacyCompatFlags.ts +138 -0
  220. package/src/constants/limits.ts +50 -0
  221. package/src/core/CLAUDE.md +109 -0
  222. package/src/core/Document.ts +15569 -0
  223. package/src/core/DocumentContent.ts +467 -0
  224. package/src/core/DocumentGenerator.ts +1104 -0
  225. package/src/core/DocumentIdManager.ts +158 -0
  226. package/src/core/DocumentParser.ts +10107 -0
  227. package/src/core/DocumentValidator.ts +372 -0
  228. package/src/core/Relationship.ts +367 -0
  229. package/src/core/RelationshipManager.ts +428 -0
  230. package/src/elements/AlternateContent.ts +42 -0
  231. package/src/elements/Bookmark.ts +210 -0
  232. package/src/elements/BookmarkManager.ts +250 -0
  233. package/src/elements/CLAUDE.md +126 -0
  234. package/src/elements/Comment.ts +359 -0
  235. package/src/elements/CommentManager.ts +502 -0
  236. package/src/elements/CommonTypes.ts +549 -0
  237. package/src/elements/CustomXml.ts +36 -0
  238. package/src/elements/Endnote.ts +217 -0
  239. package/src/elements/EndnoteManager.ts +249 -0
  240. package/src/elements/Field.ts +1233 -0
  241. package/src/elements/FieldHelpers.ts +333 -0
  242. package/src/elements/FontManager.ts +339 -0
  243. package/src/elements/Footer.ts +269 -0
  244. package/src/elements/Footnote.ts +217 -0
  245. package/src/elements/FootnoteManager.ts +249 -0
  246. package/src/elements/Header.ts +269 -0
  247. package/src/elements/HeaderFooterManager.ts +219 -0
  248. package/src/elements/Hyperlink.ts +1146 -0
  249. package/src/elements/Image.ts +1756 -0
  250. package/src/elements/ImageManager.ts +432 -0
  251. package/src/elements/ImageRun.ts +59 -0
  252. package/src/elements/MathElement.ts +65 -0
  253. package/src/elements/Paragraph.ts +4227 -0
  254. package/src/elements/PreservedElement.ts +53 -0
  255. package/src/elements/PropertyChangeTypes.ts +442 -0
  256. package/src/elements/RangeMarker.ts +400 -0
  257. package/src/elements/Revision.ts +1217 -0
  258. package/src/elements/RevisionContent.ts +73 -0
  259. package/src/elements/RevisionManager.ts +1070 -0
  260. package/src/elements/Run.ts +3068 -0
  261. package/src/elements/Section.ts +1421 -0
  262. package/src/elements/Shape.ts +873 -0
  263. package/src/elements/StructuredDocumentTag.ts +978 -0
  264. package/src/elements/Table.ts +2524 -0
  265. package/src/elements/TableCell.ts +1586 -0
  266. package/src/elements/TableGridChange.ts +151 -0
  267. package/src/elements/TableOfContents.ts +691 -0
  268. package/src/elements/TableOfContentsElement.ts +89 -0
  269. package/src/elements/TableRow.ts +906 -0
  270. package/src/elements/TextBox.ts +768 -0
  271. package/src/formatting/AbstractNumbering.ts +548 -0
  272. package/src/formatting/CLAUDE.md +74 -0
  273. package/src/formatting/NumberingInstance.ts +212 -0
  274. package/src/formatting/NumberingLevel.ts +1006 -0
  275. package/src/formatting/NumberingManager.ts +827 -0
  276. package/src/formatting/Style.ts +1833 -0
  277. package/src/formatting/StylesManager.ts +1005 -0
  278. package/src/helpers/CleanupHelper.ts +524 -0
  279. package/src/images/ImageOptimizer.ts +274 -0
  280. package/src/index.ts +554 -0
  281. package/src/managers/CLAUDE.md +47 -0
  282. package/src/managers/DrawingManager.ts +319 -0
  283. package/src/tracking/DocumentTrackingContext.ts +643 -0
  284. package/src/tracking/TrackingContext.ts +173 -0
  285. package/src/types/compatibility-types.ts +49 -0
  286. package/src/types/formatting.ts +210 -0
  287. package/src/types/list-types.ts +152 -0
  288. package/src/types/settings-types.ts +59 -0
  289. package/src/types/styleConfig.ts +189 -0
  290. package/src/utils/CLAUDE.md +153 -0
  291. package/src/utils/ChangelogGenerator.ts +1581 -0
  292. package/src/utils/CompatibilityUpgrader.ts +237 -0
  293. package/src/utils/InMemoryRevisionAcceptor.ts +668 -0
  294. package/src/utils/MoveOperationHelper.ts +238 -0
  295. package/src/utils/RevisionAwareProcessor.ts +526 -0
  296. package/src/utils/RevisionWalker.ts +457 -0
  297. package/src/utils/SelectiveRevisionAcceptor.ts +613 -0
  298. package/src/utils/ShadingResolver.ts +107 -0
  299. package/src/utils/acceptRevisions.ts +714 -0
  300. package/src/utils/cnfStyleDecoder.ts +217 -0
  301. package/src/utils/corruptionDetection.ts +345 -0
  302. package/src/utils/dateFormatting.ts +20 -0
  303. package/src/utils/deepClone.ts +78 -0
  304. package/src/utils/diagnostics.ts +129 -0
  305. package/src/utils/errorHandling.ts +80 -0
  306. package/src/utils/formatting.ts +213 -0
  307. package/src/utils/list-detection.ts +274 -0
  308. package/src/utils/logger.ts +404 -0
  309. package/src/utils/parsingHelpers.ts +190 -0
  310. package/src/utils/stripTrackedChanges.ts +353 -0
  311. package/src/utils/textDiff.ts +100 -0
  312. package/src/utils/units.ts +421 -0
  313. package/src/utils/validation.ts +542 -0
  314. package/src/utils/xmlSanitization.ts +182 -0
  315. package/src/validation/RevisionAutoFixer.ts +542 -0
  316. package/src/validation/RevisionValidator.ts +460 -0
  317. package/src/validation/ValidationRules.ts +338 -0
  318. package/src/validation/index.ts +30 -0
  319. package/src/xml/CLAUDE.md +65 -0
  320. package/src/xml/XMLBuilder.ts +871 -0
  321. package/src/xml/XMLParser.ts +919 -0
  322. package/src/zip/CLAUDE.md +55 -0
  323. package/src/zip/ZipHandler.ts +637 -0
  324. package/src/zip/ZipReader.ts +299 -0
  325. package/src/zip/ZipWriter.ts +390 -0
  326. package/src/zip/errors.ts +69 -0
  327. package/src/zip/types.ts +116 -0
  328. package/dist/core/ListNormalizer.d.ts +0 -23
  329. package/dist/core/ListNormalizer.d.ts.map +0 -1
  330. package/dist/core/ListNormalizer.js +0 -624
  331. package/dist/core/ListNormalizer.js.map +0 -1
  332. package/dist/images/index.d.ts +0 -2
  333. package/dist/images/index.d.ts.map +0 -1
  334. package/dist/images/index.js +0 -8
  335. package/dist/images/index.js.map +0 -1
  336. package/dist/ms-doc/cfb/CFBReader.d.ts +0 -35
  337. package/dist/ms-doc/cfb/CFBReader.d.ts.map +0 -1
  338. package/dist/ms-doc/cfb/CFBReader.js +0 -360
  339. package/dist/ms-doc/cfb/CFBReader.js.map +0 -1
  340. package/dist/ms-doc/converter/DocToDocxConverter.d.ts +0 -55
  341. package/dist/ms-doc/converter/DocToDocxConverter.d.ts.map +0 -1
  342. package/dist/ms-doc/converter/DocToDocxConverter.js +0 -324
  343. package/dist/ms-doc/converter/DocToDocxConverter.js.map +0 -1
  344. package/dist/ms-doc/fib/FIB.d.ts +0 -18
  345. package/dist/ms-doc/fib/FIB.d.ts.map +0 -1
  346. package/dist/ms-doc/fib/FIB.js +0 -342
  347. package/dist/ms-doc/fib/FIB.js.map +0 -1
  348. package/dist/ms-doc/fields/FieldParser.d.ts +0 -31
  349. package/dist/ms-doc/fields/FieldParser.d.ts.map +0 -1
  350. package/dist/ms-doc/fields/FieldParser.js +0 -266
  351. package/dist/ms-doc/fields/FieldParser.js.map +0 -1
  352. package/dist/ms-doc/images/PictureExtractor.d.ts +0 -22
  353. package/dist/ms-doc/images/PictureExtractor.d.ts.map +0 -1
  354. package/dist/ms-doc/images/PictureExtractor.js +0 -233
  355. package/dist/ms-doc/images/PictureExtractor.js.map +0 -1
  356. package/dist/ms-doc/index.d.ts +0 -20
  357. package/dist/ms-doc/index.d.ts.map +0 -1
  358. package/dist/ms-doc/index.js +0 -59
  359. package/dist/ms-doc/index.js.map +0 -1
  360. package/dist/ms-doc/properties/SPRM.d.ts +0 -210
  361. package/dist/ms-doc/properties/SPRM.d.ts.map +0 -1
  362. package/dist/ms-doc/properties/SPRM.js +0 -633
  363. package/dist/ms-doc/properties/SPRM.js.map +0 -1
  364. package/dist/ms-doc/sections/SectionParser.d.ts +0 -25
  365. package/dist/ms-doc/sections/SectionParser.d.ts.map +0 -1
  366. package/dist/ms-doc/sections/SectionParser.js +0 -214
  367. package/dist/ms-doc/sections/SectionParser.js.map +0 -1
  368. package/dist/ms-doc/styles/StyleSheet.d.ts +0 -23
  369. package/dist/ms-doc/styles/StyleSheet.d.ts.map +0 -1
  370. package/dist/ms-doc/styles/StyleSheet.js +0 -268
  371. package/dist/ms-doc/styles/StyleSheet.js.map +0 -1
  372. package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts +0 -61
  373. package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts.map +0 -1
  374. package/dist/ms-doc/subdocuments/SubdocumentParser.js +0 -208
  375. package/dist/ms-doc/subdocuments/SubdocumentParser.js.map +0 -1
  376. package/dist/ms-doc/tables/TableParser.d.ts +0 -29
  377. package/dist/ms-doc/tables/TableParser.d.ts.map +0 -1
  378. package/dist/ms-doc/tables/TableParser.js +0 -176
  379. package/dist/ms-doc/tables/TableParser.js.map +0 -1
  380. package/dist/ms-doc/text/PieceTable.d.ts +0 -21
  381. package/dist/ms-doc/text/PieceTable.d.ts.map +0 -1
  382. package/dist/ms-doc/text/PieceTable.js +0 -171
  383. package/dist/ms-doc/text/PieceTable.js.map +0 -1
  384. package/dist/ms-doc/types/Constants.d.ts +0 -99
  385. package/dist/ms-doc/types/Constants.d.ts.map +0 -1
  386. package/dist/ms-doc/types/Constants.js +0 -102
  387. package/dist/ms-doc/types/Constants.js.map +0 -1
  388. package/dist/ms-doc/types/DocTypes.d.ts +0 -368
  389. package/dist/ms-doc/types/DocTypes.d.ts.map +0 -1
  390. package/dist/ms-doc/types/DocTypes.js +0 -3
  391. package/dist/ms-doc/types/DocTypes.js.map +0 -1
  392. package/dist/tracking/index.d.ts +0 -3
  393. package/dist/tracking/index.d.ts.map +0 -1
  394. package/dist/tracking/index.js +0 -6
  395. package/dist/tracking/index.js.map +0 -1
@@ -0,0 +1,1421 @@
1
+ /**
2
+ * Section - Represents a document section with page setup properties
3
+ *
4
+ * Sections allow different page setups within a single document (margins, orientation, etc.)
5
+ * Each section can have its own headers, footers, and page numbering.
6
+ */
7
+
8
+ import { XMLBuilder, XMLElement } from '../xml/XMLBuilder';
9
+ import { PAGE_SIZES } from '../utils/units';
10
+
11
+ /**
12
+ * Page orientation
13
+ */
14
+ export type PageOrientation = 'portrait' | 'landscape';
15
+
16
+ /**
17
+ * Section break type
18
+ */
19
+ export type SectionType = 'nextPage' | 'continuous' | 'evenPage' | 'oddPage' | 'nextColumn';
20
+
21
+ /**
22
+ * Page numbering format
23
+ */
24
+ /**
25
+ * Per ECMA-376 Part 1 §17.18.59 (ST_NumberFormat)
26
+ * Comprehensive set of page number formats
27
+ */
28
+ export type PageNumberFormat =
29
+ | 'decimal' | 'lowerRoman' | 'upperRoman' | 'lowerLetter' | 'upperLetter'
30
+ | 'ordinal' | 'cardinalText' | 'ordinalText'
31
+ | 'hex' | 'chicago' | 'decimalZero'
32
+ | 'decimalEnclosedCircle' | 'decimalEnclosedFullstop' | 'decimalEnclosedParen'
33
+ | 'ideographDigital' | 'ideographTraditional' | 'ideographLegalTraditional'
34
+ | 'ideographEnclosedCircle' | 'ideographZodiac' | 'ideographZodiacTraditional'
35
+ | 'chineseCounting' | 'chineseCountingThousand' | 'chineseLegalSimplified'
36
+ | 'japaneseCounting' | 'japaneseDigitalTenThousand' | 'japaneseLegal'
37
+ | 'koreanCounting' | 'koreanDigital' | 'koreanDigital2' | 'koreanLegal'
38
+ | 'taiwaneseCounting' | 'taiwaneseCountingThousand' | 'taiwaneseDigital'
39
+ | 'aiueo' | 'aiueoFullWidth' | 'iroha' | 'irohaFullWidth'
40
+ | 'arabicAbjad' | 'arabicAlpha' | 'hebrew1' | 'hebrew2'
41
+ | 'hindiConsonants' | 'hindiCounting' | 'hindiNumbers' | 'hindiVowels'
42
+ | 'thaiCounting' | 'thaiLetters' | 'thaiNumbers'
43
+ | 'vietnameseCounting'
44
+ | 'russianLower' | 'russianUpper'
45
+ | 'numberInDash' | 'dollarText' | 'bullet'
46
+ | 'bahtText' | 'ganada' | 'chosung'
47
+ | 'none'
48
+ | string; // Allow any format string for forward compatibility
49
+
50
+ /**
51
+ * Page size properties
52
+ */
53
+ export interface PageSize {
54
+ /** Width in twips */
55
+ width: number;
56
+ /** Height in twips */
57
+ height: number;
58
+ /** Orientation */
59
+ orientation?: PageOrientation;
60
+ }
61
+
62
+ /**
63
+ * Margin properties
64
+ */
65
+ export interface Margins {
66
+ /** Top margin in twips */
67
+ top: number;
68
+ /** Bottom margin in twips */
69
+ bottom: number;
70
+ /** Left margin in twips */
71
+ left: number;
72
+ /** Right margin in twips */
73
+ right: number;
74
+ /** Header distance from top in twips */
75
+ header?: number;
76
+ /** Footer distance from bottom in twips */
77
+ footer?: number;
78
+ /** Gutter margin in twips */
79
+ gutter?: number;
80
+ }
81
+
82
+ /**
83
+ * Column properties
84
+ */
85
+ export interface Columns {
86
+ /** Number of columns */
87
+ count: number;
88
+ /** Space between columns in twips */
89
+ space?: number;
90
+ /** Equal column widths */
91
+ equalWidth?: boolean;
92
+ /** Show column separator line */
93
+ separator?: boolean;
94
+ /** Individual column widths (for unequal columns) in twips */
95
+ columnWidths?: number[];
96
+ }
97
+
98
+ /**
99
+ * Page numbering properties
100
+ */
101
+ export interface PageNumbering {
102
+ /** Starting page number */
103
+ start?: number;
104
+ /** Number format */
105
+ format?: PageNumberFormat;
106
+ }
107
+
108
+ /**
109
+ * Paper source (printer tray) properties
110
+ */
111
+ export interface PaperSource {
112
+ /** First page tray number */
113
+ first?: number;
114
+ /** Other pages tray number */
115
+ other?: number;
116
+ }
117
+
118
+ /**
119
+ * Vertical page alignment
120
+ */
121
+ export type VerticalAlignment = 'top' | 'center' | 'bottom' | 'both';
122
+
123
+ /**
124
+ * Text direction
125
+ */
126
+ export type TextDirection = 'ltr' | 'rtl' | 'tbRl' | 'btLr';
127
+
128
+ /**
129
+ * Document grid type for East Asian typography
130
+ */
131
+ export type DocumentGridType = 'default' | 'lines' | 'linesAndChars' | 'snapToChars';
132
+
133
+ /**
134
+ * Document grid properties
135
+ */
136
+ export interface DocumentGrid {
137
+ /** Grid type */
138
+ type?: DocumentGridType;
139
+ /** Lines per page */
140
+ linePitch?: number;
141
+ /** Characters per line */
142
+ charSpace?: number;
143
+ }
144
+
145
+ /**
146
+ * Line numbering restart mode
147
+ */
148
+ export type LineNumberingRestart = 'newPage' | 'newSection' | 'continuous';
149
+
150
+ /**
151
+ * Line numbering properties
152
+ * Per ECMA-376 Part 1, Section 17.6.8 (w:lnNumType element)
153
+ */
154
+ export interface LineNumbering {
155
+ /** Display line number every N lines (countBy attribute) */
156
+ countBy?: number;
157
+ /** Starting line number */
158
+ start?: number;
159
+ /** Distance from text margin in twips */
160
+ distance?: number;
161
+ /** When to restart line numbering */
162
+ restart?: LineNumberingRestart;
163
+ }
164
+
165
+ /**
166
+ * Footnote/endnote position
167
+ * Per ECMA-376 Part 1 §17.11.6 and §17.11.7
168
+ */
169
+ export type NotePosition = 'pageBottom' | 'beneathText' | 'sectEnd' | 'docEnd';
170
+
171
+ /**
172
+ * Note numbering restart mode
173
+ */
174
+ export type NoteNumberRestart = 'continuous' | 'eachSect' | 'eachPage';
175
+
176
+ /**
177
+ * Chapter separator character for page numbering
178
+ * Per ECMA-376 Part 1 §17.18.5
179
+ */
180
+ export type ChapterSeparator = 'colon' | 'emDash' | 'enDash' | 'hyphen' | 'period';
181
+
182
+ /**
183
+ * Footnote/endnote section-level properties
184
+ */
185
+ export interface NoteProperties {
186
+ /** Note positioning */
187
+ position?: NotePosition;
188
+ /** Number format */
189
+ numberFormat?: PageNumberFormat;
190
+ /** Starting number */
191
+ startNumber?: number;
192
+ /** Restart numbering mode */
193
+ restart?: NoteNumberRestart;
194
+ }
195
+
196
+ /**
197
+ * Page border definition for a single side
198
+ * Per ECMA-376 Part 1 §17.6.10
199
+ */
200
+ export interface PageBorderDef {
201
+ /** Border style (single, double, dashed, etc.) */
202
+ style?: string;
203
+ /** Border size in eighths of a point */
204
+ size?: number;
205
+ /** Border color in hex format (without #) */
206
+ color?: string;
207
+ /** Space between border and page edge/text in points */
208
+ space?: number;
209
+ /** Whether to show shadow */
210
+ shadow?: boolean;
211
+ /** Whether to include frame around page */
212
+ frame?: boolean;
213
+ /** Theme color reference */
214
+ themeColor?: string;
215
+ /** Art border ID (for decorative borders) */
216
+ artId?: number;
217
+ }
218
+
219
+ /**
220
+ * Page borders configuration
221
+ * Per ECMA-376 Part 1 §17.6.10
222
+ */
223
+ export interface PageBorders {
224
+ /** Top page border */
225
+ top?: PageBorderDef;
226
+ /** Bottom page border */
227
+ bottom?: PageBorderDef;
228
+ /** Left page border */
229
+ left?: PageBorderDef;
230
+ /** Right page border */
231
+ right?: PageBorderDef;
232
+ /** Whether border is measured from page edge or text edge */
233
+ offsetFrom?: 'page' | 'text';
234
+ /** Display on all pages, first page only, or not first page */
235
+ display?: 'allPages' | 'firstPage' | 'notFirstPage';
236
+ /** Z-ordering relative to text */
237
+ zOrder?: 'front' | 'back';
238
+ }
239
+
240
+ /**
241
+ * Section properties
242
+ */
243
+ export interface SectionProperties {
244
+ /** Page size */
245
+ pageSize?: PageSize;
246
+ /** Margins */
247
+ margins?: Margins;
248
+ /** Column layout */
249
+ columns?: Columns;
250
+ /** Section break type */
251
+ type?: SectionType;
252
+ /** Page numbering */
253
+ pageNumbering?: PageNumbering;
254
+ /** Header reference IDs */
255
+ headers?: {
256
+ default?: string; // rId for default header
257
+ first?: string; // rId for first page header
258
+ even?: string; // rId for even page header
259
+ };
260
+ /** Footer reference IDs */
261
+ footers?: {
262
+ default?: string; // rId for default footer
263
+ first?: string; // rId for first page footer
264
+ even?: string; // rId for even page footer
265
+ };
266
+ /** Title page (different first page) */
267
+ titlePage?: boolean;
268
+ /** Vertical page alignment */
269
+ verticalAlignment?: VerticalAlignment;
270
+ /** Paper source (printer tray) */
271
+ paperSource?: PaperSource;
272
+ /** Text direction (LTR/RTL support) */
273
+ textDirection?: TextDirection;
274
+ /** Right-to-left section layout */
275
+ bidi?: boolean;
276
+ /** Gutter on right side (for RTL) */
277
+ rtlGutter?: boolean;
278
+ /** Document grid for snapping text to grid */
279
+ docGrid?: DocumentGrid;
280
+ /** Line numbering configuration */
281
+ lineNumbering?: LineNumbering;
282
+ /** Section-level footnote properties (w:footnotePr) */
283
+ footnotePr?: NoteProperties;
284
+ /** Section-level endnote properties (w:endnotePr) */
285
+ endnotePr?: NoteProperties;
286
+ /** Suppress endnotes in this section (w:noEndnote) */
287
+ noEndnote?: boolean;
288
+ /** Form protection for this section (w:formProt) */
289
+ formProt?: boolean;
290
+ /** Page borders per ECMA-376 Part 1 §17.6.10 */
291
+ pageBorders?: PageBorders;
292
+ /** Printer settings relationship ID (w:printerSettings r:id) */
293
+ printerSettingsId?: string;
294
+ /** Chapter style heading level for page numbering (w:pgNumType w:chapStyle) */
295
+ chapStyle?: number;
296
+ /** Chapter separator for page numbering (w:pgNumType w:chapSep) */
297
+ chapSep?: ChapterSeparator;
298
+ }
299
+
300
+ /**
301
+ * Represents a document section
302
+ */
303
+ /**
304
+ * Section property change tracking (w:sectPrChange)
305
+ * Per ECMA-376 Part 1 §17.13.5.32
306
+ */
307
+ export interface SectPrChange {
308
+ author: string;
309
+ date: string;
310
+ id: string;
311
+ previousProperties: Record<string, any>;
312
+ }
313
+
314
+ export class Section {
315
+ private properties: SectionProperties;
316
+ /** Tracking context for automatic change tracking */
317
+ private trackingContext?: import('../tracking/TrackingContext').TrackingContext;
318
+ /** Section property change tracking (w:sectPrChange) */
319
+ private sectPrChange?: SectPrChange;
320
+
321
+ /**
322
+ * Creates a new section
323
+ * @param properties Section properties
324
+ */
325
+ constructor(properties: SectionProperties = {}) {
326
+ // Set defaults only where necessary
327
+ this.properties = {
328
+ pageSize: properties.pageSize || {
329
+ width: PAGE_SIZES.LETTER.width,
330
+ height: PAGE_SIZES.LETTER.height,
331
+ orientation: 'portrait',
332
+ },
333
+ margins: properties.margins || {
334
+ top: 1440, // 1 inch
335
+ bottom: 1440,
336
+ left: 1440,
337
+ right: 1440,
338
+ header: 720, // 0.5 inch
339
+ footer: 720,
340
+ },
341
+ // Default to single column layout
342
+ columns: properties.columns || {
343
+ count: 1,
344
+ },
345
+ // Default to next page section break
346
+ type: properties.type || 'nextPage',
347
+ pageNumbering: properties.pageNumbering,
348
+ headers: properties.headers,
349
+ footers: properties.footers,
350
+ titlePage: properties.titlePage,
351
+ // Phase 4.5 - New properties
352
+ verticalAlignment: properties.verticalAlignment,
353
+ paperSource: properties.paperSource,
354
+ textDirection: properties.textDirection,
355
+ pageBorders: properties.pageBorders,
356
+ };
357
+ }
358
+
359
+ /**
360
+ * Sets the tracking context for automatic change tracking.
361
+ * Called by Document when track changes is enabled.
362
+ * @internal
363
+ */
364
+ _setTrackingContext(context: import('../tracking/TrackingContext').TrackingContext): void {
365
+ this.trackingContext = context;
366
+ }
367
+
368
+ /**
369
+ * Gets the section property change tracking info
370
+ */
371
+ getSectPrChange(): SectPrChange | undefined {
372
+ return this.sectPrChange;
373
+ }
374
+
375
+ /**
376
+ * Sets the section property change tracking info
377
+ */
378
+ setSectPrChange(change: SectPrChange | undefined): void {
379
+ this.sectPrChange = change;
380
+ }
381
+
382
+ /**
383
+ * Clears the section property change tracking
384
+ */
385
+ clearSectPrChange(): void {
386
+ this.sectPrChange = undefined;
387
+ }
388
+
389
+ /**
390
+ * Gets the section properties
391
+ */
392
+ getProperties(): SectionProperties {
393
+ return { ...this.properties };
394
+ }
395
+
396
+ // ============================================================================
397
+ // Individual Property Getters
398
+ // ============================================================================
399
+
400
+ /**
401
+ * Gets the page size settings
402
+ * @returns Page size object with width, height, and orientation, or undefined
403
+ */
404
+ getPageSize(): PageSize | undefined {
405
+ return this.properties.pageSize ? { ...this.properties.pageSize } : undefined;
406
+ }
407
+
408
+ /**
409
+ * Gets the page orientation
410
+ * @returns 'portrait' or 'landscape', or undefined if not set
411
+ */
412
+ getOrientation(): PageOrientation | undefined {
413
+ return this.properties.pageSize?.orientation;
414
+ }
415
+
416
+ /**
417
+ * Gets the margin settings
418
+ * @returns Margins object or undefined if not set
419
+ */
420
+ getMargins(): Margins | undefined {
421
+ return this.properties.margins ? { ...this.properties.margins } : undefined;
422
+ }
423
+
424
+ /**
425
+ * Gets the column layout settings
426
+ * @returns Columns object or undefined if not set
427
+ */
428
+ getColumns(): Columns | undefined {
429
+ return this.properties.columns ? { ...this.properties.columns } : undefined;
430
+ }
431
+
432
+ /**
433
+ * Gets the section type (break type)
434
+ * @returns Section type or undefined if not set
435
+ */
436
+ getSectionType(): SectionType | undefined {
437
+ return this.properties.type;
438
+ }
439
+
440
+ /**
441
+ * Gets the page numbering settings
442
+ * @returns PageNumbering object or undefined if not set
443
+ */
444
+ getPageNumbering(): PageNumbering | undefined {
445
+ return this.properties.pageNumbering ? { ...this.properties.pageNumbering } : undefined;
446
+ }
447
+
448
+ /**
449
+ * Gets whether this section has a title page (different first page)
450
+ * @returns true if title page is enabled, false otherwise
451
+ */
452
+ getTitlePage(): boolean {
453
+ return this.properties.titlePage ?? false;
454
+ }
455
+
456
+ /**
457
+ * Gets header references
458
+ * @returns Object with default, first, and even header relationship IDs, or undefined
459
+ */
460
+ getHeaderReferences(): { default?: string; first?: string; even?: string } | undefined {
461
+ return this.properties.headers ? { ...this.properties.headers } : undefined;
462
+ }
463
+
464
+ /**
465
+ * Gets a specific header reference
466
+ * @param type Header type (default, first, even)
467
+ * @returns Relationship ID or undefined if not set
468
+ */
469
+ getHeaderReference(type: 'default' | 'first' | 'even'): string | undefined {
470
+ return this.properties.headers?.[type];
471
+ }
472
+
473
+ /**
474
+ * Gets footer references
475
+ * @returns Object with default, first, and even footer relationship IDs, or undefined
476
+ */
477
+ getFooterReferences(): { default?: string; first?: string; even?: string } | undefined {
478
+ return this.properties.footers ? { ...this.properties.footers } : undefined;
479
+ }
480
+
481
+ /**
482
+ * Gets a specific footer reference
483
+ * @param type Footer type (default, first, even)
484
+ * @returns Relationship ID or undefined if not set
485
+ */
486
+ getFooterReference(type: 'default' | 'first' | 'even'): string | undefined {
487
+ return this.properties.footers?.[type];
488
+ }
489
+
490
+ /**
491
+ * Gets the vertical page alignment
492
+ * @returns Vertical alignment or undefined if not set
493
+ */
494
+ getVerticalAlignment(): VerticalAlignment | undefined {
495
+ return this.properties.verticalAlignment;
496
+ }
497
+
498
+ /**
499
+ * Gets the paper source (printer tray) settings
500
+ * @returns PaperSource object or undefined if not set
501
+ */
502
+ getPaperSource(): PaperSource | undefined {
503
+ return this.properties.paperSource ? { ...this.properties.paperSource } : undefined;
504
+ }
505
+
506
+ /**
507
+ * Gets whether column separator is enabled
508
+ * @returns true if separator is enabled, false otherwise
509
+ */
510
+ getColumnSeparator(): boolean {
511
+ return this.properties.columns?.separator ?? false;
512
+ }
513
+
514
+ /**
515
+ * Gets custom column widths
516
+ * @returns Array of column widths in twips, or undefined if not set
517
+ */
518
+ getColumnWidths(): number[] | undefined {
519
+ return this.properties.columns?.columnWidths ? [...this.properties.columns.columnWidths] : undefined;
520
+ }
521
+
522
+ /**
523
+ * Gets the text direction
524
+ * @returns Text direction or undefined if not set
525
+ */
526
+ getTextDirection(): TextDirection | undefined {
527
+ return this.properties.textDirection;
528
+ }
529
+
530
+ /**
531
+ * Gets whether the section is bidirectional (RTL)
532
+ * @returns true if bidi is enabled, false otherwise
533
+ */
534
+ getBidi(): boolean {
535
+ return this.properties.bidi ?? false;
536
+ }
537
+
538
+ /**
539
+ * Gets whether RTL gutter is enabled (gutter on right side)
540
+ * @returns true if RTL gutter is enabled, false otherwise
541
+ */
542
+ getRtlGutter(): boolean {
543
+ return this.properties.rtlGutter ?? false;
544
+ }
545
+
546
+ /**
547
+ * Gets the document grid settings
548
+ * @returns DocumentGrid object or undefined if not set
549
+ */
550
+ getDocGrid(): DocumentGrid | undefined {
551
+ return this.properties.docGrid ? { ...this.properties.docGrid } : undefined;
552
+ }
553
+
554
+ // ============================================================================
555
+ // Setters
556
+ // ============================================================================
557
+
558
+ /**
559
+ * Sets page size
560
+ * @param width Width in twips
561
+ * @param height Height in twips
562
+ * @param orientation Page orientation
563
+ */
564
+ setPageSize(width: number, height: number, orientation: PageOrientation = 'portrait'): this {
565
+ const prev = this.properties.pageSize ? { ...this.properties.pageSize } : undefined;
566
+ this.properties.pageSize = { width, height, orientation };
567
+ if (this.trackingContext?.isEnabled()) {
568
+ this.trackingContext.trackSectionChange(this, 'pageSize', prev, this.properties.pageSize);
569
+ }
570
+ return this;
571
+ }
572
+
573
+ /**
574
+ * Sets page orientation
575
+ * @param orientation Page orientation
576
+ */
577
+ setOrientation(orientation: PageOrientation): this {
578
+ const prev = this.properties.pageSize?.orientation;
579
+ if (!this.properties.pageSize) {
580
+ this.properties.pageSize = {
581
+ width: PAGE_SIZES.LETTER.width,
582
+ height: PAGE_SIZES.LETTER.height,
583
+ };
584
+ }
585
+ this.properties.pageSize.orientation = orientation;
586
+
587
+ // Swap width/height for landscape
588
+ if (orientation === 'landscape' && this.properties.pageSize.width < this.properties.pageSize.height) {
589
+ const temp = this.properties.pageSize.width;
590
+ this.properties.pageSize.width = this.properties.pageSize.height;
591
+ this.properties.pageSize.height = temp;
592
+ }
593
+
594
+ if (this.trackingContext?.isEnabled() && prev !== orientation) {
595
+ this.trackingContext.trackSectionChange(this, 'orientation', prev, orientation);
596
+ }
597
+ return this;
598
+ }
599
+
600
+ /**
601
+ * Sets margins
602
+ * @param margins Margin properties
603
+ */
604
+ setMargins(margins: Margins): this {
605
+ const prev = this.properties.margins ? { ...this.properties.margins } : undefined;
606
+ const existing = this.properties.margins;
607
+ this.properties.margins = {
608
+ top: margins.top,
609
+ bottom: margins.bottom,
610
+ left: margins.left,
611
+ right: margins.right,
612
+ header: margins.header ?? existing?.header ?? 720,
613
+ footer: margins.footer ?? existing?.footer ?? 720,
614
+ gutter: margins.gutter ?? existing?.gutter,
615
+ };
616
+ if (this.trackingContext?.isEnabled()) {
617
+ this.trackingContext.trackSectionChange(this, 'margins', prev, this.properties.margins);
618
+ }
619
+ return this;
620
+ }
621
+
622
+ /**
623
+ * Sets column layout
624
+ * @param count Number of columns
625
+ * @param space Space between columns in twips
626
+ */
627
+ setColumns(count: number, space = 720): this {
628
+ const prev = this.properties.columns ? { ...this.properties.columns } : undefined;
629
+ this.properties.columns = {
630
+ count,
631
+ space,
632
+ equalWidth: true,
633
+ };
634
+ if (this.trackingContext?.isEnabled()) {
635
+ this.trackingContext.trackSectionChange(this, 'columns', prev, this.properties.columns);
636
+ }
637
+ return this;
638
+ }
639
+
640
+ /**
641
+ * Sets section type
642
+ * @param type Section break type
643
+ */
644
+ setSectionType(type: SectionType): this {
645
+ const prev = this.properties.type;
646
+ this.properties.type = type;
647
+ if (this.trackingContext?.isEnabled() && prev !== type) {
648
+ this.trackingContext.trackSectionChange(this, 'type', prev, type);
649
+ }
650
+ return this;
651
+ }
652
+
653
+ /**
654
+ * Sets page numbering
655
+ * @param start Starting page number
656
+ * @param format Number format
657
+ */
658
+ setPageNumbering(start?: number, format?: PageNumberFormat): this {
659
+ const prev = this.properties.pageNumbering ? { ...this.properties.pageNumbering } : undefined;
660
+ this.properties.pageNumbering = { start, format };
661
+ if (this.trackingContext?.isEnabled()) {
662
+ this.trackingContext.trackSectionChange(this, 'pageNumbering', prev, this.properties.pageNumbering);
663
+ }
664
+ return this;
665
+ }
666
+
667
+ /**
668
+ * Sets title page flag (different first page)
669
+ * @param titlePage Whether this section has a different first page
670
+ */
671
+ setTitlePage(titlePage = true): this {
672
+ const prev = this.properties.titlePage;
673
+ this.properties.titlePage = titlePage;
674
+ if (this.trackingContext?.isEnabled() && prev !== titlePage) {
675
+ this.trackingContext.trackSectionChange(this, 'titlePage', prev, titlePage);
676
+ }
677
+ return this;
678
+ }
679
+
680
+ /**
681
+ * Sets header reference
682
+ * @param type Header type (default, first, even)
683
+ * @param rId Relationship ID
684
+ */
685
+ setHeaderReference(type: 'default' | 'first' | 'even', rId: string): this {
686
+ const prev = this.properties.headers?.[type];
687
+ if (!this.properties.headers) {
688
+ this.properties.headers = {};
689
+ }
690
+ this.properties.headers[type] = rId;
691
+ if (this.trackingContext?.isEnabled() && prev !== rId) {
692
+ this.trackingContext.trackSectionChange(this, `headerReference:${type}`, prev, rId);
693
+ }
694
+ return this;
695
+ }
696
+
697
+ /**
698
+ * Sets footer reference
699
+ * @param type Footer type (default, first, even)
700
+ * @param rId Relationship ID
701
+ */
702
+ setFooterReference(type: 'default' | 'first' | 'even', rId: string): this {
703
+ const prev = this.properties.footers?.[type];
704
+ if (!this.properties.footers) {
705
+ this.properties.footers = {};
706
+ }
707
+ this.properties.footers[type] = rId;
708
+ if (this.trackingContext?.isEnabled() && prev !== rId) {
709
+ this.trackingContext.trackSectionChange(this, `footerReference:${type}`, prev, rId);
710
+ }
711
+ return this;
712
+ }
713
+
714
+ /**
715
+ * Sets vertical page alignment
716
+ * Controls how content is vertically aligned on the page
717
+ * @param alignment Vertical alignment (top, center, bottom, both=justified)
718
+ */
719
+ setVerticalAlignment(alignment: VerticalAlignment): this {
720
+ const prev = this.properties.verticalAlignment;
721
+ this.properties.verticalAlignment = alignment;
722
+ if (this.trackingContext?.isEnabled() && prev !== alignment) {
723
+ this.trackingContext.trackSectionChange(this, 'verticalAlignment', prev, alignment);
724
+ }
725
+ return this;
726
+ }
727
+
728
+ /**
729
+ * Sets paper source (printer tray selection)
730
+ * @param first First page tray number
731
+ * @param other Other pages tray number
732
+ */
733
+ setPaperSource(first?: number, other?: number): this {
734
+ const prev = this.properties.paperSource ? { ...this.properties.paperSource } : undefined;
735
+ this.properties.paperSource = { first, other };
736
+ if (this.trackingContext?.isEnabled()) {
737
+ this.trackingContext.trackSectionChange(this, 'paperSource', prev, this.properties.paperSource);
738
+ }
739
+ return this;
740
+ }
741
+
742
+ /**
743
+ * Sets column separator line
744
+ * Shows a vertical line between columns
745
+ * @param separator Whether to show column separator line
746
+ */
747
+ setColumnSeparator(separator = true): this {
748
+ const prev = this.properties.columns?.separator;
749
+ if (!this.properties.columns) {
750
+ this.properties.columns = { count: 1 };
751
+ }
752
+ this.properties.columns.separator = separator;
753
+ if (this.trackingContext?.isEnabled() && prev !== separator) {
754
+ this.trackingContext.trackSectionChange(this, 'columnSeparator', prev, separator);
755
+ }
756
+ return this;
757
+ }
758
+
759
+ /**
760
+ * Sets custom column widths (for unequal columns)
761
+ * @param widths Array of column widths in twips
762
+ */
763
+ setColumnWidths(widths: number[]): this {
764
+ const prev = this.properties.columns ? { ...this.properties.columns } : undefined;
765
+ if (!this.properties.columns) {
766
+ this.properties.columns = { count: widths.length };
767
+ }
768
+ this.properties.columns.columnWidths = widths;
769
+ this.properties.columns.equalWidth = false;
770
+ this.properties.columns.count = widths.length;
771
+ if (this.trackingContext?.isEnabled()) {
772
+ this.trackingContext.trackSectionChange(this, 'columns', prev, { ...this.properties.columns });
773
+ }
774
+ return this;
775
+ }
776
+
777
+ /**
778
+ * Sets text direction for the section
779
+ * @param direction Text direction (ltr=left-to-right, rtl=right-to-left, tbRl=top-to-bottom-right-to-left, btLr=bottom-to-top-left-to-right)
780
+ */
781
+ setTextDirection(direction: TextDirection): this {
782
+ const prev = this.properties.textDirection;
783
+ this.properties.textDirection = direction;
784
+ if (this.trackingContext?.isEnabled() && prev !== direction) {
785
+ this.trackingContext.trackSectionChange(this, 'textDirection', prev, direction);
786
+ }
787
+ return this;
788
+ }
789
+
790
+ /**
791
+ * Sets line numbering for the section
792
+ * Per ECMA-376 Part 1, Section 17.6.8 (w:lnNumType)
793
+ * @param options Line numbering configuration
794
+ */
795
+ setLineNumbering(options: LineNumbering): this {
796
+ const prev = this.properties.lineNumbering ? { ...this.properties.lineNumbering } : undefined;
797
+ this.properties.lineNumbering = { ...options };
798
+ if (this.trackingContext?.isEnabled()) {
799
+ this.trackingContext.trackSectionChange(this, 'lineNumbering', prev, this.properties.lineNumbering);
800
+ }
801
+ return this;
802
+ }
803
+
804
+ /**
805
+ * Gets line numbering configuration
806
+ * @returns Line numbering settings or undefined if not set
807
+ */
808
+ getLineNumbering(): LineNumbering | undefined {
809
+ return this.properties.lineNumbering ? { ...this.properties.lineNumbering } : undefined;
810
+ }
811
+
812
+ /**
813
+ * Clears line numbering for the section
814
+ */
815
+ clearLineNumbering(): this {
816
+ this.properties.lineNumbering = undefined;
817
+ return this;
818
+ }
819
+
820
+ /**
821
+ * Sets section-level footnote properties
822
+ * Per ECMA-376 Part 1 §17.11.6
823
+ */
824
+ setFootnoteProperties(props: NoteProperties): this {
825
+ const prev = this.properties.footnotePr ? { ...this.properties.footnotePr } : undefined;
826
+ this.properties.footnotePr = { ...props };
827
+ if (this.trackingContext?.isEnabled()) {
828
+ this.trackingContext.trackSectionChange(this, 'footnotePr', prev, this.properties.footnotePr);
829
+ }
830
+ return this;
831
+ }
832
+
833
+ /**
834
+ * Sets section-level endnote properties
835
+ * Per ECMA-376 Part 1 §17.11.7
836
+ */
837
+ setEndnoteProperties(props: NoteProperties): this {
838
+ const prev = this.properties.endnotePr ? { ...this.properties.endnotePr } : undefined;
839
+ this.properties.endnotePr = { ...props };
840
+ if (this.trackingContext?.isEnabled()) {
841
+ this.trackingContext.trackSectionChange(this, 'endnotePr', prev, this.properties.endnotePr);
842
+ }
843
+ return this;
844
+ }
845
+
846
+ /**
847
+ * Sets whether endnotes are suppressed in this section
848
+ * Per ECMA-376 Part 1 §17.6.14
849
+ */
850
+ setNoEndnote(noEndnote = true): this {
851
+ const prev = this.properties.noEndnote;
852
+ this.properties.noEndnote = noEndnote;
853
+ if (this.trackingContext?.isEnabled() && prev !== noEndnote) {
854
+ this.trackingContext.trackSectionChange(this, 'noEndnote', prev, noEndnote);
855
+ }
856
+ return this;
857
+ }
858
+
859
+ /**
860
+ * Sets form protection for this section
861
+ * Per ECMA-376 Part 1 §17.6.4
862
+ */
863
+ setFormProtection(formProt = true): this {
864
+ const prev = this.properties.formProt;
865
+ this.properties.formProt = formProt;
866
+ if (this.trackingContext?.isEnabled() && prev !== formProt) {
867
+ this.trackingContext.trackSectionChange(this, 'formProt', prev, formProt);
868
+ }
869
+ return this;
870
+ }
871
+
872
+ /**
873
+ * Sets printer settings relationship ID
874
+ * Per ECMA-376 Part 1 §17.6.6
875
+ */
876
+ setPrinterSettings(rId: string): this {
877
+ const prev = this.properties.printerSettingsId;
878
+ this.properties.printerSettingsId = rId;
879
+ if (this.trackingContext?.isEnabled() && prev !== rId) {
880
+ this.trackingContext.trackSectionChange(this, 'printerSettings', prev, rId);
881
+ }
882
+ return this;
883
+ }
884
+
885
+ /**
886
+ * Sets chapter numbering for page numbers
887
+ * Per ECMA-376 Part 1 §17.6.12
888
+ * @param chapStyle - Heading level (1-9) to use for chapter numbering
889
+ * @param chapSep - Separator between chapter and page number
890
+ */
891
+ setChapterNumbering(chapStyle: number, chapSep?: ChapterSeparator): this {
892
+ const prevStyle = this.properties.chapStyle;
893
+ const prevSep = this.properties.chapSep;
894
+ this.properties.chapStyle = chapStyle;
895
+ if (chapSep) this.properties.chapSep = chapSep;
896
+ if (this.trackingContext?.isEnabled()) {
897
+ this.trackingContext.trackSectionChange(this, 'chapterNumbering',
898
+ { chapStyle: prevStyle, chapSep: prevSep },
899
+ { chapStyle, chapSep: chapSep || prevSep });
900
+ }
901
+ return this;
902
+ }
903
+
904
+ /**
905
+ * Generates WordprocessingML XML for section properties
906
+ */
907
+ toXML(): XMLElement {
908
+ const children: XMLElement[] = [];
909
+
910
+ // Header references
911
+ if (this.properties.headers) {
912
+ if (this.properties.headers.first) {
913
+ children.push(
914
+ XMLBuilder.wSelf('headerReference', {
915
+ 'w:type': 'first',
916
+ 'r:id': this.properties.headers.first,
917
+ })
918
+ );
919
+ }
920
+ if (this.properties.headers.even) {
921
+ children.push(
922
+ XMLBuilder.wSelf('headerReference', {
923
+ 'w:type': 'even',
924
+ 'r:id': this.properties.headers.even,
925
+ })
926
+ );
927
+ }
928
+ if (this.properties.headers.default) {
929
+ children.push(
930
+ XMLBuilder.wSelf('headerReference', {
931
+ 'w:type': 'default',
932
+ 'r:id': this.properties.headers.default,
933
+ })
934
+ );
935
+ }
936
+ }
937
+
938
+ // Footer references
939
+ if (this.properties.footers) {
940
+ if (this.properties.footers.first) {
941
+ children.push(
942
+ XMLBuilder.wSelf('footerReference', {
943
+ 'w:type': 'first',
944
+ 'r:id': this.properties.footers.first,
945
+ })
946
+ );
947
+ }
948
+ if (this.properties.footers.even) {
949
+ children.push(
950
+ XMLBuilder.wSelf('footerReference', {
951
+ 'w:type': 'even',
952
+ 'r:id': this.properties.footers.even,
953
+ })
954
+ );
955
+ }
956
+ if (this.properties.footers.default) {
957
+ children.push(
958
+ XMLBuilder.wSelf('footerReference', {
959
+ 'w:type': 'default',
960
+ 'r:id': this.properties.footers.default,
961
+ })
962
+ );
963
+ }
964
+ }
965
+
966
+ // CT_SectPr element order per ECMA-376:
967
+ // footnotePr → endnotePr → type → pgSz → pgMar → paperSrc → pgBorders →
968
+ // lnNumType → pgNumType → cols → formProt → vAlign → noEndnote → titlePg →
969
+ // textDirection → bidi → rtlGutter → docGrid → printerSettings → sectPrChange
970
+
971
+ // Footnote properties (w:footnotePr)
972
+ if (this.properties.footnotePr) {
973
+ const fnChildren: XMLElement[] = [];
974
+ if (this.properties.footnotePr.position) {
975
+ fnChildren.push(XMLBuilder.wSelf('pos', { 'w:val': this.properties.footnotePr.position }));
976
+ }
977
+ if (this.properties.footnotePr.numberFormat) {
978
+ fnChildren.push(XMLBuilder.wSelf('numFmt', { 'w:val': this.properties.footnotePr.numberFormat }));
979
+ }
980
+ if (this.properties.footnotePr.startNumber !== undefined) {
981
+ fnChildren.push(XMLBuilder.wSelf('numStart', { 'w:val': this.properties.footnotePr.startNumber.toString() }));
982
+ }
983
+ if (this.properties.footnotePr.restart) {
984
+ fnChildren.push(XMLBuilder.wSelf('numRestart', { 'w:val': this.properties.footnotePr.restart }));
985
+ }
986
+ if (fnChildren.length > 0) {
987
+ children.push(XMLBuilder.w('footnotePr', undefined, fnChildren));
988
+ }
989
+ }
990
+
991
+ // Endnote properties (w:endnotePr)
992
+ if (this.properties.endnotePr) {
993
+ const enChildren: XMLElement[] = [];
994
+ if (this.properties.endnotePr.position) {
995
+ enChildren.push(XMLBuilder.wSelf('pos', { 'w:val': this.properties.endnotePr.position }));
996
+ }
997
+ if (this.properties.endnotePr.numberFormat) {
998
+ enChildren.push(XMLBuilder.wSelf('numFmt', { 'w:val': this.properties.endnotePr.numberFormat }));
999
+ }
1000
+ if (this.properties.endnotePr.startNumber !== undefined) {
1001
+ enChildren.push(XMLBuilder.wSelf('numStart', { 'w:val': this.properties.endnotePr.startNumber.toString() }));
1002
+ }
1003
+ if (this.properties.endnotePr.restart) {
1004
+ enChildren.push(XMLBuilder.wSelf('numRestart', { 'w:val': this.properties.endnotePr.restart }));
1005
+ }
1006
+ if (enChildren.length > 0) {
1007
+ children.push(XMLBuilder.w('endnotePr', undefined, enChildren));
1008
+ }
1009
+ }
1010
+
1011
+ // Section type
1012
+ if (this.properties.type) {
1013
+ children.push(
1014
+ XMLBuilder.wSelf('type', { 'w:val': this.properties.type })
1015
+ );
1016
+ }
1017
+
1018
+ // Page size
1019
+ if (this.properties.pageSize) {
1020
+ const attrs: Record<string, string> = {
1021
+ 'w:w': this.properties.pageSize.width.toString(),
1022
+ 'w:h': this.properties.pageSize.height.toString(),
1023
+ };
1024
+ if (this.properties.pageSize.orientation === 'landscape') {
1025
+ attrs['w:orient'] = 'landscape';
1026
+ }
1027
+ children.push(XMLBuilder.wSelf('pgSz', attrs));
1028
+ }
1029
+
1030
+ // Margins
1031
+ if (this.properties.margins) {
1032
+ const attrs: Record<string, string> = {
1033
+ 'w:top': this.properties.margins.top.toString(),
1034
+ 'w:right': this.properties.margins.right.toString(),
1035
+ 'w:bottom': this.properties.margins.bottom.toString(),
1036
+ 'w:left': this.properties.margins.left.toString(),
1037
+ };
1038
+ attrs['w:header'] = (this.properties.margins.header ?? 720).toString();
1039
+ attrs['w:footer'] = (this.properties.margins.footer ?? 720).toString();
1040
+ if (this.properties.margins.gutter !== undefined) {
1041
+ attrs['w:gutter'] = this.properties.margins.gutter.toString();
1042
+ }
1043
+ children.push(XMLBuilder.wSelf('pgMar', attrs));
1044
+ }
1045
+
1046
+ // Paper source
1047
+ if (this.properties.paperSource) {
1048
+ const attrs: Record<string, string> = {};
1049
+ if (this.properties.paperSource.first !== undefined) {
1050
+ attrs['w:first'] = this.properties.paperSource.first.toString();
1051
+ }
1052
+ if (this.properties.paperSource.other !== undefined) {
1053
+ attrs['w:other'] = this.properties.paperSource.other.toString();
1054
+ }
1055
+ if (Object.keys(attrs).length > 0) {
1056
+ children.push(XMLBuilder.wSelf('paperSrc', attrs));
1057
+ }
1058
+ }
1059
+
1060
+ // Page borders per ECMA-376 Part 1 §17.6.10
1061
+ if (this.properties.pageBorders) {
1062
+ const pgBorders = this.properties.pageBorders;
1063
+ const pgBordersAttrs: Record<string, string> = {};
1064
+ if (pgBorders.offsetFrom) pgBordersAttrs['w:offsetFrom'] = pgBorders.offsetFrom;
1065
+ if (pgBorders.display) pgBordersAttrs['w:display'] = pgBorders.display;
1066
+ if (pgBorders.zOrder) pgBordersAttrs['w:zOrder'] = pgBorders.zOrder;
1067
+
1068
+ const borderChildren: XMLElement[] = [];
1069
+ const buildBorder = (side: string, def: PageBorderDef) => {
1070
+ const bAttrs: Record<string, string | number> = {};
1071
+ if (def.style) bAttrs['w:val'] = def.style;
1072
+ // ECMA-376 Part 1 §17.18.2: sz valid range 2-96 (eighths of a point)
1073
+ if (def.size !== undefined) bAttrs['w:sz'] = Math.max(2, Math.min(96, def.size));
1074
+ if (def.color) bAttrs['w:color'] = def.color;
1075
+ // ECMA-376 Part 1 §17.18.88: space valid range 0-31680 (points)
1076
+ if (def.space !== undefined) bAttrs['w:space'] = Math.max(0, Math.min(31680, def.space));
1077
+ if (def.shadow) bAttrs['w:shadow'] = '1';
1078
+ if (def.frame) bAttrs['w:frame'] = '1';
1079
+ if (def.themeColor) bAttrs['w:themeColor'] = def.themeColor;
1080
+ if (def.artId !== undefined) bAttrs['w:id'] = def.artId;
1081
+ borderChildren.push(XMLBuilder.wSelf(side, bAttrs));
1082
+ };
1083
+
1084
+ if (pgBorders.top) buildBorder('top', pgBorders.top);
1085
+ if (pgBorders.left) buildBorder('left', pgBorders.left);
1086
+ if (pgBorders.bottom) buildBorder('bottom', pgBorders.bottom);
1087
+ if (pgBorders.right) buildBorder('right', pgBorders.right);
1088
+
1089
+ children.push(XMLBuilder.w('pgBorders', pgBordersAttrs, borderChildren));
1090
+ }
1091
+
1092
+ // Line numbering (w:lnNumType)
1093
+ if (this.properties.lineNumbering) {
1094
+ const attrs: Record<string, string> = {};
1095
+ if (this.properties.lineNumbering.countBy !== undefined) {
1096
+ attrs['w:countBy'] = this.properties.lineNumbering.countBy.toString();
1097
+ }
1098
+ if (this.properties.lineNumbering.start !== undefined) {
1099
+ attrs['w:start'] = this.properties.lineNumbering.start.toString();
1100
+ }
1101
+ if (this.properties.lineNumbering.distance !== undefined) {
1102
+ attrs['w:distance'] = this.properties.lineNumbering.distance.toString();
1103
+ }
1104
+ if (this.properties.lineNumbering.restart) {
1105
+ attrs['w:restart'] = this.properties.lineNumbering.restart;
1106
+ }
1107
+ if (Object.keys(attrs).length > 0) {
1108
+ children.push(XMLBuilder.wSelf('lnNumType', attrs));
1109
+ }
1110
+ }
1111
+
1112
+ // Page numbering
1113
+ if (this.properties.pageNumbering || this.properties.chapStyle !== undefined) {
1114
+ const attrs: Record<string, string> = {};
1115
+ if (this.properties.pageNumbering?.start !== undefined) {
1116
+ attrs['w:start'] = this.properties.pageNumbering.start.toString();
1117
+ }
1118
+ if (this.properties.pageNumbering?.format) {
1119
+ attrs['w:fmt'] = this.properties.pageNumbering.format;
1120
+ }
1121
+ if (this.properties.chapStyle !== undefined) {
1122
+ attrs['w:chapStyle'] = this.properties.chapStyle.toString();
1123
+ }
1124
+ if (this.properties.chapSep) {
1125
+ attrs['w:chapSep'] = this.properties.chapSep;
1126
+ }
1127
+ if (Object.keys(attrs).length > 0) {
1128
+ children.push(XMLBuilder.wSelf('pgNumType', attrs));
1129
+ }
1130
+ }
1131
+
1132
+ // Columns
1133
+ if (this.properties.columns) {
1134
+ const attrs: Record<string, string> = {
1135
+ 'w:num': this.properties.columns.count.toString(),
1136
+ };
1137
+ if (this.properties.columns.space !== undefined) {
1138
+ attrs['w:space'] = this.properties.columns.space.toString();
1139
+ }
1140
+ if (this.properties.columns.equalWidth !== undefined) {
1141
+ attrs['w:equalWidth'] = this.properties.columns.equalWidth ? '1' : '0';
1142
+ }
1143
+ if (this.properties.columns.separator !== undefined) {
1144
+ attrs['w:sep'] = this.properties.columns.separator ? '1' : '0';
1145
+ }
1146
+
1147
+ const colChildren: XMLElement[] = [];
1148
+ if (this.properties.columns.columnWidths) {
1149
+ for (const width of this.properties.columns.columnWidths) {
1150
+ colChildren.push(
1151
+ XMLBuilder.wSelf('col', { 'w:w': width.toString() })
1152
+ );
1153
+ }
1154
+ }
1155
+
1156
+ children.push(
1157
+ colChildren.length > 0
1158
+ ? XMLBuilder.w('cols', attrs, colChildren)
1159
+ : XMLBuilder.wSelf('cols', attrs)
1160
+ );
1161
+ }
1162
+
1163
+ // Form protection (w:formProt)
1164
+ if (this.properties.formProt) {
1165
+ children.push(XMLBuilder.wSelf('formProt'));
1166
+ }
1167
+
1168
+ // Vertical alignment
1169
+ if (this.properties.verticalAlignment) {
1170
+ children.push(
1171
+ XMLBuilder.wSelf('vAlign', { 'w:val': this.properties.verticalAlignment })
1172
+ );
1173
+ }
1174
+
1175
+ // Suppress endnotes (w:noEndnote)
1176
+ if (this.properties.noEndnote) {
1177
+ children.push(XMLBuilder.wSelf('noEndnote'));
1178
+ }
1179
+
1180
+ // Title page
1181
+ if (this.properties.titlePage) {
1182
+ children.push(XMLBuilder.wSelf('titlePg', { 'w:val': '1' }));
1183
+ }
1184
+
1185
+ // Text direction (map to valid ST_TextDirection values per ECMA-376 §17.18.93)
1186
+ if (this.properties.textDirection) {
1187
+ const textDirMap: Record<string, string> = {
1188
+ ltr: 'lrTb', rtl: 'tbRl', tbRl: 'tbRl', btLr: 'btLr',
1189
+ lrTb: 'lrTb', lrTbV: 'lrTbV', tbRlV: 'tbRlV', tbLrV: 'tbLrV',
1190
+ };
1191
+ const val = textDirMap[this.properties.textDirection] || this.properties.textDirection;
1192
+ children.push(
1193
+ XMLBuilder.wSelf('textDirection', { 'w:val': val })
1194
+ );
1195
+ }
1196
+
1197
+ // Bidirectional section (RTL)
1198
+ if (this.properties.bidi) {
1199
+ children.push(XMLBuilder.wSelf('bidi'));
1200
+ }
1201
+
1202
+ // RTL gutter (gutter on right side)
1203
+ if (this.properties.rtlGutter) {
1204
+ children.push(XMLBuilder.wSelf('rtlGutter'));
1205
+ }
1206
+
1207
+ // Document grid
1208
+ if (this.properties.docGrid) {
1209
+ const attrs: Record<string, string> = {};
1210
+ if (this.properties.docGrid.type) {
1211
+ attrs['w:type'] = this.properties.docGrid.type;
1212
+ }
1213
+ if (this.properties.docGrid.linePitch !== undefined) {
1214
+ attrs['w:linePitch'] = this.properties.docGrid.linePitch.toString();
1215
+ }
1216
+ if (this.properties.docGrid.charSpace !== undefined) {
1217
+ attrs['w:charSpace'] = this.properties.docGrid.charSpace.toString();
1218
+ }
1219
+ if (Object.keys(attrs).length > 0) {
1220
+ children.push(XMLBuilder.wSelf('docGrid', attrs));
1221
+ }
1222
+ }
1223
+
1224
+ // Printer settings (w:printerSettings)
1225
+ if (this.properties.printerSettingsId) {
1226
+ children.push(XMLBuilder.wSelf('printerSettings', {
1227
+ 'r:id': this.properties.printerSettingsId,
1228
+ }));
1229
+ }
1230
+
1231
+ // Add section property change (w:sectPrChange) per ECMA-376 Part 1 §17.13.5.32
1232
+ // Must be last child of w:sectPr
1233
+ if (this.sectPrChange) {
1234
+ const changeAttrs: Record<string, string | number> = {
1235
+ 'w:id': this.sectPrChange.id,
1236
+ 'w:author': this.sectPrChange.author,
1237
+ 'w:date': this.sectPrChange.date,
1238
+ };
1239
+ const prevChildren: XMLElement[] = [];
1240
+ const prev = this.sectPrChange.previousProperties;
1241
+ if (prev) {
1242
+ // Ordered per CT_SectPrBase:
1243
+ // type → pgSz → pgMar → lnNumType → pgNumType → cols → formProt → vAlign → titlePg → textDirection
1244
+ if (prev.type) {
1245
+ prevChildren.push(XMLBuilder.wSelf('type', { 'w:val': prev.type }));
1246
+ }
1247
+ if (prev.pageSize) {
1248
+ const pgSzAttrs: Record<string, string> = {
1249
+ 'w:w': prev.pageSize.width?.toString() || '12240',
1250
+ 'w:h': prev.pageSize.height?.toString() || '15840',
1251
+ };
1252
+ if (prev.pageSize.orientation === 'landscape') {
1253
+ pgSzAttrs['w:orient'] = 'landscape';
1254
+ }
1255
+ prevChildren.push(XMLBuilder.wSelf('pgSz', pgSzAttrs));
1256
+ }
1257
+ if (prev.margins) {
1258
+ const pgMarAttrs: Record<string, string> = {};
1259
+ if (prev.margins.top !== undefined) pgMarAttrs['w:top'] = prev.margins.top.toString();
1260
+ if (prev.margins.bottom !== undefined) pgMarAttrs['w:bottom'] = prev.margins.bottom.toString();
1261
+ if (prev.margins.left !== undefined) pgMarAttrs['w:left'] = prev.margins.left.toString();
1262
+ if (prev.margins.right !== undefined) pgMarAttrs['w:right'] = prev.margins.right.toString();
1263
+ if (prev.margins.header !== undefined) pgMarAttrs['w:header'] = prev.margins.header.toString();
1264
+ if (prev.margins.footer !== undefined) pgMarAttrs['w:footer'] = prev.margins.footer.toString();
1265
+ prevChildren.push(XMLBuilder.wSelf('pgMar', pgMarAttrs));
1266
+ }
1267
+ if (prev.lineNumbering) {
1268
+ const lnAttrs: Record<string, string> = {};
1269
+ if (prev.lineNumbering.countBy !== undefined) lnAttrs['w:countBy'] = prev.lineNumbering.countBy.toString();
1270
+ if (prev.lineNumbering.start !== undefined) lnAttrs['w:start'] = prev.lineNumbering.start.toString();
1271
+ if (prev.lineNumbering.restart) lnAttrs['w:restart'] = prev.lineNumbering.restart;
1272
+ if (prev.lineNumbering.distance !== undefined) lnAttrs['w:distance'] = prev.lineNumbering.distance.toString();
1273
+ if (Object.keys(lnAttrs).length > 0) {
1274
+ prevChildren.push(XMLBuilder.wSelf('lnNumType', lnAttrs));
1275
+ }
1276
+ }
1277
+ if (prev.pageNumbering) {
1278
+ const pnAttrs: Record<string, string> = {};
1279
+ if (prev.pageNumbering.start !== undefined) pnAttrs['w:start'] = prev.pageNumbering.start.toString();
1280
+ if (prev.pageNumbering.format) pnAttrs['w:fmt'] = prev.pageNumbering.format;
1281
+ if (Object.keys(pnAttrs).length > 0) {
1282
+ prevChildren.push(XMLBuilder.wSelf('pgNumType', pnAttrs));
1283
+ }
1284
+ }
1285
+ if (prev.columns) {
1286
+ const colAttrs: Record<string, string> = { 'w:num': prev.columns.count?.toString() || '1' };
1287
+ if (prev.columns.space !== undefined) colAttrs['w:space'] = prev.columns.space.toString();
1288
+ prevChildren.push(XMLBuilder.wSelf('cols', colAttrs));
1289
+ }
1290
+ if (prev.formProt) {
1291
+ prevChildren.push(XMLBuilder.wSelf('formProt'));
1292
+ }
1293
+ if (prev.verticalAlignment) {
1294
+ prevChildren.push(XMLBuilder.wSelf('vAlign', { 'w:val': prev.verticalAlignment }));
1295
+ }
1296
+ if (prev.titlePage) {
1297
+ prevChildren.push(XMLBuilder.wSelf('titlePg'));
1298
+ }
1299
+ if (prev.textDirection) {
1300
+ const tdMap: Record<string, string> = {
1301
+ ltr: 'lrTb', rtl: 'tbRl', tbRl: 'tbRl', btLr: 'btLr',
1302
+ lrTb: 'lrTb', lrTbV: 'lrTbV', tbRlV: 'tbRlV', tbLrV: 'tbLrV',
1303
+ };
1304
+ prevChildren.push(XMLBuilder.wSelf('textDirection', { 'w:val': tdMap[prev.textDirection] || prev.textDirection }));
1305
+ }
1306
+ }
1307
+ const prevSectPr = XMLBuilder.w('sectPr', undefined, prevChildren);
1308
+ children.push(XMLBuilder.w('sectPrChange', changeAttrs, [prevSectPr]));
1309
+ }
1310
+
1311
+ return XMLBuilder.w('sectPr', undefined, children);
1312
+ }
1313
+
1314
+ /**
1315
+ * Creates a deep clone of this section
1316
+ * @returns New Section instance with copied properties
1317
+ */
1318
+ clone(): Section {
1319
+ // Deep clone all nested objects
1320
+ const clonedProperties: SectionProperties = {};
1321
+
1322
+ if (this.properties.pageSize) {
1323
+ clonedProperties.pageSize = { ...this.properties.pageSize };
1324
+ }
1325
+
1326
+ if (this.properties.margins) {
1327
+ clonedProperties.margins = { ...this.properties.margins };
1328
+ }
1329
+
1330
+ if (this.properties.columns) {
1331
+ clonedProperties.columns = {
1332
+ ...this.properties.columns,
1333
+ columnWidths: this.properties.columns.columnWidths
1334
+ ? [...this.properties.columns.columnWidths]
1335
+ : undefined,
1336
+ };
1337
+ }
1338
+
1339
+ if (this.properties.pageNumbering) {
1340
+ clonedProperties.pageNumbering = { ...this.properties.pageNumbering };
1341
+ }
1342
+
1343
+ if (this.properties.headers) {
1344
+ clonedProperties.headers = { ...this.properties.headers };
1345
+ }
1346
+
1347
+ if (this.properties.footers) {
1348
+ clonedProperties.footers = { ...this.properties.footers };
1349
+ }
1350
+
1351
+ if (this.properties.paperSource) {
1352
+ clonedProperties.paperSource = { ...this.properties.paperSource };
1353
+ }
1354
+
1355
+ if (this.properties.docGrid) {
1356
+ clonedProperties.docGrid = { ...this.properties.docGrid };
1357
+ }
1358
+
1359
+ if (this.properties.lineNumbering) {
1360
+ clonedProperties.lineNumbering = { ...this.properties.lineNumbering };
1361
+ }
1362
+
1363
+ // Copy primitive properties
1364
+ clonedProperties.type = this.properties.type;
1365
+ clonedProperties.titlePage = this.properties.titlePage;
1366
+ clonedProperties.verticalAlignment = this.properties.verticalAlignment;
1367
+ clonedProperties.textDirection = this.properties.textDirection;
1368
+ clonedProperties.bidi = this.properties.bidi;
1369
+ clonedProperties.rtlGutter = this.properties.rtlGutter;
1370
+
1371
+ return new Section(clonedProperties);
1372
+ }
1373
+
1374
+ /**
1375
+ * Creates a section with default properties
1376
+ */
1377
+ static create(properties?: SectionProperties): Section {
1378
+ return new Section(properties);
1379
+ }
1380
+
1381
+ /**
1382
+ * Creates a letter-sized section (8.5" x 11")
1383
+ */
1384
+ static createLetter(): Section {
1385
+ return new Section({
1386
+ pageSize: {
1387
+ width: PAGE_SIZES.LETTER.width,
1388
+ height: PAGE_SIZES.LETTER.height,
1389
+ orientation: 'portrait',
1390
+ },
1391
+ });
1392
+ }
1393
+
1394
+ /**
1395
+ * Creates an A4-sized section (21cm x 29.7cm)
1396
+ */
1397
+ static createA4(): Section {
1398
+ return new Section({
1399
+ pageSize: {
1400
+ width: PAGE_SIZES.A4.width,
1401
+ height: PAGE_SIZES.A4.height,
1402
+ orientation: 'portrait',
1403
+ },
1404
+ });
1405
+ }
1406
+
1407
+ /**
1408
+ * Creates a landscape section
1409
+ * @param pageSize Page size (default: Letter)
1410
+ */
1411
+ static createLandscape(pageSize: 'letter' | 'a4' = 'letter'): Section {
1412
+ const size = pageSize === 'a4' ? PAGE_SIZES.A4 : PAGE_SIZES.LETTER;
1413
+ return new Section({
1414
+ pageSize: {
1415
+ width: size.height, // Swap for landscape
1416
+ height: size.width,
1417
+ orientation: 'landscape',
1418
+ },
1419
+ });
1420
+ }
1421
+ }