docxmlater 10.3.6 → 10.4.1

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 (184) hide show
  1. package/README.md +158 -7
  2. package/dist/core/Document.d.ts +98 -3
  3. package/dist/core/Document.d.ts.map +1 -1
  4. package/dist/core/Document.js +740 -50
  5. package/dist/core/Document.js.map +1 -1
  6. package/dist/core/DocumentContent.d.ts.map +1 -1
  7. package/dist/core/DocumentContent.js +0 -8
  8. package/dist/core/DocumentContent.js.map +1 -1
  9. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  10. package/dist/core/DocumentGenerator.js +9 -5
  11. package/dist/core/DocumentGenerator.js.map +1 -1
  12. package/dist/core/DocumentParser.d.ts.map +1 -1
  13. package/dist/core/DocumentParser.js +617 -104
  14. package/dist/core/DocumentParser.js.map +1 -1
  15. package/dist/core/RelationshipManager.d.ts.map +1 -1
  16. package/dist/core/RelationshipManager.js +4 -3
  17. package/dist/core/RelationshipManager.js.map +1 -1
  18. package/dist/elements/Bookmark.d.ts +7 -0
  19. package/dist/elements/Bookmark.d.ts.map +1 -1
  20. package/dist/elements/Bookmark.js +24 -4
  21. package/dist/elements/Bookmark.js.map +1 -1
  22. package/dist/elements/BookmarkManager.d.ts.map +1 -1
  23. package/dist/elements/BookmarkManager.js +4 -3
  24. package/dist/elements/BookmarkManager.js.map +1 -1
  25. package/dist/elements/CommonTypes.d.ts +2 -2
  26. package/dist/elements/CommonTypes.d.ts.map +1 -1
  27. package/dist/elements/CommonTypes.js +14 -1
  28. package/dist/elements/CommonTypes.js.map +1 -1
  29. package/dist/elements/Field.d.ts +1 -1
  30. package/dist/elements/Field.d.ts.map +1 -1
  31. package/dist/elements/Field.js +1 -1
  32. package/dist/elements/Field.js.map +1 -1
  33. package/dist/elements/Footer.d.ts +2 -0
  34. package/dist/elements/Footer.d.ts.map +1 -1
  35. package/dist/elements/Footer.js +6 -0
  36. package/dist/elements/Footer.js.map +1 -1
  37. package/dist/elements/Header.d.ts +2 -0
  38. package/dist/elements/Header.d.ts.map +1 -1
  39. package/dist/elements/Header.js +6 -0
  40. package/dist/elements/Header.js.map +1 -1
  41. package/dist/elements/Image.d.ts.map +1 -1
  42. package/dist/elements/Image.js +3 -0
  43. package/dist/elements/Image.js.map +1 -1
  44. package/dist/elements/Paragraph.d.ts +81 -1
  45. package/dist/elements/Paragraph.d.ts.map +1 -1
  46. package/dist/elements/Paragraph.js +515 -21
  47. package/dist/elements/Paragraph.js.map +1 -1
  48. package/dist/elements/Revision.d.ts +0 -1
  49. package/dist/elements/Revision.d.ts.map +1 -1
  50. package/dist/elements/Revision.js +0 -12
  51. package/dist/elements/Revision.js.map +1 -1
  52. package/dist/elements/RevisionManager.d.ts +0 -1
  53. package/dist/elements/RevisionManager.d.ts.map +1 -1
  54. package/dist/elements/RevisionManager.js +0 -2
  55. package/dist/elements/RevisionManager.js.map +1 -1
  56. package/dist/elements/Run.d.ts +16 -4
  57. package/dist/elements/Run.d.ts.map +1 -1
  58. package/dist/elements/Run.js +114 -22
  59. package/dist/elements/Run.js.map +1 -1
  60. package/dist/elements/Section.d.ts +7 -1
  61. package/dist/elements/Section.d.ts.map +1 -1
  62. package/dist/elements/Section.js +185 -4
  63. package/dist/elements/Section.js.map +1 -1
  64. package/dist/elements/Shape.js.map +1 -1
  65. package/dist/elements/Table.d.ts +30 -1
  66. package/dist/elements/Table.d.ts.map +1 -1
  67. package/dist/elements/Table.js +357 -40
  68. package/dist/elements/Table.js.map +1 -1
  69. package/dist/elements/TableCell.d.ts +3 -0
  70. package/dist/elements/TableCell.d.ts.map +1 -1
  71. package/dist/elements/TableCell.js +30 -3
  72. package/dist/elements/TableCell.js.map +1 -1
  73. package/dist/elements/TableGridChange.d.ts +0 -1
  74. package/dist/elements/TableGridChange.d.ts.map +1 -1
  75. package/dist/elements/TableGridChange.js +0 -10
  76. package/dist/elements/TableGridChange.js.map +1 -1
  77. package/dist/elements/TableRow.d.ts +4 -0
  78. package/dist/elements/TableRow.d.ts.map +1 -1
  79. package/dist/elements/TableRow.js +31 -3
  80. package/dist/elements/TableRow.js.map +1 -1
  81. package/dist/formatting/AbstractNumbering.d.ts +5 -0
  82. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  83. package/dist/formatting/AbstractNumbering.js +22 -0
  84. package/dist/formatting/AbstractNumbering.js.map +1 -1
  85. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  86. package/dist/formatting/NumberingLevel.js +3 -3
  87. package/dist/formatting/NumberingLevel.js.map +1 -1
  88. package/dist/formatting/Style.d.ts +1 -0
  89. package/dist/formatting/Style.d.ts.map +1 -1
  90. package/dist/formatting/Style.js +25 -59
  91. package/dist/formatting/Style.js.map +1 -1
  92. package/dist/formatting/StylesManager.d.ts +1 -0
  93. package/dist/formatting/StylesManager.d.ts.map +1 -1
  94. package/dist/formatting/StylesManager.js +12 -0
  95. package/dist/formatting/StylesManager.js.map +1 -1
  96. package/dist/helpers/CleanupHelper.js.map +1 -1
  97. package/dist/images/ImageOptimizer.d.ts.map +1 -1
  98. package/dist/images/ImageOptimizer.js +0 -1
  99. package/dist/images/ImageOptimizer.js.map +1 -1
  100. package/dist/index.d.ts +1 -1
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/managers/DrawingManager.d.ts.map +1 -1
  104. package/dist/managers/DrawingManager.js +4 -2
  105. package/dist/managers/DrawingManager.js.map +1 -1
  106. package/dist/types/formatting.d.ts +2 -2
  107. package/dist/types/formatting.d.ts.map +1 -1
  108. package/dist/types/formatting.js.map +1 -1
  109. package/dist/utils/ChangelogGenerator.d.ts +2 -2
  110. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  111. package/dist/utils/ChangelogGenerator.js +4 -5
  112. package/dist/utils/ChangelogGenerator.js.map +1 -1
  113. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  114. package/dist/utils/InMemoryRevisionAcceptor.js +0 -1
  115. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  116. package/dist/utils/RevisionAwareProcessor.d.ts +2 -2
  117. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  118. package/dist/utils/RevisionAwareProcessor.js +2 -2
  119. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  120. package/dist/utils/SelectiveRevisionAcceptor.d.ts +0 -2
  121. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  122. package/dist/utils/SelectiveRevisionAcceptor.js +0 -26
  123. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  124. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  125. package/dist/utils/ShadingResolver.js.map +1 -1
  126. package/dist/utils/acceptRevisions.js +1 -1
  127. package/dist/utils/acceptRevisions.js.map +1 -1
  128. package/dist/utils/stripTrackedChanges.js +1 -1
  129. package/dist/utils/stripTrackedChanges.js.map +1 -1
  130. package/dist/utils/units.d.ts.map +1 -1
  131. package/dist/utils/units.js +1 -1
  132. package/dist/utils/units.js.map +1 -1
  133. package/dist/validation/RevisionAutoFixer.d.ts +2 -1
  134. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  135. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  136. package/package.json +10 -1
  137. package/src/constants/CLAUDE.md +28 -0
  138. package/src/core/CLAUDE.md +4 -0
  139. package/src/core/Document.ts +1770 -83
  140. package/src/core/DocumentContent.ts +0 -11
  141. package/src/core/DocumentGenerator.ts +11 -12
  142. package/src/core/DocumentParser.ts +654 -141
  143. package/src/core/RelationshipManager.ts +6 -3
  144. package/src/elements/Bookmark.ts +39 -4
  145. package/src/elements/BookmarkManager.ts +4 -3
  146. package/src/elements/CLAUDE.md +18 -2
  147. package/src/elements/CommonTypes.ts +35 -8
  148. package/src/elements/Field.ts +1 -1
  149. package/src/elements/Footer.ts +23 -0
  150. package/src/elements/Header.ts +25 -0
  151. package/src/elements/Image.ts +5 -0
  152. package/src/elements/Paragraph.ts +1069 -41
  153. package/src/elements/Revision.ts +0 -19
  154. package/src/elements/RevisionManager.ts +1 -3
  155. package/src/elements/Run.ts +265 -35
  156. package/src/elements/Section.ts +214 -8
  157. package/src/elements/Shape.ts +1 -1
  158. package/src/elements/Table.ts +850 -61
  159. package/src/elements/TableCell.ts +84 -10
  160. package/src/elements/TableGridChange.ts +2 -16
  161. package/src/elements/TableRow.ts +94 -9
  162. package/src/formatting/AbstractNumbering.ts +42 -1
  163. package/src/formatting/CLAUDE.md +4 -0
  164. package/src/formatting/NumberingLevel.ts +11 -7
  165. package/src/formatting/Style.ts +39 -71
  166. package/src/formatting/StylesManager.ts +36 -0
  167. package/src/helpers/CleanupHelper.ts +1 -1
  168. package/src/images/ImageOptimizer.ts +0 -3
  169. package/src/index.ts +1 -1
  170. package/src/managers/DrawingManager.ts +5 -3
  171. package/src/tracking/CLAUDE.md +30 -0
  172. package/src/types/CLAUDE.md +39 -0
  173. package/src/types/formatting.ts +2 -2
  174. package/src/utils/CLAUDE.md +15 -0
  175. package/src/utils/ChangelogGenerator.ts +4 -5
  176. package/src/utils/InMemoryRevisionAcceptor.ts +0 -9
  177. package/src/utils/RevisionAwareProcessor.ts +2 -3
  178. package/src/utils/SelectiveRevisionAcceptor.ts +0 -39
  179. package/src/utils/ShadingResolver.ts +0 -1
  180. package/src/utils/acceptRevisions.ts +1 -1
  181. package/src/utils/stripTrackedChanges.ts +1 -1
  182. package/src/utils/units.ts +2 -1
  183. package/src/validation/CLAUDE.md +40 -0
  184. package/src/validation/RevisionAutoFixer.ts +2 -1
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Document = void 0;
37
37
  const Bookmark_1 = require("../elements/Bookmark");
