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
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Footer = void 0;
4
+ const XMLBuilder_js_1 = require("../xml/XMLBuilder.js");
5
+ const XMLParser_js_1 = require("../xml/XMLParser.js");
4
6
  const Paragraph_js_1 = require("./Paragraph.js");
5
7
  const Table_js_1 = require("./Table.js");
6
8
  class Footer {
@@ -8,13 +10,35 @@ class Footer {
8
10
  type;
9
11
  footerId;
10
12
  rawXML;
13
+ rawXmlBlockCount = Number.MAX_SAFE_INTEGER;
11
14
  constructor(properties = {}) {
12
15
  this.type = properties.type || 'default';
13
16
  }
14
17
  setRawXML(xml) {
15
18
  this.rawXML = xml;
19
+ this.rawXmlBlockCount = Footer.countTopLevelBlocks(xml);
16
20
  return this;
17
21
  }
22
+ static countTopLevelBlocks(xml) {
23
+ try {
24
+ const parsed = XMLParser_js_1.XMLParser.parseToObject(xml);
25
+ const root = parsed?.['w:ftr'];
26
+ if (!root || typeof root !== 'object') {
27
+ return 0;
28
+ }
29
+ const count = (node) => node === undefined ? 0 : Array.isArray(node) ? node.length : 1;
30
+ const rootObj = root;
31
+ return count(rootObj['w:p']) + count(rootObj['w:tbl']);
32
+ }
33
+ catch {
34
+ return Number.MAX_SAFE_INTEGER;
35
+ }
36
+ }
37
+ invalidateRawXmlOnGrowth() {
38
+ if (this.rawXML !== undefined && this.elements.length > this.rawXmlBlockCount) {
39
+ this.rawXML = undefined;
40
+ }
41
+ }
18
42
  getRawXML() {
19
43
  return this.rawXML;
20
44
  }
@@ -30,6 +54,7 @@ class Footer {
30
54
  }
31
55
  addParagraph(paragraph) {
32
56
  this.elements.push(paragraph);
57
+ this.invalidateRawXmlOnGrowth();
33
58
  return this;
34
59
  }
35
60
  createParagraph(text) {
@@ -38,21 +63,25 @@ class Footer {
38
63
  para.addText(text);
39
64
  }
40
65
  this.elements.push(para);
66
+ this.invalidateRawXmlOnGrowth();
41
67
  return para;
42
68
  }
43
69
  addText(text, formatting) {
44
70
  const para = new Paragraph_js_1.Paragraph();
45
71
  para.addText(text, formatting);
46
72
  this.elements.push(para);
73
+ this.invalidateRawXmlOnGrowth();
47
74
  return para;
48
75
  }
49
76
  addTable(table) {
50
77
  this.elements.push(table);
78
+ this.invalidateRawXmlOnGrowth();
51
79
  return this;
52
80
  }
53
81
  createTable(rows, columns) {
54
82
  const table = new Table_js_1.Table(rows, columns);
55
83
  this.elements.push(table);
84
+ this.invalidateRawXmlOnGrowth();
56
85
  return table;
57
86
  }
58
87
  getElements() {
@@ -70,60 +99,17 @@ class Footer {
70
99
  if (this.rawXML) {
71
100
  return this.rawXML;
72
101
  }
73
- const elementXmls = this.elements.map((el) => el.toXML());
74
- let xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
75
- xml += '<w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ';
76
- xml += 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\n';
77
- for (const element of elementXmls) {
78
- xml += this.renderElement(element, 1);
79
- }
80
- if (this.elements.length === 0) {
81
- xml += ' <w:p/>\n';
82
- }
83
- xml += '</w:ftr>';
84
- return xml;
85
- }
86
- renderElement(element, indent) {
87
- const spaces = ' '.repeat(indent);
88
- let xml = '';
89
- if (element.selfClosing) {
90
- xml += `${spaces}<${element.name}`;
91
- if (element.attributes) {
92
- for (const [key, value] of Object.entries(element.attributes)) {
93
- xml += ` ${key}="${value}"`;
94
- }
95
- }
96
- xml += '/>\n';
97
- }
98
- else {
99
- xml += `${spaces}<${element.name}`;
100
- if (element.attributes) {
101
- for (const [key, value] of Object.entries(element.attributes)) {
102
- xml += ` ${key}="${value}"`;
103
- }
104
- }
105
- xml += '>';
106
- if (element.children && element.children.length > 0) {
107
- const hasOnlyText = element.children.every((c) => typeof c === 'string');
108
- if (hasOnlyText) {
109
- xml += element.children.join('');
110
- }
111
- else {
112
- xml += '\n';
113
- for (const child of element.children) {
114
- if (typeof child === 'string') {
115
- xml += spaces + ' ' + child + '\n';
116
- }
117
- else {
118
- xml += this.renderElement(child, indent + 1);
119
- }
120
- }
121
- xml += spaces;
122
- }
123
- }
124
- xml += `</${element.name}>\n`;
102
+ const children = this.elements.map((el) => el.toXML());
103
+ if (children.length === 0) {
104
+ children.push(XMLBuilder_js_1.XMLBuilder.w('p'));
125
105
  }
126
- return xml;
106
+ const namespaces = {
107
+ ...XMLBuilder_js_1.XMLBuilder.createNamespaces(),
108
+ 'mc:Ignorable': 'w14 w15 wp14 asvg',
109
+ };
110
+ const builder = new XMLBuilder_js_1.XMLBuilder();
111
+ builder.element('w:ftr', namespaces, children);
112
+ return builder.build(true);
127
113
  }
128
114
  getFilename(number) {
129
115
  return `footer${number}.xml`;
@@ -1 +1 @@
1
- {"version":3,"file":"Footer.js","sourceRoot":"","sources":["../../src/elements/Footer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Footer - Represents a document footer\n *\n * Footers appear at the bottom of pages and can contain text, tables, images, and fields.\n * Different footers can be defined for first page, odd pages, and even pages.\n */\n\nimport { XMLElement } from '../xml/XMLBuilder.js';\nimport { Paragraph } from './Paragraph.js';\nimport { RunFormatting } from './Run.js';\nimport { Table } from './Table.js';\n\n/**\n * Footer type\n */\nexport type FooterType = 'default' | 'first' | 'even';\n\n/**\n * Footer content element\n */\ntype FooterElement = Paragraph | Table;\n\n/**\n * Footer properties\n */\nexport interface FooterProperties {\n /** Footer type (default, first page, or even page) */\n type?: FooterType;\n}\n\n/**\n * Represents a document footer\n */\nexport class Footer {\n private elements: FooterElement[] = [];\n private type: FooterType;\n private footerId?: string;\n private rawXML?: string; // Store original XML for preservation\n\n /**\n * Creates a new footer\n * @param properties Footer properties\n */\n constructor(properties: FooterProperties = {}) {\n this.type = properties.type || 'default';\n }\n\n /**\n * Sets the raw XML content (used when loading existing footers)\n * @param xml Raw XML content\n */\n setRawXML(xml: string): this {\n this.rawXML = xml;\n return this;\n }\n\n /**\n * Gets the raw XML content if available\n */\n getRawXML(): string | undefined {\n return this.rawXML;\n }\n\n /**\n * Gets the footer type\n */\n getType(): FooterType {\n return this.type;\n }\n\n /**\n * Sets the footer ID (used for relationships)\n * @param id Footer ID\n */\n setFooterId(id: string): this {\n this.footerId = id;\n return this;\n }\n\n /**\n * Gets the footer ID\n */\n getFooterId(): string | undefined {\n return this.footerId;\n }\n\n /**\n * Adds a paragraph to the footer\n * @param paragraph Paragraph to add\n */\n addParagraph(paragraph: Paragraph): this {\n this.elements.push(paragraph);\n return this;\n }\n\n /**\n * Creates and adds a new paragraph\n * @param text Optional text content\n */\n createParagraph(text?: string): Paragraph {\n const para = new Paragraph();\n if (text) {\n para.addText(text);\n }\n this.elements.push(para);\n return para;\n }\n\n /**\n * Adds formatted text to the footer as a new paragraph\n *\n * Convenience method that creates a paragraph with a single formatted run.\n *\n * @param text - Text content\n * @param formatting - Optional run formatting (bold, font, size, etc.)\n * @returns The created Paragraph for further customization\n *\n * @example\n * ```typescript\n * footer.addText('Page ', { size: 8 });\n * footer.addText('Confidential', { italic: true, color: '888888' });\n * ```\n */\n addText(text: string, formatting?: RunFormatting): Paragraph {\n const para = new Paragraph();\n para.addText(text, formatting);\n this.elements.push(para);\n return para;\n }\n\n /**\n * Adds a table to the footer\n * @param table Table to add\n */\n addTable(table: Table): this {\n this.elements.push(table);\n return this;\n }\n\n /**\n * Creates and adds a new table\n * @param rows Number of rows\n * @param columns Number of columns\n */\n createTable(rows: number, columns: number): Table {\n const table = new Table(rows, columns);\n this.elements.push(table);\n return table;\n }\n\n /**\n * Gets all elements in the footer\n */\n getElements(): FooterElement[] {\n return [...this.elements];\n }\n\n /**\n * Gets the number of elements\n */\n getElementCount(): number {\n return this.elements.length;\n }\n\n /**\n * Clears all elements and resets raw XML so toXML() regenerates an empty footer\n */\n clear(): this {\n this.elements = [];\n this.rawXML = undefined;\n return this;\n }\n\n /**\n * Generates the complete footer XML file content\n * This creates a complete footer document (footer1.xml, etc.)\n */\n toXML(): string {\n // If we have raw XML preserved from loading, use it\n if (this.rawXML) {\n return this.rawXML;\n }\n\n // Otherwise generate from elements\n const elementXmls = this.elements.map((el) => el.toXML());\n\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n';\n xml += '<w:ftr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" ';\n xml += 'xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\\n';\n\n // Add elements\n for (const element of elementXmls) {\n xml += this.renderElement(element, 1);\n }\n\n // If no elements, add an empty paragraph\n if (this.elements.length === 0) {\n xml += ' <w:p/>\\n';\n }\n\n xml += '</w:ftr>';\n\n return xml;\n }\n\n /**\n * Renders an XML element to string with indentation\n */\n private renderElement(element: XMLElement, indent: number): string {\n const spaces = ' '.repeat(indent);\n let xml = '';\n\n if (element.selfClosing) {\n xml += `${spaces}<${element.name}`;\n if (element.attributes) {\n for (const [key, value] of Object.entries(element.attributes)) {\n xml += ` ${key}=\"${value}\"`;\n }\n }\n xml += '/>\\n';\n } else {\n xml += `${spaces}<${element.name}`;\n if (element.attributes) {\n for (const [key, value] of Object.entries(element.attributes)) {\n xml += ` ${key}=\"${value}\"`;\n }\n }\n xml += '>';\n\n if (element.children && element.children.length > 0) {\n const hasOnlyText = element.children.every((c) => typeof c === 'string');\n\n if (hasOnlyText) {\n // Inline text content\n xml += element.children.join('');\n } else {\n // Block-level children\n xml += '\\n';\n for (const child of element.children) {\n if (typeof child === 'string') {\n xml += spaces + ' ' + child + '\\n';\n } else {\n xml += this.renderElement(child, indent + 1);\n }\n }\n xml += spaces;\n }\n }\n\n xml += `</${element.name}>\\n`;\n }\n\n return xml;\n }\n\n /**\n * Gets the filename for this footer\n * @param number Footer number (1, 2, 3, etc.)\n */\n getFilename(number: number): string {\n return `footer${number}.xml`;\n }\n\n /**\n * Creates a default footer\n */\n static createDefault(): Footer {\n return new Footer({ type: 'default' });\n }\n\n /**\n * Creates a first page footer\n */\n static createFirst(): Footer {\n return new Footer({ type: 'first' });\n }\n\n /**\n * Creates an even page footer\n */\n static createEven(): Footer {\n return new Footer({ type: 'even' });\n }\n\n /**\n * Creates a footer with properties\n * @param properties Footer properties\n */\n static create(properties?: FooterProperties): Footer {\n return new Footer(properties);\n }\n}\n"]}
1
+ {"version":3,"file":"Footer.js","sourceRoot":"","sources":["../../src/elements/Footer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Footer - Represents a document footer\n *\n * Footers appear at the bottom of pages and can contain text, tables, images, and fields.\n * Different footers can be defined for first page, odd pages, and even pages.\n */\n\nimport { XMLBuilder } from '../xml/XMLBuilder.js';\nimport { XMLParser } from '../xml/XMLParser.js';\nimport { Paragraph } from './Paragraph.js';\nimport { RunFormatting } from './Run.js';\nimport { Table } from './Table.js';\n\n/**\n * Footer type\n */\nexport type FooterType = 'default' | 'first' | 'even';\n\n/**\n * Footer content element\n */\ntype FooterElement = Paragraph | Table;\n\n/**\n * Footer properties\n */\nexport interface FooterProperties {\n /** Footer type (default, first page, or even page) */\n type?: FooterType;\n}\n\n/**\n * Represents a document footer\n */\nexport class Footer {\n private elements: FooterElement[] = [];\n private type: FooterType;\n private footerId?: string;\n private rawXML?: string; // Store original XML for preservation\n // Top-level w:p/w:tbl count of the preserved raw XML. DocumentParser calls\n // setRawXML() before repopulating elements from that same XML, so mutators\n // can't simply clear rawXML — they would fire during parsing and lose the\n // preserved bytes. Instead, growth beyond this count is the signal that\n // content was added after load and the preserved XML is stale.\n private rawXmlBlockCount = Number.MAX_SAFE_INTEGER;\n\n /**\n * Creates a new footer\n * @param properties Footer properties\n */\n constructor(properties: FooterProperties = {}) {\n this.type = properties.type || 'default';\n }\n\n /**\n * Sets the raw XML content (used when loading existing footers)\n * @param xml Raw XML content\n */\n setRawXML(xml: string): this {\n this.rawXML = xml;\n this.rawXmlBlockCount = Footer.countTopLevelBlocks(xml);\n return this;\n }\n\n /**\n * Counts the top-level w:p/w:tbl children of a raw footer part.\n * Parsing populates this.elements from exactly those blocks, so the count\n * is the baseline against which mutators detect post-load additions.\n */\n private static countTopLevelBlocks(xml: string): number {\n try {\n const parsed = XMLParser.parseToObject(xml) as Record<string, unknown>;\n const root = parsed?.['w:ftr'];\n if (!root || typeof root !== 'object') {\n return 0;\n }\n const count = (node: unknown): number =>\n node === undefined ? 0 : Array.isArray(node) ? node.length : 1;\n const rootObj = root as Record<string, unknown>;\n return count(rootObj['w:p']) + count(rootObj['w:tbl']);\n } catch {\n // Unparseable part: never invalidate, keep the preserved bytes\n return Number.MAX_SAFE_INTEGER;\n }\n }\n\n /**\n * Drops the preserved raw XML once content grows beyond what that XML\n * already contains, so toXML() regenerates from elements and post-load\n * edits are not silently discarded on save.\n */\n private invalidateRawXmlOnGrowth(): void {\n if (this.rawXML !== undefined && this.elements.length > this.rawXmlBlockCount) {\n this.rawXML = undefined;\n }\n }\n\n /**\n * Gets the raw XML content if available\n */\n getRawXML(): string | undefined {\n return this.rawXML;\n }\n\n /**\n * Gets the footer type\n */\n getType(): FooterType {\n return this.type;\n }\n\n /**\n * Sets the footer ID (used for relationships)\n * @param id Footer ID\n */\n setFooterId(id: string): this {\n this.footerId = id;\n return this;\n }\n\n /**\n * Gets the footer ID\n */\n getFooterId(): string | undefined {\n return this.footerId;\n }\n\n /**\n * Adds a paragraph to the footer\n * @param paragraph Paragraph to add\n */\n addParagraph(paragraph: Paragraph): this {\n this.elements.push(paragraph);\n this.invalidateRawXmlOnGrowth();\n return this;\n }\n\n /**\n * Creates and adds a new paragraph\n * @param text Optional text content\n */\n createParagraph(text?: string): Paragraph {\n const para = new Paragraph();\n if (text) {\n para.addText(text);\n }\n this.elements.push(para);\n this.invalidateRawXmlOnGrowth();\n return para;\n }\n\n /**\n * Adds formatted text to the footer as a new paragraph\n *\n * Convenience method that creates a paragraph with a single formatted run.\n *\n * @param text - Text content\n * @param formatting - Optional run formatting (bold, font, size, etc.)\n * @returns The created Paragraph for further customization\n *\n * @example\n * ```typescript\n * footer.addText('Page ', { size: 8 });\n * footer.addText('Confidential', { italic: true, color: '888888' });\n * ```\n */\n addText(text: string, formatting?: RunFormatting): Paragraph {\n const para = new Paragraph();\n para.addText(text, formatting);\n this.elements.push(para);\n this.invalidateRawXmlOnGrowth();\n return para;\n }\n\n /**\n * Adds a table to the footer\n * @param table Table to add\n */\n addTable(table: Table): this {\n this.elements.push(table);\n this.invalidateRawXmlOnGrowth();\n return this;\n }\n\n /**\n * Creates and adds a new table\n * @param rows Number of rows\n * @param columns Number of columns\n */\n createTable(rows: number, columns: number): Table {\n const table = new Table(rows, columns);\n this.elements.push(table);\n this.invalidateRawXmlOnGrowth();\n return table;\n }\n\n /**\n * Gets all elements in the footer\n */\n getElements(): FooterElement[] {\n return [...this.elements];\n }\n\n /**\n * Gets the number of elements\n */\n getElementCount(): number {\n return this.elements.length;\n }\n\n /**\n * Clears all elements and resets raw XML so toXML() regenerates an empty footer\n */\n clear(): this {\n this.elements = [];\n this.rawXML = undefined;\n return this;\n }\n\n /**\n * Generates the complete footer XML file content\n * This creates a complete footer document (footer1.xml, etc.)\n */\n toXML(): string {\n // If we have raw XML preserved from loading, use it\n if (this.rawXML) {\n return this.rawXML;\n }\n\n // Serialize through XMLBuilder so text and attribute values are\n // XML-escaped and rawXml passthrough children are honored\n const children = this.elements.map((el) => el.toXML());\n\n // ECMA-376 requires block-level content in w:ftr\n if (children.length === 0) {\n children.push(XMLBuilder.w('p'));\n }\n\n const namespaces: Record<string, string> = {\n ...XMLBuilder.createNamespaces(),\n // Extension namespaces (w14:paraId etc. on regenerated paragraphs)\n // must be declared ignorable or Word rejects the part\n 'mc:Ignorable': 'w14 w15 wp14 asvg',\n };\n\n const builder = new XMLBuilder();\n builder.element('w:ftr', namespaces, children);\n return builder.build(true);\n }\n\n /**\n * Gets the filename for this footer\n * @param number Footer number (1, 2, 3, etc.)\n */\n getFilename(number: number): string {\n return `footer${number}.xml`;\n }\n\n /**\n * Creates a default footer\n */\n static createDefault(): Footer {\n return new Footer({ type: 'default' });\n }\n\n /**\n * Creates a first page footer\n */\n static createFirst(): Footer {\n return new Footer({ type: 'first' });\n }\n\n /**\n * Creates an even page footer\n */\n static createEven(): Footer {\n return new Footer({ type: 'even' });\n }\n\n /**\n * Creates a footer with properties\n * @param properties Footer properties\n */\n static create(properties?: FooterProperties): Footer {\n return new Footer(properties);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"FootnoteManager.d.ts","sourceRoot":"","sources":["../../src/elements/FootnoteManager.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAgB,MAAM,eAAe,CAAC;AAOvD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,MAAM,CAAK;IAMnB,OAAO;IASP,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,iBAAiB;IAYzB,MAAM,CAAC,MAAM,IAAI,eAAe;IAShC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ;IAuBtC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ;IAWtC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAQ7C,eAAe,IAAI,QAAQ,EAAE;IAS7B,0BAA0B,IAAI,QAAQ,EAAE;IAQxC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAShC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAWnC,SAAS,IAAI,MAAM;IAOnB,QAAQ,IAAI,MAAM;IAOlB,OAAO,IAAI,OAAO;IAQlB,KAAK,IAAI,IAAI;IAqBb,QAAQ,IAAI;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB;IAUD,oBAAoB,IAAI,MAAM;IAwB9B,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAkBtC"}
1
+ {"version":3,"file":"FootnoteManager.d.ts","sourceRoot":"","sources":["../../src/elements/FootnoteManager.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAgB,MAAM,eAAe,CAAC;AAOvD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,MAAM,CAAK;IAMnB,OAAO;IASP,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,iBAAiB;IAYzB,MAAM,CAAC,MAAM,IAAI,eAAe;IAShC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ;IAuBtC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ;IAWtC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAQ7C,eAAe,IAAI,QAAQ,EAAE;IAS7B,0BAA0B,IAAI,QAAQ,EAAE;IAQxC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAYhC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAWnC,SAAS,IAAI,MAAM;IAOnB,QAAQ,IAAI,MAAM;IAOlB,OAAO,IAAI,OAAO;IAQlB,KAAK,IAAI,IAAI;IAqBb,QAAQ,IAAI;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB;IAUD,oBAAoB,IAAI,MAAM;IAwB9B,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAkBtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"FootnoteManager.js","sourceRoot":"","sources":["../../src/elements/FootnoteManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * FootnoteManager - Manages footnotes in a document\n *\n * Handles creation, registration, and XML generation for footnotes.\n * Maintains unique IDs and proper ordering.\n */\n\nimport { Footnote, FootnoteType } from './Footnote.js';\nimport { XMLBuilder, XMLElement } from '../xml/XMLBuilder.js';\nimport { XMLParser } from '../xml/XMLParser.js';\n\n/**\n * Manages footnotes in a document\n */\nexport class FootnoteManager {\n private footnotes = new Map<number, Footnote>();\n private nextId = 1;\n\n /**\n * Creates a new FootnoteManager\n * @private Use static factory method\n */\n private constructor() {\n // Add special footnotes (separators) with negative IDs\n this.addSpecialFootnotes();\n }\n\n /**\n * Adds special footnotes (separator, continuation)\n * These use negative IDs as per OOXML specification\n */\n private addSpecialFootnotes(): void {\n // Separator footnote (ID -1)\n const separator = Footnote.createSeparator(-1);\n this.footnotes.set(-1, separator);\n\n // Continuation separator (ID 0)\n const continuationSep = Footnote.createContinuationSeparator(0);\n this.footnotes.set(0, continuationSep);\n }\n\n /**\n * Checks if a footnote is a special/system type (separator, continuationSeparator,\n * continuationNotice) that should be preserved across clear() operations.\n * Uses type-based detection rather than ID-based, because continuationNotice\n * has a positive ID (typically 1) but is still a system footnote.\n */\n private isSpecialFootnote(footnote: Footnote): boolean {\n const type = footnote.getType();\n return (\n type === FootnoteType.Separator ||\n type === FootnoteType.ContinuationSeparator ||\n type === FootnoteType.ContinuationNotice\n );\n }\n\n /**\n * Creates a new FootnoteManager instance\n */\n static create(): FootnoteManager {\n return new FootnoteManager();\n }\n\n /**\n * Registers a footnote\n * @param footnote Footnote to register\n * @returns The registered footnote\n */\n register(footnote: Footnote): Footnote {\n const id = footnote.getId();\n\n // Ensure ID is not already used (except for special footnotes)\n if (id > 0 && this.footnotes.has(id)) {\n throw new Error(`Footnote with ID ${id} already exists`);\n }\n\n this.footnotes.set(id, footnote);\n\n // Update next ID if needed\n if (id >= this.nextId) {\n this.nextId = id + 1;\n }\n\n return footnote;\n }\n\n /**\n * Creates and registers a new footnote\n * @param text Footnote text\n * @returns The created footnote\n */\n createFootnote(text: string): Footnote {\n const footnote = Footnote.fromText(this.nextId++, text);\n this.footnotes.set(footnote.getId(), footnote);\n return footnote;\n }\n\n /**\n * Gets a footnote by ID\n * @param id Footnote ID\n * @returns The footnote, or undefined if not found\n */\n getFootnote(id: number): Footnote | undefined {\n return this.footnotes.get(id);\n }\n\n /**\n * Gets all user footnotes (excluding special system types: separator,\n * continuationSeparator, continuationNotice)\n */\n getAllFootnotes(): Footnote[] {\n return Array.from(this.footnotes.values())\n .filter((f) => !this.isSpecialFootnote(f))\n .sort((a, b) => a.getId() - b.getId());\n }\n\n /**\n * Gets all footnotes including special ones\n */\n getAllFootnotesWithSpecial(): Footnote[] {\n return Array.from(this.footnotes.values()).sort((a, b) => a.getId() - b.getId());\n }\n\n /**\n * Checks if a footnote exists\n * @param id Footnote ID\n */\n hasFootnote(id: number): boolean {\n return this.footnotes.has(id);\n }\n\n /**\n * Removes a footnote\n * @param id Footnote ID\n * @returns True if removed, false if not found or if it's a special type\n */\n removeFootnote(id: number): boolean {\n const footnote = this.footnotes.get(id);\n if (!footnote || this.isSpecialFootnote(footnote)) {\n return false;\n }\n return this.footnotes.delete(id);\n }\n\n /**\n * Gets the next available ID\n */\n getNextId(): number {\n return this.nextId;\n }\n\n /**\n * Gets the count of footnotes (excluding special ones)\n */\n getCount(): number {\n return this.getAllFootnotes().length;\n }\n\n /**\n * Checks if there are any footnotes (excluding special ones)\n */\n isEmpty(): boolean {\n return this.getCount() === 0;\n }\n\n /**\n * Clears all user footnotes (preserves special system types: separator,\n * continuationSeparator, continuationNotice)\n */\n clear(): void {\n const specialFootnotes = new Map<number, Footnote>();\n let maxSpecialId = 0;\n\n for (const [id, footnote] of this.footnotes) {\n if (this.isSpecialFootnote(footnote)) {\n specialFootnotes.set(id, footnote);\n if (id > maxSpecialId) {\n maxSpecialId = id;\n }\n }\n }\n\n this.footnotes = specialFootnotes;\n // Ensure nextId doesn't collide with special footnotes that have positive IDs\n this.nextId = Math.max(maxSpecialId + 1, 1);\n }\n\n /**\n * Gets statistics about footnotes\n */\n getStats(): {\n total: number;\n nextId: number;\n } {\n return {\n total: this.getCount(),\n nextId: this.nextId,\n };\n }\n\n /**\n * Generates the footnotes.xml content\n */\n generateFootnotesXml(): string {\n const footnotes = this.getAllFootnotesWithSpecial();\n\n // Build footnotes element\n const footnotesElement: XMLElement = {\n name: 'w:footnotes',\n attributes: {\n 'xmlns:w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',\n 'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n },\n children: footnotes.map((f) => f.toXML()),\n };\n\n // Build XML using XMLBuilder\n const builder = new XMLBuilder();\n builder.element(footnotesElement.name, footnotesElement.attributes, footnotesElement.children);\n return builder.build(true);\n }\n\n /**\n * Validates footnotes XML\n * @param xml XML string to validate\n * @returns True if valid\n */\n static validate(xml: string): boolean {\n // Use XMLParser to extract root element\n if (!xml) {\n return false;\n }\n\n const footnotesContent = XMLParser.extractBetweenTags(xml, '<w:footnotes', '</w:footnotes>');\n if (!footnotesContent) {\n return false;\n }\n\n // Check for proper structure - namespace declaration\n if (!xml.includes('xmlns:w=')) {\n return false;\n }\n\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"FootnoteManager.js","sourceRoot":"","sources":["../../src/elements/FootnoteManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * FootnoteManager - Manages footnotes in a document\n *\n * Handles creation, registration, and XML generation for footnotes.\n * Maintains unique IDs and proper ordering.\n */\n\nimport { Footnote, FootnoteType } from './Footnote.js';\nimport { XMLBuilder, XMLElement } from '../xml/XMLBuilder.js';\nimport { XMLParser } from '../xml/XMLParser.js';\n\n/**\n * Manages footnotes in a document\n */\nexport class FootnoteManager {\n private footnotes = new Map<number, Footnote>();\n private nextId = 1;\n\n /**\n * Creates a new FootnoteManager\n * @private Use static factory method\n */\n private constructor() {\n // Add special footnotes (separators) with negative IDs\n this.addSpecialFootnotes();\n }\n\n /**\n * Adds special footnotes (separator, continuation)\n * These use negative IDs as per OOXML specification\n */\n private addSpecialFootnotes(): void {\n // Separator footnote (ID -1)\n const separator = Footnote.createSeparator(-1);\n this.footnotes.set(-1, separator);\n\n // Continuation separator (ID 0)\n const continuationSep = Footnote.createContinuationSeparator(0);\n this.footnotes.set(0, continuationSep);\n }\n\n /**\n * Checks if a footnote is a special/system type (separator, continuationSeparator,\n * continuationNotice) that should be preserved across clear() operations.\n * Uses type-based detection rather than ID-based, because continuationNotice\n * has a positive ID (typically 1) but is still a system footnote.\n */\n private isSpecialFootnote(footnote: Footnote): boolean {\n const type = footnote.getType();\n return (\n type === FootnoteType.Separator ||\n type === FootnoteType.ContinuationSeparator ||\n type === FootnoteType.ContinuationNotice\n );\n }\n\n /**\n * Creates a new FootnoteManager instance\n */\n static create(): FootnoteManager {\n return new FootnoteManager();\n }\n\n /**\n * Registers a footnote\n * @param footnote Footnote to register\n * @returns The registered footnote\n */\n register(footnote: Footnote): Footnote {\n const id = footnote.getId();\n\n // Ensure ID is not already used (except for special footnotes)\n if (id > 0 && this.footnotes.has(id)) {\n throw new Error(`Footnote with ID ${id} already exists`);\n }\n\n this.footnotes.set(id, footnote);\n\n // Update next ID if needed\n if (id >= this.nextId) {\n this.nextId = id + 1;\n }\n\n return footnote;\n }\n\n /**\n * Creates and registers a new footnote\n * @param text Footnote text\n * @returns The created footnote\n */\n createFootnote(text: string): Footnote {\n const footnote = Footnote.fromText(this.nextId++, text);\n this.footnotes.set(footnote.getId(), footnote);\n return footnote;\n }\n\n /**\n * Gets a footnote by ID\n * @param id Footnote ID\n * @returns The footnote, or undefined if not found\n */\n getFootnote(id: number): Footnote | undefined {\n return this.footnotes.get(id);\n }\n\n /**\n * Gets all user footnotes (excluding special system types: separator,\n * continuationSeparator, continuationNotice)\n */\n getAllFootnotes(): Footnote[] {\n return Array.from(this.footnotes.values())\n .filter((f) => !this.isSpecialFootnote(f))\n .sort((a, b) => a.getId() - b.getId());\n }\n\n /**\n * Gets all footnotes including special ones\n */\n getAllFootnotesWithSpecial(): Footnote[] {\n return Array.from(this.footnotes.values()).sort((a, b) => a.getId() - b.getId());\n }\n\n /**\n * Checks if a footnote exists\n * @param id Footnote ID\n */\n hasFootnote(id: number): boolean {\n return this.footnotes.has(id);\n }\n\n /**\n * Removes a footnote from the model only. Does not touch body\n * w:footnoteReference runs or the document's dirty flags — callers going\n * through a Document should use Document.removeFootnote(), which also\n * strips the matching references and forces footnotes.xml regeneration.\n * @param id Footnote ID\n * @returns True if removed, false if not found or if it's a special type\n */\n removeFootnote(id: number): boolean {\n const footnote = this.footnotes.get(id);\n if (!footnote || this.isSpecialFootnote(footnote)) {\n return false;\n }\n return this.footnotes.delete(id);\n }\n\n /**\n * Gets the next available ID\n */\n getNextId(): number {\n return this.nextId;\n }\n\n /**\n * Gets the count of footnotes (excluding special ones)\n */\n getCount(): number {\n return this.getAllFootnotes().length;\n }\n\n /**\n * Checks if there are any footnotes (excluding special ones)\n */\n isEmpty(): boolean {\n return this.getCount() === 0;\n }\n\n /**\n * Clears all user footnotes (preserves special system types: separator,\n * continuationSeparator, continuationNotice)\n */\n clear(): void {\n const specialFootnotes = new Map<number, Footnote>();\n let maxSpecialId = 0;\n\n for (const [id, footnote] of this.footnotes) {\n if (this.isSpecialFootnote(footnote)) {\n specialFootnotes.set(id, footnote);\n if (id > maxSpecialId) {\n maxSpecialId = id;\n }\n }\n }\n\n this.footnotes = specialFootnotes;\n // Ensure nextId doesn't collide with special footnotes that have positive IDs\n this.nextId = Math.max(maxSpecialId + 1, 1);\n }\n\n /**\n * Gets statistics about footnotes\n */\n getStats(): {\n total: number;\n nextId: number;\n } {\n return {\n total: this.getCount(),\n nextId: this.nextId,\n };\n }\n\n /**\n * Generates the footnotes.xml content\n */\n generateFootnotesXml(): string {\n const footnotes = this.getAllFootnotesWithSpecial();\n\n // Build footnotes element\n const footnotesElement: XMLElement = {\n name: 'w:footnotes',\n attributes: {\n 'xmlns:w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',\n 'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n },\n children: footnotes.map((f) => f.toXML()),\n };\n\n // Build XML using XMLBuilder\n const builder = new XMLBuilder();\n builder.element(footnotesElement.name, footnotesElement.attributes, footnotesElement.children);\n return builder.build(true);\n }\n\n /**\n * Validates footnotes XML\n * @param xml XML string to validate\n * @returns True if valid\n */\n static validate(xml: string): boolean {\n // Use XMLParser to extract root element\n if (!xml) {\n return false;\n }\n\n const footnotesContent = XMLParser.extractBetweenTags(xml, '<w:footnotes', '</w:footnotes>');\n if (!footnotesContent) {\n return false;\n }\n\n // Check for proper structure - namespace declaration\n if (!xml.includes('xmlns:w=')) {\n return false;\n }\n\n return true;\n }\n}\n"]}
@@ -11,8 +11,11 @@ export declare class Header {
11
11
  private type;
12
12
  private headerId?;
13
13
  private rawXML?;
14
+ private rawXmlBlockCount;
14
15
  constructor(properties?: HeaderProperties);
15
16
  setRawXML(xml: string): this;
17
+ private static countTopLevelBlocks;
18
+ private invalidateRawXmlOnGrowth;
16
19
  getRawXML(): string | undefined;
17
20
  getType(): HeaderType;
18
21
  setHeaderId(id: string): this;
@@ -26,7 +29,6 @@ export declare class Header {
26
29
  getElementCount(): number;
27
30
  clear(): this;
28
31
  toXML(): string;
29
- private renderElement;
30
32
  getFilename(number: number): string;
31
33
  static createDefault(): Header;
32
34
  static createFirst(): Header;
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/elements/Header.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAKtD,KAAK,aAAa,GAAG,SAAS,GAAG,KAAK,CAAC;AAKvC,MAAM,WAAW,gBAAgB;IAE/B,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAKD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAS;gBAMZ,UAAU,GAAE,gBAAqB;IAQ7C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQ5B,SAAS,IAAI,MAAM,GAAG,SAAS;IAO/B,OAAO,IAAI,UAAU;IAQrB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ7B,WAAW,IAAI,MAAM,GAAG,SAAS;IAQjC,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IASxC,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS;IA0BzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,SAAS;IAW5D,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAU5B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK;IASjD,WAAW,IAAI,aAAa,EAAE;IAO9B,eAAe,IAAI,MAAM;IAOzB,KAAK,IAAI,IAAI;IAUb,KAAK,IAAI,MAAM;IA+Bf,OAAO,CAAC,aAAa;IAmDrB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOnC,MAAM,CAAC,aAAa,IAAI,MAAM;IAO9B,MAAM,CAAC,WAAW,IAAI,MAAM;IAO5B,MAAM,CAAC,UAAU,IAAI,MAAM;IAQ3B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,gBAAgB,GAAG,MAAM;CAGrD"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/elements/Header.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAKtD,KAAK,aAAa,GAAG,SAAS,GAAG,KAAK,CAAC;AAKvC,MAAM,WAAW,gBAAgB;IAE/B,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAKD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAS;IAMxB,OAAO,CAAC,gBAAgB,CAA2B;gBAMvC,UAAU,GAAE,gBAAqB;IAQ7C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW5B,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsBlC,OAAO,CAAC,wBAAwB;IAShC,SAAS,IAAI,MAAM,GAAG,SAAS;IAO/B,OAAO,IAAI,UAAU;IAQrB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ7B,WAAW,IAAI,MAAM,GAAG,SAAS;IAQjC,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAUxC,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS;IA2BzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,SAAS;IAY5D,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAW5B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK;IAUjD,WAAW,IAAI,aAAa,EAAE;IAO9B,eAAe,IAAI,MAAM;IAOzB,KAAK,IAAI,IAAI;IAUb,KAAK,IAAI,MAAM;IA+Bf,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOnC,MAAM,CAAC,aAAa,IAAI,MAAM;IAO9B,MAAM,CAAC,WAAW,IAAI,MAAM;IAO5B,MAAM,CAAC,UAAU,IAAI,MAAM;IAQ3B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,gBAAgB,GAAG,MAAM;CAGrD"}
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Header = void 0;
4
+ const XMLBuilder_js_1 = require("../xml/XMLBuilder.js");
5
+ const XMLParser_js_1 = require("../xml/XMLParser.js");
4
6
  const Paragraph_js_1 = require("./Paragraph.js");
5
7
  const Table_js_1 = require("./Table.js");
6
8
  class Header {
@@ -8,13 +10,35 @@ class Header {
8
10
  type;
9
11
  headerId;
10
12
  rawXML;
13
+ rawXmlBlockCount = Number.MAX_SAFE_INTEGER;
11
14
  constructor(properties = {}) {
12
15
  this.type = properties.type || 'default';
13
16
  }
14
17
  setRawXML(xml) {
15
18
  this.rawXML = xml;
19
+ this.rawXmlBlockCount = Header.countTopLevelBlocks(xml);
16
20
  return this;
17
21
  }
22
+ static countTopLevelBlocks(xml) {
23
+ try {
24
+ const parsed = XMLParser_js_1.XMLParser.parseToObject(xml);
25
+ const root = parsed?.['w:hdr'];
26
+ if (!root || typeof root !== 'object') {
27
+ return 0;
28
+ }
29
+ const count = (node) => node === undefined ? 0 : Array.isArray(node) ? node.length : 1;
30
+ const rootObj = root;
31
+ return count(rootObj['w:p']) + count(rootObj['w:tbl']);
32
+ }
33
+ catch {
34
+ return Number.MAX_SAFE_INTEGER;
35
+ }
36
+ }
37
+ invalidateRawXmlOnGrowth() {
38
+ if (this.rawXML !== undefined && this.elements.length > this.rawXmlBlockCount) {
39
+ this.rawXML = undefined;
40
+ }
41
+ }
18
42
  getRawXML() {
19
43
  return this.rawXML;
20
44
  }
@@ -30,6 +54,7 @@ class Header {
30
54
  }
31
55
  addParagraph(paragraph) {
32
56
  this.elements.push(paragraph);
57
+ this.invalidateRawXmlOnGrowth();
33
58
  return this;
34
59
  }
35
60
  createParagraph(text) {
@@ -38,21 +63,25 @@ class Header {
38
63
  para.addText(text);
39
64
  }
40
65
  this.elements.push(para);
66
+ this.invalidateRawXmlOnGrowth();
41
67
  return para;
42
68
  }
43
69
  addText(text, formatting) {
44
70
  const para = new Paragraph_js_1.Paragraph();
45
71
  para.addText(text, formatting);
46
72
  this.elements.push(para);
73
+ this.invalidateRawXmlOnGrowth();
47
74
  return para;
48
75
  }
49
76
  addTable(table) {
50
77
  this.elements.push(table);
78
+ this.invalidateRawXmlOnGrowth();
51
79
  return this;
52
80
  }
53
81
  createTable(rows, columns) {
54
82
  const table = new Table_js_1.Table(rows, columns);
55
83
  this.elements.push(table);
84
+ this.invalidateRawXmlOnGrowth();
56
85
  return table;
57
86
  }
58
87
  getElements() {
@@ -70,60 +99,17 @@ class Header {
70
99
  if (this.rawXML) {
71
100
  return this.rawXML;
72
101
  }
73
- const elementXmls = this.elements.map((el) => el.toXML());
74
- let xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
75
- xml += '<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ';
76
- xml += 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\n';
77
- for (const element of elementXmls) {
78
- xml += this.renderElement(element, 1);
79
- }
80
- if (this.elements.length === 0) {
81
- xml += ' <w:p/>\n';
82
- }
83
- xml += '</w:hdr>';
84
- return xml;
85
- }
86
- renderElement(element, indent) {
87
- const spaces = ' '.repeat(indent);
88
- let xml = '';
89
- if (element.selfClosing) {
90
- xml += `${spaces}<${element.name}`;
91
- if (element.attributes) {
92
- for (const [key, value] of Object.entries(element.attributes)) {
93
- xml += ` ${key}="${value}"`;
94
- }
95
- }
96
- xml += '/>\n';
97
- }
98
- else {
99
- xml += `${spaces}<${element.name}`;
100
- if (element.attributes) {
101
- for (const [key, value] of Object.entries(element.attributes)) {
102
- xml += ` ${key}="${value}"`;
103
- }
104
- }
105
- xml += '>';
106
- if (element.children && element.children.length > 0) {
107
- const hasOnlyText = element.children.every((c) => typeof c === 'string');
108
- if (hasOnlyText) {
109
- xml += element.children.join('');
110
- }
111
- else {
112
- xml += '\n';
113
- for (const child of element.children) {
114
- if (typeof child === 'string') {
115
- xml += spaces + ' ' + child + '\n';
116
- }
117
- else {
118
- xml += this.renderElement(child, indent + 1);
119
- }
120
- }
121
- xml += spaces;
122
- }
123
- }
124
- xml += `</${element.name}>\n`;
102
+ const children = this.elements.map((el) => el.toXML());
103
+ if (children.length === 0) {
104
+ children.push(XMLBuilder_js_1.XMLBuilder.w('p'));
125
105
  }
126
- return xml;
106
+ const namespaces = {
107
+ ...XMLBuilder_js_1.XMLBuilder.createNamespaces(),
108
+ 'mc:Ignorable': 'w14 w15 wp14 asvg',
109
+ };
110
+ const builder = new XMLBuilder_js_1.XMLBuilder();
111
+ builder.element('w:hdr', namespaces, children);
112
+ return builder.build(true);
127
113
  }
128
114
  getFilename(number) {
129
115
  return `header${number}.xml`;
@@ -1 +1 @@
1
- {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/elements/Header.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Header - Represents a document header\n *\n * Headers appear at the top of pages and can contain text, tables, images, and fields.\n * Different headers can be defined for first page, odd pages, and even pages.\n */\n\nimport { XMLElement } from '../xml/XMLBuilder.js';\nimport { Paragraph } from './Paragraph.js';\nimport { RunFormatting } from './Run.js';\nimport { Table } from './Table.js';\n\n/**\n * Header type\n */\nexport type HeaderType = 'default' | 'first' | 'even';\n\n/**\n * Header content element\n */\ntype HeaderElement = Paragraph | Table;\n\n/**\n * Header properties\n */\nexport interface HeaderProperties {\n /** Header type (default, first page, or even page) */\n type?: HeaderType;\n}\n\n/**\n * Represents a document header\n */\nexport class Header {\n private elements: HeaderElement[] = [];\n private type: HeaderType;\n private headerId?: string;\n private rawXML?: string; // Store original XML for preservation\n\n /**\n * Creates a new header\n * @param properties Header properties\n */\n constructor(properties: HeaderProperties = {}) {\n this.type = properties.type || 'default';\n }\n\n /**\n * Sets the raw XML content (used when loading existing headers)\n * @param xml Raw XML content\n */\n setRawXML(xml: string): this {\n this.rawXML = xml;\n return this;\n }\n\n /**\n * Gets the raw XML content if available\n */\n getRawXML(): string | undefined {\n return this.rawXML;\n }\n\n /**\n * Gets the header type\n */\n getType(): HeaderType {\n return this.type;\n }\n\n /**\n * Sets the header ID (used for relationships)\n * @param id Header ID\n */\n setHeaderId(id: string): this {\n this.headerId = id;\n return this;\n }\n\n /**\n * Gets the header ID\n */\n getHeaderId(): string | undefined {\n return this.headerId;\n }\n\n /**\n * Adds a paragraph to the header\n * @param paragraph Paragraph to add\n */\n addParagraph(paragraph: Paragraph): this {\n this.elements.push(paragraph);\n return this;\n }\n\n /**\n * Creates and adds a new paragraph\n * @param text Optional text content\n */\n createParagraph(text?: string): Paragraph {\n const para = new Paragraph();\n if (text) {\n para.addText(text);\n }\n this.elements.push(para);\n return para;\n }\n\n /**\n * Adds formatted text to the header as a new paragraph\n *\n * Convenience method that creates a paragraph with a single formatted run.\n * For headers with multiple runs or complex content, use `createParagraph()`\n * and build content manually.\n *\n * @param text - Text content\n * @param formatting - Optional run formatting (bold, font, size, etc.)\n * @returns The created Paragraph for further customization\n *\n * @example\n * ```typescript\n * header.addText('Company Name', { bold: true, font: 'Arial', size: 10 });\n * header.addText('Confidential', { italic: true, color: 'FF0000' });\n * ```\n */\n addText(text: string, formatting?: RunFormatting): Paragraph {\n const para = new Paragraph();\n para.addText(text, formatting);\n this.elements.push(para);\n return para;\n }\n\n /**\n * Adds a table to the header\n * @param table Table to add\n */\n addTable(table: Table): this {\n this.elements.push(table);\n return this;\n }\n\n /**\n * Creates and adds a new table\n * @param rows Number of rows\n * @param columns Number of columns\n */\n createTable(rows: number, columns: number): Table {\n const table = new Table(rows, columns);\n this.elements.push(table);\n return table;\n }\n\n /**\n * Gets all elements in the header\n */\n getElements(): HeaderElement[] {\n return [...this.elements];\n }\n\n /**\n * Gets the number of elements\n */\n getElementCount(): number {\n return this.elements.length;\n }\n\n /**\n * Clears all elements and resets raw XML so toXML() regenerates an empty header\n */\n clear(): this {\n this.elements = [];\n this.rawXML = undefined;\n return this;\n }\n\n /**\n * Generates the complete header XML file content\n * This creates a complete header document (header1.xml, etc.)\n */\n toXML(): string {\n // If we have raw XML preserved from loading, use it\n if (this.rawXML) {\n return this.rawXML;\n }\n\n // Otherwise generate from elements\n const elementXmls = this.elements.map((el) => el.toXML());\n\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n';\n xml += '<w:hdr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" ';\n xml += 'xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\\n';\n\n // Add elements\n for (const element of elementXmls) {\n xml += this.renderElement(element, 1);\n }\n\n // If no elements, add an empty paragraph\n if (this.elements.length === 0) {\n xml += ' <w:p/>\\n';\n }\n\n xml += '</w:hdr>';\n\n return xml;\n }\n\n /**\n * Renders an XML element to string with indentation\n */\n private renderElement(element: XMLElement, indent: number): string {\n const spaces = ' '.repeat(indent);\n let xml = '';\n\n if (element.selfClosing) {\n xml += `${spaces}<${element.name}`;\n if (element.attributes) {\n for (const [key, value] of Object.entries(element.attributes)) {\n xml += ` ${key}=\"${value}\"`;\n }\n }\n xml += '/>\\n';\n } else {\n xml += `${spaces}<${element.name}`;\n if (element.attributes) {\n for (const [key, value] of Object.entries(element.attributes)) {\n xml += ` ${key}=\"${value}\"`;\n }\n }\n xml += '>';\n\n if (element.children && element.children.length > 0) {\n const hasOnlyText = element.children.every((c) => typeof c === 'string');\n\n if (hasOnlyText) {\n // Inline text content\n xml += element.children.join('');\n } else {\n // Block-level children\n xml += '\\n';\n for (const child of element.children) {\n if (typeof child === 'string') {\n xml += spaces + ' ' + child + '\\n';\n } else {\n xml += this.renderElement(child, indent + 1);\n }\n }\n xml += spaces;\n }\n }\n\n xml += `</${element.name}>\\n`;\n }\n\n return xml;\n }\n\n /**\n * Gets the filename for this header\n * @param number Header number (1, 2, 3, etc.)\n */\n getFilename(number: number): string {\n return `header${number}.xml`;\n }\n\n /**\n * Creates a default header\n */\n static createDefault(): Header {\n return new Header({ type: 'default' });\n }\n\n /**\n * Creates a first page header\n */\n static createFirst(): Header {\n return new Header({ type: 'first' });\n }\n\n /**\n * Creates an even page header\n */\n static createEven(): Header {\n return new Header({ type: 'even' });\n }\n\n /**\n * Creates a header with properties\n * @param properties Header properties\n */\n static create(properties?: HeaderProperties): Header {\n return new Header(properties);\n }\n}\n"]}
1
+ {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/elements/Header.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Header - Represents a document header\n *\n * Headers appear at the top of pages and can contain text, tables, images, and fields.\n * Different headers can be defined for first page, odd pages, and even pages.\n */\n\nimport { XMLBuilder } from '../xml/XMLBuilder.js';\nimport { XMLParser } from '../xml/XMLParser.js';\nimport { Paragraph } from './Paragraph.js';\nimport { RunFormatting } from './Run.js';\nimport { Table } from './Table.js';\n\n/**\n * Header type\n */\nexport type HeaderType = 'default' | 'first' | 'even';\n\n/**\n * Header content element\n */\ntype HeaderElement = Paragraph | Table;\n\n/**\n * Header properties\n */\nexport interface HeaderProperties {\n /** Header type (default, first page, or even page) */\n type?: HeaderType;\n}\n\n/**\n * Represents a document header\n */\nexport class Header {\n private elements: HeaderElement[] = [];\n private type: HeaderType;\n private headerId?: string;\n private rawXML?: string; // Store original XML for preservation\n // Top-level w:p/w:tbl count of the preserved raw XML. DocumentParser calls\n // setRawXML() before repopulating elements from that same XML, so mutators\n // can't simply clear rawXML — they would fire during parsing and lose the\n // preserved bytes. Instead, growth beyond this count is the signal that\n // content was added after load and the preserved XML is stale.\n private rawXmlBlockCount = Number.MAX_SAFE_INTEGER;\n\n /**\n * Creates a new header\n * @param properties Header properties\n */\n constructor(properties: HeaderProperties = {}) {\n this.type = properties.type || 'default';\n }\n\n /**\n * Sets the raw XML content (used when loading existing headers)\n * @param xml Raw XML content\n */\n setRawXML(xml: string): this {\n this.rawXML = xml;\n this.rawXmlBlockCount = Header.countTopLevelBlocks(xml);\n return this;\n }\n\n /**\n * Counts the top-level w:p/w:tbl children of a raw header part.\n * Parsing populates this.elements from exactly those blocks, so the count\n * is the baseline against which mutators detect post-load additions.\n */\n private static countTopLevelBlocks(xml: string): number {\n try {\n const parsed = XMLParser.parseToObject(xml) as Record<string, unknown>;\n const root = parsed?.['w:hdr'];\n if (!root || typeof root !== 'object') {\n return 0;\n }\n const count = (node: unknown): number =>\n node === undefined ? 0 : Array.isArray(node) ? node.length : 1;\n const rootObj = root as Record<string, unknown>;\n return count(rootObj['w:p']) + count(rootObj['w:tbl']);\n } catch {\n // Unparseable part: never invalidate, keep the preserved bytes\n return Number.MAX_SAFE_INTEGER;\n }\n }\n\n /**\n * Drops the preserved raw XML once content grows beyond what that XML\n * already contains, so toXML() regenerates from elements and post-load\n * edits are not silently discarded on save.\n */\n private invalidateRawXmlOnGrowth(): void {\n if (this.rawXML !== undefined && this.elements.length > this.rawXmlBlockCount) {\n this.rawXML = undefined;\n }\n }\n\n /**\n * Gets the raw XML content if available\n */\n getRawXML(): string | undefined {\n return this.rawXML;\n }\n\n /**\n * Gets the header type\n */\n getType(): HeaderType {\n return this.type;\n }\n\n /**\n * Sets the header ID (used for relationships)\n * @param id Header ID\n */\n setHeaderId(id: string): this {\n this.headerId = id;\n return this;\n }\n\n /**\n * Gets the header ID\n */\n getHeaderId(): string | undefined {\n return this.headerId;\n }\n\n /**\n * Adds a paragraph to the header\n * @param paragraph Paragraph to add\n */\n addParagraph(paragraph: Paragraph): this {\n this.elements.push(paragraph);\n this.invalidateRawXmlOnGrowth();\n return this;\n }\n\n /**\n * Creates and adds a new paragraph\n * @param text Optional text content\n */\n createParagraph(text?: string): Paragraph {\n const para = new Paragraph();\n if (text) {\n para.addText(text);\n }\n this.elements.push(para);\n this.invalidateRawXmlOnGrowth();\n return para;\n }\n\n /**\n * Adds formatted text to the header as a new paragraph\n *\n * Convenience method that creates a paragraph with a single formatted run.\n * For headers with multiple runs or complex content, use `createParagraph()`\n * and build content manually.\n *\n * @param text - Text content\n * @param formatting - Optional run formatting (bold, font, size, etc.)\n * @returns The created Paragraph for further customization\n *\n * @example\n * ```typescript\n * header.addText('Company Name', { bold: true, font: 'Arial', size: 10 });\n * header.addText('Confidential', { italic: true, color: 'FF0000' });\n * ```\n */\n addText(text: string, formatting?: RunFormatting): Paragraph {\n const para = new Paragraph();\n para.addText(text, formatting);\n this.elements.push(para);\n this.invalidateRawXmlOnGrowth();\n return para;\n }\n\n /**\n * Adds a table to the header\n * @param table Table to add\n */\n addTable(table: Table): this {\n this.elements.push(table);\n this.invalidateRawXmlOnGrowth();\n return this;\n }\n\n /**\n * Creates and adds a new table\n * @param rows Number of rows\n * @param columns Number of columns\n */\n createTable(rows: number, columns: number): Table {\n const table = new Table(rows, columns);\n this.elements.push(table);\n this.invalidateRawXmlOnGrowth();\n return table;\n }\n\n /**\n * Gets all elements in the header\n */\n getElements(): HeaderElement[] {\n return [...this.elements];\n }\n\n /**\n * Gets the number of elements\n */\n getElementCount(): number {\n return this.elements.length;\n }\n\n /**\n * Clears all elements and resets raw XML so toXML() regenerates an empty header\n */\n clear(): this {\n this.elements = [];\n this.rawXML = undefined;\n return this;\n }\n\n /**\n * Generates the complete header XML file content\n * This creates a complete header document (header1.xml, etc.)\n */\n toXML(): string {\n // If we have raw XML preserved from loading, use it\n if (this.rawXML) {\n return this.rawXML;\n }\n\n // Serialize through XMLBuilder so text and attribute values are\n // XML-escaped and rawXml passthrough children are honored\n const children = this.elements.map((el) => el.toXML());\n\n // ECMA-376 requires block-level content in w:hdr\n if (children.length === 0) {\n children.push(XMLBuilder.w('p'));\n }\n\n const namespaces: Record<string, string> = {\n ...XMLBuilder.createNamespaces(),\n // Extension namespaces (w14:paraId etc. on regenerated paragraphs)\n // must be declared ignorable or Word rejects the part\n 'mc:Ignorable': 'w14 w15 wp14 asvg',\n };\n\n const builder = new XMLBuilder();\n builder.element('w:hdr', namespaces, children);\n return builder.build(true);\n }\n\n /**\n * Gets the filename for this header\n * @param number Header number (1, 2, 3, etc.)\n */\n getFilename(number: number): string {\n return `header${number}.xml`;\n }\n\n /**\n * Creates a default header\n */\n static createDefault(): Header {\n return new Header({ type: 'default' });\n }\n\n /**\n * Creates a first page header\n */\n static createFirst(): Header {\n return new Header({ type: 'first' });\n }\n\n /**\n * Creates an even page header\n */\n static createEven(): Header {\n return new Header({ type: 'even' });\n }\n\n /**\n * Creates a header with properties\n * @param properties Header properties\n */\n static create(properties?: HeaderProperties): Header {\n return new Header(properties);\n }\n}\n"]}
@@ -18,8 +18,10 @@ export declare class HeaderFooterManager {
18
18
  private nextHeaderNumber;
19
19
  private nextFooterNumber;
20
20
  constructor();
21
- registerHeader(header: Header, relationshipId: string): string;
22
- registerFooter(footer: Footer, relationshipId: string): string;
21
+ registerHeader(header: Header, relationshipId: string, originalFilename?: string): string;
22
+ registerFooter(footer: Footer, relationshipId: string, originalFilename?: string): string;
23
+ peekHeaderFilename(header: Header): string;
24
+ peekFooterFilename(footer: Footer): string;
23
25
  getHeaderFilename(header: Header): string | undefined;
24
26
  getFooterFilename(footer: Footer): string | undefined;
25
27
  getHeaderRelationshipId(header: Header): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"HeaderFooterManager.d.ts","sourceRoot":"","sources":["../../src/elements/HeaderFooterManager.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAKrC,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAS;;IAkBjC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM;IAiC9D,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM;IAgC9D,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASrD,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASrD,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAS3D,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQ3D,aAAa,IAAI,WAAW,EAAE;IAQ9B,aAAa,IAAI,WAAW,EAAE;IAQ9B,cAAc,IAAI,MAAM;IAQxB,cAAc,IAAI,MAAM;IASxB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IASlC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAOlC,KAAK,IAAI,IAAI;IAWb,MAAM,CAAC,MAAM,IAAI,mBAAmB;CAGrC"}
1
+ {"version":3,"file":"HeaderFooterManager.d.ts","sourceRoot":"","sources":["../../src/elements/HeaderFooterManager.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAKrC,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAS;;IAoBjC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM;IA8CzF,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM;IA6CzF,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAW1C,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAS1C,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASrD,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASrD,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAS3D,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQ3D,aAAa,IAAI,WAAW,EAAE;IAQ9B,aAAa,IAAI,WAAW,EAAE;IAQ9B,cAAc,IAAI,MAAM;IAQxB,cAAc,IAAI,MAAM;IASxB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IASlC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAOlC,KAAK,IAAI,IAAI;IAWb,MAAM,CAAC,MAAM,IAAI,mBAAmB;CAGrC"}
@@ -12,13 +12,25 @@ class HeaderFooterManager {
12
12
  this.nextHeaderNumber = 1;
13
13
  this.nextFooterNumber = 1;
14
14
  }
15
- registerHeader(header, relationshipId) {
15
+ registerHeader(header, relationshipId, originalFilename) {
16
16
  const existing = this.headers.get(header);
17
17
  if (existing) {
18
18
  return existing.filename;
19
19
  }
20
- const number = this.nextHeaderNumber++;
21
- const filename = header.getFilename(number);
20
+ let number;
21
+ let filename;
22
+ if (originalFilename) {
23
+ filename = originalFilename;
24
+ const digits = /(\d+)\.xml$/i.exec(originalFilename)?.[1];
25
+ number = digits ? parseInt(digits, 10) : this.nextHeaderNumber;
26
+ if (number >= this.nextHeaderNumber) {
27
+ this.nextHeaderNumber = number + 1;
28
+ }
29
+ }
30
+ else {
31
+ number = this.nextHeaderNumber++;
32
+ filename = header.getFilename(number);
33
+ }
22
34
  header.setHeaderId(relationshipId);
23
35
  const entry = {
24
36
  header,
@@ -29,13 +41,25 @@ class HeaderFooterManager {
29
41
  this.headers.set(header, entry);
30
42
  return filename;
31
43
  }
32
- registerFooter(footer, relationshipId) {
44
+ registerFooter(footer, relationshipId, originalFilename) {
33
45
  const existing = this.footers.get(footer);
34
46
  if (existing) {
35
47
  return existing.filename;
36
48
  }
37
- const number = this.nextFooterNumber++;
38
- const filename = footer.getFilename(number);
49
+ let number;
50
+ let filename;
51
+ if (originalFilename) {
52
+ filename = originalFilename;
53
+ const digits = /(\d+)\.xml$/i.exec(originalFilename)?.[1];
54
+ number = digits ? parseInt(digits, 10) : this.nextFooterNumber;
55
+ if (number >= this.nextFooterNumber) {
56
+ this.nextFooterNumber = number + 1;
57
+ }
58
+ }
59
+ else {
60
+ number = this.nextFooterNumber++;
61
+ filename = footer.getFilename(number);
62
+ }
39
63
  footer.setFooterId(relationshipId);
40
64
  const entry = {
41
65
  footer,
@@ -46,6 +70,12 @@ class HeaderFooterManager {
46
70
  this.footers.set(footer, entry);
47
71
  return filename;
48
72
  }
73
+ peekHeaderFilename(header) {
74
+ return this.headers.get(header)?.filename ?? header.getFilename(this.nextHeaderNumber);
75
+ }
76
+ peekFooterFilename(footer) {
77
+ return this.footers.get(footer)?.filename ?? footer.getFilename(this.nextFooterNumber);
78
+ }
49
79
  getHeaderFilename(header) {
50
80
  return this.headers.get(header)?.filename;
51
81
  }