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.
- package/README.md +158 -7
- package/dist/core/Document.d.ts +98 -3
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +740 -50
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentContent.d.ts.map +1 -1
- package/dist/core/DocumentContent.js +0 -8
- package/dist/core/DocumentContent.js.map +1 -1
- package/dist/core/DocumentGenerator.d.ts.map +1 -1
- package/dist/core/DocumentGenerator.js +9 -5
- package/dist/core/DocumentGenerator.js.map +1 -1
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +617 -104
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.map +1 -1
- package/dist/core/RelationshipManager.js +4 -3
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/elements/Bookmark.d.ts +7 -0
- package/dist/elements/Bookmark.d.ts.map +1 -1
- package/dist/elements/Bookmark.js +24 -4
- package/dist/elements/Bookmark.js.map +1 -1
- package/dist/elements/BookmarkManager.d.ts.map +1 -1
- package/dist/elements/BookmarkManager.js +4 -3
- package/dist/elements/BookmarkManager.js.map +1 -1
- package/dist/elements/CommonTypes.d.ts +2 -2
- package/dist/elements/CommonTypes.d.ts.map +1 -1
- package/dist/elements/CommonTypes.js +14 -1
- package/dist/elements/CommonTypes.js.map +1 -1
- package/dist/elements/Field.d.ts +1 -1
- package/dist/elements/Field.d.ts.map +1 -1
- package/dist/elements/Field.js +1 -1
- package/dist/elements/Field.js.map +1 -1
- package/dist/elements/Footer.d.ts +2 -0
- package/dist/elements/Footer.d.ts.map +1 -1
- package/dist/elements/Footer.js +6 -0
- package/dist/elements/Footer.js.map +1 -1
- package/dist/elements/Header.d.ts +2 -0
- package/dist/elements/Header.d.ts.map +1 -1
- package/dist/elements/Header.js +6 -0
- package/dist/elements/Header.js.map +1 -1
- package/dist/elements/Image.d.ts.map +1 -1
- package/dist/elements/Image.js +3 -0
- package/dist/elements/Image.js.map +1 -1
- package/dist/elements/Paragraph.d.ts +81 -1
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +515 -21
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/elements/Revision.d.ts +0 -1
- package/dist/elements/Revision.d.ts.map +1 -1
- package/dist/elements/Revision.js +0 -12
- package/dist/elements/Revision.js.map +1 -1
- package/dist/elements/RevisionManager.d.ts +0 -1
- package/dist/elements/RevisionManager.d.ts.map +1 -1
- package/dist/elements/RevisionManager.js +0 -2
- package/dist/elements/RevisionManager.js.map +1 -1
- package/dist/elements/Run.d.ts +16 -4
- package/dist/elements/Run.d.ts.map +1 -1
- package/dist/elements/Run.js +114 -22
- package/dist/elements/Run.js.map +1 -1
- package/dist/elements/Section.d.ts +7 -1
- package/dist/elements/Section.d.ts.map +1 -1
- package/dist/elements/Section.js +185 -4
- package/dist/elements/Section.js.map +1 -1
- package/dist/elements/Shape.js.map +1 -1
- package/dist/elements/Table.d.ts +30 -1
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +357 -40
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableCell.d.ts +3 -0
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +30 -3
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableGridChange.d.ts +0 -1
- package/dist/elements/TableGridChange.d.ts.map +1 -1
- package/dist/elements/TableGridChange.js +0 -10
- package/dist/elements/TableGridChange.js.map +1 -1
- package/dist/elements/TableRow.d.ts +4 -0
- package/dist/elements/TableRow.d.ts.map +1 -1
- package/dist/elements/TableRow.js +31 -3
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts +5 -0
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +22 -0
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +3 -3
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/Style.d.ts +1 -0
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +25 -59
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +1 -0
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js +12 -0
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/helpers/CleanupHelper.js.map +1 -1
- package/dist/images/ImageOptimizer.d.ts.map +1 -1
- package/dist/images/ImageOptimizer.js +0 -1
- package/dist/images/ImageOptimizer.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/managers/DrawingManager.d.ts.map +1 -1
- package/dist/managers/DrawingManager.js +4 -2
- package/dist/managers/DrawingManager.js.map +1 -1
- package/dist/types/formatting.d.ts +2 -2
- package/dist/types/formatting.d.ts.map +1 -1
- package/dist/types/formatting.js.map +1 -1
- package/dist/utils/ChangelogGenerator.d.ts +2 -2
- package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
- package/dist/utils/ChangelogGenerator.js +4 -5
- package/dist/utils/ChangelogGenerator.js.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.js +0 -1
- package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/utils/RevisionAwareProcessor.d.ts +2 -2
- package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
- package/dist/utils/RevisionAwareProcessor.js +2 -2
- package/dist/utils/RevisionAwareProcessor.js.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.d.ts +0 -2
- package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.js +0 -26
- package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/utils/ShadingResolver.d.ts.map +1 -1
- package/dist/utils/ShadingResolver.js.map +1 -1
- package/dist/utils/acceptRevisions.js +1 -1
- package/dist/utils/acceptRevisions.js.map +1 -1
- package/dist/utils/stripTrackedChanges.js +1 -1
- package/dist/utils/stripTrackedChanges.js.map +1 -1
- package/dist/utils/units.d.ts.map +1 -1
- package/dist/utils/units.js +1 -1
- package/dist/utils/units.js.map +1 -1
- package/dist/validation/RevisionAutoFixer.d.ts +2 -1
- package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
- package/dist/validation/RevisionAutoFixer.js.map +1 -1
- package/package.json +10 -1
- package/src/constants/CLAUDE.md +28 -0
- package/src/core/CLAUDE.md +4 -0
- package/src/core/Document.ts +1770 -83
- package/src/core/DocumentContent.ts +0 -11
- package/src/core/DocumentGenerator.ts +11 -12
- package/src/core/DocumentParser.ts +654 -141
- package/src/core/RelationshipManager.ts +6 -3
- package/src/elements/Bookmark.ts +39 -4
- package/src/elements/BookmarkManager.ts +4 -3
- package/src/elements/CLAUDE.md +18 -2
- package/src/elements/CommonTypes.ts +35 -8
- package/src/elements/Field.ts +1 -1
- package/src/elements/Footer.ts +23 -0
- package/src/elements/Header.ts +25 -0
- package/src/elements/Image.ts +5 -0
- package/src/elements/Paragraph.ts +1069 -41
- package/src/elements/Revision.ts +0 -19
- package/src/elements/RevisionManager.ts +1 -3
- package/src/elements/Run.ts +265 -35
- package/src/elements/Section.ts +214 -8
- package/src/elements/Shape.ts +1 -1
- package/src/elements/Table.ts +850 -61
- package/src/elements/TableCell.ts +84 -10
- package/src/elements/TableGridChange.ts +2 -16
- package/src/elements/TableRow.ts +94 -9
- package/src/formatting/AbstractNumbering.ts +42 -1
- package/src/formatting/CLAUDE.md +4 -0
- package/src/formatting/NumberingLevel.ts +11 -7
- package/src/formatting/Style.ts +39 -71
- package/src/formatting/StylesManager.ts +36 -0
- package/src/helpers/CleanupHelper.ts +1 -1
- package/src/images/ImageOptimizer.ts +0 -3
- package/src/index.ts +1 -1
- package/src/managers/DrawingManager.ts +5 -3
- package/src/tracking/CLAUDE.md +30 -0
- package/src/types/CLAUDE.md +39 -0
- package/src/types/formatting.ts +2 -2
- package/src/utils/CLAUDE.md +15 -0
- package/src/utils/ChangelogGenerator.ts +4 -5
- package/src/utils/InMemoryRevisionAcceptor.ts +0 -9
- package/src/utils/RevisionAwareProcessor.ts +2 -3
- package/src/utils/SelectiveRevisionAcceptor.ts +0 -39
- package/src/utils/ShadingResolver.ts +0 -1
- package/src/utils/acceptRevisions.ts +1 -1
- package/src/utils/stripTrackedChanges.ts +1 -1
- package/src/utils/units.ts +2 -1
- package/src/validation/CLAUDE.md +40 -0
- package/src/validation/RevisionAutoFixer.ts +2 -1
package/dist/core/Document.js
CHANGED
|
@@ -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.
|
|
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, (
|
|
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, (
|
|
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(/"/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, '&')
|
|
7381
|
+
.replace(/</g, '<')
|
|
7382
|
+
.replace(/>/g, '>')
|
|
7383
|
+
.replace(/"/g, '"');
|
|
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);
|