38
38
  const BookmarkManager_1 = require("../elements/BookmarkManager");
39
+ const PreservedElement_1 = require("../elements/PreservedElement");
39
40
  const CommentManager_1 = require("../elements/CommentManager");
40
41
  const EndnoteManager_1 = require("../elements/EndnoteManager");
41
42
  const Field_1 = require("../elements/Field");
@@ -155,7 +156,6 @@ class Document {
155
156
  showInkAnnotations: true,
156
157
  };
157
158
  autoPopulateTOCs = false;
158
- autoSyncTOCStyles = false;
159
159
  skipDocumentXmlRegeneration = false;
160
160
  acceptRevisionsBeforeSave = false;
161
161
  _originalContentTypes;
@@ -243,6 +243,128 @@ class Document {
243
243
  doc.initializeRequiredFiles();
244
244
  return doc;
245
245
  }
246
+ static fromMarkdown(markdown, options) {
247
+ const doc = Document.create(options);
248
+ const lines = markdown.split('\n');
249
+ let i = 0;
250
+ while (i < lines.length) {
251
+ const line = lines[i];
252
+ if (line.trim() === '') {
253
+ i++;
254
+ continue;
255
+ }
256
+ if (/^\s{0,3}([-]{3,}|[*]{3,}|[_]{3,})\s*$/.test(line)) {
257
+ doc.addHorizontalRule();
258
+ i++;
259
+ continue;
260
+ }
261
+ const headingMatch = /^(#{1,6})\s+(.+)$/.exec(line);
262
+ if (headingMatch) {
263
+ const level = headingMatch[1].length;
264
+ const text = headingMatch[2];
265
+ const para = doc.addHeading('', level);
266
+ Document.applyInlineMarkdown(para, text);
267
+ i++;
268
+ continue;
269
+ }
270
+ if (line.trimStart().startsWith('|')) {
271
+ const tableLines = [];
272
+ while (i < lines.length && lines[i].trimStart().startsWith('|')) {
273
+ tableLines.push(lines[i]);
274
+ i++;
275
+ }
276
+ const table = Document.parseMarkdownTable(tableLines);
277
+ if (table) {
278
+ doc.addTable(table);
279
+ }
280
+ continue;
281
+ }
282
+ const bulletMatch = /^(\s*)[-*+]\s+(.+)$/.exec(line);
283
+ if (bulletMatch) {
284
+ const text = bulletMatch[2];
285
+ const para = doc.createParagraph();
286
+ Document.applyInlineMarkdown(para, text);
287
+ para.setStyle('ListBullet');
288
+ i++;
289
+ continue;
290
+ }
291
+ const numberMatch = /^(\s*)\d+[.)]\s+(.+)$/.exec(line);
292
+ if (numberMatch) {
293
+ const text = numberMatch[2];
294
+ const para = doc.createParagraph();
295
+ Document.applyInlineMarkdown(para, text);
296
+ para.setStyle('ListNumber');
297
+ i++;
298
+ continue;
299
+ }
300
+ const paraLines = [line];
301
+ i++;
302
+ while (i < lines.length &&
303
+ lines[i].trim() !== '' &&
304
+ !lines[i].trim().startsWith('#') &&
305
+ !lines[i].trim().startsWith('|') &&
306
+ !/^\s{0,3}([-]{3,}|[*]{3,}|[_]{3,})\s*$/.test(lines[i]) &&
307
+ !/^(\s*)[-*+]\s+/.test(lines[i]) &&
308
+ !/^(\s*)\d+[.)]\s+/.test(lines[i])) {
309
+ paraLines.push(lines[i]);
310
+ i++;
311
+ }
312
+ const para = doc.createParagraph();
313
+ Document.applyInlineMarkdown(para, paraLines.join(' '));
314
+ }
315
+ return doc;
316
+ }
317
+ static applyInlineMarkdown(para, text) {
318
+ const inlinePattern = /(\*\*\*(.+?)\*\*\*|\*\*(.+?)\*\*|\*(.+?)\*|~~(.+?)~~|`([^`]+)`|\[([^\]]+)\]\(([^)]+)\))/g;
319
+ let lastIndex = 0;
320
+ let match;
321
+ while ((match = inlinePattern.exec(text)) !== null) {
322
+ if (match.index > lastIndex) {
323
+ para.addText(text.slice(lastIndex, match.index));
324
+ }
325
+ if (match[2] !== undefined) {
326
+ para.addText(match[2], { bold: true, italic: true });
327
+ }
328
+ else if (match[3] !== undefined) {
329
+ para.addText(match[3], { bold: true });
330
+ }
331
+ else if (match[4] !== undefined) {
332
+ para.addText(match[4], { italic: true });
333
+ }
334
+ else if (match[5] !== undefined) {
335
+ para.addText(match[5], { strike: true });
336
+ }
337
+ else if (match[6] !== undefined) {
338
+ para.addText(match[6], { font: 'Courier New' });
339
+ }
340
+ else if (match[7] !== undefined && match[8] !== undefined) {
341
+ para.addHyperlink(new Hyperlink_1.Hyperlink({ url: match[8], text: match[7] }));
342
+ }
343
+ lastIndex = match.index + match[0].length;
344
+ }
345
+ if (lastIndex < text.length) {
346
+ para.addText(text.slice(lastIndex));
347
+ }
348
+ }
349
+ static parseMarkdownTable(lines) {
350
+ if (lines.length < 2)
351
+ return null;
352
+ const parseRow = (line) => line
353
+ .replace(/^\|/, '')
354
+ .replace(/\|$/, '')
355
+ .split('|')
356
+ .map((cell) => cell.trim());
357
+ const rows = [];
358
+ for (let i = 0; i < lines.length; i++) {
359
+ const cells = parseRow(lines[i]);
360
+ if (cells.every((c) => /^:?-+:?$/.test(c)))
361
+ continue;
362
+ rows.push(cells);
363
+ }
364
+ if (rows.length === 0)
365
+ return null;
366
+ return Table_1.Table.fromArray(rows);
367
+ }
246
368
  static async load(filePath, options) {
247
369
  const logger = getLogger();
248
370
  logger.info('Loading document from file', { path: filePath });
@@ -732,6 +854,21 @@ class Document {
732
854
  this.bodyElements.push(para);
733
855
  return para;
734
856
  }
857
+ addHeading(text, level = 1) {
858
+ return this.createParagraph(text).setStyle(`Heading${level}`);
859
+ }
860
+ addPageBreak() {
861
+ const para = this.createParagraph();
862
+ const run = new Run_1.Run('');
863
+ run.addBreak('page');
864
+ para.addRun(run);
865
+ return para;
866
+ }
867
+ addHorizontalRule(color = 'auto', size = 4) {
868
+ const para = this.createParagraph();
869
+ para.setBorder({ bottom: { style: 'single', size, color, space: 1 } });
870
+ return para;
871
+ }
735
872
  addTable(table) {
736
873
  table._setStylesManager(this.stylesManager);
737
874
  if (this.trackChangesEnabled && this.trackingContext.isEnabled()) {
@@ -750,6 +887,12 @@ class Document {
750
887
  this.bodyElements.push(table);
751
888
  return table;
752
889
  }
890
+ createTableFromCSV(csv, delimiter = ',') {
891
+ const table = Table_1.Table.fromCSV(csv, delimiter);
892
+ table._setStylesManager(this.stylesManager);
893
+ this.bodyElements.push(table);
894
+ return table;
895
+ }
753
896
  getTables() {
754
897
  return this.bodyElements.filter((el) => el instanceof Table_1.Table);
755
898
  }
@@ -1007,7 +1150,7 @@ class Document {
1007
1150
  await fs.unlink(tempPath);
1008
1151
  }
1009
1152
  catch (cleanupErr) {
1010
- logger.debug('Failed to clean up temp file', { tempPath, error: String(cleanupErr) });
1153
+ logger.warn('Failed to clean up temp file', { tempPath, error: String(cleanupErr) });
1011
1154
  }
1012
1155
  throw error;
1013
1156
  }
@@ -1049,6 +1192,22 @@ class Document {
1049
1192
  }
1050
1193
  }
1051
1194
  }
1195
+ async toBase64() {
1196
+ const buffer = await this.toBuffer();
1197
+ return buffer.toString('base64');
1198
+ }
1199
+ async toDataUri() {
1200
+ const base64 = await this.toBase64();
1201
+ return `data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,${base64}`;
1202
+ }
1203
+ static async loadFromBase64(base64, options) {
1204
+ const buffer = Buffer.from(base64, 'base64');
1205
+ return Document.loadFromBuffer(buffer, options);
1206
+ }
1207
+ async clone() {
1208
+ const buffer = await this.toBuffer();
1209
+ return Document.loadFromBuffer(buffer);
1210
+ }
1052
1211
  updateDocumentXml() {
1053
1212
  let xml = this.generator.generateDocumentXml(this.bodyElements, this.section, this.namespaces, this._documentBackground);
1054
1213
  xml = this.syncTOCFieldInstructions(xml);
@@ -2181,7 +2340,6 @@ class Document {
2181
2340
  left: options?.cellMargins?.left ?? 115,
2182
2341
  right: options?.cellMargins?.right ?? 115,
2183
2342
  };
2184
- const skipSingleCellTables = options?.skipSingleCellTables !== false && !singleCellShading;
2185
2343
  let tablesProcessed = 0;
2186
2344
  let headerRowsFormatted = 0;
2187
2345
  let cellsRecolored = 0;
@@ -2584,6 +2742,19 @@ class Document {
2584
2742
  }
2585
2743
  const registeredSet = new Set(existingRevisions);
2586
2744
  let docPrId = 1;
2745
+ const existingParaIds = new Set();
2746
+ const paragraphsNeedingIds = [];
2747
+ const generateUniqueParaId = () => {
2748
+ let id;
2749
+ do {
2750
+ id = Math.floor(Math.random() * 0x7fffffff + 1)
2751
+ .toString(16)
2752
+ .toUpperCase()
2753
+ .padStart(8, '0');
2754
+ } while (existingParaIds.has(id));
2755
+ existingParaIds.add(id);
2756
+ return id;
2757
+ };
2587
2758
  const processParagraph = (para) => {
2588
2759
  for (const rev of para.getRevisions()) {
2589
2760
  if (!registeredSet.has(rev)) {
@@ -2603,6 +2774,12 @@ class Document {
2603
2774
  item.getImageElement().setDocPrId(docPrId++);
2604
2775
  }
2605
2776
  }
2777
+ if (para.formatting.paraId) {
2778
+ existingParaIds.add(para.formatting.paraId);
2779
+ }
2780
+ else {
2781
+ paragraphsNeedingIds.push(para);
2782
+ }
2606
2783
  };
2607
2784
  for (const element of this.bodyElements) {
2608
2785
  if (element instanceof Paragraph_1.Paragraph) {
@@ -2618,6 +2795,12 @@ class Document {
2618
2795
  }
2619
2796
  }
2620
2797
  }
2798
+ for (const para of paragraphsNeedingIds) {
2799
+ para.formatting.paraId = generateUniqueParaId();
2800
+ if (!para.formatting.textId) {
2801
+ para.formatting.textId = generateUniqueParaId();
2802
+ }
2803
+ }
2621
2804
  }
2622
2805
  getLastParagraph() {
2623
2806
  for (let i = this.bodyElements.length - 1; i >= 0; i--) {
@@ -2820,6 +3003,30 @@ class Document {
2820
3003
  createMultiLevelList() {
2821
3004
  return this.numberingManager.createMultiLevelList();
2822
3005
  }
3006
+ addBulletListFromArray(items, formatting) {
3007
+ if (items.length === 0)
3008
+ return [];
3009
+ const numId = this.createBulletList();
3010
+ return this.addListItems(numId, items, formatting);
3011
+ }
3012
+ addNumberedListFromArray(items, formatting) {
3013
+ if (items.length === 0)
3014
+ return [];
3015
+ const numId = this.createNumberedList();
3016
+ return this.addListItems(numId, items, formatting);
3017
+ }
3018
+ addListItems(numId, items, formatting) {
3019
+ const paragraphs = [];
3020
+ for (const item of items) {
3021
+ const text = typeof item === 'string' ? item : item.text;
3022
+ const level = typeof item === 'string' ? 0 : (item.level ?? 0);
3023
+ const para = this.createParagraph();
3024
+ para.addText(text, formatting);
3025
+ para.setNumbering(numId, level);
3026
+ paragraphs.push(para);
3027
+ }
3028
+ return paragraphs;
3029
+ }
2823
3030
  restartNumbering(numId, level, startValue) {
2824
3031
  return this.numberingManager.restartNumbering(numId, level, startValue);
2825
3032
  }
@@ -3041,6 +3248,14 @@ class Document {
3041
3248
  }
3042
3249
  return runs;
3043
3250
  }
3251
+ static stripThemeFontsIfExplicitFont(runConfig) {
3252
+ if (runConfig?.font) {
3253
+ delete runConfig.fontAsciiTheme;
3254
+ delete runConfig.fontHAnsiTheme;
3255
+ delete runConfig.fontEastAsiaTheme;
3256
+ delete runConfig.fontCsTheme;
3257
+ }
3258
+ }
3044
3259
  applyStyles(options) {
3045
3260
  const results = {
3046
3261
  heading1: false,
@@ -3109,6 +3324,11 @@ class Document {
3109
3324
  ...options?.listParagraph?.paragraph,
3110
3325
  },
3111
3326
  };
3327
+ Document.stripThemeFontsIfExplicitFont(h1Config.run);
3328
+ Document.stripThemeFontsIfExplicitFont(h2Config.run);
3329
+ Document.stripThemeFontsIfExplicitFont(h3Config.run);
3330
+ Document.stripThemeFontsIfExplicitFont(normalConfig.run);
3331
+ Document.stripThemeFontsIfExplicitFont(listParaConfig.run);
3112
3332
  const preserveBlankLines = options?.preserveBlankLinesAfterHeading2Tables ?? true;
3113
3333
  if (heading1 && h1Config.run && h1Config.paragraph) {
3114
3334
  if (h1Config.run)
@@ -3773,12 +3993,12 @@ class Document {
3773
3993
  }
3774
3994
  let updateCount = 0;
3775
3995
  const fillPattern = new RegExp(`(w:fill=["'])${normalizedOld}(["'])`, 'gi');
3776
- stylesXml = stylesXml.replace(fillPattern, (match, prefix, suffix) => {
3996
+ stylesXml = stylesXml.replace(fillPattern, (_match, prefix, suffix) => {
3777
3997
  updateCount++;
3778
3998
  return `${prefix}${normalizedNew}${suffix}`;
3779
3999
  });
3780
4000
  const colorPattern = new RegExp(`(<w:shd[^>]*w:color=["'])${normalizedOld}(["'])`, 'gi');
3781
- stylesXml = stylesXml.replace(colorPattern, (match, prefix, suffix) => {
4001
+ stylesXml = stylesXml.replace(colorPattern, (_match, prefix, suffix) => {
3782
4002
  updateCount++;
3783
4003
  return `${prefix}${normalizedNew}${suffix}`;
3784
4004
  });
@@ -3804,21 +4024,6 @@ class Document {
3804
4024
  }
3805
4025
  return totalUpdated;
3806
4026
  }
3807
- processConsecutiveBlanks(blanks, keepOne, toRemove) {
3808
- if (blanks.length === 0)
3809
- return;
3810
- if (keepOne && blanks.length > 1) {
3811
- for (let i = 1; i < blanks.length; i++) {
3812
- const blank = blanks[i];
3813
- if (blank) {
3814
- toRemove.push(blank);
3815
- }
3816
- }
3817
- }
3818
- else if (!keepOne) {
3819
- toRemove.push(...blanks);
3820
- }
3821
- }
3822
4027
  standardizeBulletSymbols(options) {
3823
4028
  const { bold = false, fontSize = 24, color = '000000', font = 'Arial', } = options || {};
3824
4029
  let listsUpdated = 0;
@@ -4108,7 +4313,6 @@ class Document {
4108
4313
  parseTOCFieldInstruction(instrText) {
4109
4314
  const levels = new Set();
4110
4315
  let hasOutlineSwitch = false;
4111
- let hasTableSwitch = false;
4112
4316
  const normalizedText = instrText.trim().replace(/&quot;/g, '"');
4113
4317
  const outlineMatch = /\\o\s+(?:"(\d+)-(\d+)"|'(\d+)-(\d+)'|(\d+)-(\d+))/.exec(normalizedText);
4114
4318
  if (outlineMatch) {
@@ -4132,7 +4336,6 @@ class Document {
4132
4336
  const tSwitchRegex = /\\t\s+"([^"]*)"/g;
4133
4337
  const tMatches = [...normalizedText.matchAll(tSwitchRegex)];
4134
4338
  for (const match of tMatches) {
4135
- hasTableSwitch = true;
4136
4339
  const content = (match[1] || '').trim();
4137
4340
  if (!content)
4138
4341
  continue;
@@ -4479,34 +4682,6 @@ class Document {
4479
4682
  }
4480
4683
  return headings;
4481
4684
  }
4482
- findHeadingsForTOC(levels) {
4483
- const headings = [];
4484
- const levelSet = new Set(levels);
4485
- for (const element of this.bodyElements) {
4486
- if (element instanceof Paragraph_1.Paragraph) {
4487
- const para = element;
4488
- const formatting = para.getFormatting();
4489
- if (formatting.style) {
4490
- const styleMatch = /Heading\s*(\d+)/i.exec(formatting.style);
4491
- if (styleMatch?.[1]) {
4492
- const headingLevel = parseInt(styleMatch[1], 10);
4493
- if (levelSet.has(headingLevel)) {
4494
- const text = para.getText().trim();
4495
- if (text) {
4496
- const bookmark = this.bookmarkManager.createHeadingBookmark(text);
4497
- headings.push({
4498
- level: headingLevel,
4499
- text: text,
4500
- bookmark: bookmark.getName(),
4501
- });
4502
- }
4503
- }
4504
- }
4505
- }
4506
- }
4507
- }
4508
- return headings;
4509
- }
4510
4685
  generateTOCXML(headings, originalInstrText) {
4511
4686
  const sdtId = Math.floor(Math.random() * 2000000000) - 1000000000;
4512
4687
  let tocXml = '<w:sdt>';
@@ -5263,6 +5438,9 @@ class Document {
5263
5438
  return true;
5264
5439
  }
5265
5440
  }
5441
+ if (item instanceof PreservedElement_1.PreservedElement && item.getRawXml().includes('w:anchor="_top"')) {
5442
+ return true;
5443
+ }
5266
5444
  }
5267
5445
  return false;
5268
5446
  }
@@ -5630,6 +5808,40 @@ class Document {
5630
5808
  this._settingsModified = true;
5631
5809
  this._modifiedBooleanSettings.add('defaultTabStop');
5632
5810
  }
5811
+ setDefaultFont(fontName, sizeInPoints) {
5812
+ let normalStyle = this.stylesManager.getStyle('Normal');
5813
+ if (!normalStyle) {
5814
+ normalStyle = new Style_1.Style({
5815
+ styleId: 'Normal',
5816
+ name: 'Normal',
5817
+ type: 'paragraph',
5818
+ isDefault: true,
5819
+ });
5820
+ this.stylesManager.addStyle(normalStyle);
5821
+ }
5822
+ const existing = normalStyle.getRunFormatting() ?? {};
5823
+ const updated = { ...existing, font: fontName };
5824
+ if (sizeInPoints !== undefined) {
5825
+ updated.size = sizeInPoints;
5826
+ }
5827
+ normalStyle.setRunFormatting(updated);
5828
+ return this;
5829
+ }
5830
+ setDefaultFontSize(sizeInPoints) {
5831
+ let normalStyle = this.stylesManager.getStyle('Normal');
5832
+ if (!normalStyle) {
5833
+ normalStyle = new Style_1.Style({
5834
+ styleId: 'Normal',
5835
+ name: 'Normal',
5836
+ type: 'paragraph',
5837
+ isDefault: true,
5838
+ });
5839
+ this.stylesManager.addStyle(normalStyle);
5840
+ }
5841
+ const existing = normalStyle.getRunFormatting() ?? {};
5842
+ normalStyle.setRunFormatting({ ...existing, size: sizeInPoints });
5843
+ return this;
5844
+ }
5633
5845
  getUpdateFields() {
5634
5846
  return this._updateFields ?? false;
5635
5847
  }
@@ -6069,6 +6281,10 @@ class Document {
6069
6281
  }
6070
6282
  return count;
6071
6283
  }
6284
+ clear() {
6285
+ this.bodyElements = [];
6286
+ return this;
6287
+ }
6072
6288
  dispose() {
6073
6289
  this.bodyElements = [];
6074
6290
  this.parser.clearParseErrors();
@@ -6751,6 +6967,33 @@ class Document {
6751
6967
  }
6752
6968
  return trackChanges ? { count, revisions } : { count };
6753
6969
  }
6970
+ fillTemplate(data, options) {
6971
+ const [open, close] = options?.delimiters ?? ['{{', '}}'];
6972
+ let totalCount = 0;
6973
+ const allParagraphs = this.getAllParagraphs();
6974
+ for (const [key, value] of Object.entries(data)) {
6975
+ const placeholder = `${open}${key}${close}`;
6976
+ for (const para of allParagraphs) {
6977
+ totalCount += para.replaceTextCrossRun(placeholder, value);
6978
+ }
6979
+ }
6980
+ return totalCount;
6981
+ }
6982
+ findAndHighlight(text, color = 'yellow', options) {
6983
+ return this.findAndFormat(text, { highlight: color }, options);
6984
+ }
6985
+ findAndFormat(text, formatting, options) {
6986
+ let totalMatches = 0;
6987
+ for (const para of this.getAllParagraphs()) {
6988
+ const matches = para.findTextCrossRun(text, options);
6989
+ for (let i = matches.length - 1; i >= 0; i--) {
6990
+ const match = matches[i];
6991
+ para.applyFormattingToRange(match.offset, match.offset + match.text.length, formatting);
6992
+ }
6993
+ totalMatches += matches.length;
6994
+ }
6995
+ return totalMatches;
6996
+ }
6754
6997
  getWordCount() {
6755
6998
  let totalWords = 0;
6756
6999
  const countedParagraphs = new Set();
@@ -6825,6 +7068,425 @@ class Document {
6825
7068
  }
6826
7069
  return totalChars;
6827
7070
  }
7071
+ getStatistics() {
7072
+ const allParagraphs = this.getAllParagraphs();
7073
+ const tables = this.getTables();
7074
+ let words = 0;
7075
+ let characters = 0;
7076
+ let charactersNoSpaces = 0;
7077
+ let headings = 0;
7078
+ let lists = 0;
7079
+ const counted = new Set();
7080
+ for (const para of allParagraphs) {
7081
+ if (counted.has(para))
7082
+ continue;
7083
+ counted.add(para);
7084
+ const text = para.getText();
7085
+ characters += text.length;
7086
+ charactersNoSpaces += text.replace(/\s/g, '').length;
7087
+ const trimmed = text.trim();
7088
+ if (trimmed) {
7089
+ words += trimmed.split(/\s+/).filter((w) => w.length > 0).length;
7090
+ }
7091
+ if (para.detectHeadingLevel() !== null)
7092
+ headings++;
7093
+ if (para.hasNumbering())
7094
+ lists++;
7095
+ }
7096
+ for (const table of tables) {
7097
+ for (const row of table.getRows()) {
7098
+ for (const cell of row.getCells()) {
7099
+ for (const para of cell.getParagraphs()) {
7100
+ if (counted.has(para))
7101
+ continue;
7102
+ counted.add(para);
7103
+ const text = para.getText();
7104
+ characters += text.length;
7105
+ charactersNoSpaces += text.replace(/\s/g, '').length;
7106
+ const trimmed = text.trim();
7107
+ if (trimmed) {
7108
+ words += trimmed.split(/\s+/).filter((w) => w.length > 0).length;
7109
+ }
7110
+ }
7111
+ }
7112
+ }
7113
+ }
7114
+ return {
7115
+ words,
7116
+ characters,
7117
+ charactersNoSpaces,
7118
+ paragraphs: allParagraphs.length,
7119
+ tables: tables.length,
7120
+ images: this.imageManager.getAllImages().length,
7121
+ headings,
7122
+ lists,
7123
+ hyperlinks: this.getHyperlinks().length,
7124
+ bookmarks: this.bookmarkManager.getAllBookmarks().length,
7125
+ footnotes: this.footnoteManager.getAllFootnotes().length,
7126
+ endnotes: this.endnoteManager.getAllEndnotes().length,
7127
+ comments: this.commentManager.getAllComments().length,
7128
+ sections: 1,
7129
+ };
7130
+ }
7131
+ forEachParagraph(callback) {
7132
+ let count = 0;
7133
+ let paraIndex = 0;
7134
+ for (const element of this.bodyElements) {
7135
+ if (element instanceof Paragraph_1.Paragraph) {
7136
+ const result = callback(element, paraIndex);
7137
+ count++;
7138
+ paraIndex++;
7139
+ if (result === false)
7140
+ break;
7141
+ }
7142
+ }
7143
+ return count;
7144
+ }
7145
+ forEachTable(callback) {
7146
+ let count = 0;
7147
+ let tableIndex = 0;
7148
+ for (const element of this.bodyElements) {
7149
+ if (element instanceof Table_1.Table) {
7150
+ const result = callback(element, tableIndex);
7151
+ count++;
7152
+ tableIndex++;
7153
+ if (result === false)
7154
+ break;
7155
+ }
7156
+ }
7157
+ return count;
7158
+ }
7159
+ toPlainText(separator = '\n') {
7160
+ const paragraphs = this.getAllParagraphs();
7161
+ return paragraphs.map((p) => p.getText()).join(separator);
7162
+ }
7163
+ toMarkdown() {
7164
+ const lines = [];
7165
+ for (const element of this.bodyElements) {
7166
+ if (element instanceof Paragraph_1.Paragraph) {
7167
+ const mdLine = this.paragraphToMarkdown(element);
7168
+ if (mdLine !== null) {
7169
+ lines.push(mdLine);
7170
+ lines.push('');
7171
+ }
7172
+ }
7173
+ else if (element instanceof Table_1.Table) {
7174
+ lines.push(...this.tableToMarkdown(element));
7175
+ lines.push('');
7176
+ }
7177
+ }
7178
+ while (lines.length > 0 && lines[lines.length - 1] === '') {
7179
+ lines.pop();
7180
+ }
7181
+ return lines.join('\n');
7182
+ }
7183
+ paragraphToMarkdown(para) {
7184
+ const text = this.paragraphContentToMarkdown(para);
7185
+ if (!text && !para.hasNumbering())
7186
+ return null;
7187
+ const headingLevel = para.detectHeadingLevel();
7188
+ if (headingLevel !== null && headingLevel >= 1 && headingLevel <= 6) {
7189
+ return '#'.repeat(headingLevel) + ' ' + text;
7190
+ }
7191
+ if (para.hasNumbering()) {
7192
+ const style = para.getStyle();
7193
+ const isBullet = style?.toLowerCase().includes('bullet') || style?.toLowerCase().includes('list bullet');
7194
+ return isBullet ? `- ${text}` : `1. ${text}`;
7195
+ }
7196
+ return text;
7197
+ }
7198
+ paragraphContentToMarkdown(para) {
7199
+ const parts = [];
7200
+ for (const item of para.getContent()) {
7201
+ if (item instanceof Run_1.Run) {
7202
+ const runText = item.getText();
7203
+ if (!runText)
7204
+ continue;
7205
+ const fmt = item.getFormatting();
7206
+ let md = runText;
7207
+ if (fmt.bold && fmt.italic) {
7208
+ md = `***${md}***`;
7209
+ }
7210
+ else if (fmt.bold) {
7211
+ md = `**${md}**`;
7212
+ }
7213
+ else if (fmt.italic) {
7214
+ md = `*${md}*`;
7215
+ }
7216
+ if (fmt.strike) {
7217
+ md = `~~${md}~~`;
7218
+ }
7219
+ if (fmt.font &&
7220
+ /^(courier|consolas|monaco|menlo|source code|fira code|jetbrains mono)/i.test(fmt.font)) {
7221
+ md = `\`${runText}\``;
7222
+ }
7223
+ parts.push(md);
7224
+ }
7225
+ else if (item instanceof Hyperlink_1.Hyperlink) {
7226
+ const url = item.getUrl() || '';
7227
+ const linkText = item.getText() || url;
7228
+ parts.push(`[${linkText}](${url})`);
7229
+ }
7230
+ }
7231
+ return parts.join('');
7232
+ }
7233
+ tableToMarkdown(table) {
7234
+ const data = table.toArray();
7235
+ if (data.length === 0)
7236
+ return [];
7237
+ const colCount = Math.max(...data.map((row) => row.length));
7238
+ if (colCount === 0)
7239
+ return [];
7240
+ const normalized = data.map((row) => {
7241
+ const padded = [...row];
7242
+ while (padded.length < colCount)
7243
+ padded.push('');
7244
+ return padded.map((cell) => cell.replace(/\|/g, '\\|').replace(/\n/g, ' ').trim());
7245
+ });
7246
+ const lines = [];
7247
+ lines.push('| ' + normalized[0].join(' | ') + ' |');
7248
+ lines.push('| ' + normalized[0].map(() => '---').join(' | ') + ' |');
7249
+ for (let i = 1; i < normalized.length; i++) {
7250
+ lines.push('| ' + normalized[i].join(' | ') + ' |');
7251
+ }
7252
+ return lines;
7253
+ }
7254
+ toHTML(options) {
7255
+ const parts = [];
7256
+ let inList = null;
7257
+ const closeList = () => {
7258
+ if (inList) {
7259
+ parts.push(`</${inList}>`);
7260
+ inList = null;
7261
+ }
7262
+ };
7263
+ for (const element of this.bodyElements) {
7264
+ if (element instanceof Paragraph_1.Paragraph) {
7265
+ const headingLevel = element.detectHeadingLevel();
7266
+ const style = element.getStyle();
7267
+ const isBullet = style?.toLowerCase().includes('bullet') || style === 'ListBullet';
7268
+ const isNumber = style?.toLowerCase().includes('listnumber') ||
7269
+ style?.toLowerCase().includes('list number') ||
7270
+ style === 'ListNumber';
7271
+ if (isBullet || isNumber) {
7272
+ const listType = isBullet ? 'ul' : 'ol';
7273
+ if (inList !== listType) {
7274
+ closeList();
7275
+ inList = listType;
7276
+ parts.push(`<${listType}>`);
7277
+ }
7278
+ parts.push(`<li>${this.paragraphContentToHTML(element)}</li>`);
7279
+ continue;
7280
+ }
7281
+ closeList();
7282
+ if (headingLevel !== null && headingLevel >= 1 && headingLevel <= 6) {
7283
+ parts.push(`<h${headingLevel}>${this.paragraphContentToHTML(element)}</h${headingLevel}>`);
7284
+ }
7285
+ else {
7286
+ const content = this.paragraphContentToHTML(element);
7287
+ if (content) {
7288
+ parts.push(`<p>${content}</p>`);
7289
+ }
7290
+ }
7291
+ }
7292
+ else if (element instanceof Table_1.Table) {
7293
+ closeList();
7294
+ parts.push(this.tableToHTML(element));
7295
+ }
7296
+ }
7297
+ closeList();
7298
+ const body = parts.join('\n');
7299
+ if (options?.wrapInDocument) {
7300
+ const title = options.title ? this.escapeHTML(options.title) : 'Document';
7301
+ return [
7302
+ '<!DOCTYPE html>',
7303
+ '<html>',
7304
+ '<head>',
7305
+ `<meta charset="utf-8">`,
7306
+ `<title>${title}</title>`,
7307
+ '</head>',
7308
+ '<body>',
7309
+ body,
7310
+ '</body>',
7311
+ '</html>',
7312
+ ].join('\n');
7313
+ }
7314
+ return body;
7315
+ }
7316
+ paragraphContentToHTML(para) {
7317
+ const parts = [];
7318
+ for (const item of para.getContent()) {
7319
+ if (item instanceof Run_1.Run) {
7320
+ const text = item.getText();
7321
+ if (!text)
7322
+ continue;
7323
+ const escaped = this.escapeHTML(text);
7324
+ const fmt = item.getFormatting();
7325
+ const isMono = fmt.font &&
7326
+ /^(courier|consolas|monaco|menlo|source code|fira code|jetbrains mono)/i.test(fmt.font);
7327
+ if (isMono) {
7328
+ parts.push(`<code>${escaped}</code>`);
7329
+ continue;
7330
+ }
7331
+ let html = escaped;
7332
+ if (fmt.bold)
7333
+ html = `<strong>${html}</strong>`;
7334
+ if (fmt.italic)
7335
+ html = `<em>${html}</em>`;
7336
+ if (fmt.strike)
7337
+ html = `<s>${html}</s>`;
7338
+ if (fmt.underline && fmt.underline !== 'none') {
7339
+ html = `<u>${html}</u>`;
7340
+ }
7341
+ parts.push(html);
7342
+ }
7343
+ else if (item instanceof Hyperlink_1.Hyperlink) {
7344
+ const url = this.escapeHTML(item.getUrl() || '');
7345
+ const linkText = this.escapeHTML(item.getText() || url);
7346
+ parts.push(`<a href="${url}">${linkText}</a>`);
7347
+ }
7348
+ }
7349
+ return parts.join('');
7350
+ }
7351
+ tableToHTML(table) {
7352
+ const rows = table.getRows();
7353
+ if (rows.length === 0)
7354
+ return '';
7355
+ const lines = ['<table>'];
7356
+ const headerCells = rows[0].getCells();
7357
+ lines.push('<thead>');
7358
+ lines.push('<tr>');
7359
+ for (const cell of headerCells) {
7360
+ lines.push(`<th>${this.escapeHTML(cell.getText())}</th>`);
7361
+ }
7362
+ lines.push('</tr>');
7363
+ lines.push('</thead>');
7364
+ if (rows.length > 1) {
7365
+ lines.push('<tbody>');
7366
+ for (let r = 1; r < rows.length; r++) {
7367
+ lines.push('<tr>');
7368
+ for (const cell of rows[r].getCells()) {
7369
+ lines.push(`<td>${this.escapeHTML(cell.getText())}</td>`);
7370
+ }
7371
+ lines.push('</tr>');
7372
+ }
7373
+ lines.push('</tbody>');
7374
+ }
7375
+ lines.push('</table>');
7376
+ return lines.join('\n');
7377
+ }
7378
+ escapeHTML(text) {
7379
+ return text
7380
+ .replace(/&/g, '&amp;')
7381
+ .replace(/</g, '&lt;')
7382
+ .replace(/>/g, '&gt;')
7383
+ .replace(/"/g, '&quot;');
7384
+ }
7385
+ toJSON() {
7386
+ const paragraphs = this.getAllParagraphs();
7387
+ const tables = this.getTables();
7388
+ const headings = this.getHeadingHierarchy();
7389
+ return {
7390
+ properties: this.getProperties(),
7391
+ stats: {
7392
+ paragraphs: paragraphs.length,
7393
+ tables: tables.length,
7394
+ images: this.imageManager.getImageCount(),
7395
+ headings: headings.length,
7396
+ sections: this.bodyElements.filter((el) => el instanceof Section_1.Section).length || 1,
7397
+ },
7398
+ headings: headings.map((h) => ({ level: h.level, text: h.text })),
7399
+ body: this.bodyElements.map((el) => {
7400
+ if (el instanceof Paragraph_1.Paragraph) {
7401
+ return {
7402
+ type: 'paragraph',
7403
+ text: el.getText(),
7404
+ style: el.getStyle(),
7405
+ };
7406
+ }
7407
+ if (el instanceof Table_1.Table) {
7408
+ return {
7409
+ type: 'table',
7410
+ text: `${el.getRows().length} rows x ${el.getRows()[0]?.getCells().length ?? 0} cols`,
7411
+ };
7412
+ }
7413
+ return { type: el.constructor.name };
7414
+ }),
7415
+ };
7416
+ }
7417
+ findImagesWithoutAltText() {
7418
+ const results = [];
7419
+ for (const para of this.getAllParagraphs()) {
7420
+ for (const item of para.getContent()) {
7421
+ if (item instanceof ImageRun_1.ImageRun) {
7422
+ const image = item.getImageElement();
7423
+ const altText = image.getAltText();
7424
+ if (!altText || altText === 'Image') {
7425
+ results.push(image);
7426
+ }
7427
+ }
7428
+ if (item instanceof Revision_1.Revision) {
7429
+ for (const revContent of item.getContent()) {
7430
+ if (revContent instanceof ImageRun_1.ImageRun) {
7431
+ const image = revContent.getImageElement();
7432
+ const altText = image.getAltText();
7433
+ if (!altText || altText === 'Image') {
7434
+ results.push(image);
7435
+ }
7436
+ }
7437
+ }
7438
+ }
7439
+ }
7440
+ }
7441
+ return results;
7442
+ }
7443
+ getHeadingHierarchy() {
7444
+ const results = [];
7445
+ for (const para of this.getAllParagraphs()) {
7446
+ const level = para.detectHeadingLevel();
7447
+ if (level !== null) {
7448
+ results.push({
7449
+ level,
7450
+ text: para.getText(),
7451
+ paragraph: para,
7452
+ });
7453
+ }
7454
+ }
7455
+ return results;
7456
+ }
7457
+ extractByHeading(maxLevel = 1) {
7458
+ const sections = [];
7459
+ let current = {
7460
+ heading: undefined,
7461
+ level: 0,
7462
+ content: [],
7463
+ };
7464
+ for (const element of this.bodyElements) {
7465
+ if (element instanceof Paragraph_1.Paragraph) {
7466
+ const headingLevel = element.detectHeadingLevel();
7467
+ if (headingLevel !== null && headingLevel <= maxLevel) {
7468
+ if (current.heading || current.content.length > 0) {
7469
+ sections.push(current);
7470
+ }
7471
+ current = { heading: element, level: headingLevel, content: [] };
7472
+ continue;
7473
+ }
7474
+ }
7475
+ current.content.push(element);
7476
+ }
7477
+ if (current.heading || current.content.length > 0) {
7478
+ sections.push(current);
7479
+ }
7480
+ return sections;
7481
+ }
7482
+ getElementsBetween(startElement, endElement) {
7483
+ const startIndex = this.bodyElements.indexOf(startElement);
7484
+ const endIndex = this.bodyElements.indexOf(endElement);
7485
+ if (startIndex === -1 || endIndex === -1 || startIndex >= endIndex) {
7486
+ return [];
7487
+ }
7488
+ return this.bodyElements.slice(startIndex + 1, endIndex);
7489
+ }
6828
7490
  removeParagraph(paragraphOrIndex) {
6829
7491
  let index;
6830
7492
  if (typeof paragraphOrIndex === 'number') {
@@ -7032,6 +7694,34 @@ class Document {
7032
7694
  }
7033
7695
  return false;
7034
7696
  }
7697
+ removeElement(element) {
7698
+ const index = this.bodyElements.indexOf(element);
7699
+ if (index === -1)
7700
+ return false;
7701
+ this.bodyElements.splice(index, 1);
7702
+ return true;
7703
+ }
7704
+ insertAfter(reference, element) {
7705
+ const index = this.bodyElements.indexOf(reference);
7706
+ if (index === -1)
7707
+ return false;
7708
+ this.bodyElements.splice(index + 1, 0, element);
7709
+ return true;
7710
+ }
7711
+ insertBefore(reference, element) {
7712
+ const index = this.bodyElements.indexOf(reference);
7713
+ if (index === -1)
7714
+ return false;
7715
+ this.bodyElements.splice(index, 0, element);
7716
+ return true;
7717
+ }
7718
+ replaceElement(oldElement, newElement) {
7719
+ const index = this.bodyElements.indexOf(oldElement);
7720
+ if (index === -1)
7721
+ return false;
7722
+ this.bodyElements[index] = newElement;
7723
+ return true;
7724
+ }
7035
7725
  insertBodyElementAt(index, element) {
7036
7726
  const clampedIndex = Math.max(0, Math.min(index, this.bodyElements.length));
7037
7727
  this.bodyElements.splice(clampedIndex, 0, element);