docxmlater 10.3.5 → 10.4.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 (185) hide show
  1. package/README.md +158 -7
  2. package/dist/core/Document.d.ts +102 -3
  3. package/dist/core/Document.d.ts.map +1 -1
  4. package/dist/core/Document.js +775 -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 +588 -102
  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 +1 -0
  42. package/dist/elements/Image.d.ts.map +1 -1
  43. package/dist/elements/Image.js +17 -2
  44. package/dist/elements/Image.js.map +1 -1
  45. package/dist/elements/Paragraph.d.ts +81 -1
  46. package/dist/elements/Paragraph.d.ts.map +1 -1
  47. package/dist/elements/Paragraph.js +515 -21
  48. package/dist/elements/Paragraph.js.map +1 -1
  49. package/dist/elements/Revision.d.ts +0 -1
  50. package/dist/elements/Revision.d.ts.map +1 -1
  51. package/dist/elements/Revision.js +0 -12
  52. package/dist/elements/Revision.js.map +1 -1
  53. package/dist/elements/RevisionManager.d.ts +0 -1
  54. package/dist/elements/RevisionManager.d.ts.map +1 -1
  55. package/dist/elements/RevisionManager.js +0 -2
  56. package/dist/elements/RevisionManager.js.map +1 -1
  57. package/dist/elements/Run.d.ts +16 -4
  58. package/dist/elements/Run.d.ts.map +1 -1
  59. package/dist/elements/Run.js +114 -22
  60. package/dist/elements/Run.js.map +1 -1
  61. package/dist/elements/Section.d.ts +7 -1
  62. package/dist/elements/Section.d.ts.map +1 -1
  63. package/dist/elements/Section.js +185 -4
  64. package/dist/elements/Section.js.map +1 -1
  65. package/dist/elements/Shape.js.map +1 -1
  66. package/dist/elements/Table.d.ts +30 -1
  67. package/dist/elements/Table.d.ts.map +1 -1
  68. package/dist/elements/Table.js +357 -40
  69. package/dist/elements/Table.js.map +1 -1
  70. package/dist/elements/TableCell.d.ts +3 -0
  71. package/dist/elements/TableCell.d.ts.map +1 -1
  72. package/dist/elements/TableCell.js +30 -3
  73. package/dist/elements/TableCell.js.map +1 -1
  74. package/dist/elements/TableGridChange.d.ts +0 -1
  75. package/dist/elements/TableGridChange.d.ts.map +1 -1
  76. package/dist/elements/TableGridChange.js +0 -10
  77. package/dist/elements/TableGridChange.js.map +1 -1
  78. package/dist/elements/TableRow.d.ts +4 -0
  79. package/dist/elements/TableRow.d.ts.map +1 -1
  80. package/dist/elements/TableRow.js +31 -3
  81. package/dist/elements/TableRow.js.map +1 -1
  82. package/dist/formatting/AbstractNumbering.d.ts +5 -0
  83. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  84. package/dist/formatting/AbstractNumbering.js +22 -0
  85. package/dist/formatting/AbstractNumbering.js.map +1 -1
  86. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  87. package/dist/formatting/NumberingLevel.js +3 -3
  88. package/dist/formatting/NumberingLevel.js.map +1 -1
  89. package/dist/formatting/Style.d.ts +1 -0
  90. package/dist/formatting/Style.d.ts.map +1 -1
  91. package/dist/formatting/Style.js +25 -59
  92. package/dist/formatting/Style.js.map +1 -1
  93. package/dist/formatting/StylesManager.d.ts +1 -0
  94. package/dist/formatting/StylesManager.d.ts.map +1 -1
  95. package/dist/formatting/StylesManager.js +12 -0
  96. package/dist/formatting/StylesManager.js.map +1 -1
  97. package/dist/helpers/CleanupHelper.js.map +1 -1
  98. package/dist/images/ImageOptimizer.d.ts.map +1 -1
  99. package/dist/images/ImageOptimizer.js +0 -1
  100. package/dist/images/ImageOptimizer.js.map +1 -1
  101. package/dist/index.d.ts +1 -1
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/managers/DrawingManager.d.ts.map +1 -1
  105. package/dist/managers/DrawingManager.js +4 -2
  106. package/dist/managers/DrawingManager.js.map +1 -1
  107. package/dist/types/formatting.d.ts +2 -2
  108. package/dist/types/formatting.d.ts.map +1 -1
  109. package/dist/types/formatting.js.map +1 -1
  110. package/dist/utils/ChangelogGenerator.d.ts +2 -2
  111. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  112. package/dist/utils/ChangelogGenerator.js +4 -5
  113. package/dist/utils/ChangelogGenerator.js.map +1 -1
  114. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  115. package/dist/utils/InMemoryRevisionAcceptor.js +0 -1
  116. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  117. package/dist/utils/RevisionAwareProcessor.d.ts +2 -2
  118. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  119. package/dist/utils/RevisionAwareProcessor.js +2 -2
  120. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  121. package/dist/utils/SelectiveRevisionAcceptor.d.ts +0 -2
  122. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  123. package/dist/utils/SelectiveRevisionAcceptor.js +0 -26
  124. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  125. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  126. package/dist/utils/ShadingResolver.js.map +1 -1
  127. package/dist/utils/acceptRevisions.js +1 -1
  128. package/dist/utils/acceptRevisions.js.map +1 -1
  129. package/dist/utils/stripTrackedChanges.js +1 -1
  130. package/dist/utils/stripTrackedChanges.js.map +1 -1
  131. package/dist/utils/units.d.ts.map +1 -1
  132. package/dist/utils/units.js +1 -1
  133. package/dist/utils/units.js.map +1 -1
  134. package/dist/validation/RevisionAutoFixer.d.ts +2 -1
  135. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  136. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  137. package/package.json +10 -1
  138. package/src/constants/CLAUDE.md +28 -0
  139. package/src/core/CLAUDE.md +4 -0
  140. package/src/core/Document.ts +1888 -137
  141. package/src/core/DocumentContent.ts +0 -11
  142. package/src/core/DocumentGenerator.ts +11 -12
  143. package/src/core/DocumentParser.ts +620 -139
  144. package/src/core/RelationshipManager.ts +6 -3
  145. package/src/elements/Bookmark.ts +39 -4
  146. package/src/elements/BookmarkManager.ts +4 -3
  147. package/src/elements/CLAUDE.md +18 -2
  148. package/src/elements/CommonTypes.ts +35 -8
  149. package/src/elements/Field.ts +1 -1
  150. package/src/elements/Footer.ts +23 -0
  151. package/src/elements/Header.ts +25 -0
  152. package/src/elements/Image.ts +28 -5
  153. package/src/elements/Paragraph.ts +1069 -41
  154. package/src/elements/Revision.ts +0 -19
  155. package/src/elements/RevisionManager.ts +1 -3
  156. package/src/elements/Run.ts +265 -35
  157. package/src/elements/Section.ts +214 -8
  158. package/src/elements/Shape.ts +1 -1
  159. package/src/elements/Table.ts +850 -61
  160. package/src/elements/TableCell.ts +84 -10
  161. package/src/elements/TableGridChange.ts +2 -16
  162. package/src/elements/TableRow.ts +94 -9
  163. package/src/formatting/AbstractNumbering.ts +42 -1
  164. package/src/formatting/CLAUDE.md +4 -0
  165. package/src/formatting/NumberingLevel.ts +11 -7
  166. package/src/formatting/Style.ts +39 -71
  167. package/src/formatting/StylesManager.ts +36 -0
  168. package/src/helpers/CleanupHelper.ts +1 -1
  169. package/src/images/ImageOptimizer.ts +0 -3
  170. package/src/index.ts +1 -1
  171. package/src/managers/DrawingManager.ts +5 -3
  172. package/src/tracking/CLAUDE.md +30 -0
  173. package/src/types/CLAUDE.md +39 -0
  174. package/src/types/formatting.ts +2 -2
  175. package/src/utils/CLAUDE.md +15 -0
  176. package/src/utils/ChangelogGenerator.ts +4 -5
  177. package/src/utils/InMemoryRevisionAcceptor.ts +0 -9
  178. package/src/utils/RevisionAwareProcessor.ts +2 -3
  179. package/src/utils/SelectiveRevisionAcceptor.ts +0 -39
  180. package/src/utils/ShadingResolver.ts +0 -1
  181. package/src/utils/acceptRevisions.ts +1 -1
  182. package/src/utils/stripTrackedChanges.ts +1 -1
  183. package/src/utils/units.ts +2 -1
  184. package/src/validation/CLAUDE.md +40 -0
  185. 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
  }
