docxmlater 11.0.10 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -13
- package/dist/core/Document.d.ts +29 -3
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +733 -170
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentGenerator.d.ts +1 -0
- package/dist/core/DocumentGenerator.d.ts.map +1 -1
- package/dist/core/DocumentGenerator.js +77 -25
- package/dist/core/DocumentGenerator.js.map +1 -1
- package/dist/core/DocumentParser.d.ts +7 -3
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +427 -81
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.map +1 -1
- package/dist/core/RelationshipManager.js +2 -2
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/elements/Comment.d.ts +15 -1
- package/dist/elements/Comment.d.ts.map +1 -1
- package/dist/elements/Comment.js +67 -12
- package/dist/elements/Comment.js.map +1 -1
- package/dist/elements/CommentManager.d.ts +4 -0
- package/dist/elements/CommentManager.d.ts.map +1 -1
- package/dist/elements/CommentManager.js +74 -16
- package/dist/elements/CommentManager.js.map +1 -1
- package/dist/elements/EndnoteManager.d.ts.map +1 -1
- package/dist/elements/EndnoteManager.js.map +1 -1
- package/dist/elements/Field.d.ts +10 -1
- package/dist/elements/Field.d.ts.map +1 -1
- package/dist/elements/Field.js +76 -34
- package/dist/elements/Field.js.map +1 -1
- package/dist/elements/FieldHelpers.d.ts +1 -0
- package/dist/elements/FieldHelpers.d.ts.map +1 -1
- package/dist/elements/FieldHelpers.js +8 -4
- package/dist/elements/FieldHelpers.js.map +1 -1
- package/dist/elements/Footer.d.ts +3 -1
- package/dist/elements/Footer.d.ts.map +1 -1
- package/dist/elements/Footer.js +39 -53
- package/dist/elements/Footer.js.map +1 -1
- package/dist/elements/FootnoteManager.d.ts.map +1 -1
- package/dist/elements/FootnoteManager.js.map +1 -1
- package/dist/elements/Header.d.ts +3 -1
- package/dist/elements/Header.d.ts.map +1 -1
- package/dist/elements/Header.js +39 -53
- package/dist/elements/Header.js.map +1 -1
- package/dist/elements/HeaderFooterManager.d.ts +4 -2
- package/dist/elements/HeaderFooterManager.d.ts.map +1 -1
- package/dist/elements/HeaderFooterManager.js +36 -6
- package/dist/elements/HeaderFooterManager.js.map +1 -1
- package/dist/elements/Hyperlink.d.ts +6 -1
- package/dist/elements/Hyperlink.d.ts.map +1 -1
- package/dist/elements/Hyperlink.js +69 -44
- package/dist/elements/Hyperlink.js.map +1 -1
- package/dist/elements/Image.d.ts.map +1 -1
- package/dist/elements/Image.js +33 -6
- package/dist/elements/Image.js.map +1 -1
- package/dist/elements/ImageManager.d.ts +1 -0
- package/dist/elements/ImageManager.d.ts.map +1 -1
- package/dist/elements/ImageManager.js +11 -0
- package/dist/elements/ImageManager.js.map +1 -1
- package/dist/elements/Paragraph.d.ts +3 -0
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +91 -26
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/elements/Revision.d.ts +4 -0
- package/dist/elements/Revision.d.ts.map +1 -1
- package/dist/elements/Revision.js +369 -29
- package/dist/elements/Revision.js.map +1 -1
- package/dist/elements/Run.d.ts +1 -0
- package/dist/elements/Run.d.ts.map +1 -1
- package/dist/elements/Run.js +24 -4
- package/dist/elements/Run.js.map +1 -1
- package/dist/elements/Section.d.ts.map +1 -1
- package/dist/elements/Section.js +17 -7
- package/dist/elements/Section.js.map +1 -1
- package/dist/elements/Shape.d.ts.map +1 -1
- package/dist/elements/Shape.js +50 -42
- package/dist/elements/Shape.js.map +1 -1
- package/dist/elements/StructuredDocumentTag.d.ts +9 -1
- package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
- package/dist/elements/StructuredDocumentTag.js +46 -6
- package/dist/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/elements/Table.d.ts +2 -0
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +90 -42
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableCell.d.ts +1 -0
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +32 -13
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableOfContents.d.ts.map +1 -1
- package/dist/elements/TableOfContents.js +5 -7
- package/dist/elements/TableOfContents.js.map +1 -1
- package/dist/elements/TableRow.d.ts +1 -0
- package/dist/elements/TableRow.d.ts.map +1 -1
- package/dist/elements/TableRow.js +16 -1
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/elements/TextBox.d.ts.map +1 -1
- package/dist/elements/TextBox.js +55 -42
- package/dist/elements/TextBox.js.map +1 -1
- package/dist/esm/core/Document.js +735 -172
- package/dist/esm/core/Document.js.map +1 -1
- package/dist/esm/core/DocumentGenerator.js +77 -25
- package/dist/esm/core/DocumentGenerator.js.map +1 -1
- package/dist/esm/core/DocumentParser.js +427 -81
- package/dist/esm/core/DocumentParser.js.map +1 -1
- package/dist/esm/core/RelationshipManager.js +2 -2
- package/dist/esm/core/RelationshipManager.js.map +1 -1
- package/dist/esm/elements/Comment.js +67 -12
- package/dist/esm/elements/Comment.js.map +1 -1
- package/dist/esm/elements/CommentManager.js +74 -16
- package/dist/esm/elements/CommentManager.js.map +1 -1
- package/dist/esm/elements/EndnoteManager.js.map +1 -1
- package/dist/esm/elements/Field.js +77 -35
- package/dist/esm/elements/Field.js.map +1 -1
- package/dist/esm/elements/FieldHelpers.js +7 -4
- package/dist/esm/elements/FieldHelpers.js.map +1 -1
- package/dist/esm/elements/Footer.js +39 -53
- package/dist/esm/elements/Footer.js.map +1 -1
- package/dist/esm/elements/FootnoteManager.js.map +1 -1
- package/dist/esm/elements/Header.js +39 -53
- package/dist/esm/elements/Header.js.map +1 -1
- package/dist/esm/elements/HeaderFooterManager.js +36 -6
- package/dist/esm/elements/HeaderFooterManager.js.map +1 -1
- package/dist/esm/elements/Hyperlink.js +69 -44
- package/dist/esm/elements/Hyperlink.js.map +1 -1
- package/dist/esm/elements/Image.js +33 -6
- package/dist/esm/elements/Image.js.map +1 -1
- package/dist/esm/elements/ImageManager.js +11 -0
- package/dist/esm/elements/ImageManager.js.map +1 -1
- package/dist/esm/elements/Paragraph.js +91 -26
- package/dist/esm/elements/Paragraph.js.map +1 -1
- package/dist/esm/elements/Revision.js +369 -29
- package/dist/esm/elements/Revision.js.map +1 -1
- package/dist/esm/elements/Run.js +24 -4
- package/dist/esm/elements/Run.js.map +1 -1
- package/dist/esm/elements/Section.js +17 -7
- package/dist/esm/elements/Section.js.map +1 -1
- package/dist/esm/elements/Shape.js +50 -42
- package/dist/esm/elements/Shape.js.map +1 -1
- package/dist/esm/elements/StructuredDocumentTag.js +46 -6
- package/dist/esm/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/esm/elements/Table.js +90 -42
- package/dist/esm/elements/Table.js.map +1 -1
- package/dist/esm/elements/TableCell.js +32 -13
- package/dist/esm/elements/TableCell.js.map +1 -1
- package/dist/esm/elements/TableOfContents.js +5 -7
- package/dist/esm/elements/TableOfContents.js.map +1 -1
- package/dist/esm/elements/TableRow.js +16 -1
- package/dist/esm/elements/TableRow.js.map +1 -1
- package/dist/esm/elements/TextBox.js +55 -42
- package/dist/esm/elements/TextBox.js.map +1 -1
- package/dist/esm/formatting/AbstractNumbering.js +1 -1
- package/dist/esm/formatting/AbstractNumbering.js.map +1 -1
- package/dist/esm/formatting/NumberingLevel.js +8 -6
- package/dist/esm/formatting/NumberingLevel.js.map +1 -1
- package/dist/esm/formatting/NumberingManager.js +16 -1
- package/dist/esm/formatting/NumberingManager.js.map +1 -1
- package/dist/esm/formatting/Style.js +14 -0
- package/dist/esm/formatting/Style.js.map +1 -1
- package/dist/esm/formatting/StylesManager.js +14 -2
- package/dist/esm/formatting/StylesManager.js.map +1 -1
- package/dist/esm/helpers/CleanupHelper.js +103 -26
- package/dist/esm/helpers/CleanupHelper.js.map +1 -1
- package/dist/esm/images/ImageOptimizer.js +52 -4
- package/dist/esm/images/ImageOptimizer.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal.js +1 -1
- package/dist/esm/internal.js.map +1 -1
- package/dist/esm/processors/CompatibilityUpgrader.js +7 -1
- package/dist/esm/processors/CompatibilityUpgrader.js.map +1 -1
- package/dist/esm/processors/InMemoryRevisionAcceptor.js +134 -13
- package/dist/esm/processors/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/esm/processors/RevisionWalker.js +223 -39
- package/dist/esm/processors/RevisionWalker.js.map +1 -1
- package/dist/esm/processors/SelectiveRevisionAcceptor.js +116 -17
- package/dist/esm/processors/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/esm/processors/acceptRevisions.js +20 -11
- package/dist/esm/processors/acceptRevisions.js.map +1 -1
- package/dist/esm/processors/cnfStyleDecoder.js +7 -7
- package/dist/esm/processors/cnfStyleDecoder.js.map +1 -1
- package/dist/esm/processors/stripTrackedChanges.js +16 -5
- package/dist/esm/processors/stripTrackedChanges.js.map +1 -1
- package/dist/esm/utils/deepClone.js +24 -11
- package/dist/esm/utils/deepClone.js.map +1 -1
- package/dist/esm/utils/units.js +1 -1
- package/dist/esm/utils/units.js.map +1 -1
- package/dist/esm/utils/validation.js +11 -23
- package/dist/esm/utils/validation.js.map +1 -1
- package/dist/esm/utils/xmlSanitization.js +131 -7
- package/dist/esm/utils/xmlSanitization.js.map +1 -1
- package/dist/esm/validation/RevisionAutoFixer.js +69 -55
- package/dist/esm/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/esm/validation/RevisionValidator.js +24 -20
- package/dist/esm/validation/RevisionValidator.js.map +1 -1
- package/dist/esm/xml/XMLBuilder.js +52 -20
- package/dist/esm/xml/XMLBuilder.js.map +1 -1
- package/dist/esm/xml/XMLParser.js +55 -13
- package/dist/esm/xml/XMLParser.js.map +1 -1
- package/dist/esm/zip/ZipHandler.js +37 -13
- package/dist/esm/zip/ZipHandler.js.map +1 -1
- package/dist/esm/zip/ZipReader.js +53 -6
- package/dist/esm/zip/ZipReader.js.map +1 -1
- package/dist/esm/zip/errors.js +7 -0
- package/dist/esm/zip/errors.js.map +1 -1
- package/dist/esm/zip/types.js +4 -0
- package/dist/esm/zip/types.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +1 -1
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts +1 -1
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +8 -6
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/NumberingManager.d.ts.map +1 -1
- package/dist/formatting/NumberingManager.js +16 -1
- package/dist/formatting/NumberingManager.js.map +1 -1
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +14 -0
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +2 -0
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js +14 -2
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/helpers/CleanupHelper.d.ts.map +1 -1
- package/dist/helpers/CleanupHelper.js +103 -26
- package/dist/helpers/CleanupHelper.js.map +1 -1
- package/dist/images/ImageOptimizer.d.ts.map +1 -1
- package/dist/images/ImageOptimizer.js +52 -4
- package/dist/images/ImageOptimizer.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -1
- package/dist/internal.js.map +1 -1
- package/dist/processors/CompatibilityUpgrader.d.ts.map +1 -1
- package/dist/processors/CompatibilityUpgrader.js +7 -1
- package/dist/processors/CompatibilityUpgrader.js.map +1 -1
- package/dist/processors/InMemoryRevisionAcceptor.d.ts +1 -0
- package/dist/processors/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/processors/InMemoryRevisionAcceptor.js +135 -13
- package/dist/processors/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/processors/RevisionWalker.d.ts +9 -3
- package/dist/processors/RevisionWalker.d.ts.map +1 -1
- package/dist/processors/RevisionWalker.js +223 -39
- package/dist/processors/RevisionWalker.js.map +1 -1
- package/dist/processors/SelectiveRevisionAcceptor.d.ts.map +1 -1
- package/dist/processors/SelectiveRevisionAcceptor.js +116 -17
- package/dist/processors/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/processors/acceptRevisions.d.ts +1 -0
- package/dist/processors/acceptRevisions.d.ts.map +1 -1
- package/dist/processors/acceptRevisions.js +21 -11
- package/dist/processors/acceptRevisions.js.map +1 -1
- package/dist/processors/cnfStyleDecoder.d.ts.map +1 -1
- package/dist/processors/cnfStyleDecoder.js +7 -7
- package/dist/processors/cnfStyleDecoder.js.map +1 -1
- package/dist/processors/stripTrackedChanges.d.ts.map +1 -1
- package/dist/processors/stripTrackedChanges.js +16 -5
- package/dist/processors/stripTrackedChanges.js.map +1 -1
- package/dist/utils/deepClone.d.ts.map +1 -1
- package/dist/utils/deepClone.js +24 -11
- package/dist/utils/deepClone.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/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +11 -23
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/xmlSanitization.d.ts +2 -0
- package/dist/utils/xmlSanitization.d.ts.map +1 -1
- package/dist/utils/xmlSanitization.js +133 -7
- package/dist/utils/xmlSanitization.js.map +1 -1
- package/dist/validation/RevisionAutoFixer.d.ts +6 -2
- package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
- package/dist/validation/RevisionAutoFixer.js +68 -54
- package/dist/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/validation/RevisionValidator.d.ts +2 -0
- package/dist/validation/RevisionValidator.d.ts.map +1 -1
- package/dist/validation/RevisionValidator.js +26 -21
- package/dist/validation/RevisionValidator.js.map +1 -1
- package/dist/xml/XMLBuilder.d.ts +1 -0
- package/dist/xml/XMLBuilder.d.ts.map +1 -1
- package/dist/xml/XMLBuilder.js +52 -20
- package/dist/xml/XMLBuilder.js.map +1 -1
- package/dist/xml/XMLParser.d.ts +1 -0
- package/dist/xml/XMLParser.d.ts.map +1 -1
- package/dist/xml/XMLParser.js +55 -13
- package/dist/xml/XMLParser.js.map +1 -1
- package/dist/zip/ZipHandler.d.ts.map +1 -1
- package/dist/zip/ZipHandler.js +37 -13
- package/dist/zip/ZipHandler.js.map +1 -1
- package/dist/zip/ZipReader.d.ts.map +1 -1
- package/dist/zip/ZipReader.js +52 -5
- package/dist/zip/ZipReader.js.map +1 -1
- package/dist/zip/errors.d.ts +3 -0
- package/dist/zip/errors.d.ts.map +1 -1
- package/dist/zip/errors.js +9 -1
- package/dist/zip/errors.js.map +1 -1
- package/dist/zip/types.d.ts +4 -0
- package/dist/zip/types.d.ts.map +1 -1
- package/dist/zip/types.js +4 -0
- package/dist/zip/types.js.map +1 -1
- package/package.json +2 -2
- package/src/core/Document.ts +1184 -242
- package/src/core/DocumentGenerator.ts +106 -26
- package/src/core/DocumentParser.ts +681 -114
- package/src/core/RelationshipManager.ts +446 -442
- package/src/elements/Comment.ts +123 -18
- package/src/elements/CommentManager.ts +121 -22
- package/src/elements/EndnoteManager.ts +4 -1
- package/src/elements/Field.ts +134 -43
- package/src/elements/FieldHelpers.ts +20 -4
- package/src/elements/Footer.ts +62 -67
- package/src/elements/FootnoteManager.ts +4 -1
- package/src/elements/Header.ts +62 -67
- package/src/elements/HeaderFooterManager.ts +56 -8
- package/src/elements/Hyperlink.ts +150 -55
- package/src/elements/Image.ts +51 -7
- package/src/elements/ImageManager.ts +24 -0
- package/src/elements/Paragraph.ts +161 -40
- package/src/elements/Revision.ts +446 -47
- package/src/elements/Run.ts +44 -6
- package/src/elements/Section.ts +25 -9
- package/src/elements/Shape.ts +52 -44
- package/src/elements/StructuredDocumentTag.ts +83 -8
- package/src/elements/Table.ts +151 -50
- package/src/elements/TableCell.ts +57 -17
- package/src/elements/TableOfContents.ts +10 -9
- package/src/elements/TableRow.ts +35 -3
- package/src/elements/TextBox.ts +58 -43
- package/src/formatting/AbstractNumbering.ts +4 -2
- package/src/formatting/NumberingLevel.ts +50 -12
- package/src/formatting/NumberingManager.ts +32 -3
- package/src/formatting/Style.ts +14 -0
- package/src/formatting/StylesManager.ts +29 -2
- package/src/helpers/CleanupHelper.ts +122 -30
- package/src/images/ImageOptimizer.ts +64 -5
- package/src/index.ts +7 -0
- package/src/internal.ts +1 -0
- package/src/processors/CompatibilityUpgrader.ts +15 -2
- package/src/processors/InMemoryRevisionAcceptor.ts +276 -17
- package/src/processors/RevisionWalker.ts +390 -46
- package/src/processors/SelectiveRevisionAcceptor.ts +164 -28
- package/src/processors/acceptRevisions.ts +67 -17
- package/src/processors/cnfStyleDecoder.ts +18 -12
- package/src/processors/stripTrackedChanges.ts +47 -10
- package/src/utils/deepClone.ts +48 -14
- package/src/utils/units.ts +3 -1
- package/src/utils/validation.ts +30 -32
- package/src/utils/xmlSanitization.ts +218 -22
- package/src/validation/RevisionAutoFixer.ts +109 -65
- package/src/validation/RevisionValidator.ts +48 -23
- package/src/xml/XMLBuilder.ts +82 -22
- package/src/xml/XMLParser.ts +87 -20
- package/src/zip/ZipHandler.ts +61 -21
- package/src/zip/ZipReader.ts +135 -13
- package/src/zip/errors.ts +15 -0
- package/src/zip/types.ts +44 -2
|
@@ -35,10 +35,11 @@ import { UNITS } from '../utils/units.js';
|
|
|
35
35
|
function getLogger() {
|
|
36
36
|
return createScopedLogger(getGlobalLogger(), 'Document');
|
|
37
37
|
}
|
|
38
|
-
import { acceptAllRevisions, cleanupRevisionMetadata } from '../processors/acceptRevisions.js';
|
|
38
|
+
import { acceptAllRevisions, rejectAllRevisions, cleanupRevisionMetadata, } from '../processors/acceptRevisions.js';
|
|
39
39
|
import { acceptRevisionsInMemory } from '../processors/InMemoryRevisionAcceptor.js';
|
|
40
40
|
import { stripTrackedChanges } from '../processors/stripTrackedChanges.js';
|
|
41
41
|
import { diffText, diffHasUnchangedParts } from '../utils/textDiff.js';
|
|
42
|
+
import { reorderRunPropertyChildren } from '../utils/xmlSanitization.js';
|
|
42
43
|
import { XMLBuilder } from '../xml/XMLBuilder.js';
|
|
43
44
|
import { XMLParser } from '../xml/XMLParser.js';
|
|
44
45
|
import { DocumentTrackingContext } from '../tracking/DocumentTrackingContext.js';
|
|
@@ -50,7 +51,7 @@ import { DocumentParser } from './DocumentParser.js';
|
|
|
50
51
|
import { DocumentValidator } from './DocumentValidator.js';
|
|
51
52
|
import { DocumentEventEmitter, } from './DocumentEvents.js';
|
|
52
53
|
import { RelationshipManager } from './RelationshipManager.js';
|
|
53
|
-
import { RelationshipType } from './Relationship.js';
|
|
54
|
+
import { Relationship, RelationshipType } from './Relationship.js';
|
|
54
55
|
import { optimizeImage } from '../images/ImageOptimizer.js';
|
|
55
56
|
export class Document {
|
|
56
57
|
constructor(zipHandler, options = {}, initDefaults = true) {
|
|
@@ -75,6 +76,9 @@ export class Document {
|
|
|
75
76
|
this.bookmarkManager.setIdProvider(() => this.documentIdManager.getNextId(), (existingId) => this.documentIdManager.ensureNextIdAbove(existingId));
|
|
76
77
|
this.revisionManager.setIdProvider(() => this.documentIdManager.getNextId(), (existingId) => this.documentIdManager.ensureNextIdAbove(existingId));
|
|
77
78
|
this.commentManager.setIdProvider(() => this.documentIdManager.getNextId(), (existingId) => this.documentIdManager.ensureNextIdAbove(existingId));
|
|
79
|
+
this.commentManager.setModifiedNotifier(() => {
|
|
80
|
+
this._commentsModified = true;
|
|
81
|
+
});
|
|
78
82
|
this.trackingContext = new DocumentTrackingContext(this.revisionManager);
|
|
79
83
|
this.parser = new DocumentParser();
|
|
80
84
|
this.generator = new DocumentGenerator();
|
|
@@ -129,6 +133,7 @@ export class Document {
|
|
|
129
133
|
_originalNumberingXml;
|
|
130
134
|
_originalSettingsXml;
|
|
131
135
|
_originalAppPropsXml;
|
|
136
|
+
_originalCorePropsXml;
|
|
132
137
|
_originalFootnotesXml;
|
|
133
138
|
_originalEndnotesXml;
|
|
134
139
|
_originalCommentsXml;
|
|
@@ -138,6 +143,7 @@ export class Document {
|
|
|
138
143
|
_saveQueue = Promise.resolve();
|
|
139
144
|
_removedParts = new Set();
|
|
140
145
|
_appPropsModified = false;
|
|
146
|
+
_corePropsModified = false;
|
|
141
147
|
_footnotesModified = false;
|
|
142
148
|
_endnotesModified = false;
|
|
143
149
|
_settingsModified = false;
|
|
@@ -337,7 +343,7 @@ export class Document {
|
|
|
337
343
|
const logger = getLogger();
|
|
338
344
|
logger.info('Loading document from file', { path: filePath });
|
|
339
345
|
const zipHandler = new ZipHandler();
|
|
340
|
-
await zipHandler.load(filePath);
|
|
346
|
+
await zipHandler.load(filePath, { sizeLimits: options?.sizeLimits });
|
|
341
347
|
const doc = await Document.initializeFromZip(zipHandler, options);
|
|
342
348
|
doc._events.emit('afterLoad', { source: 'file', path: filePath });
|
|
343
349
|
return doc;
|
|
@@ -346,7 +352,7 @@ export class Document {
|
|
|
346
352
|
const logger = getLogger();
|
|
347
353
|
logger.info('Loading document from buffer', { bufferSize: buffer.length });
|
|
348
354
|
const zipHandler = new ZipHandler();
|
|
349
|
-
await zipHandler.loadFromBuffer(buffer);
|
|
355
|
+
await zipHandler.loadFromBuffer(buffer, { sizeLimits: options?.sizeLimits });
|
|
350
356
|
const doc = await Document.initializeFromZip(zipHandler, options);
|
|
351
357
|
doc._events.emit('afterLoad', { source: 'buffer' });
|
|
352
358
|
return doc;
|
|
@@ -354,12 +360,20 @@ export class Document {
|
|
|
354
360
|
static async initializeFromZip(zipHandler, options) {
|
|
355
361
|
const logger = getLogger();
|
|
356
362
|
const useInMemoryAccept = options?.acceptRevisions === true;
|
|
363
|
+
if (useInMemoryAccept && options?.revisionHandling === 'reject') {
|
|
364
|
+
throw new Error("Conflicting load options: 'acceptRevisions: true' (in-memory accept) cannot be combined " +
|
|
365
|
+
'with \'revisionHandling: "reject"\'. Use \'revisionHandling: "reject"\' on its own to ' +
|
|
366
|
+
'revert the document to its original pre-edit state.');
|
|
367
|
+
}
|
|
357
368
|
const revisionHandling = useInMemoryAccept
|
|
358
369
|
? 'preserve'
|
|
359
370
|
: (options?.revisionHandling ?? 'accept');
|
|
360
371
|
if (revisionHandling === 'accept') {
|
|
361
372
|
await acceptAllRevisions(zipHandler);
|
|
362
373
|
}
|
|
374
|
+
else if (revisionHandling === 'reject') {
|
|
375
|
+
await rejectAllRevisions(zipHandler);
|
|
376
|
+
}
|
|
363
377
|
else if (revisionHandling === 'strip') {
|
|
364
378
|
await stripTrackedChanges(zipHandler);
|
|
365
379
|
}
|
|
@@ -386,7 +400,7 @@ export class Document {
|
|
|
386
400
|
}
|
|
387
401
|
const numberingXml = zipHandler.getFileAsString(DOCX_PATHS.NUMBERING);
|
|
388
402
|
if (numberingXml) {
|
|
389
|
-
doc._originalNumberingXml = numberingXml;
|
|
403
|
+
doc._originalNumberingXml = reorderRunPropertyChildren(numberingXml);
|
|
390
404
|
}
|
|
391
405
|
const settingsXml = zipHandler.getFileAsString(DOCX_PATHS.SETTINGS);
|
|
392
406
|
if (settingsXml) {
|
|
@@ -397,6 +411,10 @@ export class Document {
|
|
|
397
411
|
if (appPropsXml) {
|
|
398
412
|
doc._originalAppPropsXml = appPropsXml;
|
|
399
413
|
}
|
|
414
|
+
const corePropsXml = zipHandler.getFileAsString(DOCX_PATHS.CORE_PROPS);
|
|
415
|
+
if (corePropsXml) {
|
|
416
|
+
doc._originalCorePropsXml = corePropsXml;
|
|
417
|
+
}
|
|
400
418
|
const webSettingsXml = zipHandler.getFileAsString(DOCX_PATHS.WEB_SETTINGS);
|
|
401
419
|
if (webSettingsXml) {
|
|
402
420
|
doc._originalWebSettingsXml = webSettingsXml;
|
|
@@ -659,17 +677,17 @@ export class Document {
|
|
|
659
677
|
try {
|
|
660
678
|
const headersFooters = await this.parser.parseHeadersAndFooters(this.zipHandler, result.section, this.relationshipManager, this.imageManager);
|
|
661
679
|
const registeredHeaderRIds = new Set();
|
|
662
|
-
for (const { header, relationshipId } of headersFooters.headers) {
|
|
680
|
+
for (const { header, relationshipId, filename } of headersFooters.headers) {
|
|
663
681
|
if (registeredHeaderRIds.has(relationshipId))
|
|
664
682
|
continue;
|
|
665
|
-
this.headerFooterManager.registerHeader(header, relationshipId);
|
|
683
|
+
this.headerFooterManager.registerHeader(header, relationshipId, filename);
|
|
666
684
|
registeredHeaderRIds.add(relationshipId);
|
|
667
685
|
}
|
|
668
686
|
const registeredFooterRIds = new Set();
|
|
669
|
-
for (const { footer, relationshipId } of headersFooters.footers) {
|
|
687
|
+
for (const { footer, relationshipId, filename } of headersFooters.footers) {
|
|
670
688
|
if (registeredFooterRIds.has(relationshipId))
|
|
671
689
|
continue;
|
|
672
|
-
this.headerFooterManager.registerFooter(footer, relationshipId);
|
|
690
|
+
this.headerFooterManager.registerFooter(footer, relationshipId, filename);
|
|
673
691
|
registeredFooterRIds.add(relationshipId);
|
|
674
692
|
}
|
|
675
693
|
}
|
|
@@ -712,7 +730,7 @@ export class Document {
|
|
|
712
730
|
}
|
|
713
731
|
}
|
|
714
732
|
const parser = new DocumentParser();
|
|
715
|
-
const comments = parser.parseCommentsXml(commentsXml);
|
|
733
|
+
const comments = parser.parseCommentsXml(commentsXml, this._originalCommentCompanionFiles.get(DOCX_PATHS.COMMENTS_EXTENDED));
|
|
716
734
|
for (const comment of comments) {
|
|
717
735
|
this.commentManager.registerExisting(comment);
|
|
718
736
|
}
|
|
@@ -726,7 +744,9 @@ export class Document {
|
|
|
726
744
|
this._originalFootnotesXml = footnotesXml;
|
|
727
745
|
try {
|
|
728
746
|
const parser = new DocumentParser();
|
|
729
|
-
const
|
|
747
|
+
const relsXml = this.zipHandler.getFileAsString('word/_rels/footnotes.xml.rels');
|
|
748
|
+
const partRels = relsXml ? RelationshipManager.fromXml(relsXml) : undefined;
|
|
749
|
+
const footnotes = parser.parseFootnotesXml(footnotesXml, partRels);
|
|
730
750
|
for (const footnote of footnotes) {
|
|
731
751
|
const id = footnote.getId();
|
|
732
752
|
if (!this.footnoteManager.hasFootnote(id)) {
|
|
@@ -748,7 +768,9 @@ export class Document {
|
|
|
748
768
|
this._originalEndnotesXml = endnotesXml;
|
|
749
769
|
try {
|
|
750
770
|
const parser = new DocumentParser();
|
|
751
|
-
const
|
|
771
|
+
const relsXml = this.zipHandler.getFileAsString('word/_rels/endnotes.xml.rels');
|
|
772
|
+
const partRels = relsXml ? RelationshipManager.fromXml(relsXml) : undefined;
|
|
773
|
+
const endnotes = parser.parseEndnotesXml(endnotesXml, partRels);
|
|
752
774
|
for (const endnote of endnotes) {
|
|
753
775
|
const id = endnote.getId();
|
|
754
776
|
if (!this.endnoteManager.hasEndnote(id)) {
|
|
@@ -840,12 +862,13 @@ export class Document {
|
|
|
840
862
|
paragraph._setStylesManager(this.stylesManager);
|
|
841
863
|
if (this.trackChangesEnabled && this.trackingContext.isEnabled()) {
|
|
842
864
|
this.bindTrackingToElement(paragraph);
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
865
|
+
const author = this.trackingContext.getAuthor();
|
|
866
|
+
for (const item of paragraph.getContent()) {
|
|
867
|
+
if (item instanceof Run || item instanceof Hyperlink) {
|
|
868
|
+
const insertion = Revision.createInsertion(author, item);
|
|
869
|
+
this.trackingContext.getRevisionManager().register(insertion);
|
|
870
|
+
paragraph.replaceContent(item, [insertion]);
|
|
871
|
+
}
|
|
849
872
|
}
|
|
850
873
|
}
|
|
851
874
|
this.bodyElements.push(paragraph);
|
|
@@ -1061,14 +1084,17 @@ export class Document {
|
|
|
1061
1084
|
}
|
|
1062
1085
|
setTitle(title) {
|
|
1063
1086
|
this.properties.title = title;
|
|
1087
|
+
this._corePropsModified = true;
|
|
1064
1088
|
return this;
|
|
1065
1089
|
}
|
|
1066
1090
|
setSubject(subject) {
|
|
1067
1091
|
this.properties.subject = subject;
|
|
1092
|
+
this._corePropsModified = true;
|
|
1068
1093
|
return this;
|
|
1069
1094
|
}
|
|
1070
1095
|
setCreator(creator) {
|
|
1071
1096
|
this.properties.creator = creator;
|
|
1097
|
+
this._corePropsModified = true;
|
|
1072
1098
|
return this;
|
|
1073
1099
|
}
|
|
1074
1100
|
setAuthor(author) {
|
|
@@ -1076,18 +1102,22 @@ export class Document {
|
|
|
1076
1102
|
}
|
|
1077
1103
|
setKeywords(keywords) {
|
|
1078
1104
|
this.properties.keywords = keywords;
|
|
1105
|
+
this._corePropsModified = true;
|
|
1079
1106
|
return this;
|
|
1080
1107
|
}
|
|
1081
1108
|
setDescription(description) {
|
|
1082
1109
|
this.properties.description = description;
|
|
1110
|
+
this._corePropsModified = true;
|
|
1083
1111
|
return this;
|
|
1084
1112
|
}
|
|
1085
1113
|
setCategory(category) {
|
|
1086
1114
|
this.properties.category = category;
|
|
1115
|
+
this._corePropsModified = true;
|
|
1087
1116
|
return this;
|
|
1088
1117
|
}
|
|
1089
1118
|
setContentStatus(status) {
|
|
1090
1119
|
this.properties.contentStatus = status;
|
|
1120
|
+
this._corePropsModified = true;
|
|
1091
1121
|
return this;
|
|
1092
1122
|
}
|
|
1093
1123
|
setApplication(application) {
|
|
@@ -1534,8 +1564,48 @@ export class Document {
|
|
|
1534
1564
|
if (this._removedParts.has(DOCX_PATHS.CORE_PROPS) ||
|
|
1535
1565
|
this._removedParts.has('docProps/core.xml'))
|
|
1536
1566
|
return;
|
|
1537
|
-
|
|
1538
|
-
|
|
1567
|
+
if (this._originalCorePropsXml && !this._corePropsModified) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
if (this._originalCorePropsXml && this._corePropsModified) {
|
|
1571
|
+
const mergedXml = this.mergeCorePropsWithOriginal();
|
|
1572
|
+
this.zipHandler.updateFile(DOCX_PATHS.CORE_PROPS, mergedXml);
|
|
1573
|
+
}
|
|
1574
|
+
else {
|
|
1575
|
+
const xml = this.generator.generateCoreProps(this.properties);
|
|
1576
|
+
this.zipHandler.updateFile(DOCX_PATHS.CORE_PROPS, xml);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
mergeCorePropsWithOriginal() {
|
|
1580
|
+
if (!this._originalCorePropsXml) {
|
|
1581
|
+
return this.generator.generateCoreProps(this.properties);
|
|
1582
|
+
}
|
|
1583
|
+
let xml = this._originalCorePropsXml;
|
|
1584
|
+
const mergeField = (tag, value) => {
|
|
1585
|
+
if (value === undefined)
|
|
1586
|
+
return;
|
|
1587
|
+
const escaped = XMLBuilder.sanitizeXmlContent(value);
|
|
1588
|
+
const openClose = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?</${tag}>`);
|
|
1589
|
+
const selfClosing = new RegExp(`<${tag}\\b[^>]*/>`);
|
|
1590
|
+
if (openClose.test(xml)) {
|
|
1591
|
+
xml = xml.replace(openClose, `<${tag}>${escaped}</${tag}>`);
|
|
1592
|
+
}
|
|
1593
|
+
else if (selfClosing.test(xml)) {
|
|
1594
|
+
xml = xml.replace(selfClosing, `<${tag}>${escaped}</${tag}>`);
|
|
1595
|
+
}
|
|
1596
|
+
else {
|
|
1597
|
+
xml = xml.replace(/<\/cp:coreProperties>/, ` <${tag}>${escaped}</${tag}>\n</cp:coreProperties>`);
|
|
1598
|
+
}
|
|
1599
|
+
};
|
|
1600
|
+
mergeField('dc:title', this.properties.title);
|
|
1601
|
+
mergeField('dc:subject', this.properties.subject);
|
|
1602
|
+
mergeField('dc:creator', this.properties.creator);
|
|
1603
|
+
mergeField('cp:keywords', this.properties.keywords);
|
|
1604
|
+
mergeField('dc:description', this.properties.description);
|
|
1605
|
+
mergeField('cp:category', this.properties.category);
|
|
1606
|
+
mergeField('cp:contentStatus', this.properties.contentStatus);
|
|
1607
|
+
mergeField('dc:language', this.properties.language);
|
|
1608
|
+
return xml;
|
|
1539
1609
|
}
|
|
1540
1610
|
updateAppProps() {
|
|
1541
1611
|
if (this._removedParts.has(DOCX_PATHS.APP_PROPS) || this._removedParts.has('docProps/app.xml'))
|
|
@@ -1565,24 +1635,36 @@ export class Document {
|
|
|
1565
1635
|
else if (xml.includes('<Company/>')) {
|
|
1566
1636
|
xml = xml.replace(/<Company\/>/, `<Company>${escaped}</Company>`);
|
|
1567
1637
|
}
|
|
1638
|
+
else {
|
|
1639
|
+
xml = xml.replace(/<\/Properties>/, ` <Company>${escaped}</Company>\n</Properties>`);
|
|
1640
|
+
}
|
|
1568
1641
|
}
|
|
1569
1642
|
if (this.properties.application !== undefined) {
|
|
1570
1643
|
const escaped = XMLBuilder.sanitizeXmlContent(this.properties.application);
|
|
1571
1644
|
if (xml.includes('<Application>')) {
|
|
1572
1645
|
xml = xml.replace(/<Application>[^<]*<\/Application>/, `<Application>${escaped}</Application>`);
|
|
1573
1646
|
}
|
|
1647
|
+
else {
|
|
1648
|
+
xml = xml.replace(/<\/Properties>/, ` <Application>${escaped}</Application>\n</Properties>`);
|
|
1649
|
+
}
|
|
1574
1650
|
}
|
|
1575
1651
|
if (this.properties.appVersion !== undefined) {
|
|
1576
1652
|
const escaped = XMLBuilder.sanitizeXmlContent(this.properties.appVersion);
|
|
1577
1653
|
if (xml.includes('<AppVersion>')) {
|
|
1578
1654
|
xml = xml.replace(/<AppVersion>[^<]*<\/AppVersion>/, `<AppVersion>${escaped}</AppVersion>`);
|
|
1579
1655
|
}
|
|
1656
|
+
else {
|
|
1657
|
+
xml = xml.replace(/<\/Properties>/, ` <AppVersion>${escaped}</AppVersion>\n</Properties>`);
|
|
1658
|
+
}
|
|
1580
1659
|
}
|
|
1581
1660
|
if (this.properties.manager !== undefined) {
|
|
1582
1661
|
const escaped = XMLBuilder.sanitizeXmlContent(this.properties.manager);
|
|
1583
1662
|
if (xml.includes('<Manager>')) {
|
|
1584
1663
|
xml = xml.replace(/<Manager>[^<]*<\/Manager>/, `<Manager>${escaped}</Manager>`);
|
|
1585
1664
|
}
|
|
1665
|
+
else {
|
|
1666
|
+
xml = xml.replace(/<\/Properties>/, ` <Manager>${escaped}</Manager>\n</Properties>`);
|
|
1667
|
+
}
|
|
1586
1668
|
}
|
|
1587
1669
|
return xml;
|
|
1588
1670
|
}
|
|
@@ -1708,7 +1790,8 @@ export class Document {
|
|
|
1708
1790
|
return this.stylesManager.generateStylesXml();
|
|
1709
1791
|
}
|
|
1710
1792
|
const modifiedStyleIds = this.stylesManager.getModifiedStyleIds();
|
|
1711
|
-
|
|
1793
|
+
const removedStyleIds = this.stylesManager.getRemovedStyleIds();
|
|
1794
|
+
if (modifiedStyleIds.size === 0 && removedStyleIds.size === 0) {
|
|
1712
1795
|
return this._originalStylesXml;
|
|
1713
1796
|
}
|
|
1714
1797
|
const modifiedStyles = new Map();
|
|
@@ -1730,6 +1813,11 @@ export class Document {
|
|
|
1730
1813
|
resultXml = resultXml.replace('</w:styles>', `${newStyleXml}\n</w:styles>`);
|
|
1731
1814
|
}
|
|
1732
1815
|
}
|
|
1816
|
+
for (const styleId of removedStyleIds) {
|
|
1817
|
+
const escapedStyleId = styleId.replace(/[.*+?^${}()|[\]\\"]/g, '\\$&');
|
|
1818
|
+
const removedPattern = new RegExp(`\\s*<w:style[^>]*\\sw:styleId="${escapedStyleId}"[^>]*>[\\s\\S]*?</w:style>`);
|
|
1819
|
+
resultXml = resultXml.replace(removedPattern, '');
|
|
1820
|
+
}
|
|
1733
1821
|
return resultXml;
|
|
1734
1822
|
}
|
|
1735
1823
|
updateNumberingXml() {
|
|
@@ -1928,8 +2016,14 @@ export class Document {
|
|
|
1928
2016
|
xml = xml.replace(/<w:revisionView\b[^>]*>[\s\S]*?<\/w:revisionView>/g, '');
|
|
1929
2017
|
let trackBlock = '';
|
|
1930
2018
|
const view = this.revisionViewSettings;
|
|
1931
|
-
if (!view.showInsertionsAndDeletions ||
|
|
1932
|
-
|
|
2019
|
+
if (!view.showInsertionsAndDeletions ||
|
|
2020
|
+
!view.showFormatting ||
|
|
2021
|
+
!view.showInkAnnotations ||
|
|
2022
|
+
view.showMarkup === false ||
|
|
2023
|
+
view.showComments === false) {
|
|
2024
|
+
const markupAttr = view.showMarkup === false ? ' w:markup="0"' : '';
|
|
2025
|
+
const commentsAttr = view.showComments === false ? ' w:comments="0"' : '';
|
|
2026
|
+
trackBlock += `\n <w:revisionView w:insDel="${view.showInsertionsAndDeletions ? '1' : '0'}" w:formatting="${view.showFormatting ? '1' : '0'}" w:inkAnnotations="${view.showInkAnnotations ? '1' : '0'}"${markupAttr}${commentsAttr}/>`;
|
|
1933
2027
|
}
|
|
1934
2028
|
if (this.trackChangesEnabled) {
|
|
1935
2029
|
trackBlock += '\n <w:trackRevisions/>';
|
|
@@ -1965,6 +2059,8 @@ export class Document {
|
|
|
1965
2059
|
const prot = this.documentProtection;
|
|
1966
2060
|
const esc = XMLBuilder.escapeXmlAttribute;
|
|
1967
2061
|
let protXml = `\n <w:documentProtection w:edit="${esc(prot.edit)}" w:enforcement="${prot.enforcement ? '1' : '0'}"`;
|
|
2062
|
+
if (prot.formatting !== undefined)
|
|
2063
|
+
protXml += ` w:formatting="${prot.formatting ? '1' : '0'}"`;
|
|
1968
2064
|
if (prot.cryptProviderType)
|
|
1969
2065
|
protXml += ` w:cryptProviderType="${esc(prot.cryptProviderType)}"`;
|
|
1970
2066
|
if (prot.cryptAlgorithmClass)
|
|
@@ -1979,6 +2075,12 @@ export class Document {
|
|
|
1979
2075
|
protXml += ` w:hash="${esc(prot.hash)}"`;
|
|
1980
2076
|
if (prot.salt)
|
|
1981
2077
|
protXml += ` w:salt="${esc(prot.salt)}"`;
|
|
2078
|
+
if (prot.algorithmName)
|
|
2079
|
+
protXml += ` w:algorithmName="${esc(prot.algorithmName)}"`;
|
|
2080
|
+
if (prot.hashValue)
|
|
2081
|
+
protXml += ` w:hashValue="${esc(prot.hashValue)}"`;
|
|
2082
|
+
if (prot.saltValue)
|
|
2083
|
+
protXml += ` w:saltValue="${esc(prot.saltValue)}"`;
|
|
1982
2084
|
protXml += '/>';
|
|
1983
2085
|
if (/<w:autoFormatOverride\b/.test(xml)) {
|
|
1984
2086
|
xml = xml.replace(/<w:autoFormatOverride\b/, protXml + '\n <w:autoFormatOverride');
|
|
@@ -2732,6 +2834,18 @@ export class Document {
|
|
|
2732
2834
|
}
|
|
2733
2835
|
}
|
|
2734
2836
|
}
|
|
2837
|
+
for (const style of this.stylesManager.getAllStyles()) {
|
|
2838
|
+
const styleNumId = style.getProperties().numPr?.numId;
|
|
2839
|
+
if (styleNumId !== undefined) {
|
|
2840
|
+
usedNumIds.add(styleNumId);
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
for (const filePath of [DOCX_PATHS.STYLES, 'word/comments.xml']) {
|
|
2844
|
+
const xml = this.zipHandler.getFileAsString(filePath);
|
|
2845
|
+
if (xml) {
|
|
2846
|
+
this.collectNumIdsFromXml(xml, usedNumIds);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2735
2849
|
this.numberingManager.cleanupUnusedNumbering(usedNumIds);
|
|
2736
2850
|
}
|
|
2737
2851
|
validateNumberingReferences() {
|
|
@@ -2833,7 +2947,67 @@ export class Document {
|
|
|
2833
2947
|
maxRevId = rev.getId();
|
|
2834
2948
|
}
|
|
2835
2949
|
const registeredSet = new Set(existingRevisions);
|
|
2836
|
-
let
|
|
2950
|
+
let maxPreservedDocPrId = 0;
|
|
2951
|
+
const collectPreservedDocPrIds = (rawXml) => {
|
|
2952
|
+
if (!rawXml || !rawXml.includes('wp:docPr'))
|
|
2953
|
+
return;
|
|
2954
|
+
const docPrPattern = /<wp:docPr\b[^>]*\bid="(\d+)"/g;
|
|
2955
|
+
let match;
|
|
2956
|
+
while ((match = docPrPattern.exec(rawXml)) !== null) {
|
|
2957
|
+
const id = parseInt(match[1], 10);
|
|
2958
|
+
if (id > maxPreservedDocPrId)
|
|
2959
|
+
maxPreservedDocPrId = id;
|
|
2960
|
+
}
|
|
2961
|
+
};
|
|
2962
|
+
const collectFromRun = (run) => {
|
|
2963
|
+
if (run instanceof ImageRun) {
|
|
2964
|
+
collectPreservedDocPrIds(run.getRawRunXml());
|
|
2965
|
+
return;
|
|
2966
|
+
}
|
|
2967
|
+
for (const contentItem of run.getContent()) {
|
|
2968
|
+
collectPreservedDocPrIds(contentItem.rawXml);
|
|
2969
|
+
}
|
|
2970
|
+
};
|
|
2971
|
+
const collectFromParagraph = (para) => {
|
|
2972
|
+
for (const item of para.getContent()) {
|
|
2973
|
+
if (item instanceof Revision) {
|
|
2974
|
+
for (const revItem of item.getContent()) {
|
|
2975
|
+
if (revItem instanceof Run)
|
|
2976
|
+
collectFromRun(revItem);
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
else if (item instanceof Run) {
|
|
2980
|
+
collectFromRun(item);
|
|
2981
|
+
}
|
|
2982
|
+
else if (item instanceof PreservedElement) {
|
|
2983
|
+
collectPreservedDocPrIds(item.getRawXml());
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
for (const element of this.bodyElements) {
|
|
2988
|
+
if (element instanceof Paragraph) {
|
|
2989
|
+
collectFromParagraph(element);
|
|
2990
|
+
}
|
|
2991
|
+
else if (element instanceof Table) {
|
|
2992
|
+
for (const row of element.getRows()) {
|
|
2993
|
+
for (const cell of row.getCells()) {
|
|
2994
|
+
for (const para of cell.getParagraphs()) {
|
|
2995
|
+
collectFromParagraph(para);
|
|
2996
|
+
}
|
|
2997
|
+
for (const nested of cell.getRawNestedContent()) {
|
|
2998
|
+
collectPreservedDocPrIds(nested.xml);
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
else {
|
|
3004
|
+
const passthrough = element;
|
|
3005
|
+
if (typeof passthrough.getRawXml === 'function') {
|
|
3006
|
+
collectPreservedDocPrIds(passthrough.getRawXml());
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
let docPrId = maxPreservedDocPrId + 1;
|
|
2837
3011
|
const existingParaIds = new Set();
|
|
2838
3012
|
const paragraphsNeedingIds = [];
|
|
2839
3013
|
const generateUniqueParaId = () => {
|
|
@@ -2865,6 +3039,13 @@ export class Document {
|
|
|
2865
3039
|
else if (item instanceof ImageRun) {
|
|
2866
3040
|
item.getImageElement().setDocPrId(docPrId++);
|
|
2867
3041
|
}
|
|
3042
|
+
else if (item instanceof Revision) {
|
|
3043
|
+
for (const revItem of item.getContent()) {
|
|
3044
|
+
if (revItem instanceof ImageRun) {
|
|
3045
|
+
revItem.getImageElement().setDocPrId(docPrId++);
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
2868
3049
|
}
|
|
2869
3050
|
if (para.formatting.paraId) {
|
|
2870
3051
|
existingParaIds.add(para.formatting.paraId);
|
|
@@ -3154,6 +3335,7 @@ export class Document {
|
|
|
3154
3335
|
numLevel.setLeftIndent(720 * (levelIndex + 1));
|
|
3155
3336
|
numLevel.setHangingIndent(360);
|
|
3156
3337
|
}
|
|
3338
|
+
this.numberingManager.markAbstractNumberingModified(abstractNumId);
|
|
3157
3339
|
this.applyFormattingToListParagraphs(instance.getNumId());
|
|
3158
3340
|
count++;
|
|
3159
3341
|
}
|
|
@@ -3180,6 +3362,7 @@ export class Document {
|
|
|
3180
3362
|
numLevel.setHangingIndent(360);
|
|
3181
3363
|
numLevel.setAlignment('left');
|
|
3182
3364
|
}
|
|
3365
|
+
this.numberingManager.markAbstractNumberingModified(abstractNumId);
|
|
3183
3366
|
this.applyFormattingToListParagraphs(instance.getNumId());
|
|
3184
3367
|
count++;
|
|
3185
3368
|
}
|
|
@@ -5002,39 +5185,39 @@ export class Document {
|
|
|
5002
5185
|
return this;
|
|
5003
5186
|
}
|
|
5004
5187
|
setHeader(header) {
|
|
5005
|
-
const relationship = this.relationshipManager.addHeader(
|
|
5188
|
+
const relationship = this.relationshipManager.addHeader(this.headerFooterManager.peekHeaderFilename(header));
|
|
5006
5189
|
this.headerFooterManager.registerHeader(header, relationship.getId());
|
|
5007
5190
|
this.section.setHeaderReference('default', relationship.getId());
|
|
5008
5191
|
return this;
|
|
5009
5192
|
}
|
|
5010
5193
|
setFirstPageHeader(header) {
|
|
5011
5194
|
this.section.setTitlePage(true);
|
|
5012
|
-
const relationship = this.relationshipManager.addHeader(
|
|
5195
|
+
const relationship = this.relationshipManager.addHeader(this.headerFooterManager.peekHeaderFilename(header));
|
|
5013
5196
|
this.headerFooterManager.registerHeader(header, relationship.getId());
|
|
5014
5197
|
this.section.setHeaderReference('first', relationship.getId());
|
|
5015
5198
|
return this;
|
|
5016
5199
|
}
|
|
5017
5200
|
setEvenPageHeader(header) {
|
|
5018
|
-
const relationship = this.relationshipManager.addHeader(
|
|
5201
|
+
const relationship = this.relationshipManager.addHeader(this.headerFooterManager.peekHeaderFilename(header));
|
|
5019
5202
|
this.headerFooterManager.registerHeader(header, relationship.getId());
|
|
5020
5203
|
this.section.setHeaderReference('even', relationship.getId());
|
|
5021
5204
|
return this;
|
|
5022
5205
|
}
|
|
5023
5206
|
setFooter(footer) {
|
|
5024
|
-
const relationship = this.relationshipManager.addFooter(
|
|
5207
|
+
const relationship = this.relationshipManager.addFooter(this.headerFooterManager.peekFooterFilename(footer));
|
|
5025
5208
|
this.headerFooterManager.registerFooter(footer, relationship.getId());
|
|
5026
5209
|
this.section.setFooterReference('default', relationship.getId());
|
|
5027
5210
|
return this;
|
|
5028
5211
|
}
|
|
5029
5212
|
setFirstPageFooter(footer) {
|
|
5030
5213
|
this.section.setTitlePage(true);
|
|
5031
|
-
const relationship = this.relationshipManager.addFooter(
|
|
5214
|
+
const relationship = this.relationshipManager.addFooter(this.headerFooterManager.peekFooterFilename(footer));
|
|
5032
5215
|
this.headerFooterManager.registerFooter(footer, relationship.getId());
|
|
5033
5216
|
this.section.setFooterReference('first', relationship.getId());
|
|
5034
5217
|
return this;
|
|
5035
5218
|
}
|
|
5036
5219
|
setEvenPageFooter(footer) {
|
|
5037
|
-
const relationship = this.relationshipManager.addFooter(
|
|
5220
|
+
const relationship = this.relationshipManager.addFooter(this.headerFooterManager.peekFooterFilename(footer));
|
|
5038
5221
|
this.headerFooterManager.registerFooter(footer, relationship.getId());
|
|
5039
5222
|
this.section.setFooterReference('even', relationship.getId());
|
|
5040
5223
|
return this;
|
|
@@ -5180,6 +5363,20 @@ export class Document {
|
|
|
5180
5363
|
}
|
|
5181
5364
|
}
|
|
5182
5365
|
this.removeCommentCompanionFiles();
|
|
5366
|
+
const extendedXml = this.commentManager.generateCommentsExtendedXml();
|
|
5367
|
+
if (extendedXml) {
|
|
5368
|
+
this.zipHandler.addFile(DOCX_PATHS.COMMENTS_EXTENDED, extendedXml);
|
|
5369
|
+
const hasExtendedRel = this.relationshipManager
|
|
5370
|
+
.getAllRelationships()
|
|
5371
|
+
.some((rel) => rel.getTarget() === 'commentsExtended.xml');
|
|
5372
|
+
if (!hasExtendedRel) {
|
|
5373
|
+
this.relationshipManager.addRelationship(Relationship.create({
|
|
5374
|
+
id: this.relationshipManager.generateId(),
|
|
5375
|
+
type: 'http://schemas.microsoft.com/office/2011/relationships/commentsExtended',
|
|
5376
|
+
target: 'commentsExtended.xml',
|
|
5377
|
+
}));
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5183
5380
|
}
|
|
5184
5381
|
else if (this._originalCommentsXml) {
|
|
5185
5382
|
this.zipHandler.addFile('word/comments.xml', this._originalCommentsXml);
|
|
@@ -5217,7 +5414,8 @@ export class Document {
|
|
|
5217
5414
|
}
|
|
5218
5415
|
}
|
|
5219
5416
|
saveFootnotes() {
|
|
5220
|
-
if (this._footnotesModified ||
|
|
5417
|
+
if (this._footnotesModified ||
|
|
5418
|
+
(!this._originalFootnotesXml && this.footnoteManager.getCount() > 0)) {
|
|
5221
5419
|
const xml = this.footnoteManager.generateFootnotesXml();
|
|
5222
5420
|
this.zipHandler.addFile(DOCX_PATHS.FOOTNOTES, xml);
|
|
5223
5421
|
const existingRels = this.relationshipManager.getRelationshipsByType(RelationshipType.FOOTNOTES);
|
|
@@ -5235,7 +5433,8 @@ export class Document {
|
|
|
5235
5433
|
}
|
|
5236
5434
|
}
|
|
5237
5435
|
saveEndnotes() {
|
|
5238
|
-
if (this._endnotesModified ||
|
|
5436
|
+
if (this._endnotesModified ||
|
|
5437
|
+
(!this._originalEndnotesXml && this.endnoteManager.getCount() > 0)) {
|
|
5239
5438
|
const xml = this.endnoteManager.generateEndnotesXml();
|
|
5240
5439
|
this.zipHandler.addFile(DOCX_PATHS.ENDNOTES, xml);
|
|
5241
5440
|
const existingRels = this.relationshipManager.getRelationshipsByType(RelationshipType.ENDNOTES);
|
|
@@ -5304,7 +5503,12 @@ export class Document {
|
|
|
5304
5503
|
xml += '</Relationships>';
|
|
5305
5504
|
this.zipHandler.addFile(relsPath, xml);
|
|
5306
5505
|
for (const rel of hyperlinkRels) {
|
|
5307
|
-
this.relationshipManager.
|
|
5506
|
+
const mainRel = this.relationshipManager.getRelationship(rel.id);
|
|
5507
|
+
if (mainRel &&
|
|
5508
|
+
mainRel.getType() === RelationshipType.HYPERLINK &&
|
|
5509
|
+
mainRel.getTarget() === rel.url) {
|
|
5510
|
+
this.relationshipManager.removeRelationship(rel.id);
|
|
5511
|
+
}
|
|
5308
5512
|
}
|
|
5309
5513
|
}
|
|
5310
5514
|
}
|
|
@@ -5422,13 +5626,25 @@ export class Document {
|
|
|
5422
5626
|
parseContentTypes(xml) {
|
|
5423
5627
|
const defaults = new Set();
|
|
5424
5628
|
const overrides = new Set();
|
|
5425
|
-
const
|
|
5426
|
-
|
|
5427
|
-
|
|
5629
|
+
const readAttr = (tag, name) => {
|
|
5630
|
+
const match = tag.match(new RegExp(`(?:^|\\s)${name}\\s*=\\s*("([^"]*)"|'([^']*)')`));
|
|
5631
|
+
if (!match)
|
|
5632
|
+
return undefined;
|
|
5633
|
+
return XMLBuilder.unescapeXml(match[2] ?? match[3] ?? '');
|
|
5634
|
+
};
|
|
5635
|
+
for (const tagMatch of xml.matchAll(/<Default\b[^>]*>/g)) {
|
|
5636
|
+
const ext = readAttr(tagMatch[0], 'Extension');
|
|
5637
|
+
const contentType = readAttr(tagMatch[0], 'ContentType');
|
|
5638
|
+
if (ext && contentType) {
|
|
5639
|
+
defaults.add(`${ext}|${contentType}`);
|
|
5640
|
+
}
|
|
5428
5641
|
}
|
|
5429
|
-
const
|
|
5430
|
-
|
|
5431
|
-
|
|
5642
|
+
for (const tagMatch of xml.matchAll(/<Override\b[^>]*>/g)) {
|
|
5643
|
+
const partName = readAttr(tagMatch[0], 'PartName');
|
|
5644
|
+
const contentType = readAttr(tagMatch[0], 'ContentType');
|
|
5645
|
+
if (partName && contentType) {
|
|
5646
|
+
overrides.add(`${partName}|${contentType}`);
|
|
5647
|
+
}
|
|
5432
5648
|
}
|
|
5433
5649
|
return { defaults, overrides };
|
|
5434
5650
|
}
|
|
@@ -5748,9 +5964,7 @@ export class Document {
|
|
|
5748
5964
|
}
|
|
5749
5965
|
if (element && typeof element.getContent === 'function') {
|
|
5750
5966
|
for (const item of element.getContent()) {
|
|
5751
|
-
if (item &&
|
|
5752
|
-
typeof item._setTrackingContext === 'function' &&
|
|
5753
|
-
typeof item.getInstruction === 'function') {
|
|
5967
|
+
if (item && typeof item._setTrackingContext === 'function') {
|
|
5754
5968
|
item._setTrackingContext(this.trackingContext);
|
|
5755
5969
|
}
|
|
5756
5970
|
}
|
|
@@ -5917,6 +6131,7 @@ export class Document {
|
|
|
5917
6131
|
updated.size = sizeInPoints;
|
|
5918
6132
|
}
|
|
5919
6133
|
normalStyle.setRunFormatting(updated);
|
|
6134
|
+
this.stylesManager.addStyle(normalStyle);
|
|
5920
6135
|
return this;
|
|
5921
6136
|
}
|
|
5922
6137
|
setDefaultFontSize(sizeInPoints) {
|
|
@@ -5932,6 +6147,7 @@ export class Document {
|
|
|
5932
6147
|
}
|
|
5933
6148
|
const existing = normalStyle.getRunFormatting() ?? {};
|
|
5934
6149
|
normalStyle.setRunFormatting({ ...existing, size: sizeInPoints });
|
|
6150
|
+
this.stylesManager.addStyle(normalStyle);
|
|
5935
6151
|
return this;
|
|
5936
6152
|
}
|
|
5937
6153
|
getUpdateFields() {
|
|
@@ -6123,6 +6339,40 @@ export class Document {
|
|
|
6123
6339
|
this.endnoteManager.clear();
|
|
6124
6340
|
this._endnotesModified = true;
|
|
6125
6341
|
}
|
|
6342
|
+
removeFootnote(id) {
|
|
6343
|
+
const removed = this.footnoteManager.removeFootnote(id);
|
|
6344
|
+
if (removed) {
|
|
6345
|
+
this._footnotesModified = true;
|
|
6346
|
+
this.removeNoteReferenceRuns('footnoteReference', id);
|
|
6347
|
+
}
|
|
6348
|
+
return removed;
|
|
6349
|
+
}
|
|
6350
|
+
removeEndnote(id) {
|
|
6351
|
+
const removed = this.endnoteManager.removeEndnote(id);
|
|
6352
|
+
if (removed) {
|
|
6353
|
+
this._endnotesModified = true;
|
|
6354
|
+
this.removeNoteReferenceRuns('endnoteReference', id);
|
|
6355
|
+
}
|
|
6356
|
+
return removed;
|
|
6357
|
+
}
|
|
6358
|
+
removeNoteReferenceRuns(refType, id) {
|
|
6359
|
+
for (const para of this.getAllParagraphs()) {
|
|
6360
|
+
const content = para.getContent();
|
|
6361
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
6362
|
+
const item = content[i];
|
|
6363
|
+
if (!(item instanceof Run)) {
|
|
6364
|
+
continue;
|
|
6365
|
+
}
|
|
6366
|
+
const matches = item
|
|
6367
|
+
.getContent()
|
|
6368
|
+
.some((c) => c.type === refType &&
|
|
6369
|
+
(refType === 'footnoteReference' ? c.footnoteId === id : c.endnoteId === id));
|
|
6370
|
+
if (matches) {
|
|
6371
|
+
para.removeContentAt(i);
|
|
6372
|
+
}
|
|
6373
|
+
}
|
|
6374
|
+
}
|
|
6375
|
+
}
|
|
6126
6376
|
addCommentToParagraph(paragraph, commentOrAuthor, content, initials) {
|
|
6127
6377
|
const comment = typeof commentOrAuthor === 'string'
|
|
6128
6378
|
? this.createComment(commentOrAuthor, content, initials)
|
|
@@ -6173,12 +6423,52 @@ export class Document {
|
|
|
6173
6423
|
return this.commentManager.hasReplies(commentId);
|
|
6174
6424
|
}
|
|
6175
6425
|
removeComment(id) {
|
|
6426
|
+
const replyIds = this.commentManager.getReplies(id).map((reply) => reply.getId());
|
|
6176
6427
|
const removed = this.commentManager.removeComment(id);
|
|
6177
6428
|
if (removed) {
|
|
6429
|
+
this.removeCommentAnchors([id, ...replyIds]);
|
|
6178
6430
|
this._commentsModified = true;
|
|
6179
6431
|
}
|
|
6180
6432
|
return removed;
|
|
6181
6433
|
}
|
|
6434
|
+
removeCommentAnchors(commentIds) {
|
|
6435
|
+
const strip = (paragraphs) => {
|
|
6436
|
+
let removed = false;
|
|
6437
|
+
for (const paragraph of paragraphs) {
|
|
6438
|
+
for (const commentId of commentIds) {
|
|
6439
|
+
if (paragraph.removeCommentAnchor(commentId)) {
|
|
6440
|
+
removed = true;
|
|
6441
|
+
}
|
|
6442
|
+
}
|
|
6443
|
+
}
|
|
6444
|
+
return removed;
|
|
6445
|
+
};
|
|
6446
|
+
strip(this.getAllParagraphs());
|
|
6447
|
+
for (const entry of this.headerFooterManager.getAllHeaders()) {
|
|
6448
|
+
strip(this.extractParagraphsFromElements(entry.header.getElements()));
|
|
6449
|
+
}
|
|
6450
|
+
for (const entry of this.headerFooterManager.getAllFooters()) {
|
|
6451
|
+
strip(this.extractParagraphsFromElements(entry.footer.getElements()));
|
|
6452
|
+
}
|
|
6453
|
+
let footnotesChanged = false;
|
|
6454
|
+
for (const footnote of this.footnoteManager.getAllFootnotes()) {
|
|
6455
|
+
if (strip(footnote.getParagraphs())) {
|
|
6456
|
+
footnotesChanged = true;
|
|
6457
|
+
}
|
|
6458
|
+
}
|
|
6459
|
+
if (footnotesChanged) {
|
|
6460
|
+
this._footnotesModified = true;
|
|
6461
|
+
}
|
|
6462
|
+
let endnotesChanged = false;
|
|
6463
|
+
for (const endnote of this.endnoteManager.getAllEndnotes()) {
|
|
6464
|
+
if (strip(endnote.getParagraphs())) {
|
|
6465
|
+
endnotesChanged = true;
|
|
6466
|
+
}
|
|
6467
|
+
}
|
|
6468
|
+
if (endnotesChanged) {
|
|
6469
|
+
this._endnotesModified = true;
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6182
6472
|
hasNoRevisions() {
|
|
6183
6473
|
return this.revisionManager.isEmpty();
|
|
6184
6474
|
}
|
|
@@ -6434,8 +6724,8 @@ export class Document {
|
|
|
6434
6724
|
this.parser.clearParseErrors();
|
|
6435
6725
|
this.stylesManager.clear();
|
|
6436
6726
|
this.numberingManager.clear();
|
|
6437
|
-
this.imageManager.clear();
|
|
6438
6727
|
this.imageManager.releaseAllImageData();
|
|
6728
|
+
this.imageManager.clear();
|
|
6439
6729
|
this.relationshipManager.clear();
|
|
6440
6730
|
this.headerFooterManager.clear();
|
|
6441
6731
|
this.bookmarkManager.clear();
|
|
@@ -6449,6 +6739,7 @@ export class Document {
|
|
|
6449
6739
|
this._originalNumberingXml = undefined;
|
|
6450
6740
|
this._originalSettingsXml = undefined;
|
|
6451
6741
|
this._originalAppPropsXml = undefined;
|
|
6742
|
+
this._originalCorePropsXml = undefined;
|
|
6452
6743
|
this._originalFootnotesXml = undefined;
|
|
6453
6744
|
this._originalEndnotesXml = undefined;
|
|
6454
6745
|
this._originalCommentsXml = undefined;
|
|
@@ -6457,6 +6748,7 @@ export class Document {
|
|
|
6457
6748
|
this._originalContentTypes = undefined;
|
|
6458
6749
|
this._settingsModified = false;
|
|
6459
6750
|
this._appPropsModified = false;
|
|
6751
|
+
this._corePropsModified = false;
|
|
6460
6752
|
this._footnotesModified = false;
|
|
6461
6753
|
this._endnotesModified = false;
|
|
6462
6754
|
this._originalWebSettingsXml = undefined;
|
|
@@ -7014,7 +7306,7 @@ export class Document {
|
|
|
7014
7306
|
const matches = originalText.match(wordPattern);
|
|
7015
7307
|
if (matches) {
|
|
7016
7308
|
replacementCount += matches.length;
|
|
7017
|
-
newText = originalText.replace(wordPattern, replace);
|
|
7309
|
+
newText = originalText.replace(wordPattern, () => replace);
|
|
7018
7310
|
}
|
|
7019
7311
|
}
|
|
7020
7312
|
else {
|
|
@@ -7022,7 +7314,7 @@ export class Document {
|
|
|
7022
7314
|
const matches = originalText.match(searchPattern);
|
|
7023
7315
|
if (matches) {
|
|
7024
7316
|
replacementCount += matches.length;
|
|
7025
|
-
newText = originalText.replace(searchPattern, replace);
|
|
7317
|
+
newText = originalText.replace(searchPattern, () => replace);
|
|
7026
7318
|
}
|
|
7027
7319
|
}
|
|
7028
7320
|
if (newText !== originalText) {
|
|
@@ -7302,90 +7594,303 @@ export class Document {
|
|
|
7302
7594
|
}
|
|
7303
7595
|
toPlainText(separator = '\n') {
|
|
7304
7596
|
const paragraphs = this.getAllParagraphs();
|
|
7305
|
-
return paragraphs.map((p) => p.
|
|
7306
|
-
}
|
|
7307
|
-
toMarkdown() {
|
|
7597
|
+
return paragraphs.map((p) => p.getTextIncludingRevisions()).join(separator);
|
|
7598
|
+
}
|
|
7599
|
+
toMarkdown(options) {
|
|
7600
|
+
const ctx = {
|
|
7601
|
+
opts: {
|
|
7602
|
+
htmlFallback: options?.htmlFallback ?? true,
|
|
7603
|
+
footnotes: options?.footnotes ?? true,
|
|
7604
|
+
images: options?.images ?? true,
|
|
7605
|
+
},
|
|
7606
|
+
notes: [],
|
|
7607
|
+
noteMarkers: new Set(),
|
|
7608
|
+
};
|
|
7308
7609
|
const lines = [];
|
|
7309
7610
|
for (const element of this.bodyElements) {
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7611
|
+
this.bodyElementToMarkdown(element, ctx, lines);
|
|
7612
|
+
}
|
|
7613
|
+
while (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
7614
|
+
lines.pop();
|
|
7615
|
+
}
|
|
7616
|
+
let out = lines.join('\n');
|
|
7617
|
+
if (ctx.opts.footnotes && ctx.notes.length > 0) {
|
|
7618
|
+
const defs = ctx.notes.map((n) => `[^${n.marker}]: ${n.text}`).join('\n');
|
|
7619
|
+
out = out ? `${out}\n\n${defs}` : defs;
|
|
7620
|
+
}
|
|
7621
|
+
return out;
|
|
7622
|
+
}
|
|
7623
|
+
bodyElementToMarkdown(element, ctx, lines) {
|
|
7624
|
+
if (element instanceof Paragraph) {
|
|
7625
|
+
const md = this.paragraphToMarkdown(element, ctx);
|
|
7626
|
+
if (md !== null) {
|
|
7627
|
+
lines.push(md);
|
|
7628
|
+
lines.push('');
|
|
7316
7629
|
}
|
|
7317
|
-
|
|
7318
|
-
|
|
7630
|
+
}
|
|
7631
|
+
else if (element instanceof Table) {
|
|
7632
|
+
const tableLines = this.tableToMarkdown(element, ctx);
|
|
7633
|
+
if (tableLines.length > 0) {
|
|
7634
|
+
lines.push(...tableLines);
|
|
7319
7635
|
lines.push('');
|
|
7320
7636
|
}
|
|
7321
7637
|
}
|
|
7322
|
-
|
|
7323
|
-
|
|
7638
|
+
else if (element instanceof StructuredDocumentTag) {
|
|
7639
|
+
for (const child of element.getContent()) {
|
|
7640
|
+
this.bodyElementToMarkdown(child, ctx, lines);
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
else if (element instanceof PreservedElement) {
|
|
7644
|
+
const text = this.extractTextFromRawXml(element.getRawXml());
|
|
7645
|
+
if (text) {
|
|
7646
|
+
lines.push(this.escapeMarkdown(text));
|
|
7647
|
+
lines.push('');
|
|
7648
|
+
}
|
|
7324
7649
|
}
|
|
7325
|
-
return lines.join('\n');
|
|
7326
7650
|
}
|
|
7327
|
-
paragraphToMarkdown(para) {
|
|
7328
|
-
const
|
|
7329
|
-
|
|
7651
|
+
paragraphToMarkdown(para, ctx) {
|
|
7652
|
+
const inline = this.paragraphContentToMarkdown(para, ctx);
|
|
7653
|
+
const hasNumbering = para.hasNumbering();
|
|
7654
|
+
if (!inline && !hasNumbering)
|
|
7330
7655
|
return null;
|
|
7331
7656
|
const headingLevel = para.detectHeadingLevel();
|
|
7332
7657
|
if (headingLevel !== null && headingLevel >= 1 && headingLevel <= 6) {
|
|
7333
|
-
return '#'.repeat(headingLevel) + ' ' +
|
|
7334
|
-
}
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7658
|
+
return '#'.repeat(headingLevel) + ' ' + this.toSingleLine(inline);
|
|
7659
|
+
}
|
|
7660
|
+
const style = (para.getStyle() ?? '').toLowerCase();
|
|
7661
|
+
const isListStyle = style.includes('listbullet') ||
|
|
7662
|
+
style.includes('list bullet') ||
|
|
7663
|
+
style.includes('listnumber') ||
|
|
7664
|
+
style.includes('list number');
|
|
7665
|
+
if (hasNumbering || isListStyle) {
|
|
7666
|
+
const level = para.getNumbering()?.level ?? 0;
|
|
7667
|
+
const indent = ' '.repeat(Math.max(0, level));
|
|
7668
|
+
const marker = this.isOrderedList(para) ? '1.' : '-';
|
|
7669
|
+
return `${indent}${marker} ${this.toSingleLine(inline)}`;
|
|
7670
|
+
}
|
|
7671
|
+
if (style.includes('quote')) {
|
|
7672
|
+
return this.toSingleLine(inline)
|
|
7673
|
+
.split('\n')
|
|
7674
|
+
.map((l) => `> ${l}`)
|
|
7675
|
+
.join('\n');
|
|
7676
|
+
}
|
|
7677
|
+
return inline;
|
|
7678
|
+
}
|
|
7679
|
+
isOrderedList(para) {
|
|
7680
|
+
const numbering = para.getNumbering();
|
|
7681
|
+
if (numbering) {
|
|
7682
|
+
const instance = this.numberingManager.getInstance(numbering.numId);
|
|
7683
|
+
if (instance) {
|
|
7684
|
+
const abstract = this.numberingManager.getAbstractNumbering(instance.getAbstractNumId());
|
|
7685
|
+
const levelDef = abstract?.getLevel(numbering.level);
|
|
7686
|
+
const format = levelDef?.getFormat();
|
|
7687
|
+
if (format)
|
|
7688
|
+
return format !== 'bullet';
|
|
7689
|
+
}
|
|
7339
7690
|
}
|
|
7340
|
-
|
|
7691
|
+
const style = (para.getStyle() ?? '').toLowerCase();
|
|
7692
|
+
if (style.includes('bullet'))
|
|
7693
|
+
return false;
|
|
7694
|
+
if (style.includes('number'))
|
|
7695
|
+
return true;
|
|
7696
|
+
return true;
|
|
7697
|
+
}
|
|
7698
|
+
paragraphContentToMarkdown(para, ctx) {
|
|
7699
|
+
return this.inlineContentToMarkdown(para.getContent(), ctx);
|
|
7341
7700
|
}
|
|
7342
|
-
|
|
7701
|
+
inlineContentToMarkdown(items, ctx) {
|
|
7343
7702
|
const parts = [];
|
|
7344
|
-
for (const item of
|
|
7345
|
-
if (item instanceof
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
if (fmt.bold && fmt.italic) {
|
|
7352
|
-
md = `***${md}***`;
|
|
7353
|
-
}
|
|
7354
|
-
else if (fmt.bold) {
|
|
7355
|
-
md = `**${md}**`;
|
|
7356
|
-
}
|
|
7357
|
-
else if (fmt.italic) {
|
|
7358
|
-
md = `*${md}*`;
|
|
7703
|
+
for (const item of items) {
|
|
7704
|
+
if (item instanceof ImageRun) {
|
|
7705
|
+
if (ctx.opts.images) {
|
|
7706
|
+
const image = item.getImageElement();
|
|
7707
|
+
const alt = this.escapeMarkdown(image.getAltText() || 'image');
|
|
7708
|
+
const src = image.getRelationshipId() ?? 'image';
|
|
7709
|
+
parts.push(``);
|
|
7359
7710
|
}
|
|
7360
|
-
|
|
7361
|
-
|
|
7711
|
+
}
|
|
7712
|
+
else if (item instanceof Run) {
|
|
7713
|
+
parts.push(this.runToMarkdown(item, ctx));
|
|
7714
|
+
}
|
|
7715
|
+
else if (item instanceof Hyperlink) {
|
|
7716
|
+
const runs = item.getRuns();
|
|
7717
|
+
let label = runs.length > 0
|
|
7718
|
+
? runs.map((r) => this.runToMarkdown(r, ctx, true)).join('')
|
|
7719
|
+
: this.escapeMarkdown(item.getText());
|
|
7720
|
+
if (!label)
|
|
7721
|
+
label = this.escapeMarkdown(item.getText());
|
|
7722
|
+
let url = item.getUrl() ?? '';
|
|
7723
|
+
const anchor = item.getAnchor();
|
|
7724
|
+
if (anchor)
|
|
7725
|
+
url = url ? `${url}#${anchor}` : `#${anchor}`;
|
|
7726
|
+
parts.push(`[${label}](${url})`);
|
|
7727
|
+
}
|
|
7728
|
+
else if (item instanceof Revision) {
|
|
7729
|
+
const inner = this.inlineContentToMarkdown(item.getContent(), ctx);
|
|
7730
|
+
if (!inner)
|
|
7731
|
+
continue;
|
|
7732
|
+
const type = item.getType();
|
|
7733
|
+
if (type === 'delete' || type === 'moveFrom') {
|
|
7734
|
+
parts.push(ctx.opts.htmlFallback ? `<del>${inner}</del>` : `~~${inner}~~`);
|
|
7362
7735
|
}
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
md = `\`${runText}\``;
|
|
7736
|
+
else {
|
|
7737
|
+
parts.push(inner);
|
|
7366
7738
|
}
|
|
7367
|
-
parts.push(md);
|
|
7368
7739
|
}
|
|
7369
|
-
else if (item instanceof
|
|
7370
|
-
const
|
|
7371
|
-
|
|
7372
|
-
|
|
7740
|
+
else if (item instanceof ComplexField) {
|
|
7741
|
+
const result = item.getResult();
|
|
7742
|
+
if (result)
|
|
7743
|
+
parts.push(this.escapeMarkdown(result));
|
|
7744
|
+
}
|
|
7745
|
+
else if (item instanceof Field) {
|
|
7746
|
+
const result = item.getCachedResult();
|
|
7747
|
+
if (result)
|
|
7748
|
+
parts.push(this.escapeMarkdown(result));
|
|
7749
|
+
}
|
|
7750
|
+
else if (item instanceof TextBox) {
|
|
7751
|
+
const text = item
|
|
7752
|
+
.getParagraphs()
|
|
7753
|
+
.map((p) => this.paragraphContentToMarkdown(p, ctx))
|
|
7754
|
+
.filter((s) => s !== '')
|
|
7755
|
+
.join(' ');
|
|
7756
|
+
if (text)
|
|
7757
|
+
parts.push(text);
|
|
7758
|
+
}
|
|
7759
|
+
else if (item instanceof Shape) {
|
|
7760
|
+
const text = item.getText();
|
|
7761
|
+
if (text)
|
|
7762
|
+
parts.push(this.escapeMarkdown(text));
|
|
7763
|
+
}
|
|
7764
|
+
else if (item instanceof PreservedElement) {
|
|
7765
|
+
const type = item.getElementType();
|
|
7766
|
+
if (!type.startsWith('w:comment')) {
|
|
7767
|
+
const text = this.extractTextFromRawXml(item.getRawXml());
|
|
7768
|
+
if (text)
|
|
7769
|
+
parts.push(this.escapeMarkdown(text));
|
|
7770
|
+
}
|
|
7373
7771
|
}
|
|
7374
7772
|
}
|
|
7375
7773
|
return parts.join('');
|
|
7376
7774
|
}
|
|
7377
|
-
|
|
7378
|
-
const
|
|
7379
|
-
|
|
7775
|
+
runToMarkdown(run, ctx, inLink = false) {
|
|
7776
|
+
const fmt = run.getFormatting();
|
|
7777
|
+
const isMono = !!(fmt.font &&
|
|
7778
|
+
/^(courier|consolas|monaco|menlo|source code|fira code|jetbrains mono)/i.test(fmt.font));
|
|
7779
|
+
const escape = (s) => (isMono ? s : this.escapeMarkdown(s));
|
|
7780
|
+
const segments = [];
|
|
7781
|
+
const markers = [];
|
|
7782
|
+
for (const content of run.getContent()) {
|
|
7783
|
+
switch (content.type) {
|
|
7784
|
+
case 'text':
|
|
7785
|
+
case 'instructionText':
|
|
7786
|
+
segments.push(escape(content.value ?? ''));
|
|
7787
|
+
break;
|
|
7788
|
+
case 'tab':
|
|
7789
|
+
segments.push('\t');
|
|
7790
|
+
break;
|
|
7791
|
+
case 'carriageReturn':
|
|
7792
|
+
segments.push('\n');
|
|
7793
|
+
break;
|
|
7794
|
+
case 'break':
|
|
7795
|
+
if (content.breakType !== 'page' && content.breakType !== 'column') {
|
|
7796
|
+
segments.push(ctx.opts.htmlFallback ? '<br>' : '\n');
|
|
7797
|
+
}
|
|
7798
|
+
break;
|
|
7799
|
+
case 'noBreakHyphen':
|
|
7800
|
+
segments.push('‑');
|
|
7801
|
+
break;
|
|
7802
|
+
case 'symbol':
|
|
7803
|
+
if (content.symbolChar) {
|
|
7804
|
+
const code = parseInt(content.symbolChar, 16);
|
|
7805
|
+
if (!Number.isNaN(code))
|
|
7806
|
+
segments.push(escape(String.fromCharCode(code)));
|
|
7807
|
+
}
|
|
7808
|
+
break;
|
|
7809
|
+
case 'footnoteReference':
|
|
7810
|
+
if (ctx.opts.footnotes && content.footnoteId !== undefined) {
|
|
7811
|
+
markers.push(this.noteMarker(content.footnoteId, 'fn', ctx));
|
|
7812
|
+
}
|
|
7813
|
+
break;
|
|
7814
|
+
case 'endnoteReference':
|
|
7815
|
+
if (ctx.opts.footnotes && content.endnoteId !== undefined) {
|
|
7816
|
+
markers.push(this.noteMarker(content.endnoteId, 'en', ctx));
|
|
7817
|
+
}
|
|
7818
|
+
break;
|
|
7819
|
+
default:
|
|
7820
|
+
break;
|
|
7821
|
+
}
|
|
7822
|
+
}
|
|
7823
|
+
let text = segments.join('');
|
|
7824
|
+
if (text) {
|
|
7825
|
+
if (isMono) {
|
|
7826
|
+
text = `\`${text}\``;
|
|
7827
|
+
}
|
|
7828
|
+
if (fmt.bold && fmt.italic)
|
|
7829
|
+
text = `***${text}***`;
|
|
7830
|
+
else if (fmt.bold)
|
|
7831
|
+
text = `**${text}**`;
|
|
7832
|
+
else if (fmt.italic)
|
|
7833
|
+
text = `*${text}*`;
|
|
7834
|
+
if (fmt.strike || fmt.dstrike)
|
|
7835
|
+
text = `~~${text}~~`;
|
|
7836
|
+
if (ctx.opts.htmlFallback) {
|
|
7837
|
+
if (fmt.superscript)
|
|
7838
|
+
text = `<sup>${text}</sup>`;
|
|
7839
|
+
else if (fmt.subscript)
|
|
7840
|
+
text = `<sub>${text}</sub>`;
|
|
7841
|
+
if (fmt.highlight && fmt.highlight !== 'none')
|
|
7842
|
+
text = `<mark>${text}</mark>`;
|
|
7843
|
+
if (!inLink) {
|
|
7844
|
+
if (fmt.underline && fmt.underline !== 'none')
|
|
7845
|
+
text = `<u>${text}</u>`;
|
|
7846
|
+
if (fmt.color && fmt.color !== 'auto' && /^[0-9a-fA-F]{6}$/.test(fmt.color)) {
|
|
7847
|
+
text = `<span style="color:#${fmt.color}">${text}</span>`;
|
|
7848
|
+
}
|
|
7849
|
+
}
|
|
7850
|
+
}
|
|
7851
|
+
}
|
|
7852
|
+
return text + markers.join('');
|
|
7853
|
+
}
|
|
7854
|
+
noteMarker(id, kind, ctx) {
|
|
7855
|
+
const marker = `${kind}${id}`;
|
|
7856
|
+
if (!ctx.noteMarkers.has(marker)) {
|
|
7857
|
+
ctx.noteMarkers.add(marker);
|
|
7858
|
+
const note = kind === 'fn' ? this.footnoteManager.getFootnote(id) : this.endnoteManager.getEndnote(id);
|
|
7859
|
+
let text = '';
|
|
7860
|
+
if (note) {
|
|
7861
|
+
text = note
|
|
7862
|
+
.getParagraphs()
|
|
7863
|
+
.map((p) => this.paragraphContentToMarkdown(p, ctx))
|
|
7864
|
+
.filter((s) => s !== '')
|
|
7865
|
+
.join(' ')
|
|
7866
|
+
.replace(/\s*\n\s*/g, ' ')
|
|
7867
|
+
.trim();
|
|
7868
|
+
}
|
|
7869
|
+
ctx.notes.push({ marker, text });
|
|
7870
|
+
}
|
|
7871
|
+
return `[^${marker}]`;
|
|
7872
|
+
}
|
|
7873
|
+
tableToMarkdown(table, ctx) {
|
|
7874
|
+
const rows = table.getRows();
|
|
7875
|
+
if (rows.length === 0)
|
|
7380
7876
|
return [];
|
|
7381
|
-
const
|
|
7877
|
+
const isComplex = rows.some((row) => row
|
|
7878
|
+
.getCells()
|
|
7879
|
+
.some((cell) => (cell.getColumnSpan() ?? 1) > 1 ||
|
|
7880
|
+
cell.getVerticalMerge() !== undefined ||
|
|
7881
|
+
cell.hasNestedTables()));
|
|
7882
|
+
if (isComplex && ctx.opts.htmlFallback) {
|
|
7883
|
+
return this.tableToHtmlBlock(table);
|
|
7884
|
+
}
|
|
7885
|
+
const matrix = rows.map((row) => row.getCells().map((cell) => this.cellToMarkdown(cell, ctx)));
|
|
7886
|
+
const colCount = Math.max(...matrix.map((row) => row.length));
|
|
7382
7887
|
if (colCount === 0)
|
|
7383
7888
|
return [];
|
|
7384
|
-
const normalized =
|
|
7889
|
+
const normalized = matrix.map((row) => {
|
|
7385
7890
|
const padded = [...row];
|
|
7386
7891
|
while (padded.length < colCount)
|
|
7387
7892
|
padded.push('');
|
|
7388
|
-
return padded
|
|
7893
|
+
return padded;
|
|
7389
7894
|
});
|
|
7390
7895
|
const lines = [];
|
|
7391
7896
|
lines.push('| ' + normalized[0].join(' | ') + ' |');
|
|
@@ -7395,6 +7900,88 @@ export class Document {
|
|
|
7395
7900
|
}
|
|
7396
7901
|
return lines;
|
|
7397
7902
|
}
|
|
7903
|
+
cellToMarkdown(cell, ctx) {
|
|
7904
|
+
const text = cell
|
|
7905
|
+
.getParagraphs()
|
|
7906
|
+
.map((p) => this.paragraphContentToMarkdown(p, ctx))
|
|
7907
|
+
.filter((s) => s !== '')
|
|
7908
|
+
.join(' ');
|
|
7909
|
+
return text.replace(/\|/g, '\\|').replace(/<br>/g, ' ').replace(/\n/g, ' ').trim();
|
|
7910
|
+
}
|
|
7911
|
+
tableToHtmlBlock(table) {
|
|
7912
|
+
const rows = table.getRows();
|
|
7913
|
+
const rowCells = rows.map((row) => {
|
|
7914
|
+
let gridStart = 0;
|
|
7915
|
+
return row.getCells().map((cell) => {
|
|
7916
|
+
const span = cell.getColumnSpan() ?? 1;
|
|
7917
|
+
const entry = { cell, gridStart, span };
|
|
7918
|
+
gridStart += span;
|
|
7919
|
+
return entry;
|
|
7920
|
+
});
|
|
7921
|
+
});
|
|
7922
|
+
const html = ['<table>'];
|
|
7923
|
+
for (let ri = 0; ri < rowCells.length; ri++) {
|
|
7924
|
+
html.push('<tr>');
|
|
7925
|
+
for (const { cell, gridStart, span } of rowCells[ri]) {
|
|
7926
|
+
if (cell.getVerticalMerge() === 'continue')
|
|
7927
|
+
continue;
|
|
7928
|
+
let rowspan = 1;
|
|
7929
|
+
if (cell.getVerticalMerge() === 'restart') {
|
|
7930
|
+
for (let rj = ri + 1; rj < rowCells.length; rj++) {
|
|
7931
|
+
const below = rowCells[rj].find((e) => e.gridStart === gridStart);
|
|
7932
|
+
if (below?.cell.getVerticalMerge() === 'continue')
|
|
7933
|
+
rowspan++;
|
|
7934
|
+
else
|
|
7935
|
+
break;
|
|
7936
|
+
}
|
|
7937
|
+
}
|
|
7938
|
+
const tag = ri === 0 ? 'th' : 'td';
|
|
7939
|
+
const attrs = (span > 1 ? ` colspan="${span}"` : '') + (rowspan > 1 ? ` rowspan="${rowspan}"` : '');
|
|
7940
|
+
let content = cell
|
|
7941
|
+
.getParagraphs()
|
|
7942
|
+
.map((p) => this.paragraphContentToHTML(p))
|
|
7943
|
+
.filter((s) => s !== '')
|
|
7944
|
+
.join('<br>') || this.escapeHTML(cell.getText());
|
|
7945
|
+
if (cell.hasNestedTables()) {
|
|
7946
|
+
const nestedText = cell
|
|
7947
|
+
.getRawNestedContent()
|
|
7948
|
+
.map((n) => this.extractTextFromRawXml(n.xml))
|
|
7949
|
+
.filter((s) => s)
|
|
7950
|
+
.join(' ');
|
|
7951
|
+
if (nestedText)
|
|
7952
|
+
content += `<br>${this.escapeHTML(nestedText)}`;
|
|
7953
|
+
}
|
|
7954
|
+
html.push(`<${tag}${attrs}>${content}</${tag}>`);
|
|
7955
|
+
}
|
|
7956
|
+
html.push('</tr>');
|
|
7957
|
+
}
|
|
7958
|
+
html.push('</table>');
|
|
7959
|
+
return html;
|
|
7960
|
+
}
|
|
7961
|
+
escapeMarkdown(text) {
|
|
7962
|
+
return text.replace(/([\\`*_[\]<>])/g, '\\$1');
|
|
7963
|
+
}
|
|
7964
|
+
toSingleLine(text) {
|
|
7965
|
+
return text.replace(/<br>/g, ' ').replace(/\s*\n\s*/g, ' ');
|
|
7966
|
+
}
|
|
7967
|
+
extractTextFromRawXml(xml) {
|
|
7968
|
+
if (!xml.includes('<w:t'))
|
|
7969
|
+
return '';
|
|
7970
|
+
const parts = [];
|
|
7971
|
+
const regex = /<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g;
|
|
7972
|
+
let match;
|
|
7973
|
+
while ((match = regex.exec(xml)) !== null) {
|
|
7974
|
+
parts.push(match[1] ?? '');
|
|
7975
|
+
}
|
|
7976
|
+
return parts
|
|
7977
|
+
.join('')
|
|
7978
|
+
.replace(/</g, '<')
|
|
7979
|
+
.replace(/>/g, '>')
|
|
7980
|
+
.replace(/"/g, '"')
|
|
7981
|
+
.replace(/'/g, "'")
|
|
7982
|
+
.replace(/&/g, '&')
|
|
7983
|
+
.trim();
|
|
7984
|
+
}
|
|
7398
7985
|
toHTML(options) {
|
|
7399
7986
|
const parts = [];
|
|
7400
7987
|
let inList = null;
|
|
@@ -7485,8 +8072,12 @@ export class Document {
|
|
|
7485
8072
|
parts.push(html);
|
|
7486
8073
|
}
|
|
7487
8074
|
else if (item instanceof Hyperlink) {
|
|
7488
|
-
|
|
7489
|
-
const
|
|
8075
|
+
let rawUrl = item.getUrl() ?? '';
|
|
8076
|
+
const anchor = item.getAnchor();
|
|
8077
|
+
if (anchor)
|
|
8078
|
+
rawUrl = rawUrl ? `${rawUrl}#${anchor}` : `#${anchor}`;
|
|
8079
|
+
const url = this.escapeHTML(rawUrl);
|
|
8080
|
+
const linkText = this.escapeHTML(item.getText() || rawUrl);
|
|
7490
8081
|
parts.push(`<a href="${url}">${linkText}</a>`);
|
|
7491
8082
|
}
|
|
7492
8083
|
}
|
|
@@ -7634,7 +8225,10 @@ export class Document {
|
|
|
7634
8225
|
removeParagraph(paragraphOrIndex) {
|
|
7635
8226
|
let index;
|
|
7636
8227
|
if (typeof paragraphOrIndex === 'number') {
|
|
7637
|
-
|
|
8228
|
+
const para = this.getParagraphAt(paragraphOrIndex);
|
|
8229
|
+
if (!para)
|
|
8230
|
+
return false;
|
|
8231
|
+
index = this.bodyElements.indexOf(para);
|
|
7638
8232
|
}
|
|
7639
8233
|
else {
|
|
7640
8234
|
index = this.bodyElements.indexOf(paragraphOrIndex);
|
|
@@ -7643,13 +8237,8 @@ export class Document {
|
|
|
7643
8237
|
const element = this.bodyElements[index];
|
|
7644
8238
|
if (element instanceof Paragraph) {
|
|
7645
8239
|
if (this.trackChangesEnabled && this.trackingContext.isEnabled()) {
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
const author = this.trackingContext.getAuthor();
|
|
7649
|
-
const deletion = Revision.createDeletion(author, runs);
|
|
7650
|
-
this.trackingContext.getRevisionManager().register(deletion);
|
|
7651
|
-
element.addRevision(deletion);
|
|
7652
|
-
}
|
|
8240
|
+
this.bindTrackingToElement(element);
|
|
8241
|
+
element.clearContent();
|
|
7653
8242
|
return true;
|
|
7654
8243
|
}
|
|
7655
8244
|
this.bodyElements.splice(index, 1);
|
|
@@ -7903,16 +8492,6 @@ export class Document {
|
|
|
7903
8492
|
for (const paragraph of this.getAllParagraphs()) {
|
|
7904
8493
|
extractHyperlinksFromParagraph(paragraph);
|
|
7905
8494
|
}
|
|
7906
|
-
for (const table of this.getTables()) {
|
|
7907
|
-
for (const row of table.getRows()) {
|
|
7908
|
-
for (const cell of row.getCells()) {
|
|
7909
|
-
const cellParagraphs = cell instanceof TableCell ? cell.getParagraphs() : [];
|
|
7910
|
-
for (const para of cellParagraphs) {
|
|
7911
|
-
extractHyperlinksFromParagraph(para);
|
|
7912
|
-
}
|
|
7913
|
-
}
|
|
7914
|
-
}
|
|
7915
|
-
}
|
|
7916
8495
|
return hyperlinks;
|
|
7917
8496
|
}
|
|
7918
8497
|
collectAllReferencedHyperlinkIds() {
|
|
@@ -8037,17 +8616,6 @@ export class Document {
|
|
|
8037
8616
|
bookmarks.push({ bookmark, paragraph });
|
|
8038
8617
|
}
|
|
8039
8618
|
}
|
|
8040
|
-
for (const table of this.getTables()) {
|
|
8041
|
-
for (const row of table.getRows()) {
|
|
8042
|
-
for (const cell of row.getCells()) {
|
|
8043
|
-
for (const para of cell.getParagraphs()) {
|
|
8044
|
-
for (const bookmark of para.getBookmarksStart()) {
|
|
8045
|
-
bookmarks.push({ bookmark, paragraph: para });
|
|
8046
|
-
}
|
|
8047
|
-
}
|
|
8048
|
-
}
|
|
8049
|
-
}
|
|
8050
|
-
}
|
|
8051
8619
|
return bookmarks;
|
|
8052
8620
|
}
|
|
8053
8621
|
getFields() {
|
|
@@ -8057,18 +8625,6 @@ export class Document {
|
|
|
8057
8625
|
results.push({ field, paragraph });
|
|
8058
8626
|
}
|
|
8059
8627
|
}
|
|
8060
|
-
for (const table of this.getTables()) {
|
|
8061
|
-
for (const row of table.getRows()) {
|
|
8062
|
-
for (const cell of row.getCells()) {
|
|
8063
|
-
const cellParagraphs = cell instanceof TableCell ? cell.getParagraphs() : [];
|
|
8064
|
-
for (const para of cellParagraphs) {
|
|
8065
|
-
for (const field of para.getFields()) {
|
|
8066
|
-
results.push({ field, paragraph: para, table });
|
|
8067
|
-
}
|
|
8068
|
-
}
|
|
8069
|
-
}
|
|
8070
|
-
}
|
|
8071
|
-
}
|
|
8072
8628
|
return results;
|
|
8073
8629
|
}
|
|
8074
8630
|
getImages() {
|
|
@@ -8107,7 +8663,7 @@ export class Document {
|
|
|
8107
8663
|
await entry.image.updateImageData(result.data);
|
|
8108
8664
|
}
|
|
8109
8665
|
if (result.newExtension !== extension) {
|
|
8110
|
-
const newFilename = filename.replace(/\.[^.]+$/, `.${result.newExtension}`);
|
|
8666
|
+
const newFilename = this.resolveUniqueMediaFilename(filename.replace(/\.[^.]+$/, `.${result.newExtension}`), filename);
|
|
8111
8667
|
this.imageManager.updateEntryFilename(image, newFilename);
|
|
8112
8668
|
for (const entry of entries) {
|
|
8113
8669
|
this.updateImageRelationshipTarget(entry.relationshipId, filename, newFilename);
|
|
@@ -8118,6 +8674,20 @@ export class Document {
|
|
|
8118
8674
|
}
|
|
8119
8675
|
return { optimizedCount, totalSavedBytes: totalSaved };
|
|
8120
8676
|
}
|
|
8677
|
+
resolveUniqueMediaFilename(candidate, currentFilename) {
|
|
8678
|
+
const dotIndex = candidate.lastIndexOf('.');
|
|
8679
|
+
const base = dotIndex === -1 ? candidate : candidate.slice(0, dotIndex);
|
|
8680
|
+
const ext = dotIndex === -1 ? '' : candidate.slice(dotIndex);
|
|
8681
|
+
const isTaken = (name) => this.zipHandler.hasFile(`word/media/${name}`) ||
|
|
8682
|
+
this.imageManager.isFilenameOwnedByOther(name, currentFilename);
|
|
8683
|
+
let name = candidate;
|
|
8684
|
+
let counter = 1;
|
|
8685
|
+
while (isTaken(name)) {
|
|
8686
|
+
name = `${base}-${counter}${ext}`;
|
|
8687
|
+
counter++;
|
|
8688
|
+
}
|
|
8689
|
+
return name;
|
|
8690
|
+
}
|
|
8121
8691
|
updateImageRelationshipTarget(relId, oldFilename, newFilename) {
|
|
8122
8692
|
const rel = this.relationshipManager.getRelationship(relId);
|
|
8123
8693
|
if (rel) {
|
|
@@ -8241,7 +8811,7 @@ export class Document {
|
|
|
8241
8811
|
const toRemove = [];
|
|
8242
8812
|
this.bodyElements.forEach((element, index) => {
|
|
8243
8813
|
if (element instanceof Paragraph) {
|
|
8244
|
-
const isEmpty =
|
|
8814
|
+
const isEmpty = this.isParagraphRemovableBlank(element);
|
|
8245
8815
|
if (isEmpty && lastWasEmpty) {
|
|
8246
8816
|
toRemove.push(index);
|
|
8247
8817
|
}
|
|
@@ -8325,11 +8895,30 @@ export class Document {
|
|
|
8325
8895
|
}
|
|
8326
8896
|
return { removed, normalized };
|
|
8327
8897
|
}
|
|
8898
|
+
isParagraphRemovableBlank(para) {
|
|
8899
|
+
if (para.getText().trim() !== '')
|
|
8900
|
+
return false;
|
|
8901
|
+
if (para.formatting.sectPr !== undefined)
|
|
8902
|
+
return false;
|
|
8903
|
+
if (para.getBookmarksStart().length > 0 || para.getBookmarksEnd().length > 0) {
|
|
8904
|
+
return false;
|
|
8905
|
+
}
|
|
8906
|
+
if (para.getCommentsStart().length > 0 || para.getCommentsEnd().length > 0) {
|
|
8907
|
+
return false;
|
|
8908
|
+
}
|
|
8909
|
+
for (const item of para.getContent()) {
|
|
8910
|
+
if (item instanceof ImageRun || item instanceof Shape || item instanceof RangeMarker) {
|
|
8911
|
+
return false;
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
return true;
|
|
8915
|
+
}
|
|
8328
8916
|
setLanguage(language) {
|
|
8329
8917
|
if (!this.properties) {
|
|
8330
8918
|
this.properties = {};
|
|
8331
8919
|
}
|
|
8332
8920
|
this.properties.language = language;
|
|
8921
|
+
this._corePropsModified = true;
|
|
8333
8922
|
return this;
|
|
8334
8923
|
}
|
|
8335
8924
|
getLanguage() {
|
|
@@ -8445,32 +9034,6 @@ export class Document {
|
|
|
8445
9034
|
pattern.lastIndex = 0;
|
|
8446
9035
|
}
|
|
8447
9036
|
}
|
|
8448
|
-
for (const table of this.getTables()) {
|
|
8449
|
-
for (const row of table.getRows()) {
|
|
8450
|
-
for (const cell of row.getCells()) {
|
|
8451
|
-
for (const para of cell.getParagraphs()) {
|
|
8452
|
-
for (const run of para.getRuns()) {
|
|
8453
|
-
const text = run.getText();
|
|
8454
|
-
if (!text)
|
|
8455
|
-
continue;
|
|
8456
|
-
const runFormatting = run.getFormatting();
|
|
8457
|
-
if (matchBold && !runFormatting.bold)
|
|
8458
|
-
continue;
|
|
8459
|
-
if (matchItalic && !runFormatting.italic)
|
|
8460
|
-
continue;
|
|
8461
|
-
if (pattern.test(text)) {
|
|
8462
|
-
const newText = text.replace(pattern, replace);
|
|
8463
|
-
if (newText !== text) {
|
|
8464
|
-
run.setText(newText);
|
|
8465
|
-
replacedCount++;
|
|
8466
|
-
}
|
|
8467
|
-
}
|
|
8468
|
-
pattern.lastIndex = 0;
|
|
8469
|
-
}
|
|
8470
|
-
}
|
|
8471
|
-
}
|
|
8472
|
-
}
|
|
8473
|
-
}
|
|
8474
9037
|
return replacedCount;
|
|
8475
9038
|
}
|
|
8476
9039
|
static createEmpty() {
|