docxmlater 11.0.10 → 12.1.0

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 (361) hide show
  1. package/README.md +53 -13
  2. package/dist/core/Document.d.ts +29 -3
  3. package/dist/core/Document.d.ts.map +1 -1
  4. package/dist/core/Document.js +733 -170
  5. package/dist/core/Document.js.map +1 -1
  6. package/dist/core/DocumentGenerator.d.ts +1 -0
  7. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  8. package/dist/core/DocumentGenerator.js +77 -25
  9. package/dist/core/DocumentGenerator.js.map +1 -1
  10. package/dist/core/DocumentParser.d.ts +7 -3
  11. package/dist/core/DocumentParser.d.ts.map +1 -1
  12. package/dist/core/DocumentParser.js +427 -81
  13. package/dist/core/DocumentParser.js.map +1 -1
  14. package/dist/core/RelationshipManager.d.ts.map +1 -1
  15. package/dist/core/RelationshipManager.js +2 -2
  16. package/dist/core/RelationshipManager.js.map +1 -1
  17. package/dist/elements/Comment.d.ts +15 -1
  18. package/dist/elements/Comment.d.ts.map +1 -1
  19. package/dist/elements/Comment.js +67 -12
  20. package/dist/elements/Comment.js.map +1 -1
  21. package/dist/elements/CommentManager.d.ts +4 -0
  22. package/dist/elements/CommentManager.d.ts.map +1 -1
  23. package/dist/elements/CommentManager.js +74 -16
  24. package/dist/elements/CommentManager.js.map +1 -1
  25. package/dist/elements/EndnoteManager.d.ts.map +1 -1
  26. package/dist/elements/EndnoteManager.js.map +1 -1
  27. package/dist/elements/Field.d.ts +10 -1
  28. package/dist/elements/Field.d.ts.map +1 -1
  29. package/dist/elements/Field.js +76 -34
  30. package/dist/elements/Field.js.map +1 -1
  31. package/dist/elements/FieldHelpers.d.ts +1 -0
  32. package/dist/elements/FieldHelpers.d.ts.map +1 -1
  33. package/dist/elements/FieldHelpers.js +8 -4
  34. package/dist/elements/FieldHelpers.js.map +1 -1
  35. package/dist/elements/Footer.d.ts +3 -1
  36. package/dist/elements/Footer.d.ts.map +1 -1
  37. package/dist/elements/Footer.js +39 -53
  38. package/dist/elements/Footer.js.map +1 -1
  39. package/dist/elements/FootnoteManager.d.ts.map +1 -1
  40. package/dist/elements/FootnoteManager.js.map +1 -1
  41. package/dist/elements/Header.d.ts +3 -1
  42. package/dist/elements/Header.d.ts.map +1 -1
  43. package/dist/elements/Header.js +39 -53
  44. package/dist/elements/Header.js.map +1 -1
  45. package/dist/elements/HeaderFooterManager.d.ts +4 -2
  46. package/dist/elements/HeaderFooterManager.d.ts.map +1 -1
  47. package/dist/elements/HeaderFooterManager.js +36 -6
  48. package/dist/elements/HeaderFooterManager.js.map +1 -1
  49. package/dist/elements/Hyperlink.d.ts +6 -1
  50. package/dist/elements/Hyperlink.d.ts.map +1 -1
  51. package/dist/elements/Hyperlink.js +69 -44
  52. package/dist/elements/Hyperlink.js.map +1 -1
  53. package/dist/elements/Image.d.ts.map +1 -1
  54. package/dist/elements/Image.js +33 -6
  55. package/dist/elements/Image.js.map +1 -1
  56. package/dist/elements/ImageManager.d.ts +1 -0
  57. package/dist/elements/ImageManager.d.ts.map +1 -1
  58. package/dist/elements/ImageManager.js +11 -0
  59. package/dist/elements/ImageManager.js.map +1 -1
  60. package/dist/elements/Paragraph.d.ts +3 -0
  61. package/dist/elements/Paragraph.d.ts.map +1 -1
  62. package/dist/elements/Paragraph.js +91 -26
  63. package/dist/elements/Paragraph.js.map +1 -1
  64. package/dist/elements/Revision.d.ts +4 -0
  65. package/dist/elements/Revision.d.ts.map +1 -1
  66. package/dist/elements/Revision.js +369 -29
  67. package/dist/elements/Revision.js.map +1 -1
  68. package/dist/elements/Run.d.ts +1 -0
  69. package/dist/elements/Run.d.ts.map +1 -1
  70. package/dist/elements/Run.js +24 -4
  71. package/dist/elements/Run.js.map +1 -1
  72. package/dist/elements/Section.d.ts.map +1 -1
  73. package/dist/elements/Section.js +17 -7
  74. package/dist/elements/Section.js.map +1 -1
  75. package/dist/elements/Shape.d.ts.map +1 -1
  76. package/dist/elements/Shape.js +50 -42
  77. package/dist/elements/Shape.js.map +1 -1
  78. package/dist/elements/StructuredDocumentTag.d.ts +9 -1
  79. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  80. package/dist/elements/StructuredDocumentTag.js +46 -6
  81. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  82. package/dist/elements/Table.d.ts +2 -0
  83. package/dist/elements/Table.d.ts.map +1 -1
  84. package/dist/elements/Table.js +90 -42
  85. package/dist/elements/Table.js.map +1 -1
  86. package/dist/elements/TableCell.d.ts +1 -0
  87. package/dist/elements/TableCell.d.ts.map +1 -1
  88. package/dist/elements/TableCell.js +32 -13
  89. package/dist/elements/TableCell.js.map +1 -1
  90. package/dist/elements/TableOfContents.d.ts.map +1 -1
  91. package/dist/elements/TableOfContents.js +5 -7
  92. package/dist/elements/TableOfContents.js.map +1 -1
  93. package/dist/elements/TableRow.d.ts +1 -0
  94. package/dist/elements/TableRow.d.ts.map +1 -1
  95. package/dist/elements/TableRow.js +16 -1
  96. package/dist/elements/TableRow.js.map +1 -1
  97. package/dist/elements/TextBox.d.ts.map +1 -1
  98. package/dist/elements/TextBox.js +55 -42
  99. package/dist/elements/TextBox.js.map +1 -1
  100. package/dist/esm/core/Document.js +735 -172
  101. package/dist/esm/core/Document.js.map +1 -1
  102. package/dist/esm/core/DocumentGenerator.js +77 -25
  103. package/dist/esm/core/DocumentGenerator.js.map +1 -1
  104. package/dist/esm/core/DocumentParser.js +427 -81
  105. package/dist/esm/core/DocumentParser.js.map +1 -1
  106. package/dist/esm/core/RelationshipManager.js +2 -2
  107. package/dist/esm/core/RelationshipManager.js.map +1 -1
  108. package/dist/esm/elements/Comment.js +67 -12
  109. package/dist/esm/elements/Comment.js.map +1 -1
  110. package/dist/esm/elements/CommentManager.js +74 -16
  111. package/dist/esm/elements/CommentManager.js.map +1 -1
  112. package/dist/esm/elements/EndnoteManager.js.map +1 -1
  113. package/dist/esm/elements/Field.js +77 -35
  114. package/dist/esm/elements/Field.js.map +1 -1
  115. package/dist/esm/elements/FieldHelpers.js +7 -4
  116. package/dist/esm/elements/FieldHelpers.js.map +1 -1
  117. package/dist/esm/elements/Footer.js +39 -53
  118. package/dist/esm/elements/Footer.js.map +1 -1
  119. package/dist/esm/elements/FootnoteManager.js.map +1 -1
  120. package/dist/esm/elements/Header.js +39 -53
  121. package/dist/esm/elements/Header.js.map +1 -1
  122. package/dist/esm/elements/HeaderFooterManager.js +36 -6
  123. package/dist/esm/elements/HeaderFooterManager.js.map +1 -1
  124. package/dist/esm/elements/Hyperlink.js +69 -44
  125. package/dist/esm/elements/Hyperlink.js.map +1 -1
  126. package/dist/esm/elements/Image.js +33 -6
  127. package/dist/esm/elements/Image.js.map +1 -1
  128. package/dist/esm/elements/ImageManager.js +11 -0
  129. package/dist/esm/elements/ImageManager.js.map +1 -1
  130. package/dist/esm/elements/Paragraph.js +91 -26
  131. package/dist/esm/elements/Paragraph.js.map +1 -1
  132. package/dist/esm/elements/Revision.js +369 -29
  133. package/dist/esm/elements/Revision.js.map +1 -1
  134. package/dist/esm/elements/Run.js +24 -4
  135. package/dist/esm/elements/Run.js.map +1 -1
  136. package/dist/esm/elements/Section.js +17 -7
  137. package/dist/esm/elements/Section.js.map +1 -1
  138. package/dist/esm/elements/Shape.js +50 -42
  139. package/dist/esm/elements/Shape.js.map +1 -1
  140. package/dist/esm/elements/StructuredDocumentTag.js +46 -6
  141. package/dist/esm/elements/StructuredDocumentTag.js.map +1 -1
  142. package/dist/esm/elements/Table.js +90 -42
  143. package/dist/esm/elements/Table.js.map +1 -1
  144. package/dist/esm/elements/TableCell.js +32 -13
  145. package/dist/esm/elements/TableCell.js.map +1 -1
  146. package/dist/esm/elements/TableOfContents.js +5 -7
  147. package/dist/esm/elements/TableOfContents.js.map +1 -1
  148. package/dist/esm/elements/TableRow.js +16 -1
  149. package/dist/esm/elements/TableRow.js.map +1 -1
  150. package/dist/esm/elements/TextBox.js +55 -42
  151. package/dist/esm/elements/TextBox.js.map +1 -1
  152. package/dist/esm/formatting/AbstractNumbering.js +1 -1
  153. package/dist/esm/formatting/AbstractNumbering.js.map +1 -1
  154. package/dist/esm/formatting/NumberingLevel.js +8 -6
  155. package/dist/esm/formatting/NumberingLevel.js.map +1 -1
  156. package/dist/esm/formatting/NumberingManager.js +16 -1
  157. package/dist/esm/formatting/NumberingManager.js.map +1 -1
  158. package/dist/esm/formatting/Style.js +14 -0
  159. package/dist/esm/formatting/Style.js.map +1 -1
  160. package/dist/esm/formatting/StylesManager.js +14 -2
  161. package/dist/esm/formatting/StylesManager.js.map +1 -1
  162. package/dist/esm/helpers/CleanupHelper.js +103 -26
  163. package/dist/esm/helpers/CleanupHelper.js.map +1 -1
  164. package/dist/esm/images/ImageOptimizer.js +52 -4
  165. package/dist/esm/images/ImageOptimizer.js.map +1 -1
  166. package/dist/esm/index.js +1 -0
  167. package/dist/esm/index.js.map +1 -1
  168. package/dist/esm/internal.js +1 -1
  169. package/dist/esm/internal.js.map +1 -1
  170. package/dist/esm/processors/CompatibilityUpgrader.js +7 -1
  171. package/dist/esm/processors/CompatibilityUpgrader.js.map +1 -1
  172. package/dist/esm/processors/InMemoryRevisionAcceptor.js +134 -13
  173. package/dist/esm/processors/InMemoryRevisionAcceptor.js.map +1 -1
  174. package/dist/esm/processors/RevisionWalker.js +223 -39
  175. package/dist/esm/processors/RevisionWalker.js.map +1 -1
  176. package/dist/esm/processors/SelectiveRevisionAcceptor.js +116 -17
  177. package/dist/esm/processors/SelectiveRevisionAcceptor.js.map +1 -1
  178. package/dist/esm/processors/acceptRevisions.js +20 -11
  179. package/dist/esm/processors/acceptRevisions.js.map +1 -1
  180. package/dist/esm/processors/cnfStyleDecoder.js +7 -7
  181. package/dist/esm/processors/cnfStyleDecoder.js.map +1 -1
  182. package/dist/esm/processors/stripTrackedChanges.js +16 -5
  183. package/dist/esm/processors/stripTrackedChanges.js.map +1 -1
  184. package/dist/esm/utils/deepClone.js +24 -11
  185. package/dist/esm/utils/deepClone.js.map +1 -1
  186. package/dist/esm/utils/units.js +1 -1
  187. package/dist/esm/utils/units.js.map +1 -1
  188. package/dist/esm/utils/validation.js +11 -23
  189. package/dist/esm/utils/validation.js.map +1 -1
  190. package/dist/esm/utils/xmlSanitization.js +131 -7
  191. package/dist/esm/utils/xmlSanitization.js.map +1 -1
  192. package/dist/esm/validation/RevisionAutoFixer.js +69 -55
  193. package/dist/esm/validation/RevisionAutoFixer.js.map +1 -1
  194. package/dist/esm/validation/RevisionValidator.js +24 -20
  195. package/dist/esm/validation/RevisionValidator.js.map +1 -1
  196. package/dist/esm/xml/XMLBuilder.js +52 -20
  197. package/dist/esm/xml/XMLBuilder.js.map +1 -1
  198. package/dist/esm/xml/XMLParser.js +55 -13
  199. package/dist/esm/xml/XMLParser.js.map +1 -1
  200. package/dist/esm/zip/ZipHandler.js +37 -13
  201. package/dist/esm/zip/ZipHandler.js.map +1 -1
  202. package/dist/esm/zip/ZipReader.js +53 -6
  203. package/dist/esm/zip/ZipReader.js.map +1 -1
  204. package/dist/esm/zip/errors.js +7 -0
  205. package/dist/esm/zip/errors.js.map +1 -1
  206. package/dist/esm/zip/types.js +4 -0
  207. package/dist/esm/zip/types.js.map +1 -1
  208. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  209. package/dist/formatting/AbstractNumbering.js +1 -1
  210. package/dist/formatting/AbstractNumbering.js.map +1 -1
  211. package/dist/formatting/NumberingLevel.d.ts +1 -1
  212. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  213. package/dist/formatting/NumberingLevel.js +8 -6
  214. package/dist/formatting/NumberingLevel.js.map +1 -1
  215. package/dist/formatting/NumberingManager.d.ts.map +1 -1
  216. package/dist/formatting/NumberingManager.js +16 -1
  217. package/dist/formatting/NumberingManager.js.map +1 -1
  218. package/dist/formatting/Style.d.ts.map +1 -1
  219. package/dist/formatting/Style.js +14 -0
  220. package/dist/formatting/Style.js.map +1 -1
  221. package/dist/formatting/StylesManager.d.ts +2 -0
  222. package/dist/formatting/StylesManager.d.ts.map +1 -1
  223. package/dist/formatting/StylesManager.js +14 -2
  224. package/dist/formatting/StylesManager.js.map +1 -1
  225. package/dist/helpers/CleanupHelper.d.ts.map +1 -1
  226. package/dist/helpers/CleanupHelper.js +103 -26
  227. package/dist/helpers/CleanupHelper.js.map +1 -1
  228. package/dist/images/ImageOptimizer.d.ts.map +1 -1
  229. package/dist/images/ImageOptimizer.js +52 -4
  230. package/dist/images/ImageOptimizer.js.map +1 -1
  231. package/dist/index.d.ts +3 -1
  232. package/dist/index.d.ts.map +1 -1
  233. package/dist/index.js +4 -2
  234. package/dist/index.js.map +1 -1
  235. package/dist/internal.d.ts +1 -1
  236. package/dist/internal.d.ts.map +1 -1
  237. package/dist/internal.js +2 -1
  238. package/dist/internal.js.map +1 -1
  239. package/dist/processors/CompatibilityUpgrader.d.ts.map +1 -1
  240. package/dist/processors/CompatibilityUpgrader.js +7 -1
  241. package/dist/processors/CompatibilityUpgrader.js.map +1 -1
  242. package/dist/processors/InMemoryRevisionAcceptor.d.ts +1 -0
  243. package/dist/processors/InMemoryRevisionAcceptor.d.ts.map +1 -1
  244. package/dist/processors/InMemoryRevisionAcceptor.js +135 -13
  245. package/dist/processors/InMemoryRevisionAcceptor.js.map +1 -1
  246. package/dist/processors/RevisionWalker.d.ts +9 -3
  247. package/dist/processors/RevisionWalker.d.ts.map +1 -1
  248. package/dist/processors/RevisionWalker.js +223 -39
  249. package/dist/processors/RevisionWalker.js.map +1 -1
  250. package/dist/processors/SelectiveRevisionAcceptor.d.ts.map +1 -1
  251. package/dist/processors/SelectiveRevisionAcceptor.js +116 -17
  252. package/dist/processors/SelectiveRevisionAcceptor.js.map +1 -1
  253. package/dist/processors/acceptRevisions.d.ts +1 -0
  254. package/dist/processors/acceptRevisions.d.ts.map +1 -1
  255. package/dist/processors/acceptRevisions.js +21 -11
  256. package/dist/processors/acceptRevisions.js.map +1 -1
  257. package/dist/processors/cnfStyleDecoder.d.ts.map +1 -1
  258. package/dist/processors/cnfStyleDecoder.js +7 -7
  259. package/dist/processors/cnfStyleDecoder.js.map +1 -1
  260. package/dist/processors/stripTrackedChanges.d.ts.map +1 -1
  261. package/dist/processors/stripTrackedChanges.js +16 -5
  262. package/dist/processors/stripTrackedChanges.js.map +1 -1
  263. package/dist/utils/deepClone.d.ts.map +1 -1
  264. package/dist/utils/deepClone.js +24 -11
  265. package/dist/utils/deepClone.js.map +1 -1
  266. package/dist/utils/units.d.ts.map +1 -1
  267. package/dist/utils/units.js +1 -1
  268. package/dist/utils/units.js.map +1 -1
  269. package/dist/utils/validation.d.ts.map +1 -1
  270. package/dist/utils/validation.js +11 -23
  271. package/dist/utils/validation.js.map +1 -1
  272. package/dist/utils/xmlSanitization.d.ts +2 -0
  273. package/dist/utils/xmlSanitization.d.ts.map +1 -1
  274. package/dist/utils/xmlSanitization.js +133 -7
  275. package/dist/utils/xmlSanitization.js.map +1 -1
  276. package/dist/validation/RevisionAutoFixer.d.ts +6 -2
  277. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  278. package/dist/validation/RevisionAutoFixer.js +68 -54
  279. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  280. package/dist/validation/RevisionValidator.d.ts +2 -0
  281. package/dist/validation/RevisionValidator.d.ts.map +1 -1
  282. package/dist/validation/RevisionValidator.js +26 -21
  283. package/dist/validation/RevisionValidator.js.map +1 -1
  284. package/dist/xml/XMLBuilder.d.ts +1 -0
  285. package/dist/xml/XMLBuilder.d.ts.map +1 -1
  286. package/dist/xml/XMLBuilder.js +52 -20
  287. package/dist/xml/XMLBuilder.js.map +1 -1
  288. package/dist/xml/XMLParser.d.ts +1 -0
  289. package/dist/xml/XMLParser.d.ts.map +1 -1
  290. package/dist/xml/XMLParser.js +55 -13
  291. package/dist/xml/XMLParser.js.map +1 -1
  292. package/dist/zip/ZipHandler.d.ts.map +1 -1
  293. package/dist/zip/ZipHandler.js +37 -13
  294. package/dist/zip/ZipHandler.js.map +1 -1
  295. package/dist/zip/ZipReader.d.ts.map +1 -1
  296. package/dist/zip/ZipReader.js +52 -5
  297. package/dist/zip/ZipReader.js.map +1 -1
  298. package/dist/zip/errors.d.ts +3 -0
  299. package/dist/zip/errors.d.ts.map +1 -1
  300. package/dist/zip/errors.js +9 -1
  301. package/dist/zip/errors.js.map +1 -1
  302. package/dist/zip/types.d.ts +4 -0
  303. package/dist/zip/types.d.ts.map +1 -1
  304. package/dist/zip/types.js +4 -0
  305. package/dist/zip/types.js.map +1 -1
  306. package/package.json +2 -2
  307. package/src/core/Document.ts +1184 -242
  308. package/src/core/DocumentGenerator.ts +106 -26
  309. package/src/core/DocumentParser.ts +681 -114
  310. package/src/core/RelationshipManager.ts +446 -442
  311. package/src/elements/Comment.ts +123 -18
  312. package/src/elements/CommentManager.ts +121 -22
  313. package/src/elements/EndnoteManager.ts +4 -1
  314. package/src/elements/Field.ts +134 -43
  315. package/src/elements/FieldHelpers.ts +20 -4
  316. package/src/elements/Footer.ts +62 -67
  317. package/src/elements/FootnoteManager.ts +4 -1
  318. package/src/elements/Header.ts +62 -67
  319. package/src/elements/HeaderFooterManager.ts +56 -8
  320. package/src/elements/Hyperlink.ts +150 -55
  321. package/src/elements/Image.ts +51 -7
  322. package/src/elements/ImageManager.ts +24 -0
  323. package/src/elements/Paragraph.ts +161 -40
  324. package/src/elements/Revision.ts +446 -47
  325. package/src/elements/Run.ts +44 -6
  326. package/src/elements/Section.ts +25 -9
  327. package/src/elements/Shape.ts +52 -44
  328. package/src/elements/StructuredDocumentTag.ts +83 -8
  329. package/src/elements/Table.ts +151 -50
  330. package/src/elements/TableCell.ts +57 -17
  331. package/src/elements/TableOfContents.ts +10 -9
  332. package/src/elements/TableRow.ts +35 -3
  333. package/src/elements/TextBox.ts +58 -43
  334. package/src/formatting/AbstractNumbering.ts +4 -2
  335. package/src/formatting/NumberingLevel.ts +50 -12
  336. package/src/formatting/NumberingManager.ts +32 -3
  337. package/src/formatting/Style.ts +14 -0
  338. package/src/formatting/StylesManager.ts +29 -2
  339. package/src/helpers/CleanupHelper.ts +122 -30
  340. package/src/images/ImageOptimizer.ts +64 -5
  341. package/src/index.ts +7 -0
  342. package/src/internal.ts +1 -0
  343. package/src/processors/CompatibilityUpgrader.ts +15 -2
  344. package/src/processors/InMemoryRevisionAcceptor.ts +276 -17
  345. package/src/processors/RevisionWalker.ts +390 -46
  346. package/src/processors/SelectiveRevisionAcceptor.ts +164 -28
  347. package/src/processors/acceptRevisions.ts +67 -17
  348. package/src/processors/cnfStyleDecoder.ts +18 -12
  349. package/src/processors/stripTrackedChanges.ts +47 -10
  350. package/src/utils/deepClone.ts +48 -14
  351. package/src/utils/units.ts +3 -1
  352. package/src/utils/validation.ts +30 -32
  353. package/src/utils/xmlSanitization.ts +218 -22
  354. package/src/validation/RevisionAutoFixer.ts +109 -65
  355. package/src/validation/RevisionValidator.ts +48 -23
  356. package/src/xml/XMLBuilder.ts +82 -22
  357. package/src/xml/XMLParser.ts +87 -20
  358. package/src/zip/ZipHandler.ts +61 -21
  359. package/src/zip/ZipReader.ts +135 -13
  360. package/src/zip/errors.ts +15 -0
  361. package/src/zip/types.ts +44 -2