@@ -3773,12 +3980,12 @@ class Document {
3773
3980
  }
3774
3981
  let updateCount = 0;
3775
3982
  const fillPattern = new RegExp(`(w:fill=["'])${normalizedOld}(["'])`, 'gi');
3776
- stylesXml = stylesXml.replace(fillPattern, (match, prefix, suffix) => {
3983
+ stylesXml = stylesXml.replace(fillPattern, (_match, prefix, suffix) => {
3777
3984
  updateCount++;
3778
3985
  return `${prefix}${normalizedNew}${suffix}`;
3779
3986
  });
3780
3987
  const colorPattern = new RegExp(`(<w:shd[^>]*w:color=["'])${normalizedOld}(["'])`, 'gi');
3781
- stylesXml = stylesXml.replace(colorPattern, (match, prefix, suffix) => {
3988
+ stylesXml = stylesXml.replace(colorPattern, (_match, prefix, suffix) => {
3782
3989
  updateCount++;
3783
3990
  return `${prefix}${normalizedNew}${suffix}`;
3784
3991
  });
@@ -3804,21 +4011,6 @@ class Document {
3804
4011
  }
3805
4012
  return totalUpdated;
3806
4013
  }
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
4014
  standardizeBulletSymbols(options) {
3823
4015
  const { bold = false, fontSize = 24, color = '000000', font = 'Arial', } = options || {};
3824
4016
  let listsUpdated = 0;
@@ -4108,7 +4300,6 @@ class Document {
4108
4300
  parseTOCFieldInstruction(instrText) {
4109
4301
  const levels = new Set();
4110
4302
  let hasOutlineSwitch = false;
4111
- let hasTableSwitch = false;
4112
4303
  const normalizedText = instrText.trim().replace(/&quot;/g, '"');
4113
4304
  const outlineMatch = /\\o\s+(?:"(\d+)-(\d+)"|'(\d+)-(\d+)'|(\d+)-(\d+))/.exec(normalizedText);
4114
4305
  if (outlineMatch) {
@@ -4132,7 +4323,6 @@ class Document {
4132
4323
  const tSwitchRegex = /\\t\s+"([^"]*)"/g;
4133
4324
  const tMatches = [...normalizedText.matchAll(tSwitchRegex)];
4134
4325
  for (const match of tMatches) {
4135
- hasTableSwitch = true;
4136
4326
  const content = (match[1] || '').trim();
4137
4327
  if (!content)
4138
4328
  continue;
@@ -4479,34 +4669,6 @@ class Document {
4479
4669
  }
4480
4670
  return headings;
4481
4671
  }
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
4672
  generateTOCXML(headings, originalInstrText) {
4511
4673
  const sdtId = Math.floor(Math.random() * 2000000000) - 1000000000;
4512
4674
  let tocXml = '<w:sdt>';
@@ -5218,6 +5380,57 @@ class Document {
5218
5380
  },
5219
5381
  };
5220
5382
  }
5383
+ ensureTopLinksAbove1x1Tables(options) {
5384
+ const linkText = options?.text || 'Top of the Document';
5385
+ const formatting = options?.formatting;
5386
+ this.addTopBookmark();
5387
+ let insertedCount = 0;
5388
+ let oneByOneCount = 0;
5389
+ let i = 0;
5390
+ while (i < this.bodyElements.length) {
5391
+ const element = this.bodyElements[i];
5392
+ if (element instanceof Table_1.Table &&
5393
+ element.getRowCount() === 1 &&
5394
+ element.getColumnCount() === 1) {
5395
+ oneByOneCount++;
5396
+ if (oneByOneCount > 1) {
5397
+ const prevElement = i > 0 ? this.bodyElements[i - 1] : undefined;
5398
+ const hasLink = prevElement instanceof Paragraph_1.Paragraph && this._paragraphHasTopLink(prevElement);
5399
+ if (!hasLink) {
5400
+ const para = new Paragraph_1.Paragraph();
5401
+ const link = Hyperlink_1.Hyperlink.createInternal('_top', linkText, {
5402
+ color: '0000FF',
5403
+ underline: 'single',
5404
+ ...formatting,
5405
+ });
5406
+ para.addHyperlink(link);
5407
+ this.bodyElements.splice(i, 0, para);
5408
+ insertedCount++;
5409
+ i++;
5410
+ }
5411
+ }
5412
+ }
5413
+ i++;
5414
+ }
5415
+ return insertedCount;
5416
+ }
5417
+ _paragraphHasTopLink(paragraph) {
5418
+ for (const item of paragraph.getContent()) {
5419
+ if (item instanceof Hyperlink_1.Hyperlink && item.getAnchor() === '_top') {
5420
+ return true;
5421
+ }
5422
+ if (item instanceof Field_1.ComplexField && item.isHyperlinkField()) {
5423
+ const parsed = item.getParsedHyperlink();
5424
+ if (parsed?.anchor === '_top') {
5425
+ return true;
5426
+ }
5427
+ }
5428
+ if (item instanceof PreservedElement_1.PreservedElement && item.getRawXml().includes('w:anchor="_top"')) {
5429
+ return true;
5430
+ }
5431
+ }
5432
+ return false;
5433
+ }
5221
5434
  getRevisionManager() {
5222
5435
  return this.revisionManager;
5223
5436
  }
@@ -5582,6 +5795,40 @@ class Document {
5582
5795
  this._settingsModified = true;
5583
5796
  this._modifiedBooleanSettings.add('defaultTabStop');
5584
5797
  }
5798
+ setDefaultFont(fontName, sizeInPoints) {
5799
+ let normalStyle = this.stylesManager.getStyle('Normal');
5800
+ if (!normalStyle) {
5801
+ normalStyle = new Style_1.Style({
5802
+ styleId: 'Normal',
5803
+ name: 'Normal',
5804
+ type: 'paragraph',
5805
+ isDefault: true,
5806
+ });
5807
+ this.stylesManager.addStyle(normalStyle);
5808
+ }
5809
+ const existing = normalStyle.getRunFormatting() ?? {};
5810
+ const updated = { ...existing, font: fontName };
5811
+ if (sizeInPoints !== undefined) {
5812
+ updated.size = sizeInPoints;
5813
+ }
5814
+ normalStyle.setRunFormatting(updated);
5815
+ return this;
5816
+ }
5817
+ setDefaultFontSize(sizeInPoints) {
5818
+ let normalStyle = this.stylesManager.getStyle('Normal');
5819
+ if (!normalStyle) {
5820
+ normalStyle = new Style_1.Style({
5821
+ styleId: 'Normal',
5822
+ name: 'Normal',
5823
+ type: 'paragraph',
5824
+ isDefault: true,
5825
+ });
5826
+ this.stylesManager.addStyle(normalStyle);
5827
+ }
5828
+ const existing = normalStyle.getRunFormatting() ?? {};
5829
+ normalStyle.setRunFormatting({ ...existing, size: sizeInPoints });
5830
+ return this;
5831
+ }
5585
5832
  getUpdateFields() {
5586
5833
  return this._updateFields ?? false;
5587
5834
  }
@@ -6021,6 +6268,10 @@ class Document {
6021
6268
  }
6022
6269
  return count;
6023
6270
  }
6271
+ clear() {
6272
+ this.bodyElements = [];
6273
+ return this;
6274
+ }
6024
6275
  dispose() {
6025
6276
  this.bodyElements = [];
6026
6277
  this.parser.clearParseErrors();
@@ -6703,6 +6954,33 @@ class Document {
6703
6954
  }
6704
6955
  return trackChanges ? { count, revisions } : { count };
6705
6956
  }
6957
+ fillTemplate(data, options) {
6958
+ const [open, close] = options?.delimiters ?? ['{{', '}}'];
6959
+ let totalCount = 0;
6960
+ const allParagraphs = this.getAllParagraphs();
6961
+ for (const [key, value] of Object.entries(data)) {
6962
+ const placeholder = `${open}${key}${close}`;
6963
+ for (const para of allParagraphs) {
6964
+ totalCount += para.replaceTextCrossRun(placeholder, value);
6965
+ }
6966
+ }
6967
+ return totalCount;
6968
+ }
6969
+ findAndHighlight(text, color = 'yellow', options) {
6970
+ return this.findAndFormat(text, { highlight: color }, options);
6971
+ }
6972
+ findAndFormat(text, formatting, options) {
6973
+ let totalMatches = 0;
6974
+ for (const para of this.getAllParagraphs()) {
6975
+ const matches = para.findTextCrossRun(text, options);
6976
+ for (let i = matches.length - 1; i >= 0; i--) {
6977
+ const match = matches[i];
6978
+ para.applyFormattingToRange(match.offset, match.offset + match.text.length, formatting);
6979
+ }
6980
+ totalMatches += matches.length;
6981
+ }
6982
+ return totalMatches;
6983
+ }
6706
6984
  getWordCount() {
6707
6985
  let totalWords = 0;
6708
6986
  const countedParagraphs = new Set();
@@ -6777,6 +7055,425 @@ class Document {
6777
7055
  }
6778
7056
  return totalChars;
6779
7057
  }
7058
+ getStatistics() {
7059
+ const allParagraphs = this.getAllParagraphs();
7060
+ const tables = this.getTables();
7061
+ let words = 0;
7062
+ let characters = 0;
7063
+ let charactersNoSpaces = 0;
7064
+ let headings = 0;
7065
+ let lists = 0;
7066
+ const counted = new Set();
7067
+ for (const para of allParagraphs) {
7068
+ if (counted.has(para))
7069
+ continue;
7070
+ counted.add(para);
7071
+ const text = para.getText();
7072
+ characters += text.length;
7073
+ charactersNoSpaces += text.replace(/\s/g, '').length;
7074
+ const trimmed = text.trim();
7075
+ if (trimmed) {
7076
+ words += trimmed.split(/\s+/).filter((w) => w.length > 0).length;
7077
+ }
7078
+ if (para.detectHeadingLevel() !== null)
7079
+ headings++;
7080
+ if (para.hasNumbering())
7081
+ lists++;
7082
+ }
7083
+ for (const table of tables) {
7084
+ for (const row of table.getRows()) {
7085
+ for (const cell of row.getCells()) {
7086
+ for (const para of cell.getParagraphs()) {
7087
+ if (counted.has(para))
7088
+ continue;
7089
+ counted.add(para);
7090
+ const text = para.getText();
7091
+ characters += text.length;
7092
+ charactersNoSpaces += text.replace(/\s/g, '').length;
7093
+ const trimmed = text.trim();
7094
+ if (trimmed) {
7095
+ words += trimmed.split(/\s+/).filter((w) => w.length > 0).length;
7096
+ }
7097
+ }
7098
+ }
7099
+ }
7100
+ }
7101
+ return {
7102
+ words,
7103
+ characters,
7104
+ charactersNoSpaces,
7105
+ paragraphs: allParagraphs.length,
7106
+ tables: tables.length,
7107
+ images: this.imageManager.getAllImages().length,
7108
+ headings,
7109
+ lists,
7110
+ hyperlinks: this.getHyperlinks().length,
7111
+ bookmarks: this.bookmarkManager.getAllBookmarks().length,
7112
+ footnotes: this.footnoteManager.getAllFootnotes().length,
7113
+ endnotes: this.endnoteManager.getAllEndnotes().length,
7114
+ comments: this.commentManager.getAllComments().length,
7115
+ sections: 1,
7116
+ };
7117
+ }
7118
+ forEachParagraph(callback) {
7119
+ let count = 0;
7120
+ let paraIndex = 0;
7121
+ for (const element of this.bodyElements) {
7122
+ if (element instanceof Paragraph_1.Paragraph) {
7123
+ const result = callback(element, paraIndex);
7124
+ count++;
7125
+ paraIndex++;
7126
+ if (result === false)
7127
+ break;
7128
+ }
7129
+ }
7130
+ return count;
7131
+ }
7132
+ forEachTable(callback) {
7133
+ let count = 0;
7134
+ let tableIndex = 0;
7135
+ for (const element of this.bodyElements) {
7136
+ if (element instanceof Table_1.Table) {
7137
+ const result = callback(element, tableIndex);
7138
+ count++;
7139
+ tableIndex++;
7140
+ if (result === false)
7141
+ break;
7142
+ }
7143
+ }
7144
+ return count;
7145
+ }
7146
+ toPlainText(separator = '\n') {
7147
+ const paragraphs = this.getAllParagraphs();
7148
+ return paragraphs.map((p) => p.getText()).join(separator);
7149
+ }
7150
+ toMarkdown() {
7151
+ const lines = [];
7152
+ for (const element of this.bodyElements) {
7153
+ if (element instanceof Paragraph_1.Paragraph) {
7154
+ const mdLine = this.paragraphToMarkdown(element);
7155
+ if (mdLine !== null) {
7156
+ lines.push(mdLine);
7157
+ lines.push('');
7158
+ }
7159
+ }
7160
+ else if (element instanceof Table_1.Table) {
7161
+ lines.push(...this.tableToMarkdown(element));
7162
+ lines.push('');
7163
+ }
7164
+ }
7165
+ while (lines.length > 0 && lines[lines.length - 1] === '') {
7166
+ lines.pop();
7167
+ }
7168
+ return lines.join('\n');
7169
+ }
7170
+ paragraphToMarkdown(para) {
7171
+ const text = this.paragraphContentToMarkdown(para);
7172
+ if (!text && !para.hasNumbering())
7173
+ return null;
7174
+ const headingLevel = para.detectHeadingLevel();
7175
+ if (headingLevel !== null && headingLevel >= 1 && headingLevel <= 6) {
7176
+ return '#'.repeat(headingLevel) + ' ' + text;
7177
+ }
7178
+ if (para.hasNumbering()) {
7179
+ const style = para.getStyle();
7180
+ const isBullet = style?.toLowerCase().includes('bullet') || style?.toLowerCase().includes('list bullet');
7181
+ return isBullet ? `- ${text}` : `1. ${text}`;
7182
+ }
7183
+ return text;
7184
+ }
7185
+ paragraphContentToMarkdown(para) {
7186
+ const parts = [];
7187
+ for (const item of para.getContent()) {
7188
+ if (item instanceof Run_1.Run) {
7189
+ const runText = item.getText();
7190
+ if (!runText)
7191
+ continue;
7192
+ const fmt = item.getFormatting();
7193
+ let md = runText;
7194
+ if (fmt.bold && fmt.italic) {
7195
+ md = `***${md}***`;
7196
+ }
7197
+ else if (fmt.bold) {
7198
+ md = `**${md}**`;
7199
+ }
7200
+ else if (fmt.italic) {
7201
+ md = `*${md}*`;
7202
+ }
7203
+ if (fmt.strike) {
7204
+ md = `~~${md}~~`;
7205
+ }
7206
+ if (fmt.font &&
7207
+ /^(courier|consolas|monaco|menlo|source code|fira code|jetbrains mono)/i.test(fmt.font)) {
7208
+ md = `\`${runText}\``;
7209
+ }
7210
+ parts.push(md);
7211
+ }
7212
+ else if (item instanceof Hyperlink_1.Hyperlink) {
7213
+ const url = item.getUrl() || '';
7214
+ const linkText = item.getText() || url;
7215
+ parts.push(`[${linkText}](${url})`);
7216
+ }
7217
+ }
7218
+ return parts.join('');
7219
+ }
7220
+ tableToMarkdown(table) {
7221
+ const data = table.toArray();
7222
+ if (data.length === 0)
7223
+ return [];
7224
+ const colCount = Math.max(...data.map((row) => row.length));
7225
+ if (colCount === 0)
7226
+ return [];
7227
+ const normalized = data.map((row) => {
7228
+ const padded = [...row];
7229
+ while (padded.length < colCount)
7230
+ padded.push('');
7231
+ return padded.map((cell) => cell.replace(/\|/g, '\\|').replace(/\n/g, ' ').trim());
7232
+ });
7233
+ const lines = [];
7234
+ lines.push('| ' + normalized[0].join(' | ') + ' |');
7235
+ lines.push('| ' + normalized[0].map(() => '---').join(' | ') + ' |');
7236
+ for (let i = 1; i < normalized.length; i++) {
7237
+ lines.push('| ' + normalized[i].join(' | ') + ' |');
7238
+ }
7239
+ return lines;
7240
+ }
7241
+ toHTML(options) {
7242
+ const parts = [];
7243
+ let inList = null;
7244
+ const closeList = () => {
7245
+ if (inList) {
7246
+ parts.push(`</${inList}>`);
7247
+ inList = null;
7248
+ }
7249
+ };
7250
+ for (const element of this.bodyElements) {
7251
+ if (element instanceof Paragraph_1.Paragraph) {
7252
+ const headingLevel = element.detectHeadingLevel();
7253
+ const style = element.getStyle();
7254
+ const isBullet = style?.toLowerCase().includes('bullet') || style === 'ListBullet';
7255
+ const isNumber = style?.toLowerCase().includes('listnumber') ||
7256
+ style?.toLowerCase().includes('list number') ||
7257
+ style === 'ListNumber';
7258
+ if (isBullet || isNumber) {
7259
+ const listType = isBullet ? 'ul' : 'ol';
7260
+ if (inList !== listType) {
7261
+ closeList();
7262
+ inList = listType;
7263
+ parts.push(`<${listType}>`);
7264
+ }
7265
+ parts.push(`<li>${this.paragraphContentToHTML(element)}</li>`);
7266
+ continue;
7267
+ }
7268
+ closeList();
7269
+ if (headingLevel !== null && headingLevel >= 1 && headingLevel <= 6) {
7270
+ parts.push(`<h${headingLevel}>${this.paragraphContentToHTML(element)}</h${headingLevel}>`);
7271
+ }
7272
+ else {
7273
+ const content = this.paragraphContentToHTML(element);
7274
+ if (content) {
7275
+ parts.push(`<p>${content}</p>`);
7276
+ }
7277
+ }
7278
+ }
7279
+ else if (element instanceof Table_1.Table) {
7280
+ closeList();
7281
+ parts.push(this.tableToHTML(element));
7282
+ }
7283
+ }
7284
+ closeList();
7285
+ const body = parts.join('\n');
7286
+ if (options?.wrapInDocument) {
7287
+ const title = options.title ? this.escapeHTML(options.title) : 'Document';
7288
+ return [
7289
+ '<!DOCTYPE html>',
7290
+ '<html>',
7291
+ '<head>',
7292
+ `<meta charset="utf-8">`,
7293
+ `<title>${title}</title>`,
7294
+ '</head>',
7295
+ '<body>',
7296
+ body,
7297
+ '</body>',
7298
+ '</html>',
7299
+ ].join('\n');
7300
+ }
7301
+ return body;
7302
+ }
7303
+ paragraphContentToHTML(para) {
7304
+ const parts = [];
7305
+ for (const item of para.getContent()) {
7306
+ if (item instanceof Run_1.Run) {
7307
+ const text = item.getText();
7308
+ if (!text)
7309
+ continue;
7310
+ const escaped = this.escapeHTML(text);
7311
+ const fmt = item.getFormatting();
7312
+ const isMono = fmt.font &&
7313
+ /^(courier|consolas|monaco|menlo|source code|fira code|jetbrains mono)/i.test(fmt.font);
7314
+ if (isMono) {
7315
+ parts.push(`<code>${escaped}</code>`);
7316
+ continue;
7317
+ }
7318
+ let html = escaped;
7319
+ if (fmt.bold)
7320
+ html = `<strong>${html}</strong>`;
7321
+ if (fmt.italic)
7322
+ html = `<em>${html}</em>`;
7323
+ if (fmt.strike)
7324
+ html = `<s>${html}</s>`;
7325
+ if (fmt.underline && fmt.underline !== 'none') {
7326
+ html = `<u>${html}</u>`;
7327
+ }
7328
+ parts.push(html);
7329
+ }
7330
+ else if (item instanceof Hyperlink_1.Hyperlink) {
7331
+ const url = this.escapeHTML(item.getUrl() || '');
7332
+ const linkText = this.escapeHTML(item.getText() || url);
7333
+ parts.push(`<a href="${url}">${linkText}</a>`);
7334
+ }
7335
+ }
7336
+ return parts.join('');
7337
+ }
7338
+ tableToHTML(table) {
7339
+ const rows = table.getRows();
7340
+ if (rows.length === 0)
7341
+ return '';
7342
+ const lines = ['<table>'];
7343
+ const headerCells = rows[0].getCells();
7344
+ lines.push('<thead>');
7345
+ lines.push('<tr>');
7346
+ for (const cell of headerCells) {
7347
+ lines.push(`<th>${this.escapeHTML(cell.getText())}</th>`);
7348
+ }
7349
+ lines.push('</tr>');
7350
+ lines.push('</thead>');
7351
+ if (rows.length > 1) {
7352
+ lines.push('<tbody>');
7353
+ for (let r = 1; r < rows.length; r++) {
7354
+ lines.push('<tr>');
7355
+ for (const cell of rows[r].getCells()) {
7356
+ lines.push(`<td>${this.escapeHTML(cell.getText())}</td>`);
7357
+ }
7358
+ lines.push('</tr>');
7359
+ }
7360
+ lines.push('</tbody>');
7361
+ }
7362
+ lines.push('</table>');
7363
+ return lines.join('\n');
7364
+ }
7365
+ escapeHTML(text) {
7366
+ return text
7367
+ .replace(/&/g, '&amp;')
7368
+ .replace(/</g, '&lt;')
7369
+ .replace(/>/g, '&gt;')
7370
+ .replace(/"/g, '&quot;');
7371
+ }
7372
+ toJSON() {
7373
+ const paragraphs = this.getAllParagraphs();
7374
+ const tables = this.getTables();
7375
+ const headings = this.getHeadingHierarchy();
7376
+ return {
7377
+ properties: this.getProperties(),
7378
+ stats: {
7379
+ paragraphs: paragraphs.length,
7380
+ tables: tables.length,
7381
+ images: this.imageManager.getImageCount(),
7382
+ headings: headings.length,
7383
+ sections: this.bodyElements.filter((el) => el instanceof Section_1.Section).length || 1,
7384
+ },
7385
+ headings: headings.map((h) => ({ level: h.level, text: h.text })),
7386
+ body: this.bodyElements.map((el) => {
7387
+ if (el instanceof Paragraph_1.Paragraph) {
7388
+ return {
7389
+ type: 'paragraph',
7390
+ text: el.getText(),
7391
+ style: el.getStyle(),
7392
+ };
7393
+ }
7394
+ if (el instanceof Table_1.Table) {
7395
+ return {
7396
+ type: 'table',
7397
+ text: `${el.getRows().length} rows x ${el.getRows()[0]?.getCells().length ?? 0} cols`,
7398
+ };
7399
+ }
7400
+ return { type: el.constructor.name };
7401
+ }),
7402
+ };
7403
+ }
7404
+ findImagesWithoutAltText() {
7405
+ const results = [];
7406
+ for (const para of this.getAllParagraphs()) {
7407
+ for (const item of para.getContent()) {
7408
+ if (item instanceof ImageRun_1.ImageRun) {
7409
+ const image = item.getImageElement();
7410
+ const altText = image.getAltText();
7411
+ if (!altText || altText === 'Image') {
7412
+ results.push(image);
7413
+ }
7414
+ }
7415
+ if (item instanceof Revision_1.Revision) {
7416
+ for (const revContent of item.getContent()) {
7417
+ if (revContent instanceof ImageRun_1.ImageRun) {
7418
+ const image = revContent.getImageElement();
7419
+ const altText = image.getAltText();
7420
+ if (!altText || altText === 'Image') {
7421
+ results.push(image);
7422
+ }
7423
+ }
7424
+ }
7425
+ }
7426
+ }
7427
+ }
7428
+ return results;
7429
+ }
7430
+ getHeadingHierarchy() {
7431
+ const results = [];
7432
+ for (const para of this.getAllParagraphs()) {
7433
+ const level = para.detectHeadingLevel();
7434
+ if (level !== null) {
7435
+ results.push({
7436
+ level,
7437
+ text: para.getText(),
7438
+ paragraph: para,
7439
+ });
7440
+ }
7441
+ }
7442
+ return results;
7443
+ }
7444
+ extractByHeading(maxLevel = 1) {
7445
+ const sections = [];
7446
+ let current = {
7447
+ heading: undefined,
7448
+ level: 0,
7449
+ content: [],
7450
+ };
7451
+ for (const element of this.bodyElements) {
7452
+ if (element instanceof Paragraph_1.Paragraph) {
7453
+ const headingLevel = element.detectHeadingLevel();
7454
+ if (headingLevel !== null && headingLevel <= maxLevel) {
7455
+ if (current.heading || current.content.length > 0) {
7456
+ sections.push(current);
7457
+ }
7458
+ current = { heading: element, level: headingLevel, content: [] };
7459
+ continue;
7460
+ }
7461
+ }
7462
+ current.content.push(element);
7463
+ }
7464
+ if (current.heading || current.content.length > 0) {
7465
+ sections.push(current);
7466
+ }
7467
+ return sections;
7468
+ }
7469
+ getElementsBetween(startElement, endElement) {
7470
+ const startIndex = this.bodyElements.indexOf(startElement);
7471
+ const endIndex = this.bodyElements.indexOf(endElement);
7472
+ if (startIndex === -1 || endIndex === -1 || startIndex >= endIndex) {
7473
+ return [];
7474
+ }
7475
+ return this.bodyElements.slice(startIndex + 1, endIndex);
7476
+ }
6780
7477
  removeParagraph(paragraphOrIndex) {
6781
7478
  let index;
6782
7479
  if (typeof paragraphOrIndex === 'number') {
@@ -6984,6 +7681,34 @@ class Document {
6984
7681
  }
6985
7682
  return false;
6986
7683
  }
7684
+ removeElement(element) {
7685
+ const index = this.bodyElements.indexOf(element);
7686
+ if (index === -1)
7687
+ return false;
7688
+ this.bodyElements.splice(index, 1);
7689
+ return true;
7690
+ }
7691
+ insertAfter(reference, element) {
7692
+ const index = this.bodyElements.indexOf(reference);
7693
+ if (index === -1)
7694
+ return false;
7695
+ this.bodyElements.splice(index + 1, 0, element);
7696
+ return true;
7697
+ }
7698
+ insertBefore(reference, element) {
7699
+ const index = this.bodyElements.indexOf(reference);
7700
+ if (index === -1)
7701
+ return false;
7702
+ this.bodyElements.splice(index, 0, element);
7703
+ return true;
7704
+ }
7705
+ replaceElement(oldElement, newElement) {
7706
+ const index = this.bodyElements.indexOf(oldElement);
7707
+ if (index === -1)
7708
+ return false;
7709
+ this.bodyElements[index] = newElement;
7710
+ return true;
7711
+ }
6987
7712
  insertBodyElementAt(index, element) {
6988
7713
  const clampedIndex = Math.max(0, Math.min(index, this.bodyElements.length));
6989
7714
  this.bodyElements.splice(clampedIndex, 0, element);