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
@@ -215,6 +215,16 @@ export class ImageManager {
215
215
  const oldFilename = entry.filename;
216
216
  if (oldFilename === newFilename) return oldFilename;
217
217
 
218
+ // Guard against clobbering a distinct image: if another entry already owns
219
+ // newFilename, renaming here would point two different images at the same
220
+ // media part and saveImages() would write both to the same path (last write
221
+ // wins). Callers must resolve the collision to a fresh name first.
222
+ if (this.isFilenameOwnedByOther(newFilename, oldFilename)) {
223
+ throw new Error(
224
+ `Cannot rename image to "${newFilename}": filename already in use by a different image`
225
+ );
226
+ }
227
+
218
228
  // Update all entries sharing the old filename
219
229
  for (const e of this.images.values()) {
220
230
  if (e.filename === oldFilename) e.filename = newFilename;
@@ -225,6 +235,20 @@ export class ImageManager {
225
235
  return oldFilename;
226
236
  }
227
237
 
238
+ /**
239
+ * Returns true if a registered image other than those sharing `excludeFilename`
240
+ * already uses `filename`. Used to detect rename collisions before they
241
+ * silently clobber a distinct media part.
242
+ */
243
+ isFilenameOwnedByOther(filename: string, excludeFilename: string): boolean {
244
+ for (const e of this.images.values()) {
245
+ if (e.filename === filename && e.filename !== excludeFilename) {
246
+ return true;
247
+ }
248
+ }
249
+ return false;
250
+ }
251
+
228
252
  /**
229
253
  * Gets all registered images
230
254
  * @returns Array of image entries
@@ -975,6 +975,62 @@ export class Paragraph {
975
975
  return [...this.commentsEnd];
976
976
  }
977
977
 
978
+ /**
979
+ * Removes every anchor for a comment ID from this paragraph: programmatic
980
+ * range markers (commentsStart/commentsEnd, which also emit the reference
981
+ * run) and raw-XML anchors preserved from loaded documents. Anchors left
982
+ * behind after the comment definition is deleted would point at a comment
983
+ * that no longer exists in comments.xml, which Word reports as unreadable
984
+ * content.
985
+ * @param commentId - ID of the comment whose anchors should be removed
986
+ * @returns true if any anchor was removed
987
+ */
988
+ removeCommentAnchor(commentId: number): boolean {
989
+ let removed = false;
990
+
991
+ const startCount = this.commentsStart.length;
992
+ this.commentsStart = this.commentsStart.filter((c) => c.getId() !== commentId);
993
+ if (this.commentsStart.length !== startCount) {
994
+ removed = true;
995
+ }
996
+
997
+ const endCount = this.commentsEnd.length;
998
+ this.commentsEnd = this.commentsEnd.filter((c) => c.getId() !== commentId);
999
+ if (this.commentsEnd.length !== endCount) {
1000
+ removed = true;
1001
+ }
1002
+
1003
+ const contentCount = this.content.length;
1004
+ this.content = this.content.filter((item) => {
1005
+ if (!(item instanceof PreservedElement)) {
1006
+ return true;
1007
+ }
1008
+ const elementType = item.getElementType();
1009
+ if (elementType === 'w:commentRangeStart' || elementType === 'w:commentRangeEnd') {
1010
+ return !Paragraph.rawXmlMatchesCommentId(item.getRawXml(), elementType, commentId);
1011
+ }
1012
+ if (elementType === 'w:r') {
1013
+ // Loaded comment reference runs are preserved as raw w:r XML
1014
+ return !Paragraph.rawXmlMatchesCommentId(item.getRawXml(), 'w:commentReference', commentId);
1015
+ }
1016
+ return true;
1017
+ });
1018
+ if (this.content.length !== contentCount) {
1019
+ removed = true;
1020
+ }
1021
+
1022
+ return removed;
1023
+ }
1024
+
1025
+ private static rawXmlMatchesCommentId(
1026
+ rawXml: string,
1027
+ elementName: string,
1028
+ commentId: number
1029
+ ): boolean {
1030
+ const match = rawXml.match(new RegExp(`<${elementName}\\b[^>]*\\bw:id="(\\d+)"`));
1031
+ return match !== null && Number(match[1]) === commentId;
1032
+ }
1033
+
978
1034
  /**
979
1035
  * Adds a page number field
980
1036
  * @param formatting - Optional run formatting for the page number
@@ -1152,7 +1208,46 @@ export class Paragraph {
1152
1208
  * ```
1153
1209
  */
1154
1210
  setText(text: string, formatting?: RunFormatting): this {
1155
- this.content = [new Run(text, formatting)];
1211
+ const newRun = new Run(text, formatting);
1212
+ // Wire parent/tracking so subsequent run.setText() tracking and table
1213
+ // conditional-formatting resolution work for the new run
1214
+ newRun._setParentParagraph(this);
1215
+ if (this.trackingContext) {
1216
+ newRun._setTrackingContext(this.trackingContext);
1217
+ }
1218
+
1219
+ if (this.trackingContext?.isEnabled()) {
1220
+ // Record the replacement as tracked delete + insert so the edit
1221
+ // appears in the revision record (mirrors clearContent() + addText())
1222
+ const deletedContent: ParagraphContent[] = [];
1223
+ for (const item of this.content) {
1224
+ // Skip items that are already revisions (don't double-wrap)
1225
+ if (item instanceof Revision) {
1226
+ deletedContent.push(item);
1227
+ } else if (item instanceof Run || item instanceof Hyperlink) {
1228
+ const revision = Revision.createDeletion(
1229
+ this.trackingContext.getAuthor(),
1230
+ item,
1231
+ new Date()
1232
+ );
1233
+ this.trackingContext.getRevisionManager().register(revision);
1234
+ deletedContent.push(revision);
1235
+ } else {
1236
+ // For other content types (fields, etc.), just keep them
1237
+ // as they may have complex structures
1238
+ deletedContent.push(item);
1239
+ }
1240
+ }
1241
+ const insertion = Revision.createInsertion(
1242
+ this.trackingContext.getAuthor(),
1243
+ newRun,
1244
+ new Date()
1245
+ );
1246
+ this.trackingContext.getRevisionManager().register(insertion);
1247
+ this.content = [...deletedContent, insertion];
1248
+ } else {
1249
+ this.content = [newRun];
1250
+ }
1156
1251
  return this;
1157
1252
  }
1158
1253
 
@@ -1424,6 +1519,35 @@ export class Paragraph {
1424
1519
  .join('');
1425
1520
  }
1426
1521
 
1522
+ /**
1523
+ * Gets the combined text content including tracked-change text.
1524
+ *
1525
+ * Like {@link getText}, but also emits text carried by `Revision` objects in
1526
+ * document order — both inserted text (`w:t`) and deleted text (`w:delText`).
1527
+ * Move and property-change revisions contribute no text. This exists as a
1528
+ * separate method because offset-based operations (`splitAt`, `findAndReplace`,
1529
+ * etc.) and round-trip serialization depend on the narrower {@link getText}
1530
+ * filter, which must keep ignoring revisions.
1531
+ *
1532
+ * @returns Combined text from Runs, Hyperlinks, and Revisions in document order
1533
+ *
1534
+ * @example
1535
+ * ```typescript
1536
+ * // Paragraph: run "H" + tracked-delete "ello" + tracked-insert "i" + run " World"
1537
+ * para.getText(); // "H World" (revisions filtered out)
1538
+ * para.getTextIncludingRevisions(); // "Helloi World" (deleted + inserted, in order)
1539
+ * ```
1540
+ */
1541
+ getTextIncludingRevisions(): string {
1542
+ return this.content
1543
+ .filter(
1544
+ (item): item is Run | Hyperlink | Revision =>
1545
+ item instanceof Run || item instanceof Hyperlink || item instanceof Revision
1546
+ )
1547
+ .map((item) => item.getText())
1548
+ .join('');
1549
+ }
1550
+
1427
1551
  /**
1428
1552
  * Gets all fields in the paragraph (both Field and ComplexField)
1429
1553
  *
@@ -4128,10 +4252,10 @@ export class Paragraph {
4128
4252
  // Clone all content (runs, fields, hyperlinks, revisions)
4129
4253
  for (const item of this.content) {
4130
4254
  if (item instanceof Run) {
4131
- // Clone the run with its text and formatting
4132
- const runFormatting = item.getFormatting();
4133
- const clonedRun = new Run(item.getText(), deepClone(runFormatting));
4134
- clonedParagraph.addRun(clonedRun);
4255
+ // Run.clone() deep-copies the content array, so non-text run content
4256
+ // (page breaks with breakType, field chars, footnote references,
4257
+ // symbols, etc.) survives instead of being flattened through getText()
4258
+ clonedParagraph.addRun(item.clone());
4135
4259
  } else {
4136
4260
  // For other content types, add them as-is (shallow copy for now)
4137
4261
  // In a more complete implementation, we'd clone these too
@@ -4814,16 +4938,26 @@ export class Paragraph {
4814
4938
  ? lastAffected.run.getText().slice(match.end - lastAffected.start)
4815
4939
  : '';
4816
4940
 
4817
- // Set the first affected run to: kept-before + replacement + kept-after
4818
- firstAffected.run.setText(keepBefore + replace + keepAfter);
4819
-
4820
- // Remove any middle/last runs that were fully or partially consumed
4821
- // (iterate in reverse to preserve indices)
4822
- for (let r = affectedRuns.length - 1; r >= 1; r--) {
4823
- const runEntry = affectedRuns[r]!;
4824
- const idx = this.content.indexOf(runEntry.run);
4825
- if (idx !== -1) {
4826
- this.content.splice(idx, 1);
4941
+ if (affectedRuns.length === 1) {
4942
+ // Match contained in a single run: rebuild it in place
4943
+ firstAffected.run.setText(keepBefore + replace + keepAfter);
4944
+ } else {
4945
+ // Trim the last run in place when partially consumed so its
4946
+ // formatting (rPr) survives on the unmatched tail
4947
+ if (keepAfter !== '') {
4948
+ lastAffected.run.setText(keepAfter);
4949
+ }
4950
+ firstAffected.run.setText(keepBefore + replace);
4951
+
4952
+ // Remove only fully consumed runs (iterate in reverse to preserve
4953
+ // indices); a partially consumed last run was trimmed above
4954
+ const lastRemovable = keepAfter !== '' ? affectedRuns.length - 2 : affectedRuns.length - 1;
4955
+ for (let r = lastRemovable; r >= 1; r--) {
4956
+ const runEntry = affectedRuns[r]!;
4957
+ const idx = this.content.indexOf(runEntry.run);
4958
+ if (idx !== -1) {
4959
+ this.content.splice(idx, 1);
4960
+ }
4827
4961
  }
4828
4962
  }
4829
4963
  }
@@ -5205,6 +5339,11 @@ export class Paragraph {
5205
5339
 
5206
5340
  if (
5207
5341
  prev instanceof Run &&
5342
+ // w:rPrChange lives outside formatting and Run.createFromContent()
5343
+ // would not carry it over, so treat it as a merge boundary to keep
5344
+ // tracked formatting history intact
5345
+ !prev.hasPropertyChangeRevision() &&
5346
+ !item.hasPropertyChangeRevision() &&
5208
5347
  isEqualFormatting(
5209
5348
  prev.getFormatting() as unknown as Record<string, unknown>,
5210
5349
  item.getFormatting() as unknown as Record<string, unknown>
@@ -5292,37 +5431,19 @@ export class Paragraph {
5292
5431
  clearDirectRunFormatting(properties?: string[]): this {
5293
5432
  const runs = this.getRuns();
5294
5433
 
5434
+ // Mutate formatting in place rather than rebuilding runs from getText():
5435
+ // reconstruction flattens non-text content (footnote/endnote references,
5436
+ // field chars, symbols disappear; page/column breaks demote to line breaks).
5295
5437
  for (const run of runs) {
5296
- const formatting = run.getFormatting();
5297
-
5298
5438
  if (properties && properties.length > 0) {
5299
- // Clear only specified properties
5300
- const newFormatting: RunFormatting = { ...formatting };
5439
+ const formatting = (run as unknown as { formatting: RunFormatting }).formatting;
5301
5440
  for (const prop of properties) {
5302
- if (prop in newFormatting) {
5303
- delete (newFormatting as any)[prop];
5441
+ if (prop in formatting) {
5442
+ delete (formatting as any)[prop];
5304
5443
  }
5305
5444
  }
5306
-
5307
- // Create new run with cleared formatting
5308
- const text = run.getText();
5309
- const newRun = new Run(text, newFormatting);
5310
-
5311
- // Replace in content array
5312
- const index = this.content.indexOf(run);
5313
- if (index !== -1) {
5314
- this.content[index] = newRun;
5315
- }
5316
5445
  } else {
5317
- // Clear ALL direct formatting - replace with plain text run
5318
- const text = run.getText();
5319
- const newRun = new Run(text, {});
5320
-
5321
- // Replace in content array
5322
- const index = this.content.indexOf(run);
5323
- if (index !== -1) {
5324
- this.content[index] = newRun;
5325
- }
5446
+ run.clearFormatting();
5326
5447
  }
5327
5448
  }
5328
5449