docxmlater 11.0.10 → 12.0.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 +51 -13
- package/dist/core/Document.d.ts +28 -2
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +725 -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 +726 -171
- 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 +58 -8
- 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/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 +2 -0
- package/dist/processors/RevisionWalker.d.ts.map +1 -1
- package/dist/processors/RevisionWalker.js +58 -8
- 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/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 +1159 -240
- 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 +83 -7
- package/src/processors/SelectiveRevisionAcceptor.ts +164 -28
- 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
|
@@ -39,6 +39,7 @@ import { acceptAllRevisions, cleanupRevisionMetadata } from '../processors/accep
|
|
|
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;
|
|
@@ -386,7 +392,7 @@ export class Document {
|
|
|
386
392
|
}
|
|
387
393
|
const numberingXml = zipHandler.getFileAsString(DOCX_PATHS.NUMBERING);
|
|
388
394
|
if (numberingXml) {
|
|
389
|
-
doc._originalNumberingXml = numberingXml;
|
|
395
|
+
doc._originalNumberingXml = reorderRunPropertyChildren(numberingXml);
|
|
390
396
|
}
|
|
391
397
|
const settingsXml = zipHandler.getFileAsString(DOCX_PATHS.SETTINGS);
|
|
392
398
|
if (settingsXml) {
|
|
@@ -397,6 +403,10 @@ export class Document {
|
|
|
397
403
|
if (appPropsXml) {
|
|
398
404
|
doc._originalAppPropsXml = appPropsXml;
|
|
399
405
|
}
|
|
406
|
+
const corePropsXml = zipHandler.getFileAsString(DOCX_PATHS.CORE_PROPS);
|
|
407
|
+
if (corePropsXml) {
|
|
408
|
+
doc._originalCorePropsXml = corePropsXml;
|
|
409
|
+
}
|
|
400
410
|
const webSettingsXml = zipHandler.getFileAsString(DOCX_PATHS.WEB_SETTINGS);
|
|
401
411
|
if (webSettingsXml) {
|
|
402
412
|
doc._originalWebSettingsXml = webSettingsXml;
|
|
@@ -659,17 +669,17 @@ export class Document {
|
|
|
659
669
|
try {
|
|
660
670
|
const headersFooters = await this.parser.parseHeadersAndFooters(this.zipHandler, result.section, this.relationshipManager, this.imageManager);
|
|
661
671
|
const registeredHeaderRIds = new Set();
|
|
662
|
-
for (const { header, relationshipId } of headersFooters.headers) {
|
|
672
|
+
for (const { header, relationshipId, filename } of headersFooters.headers) {
|
|
663
673
|
if (registeredHeaderRIds.has(relationshipId))
|
|
664
674
|
continue;
|
|
665
|
-
this.headerFooterManager.registerHeader(header, relationshipId);
|
|
675
|
+
this.headerFooterManager.registerHeader(header, relationshipId, filename);
|
|
666
676
|
registeredHeaderRIds.add(relationshipId);
|
|
667
677
|
}
|
|
668
678
|
const registeredFooterRIds = new Set();
|
|
669
|
-
for (const { footer, relationshipId } of headersFooters.footers) {
|
|
679
|
+
for (const { footer, relationshipId, filename } of headersFooters.footers) {
|
|
670
680
|
if (registeredFooterRIds.has(relationshipId))
|
|
671
681
|
continue;
|
|
672
|
-
this.headerFooterManager.registerFooter(footer, relationshipId);
|
|
682
|
+
this.headerFooterManager.registerFooter(footer, relationshipId, filename);
|
|
673
683
|
registeredFooterRIds.add(relationshipId);
|
|
674
684
|
}
|
|
675
685
|
}
|
|
@@ -712,7 +722,7 @@ export class Document {
|
|
|
712
722
|
}
|
|
713
723
|
}
|
|
714
724
|
const parser = new DocumentParser();
|
|
715
|
-
const comments = parser.parseCommentsXml(commentsXml);
|
|
725
|
+
const comments = parser.parseCommentsXml(commentsXml, this._originalCommentCompanionFiles.get(DOCX_PATHS.COMMENTS_EXTENDED));
|
|
716
726
|
for (const comment of comments) {
|
|
717
727
|
this.commentManager.registerExisting(comment);
|
|
718
728
|
}
|
|
@@ -726,7 +736,9 @@ export class Document {
|
|
|
726
736
|
this._originalFootnotesXml = footnotesXml;
|
|
727
737
|
try {
|
|
728
738
|
const parser = new DocumentParser();
|
|
729
|
-
const
|
|
739
|
+
const relsXml = this.zipHandler.getFileAsString('word/_rels/footnotes.xml.rels');
|
|
740
|
+
const partRels = relsXml ? RelationshipManager.fromXml(relsXml) : undefined;
|
|
741
|
+
const footnotes = parser.parseFootnotesXml(footnotesXml, partRels);
|
|
730
742
|
for (const footnote of footnotes) {
|
|
731
743
|
const id = footnote.getId();
|
|
732
744
|
if (!this.footnoteManager.hasFootnote(id)) {
|
|
@@ -748,7 +760,9 @@ export class Document {
|
|
|
748
760
|
this._originalEndnotesXml = endnotesXml;
|
|
749
761
|
try {
|
|
750
762
|
const parser = new DocumentParser();
|
|
751
|
-
const
|
|
763
|
+
const relsXml = this.zipHandler.getFileAsString('word/_rels/endnotes.xml.rels');
|
|
764
|
+
const partRels = relsXml ? RelationshipManager.fromXml(relsXml) : undefined;
|
|
765
|
+
const endnotes = parser.parseEndnotesXml(endnotesXml, partRels);
|
|
752
766
|
for (const endnote of endnotes) {
|
|
753
767
|
const id = endnote.getId();
|
|
754
768
|
if (!this.endnoteManager.hasEndnote(id)) {
|
|
@@ -840,12 +854,13 @@ export class Document {
|
|
|
840
854
|
paragraph._setStylesManager(this.stylesManager);
|
|
841
855
|
if (this.trackChangesEnabled && this.trackingContext.isEnabled()) {
|
|
842
856
|
this.bindTrackingToElement(paragraph);
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
857
|
+
const author = this.trackingContext.getAuthor();
|
|
858
|
+
for (const item of paragraph.getContent()) {
|
|
859
|
+
if (item instanceof Run || item instanceof Hyperlink) {
|
|
860
|
+
const insertion = Revision.createInsertion(author, item);
|
|
861
|
+
this.trackingContext.getRevisionManager().register(insertion);
|
|
862
|
+
paragraph.replaceContent(item, [insertion]);
|
|
863
|
+
}
|
|
849
864
|
}
|
|
850
865
|
}
|
|
851
866
|
this.bodyElements.push(paragraph);
|
|
@@ -1061,14 +1076,17 @@ export class Document {
|
|
|
1061
1076
|
}
|
|
1062
1077
|
setTitle(title) {
|
|
1063
1078
|
this.properties.title = title;
|
|
1079
|
+
this._corePropsModified = true;
|
|
1064
1080
|
return this;
|
|
1065
1081
|
}
|
|
1066
1082
|
setSubject(subject) {
|
|
1067
1083
|
this.properties.subject = subject;
|
|
1084
|
+
this._corePropsModified = true;
|
|
1068
1085
|
return this;
|
|
1069
1086
|
}
|
|
1070
1087
|
setCreator(creator) {
|
|
1071
1088
|
this.properties.creator = creator;
|
|
1089
|
+
this._corePropsModified = true;
|
|
1072
1090
|
return this;
|
|
1073
1091
|
}
|
|
1074
1092
|
setAuthor(author) {
|
|
@@ -1076,18 +1094,22 @@ export class Document {
|
|
|
1076
1094
|
}
|
|
1077
1095
|
setKeywords(keywords) {
|
|
1078
1096
|
this.properties.keywords = keywords;
|
|
1097
|
+
this._corePropsModified = true;
|
|
1079
1098
|
return this;
|
|
1080
1099
|
}
|
|
1081
1100
|
setDescription(description) {
|
|
1082
1101
|
this.properties.description = description;
|
|
1102
|
+
this._corePropsModified = true;
|
|
1083
1103
|
return this;
|
|
1084
1104
|
}
|
|
1085
1105
|
setCategory(category) {
|
|
1086
1106
|
this.properties.category = category;
|
|
1107
|
+
this._corePropsModified = true;
|
|
1087
1108
|
return this;
|
|
1088
1109
|
}
|
|
1089
1110
|
setContentStatus(status) {
|
|
1090
1111
|
this.properties.contentStatus = status;
|
|
1112
|
+
this._corePropsModified = true;
|
|
1091
1113
|
return this;
|
|
1092
1114
|
}
|
|
1093
1115
|
setApplication(application) {
|
|
@@ -1534,8 +1556,48 @@ export class Document {
|
|
|
1534
1556
|
if (this._removedParts.has(DOCX_PATHS.CORE_PROPS) ||
|
|
1535
1557
|
this._removedParts.has('docProps/core.xml'))
|
|
1536
1558
|
return;
|
|
1537
|
-
|
|
1538
|
-
|
|
1559
|
+
if (this._originalCorePropsXml && !this._corePropsModified) {
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
if (this._originalCorePropsXml && this._corePropsModified) {
|
|
1563
|
+
const mergedXml = this.mergeCorePropsWithOriginal();
|
|
1564
|
+
this.zipHandler.updateFile(DOCX_PATHS.CORE_PROPS, mergedXml);
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
const xml = this.generator.generateCoreProps(this.properties);
|
|
1568
|
+
this.zipHandler.updateFile(DOCX_PATHS.CORE_PROPS, xml);
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
mergeCorePropsWithOriginal() {
|
|
1572
|
+
if (!this._originalCorePropsXml) {
|
|
1573
|
+
return this.generator.generateCoreProps(this.properties);
|
|
1574
|
+
}
|
|
1575
|
+
let xml = this._originalCorePropsXml;
|
|
1576
|
+
const mergeField = (tag, value) => {
|
|
1577
|
+
if (value === undefined)
|
|
1578
|
+
return;
|
|
1579
|
+
const escaped = XMLBuilder.sanitizeXmlContent(value);
|
|
1580
|
+
const openClose = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?</${tag}>`);
|
|
1581
|
+
const selfClosing = new RegExp(`<${tag}\\b[^>]*/>`);
|
|
1582
|
+
if (openClose.test(xml)) {
|
|
1583
|
+
xml = xml.replace(openClose, `<${tag}>${escaped}</${tag}>`);
|
|
1584
|
+
}
|
|
1585
|
+
else if (selfClosing.test(xml)) {
|
|
1586
|
+
xml = xml.replace(selfClosing, `<${tag}>${escaped}</${tag}>`);
|
|
1587
|
+
}
|
|
1588
|
+
else {
|
|
1589
|
+
xml = xml.replace(/<\/cp:coreProperties>/, ` <${tag}>${escaped}</${tag}>\n</cp:coreProperties>`);
|
|
1590
|
+
}
|
|
1591
|
+
};
|
|
1592
|
+
mergeField('dc:title', this.properties.title);
|
|
1593
|
+
mergeField('dc:subject', this.properties.subject);
|
|
1594
|
+
mergeField('dc:creator', this.properties.creator);
|
|
1595
|
+
mergeField('cp:keywords', this.properties.keywords);
|
|
1596
|
+
mergeField('dc:description', this.properties.description);
|
|
1597
|
+
mergeField('cp:category', this.properties.category);
|
|
1598
|
+
mergeField('cp:contentStatus', this.properties.contentStatus);
|
|
1599
|
+
mergeField('dc:language', this.properties.language);
|
|
1600
|
+
return xml;
|
|
1539
1601
|
}
|
|
1540
1602
|
updateAppProps() {
|
|
1541
1603
|
if (this._removedParts.has(DOCX_PATHS.APP_PROPS) || this._removedParts.has('docProps/app.xml'))
|
|
@@ -1565,24 +1627,36 @@ export class Document {
|
|
|
1565
1627
|
else if (xml.includes('<Company/>')) {
|
|
1566
1628
|
xml = xml.replace(/<Company\/>/, `<Company>${escaped}</Company>`);
|
|
1567
1629
|
}
|
|
1630
|
+
else {
|
|
1631
|
+
xml = xml.replace(/<\/Properties>/, ` <Company>${escaped}</Company>\n</Properties>`);
|
|
1632
|
+
}
|
|
1568
1633
|
}
|
|
1569
1634
|
if (this.properties.application !== undefined) {
|
|
1570
1635
|
const escaped = XMLBuilder.sanitizeXmlContent(this.properties.application);
|
|
1571
1636
|
if (xml.includes('<Application>')) {
|
|
1572
1637
|
xml = xml.replace(/<Application>[^<]*<\/Application>/, `<Application>${escaped}</Application>`);
|
|
1573
1638
|
}
|
|
1639
|
+
else {
|
|
1640
|
+
xml = xml.replace(/<\/Properties>/, ` <Application>${escaped}</Application>\n</Properties>`);
|
|
1641
|
+
}
|
|
1574
1642
|
}
|
|
1575
1643
|
if (this.properties.appVersion !== undefined) {
|
|
1576
1644
|
const escaped = XMLBuilder.sanitizeXmlContent(this.properties.appVersion);
|
|
1577
1645
|
if (xml.includes('<AppVersion>')) {
|
|
1578
1646
|
xml = xml.replace(/<AppVersion>[^<]*<\/AppVersion>/, `<AppVersion>${escaped}</AppVersion>`);
|
|
1579
1647
|
}
|
|
1648
|
+
else {
|
|
1649
|
+
xml = xml.replace(/<\/Properties>/, ` <AppVersion>${escaped}</AppVersion>\n</Properties>`);
|
|
1650
|
+
}
|
|
1580
1651
|
}
|
|
1581
1652
|
if (this.properties.manager !== undefined) {
|
|
1582
1653
|
const escaped = XMLBuilder.sanitizeXmlContent(this.properties.manager);
|
|
1583
1654
|
if (xml.includes('<Manager>')) {
|
|
1584
1655
|
xml = xml.replace(/<Manager>[^<]*<\/Manager>/, `<Manager>${escaped}</Manager>`);
|
|
1585
1656
|
}
|
|
1657
|
+
else {
|
|
1658
|
+
xml = xml.replace(/<\/Properties>/, ` <Manager>${escaped}</Manager>\n</Properties>`);
|
|
1659
|
+
}
|
|
1586
1660
|
}
|
|
1587
1661
|
return xml;
|
|
1588
1662
|
}
|
|
@@ -1708,7 +1782,8 @@ export class Document {
|
|
|
1708
1782
|
return this.stylesManager.generateStylesXml();
|
|
1709
1783
|
}
|
|
1710
1784
|
const modifiedStyleIds = this.stylesManager.getModifiedStyleIds();
|
|
1711
|
-
|
|
1785
|
+
const removedStyleIds = this.stylesManager.getRemovedStyleIds();
|
|
1786
|
+
if (modifiedStyleIds.size === 0 && removedStyleIds.size === 0) {
|
|
1712
1787
|
return this._originalStylesXml;
|
|
1713
1788
|
}
|
|
1714
1789
|
const modifiedStyles = new Map();
|
|
@@ -1730,6 +1805,11 @@ export class Document {
|
|
|
1730
1805
|
resultXml = resultXml.replace('</w:styles>', `${newStyleXml}\n</w:styles>`);
|
|
1731
1806
|
}
|
|
1732
1807
|
}
|
|
1808
|
+
for (const styleId of removedStyleIds) {
|
|
1809
|
+
const escapedStyleId = styleId.replace(/[.*+?^${}()|[\]\\"]/g, '\\$&');
|
|
1810
|
+
const removedPattern = new RegExp(`\\s*<w:style[^>]*\\sw:styleId="${escapedStyleId}"[^>]*>[\\s\\S]*?</w:style>`);
|
|
1811
|
+
resultXml = resultXml.replace(removedPattern, '');
|
|
1812
|
+
}
|
|
1733
1813
|
return resultXml;
|
|
1734
1814
|
}
|
|
1735
1815
|
updateNumberingXml() {
|
|
@@ -1928,8 +2008,14 @@ export class Document {
|
|
|
1928
2008
|
xml = xml.replace(/<w:revisionView\b[^>]*>[\s\S]*?<\/w:revisionView>/g, '');
|
|
1929
2009
|
let trackBlock = '';
|
|
1930
2010
|
const view = this.revisionViewSettings;
|
|
1931
|
-
if (!view.showInsertionsAndDeletions ||
|
|
1932
|
-
|
|
2011
|
+
if (!view.showInsertionsAndDeletions ||
|
|
2012
|
+
!view.showFormatting ||
|
|
2013
|
+
!view.showInkAnnotations ||
|
|
2014
|
+
view.showMarkup === false ||
|
|
2015
|
+
view.showComments === false) {
|
|
2016
|
+
const markupAttr = view.showMarkup === false ? ' w:markup="0"' : '';
|
|
2017
|
+
const commentsAttr = view.showComments === false ? ' w:comments="0"' : '';
|
|
2018
|
+
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
2019
|
}
|
|
1934
2020
|
if (this.trackChangesEnabled) {
|
|
1935
2021
|
trackBlock += '\n <w:trackRevisions/>';
|
|
@@ -1965,6 +2051,8 @@ export class Document {
|
|
|
1965
2051
|
const prot = this.documentProtection;
|
|
1966
2052
|
const esc = XMLBuilder.escapeXmlAttribute;
|
|
1967
2053
|
let protXml = `\n <w:documentProtection w:edit="${esc(prot.edit)}" w:enforcement="${prot.enforcement ? '1' : '0'}"`;
|
|
2054
|
+
if (prot.formatting !== undefined)
|
|
2055
|
+
protXml += ` w:formatting="${prot.formatting ? '1' : '0'}"`;
|
|
1968
2056
|
if (prot.cryptProviderType)
|
|
1969
2057
|
protXml += ` w:cryptProviderType="${esc(prot.cryptProviderType)}"`;
|
|
1970
2058
|
if (prot.cryptAlgorithmClass)
|
|
@@ -1979,6 +2067,12 @@ export class Document {
|
|
|
1979
2067
|
protXml += ` w:hash="${esc(prot.hash)}"`;
|
|
1980
2068
|
if (prot.salt)
|
|
1981
2069
|
protXml += ` w:salt="${esc(prot.salt)}"`;
|
|
2070
|
+
if (prot.algorithmName)
|
|
2071
|
+
protXml += ` w:algorithmName="${esc(prot.algorithmName)}"`;
|
|
2072
|
+
if (prot.hashValue)
|
|
2073
|
+
protXml += ` w:hashValue="${esc(prot.hashValue)}"`;
|
|
2074
|
+
if (prot.saltValue)
|
|
2075
|
+
protXml += ` w:saltValue="${esc(prot.saltValue)}"`;
|
|
1982
2076
|
protXml += '/>';
|
|
1983
2077
|
if (/<w:autoFormatOverride\b/.test(xml)) {
|
|
1984
2078
|
xml = xml.replace(/<w:autoFormatOverride\b/, protXml + '\n <w:autoFormatOverride');
|
|
@@ -2732,6 +2826,18 @@ export class Document {
|
|
|
2732
2826
|
}
|
|
2733
2827
|
}
|
|
2734
2828
|
}
|
|
2829
|
+
for (const style of this.stylesManager.getAllStyles()) {
|
|
2830
|
+
const styleNumId = style.getProperties().numPr?.numId;
|
|
2831
|
+
if (styleNumId !== undefined) {
|
|
2832
|
+
usedNumIds.add(styleNumId);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
for (const filePath of [DOCX_PATHS.STYLES, 'word/comments.xml']) {
|
|
2836
|
+
const xml = this.zipHandler.getFileAsString(filePath);
|
|
2837
|
+
if (xml) {
|
|
2838
|
+
this.collectNumIdsFromXml(xml, usedNumIds);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2735
2841
|
this.numberingManager.cleanupUnusedNumbering(usedNumIds);
|
|
2736
2842
|
}
|
|
2737
2843
|
validateNumberingReferences() {
|
|
@@ -2833,7 +2939,67 @@ export class Document {
|
|
|
2833
2939
|
maxRevId = rev.getId();
|
|
2834
2940
|
}
|
|
2835
2941
|
const registeredSet = new Set(existingRevisions);
|
|
2836
|
-
let
|
|
2942
|
+
let maxPreservedDocPrId = 0;
|
|
2943
|
+
const collectPreservedDocPrIds = (rawXml) => {
|
|
2944
|
+
if (!rawXml || !rawXml.includes('wp:docPr'))
|
|
2945
|
+
return;
|
|
2946
|
+
const docPrPattern = /<wp:docPr\b[^>]*\bid="(\d+)"/g;
|
|
2947
|
+
let match;
|
|
2948
|
+
while ((match = docPrPattern.exec(rawXml)) !== null) {
|
|
2949
|
+
const id = parseInt(match[1], 10);
|
|
2950
|
+
if (id > maxPreservedDocPrId)
|
|
2951
|
+
maxPreservedDocPrId = id;
|
|
2952
|
+
}
|
|
2953
|
+
};
|
|
2954
|
+
const collectFromRun = (run) => {
|
|
2955
|
+
if (run instanceof ImageRun) {
|
|
2956
|
+
collectPreservedDocPrIds(run.getRawRunXml());
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
for (const contentItem of run.getContent()) {
|
|
2960
|
+
collectPreservedDocPrIds(contentItem.rawXml);
|
|
2961
|
+
}
|
|
2962
|
+
};
|
|
2963
|
+
const collectFromParagraph = (para) => {
|
|
2964
|
+
for (const item of para.getContent()) {
|
|
2965
|
+
if (item instanceof Revision) {
|
|
2966
|
+
for (const revItem of item.getContent()) {
|
|
2967
|
+
if (revItem instanceof Run)
|
|
2968
|
+
collectFromRun(revItem);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
else if (item instanceof Run) {
|
|
2972
|
+
collectFromRun(item);
|
|
2973
|
+
}
|
|
2974
|
+
else if (item instanceof PreservedElement) {
|
|
2975
|
+
collectPreservedDocPrIds(item.getRawXml());
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
};
|
|
2979
|
+
for (const element of this.bodyElements) {
|
|
2980
|
+
if (element instanceof Paragraph) {
|
|
2981
|
+
collectFromParagraph(element);
|
|
2982
|
+
}
|
|
2983
|
+
else if (element instanceof Table) {
|
|
2984
|
+
for (const row of element.getRows()) {
|
|
2985
|
+
for (const cell of row.getCells()) {
|
|
2986
|
+
for (const para of cell.getParagraphs()) {
|
|
2987
|
+
collectFromParagraph(para);
|
|
2988
|
+
}
|
|
2989
|
+
for (const nested of cell.getRawNestedContent()) {
|
|
2990
|
+
collectPreservedDocPrIds(nested.xml);
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
else {
|
|
2996
|
+
const passthrough = element;
|
|
2997
|
+
if (typeof passthrough.getRawXml === 'function') {
|
|
2998
|
+
collectPreservedDocPrIds(passthrough.getRawXml());
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
let docPrId = maxPreservedDocPrId + 1;
|
|
2837
3003
|
const existingParaIds = new Set();
|
|
2838
3004
|
const paragraphsNeedingIds = [];
|
|
2839
3005
|
const generateUniqueParaId = () => {
|
|
@@ -2865,6 +3031,13 @@ export class Document {
|
|
|
2865
3031
|
else if (item instanceof ImageRun) {
|
|
2866
3032
|
item.getImageElement().setDocPrId(docPrId++);
|
|
2867
3033
|
}
|
|
3034
|
+
else if (item instanceof Revision) {
|
|
3035
|
+
for (const revItem of item.getContent()) {
|
|
3036
|
+
if (revItem instanceof ImageRun) {
|
|
3037
|
+
revItem.getImageElement().setDocPrId(docPrId++);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
2868
3041
|
}
|
|
2869
3042
|
if (para.formatting.paraId) {
|
|
2870
3043
|
existingParaIds.add(para.formatting.paraId);
|
|
@@ -3154,6 +3327,7 @@ export class Document {
|
|
|
3154
3327
|
numLevel.setLeftIndent(720 * (levelIndex + 1));
|
|
3155
3328
|
numLevel.setHangingIndent(360);
|
|
3156
3329
|
}
|
|
3330
|
+
this.numberingManager.markAbstractNumberingModified(abstractNumId);
|
|
3157
3331
|
this.applyFormattingToListParagraphs(instance.getNumId());
|
|
3158
3332
|
count++;
|
|
3159
3333
|
}
|
|
@@ -3180,6 +3354,7 @@ export class Document {
|
|
|
3180
3354
|
numLevel.setHangingIndent(360);
|
|
3181
3355
|
numLevel.setAlignment('left');
|
|
3182
3356
|
}
|
|
3357
|
+
this.numberingManager.markAbstractNumberingModified(abstractNumId);
|
|
3183
3358
|
this.applyFormattingToListParagraphs(instance.getNumId());
|
|
3184
3359
|
count++;
|
|
3185
3360
|
}
|
|
@@ -5002,39 +5177,39 @@ export class Document {
|
|
|
5002
5177
|
return this;
|
|
5003
5178
|
}
|
|
5004
5179
|
setHeader(header) {
|
|
5005
|
-
const relationship = this.relationshipManager.addHeader(
|
|
5180
|
+
const relationship = this.relationshipManager.addHeader(this.headerFooterManager.peekHeaderFilename(header));
|
|
5006
5181
|
this.headerFooterManager.registerHeader(header, relationship.getId());
|
|
5007
5182
|
this.section.setHeaderReference('default', relationship.getId());
|
|
5008
5183
|
return this;
|
|
5009
5184
|
}
|
|
5010
5185
|
setFirstPageHeader(header) {
|
|
5011
5186
|
this.section.setTitlePage(true);
|
|
5012
|
-
const relationship = this.relationshipManager.addHeader(
|
|
5187
|
+
const relationship = this.relationshipManager.addHeader(this.headerFooterManager.peekHeaderFilename(header));
|
|
5013
5188
|
this.headerFooterManager.registerHeader(header, relationship.getId());
|
|
5014
5189
|
this.section.setHeaderReference('first', relationship.getId());
|
|
5015
5190
|
return this;
|
|
5016
5191
|
}
|
|
5017
5192
|
setEvenPageHeader(header) {
|
|
5018
|
-
const relationship = this.relationshipManager.addHeader(
|
|
5193
|
+
const relationship = this.relationshipManager.addHeader(this.headerFooterManager.peekHeaderFilename(header));
|
|
5019
5194
|
this.headerFooterManager.registerHeader(header, relationship.getId());
|
|
5020
5195
|
this.section.setHeaderReference('even', relationship.getId());
|
|
5021
5196
|
return this;
|
|
5022
5197
|
}
|
|
5023
5198
|
setFooter(footer) {
|
|
5024
|
-
const relationship = this.relationshipManager.addFooter(
|
|
5199
|
+
const relationship = this.relationshipManager.addFooter(this.headerFooterManager.peekFooterFilename(footer));
|
|
5025
5200
|
this.headerFooterManager.registerFooter(footer, relationship.getId());
|
|
5026
5201
|
this.section.setFooterReference('default', relationship.getId());
|
|
5027
5202
|
return this;
|
|
5028
5203
|
}
|
|
5029
5204
|
setFirstPageFooter(footer) {
|
|
5030
5205
|
this.section.setTitlePage(true);
|
|
5031
|
-
const relationship = this.relationshipManager.addFooter(
|
|
5206
|
+
const relationship = this.relationshipManager.addFooter(this.headerFooterManager.peekFooterFilename(footer));
|
|
5032
5207
|
this.headerFooterManager.registerFooter(footer, relationship.getId());
|
|
5033
5208
|
this.section.setFooterReference('first', relationship.getId());
|
|
5034
5209
|
return this;
|
|
5035
5210
|
}
|
|
5036
5211
|
setEvenPageFooter(footer) {
|
|
5037
|
-
const relationship = this.relationshipManager.addFooter(
|
|
5212
|
+
const relationship = this.relationshipManager.addFooter(this.headerFooterManager.peekFooterFilename(footer));
|
|
5038
5213
|
this.headerFooterManager.registerFooter(footer, relationship.getId());
|
|
5039
5214
|
this.section.setFooterReference('even', relationship.getId());
|
|
5040
5215
|
return this;
|
|
@@ -5180,6 +5355,20 @@ export class Document {
|
|
|
5180
5355
|
}
|
|
5181
5356
|
}
|
|
5182
5357
|
this.removeCommentCompanionFiles();
|
|
5358
|
+
const extendedXml = this.commentManager.generateCommentsExtendedXml();
|
|
5359
|
+
if (extendedXml) {
|
|
5360
|
+
this.zipHandler.addFile(DOCX_PATHS.COMMENTS_EXTENDED, extendedXml);
|
|
5361
|
+
const hasExtendedRel = this.relationshipManager
|
|
5362
|
+
.getAllRelationships()
|
|
5363
|
+
.some((rel) => rel.getTarget() === 'commentsExtended.xml');
|
|
5364
|
+
if (!hasExtendedRel) {
|
|
5365
|
+
this.relationshipManager.addRelationship(Relationship.create({
|
|
5366
|
+
id: this.relationshipManager.generateId(),
|
|
5367
|
+
type: 'http://schemas.microsoft.com/office/2011/relationships/commentsExtended',
|
|
5368
|
+
target: 'commentsExtended.xml',
|
|
5369
|
+
}));
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5183
5372
|
}
|
|
5184
5373
|
else if (this._originalCommentsXml) {
|
|
5185
5374
|
this.zipHandler.addFile('word/comments.xml', this._originalCommentsXml);
|
|
@@ -5217,7 +5406,8 @@ export class Document {
|
|
|
5217
5406
|
}
|
|
5218
5407
|
}
|
|
5219
5408
|
saveFootnotes() {
|
|
5220
|
-
if (this._footnotesModified ||
|
|
5409
|
+
if (this._footnotesModified ||
|
|
5410
|
+
(!this._originalFootnotesXml && this.footnoteManager.getCount() > 0)) {
|
|
5221
5411
|
const xml = this.footnoteManager.generateFootnotesXml();
|
|
5222
5412
|
this.zipHandler.addFile(DOCX_PATHS.FOOTNOTES, xml);
|
|
5223
5413
|
const existingRels = this.relationshipManager.getRelationshipsByType(RelationshipType.FOOTNOTES);
|
|
@@ -5235,7 +5425,8 @@ export class Document {
|
|
|
5235
5425
|
}
|
|
5236
5426
|
}
|
|
5237
5427
|
saveEndnotes() {
|
|
5238
|
-
if (this._endnotesModified ||
|
|
5428
|
+
if (this._endnotesModified ||
|
|
5429
|
+
(!this._originalEndnotesXml && this.endnoteManager.getCount() > 0)) {
|
|
5239
5430
|
const xml = this.endnoteManager.generateEndnotesXml();
|
|
5240
5431
|
this.zipHandler.addFile(DOCX_PATHS.ENDNOTES, xml);
|
|
5241
5432
|
const existingRels = this.relationshipManager.getRelationshipsByType(RelationshipType.ENDNOTES);
|
|
@@ -5304,7 +5495,12 @@ export class Document {
|
|
|
5304
5495
|
xml += '</Relationships>';
|
|
5305
5496
|
this.zipHandler.addFile(relsPath, xml);
|
|
5306
5497
|
for (const rel of hyperlinkRels) {
|
|
5307
|
-
this.relationshipManager.
|
|
5498
|
+
const mainRel = this.relationshipManager.getRelationship(rel.id);
|
|
5499
|
+
if (mainRel &&
|
|
5500
|
+
mainRel.getType() === RelationshipType.HYPERLINK &&
|
|
5501
|
+
mainRel.getTarget() === rel.url) {
|
|
5502
|
+
this.relationshipManager.removeRelationship(rel.id);
|
|
5503
|
+
}
|
|
5308
5504
|
}
|
|
5309
5505
|
}
|
|
5310
5506
|
}
|
|
@@ -5422,13 +5618,25 @@ export class Document {
|
|
|
5422
5618
|
parseContentTypes(xml) {
|
|
5423
5619
|
const defaults = new Set();
|
|
5424
5620
|
const overrides = new Set();
|
|
5425
|
-
const
|
|
5426
|
-
|
|
5427
|
-
|
|
5621
|
+
const readAttr = (tag, name) => {
|
|
5622
|
+
const match = tag.match(new RegExp(`(?:^|\\s)${name}\\s*=\\s*("([^"]*)"|'([^']*)')`));
|
|
5623
|
+
if (!match)
|
|
5624
|
+
return undefined;
|
|
5625
|
+
return XMLBuilder.unescapeXml(match[2] ?? match[3] ?? '');
|
|
5626
|
+
};
|
|
5627
|
+
for (const tagMatch of xml.matchAll(/<Default\b[^>]*>/g)) {
|
|
5628
|
+
const ext = readAttr(tagMatch[0], 'Extension');
|
|
5629
|
+
const contentType = readAttr(tagMatch[0], 'ContentType');
|
|
5630
|
+
if (ext && contentType) {
|
|
5631
|
+
defaults.add(`${ext}|${contentType}`);
|
|
5632
|
+
}
|
|
5428
5633
|
}
|
|
5429
|
-
const
|
|
5430
|
-
|
|
5431
|
-
|
|
5634
|
+
for (const tagMatch of xml.matchAll(/<Override\b[^>]*>/g)) {
|
|
5635
|
+
const partName = readAttr(tagMatch[0], 'PartName');
|
|
5636
|
+
const contentType = readAttr(tagMatch[0], 'ContentType');
|
|
5637
|
+
if (partName && contentType) {
|
|
5638
|
+
overrides.add(`${partName}|${contentType}`);
|
|
5639
|
+
}
|
|
5432
5640
|
}
|
|
5433
5641
|
return { defaults, overrides };
|
|
5434
5642
|
}
|
|
@@ -5748,9 +5956,7 @@ export class Document {
|
|
|
5748
5956
|
}
|
|
5749
5957
|
if (element && typeof element.getContent === 'function') {
|
|
5750
5958
|
for (const item of element.getContent()) {
|
|
5751
|
-
if (item &&
|
|
5752
|
-
typeof item._setTrackingContext === 'function' &&
|
|
5753
|
-
typeof item.getInstruction === 'function') {
|
|
5959
|
+
if (item && typeof item._setTrackingContext === 'function') {
|
|
5754
5960
|
item._setTrackingContext(this.trackingContext);
|
|
5755
5961
|
}
|
|
5756
5962
|
}
|
|
@@ -5917,6 +6123,7 @@ export class Document {
|
|
|
5917
6123
|
updated.size = sizeInPoints;
|
|
5918
6124
|
}
|
|
5919
6125
|
normalStyle.setRunFormatting(updated);
|
|
6126
|
+
this.stylesManager.addStyle(normalStyle);
|
|
5920
6127
|
return this;
|
|
5921
6128
|
}
|
|
5922
6129
|
setDefaultFontSize(sizeInPoints) {
|
|
@@ -5932,6 +6139,7 @@ export class Document {
|
|
|
5932
6139
|
}
|
|
5933
6140
|
const existing = normalStyle.getRunFormatting() ?? {};
|
|
5934
6141
|
normalStyle.setRunFormatting({ ...existing, size: sizeInPoints });
|
|
6142
|
+
this.stylesManager.addStyle(normalStyle);
|
|
5935
6143
|
return this;
|
|
5936
6144
|
}
|
|
5937
6145
|
getUpdateFields() {
|
|
@@ -6123,6 +6331,40 @@ export class Document {
|
|
|
6123
6331
|
this.endnoteManager.clear();
|
|
6124
6332
|
this._endnotesModified = true;
|
|
6125
6333
|
}
|
|
6334
|
+
removeFootnote(id) {
|
|
6335
|
+
const removed = this.footnoteManager.removeFootnote(id);
|
|
6336
|
+
if (removed) {
|
|
6337
|
+
this._footnotesModified = true;
|
|
6338
|
+
this.removeNoteReferenceRuns('footnoteReference', id);
|
|
6339
|
+
}
|
|
6340
|
+
return removed;
|
|
6341
|
+
}
|
|
6342
|
+
removeEndnote(id) {
|
|
6343
|
+
const removed = this.endnoteManager.removeEndnote(id);
|
|
6344
|
+
if (removed) {
|
|
6345
|
+
this._endnotesModified = true;
|
|
6346
|
+
this.removeNoteReferenceRuns('endnoteReference', id);
|
|
6347
|
+
}
|
|
6348
|
+
return removed;
|
|
6349
|
+
}
|
|
6350
|
+
removeNoteReferenceRuns(refType, id) {
|
|
6351
|
+
for (const para of this.getAllParagraphs()) {
|
|
6352
|
+
const content = para.getContent();
|
|
6353
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
6354
|
+
const item = content[i];
|
|
6355
|
+
if (!(item instanceof Run)) {
|
|
6356
|
+
continue;
|
|
6357
|
+
}
|
|
6358
|
+
const matches = item
|
|
6359
|
+
.getContent()
|
|
6360
|
+
.some((c) => c.type === refType &&
|
|
6361
|
+
(refType === 'footnoteReference' ? c.footnoteId === id : c.endnoteId === id));
|
|
6362
|
+
if (matches) {
|
|
6363
|
+
para.removeContentAt(i);
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
}
|
|
6126
6368
|
addCommentToParagraph(paragraph, commentOrAuthor, content, initials) {
|
|
6127
6369
|
const comment = typeof commentOrAuthor === 'string'
|
|
6128
6370
|
? this.createComment(commentOrAuthor, content, initials)
|
|
@@ -6173,12 +6415,52 @@ export class Document {
|
|
|
6173
6415
|
return this.commentManager.hasReplies(commentId);
|
|
6174
6416
|
}
|
|
6175
6417
|
removeComment(id) {
|
|
6418
|
+
const replyIds = this.commentManager.getReplies(id).map((reply) => reply.getId());
|
|
6176
6419
|
const removed = this.commentManager.removeComment(id);
|
|
6177
6420
|
if (removed) {
|
|
6421
|
+
this.removeCommentAnchors([id, ...replyIds]);
|
|
6178
6422
|
this._commentsModified = true;
|
|
6179
6423
|
}
|
|
6180
6424
|
return removed;
|
|
6181
6425
|
}
|
|
6426
|
+
removeCommentAnchors(commentIds) {
|
|
6427
|
+
const strip = (paragraphs) => {
|
|
6428
|
+
let removed = false;
|
|
6429
|
+
for (const paragraph of paragraphs) {
|
|
6430
|
+
for (const commentId of commentIds) {
|
|
6431
|
+
if (paragraph.removeCommentAnchor(commentId)) {
|
|
6432
|
+
removed = true;
|
|
6433
|
+
}
|
|
6434
|
+
}
|
|
6435
|
+
}
|
|
6436
|
+
return removed;
|
|
6437
|
+
};
|
|
6438
|
+
strip(this.getAllParagraphs());
|
|
6439
|
+
for (const entry of this.headerFooterManager.getAllHeaders()) {
|
|
6440
|
+
strip(this.extractParagraphsFromElements(entry.header.getElements()));
|
|
6441
|
+
}
|
|
6442
|
+
for (const entry of this.headerFooterManager.getAllFooters()) {
|
|
6443
|
+
strip(this.extractParagraphsFromElements(entry.footer.getElements()));
|
|
6444
|
+
}
|
|
6445
|
+
let footnotesChanged = false;
|
|
6446
|
+
for (const footnote of this.footnoteManager.getAllFootnotes()) {
|
|
6447
|
+
if (strip(footnote.getParagraphs())) {
|
|
6448
|
+
footnotesChanged = true;
|
|
6449
|
+
}
|
|
6450
|
+
}
|
|
6451
|
+
if (footnotesChanged) {
|
|
6452
|
+
this._footnotesModified = true;
|
|
6453
|
+
}
|
|
6454
|
+
let endnotesChanged = false;
|
|
6455
|
+
for (const endnote of this.endnoteManager.getAllEndnotes()) {
|
|
6456
|
+
if (strip(endnote.getParagraphs())) {
|
|
6457
|
+
endnotesChanged = true;
|
|
6458
|
+
}
|
|
6459
|
+
}
|
|
6460
|
+
if (endnotesChanged) {
|
|
6461
|
+
this._endnotesModified = true;
|
|
6462
|
+
}
|
|
6463
|
+
}
|
|
6182
6464
|
hasNoRevisions() {
|
|
6183
6465
|
return this.revisionManager.isEmpty();
|
|
6184
6466
|
}
|
|
@@ -6434,8 +6716,8 @@ export class Document {
|
|
|
6434
6716
|
this.parser.clearParseErrors();
|
|
6435
6717
|
this.stylesManager.clear();
|
|
6436
6718
|
this.numberingManager.clear();
|
|
6437
|
-
this.imageManager.clear();
|
|
6438
6719
|
this.imageManager.releaseAllImageData();
|
|
6720
|
+
this.imageManager.clear();
|
|
6439
6721
|
this.relationshipManager.clear();
|
|
6440
6722
|
this.headerFooterManager.clear();
|
|
6441
6723
|
this.bookmarkManager.clear();
|
|
@@ -6449,6 +6731,7 @@ export class Document {
|
|
|
6449
6731
|
this._originalNumberingXml = undefined;
|
|
6450
6732
|
this._originalSettingsXml = undefined;
|
|
6451
6733
|
this._originalAppPropsXml = undefined;
|
|
6734
|
+
this._originalCorePropsXml = undefined;
|
|
6452
6735
|
this._originalFootnotesXml = undefined;
|
|
6453
6736
|
this._originalEndnotesXml = undefined;
|
|
6454
6737
|
this._originalCommentsXml = undefined;
|
|
@@ -6457,6 +6740,7 @@ export class Document {
|
|
|
6457
6740
|
this._originalContentTypes = undefined;
|
|
6458
6741
|
this._settingsModified = false;
|
|
6459
6742
|
this._appPropsModified = false;
|
|
6743
|
+
this._corePropsModified = false;
|
|
6460
6744
|
this._footnotesModified = false;
|
|
6461
6745
|
this._endnotesModified = false;
|
|
6462
6746
|
this._originalWebSettingsXml = undefined;
|
|
@@ -7014,7 +7298,7 @@ export class Document {
|
|
|
7014
7298
|
const matches = originalText.match(wordPattern);
|
|
7015
7299
|
if (matches) {
|
|
7016
7300
|
replacementCount += matches.length;
|
|
7017
|
-
newText = originalText.replace(wordPattern, replace);
|
|
7301
|
+
newText = originalText.replace(wordPattern, () => replace);
|
|
7018
7302
|
}
|
|
7019
7303
|
}
|
|
7020
7304
|
else {
|
|
@@ -7022,7 +7306,7 @@ export class Document {
|
|
|
7022
7306
|
const matches = originalText.match(searchPattern);
|
|
7023
7307
|
if (matches) {
|
|
7024
7308
|
replacementCount += matches.length;
|
|
7025
|
-
newText = originalText.replace(searchPattern, replace);
|
|
7309
|
+
newText = originalText.replace(searchPattern, () => replace);
|
|
7026
7310
|
}
|
|
7027
7311
|
}
|
|
7028
7312
|
if (newText !== originalText) {
|
|
@@ -7302,90 +7586,303 @@ export class Document {
|
|
|
7302
7586
|
}
|
|
7303
7587
|
toPlainText(separator = '\n') {
|
|
7304
7588
|
const paragraphs = this.getAllParagraphs();
|
|
7305
|
-
return paragraphs.map((p) => p.
|
|
7306
|
-
}
|
|
7307
|
-
toMarkdown() {
|
|
7589
|
+
return paragraphs.map((p) => p.getTextIncludingRevisions()).join(separator);
|
|
7590
|
+
}
|
|
7591
|
+
toMarkdown(options) {
|
|
7592
|
+
const ctx = {
|
|
7593
|
+
opts: {
|
|
7594
|
+
htmlFallback: options?.htmlFallback ?? true,
|
|
7595
|
+
footnotes: options?.footnotes ?? true,
|
|
7596
|
+
images: options?.images ?? true,
|
|
7597
|
+
},
|
|
7598
|
+
notes: [],
|
|
7599
|
+
noteMarkers: new Set(),
|
|
7600
|
+
};
|
|
7308
7601
|
const lines = [];
|
|
7309
7602
|
for (const element of this.bodyElements) {
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7603
|
+
this.bodyElementToMarkdown(element, ctx, lines);
|
|
7604
|
+
}
|
|
7605
|
+
while (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
7606
|
+
lines.pop();
|
|
7607
|
+
}
|
|
7608
|
+
let out = lines.join('\n');
|
|
7609
|
+
if (ctx.opts.footnotes && ctx.notes.length > 0) {
|
|
7610
|
+
const defs = ctx.notes.map((n) => `[^${n.marker}]: ${n.text}`).join('\n');
|
|
7611
|
+
out = out ? `${out}\n\n${defs}` : defs;
|
|
7612
|
+
}
|
|
7613
|
+
return out;
|
|
7614
|
+
}
|
|
7615
|
+
bodyElementToMarkdown(element, ctx, lines) {
|
|
7616
|
+
if (element instanceof Paragraph) {
|
|
7617
|
+
const md = this.paragraphToMarkdown(element, ctx);
|
|
7618
|
+
if (md !== null) {
|
|
7619
|
+
lines.push(md);
|
|
7620
|
+
lines.push('');
|
|
7316
7621
|
}
|
|
7317
|
-
|
|
7318
|
-
|
|
7622
|
+
}
|
|
7623
|
+
else if (element instanceof Table) {
|
|
7624
|
+
const tableLines = this.tableToMarkdown(element, ctx);
|
|
7625
|
+
if (tableLines.length > 0) {
|
|
7626
|
+
lines.push(...tableLines);
|
|
7319
7627
|
lines.push('');
|
|
7320
7628
|
}
|
|
7321
7629
|
}
|
|
7322
|
-
|
|
7323
|
-
|
|
7630
|
+
else if (element instanceof StructuredDocumentTag) {
|
|
7631
|
+
for (const child of element.getContent()) {
|
|
7632
|
+
this.bodyElementToMarkdown(child, ctx, lines);
|
|
7633
|
+
}
|
|
7634
|
+
}
|
|
7635
|
+
else if (element instanceof PreservedElement) {
|
|
7636
|
+
const text = this.extractTextFromRawXml(element.getRawXml());
|
|
7637
|
+
if (text) {
|
|
7638
|
+
lines.push(this.escapeMarkdown(text));
|
|
7639
|
+
lines.push('');
|
|
7640
|
+
}
|
|
7324
7641
|
}
|
|
7325
|
-
return lines.join('\n');
|
|
7326
7642
|
}
|
|
7327
|
-
paragraphToMarkdown(para) {
|
|
7328
|
-
const
|
|
7329
|
-
|
|
7643
|
+
paragraphToMarkdown(para, ctx) {
|
|
7644
|
+
const inline = this.paragraphContentToMarkdown(para, ctx);
|
|
7645
|
+
const hasNumbering = para.hasNumbering();
|
|
7646
|
+
if (!inline && !hasNumbering)
|
|
7330
7647
|
return null;
|
|
7331
7648
|
const headingLevel = para.detectHeadingLevel();
|
|
7332
7649
|
if (headingLevel !== null && headingLevel >= 1 && headingLevel <= 6) {
|
|
7333
|
-
return '#'.repeat(headingLevel) + ' ' +
|
|
7334
|
-
}
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7650
|
+
return '#'.repeat(headingLevel) + ' ' + this.toSingleLine(inline);
|
|
7651
|
+
}
|
|
7652
|
+
const style = (para.getStyle() ?? '').toLowerCase();
|
|
7653
|
+
const isListStyle = style.includes('listbullet') ||
|
|
7654
|
+
style.includes('list bullet') ||
|
|
7655
|
+
style.includes('listnumber') ||
|
|
7656
|
+
style.includes('list number');
|
|
7657
|
+
if (hasNumbering || isListStyle) {
|
|
7658
|
+
const level = para.getNumbering()?.level ?? 0;
|
|
7659
|
+
const indent = ' '.repeat(Math.max(0, level));
|
|
7660
|
+
const marker = this.isOrderedList(para) ? '1.' : '-';
|
|
7661
|
+
return `${indent}${marker} ${this.toSingleLine(inline)}`;
|
|
7662
|
+
}
|
|
7663
|
+
if (style.includes('quote')) {
|
|
7664
|
+
return this.toSingleLine(inline)
|
|
7665
|
+
.split('\n')
|
|
7666
|
+
.map((l) => `> ${l}`)
|
|
7667
|
+
.join('\n');
|
|
7668
|
+
}
|
|
7669
|
+
return inline;
|
|
7670
|
+
}
|
|
7671
|
+
isOrderedList(para) {
|
|
7672
|
+
const numbering = para.getNumbering();
|
|
7673
|
+
if (numbering) {
|
|
7674
|
+
const instance = this.numberingManager.getInstance(numbering.numId);
|
|
7675
|
+
if (instance) {
|
|
7676
|
+
const abstract = this.numberingManager.getAbstractNumbering(instance.getAbstractNumId());
|
|
7677
|
+
const levelDef = abstract?.getLevel(numbering.level);
|
|
7678
|
+
const format = levelDef?.getFormat();
|
|
7679
|
+
if (format)
|
|
7680
|
+
return format !== 'bullet';
|
|
7681
|
+
}
|
|
7339
7682
|
}
|
|
7340
|
-
|
|
7683
|
+
const style = (para.getStyle() ?? '').toLowerCase();
|
|
7684
|
+
if (style.includes('bullet'))
|
|
7685
|
+
return false;
|
|
7686
|
+
if (style.includes('number'))
|
|
7687
|
+
return true;
|
|
7688
|
+
return true;
|
|
7341
7689
|
}
|
|
7342
|
-
paragraphContentToMarkdown(para) {
|
|
7690
|
+
paragraphContentToMarkdown(para, ctx) {
|
|
7691
|
+
return this.inlineContentToMarkdown(para.getContent(), ctx);
|
|
7692
|
+
}
|
|
7693
|
+
inlineContentToMarkdown(items, ctx) {
|
|
7343
7694
|
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}*`;
|
|
7695
|
+
for (const item of items) {
|
|
7696
|
+
if (item instanceof ImageRun) {
|
|
7697
|
+
if (ctx.opts.images) {
|
|
7698
|
+
const image = item.getImageElement();
|
|
7699
|
+
const alt = this.escapeMarkdown(image.getAltText() || 'image');
|
|
7700
|
+
const src = image.getRelationshipId() ?? 'image';
|
|
7701
|
+
parts.push(``);
|
|
7359
7702
|
}
|
|
7360
|
-
|
|
7361
|
-
|
|
7703
|
+
}
|
|
7704
|
+
else if (item instanceof Run) {
|
|
7705
|
+
parts.push(this.runToMarkdown(item, ctx));
|
|
7706
|
+
}
|
|
7707
|
+
else if (item instanceof Hyperlink) {
|
|
7708
|
+
const runs = item.getRuns();
|
|
7709
|
+
let label = runs.length > 0
|
|
7710
|
+
? runs.map((r) => this.runToMarkdown(r, ctx, true)).join('')
|
|
7711
|
+
: this.escapeMarkdown(item.getText());
|
|
7712
|
+
if (!label)
|
|
7713
|
+
label = this.escapeMarkdown(item.getText());
|
|
7714
|
+
let url = item.getUrl() ?? '';
|
|
7715
|
+
const anchor = item.getAnchor();
|
|
7716
|
+
if (anchor)
|
|
7717
|
+
url = url ? `${url}#${anchor}` : `#${anchor}`;
|
|
7718
|
+
parts.push(`[${label}](${url})`);
|
|
7719
|
+
}
|
|
7720
|
+
else if (item instanceof Revision) {
|
|
7721
|
+
const inner = this.inlineContentToMarkdown(item.getContent(), ctx);
|
|
7722
|
+
if (!inner)
|
|
7723
|
+
continue;
|
|
7724
|
+
const type = item.getType();
|
|
7725
|
+
if (type === 'delete' || type === 'moveFrom') {
|
|
7726
|
+
parts.push(ctx.opts.htmlFallback ? `<del>${inner}</del>` : `~~${inner}~~`);
|
|
7362
7727
|
}
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
md = `\`${runText}\``;
|
|
7728
|
+
else {
|
|
7729
|
+
parts.push(inner);
|
|
7366
7730
|
}
|
|
7367
|
-
parts.push(md);
|
|
7368
7731
|
}
|
|
7369
|
-
else if (item instanceof
|
|
7370
|
-
const
|
|
7371
|
-
|
|
7372
|
-
|
|
7732
|
+
else if (item instanceof ComplexField) {
|
|
7733
|
+
const result = item.getResult();
|
|
7734
|
+
if (result)
|
|
7735
|
+
parts.push(this.escapeMarkdown(result));
|
|
7736
|
+
}
|
|
7737
|
+
else if (item instanceof Field) {
|
|
7738
|
+
const result = item.getCachedResult();
|
|
7739
|
+
if (result)
|
|
7740
|
+
parts.push(this.escapeMarkdown(result));
|
|
7741
|
+
}
|
|
7742
|
+
else if (item instanceof TextBox) {
|
|
7743
|
+
const text = item
|
|
7744
|
+
.getParagraphs()
|
|
7745
|
+
.map((p) => this.paragraphContentToMarkdown(p, ctx))
|
|
7746
|
+
.filter((s) => s !== '')
|
|
7747
|
+
.join(' ');
|
|
7748
|
+
if (text)
|
|
7749
|
+
parts.push(text);
|
|
7750
|
+
}
|
|
7751
|
+
else if (item instanceof Shape) {
|
|
7752
|
+
const text = item.getText();
|
|
7753
|
+
if (text)
|
|
7754
|
+
parts.push(this.escapeMarkdown(text));
|
|
7755
|
+
}
|
|
7756
|
+
else if (item instanceof PreservedElement) {
|
|
7757
|
+
const type = item.getElementType();
|
|
7758
|
+
if (!type.startsWith('w:comment')) {
|
|
7759
|
+
const text = this.extractTextFromRawXml(item.getRawXml());
|
|
7760
|
+
if (text)
|
|
7761
|
+
parts.push(this.escapeMarkdown(text));
|
|
7762
|
+
}
|
|
7373
7763
|
}
|
|
7374
7764
|
}
|
|
7375
7765
|
return parts.join('');
|
|
7376
7766
|
}
|
|
7377
|
-
|
|
7378
|
-
const
|
|
7379
|
-
|
|
7767
|
+
runToMarkdown(run, ctx, inLink = false) {
|
|
7768
|
+
const fmt = run.getFormatting();
|
|
7769
|
+
const isMono = !!(fmt.font &&
|
|
7770
|
+
/^(courier|consolas|monaco|menlo|source code|fira code|jetbrains mono)/i.test(fmt.font));
|
|
7771
|
+
const escape = (s) => (isMono ? s : this.escapeMarkdown(s));
|
|
7772
|
+
const segments = [];
|
|
7773
|
+
const markers = [];
|
|
7774
|
+
for (const content of run.getContent()) {
|
|
7775
|
+
switch (content.type) {
|
|
7776
|
+
case 'text':
|
|
7777
|
+
case 'instructionText':
|
|
7778
|
+
segments.push(escape(content.value ?? ''));
|
|
7779
|
+
break;
|
|
7780
|
+
case 'tab':
|
|
7781
|
+
segments.push('\t');
|
|
7782
|
+
break;
|
|
7783
|
+
case 'carriageReturn':
|
|
7784
|
+
segments.push('\n');
|
|
7785
|
+
break;
|
|
7786
|
+
case 'break':
|
|
7787
|
+
if (content.breakType !== 'page' && content.breakType !== 'column') {
|
|
7788
|
+
segments.push(ctx.opts.htmlFallback ? '<br>' : '\n');
|
|
7789
|
+
}
|
|
7790
|
+
break;
|
|
7791
|
+
case 'noBreakHyphen':
|
|
7792
|
+
segments.push('‑');
|
|
7793
|
+
break;
|
|
7794
|
+
case 'symbol':
|
|
7795
|
+
if (content.symbolChar) {
|
|
7796
|
+
const code = parseInt(content.symbolChar, 16);
|
|
7797
|
+
if (!Number.isNaN(code))
|
|
7798
|
+
segments.push(escape(String.fromCharCode(code)));
|
|
7799
|
+
}
|
|
7800
|
+
break;
|
|
7801
|
+
case 'footnoteReference':
|
|
7802
|
+
if (ctx.opts.footnotes && content.footnoteId !== undefined) {
|
|
7803
|
+
markers.push(this.noteMarker(content.footnoteId, 'fn', ctx));
|
|
7804
|
+
}
|
|
7805
|
+
break;
|
|
7806
|
+
case 'endnoteReference':
|
|
7807
|
+
if (ctx.opts.footnotes && content.endnoteId !== undefined) {
|
|
7808
|
+
markers.push(this.noteMarker(content.endnoteId, 'en', ctx));
|
|
7809
|
+
}
|
|
7810
|
+
break;
|
|
7811
|
+
default:
|
|
7812
|
+
break;
|
|
7813
|
+
}
|
|
7814
|
+
}
|
|
7815
|
+
let text = segments.join('');
|
|
7816
|
+
if (text) {
|
|
7817
|
+
if (isMono) {
|
|
7818
|
+
text = `\`${text}\``;
|
|
7819
|
+
}
|
|
7820
|
+
if (fmt.bold && fmt.italic)
|
|
7821
|
+
text = `***${text}***`;
|
|
7822
|
+
else if (fmt.bold)
|
|
7823
|
+
text = `**${text}**`;
|
|
7824
|
+
else if (fmt.italic)
|
|
7825
|
+
text = `*${text}*`;
|
|
7826
|
+
if (fmt.strike || fmt.dstrike)
|
|
7827
|
+
text = `~~${text}~~`;
|
|
7828
|
+
if (ctx.opts.htmlFallback) {
|
|
7829
|
+
if (fmt.superscript)
|
|
7830
|
+
text = `<sup>${text}</sup>`;
|
|
7831
|
+
else if (fmt.subscript)
|
|
7832
|
+
text = `<sub>${text}</sub>`;
|
|
7833
|
+
if (fmt.highlight && fmt.highlight !== 'none')
|
|
7834
|
+
text = `<mark>${text}</mark>`;
|
|
7835
|
+
if (!inLink) {
|
|
7836
|
+
if (fmt.underline && fmt.underline !== 'none')
|
|
7837
|
+
text = `<u>${text}</u>`;
|
|
7838
|
+
if (fmt.color && fmt.color !== 'auto' && /^[0-9a-fA-F]{6}$/.test(fmt.color)) {
|
|
7839
|
+
text = `<span style="color:#${fmt.color}">${text}</span>`;
|
|
7840
|
+
}
|
|
7841
|
+
}
|
|
7842
|
+
}
|
|
7843
|
+
}
|
|
7844
|
+
return text + markers.join('');
|
|
7845
|
+
}
|
|
7846
|
+
noteMarker(id, kind, ctx) {
|
|
7847
|
+
const marker = `${kind}${id}`;
|
|
7848
|
+
if (!ctx.noteMarkers.has(marker)) {
|
|
7849
|
+
ctx.noteMarkers.add(marker);
|
|
7850
|
+
const note = kind === 'fn' ? this.footnoteManager.getFootnote(id) : this.endnoteManager.getEndnote(id);
|
|
7851
|
+
let text = '';
|
|
7852
|
+
if (note) {
|
|
7853
|
+
text = note
|
|
7854
|
+
.getParagraphs()
|
|
7855
|
+
.map((p) => this.paragraphContentToMarkdown(p, ctx))
|
|
7856
|
+
.filter((s) => s !== '')
|
|
7857
|
+
.join(' ')
|
|
7858
|
+
.replace(/\s*\n\s*/g, ' ')
|
|
7859
|
+
.trim();
|
|
7860
|
+
}
|
|
7861
|
+
ctx.notes.push({ marker, text });
|
|
7862
|
+
}
|
|
7863
|
+
return `[^${marker}]`;
|
|
7864
|
+
}
|
|
7865
|
+
tableToMarkdown(table, ctx) {
|
|
7866
|
+
const rows = table.getRows();
|
|
7867
|
+
if (rows.length === 0)
|
|
7380
7868
|
return [];
|
|
7381
|
-
const
|
|
7869
|
+
const isComplex = rows.some((row) => row
|
|
7870
|
+
.getCells()
|
|
7871
|
+
.some((cell) => (cell.getColumnSpan() ?? 1) > 1 ||
|
|
7872
|
+
cell.getVerticalMerge() !== undefined ||
|
|
7873
|
+
cell.hasNestedTables()));
|
|
7874
|
+
if (isComplex && ctx.opts.htmlFallback) {
|
|
7875
|
+
return this.tableToHtmlBlock(table);
|
|
7876
|
+
}
|
|
7877
|
+
const matrix = rows.map((row) => row.getCells().map((cell) => this.cellToMarkdown(cell, ctx)));
|
|
7878
|
+
const colCount = Math.max(...matrix.map((row) => row.length));
|
|
7382
7879
|
if (colCount === 0)
|
|
7383
7880
|
return [];
|
|
7384
|
-
const normalized =
|
|
7881
|
+
const normalized = matrix.map((row) => {
|
|
7385
7882
|
const padded = [...row];
|
|
7386
7883
|
while (padded.length < colCount)
|
|
7387
7884
|
padded.push('');
|
|
7388
|
-
return padded
|
|
7885
|
+
return padded;
|
|
7389
7886
|
});
|
|
7390
7887
|
const lines = [];
|
|
7391
7888
|
lines.push('| ' + normalized[0].join(' | ') + ' |');
|
|
@@ -7395,6 +7892,88 @@ export class Document {
|
|
|
7395
7892
|
}
|
|
7396
7893
|
return lines;
|
|
7397
7894
|
}
|
|
7895
|
+
cellToMarkdown(cell, ctx) {
|
|
7896
|
+
const text = cell
|
|
7897
|
+
.getParagraphs()
|
|
7898
|
+
.map((p) => this.paragraphContentToMarkdown(p, ctx))
|
|
7899
|
+
.filter((s) => s !== '')
|
|
7900
|
+
.join(' ');
|
|
7901
|
+
return text.replace(/\|/g, '\\|').replace(/<br>/g, ' ').replace(/\n/g, ' ').trim();
|
|
7902
|
+
}
|
|
7903
|
+
tableToHtmlBlock(table) {
|
|
7904
|
+
const rows = table.getRows();
|
|
7905
|
+
const rowCells = rows.map((row) => {
|
|
7906
|
+
let gridStart = 0;
|
|
7907
|
+
return row.getCells().map((cell) => {
|
|
7908
|
+
const span = cell.getColumnSpan() ?? 1;
|
|
7909
|
+
const entry = { cell, gridStart, span };
|
|
7910
|
+
gridStart += span;
|
|
7911
|
+
return entry;
|
|
7912
|
+
});
|
|
7913
|
+
});
|
|
7914
|
+
const html = ['<table>'];
|
|
7915
|
+
for (let ri = 0; ri < rowCells.length; ri++) {
|
|
7916
|
+
html.push('<tr>');
|
|
7917
|
+
for (const { cell, gridStart, span } of rowCells[ri]) {
|
|
7918
|
+
if (cell.getVerticalMerge() === 'continue')
|
|
7919
|
+
continue;
|
|
7920
|
+
let rowspan = 1;
|
|
7921
|
+
if (cell.getVerticalMerge() === 'restart') {
|
|
7922
|
+
for (let rj = ri + 1; rj < rowCells.length; rj++) {
|
|
7923
|
+
const below = rowCells[rj].find((e) => e.gridStart === gridStart);
|
|
7924
|
+
if (below?.cell.getVerticalMerge() === 'continue')
|
|
7925
|
+
rowspan++;
|
|
7926
|
+
else
|
|
7927
|
+
break;
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
const tag = ri === 0 ? 'th' : 'td';
|
|
7931
|
+
const attrs = (span > 1 ? ` colspan="${span}"` : '') + (rowspan > 1 ? ` rowspan="${rowspan}"` : '');
|
|
7932
|
+
let content = cell
|
|
7933
|
+
.getParagraphs()
|
|
7934
|
+
.map((p) => this.paragraphContentToHTML(p))
|
|
7935
|
+
.filter((s) => s !== '')
|
|
7936
|
+
.join('<br>') || this.escapeHTML(cell.getText());
|
|
7937
|
+
if (cell.hasNestedTables()) {
|
|
7938
|
+
const nestedText = cell
|
|
7939
|
+
.getRawNestedContent()
|
|
7940
|
+
.map((n) => this.extractTextFromRawXml(n.xml))
|
|
7941
|
+
.filter((s) => s)
|
|
7942
|
+
.join(' ');
|
|
7943
|
+
if (nestedText)
|
|
7944
|
+
content += `<br>${this.escapeHTML(nestedText)}`;
|
|
7945
|
+
}
|
|
7946
|
+
html.push(`<${tag}${attrs}>${content}</${tag}>`);
|
|
7947
|
+
}
|
|
7948
|
+
html.push('</tr>');
|
|
7949
|
+
}
|
|
7950
|
+
html.push('</table>');
|
|
7951
|
+
return html;
|
|
7952
|
+
}
|
|
7953
|
+
escapeMarkdown(text) {
|
|
7954
|
+
return text.replace(/([\\`*_[\]<>])/g, '\\$1');
|
|
7955
|
+
}
|
|
7956
|
+
toSingleLine(text) {
|
|
7957
|
+
return text.replace(/<br>/g, ' ').replace(/\s*\n\s*/g, ' ');
|
|
7958
|
+
}
|
|
7959
|
+
extractTextFromRawXml(xml) {
|
|
7960
|
+
if (!xml.includes('<w:t'))
|
|
7961
|
+
return '';
|
|
7962
|
+
const parts = [];
|
|
7963
|
+
const regex = /<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g;
|
|
7964
|
+
let match;
|
|
7965
|
+
while ((match = regex.exec(xml)) !== null) {
|
|
7966
|
+
parts.push(match[1] ?? '');
|
|
7967
|
+
}
|
|
7968
|
+
return parts
|
|
7969
|
+
.join('')
|
|
7970
|
+
.replace(/</g, '<')
|
|
7971
|
+
.replace(/>/g, '>')
|
|
7972
|
+
.replace(/"/g, '"')
|
|
7973
|
+
.replace(/'/g, "'")
|
|
7974
|
+
.replace(/&/g, '&')
|
|
7975
|
+
.trim();
|
|
7976
|
+
}
|
|
7398
7977
|
toHTML(options) {
|
|
7399
7978
|
const parts = [];
|
|
7400
7979
|
let inList = null;
|
|
@@ -7485,8 +8064,12 @@ export class Document {
|
|
|
7485
8064
|
parts.push(html);
|
|
7486
8065
|
}
|
|
7487
8066
|
else if (item instanceof Hyperlink) {
|
|
7488
|
-
|
|
7489
|
-
const
|
|
8067
|
+
let rawUrl = item.getUrl() ?? '';
|
|
8068
|
+
const anchor = item.getAnchor();
|
|
8069
|
+
if (anchor)
|
|
8070
|
+
rawUrl = rawUrl ? `${rawUrl}#${anchor}` : `#${anchor}`;
|
|
8071
|
+
const url = this.escapeHTML(rawUrl);
|
|
8072
|
+
const linkText = this.escapeHTML(item.getText() || rawUrl);
|
|
7490
8073
|
parts.push(`<a href="${url}">${linkText}</a>`);
|
|
7491
8074
|
}
|
|
7492
8075
|
}
|
|
@@ -7634,7 +8217,10 @@ export class Document {
|
|
|
7634
8217
|
removeParagraph(paragraphOrIndex) {
|
|
7635
8218
|
let index;
|
|
7636
8219
|
if (typeof paragraphOrIndex === 'number') {
|
|
7637
|
-
|
|
8220
|
+
const para = this.getParagraphAt(paragraphOrIndex);
|
|
8221
|
+
if (!para)
|
|
8222
|
+
return false;
|
|
8223
|
+
index = this.bodyElements.indexOf(para);
|
|
7638
8224
|
}
|
|
7639
8225
|
else {
|
|
7640
8226
|
index = this.bodyElements.indexOf(paragraphOrIndex);
|
|
@@ -7643,13 +8229,8 @@ export class Document {
|
|
|
7643
8229
|
const element = this.bodyElements[index];
|
|
7644
8230
|
if (element instanceof Paragraph) {
|
|
7645
8231
|
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
|
-
}
|
|
8232
|
+
this.bindTrackingToElement(element);
|
|
8233
|
+
element.clearContent();
|
|
7653
8234
|
return true;
|
|
7654
8235
|
}
|
|
7655
8236
|
this.bodyElements.splice(index, 1);
|
|
@@ -7903,16 +8484,6 @@ export class Document {
|
|
|
7903
8484
|
for (const paragraph of this.getAllParagraphs()) {
|
|
7904
8485
|
extractHyperlinksFromParagraph(paragraph);
|
|
7905
8486
|
}
|
|
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
8487
|
return hyperlinks;
|
|
7917
8488
|
}
|
|
7918
8489
|
collectAllReferencedHyperlinkIds() {
|
|
@@ -8037,17 +8608,6 @@ export class Document {
|
|
|
8037
8608
|
bookmarks.push({ bookmark, paragraph });
|
|
8038
8609
|
}
|
|
8039
8610
|
}
|
|
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
8611
|
return bookmarks;
|
|
8052
8612
|
}
|
|
8053
8613
|
getFields() {
|
|
@@ -8057,18 +8617,6 @@ export class Document {
|
|
|
8057
8617
|
results.push({ field, paragraph });
|
|
8058
8618
|
}
|
|
8059
8619
|
}
|
|
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
8620
|
return results;
|
|
8073
8621
|
}
|
|
8074
8622
|
getImages() {
|
|
@@ -8107,7 +8655,7 @@ export class Document {
|
|
|
8107
8655
|
await entry.image.updateImageData(result.data);
|
|
8108
8656
|
}
|
|
8109
8657
|
if (result.newExtension !== extension) {
|
|
8110
|
-
const newFilename = filename.replace(/\.[^.]+$/, `.${result.newExtension}`);
|
|
8658
|
+
const newFilename = this.resolveUniqueMediaFilename(filename.replace(/\.[^.]+$/, `.${result.newExtension}`), filename);
|
|
8111
8659
|
this.imageManager.updateEntryFilename(image, newFilename);
|
|
8112
8660
|
for (const entry of entries) {
|
|
8113
8661
|
this.updateImageRelationshipTarget(entry.relationshipId, filename, newFilename);
|
|
@@ -8118,6 +8666,20 @@ export class Document {
|
|
|
8118
8666
|
}
|
|
8119
8667
|
return { optimizedCount, totalSavedBytes: totalSaved };
|
|
8120
8668
|
}
|
|
8669
|
+
resolveUniqueMediaFilename(candidate, currentFilename) {
|
|
8670
|
+
const dotIndex = candidate.lastIndexOf('.');
|
|
8671
|
+
const base = dotIndex === -1 ? candidate : candidate.slice(0, dotIndex);
|
|
8672
|
+
const ext = dotIndex === -1 ? '' : candidate.slice(dotIndex);
|
|
8673
|
+
const isTaken = (name) => this.zipHandler.hasFile(`word/media/${name}`) ||
|
|
8674
|
+
this.imageManager.isFilenameOwnedByOther(name, currentFilename);
|
|
8675
|
+
let name = candidate;
|
|
8676
|
+
let counter = 1;
|
|
8677
|
+
while (isTaken(name)) {
|
|
8678
|
+
name = `${base}-${counter}${ext}`;
|
|
8679
|
+
counter++;
|
|
8680
|
+
}
|
|
8681
|
+
return name;
|
|
8682
|
+
}
|
|
8121
8683
|
updateImageRelationshipTarget(relId, oldFilename, newFilename) {
|
|
8122
8684
|
const rel = this.relationshipManager.getRelationship(relId);
|
|
8123
8685
|
if (rel) {
|
|
@@ -8241,7 +8803,7 @@ export class Document {
|
|
|
8241
8803
|
const toRemove = [];
|
|
8242
8804
|
this.bodyElements.forEach((element, index) => {
|
|
8243
8805
|
if (element instanceof Paragraph) {
|
|
8244
|
-
const isEmpty =
|
|
8806
|
+
const isEmpty = this.isParagraphRemovableBlank(element);
|
|
8245
8807
|
if (isEmpty && lastWasEmpty) {
|
|
8246
8808
|
toRemove.push(index);
|
|
8247
8809
|
}
|
|
@@ -8325,11 +8887,30 @@ export class Document {
|
|
|
8325
8887
|
}
|
|
8326
8888
|
return { removed, normalized };
|
|
8327
8889
|
}
|
|
8890
|
+
isParagraphRemovableBlank(para) {
|
|
8891
|
+
if (para.getText().trim() !== '')
|
|
8892
|
+
return false;
|
|
8893
|
+
if (para.formatting.sectPr !== undefined)
|
|
8894
|
+
return false;
|
|
8895
|
+
if (para.getBookmarksStart().length > 0 || para.getBookmarksEnd().length > 0) {
|
|
8896
|
+
return false;
|
|
8897
|
+
}
|
|
8898
|
+
if (para.getCommentsStart().length > 0 || para.getCommentsEnd().length > 0) {
|
|
8899
|
+
return false;
|
|
8900
|
+
}
|
|
8901
|
+
for (const item of para.getContent()) {
|
|
8902
|
+
if (item instanceof ImageRun || item instanceof Shape || item instanceof RangeMarker) {
|
|
8903
|
+
return false;
|
|
8904
|
+
}
|
|
8905
|
+
}
|
|
8906
|
+
return true;
|
|
8907
|
+
}
|
|
8328
8908
|
setLanguage(language) {
|
|
8329
8909
|
if (!this.properties) {
|
|
8330
8910
|
this.properties = {};
|
|
8331
8911
|
}
|
|
8332
8912
|
this.properties.language = language;
|
|
8913
|
+
this._corePropsModified = true;
|
|
8333
8914
|
return this;
|
|
8334
8915
|
}
|
|
8335
8916
|
getLanguage() {
|
|
@@ -8445,32 +9026,6 @@ export class Document {
|
|
|
8445
9026
|
pattern.lastIndex = 0;
|
|
8446
9027
|
}
|
|
8447
9028
|
}
|
|
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
9029
|
return replacedCount;
|
|
8475
9030
|
}
|
|
8476
9031
|
static createEmpty() {
|