docxmlater 10.0.1 → 10.0.3
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 +3 -2
- package/dist/constants/legacyCompatFlags.d.ts.map +1 -1
- package/dist/constants/legacyCompatFlags.js.map +1 -1
- package/dist/constants/limits.d.ts +0 -27
- package/dist/constants/limits.d.ts.map +1 -1
- package/dist/constants/limits.js +13 -13
- package/dist/constants/limits.js.map +1 -1
- package/dist/core/Document.d.ts +24 -19
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +272 -71
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentContent.d.ts.map +1 -1
- package/dist/core/DocumentContent.js.map +1 -1
- package/dist/core/DocumentGenerator.d.ts.map +1 -1
- package/dist/core/DocumentGenerator.js +59 -24
- package/dist/core/DocumentGenerator.js.map +1 -1
- package/dist/core/DocumentIdManager.d.ts.map +1 -1
- package/dist/core/DocumentIdManager.js.map +1 -1
- package/dist/core/DocumentParser.d.ts +6 -6
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +60 -54
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/core/DocumentValidator.d.ts.map +1 -1
- package/dist/core/DocumentValidator.js.map +1 -1
- package/dist/core/Relationship.d.ts.map +1 -1
- package/dist/core/Relationship.js +1 -1
- package/dist/core/Relationship.js.map +1 -1
- package/dist/core/RelationshipManager.js +3 -3
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/elements/AlternateContent.js.map +1 -1
- package/dist/elements/Bookmark.d.ts.map +1 -1
- package/dist/elements/Bookmark.js.map +1 -1
- package/dist/elements/BookmarkManager.d.ts.map +1 -1
- package/dist/elements/BookmarkManager.js.map +1 -1
- package/dist/elements/Comment.js +1 -1
- package/dist/elements/Comment.js.map +1 -1
- package/dist/elements/CommentManager.d.ts.map +1 -1
- package/dist/elements/CommentManager.js +8 -2
- package/dist/elements/CommentManager.js.map +1 -1
- package/dist/elements/CommonTypes.d.ts.map +1 -1
- package/dist/elements/CommonTypes.js +1 -2
- package/dist/elements/CommonTypes.js.map +1 -1
- package/dist/elements/CustomXml.js.map +1 -1
- package/dist/elements/Endnote.d.ts.map +1 -1
- package/dist/elements/Endnote.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.map +1 -1
- package/dist/elements/Field.js +31 -28
- package/dist/elements/Field.js.map +1 -1
- package/dist/elements/FieldHelpers.d.ts.map +1 -1
- package/dist/elements/FieldHelpers.js +6 -6
- package/dist/elements/FieldHelpers.js.map +1 -1
- package/dist/elements/FontManager.d.ts.map +1 -1
- package/dist/elements/FontManager.js.map +1 -1
- package/dist/elements/Footer.js.map +1 -1
- package/dist/elements/Footnote.d.ts.map +1 -1
- package/dist/elements/Footnote.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.js.map +1 -1
- package/dist/elements/HeaderFooterManager.js.map +1 -1
- package/dist/elements/Hyperlink.d.ts.map +1 -1
- package/dist/elements/Hyperlink.js +5 -5
- package/dist/elements/Hyperlink.js.map +1 -1
- package/dist/elements/Image.d.ts +2 -2
- package/dist/elements/Image.d.ts.map +1 -1
- package/dist/elements/Image.js +21 -5
- package/dist/elements/Image.js.map +1 -1
- package/dist/elements/ImageManager.d.ts.map +1 -1
- package/dist/elements/ImageManager.js +2 -2
- package/dist/elements/ImageManager.js.map +1 -1
- package/dist/elements/ImageRun.js.map +1 -1
- package/dist/elements/MathElement.js.map +1 -1
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +128 -117
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/elements/PreservedElement.js.map +1 -1
- package/dist/elements/PropertyChangeTypes.js.map +1 -1
- package/dist/elements/RangeMarker.js.map +1 -1
- package/dist/elements/Revision.d.ts +1 -0
- package/dist/elements/Revision.d.ts.map +1 -1
- package/dist/elements/Revision.js +44 -5
- package/dist/elements/Revision.js.map +1 -1
- package/dist/elements/RevisionContent.js.map +1 -1
- package/dist/elements/RevisionManager.d.ts.map +1 -1
- package/dist/elements/RevisionManager.js.map +1 -1
- package/dist/elements/Run.d.ts.map +1 -1
- package/dist/elements/Run.js +1 -3
- package/dist/elements/Run.js.map +1 -1
- package/dist/elements/Section.d.ts.map +1 -1
- package/dist/elements/Section.js +127 -118
- package/dist/elements/Section.js.map +1 -1
- package/dist/elements/Shape.d.ts.map +1 -1
- package/dist/elements/Shape.js +21 -0
- package/dist/elements/Shape.js.map +1 -1
- package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
- package/dist/elements/StructuredDocumentTag.js +20 -8
- package/dist/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/elements/Table.d.ts +2 -2
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +29 -35
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableCell.d.ts +2 -2
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +63 -67
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableGridChange.js.map +1 -1
- package/dist/elements/TableOfContents.d.ts +6 -6
- package/dist/elements/TableOfContents.d.ts.map +1 -1
- package/dist/elements/TableOfContents.js.map +1 -1
- package/dist/elements/TableOfContentsElement.js.map +1 -1
- package/dist/elements/TableRow.d.ts.map +1 -1
- package/dist/elements/TableRow.js +65 -47
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/elements/TextBox.d.ts.map +1 -1
- package/dist/elements/TextBox.js +1 -1
- package/dist/elements/TextBox.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts +1 -1
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +11 -11
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingInstance.d.ts.map +1 -1
- package/dist/formatting/NumberingInstance.js +4 -4
- package/dist/formatting/NumberingInstance.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +26 -26
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/NumberingManager.d.ts +1 -1
- package/dist/formatting/NumberingManager.d.ts.map +1 -1
- package/dist/formatting/NumberingManager.js.map +1 -1
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +87 -95
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +3 -3
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/helpers/CleanupHelper.d.ts.map +1 -1
- package/dist/helpers/CleanupHelper.js +1 -7
- package/dist/helpers/CleanupHelper.js.map +1 -1
- package/dist/images/ImageOptimizer.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/managers/DrawingManager.d.ts.map +1 -1
- package/dist/managers/DrawingManager.js.map +1 -1
- package/dist/tracking/DocumentTrackingContext.js.map +1 -1
- package/dist/tracking/TrackingContext.js.map +1 -1
- package/dist/types/compatibility-types.js.map +1 -1
- package/dist/types/formatting.js.map +1 -1
- package/dist/types/list-types.d.ts +4 -4
- package/dist/types/list-types.d.ts.map +1 -1
- package/dist/types/list-types.js.map +1 -1
- package/dist/types/settings-types.js.map +1 -1
- package/dist/types/styleConfig.js.map +1 -1
- package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
- package/dist/utils/ChangelogGenerator.js.map +1 -1
- package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
- package/dist/utils/CompatibilityUpgrader.js +7 -7
- package/dist/utils/CompatibilityUpgrader.js.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.js +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/utils/MoveOperationHelper.js.map +1 -1
- package/dist/utils/RevisionAwareProcessor.js.map +1 -1
- package/dist/utils/RevisionWalker.js.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/utils/ShadingResolver.js +1 -1
- package/dist/utils/ShadingResolver.js.map +1 -1
- package/dist/utils/acceptRevisions.d.ts +0 -28
- package/dist/utils/acceptRevisions.d.ts.map +1 -1
- package/dist/utils/acceptRevisions.js +5 -7
- package/dist/utils/acceptRevisions.js.map +1 -1
- package/dist/utils/cnfStyleDecoder.js +1 -1
- package/dist/utils/cnfStyleDecoder.js.map +1 -1
- package/dist/utils/corruptionDetection.js.map +1 -1
- package/dist/utils/dateFormatting.js.map +1 -1
- package/dist/utils/deepClone.d.ts +0 -1
- package/dist/utils/deepClone.d.ts.map +1 -1
- package/dist/utils/deepClone.js +0 -7
- package/dist/utils/deepClone.js.map +1 -1
- package/dist/utils/diagnostics.d.ts +2 -2
- package/dist/utils/diagnostics.d.ts.map +1 -1
- package/dist/utils/diagnostics.js.map +1 -1
- package/dist/utils/errorHandling.js.map +1 -1
- package/dist/utils/formatting.js.map +1 -1
- package/dist/utils/list-detection.d.ts +2 -2
- package/dist/utils/list-detection.d.ts.map +1 -1
- package/dist/utils/list-detection.js +3 -3
- package/dist/utils/list-detection.js.map +1 -1
- package/dist/utils/logger.d.ts +2 -4
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +0 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/parsingHelpers.js.map +1 -1
- package/dist/utils/stripTrackedChanges.d.ts +0 -19
- package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
- package/dist/utils/stripTrackedChanges.js +0 -2
- package/dist/utils/stripTrackedChanges.js.map +1 -1
- package/dist/utils/textDiff.js.map +1 -1
- package/dist/utils/units.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/xmlSanitization.js.map +1 -1
- package/dist/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/validation/RevisionValidator.js.map +1 -1
- package/dist/validation/ValidationRules.js.map +1 -1
- package/dist/validation/index.js.map +1 -1
- package/dist/xml/XMLBuilder.d.ts.map +1 -1
- package/dist/xml/XMLBuilder.js +10 -0
- package/dist/xml/XMLBuilder.js.map +1 -1
- package/dist/xml/XMLParser.d.ts.map +1 -1
- package/dist/xml/XMLParser.js +4 -5
- package/dist/xml/XMLParser.js.map +1 -1
- package/dist/zip/ZipHandler.js.map +1 -1
- package/dist/zip/ZipReader.js.map +1 -1
- package/dist/zip/ZipWriter.js.map +1 -1
- package/dist/zip/errors.js.map +1 -1
- package/dist/zip/types.js.map +1 -1
- package/package.json +34 -4
- package/src/__tests__/helper-methods.test.ts +512 -0
- package/src/constants/legacyCompatFlags.ts +138 -0
- package/src/constants/limits.ts +50 -0
- package/src/core/CLAUDE.md +109 -0
- package/src/core/Document.ts +15569 -0
- package/src/core/DocumentContent.ts +467 -0
- package/src/core/DocumentGenerator.ts +1104 -0
- package/src/core/DocumentIdManager.ts +158 -0
- package/src/core/DocumentParser.ts +10107 -0
- package/src/core/DocumentValidator.ts +372 -0
- package/src/core/Relationship.ts +367 -0
- package/src/core/RelationshipManager.ts +428 -0
- package/src/elements/AlternateContent.ts +42 -0
- package/src/elements/Bookmark.ts +210 -0
- package/src/elements/BookmarkManager.ts +250 -0
- package/src/elements/CLAUDE.md +126 -0
- package/src/elements/Comment.ts +359 -0
- package/src/elements/CommentManager.ts +502 -0
- package/src/elements/CommonTypes.ts +549 -0
- package/src/elements/CustomXml.ts +36 -0
- package/src/elements/Endnote.ts +217 -0
- package/src/elements/EndnoteManager.ts +249 -0
- package/src/elements/Field.ts +1233 -0
- package/src/elements/FieldHelpers.ts +333 -0
- package/src/elements/FontManager.ts +339 -0
- package/src/elements/Footer.ts +269 -0
- package/src/elements/Footnote.ts +217 -0
- package/src/elements/FootnoteManager.ts +249 -0
- package/src/elements/Header.ts +269 -0
- package/src/elements/HeaderFooterManager.ts +219 -0
- package/src/elements/Hyperlink.ts +1146 -0
- package/src/elements/Image.ts +1756 -0
- package/src/elements/ImageManager.ts +432 -0
- package/src/elements/ImageRun.ts +59 -0
- package/src/elements/MathElement.ts +65 -0
- package/src/elements/Paragraph.ts +4227 -0
- package/src/elements/PreservedElement.ts +53 -0
- package/src/elements/PropertyChangeTypes.ts +442 -0
- package/src/elements/RangeMarker.ts +400 -0
- package/src/elements/Revision.ts +1217 -0
- package/src/elements/RevisionContent.ts +73 -0
- package/src/elements/RevisionManager.ts +1070 -0
- package/src/elements/Run.ts +3068 -0
- package/src/elements/Section.ts +1421 -0
- package/src/elements/Shape.ts +873 -0
- package/src/elements/StructuredDocumentTag.ts +978 -0
- package/src/elements/Table.ts +2524 -0
- package/src/elements/TableCell.ts +1586 -0
- package/src/elements/TableGridChange.ts +151 -0
- package/src/elements/TableOfContents.ts +691 -0
- package/src/elements/TableOfContentsElement.ts +89 -0
- package/src/elements/TableRow.ts +906 -0
- package/src/elements/TextBox.ts +768 -0
- package/src/formatting/AbstractNumbering.ts +548 -0
- package/src/formatting/CLAUDE.md +74 -0
- package/src/formatting/NumberingInstance.ts +212 -0
- package/src/formatting/NumberingLevel.ts +1006 -0
- package/src/formatting/NumberingManager.ts +827 -0
- package/src/formatting/Style.ts +1833 -0
- package/src/formatting/StylesManager.ts +1005 -0
- package/src/helpers/CleanupHelper.ts +524 -0
- package/src/images/ImageOptimizer.ts +274 -0
- package/src/index.ts +554 -0
- package/src/managers/CLAUDE.md +47 -0
- package/src/managers/DrawingManager.ts +319 -0
- package/src/tracking/DocumentTrackingContext.ts +643 -0
- package/src/tracking/TrackingContext.ts +173 -0
- package/src/types/compatibility-types.ts +49 -0
- package/src/types/formatting.ts +210 -0
- package/src/types/list-types.ts +152 -0
- package/src/types/settings-types.ts +59 -0
- package/src/types/styleConfig.ts +189 -0
- package/src/utils/CLAUDE.md +153 -0
- package/src/utils/ChangelogGenerator.ts +1581 -0
- package/src/utils/CompatibilityUpgrader.ts +237 -0
- package/src/utils/InMemoryRevisionAcceptor.ts +668 -0
- package/src/utils/MoveOperationHelper.ts +238 -0
- package/src/utils/RevisionAwareProcessor.ts +526 -0
- package/src/utils/RevisionWalker.ts +457 -0
- package/src/utils/SelectiveRevisionAcceptor.ts +613 -0
- package/src/utils/ShadingResolver.ts +107 -0
- package/src/utils/acceptRevisions.ts +714 -0
- package/src/utils/cnfStyleDecoder.ts +217 -0
- package/src/utils/corruptionDetection.ts +345 -0
- package/src/utils/dateFormatting.ts +20 -0
- package/src/utils/deepClone.ts +78 -0
- package/src/utils/diagnostics.ts +129 -0
- package/src/utils/errorHandling.ts +80 -0
- package/src/utils/formatting.ts +213 -0
- package/src/utils/list-detection.ts +274 -0
- package/src/utils/logger.ts +404 -0
- package/src/utils/parsingHelpers.ts +190 -0
- package/src/utils/stripTrackedChanges.ts +353 -0
- package/src/utils/textDiff.ts +100 -0
- package/src/utils/units.ts +421 -0
- package/src/utils/validation.ts +542 -0
- package/src/utils/xmlSanitization.ts +182 -0
- package/src/validation/RevisionAutoFixer.ts +542 -0
- package/src/validation/RevisionValidator.ts +460 -0
- package/src/validation/ValidationRules.ts +338 -0
- package/src/validation/index.ts +30 -0
- package/src/xml/CLAUDE.md +65 -0
- package/src/xml/XMLBuilder.ts +871 -0
- package/src/xml/XMLParser.ts +919 -0
- package/src/zip/CLAUDE.md +55 -0
- package/src/zip/ZipHandler.ts +637 -0
- package/src/zip/ZipReader.ts +299 -0
- package/src/zip/ZipWriter.ts +390 -0
- package/src/zip/errors.ts +69 -0
- package/src/zip/types.ts +116 -0
- package/dist/core/ListNormalizer.d.ts +0 -23
- package/dist/core/ListNormalizer.d.ts.map +0 -1
- package/dist/core/ListNormalizer.js +0 -624
- package/dist/core/ListNormalizer.js.map +0 -1
- package/dist/images/index.d.ts +0 -2
- package/dist/images/index.d.ts.map +0 -1
- package/dist/images/index.js +0 -8
- package/dist/images/index.js.map +0 -1
- package/dist/ms-doc/cfb/CFBReader.d.ts +0 -35
- package/dist/ms-doc/cfb/CFBReader.d.ts.map +0 -1
- package/dist/ms-doc/cfb/CFBReader.js +0 -360
- package/dist/ms-doc/cfb/CFBReader.js.map +0 -1
- package/dist/ms-doc/converter/DocToDocxConverter.d.ts +0 -55
- package/dist/ms-doc/converter/DocToDocxConverter.d.ts.map +0 -1
- package/dist/ms-doc/converter/DocToDocxConverter.js +0 -324
- package/dist/ms-doc/converter/DocToDocxConverter.js.map +0 -1
- package/dist/ms-doc/fib/FIB.d.ts +0 -18
- package/dist/ms-doc/fib/FIB.d.ts.map +0 -1
- package/dist/ms-doc/fib/FIB.js +0 -342
- package/dist/ms-doc/fib/FIB.js.map +0 -1
- package/dist/ms-doc/fields/FieldParser.d.ts +0 -31
- package/dist/ms-doc/fields/FieldParser.d.ts.map +0 -1
- package/dist/ms-doc/fields/FieldParser.js +0 -266
- package/dist/ms-doc/fields/FieldParser.js.map +0 -1
- package/dist/ms-doc/images/PictureExtractor.d.ts +0 -22
- package/dist/ms-doc/images/PictureExtractor.d.ts.map +0 -1
- package/dist/ms-doc/images/PictureExtractor.js +0 -233
- package/dist/ms-doc/images/PictureExtractor.js.map +0 -1
- package/dist/ms-doc/index.d.ts +0 -20
- package/dist/ms-doc/index.d.ts.map +0 -1
- package/dist/ms-doc/index.js +0 -59
- package/dist/ms-doc/index.js.map +0 -1
- package/dist/ms-doc/properties/SPRM.d.ts +0 -210
- package/dist/ms-doc/properties/SPRM.d.ts.map +0 -1
- package/dist/ms-doc/properties/SPRM.js +0 -633
- package/dist/ms-doc/properties/SPRM.js.map +0 -1
- package/dist/ms-doc/sections/SectionParser.d.ts +0 -25
- package/dist/ms-doc/sections/SectionParser.d.ts.map +0 -1
- package/dist/ms-doc/sections/SectionParser.js +0 -214
- package/dist/ms-doc/sections/SectionParser.js.map +0 -1
- package/dist/ms-doc/styles/StyleSheet.d.ts +0 -23
- package/dist/ms-doc/styles/StyleSheet.d.ts.map +0 -1
- package/dist/ms-doc/styles/StyleSheet.js +0 -268
- package/dist/ms-doc/styles/StyleSheet.js.map +0 -1
- package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts +0 -61
- package/dist/ms-doc/subdocuments/SubdocumentParser.d.ts.map +0 -1
- package/dist/ms-doc/subdocuments/SubdocumentParser.js +0 -208
- package/dist/ms-doc/subdocuments/SubdocumentParser.js.map +0 -1
- package/dist/ms-doc/tables/TableParser.d.ts +0 -29
- package/dist/ms-doc/tables/TableParser.d.ts.map +0 -1
- package/dist/ms-doc/tables/TableParser.js +0 -176
- package/dist/ms-doc/tables/TableParser.js.map +0 -1
- package/dist/ms-doc/text/PieceTable.d.ts +0 -21
- package/dist/ms-doc/text/PieceTable.d.ts.map +0 -1
- package/dist/ms-doc/text/PieceTable.js +0 -171
- package/dist/ms-doc/text/PieceTable.js.map +0 -1
- package/dist/ms-doc/types/Constants.d.ts +0 -99
- package/dist/ms-doc/types/Constants.d.ts.map +0 -1
- package/dist/ms-doc/types/Constants.js +0 -102
- package/dist/ms-doc/types/Constants.js.map +0 -1
- package/dist/ms-doc/types/DocTypes.d.ts +0 -368
- package/dist/ms-doc/types/DocTypes.d.ts.map +0 -1
- package/dist/ms-doc/types/DocTypes.js +0 -3
- package/dist/ms-doc/types/DocTypes.js.map +0 -1
- package/dist/tracking/index.d.ts +0 -3
- package/dist/tracking/index.d.ts.map +0 -1
- package/dist/tracking/index.js +0 -6
- package/dist/tracking/index.js.map +0 -1
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RevisionWalker - DOM-based tree walker for accepting tracked changes
|
|
3
|
+
*
|
|
4
|
+
* Replaces the fragile RegEx-based revision acceptance with a robust
|
|
5
|
+
* DOM-based approach that properly handles nested elements and preserves
|
|
6
|
+
* element ordering.
|
|
7
|
+
*
|
|
8
|
+
* @module RevisionWalker
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { ParsedXMLObject } from '../xml/XMLParser';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Options for controlling which revision types to accept
|
|
15
|
+
*/
|
|
16
|
+
export interface RevisionWalkerOptions {
|
|
17
|
+
/** Keep content, remove w:ins wrapper (default: true) */
|
|
18
|
+
acceptInsertions?: boolean;
|
|
19
|
+
/** Remove w:del and content entirely (default: true) */
|
|
20
|
+
acceptDeletions?: boolean;
|
|
21
|
+
/** Handle w:moveFrom/w:moveTo (default: true) */
|
|
22
|
+
acceptMoves?: boolean;
|
|
23
|
+
/** Remove *Change elements (default: true) */
|
|
24
|
+
acceptPropertyChanges?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Structure for tracking element order
|
|
29
|
+
*/
|
|
30
|
+
interface OrderedChildInfo {
|
|
31
|
+
type: string;
|
|
32
|
+
index: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Revision element categories
|
|
37
|
+
*/
|
|
38
|
+
const REVISION_ELEMENTS = {
|
|
39
|
+
/** Elements to unwrap (keep content, remove wrapper) */
|
|
40
|
+
UNWRAP: ['w:ins', 'w:moveTo'],
|
|
41
|
+
|
|
42
|
+
/** Elements to remove entirely (with content) */
|
|
43
|
+
REMOVE: ['w:del', 'w:moveFrom'],
|
|
44
|
+
|
|
45
|
+
/** Property change tracking elements */
|
|
46
|
+
PROPERTY_CHANGES: [
|
|
47
|
+
'w:rPrChange',
|
|
48
|
+
'w:pPrChange',
|
|
49
|
+
'w:tblPrChange',
|
|
50
|
+
'w:tcPrChange',
|
|
51
|
+
'w:trPrChange',
|
|
52
|
+
'w:sectPrChange',
|
|
53
|
+
'w:tblGridChange',
|
|
54
|
+
'w:numberingChange',
|
|
55
|
+
'w:tblPrExChange',
|
|
56
|
+
],
|
|
57
|
+
|
|
58
|
+
/** Range marker elements */
|
|
59
|
+
RANGE_MARKERS: [
|
|
60
|
+
'w:moveFromRangeStart',
|
|
61
|
+
'w:moveFromRangeEnd',
|
|
62
|
+
'w:moveToRangeStart',
|
|
63
|
+
'w:moveToRangeEnd',
|
|
64
|
+
'w:customXmlInsRangeStart',
|
|
65
|
+
'w:customXmlInsRangeEnd',
|
|
66
|
+
'w:customXmlDelRangeStart',
|
|
67
|
+
'w:customXmlDelRangeEnd',
|
|
68
|
+
'w:customXmlMoveFromRangeStart',
|
|
69
|
+
'w:customXmlMoveFromRangeEnd',
|
|
70
|
+
'w:customXmlMoveToRangeStart',
|
|
71
|
+
'w:customXmlMoveToRangeEnd',
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* DOM-based tree walker for accepting Word document revisions
|
|
77
|
+
*
|
|
78
|
+
* This class processes a parsed XML object tree (from XMLParser.parseToObject())
|
|
79
|
+
* and accepts all tracked changes by:
|
|
80
|
+
* - Unwrapping insertions (w:ins, w:moveTo) - keeping content
|
|
81
|
+
* - Removing deletions (w:del, w:moveFrom) - discarding content
|
|
82
|
+
* - Removing property changes (*Change elements)
|
|
83
|
+
* - Removing range markers
|
|
84
|
+
*
|
|
85
|
+
* Element order is preserved using the _orderedChildren metadata.
|
|
86
|
+
*/
|
|
87
|
+
export class RevisionWalker {
|
|
88
|
+
/**
|
|
89
|
+
* Process a parsed XML object tree and accept all revisions
|
|
90
|
+
*
|
|
91
|
+
* @param obj - Parsed XML object from XMLParser.parseToObject()
|
|
92
|
+
* @param options - Options controlling which revisions to accept
|
|
93
|
+
* @returns New object tree with revisions accepted
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const parsed = XMLParser.parseToObject(documentXml);
|
|
98
|
+
* const clean = RevisionWalker.processTree(parsed);
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
static processTree(
|
|
102
|
+
obj: ParsedXMLObject,
|
|
103
|
+
options?: RevisionWalkerOptions
|
|
104
|
+
): ParsedXMLObject {
|
|
105
|
+
const opts: Required<RevisionWalkerOptions> = {
|
|
106
|
+
acceptInsertions: options?.acceptInsertions ?? true,
|
|
107
|
+
acceptDeletions: options?.acceptDeletions ?? true,
|
|
108
|
+
acceptMoves: options?.acceptMoves ?? true,
|
|
109
|
+
acceptPropertyChanges: options?.acceptPropertyChanges ?? true,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Deep clone the object to avoid mutating the original
|
|
113
|
+
const clone = RevisionWalker.deepClone(obj);
|
|
114
|
+
|
|
115
|
+
// Walk and transform the tree
|
|
116
|
+
RevisionWalker.walkAndTransform(clone, opts);
|
|
117
|
+
|
|
118
|
+
return clone;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Deep clone an object
|
|
123
|
+
*/
|
|
124
|
+
private static deepClone(obj: any): any {
|
|
125
|
+
if (obj === null || typeof obj !== 'object') {
|
|
126
|
+
return obj;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (Array.isArray(obj)) {
|
|
130
|
+
return obj.map((item) => RevisionWalker.deepClone(item));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const clone: any = {};
|
|
134
|
+
for (const key of Object.keys(obj)) {
|
|
135
|
+
clone[key] = RevisionWalker.deepClone(obj[key]);
|
|
136
|
+
}
|
|
137
|
+
return clone;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Recursively walk and transform the object tree
|
|
142
|
+
* Processes children first (depth-first) to handle nested revisions
|
|
143
|
+
*/
|
|
144
|
+
private static walkAndTransform(
|
|
145
|
+
obj: any,
|
|
146
|
+
options: Required<RevisionWalkerOptions>
|
|
147
|
+
): void {
|
|
148
|
+
if (obj === null || typeof obj !== 'object') {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Get keys to process (excluding metadata keys)
|
|
153
|
+
const keys = Object.keys(obj).filter(
|
|
154
|
+
(k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// First pass: recurse into children (depth-first)
|
|
158
|
+
for (const key of keys) {
|
|
159
|
+
const value = obj[key];
|
|
160
|
+
if (Array.isArray(value)) {
|
|
161
|
+
for (const item of value) {
|
|
162
|
+
RevisionWalker.walkAndTransform(item, options);
|
|
163
|
+
}
|
|
164
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
165
|
+
RevisionWalker.walkAndTransform(value, options);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Second pass: process revision elements at this level
|
|
170
|
+
// We need to iterate carefully because we're modifying the object
|
|
171
|
+
RevisionWalker.processRevisions(obj, options);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Process revision elements at the current level
|
|
176
|
+
*/
|
|
177
|
+
private static processRevisions(
|
|
178
|
+
parent: any,
|
|
179
|
+
options: Required<RevisionWalkerOptions>
|
|
180
|
+
): void {
|
|
181
|
+
if (!parent || typeof parent !== 'object') {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const keysToProcess = Object.keys(parent).filter(
|
|
186
|
+
(k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
for (const key of keysToProcess) {
|
|
190
|
+
// Check if this is a revision element
|
|
191
|
+
if (RevisionWalker.shouldUnwrap(key, options)) {
|
|
192
|
+
RevisionWalker.unwrapAllElements(parent, key);
|
|
193
|
+
} else if (RevisionWalker.shouldRemove(key, options)) {
|
|
194
|
+
RevisionWalker.removeAllElements(parent, key);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Check if an element should be unwrapped (content kept)
|
|
201
|
+
*/
|
|
202
|
+
private static shouldUnwrap(
|
|
203
|
+
key: string,
|
|
204
|
+
options: Required<RevisionWalkerOptions>
|
|
205
|
+
): boolean {
|
|
206
|
+
if (REVISION_ELEMENTS.UNWRAP.includes(key)) {
|
|
207
|
+
if (key === 'w:ins' && !options.acceptInsertions) return false;
|
|
208
|
+
if (key === 'w:moveTo' && !options.acceptMoves) return false;
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Check if an element should be removed (content discarded)
|
|
216
|
+
*/
|
|
217
|
+
private static shouldRemove(
|
|
218
|
+
key: string,
|
|
219
|
+
options: Required<RevisionWalkerOptions>
|
|
220
|
+
): boolean {
|
|
221
|
+
if (REVISION_ELEMENTS.REMOVE.includes(key)) {
|
|
222
|
+
if (key === 'w:del' && !options.acceptDeletions) return false;
|
|
223
|
+
if (key === 'w:moveFrom' && !options.acceptMoves) return false;
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
if (REVISION_ELEMENTS.PROPERTY_CHANGES.includes(key)) {
|
|
227
|
+
return options.acceptPropertyChanges;
|
|
228
|
+
}
|
|
229
|
+
if (REVISION_ELEMENTS.RANGE_MARKERS.includes(key)) {
|
|
230
|
+
return true; // Always remove range markers
|
|
231
|
+
}
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Unwrap all elements of a given type, promoting their children to parent
|
|
237
|
+
*
|
|
238
|
+
* This is the most complex operation in RevisionWalker. When we unwrap a
|
|
239
|
+
* revision element like w:ins, we need to:
|
|
240
|
+
* 1. Extract the children from inside w:ins
|
|
241
|
+
* 2. Insert them at the correct position in the parent's element arrays
|
|
242
|
+
* 3. Update _orderedChildren to reflect the new structure
|
|
243
|
+
*
|
|
244
|
+
* The key challenge is maintaining correct element order. For example:
|
|
245
|
+
* Before: <w:tbl><w:tr>Row1</w:tr><w:ins><w:tr>Row2</w:tr></w:ins><w:tr>Row3</w:tr></w:tbl>
|
|
246
|
+
* After: <w:tbl><w:tr>Row1</w:tr><w:tr>Row2</w:tr><w:tr>Row3</w:tr></w:tbl>
|
|
247
|
+
*/
|
|
248
|
+
private static unwrapAllElements(parent: any, key: string): void {
|
|
249
|
+
const elements = parent[key];
|
|
250
|
+
if (!elements) return;
|
|
251
|
+
|
|
252
|
+
const elementArray = Array.isArray(elements) ? elements : [elements];
|
|
253
|
+
|
|
254
|
+
// Build a complete ordered list of child elements by walking _orderedChildren
|
|
255
|
+
// This captures the intended order before we modify anything
|
|
256
|
+
const orderedElements: { type: string; element: any }[] = [];
|
|
257
|
+
|
|
258
|
+
if (parent._orderedChildren) {
|
|
259
|
+
// Track how many of each type we've seen to get correct array index
|
|
260
|
+
const typeCounters = new Map<string, number>();
|
|
261
|
+
let unwrappedIndex = 0;
|
|
262
|
+
|
|
263
|
+
for (const entry of parent._orderedChildren) {
|
|
264
|
+
const { type } = entry;
|
|
265
|
+
|
|
266
|
+
if (type === key) {
|
|
267
|
+
// This is a revision element - extract its children in order
|
|
268
|
+
const revElement = elementArray[unwrappedIndex];
|
|
269
|
+
unwrappedIndex++;
|
|
270
|
+
|
|
271
|
+
if (revElement && typeof revElement === 'object') {
|
|
272
|
+
if (revElement._orderedChildren) {
|
|
273
|
+
// Use the revision element's _orderedChildren for correct order
|
|
274
|
+
const childCounters = new Map<string, number>();
|
|
275
|
+
for (const childEntry of revElement._orderedChildren) {
|
|
276
|
+
const childType = childEntry.type;
|
|
277
|
+
const childIdx = childCounters.get(childType) || 0;
|
|
278
|
+
childCounters.set(childType, childIdx + 1);
|
|
279
|
+
|
|
280
|
+
const childElements = revElement[childType];
|
|
281
|
+
if (childElements) {
|
|
282
|
+
const childArray = Array.isArray(childElements)
|
|
283
|
+
? childElements
|
|
284
|
+
: [childElements];
|
|
285
|
+
if (childIdx < childArray.length) {
|
|
286
|
+
orderedElements.push({
|
|
287
|
+
type: childType,
|
|
288
|
+
element: childArray[childIdx],
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
// No _orderedChildren, extract children in object key order
|
|
295
|
+
const childKeys = Object.keys(revElement).filter(
|
|
296
|
+
(k) =>
|
|
297
|
+
!k.startsWith('@_') &&
|
|
298
|
+
k !== '#text' &&
|
|
299
|
+
k !== '_orderedChildren'
|
|
300
|
+
);
|
|
301
|
+
for (const childKey of childKeys) {
|
|
302
|
+
const childValue = revElement[childKey];
|
|
303
|
+
const childArray = Array.isArray(childValue)
|
|
304
|
+
? childValue
|
|
305
|
+
: [childValue];
|
|
306
|
+
for (const child of childArray) {
|
|
307
|
+
orderedElements.push({ type: childKey, element: child });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
// Regular element - get it from the parent
|
|
314
|
+
const idx = typeCounters.get(type) || 0;
|
|
315
|
+
typeCounters.set(type, idx + 1);
|
|
316
|
+
|
|
317
|
+
const parentElements = parent[type];
|
|
318
|
+
if (parentElements) {
|
|
319
|
+
const parentArray = Array.isArray(parentElements)
|
|
320
|
+
? parentElements
|
|
321
|
+
: [parentElements];
|
|
322
|
+
if (idx < parentArray.length) {
|
|
323
|
+
orderedElements.push({ type, element: parentArray[idx] });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Remove the revision wrapper
|
|
331
|
+
delete parent[key];
|
|
332
|
+
|
|
333
|
+
// If we have ordered elements, rebuild the arrays in correct order
|
|
334
|
+
if (orderedElements.length > 0) {
|
|
335
|
+
// Group elements by type
|
|
336
|
+
const rebuiltArrays = new Map<string, any[]>();
|
|
337
|
+
|
|
338
|
+
for (const { type, element } of orderedElements) {
|
|
339
|
+
if (!rebuiltArrays.has(type)) {
|
|
340
|
+
rebuiltArrays.set(type, []);
|
|
341
|
+
}
|
|
342
|
+
rebuiltArrays.get(type)!.push(element);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Update parent with rebuilt arrays
|
|
346
|
+
for (const [type, elements] of rebuiltArrays) {
|
|
347
|
+
if (elements.length === 1) {
|
|
348
|
+
parent[type] = elements[0];
|
|
349
|
+
} else {
|
|
350
|
+
parent[type] = elements;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Rebuild _orderedChildren
|
|
355
|
+
const newOrderedChildren: OrderedChildInfo[] = [];
|
|
356
|
+
const typeCounters = new Map<string, number>();
|
|
357
|
+
|
|
358
|
+
for (const { type } of orderedElements) {
|
|
359
|
+
const idx = typeCounters.get(type) || 0;
|
|
360
|
+
typeCounters.set(type, idx + 1);
|
|
361
|
+
newOrderedChildren.push({ type, index: idx });
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
parent._orderedChildren = newOrderedChildren;
|
|
365
|
+
} else {
|
|
366
|
+
// Fallback for when there's no _orderedChildren - just merge
|
|
367
|
+
for (const element of elementArray) {
|
|
368
|
+
if (!element || typeof element !== 'object') continue;
|
|
369
|
+
|
|
370
|
+
const elementKeys = Object.keys(element).filter(
|
|
371
|
+
(k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
for (const childKey of elementKeys) {
|
|
375
|
+
RevisionWalker.mergeIntoParent(parent, childKey, element[childKey]);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Remove all elements of a given type (including their content)
|
|
383
|
+
*/
|
|
384
|
+
private static removeAllElements(parent: any, key: string): void {
|
|
385
|
+
if (!parent[key]) return;
|
|
386
|
+
|
|
387
|
+
// Update _orderedChildren before removing
|
|
388
|
+
if (parent._orderedChildren) {
|
|
389
|
+
parent._orderedChildren = parent._orderedChildren.filter(
|
|
390
|
+
(c: OrderedChildInfo) => c.type !== key
|
|
391
|
+
);
|
|
392
|
+
// Re-index remaining elements of same types
|
|
393
|
+
RevisionWalker.reindexOrderedChildren(parent._orderedChildren);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Remove the element
|
|
397
|
+
delete parent[key];
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Merge a child value into the parent, handling arrays properly
|
|
402
|
+
*/
|
|
403
|
+
private static mergeIntoParent(
|
|
404
|
+
parent: any,
|
|
405
|
+
childKey: string,
|
|
406
|
+
childValue: any
|
|
407
|
+
): void {
|
|
408
|
+
if (parent[childKey] === undefined) {
|
|
409
|
+
// No existing value, just assign
|
|
410
|
+
parent[childKey] = childValue;
|
|
411
|
+
} else {
|
|
412
|
+
// Existing value, need to merge
|
|
413
|
+
const existing = parent[childKey];
|
|
414
|
+
const incoming = Array.isArray(childValue) ? childValue : [childValue];
|
|
415
|
+
|
|
416
|
+
if (Array.isArray(existing)) {
|
|
417
|
+
parent[childKey] = [...existing, ...incoming];
|
|
418
|
+
} else {
|
|
419
|
+
parent[childKey] = [existing, ...incoming];
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Re-index _orderedChildren to ensure indices are sequential per type
|
|
426
|
+
*/
|
|
427
|
+
private static reindexOrderedChildren(
|
|
428
|
+
orderedChildren: OrderedChildInfo[]
|
|
429
|
+
): void {
|
|
430
|
+
const typeCounters = new Map<string, number>();
|
|
431
|
+
|
|
432
|
+
for (const entry of orderedChildren) {
|
|
433
|
+
const currentIndex = typeCounters.get(entry.type) || 0;
|
|
434
|
+
entry.index = currentIndex;
|
|
435
|
+
typeCounters.set(entry.type, currentIndex + 1);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Check if an element is a revision-related element (any type)
|
|
441
|
+
*/
|
|
442
|
+
static isRevisionElement(key: string): boolean {
|
|
443
|
+
return (
|
|
444
|
+
REVISION_ELEMENTS.UNWRAP.includes(key) ||
|
|
445
|
+
REVISION_ELEMENTS.REMOVE.includes(key) ||
|
|
446
|
+
REVISION_ELEMENTS.PROPERTY_CHANGES.includes(key) ||
|
|
447
|
+
REVISION_ELEMENTS.RANGE_MARKERS.includes(key)
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Get revision element categories (for external use/testing)
|
|
453
|
+
*/
|
|
454
|
+
static getRevisionElementCategories(): typeof REVISION_ELEMENTS {
|
|
455
|
+
return { ...REVISION_ELEMENTS };
|
|
456
|
+
}
|
|
457
|
+
}
|