@@ -5,7 +5,8 @@
5
5
  * Different headers can be defined for first page, odd pages, and even pages.
6
6
  */
7
7
 
8
- import { XMLElement } from '../xml/XMLBuilder.js';
8
+ import { XMLBuilder } from '../xml/XMLBuilder.js';
9
+ import { XMLParser } from '../xml/XMLParser.js';
9
10
  import { Paragraph } from './Paragraph.js';
10
11
  import { RunFormatting } from './Run.js';
11
12
  import { Table } from './Table.js';
@@ -36,6 +37,12 @@ export class Header {
36
37
  private type: HeaderType;
37
38
  private headerId?: string;
38
39
  private rawXML?: string; // Store original XML for preservation
40
+ // Top-level w:p/w:tbl count of the preserved raw XML. DocumentParser calls
41
+ // setRawXML() before repopulating elements from that same XML, so mutators
42
+ // can't simply clear rawXML — they would fire during parsing and lose the
43
+ // preserved bytes. Instead, growth beyond this count is the signal that
44
+ // content was added after load and the preserved XML is stale.
45
+ private rawXmlBlockCount = Number.MAX_SAFE_INTEGER;
39
46
 
40
47
  /**
41
48
  * Creates a new header
@@ -51,9 +58,43 @@ export class Header {
51
58
  */
52
59
  setRawXML(xml: string): this {
53
60
  this.rawXML = xml;
61
+ this.rawXmlBlockCount = Header.countTopLevelBlocks(xml);
54
62
  return this;
55
63
  }
56
64
 
65
+ /**
66
+ * Counts the top-level w:p/w:tbl children of a raw header part.
67
+ * Parsing populates this.elements from exactly those blocks, so the count
68
+ * is the baseline against which mutators detect post-load additions.
69
+ */
70
+ private static countTopLevelBlocks(xml: string): number {
71
+ try {
72
+ const parsed = XMLParser.parseToObject(xml) as Record<string, unknown>;
73
+ const root = parsed?.['w:hdr'];
74
+ if (!root || typeof root !== 'object') {
75
+ return 0;
76
+ }
77
+ const count = (node: unknown): number =>
78
+ node === undefined ? 0 : Array.isArray(node) ? node.length : 1;
79
+ const rootObj = root as Record<string, unknown>;
80
+ return count(rootObj['w:p']) + count(rootObj['w:tbl']);
81
+ } catch {
82
+ // Unparseable part: never invalidate, keep the preserved bytes
83
+ return Number.MAX_SAFE_INTEGER;
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Drops the preserved raw XML once content grows beyond what that XML
89
+ * already contains, so toXML() regenerates from elements and post-load
90
+ * edits are not silently discarded on save.
91
+ */
92
+ private invalidateRawXmlOnGrowth(): void {
93
+ if (this.rawXML !== undefined && this.elements.length > this.rawXmlBlockCount) {
94
+ this.rawXML = undefined;
95
+ }
96
+ }
97
+
57
98
  /**
58
99
  * Gets the raw XML content if available
59
100
  */
@@ -90,6 +131,7 @@ export class Header {
90
131
  */
91
132
  addParagraph(paragraph: Paragraph): this {
92
133
  this.elements.push(paragraph);
134
+ this.invalidateRawXmlOnGrowth();
93
135
  return this;
94
136
  }
95
137
 
@@ -103,6 +145,7 @@ export class Header {
103
145
  para.addText(text);
104
146
  }
105
147
  this.elements.push(para);
148
+ this.invalidateRawXmlOnGrowth();
106
149
  return para;
107
150
  }
108
151
 
@@ -127,6 +170,7 @@ export class Header {
127
170
  const para = new Paragraph();
128
171
  para.addText(text, formatting);
129
172
  this.elements.push(para);
173
+ this.invalidateRawXmlOnGrowth();
130
174
  return para;
131
175
  }
132
176
 
@@ -136,6 +180,7 @@ export class Header {
136
180
  */
137
181
  addTable(table: Table): this {
138
182
  this.elements.push(table);
183
+ this.invalidateRawXmlOnGrowth();
139
184
  return this;
140
185
  }
141
186
 
@@ -147,6 +192,7 @@ export class Header {
147
192
  createTable(rows: number, columns: number): Table {
148
193
  const table = new Table(rows, columns);
149
194
  this.elements.push(table);
195
+ this.invalidateRawXmlOnGrowth();
150
196
  return table;
151
197
  }
152
198
 
@@ -183,76 +229,25 @@ export class Header {
183
229
  return this.rawXML;
184
230
  }
185
231
 
186
- // Otherwise generate from elements
187
- const elementXmls = this.elements.map((el) => el.toXML());
188
-
189
- let xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
190
- xml += '<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ';
191
- xml += 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\n';
192
-
193
- // Add elements
194
- for (const element of elementXmls) {
195
- xml += this.renderElement(element, 1);
196
- }
232
+ // Serialize through XMLBuilder so text and attribute values are
233
+ // XML-escaped and rawXml passthrough children are honored
234
+ const children = this.elements.map((el) => el.toXML());
197
235
 
198
- // If no elements, add an empty paragraph
199
- if (this.elements.length === 0) {
200
- xml += ' <w:p/>\n';
236
+ // ECMA-376 requires block-level content in w:hdr
237
+ if (children.length === 0) {
238
+ children.push(XMLBuilder.w('p'));
201
239
  }
202
240
 
203
- xml += '</w:hdr>';
204
-
205
- return xml;
206
- }
207
-
208
- /**
209
- * Renders an XML element to string with indentation
210
- */
211
- private renderElement(element: XMLElement, indent: number): string {
212
- const spaces = ' '.repeat(indent);
213
- let xml = '';
214
-
215
- if (element.selfClosing) {
216
- xml += `${spaces}<${element.name}`;
217
- if (element.attributes) {
218
- for (const [key, value] of Object.entries(element.attributes)) {
219
- xml += ` ${key}="${value}"`;
220
- }
221
- }
222
- xml += '/>\n';
223
- } else {
224
- xml += `${spaces}<${element.name}`;
225
- if (element.attributes) {
226
- for (const [key, value] of Object.entries(element.attributes)) {
227
- xml += ` ${key}="${value}"`;
228
- }
229
- }
230
- xml += '>';
231
-
232
- if (element.children && element.children.length > 0) {
233
- const hasOnlyText = element.children.every((c) => typeof c === 'string');
234
-
235
- if (hasOnlyText) {
236
- // Inline text content
237
- xml += element.children.join('');
238
- } else {
239
- // Block-level children
240
- xml += '\n';
241
- for (const child of element.children) {
242
- if (typeof child === 'string') {
243
- xml += spaces + ' ' + child + '\n';
244
- } else {
245
- xml += this.renderElement(child, indent + 1);
246
- }
247
- }
248
- xml += spaces;
249
- }
250
- }
251
-
252
- xml += `</${element.name}>\n`;
253
- }
241
+ const namespaces: Record<string, string> = {
242
+ ...XMLBuilder.createNamespaces(),
243
+ // Extension namespaces (w14:paraId etc. on regenerated paragraphs)
244
+ // must be declared ignorable or Word rejects the part
245
+ 'mc:Ignorable': 'w14 w15 wp14 asvg',
246
+ };
254
247
 
255
- return xml;
248
+ const builder = new XMLBuilder();
249
+ builder.element('w:hdr', namespaces, children);
250
+ return builder.build(true);
256
251
  }
257
252
 
258
253
  /**
@@ -51,18 +51,31 @@ export class HeaderFooterManager {
51
51
  * Registers a header with the manager
52
52
  * @param header The header to register
53
53
  * @param relationshipId The relationship ID for this header
54
+ * @param originalFilename Part name from the relationship target for loaded
55
+ * headers — kept as-is so saved content lands where the relationship points
54
56
  * @returns The filename assigned to this header
55
57
  */
56
- registerHeader(header: Header, relationshipId: string): string {
58
+ registerHeader(header: Header, relationshipId: string, originalFilename?: string): string {
57
59
  // Check if already registered
58
60
  const existing = this.headers.get(header);
59
61
  if (existing) {
60
62
  return existing.filename;
61
63
  }
62
64
 
63
- // Generate filename
64
- const number = this.nextHeaderNumber++;
65
- const filename = header.getFilename(number);
65
+ let number: number;
66
+ let filename: string;
67
+ if (originalFilename) {
68
+ filename = originalFilename;
69
+ const digits = /(\d+)\.xml$/i.exec(originalFilename)?.[1];
70
+ number = digits ? parseInt(digits, 10) : this.nextHeaderNumber;
71
+ // Keep the counter ahead of parsed part names so generated names never collide
72
+ if (number >= this.nextHeaderNumber) {
73
+ this.nextHeaderNumber = number + 1;
74
+ }
75
+ } else {
76
+ number = this.nextHeaderNumber++;
77
+ filename = header.getFilename(number);
78
+ }
66
79
 
67
80
  // Set header ID
68
81
  header.setHeaderId(relationshipId);
@@ -84,18 +97,31 @@ export class HeaderFooterManager {
84
97
  * Registers a footer with the manager
85
98
  * @param footer The footer to register
86
99
  * @param relationshipId The relationship ID for this footer
100
+ * @param originalFilename Part name from the relationship target for loaded
101
+ * footers — kept as-is so saved content lands where the relationship points
87
102
  * @returns The filename assigned to this footer
88
103
  */
89
- registerFooter(footer: Footer, relationshipId: string): string {
104
+ registerFooter(footer: Footer, relationshipId: string, originalFilename?: string): string {
90
105
  // Check if already registered
91
106
  const existing = this.footers.get(footer);
92
107
  if (existing) {
93
108
  return existing.filename;
94
109
  }
95
110
 
96
- // Generate filename
97
- const number = this.nextFooterNumber++;
98
- const filename = footer.getFilename(number);
111
+ let number: number;
112
+ let filename: string;
113
+ if (originalFilename) {
114
+ filename = originalFilename;
115
+ const digits = /(\d+)\.xml$/i.exec(originalFilename)?.[1];
116
+ number = digits ? parseInt(digits, 10) : this.nextFooterNumber;
117
+ // Keep the counter ahead of parsed part names so generated names never collide
118
+ if (number >= this.nextFooterNumber) {
119
+ this.nextFooterNumber = number + 1;
120
+ }
121
+ } else {
122
+ number = this.nextFooterNumber++;
123
+ filename = footer.getFilename(number);
124
+ }
99
125
 
100
126
  // Set footer ID
101
127
  footer.setFooterId(relationshipId);
@@ -113,6 +139,28 @@ export class HeaderFooterManager {
113
139
  return filename;
114
140
  }
115
141
 
142
+ /**
143
+ * Returns the part filename this header has, or would receive when
144
+ * registered. Does not consume a sequence number — callers can create the
145
+ * relationship targeting the same part name registerHeader() will assign.
146
+ * @param header The header
147
+ * @returns The current or upcoming filename
148
+ */
149
+ peekHeaderFilename(header: Header): string {
150
+ return this.headers.get(header)?.filename ?? header.getFilename(this.nextHeaderNumber);
151
+ }
152
+
153
+ /**
154
+ * Returns the part filename this footer has, or would receive when
155
+ * registered. Does not consume a sequence number — callers can create the
156
+ * relationship targeting the same part name registerFooter() will assign.
157
+ * @param footer The footer
158
+ * @returns The current or upcoming filename
159
+ */
160
+ peekFooterFilename(footer: Footer): string {
161
+ return this.footers.get(footer)?.filename ?? footer.getFilename(this.nextFooterNumber);
162
+ }
163
+
116
164
  /**
117
165
  * Gets the filename for a header
118
166
  * @param header The header