docxmlater 10.1.3 → 10.1.5
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 +759 -754
- package/dist/constants/legacyCompatFlags.js +1 -1
- package/dist/constants/legacyCompatFlags.js.map +1 -1
- package/dist/constants/limits.js.map +1 -1
- package/dist/core/Document.d.ts +50 -50
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +483 -471
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentContent.d.ts +9 -9
- package/dist/core/DocumentContent.d.ts.map +1 -1
- package/dist/core/DocumentContent.js +1 -1
- package/dist/core/DocumentContent.js.map +1 -1
- package/dist/core/DocumentGenerator.d.ts +11 -11
- package/dist/core/DocumentGenerator.d.ts.map +1 -1
- package/dist/core/DocumentGenerator.js +251 -251
- package/dist/core/DocumentGenerator.js.map +1 -1
- package/dist/core/DocumentIdManager.js.map +1 -1
- package/dist/core/DocumentParser.d.ts +15 -15
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +2123 -2155
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/core/DocumentValidator.d.ts.map +1 -1
- package/dist/core/DocumentValidator.js +2 -5
- package/dist/core/DocumentValidator.js.map +1 -1
- package/dist/core/Relationship.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.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 +3 -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.d.ts.map +1 -1
- package/dist/elements/Comment.js +9 -6
- package/dist/elements/Comment.js.map +1 -1
- package/dist/elements/CommentManager.d.ts.map +1 -1
- package/dist/elements/CommentManager.js +18 -17
- package/dist/elements/CommentManager.js.map +1 -1
- package/dist/elements/CommonTypes.d.ts +21 -21
- package/dist/elements/CommonTypes.d.ts.map +1 -1
- package/dist/elements/CommonTypes.js +56 -56
- 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 +6 -6
- package/dist/elements/Endnote.js.map +1 -1
- package/dist/elements/EndnoteManager.d.ts.map +1 -1
- package/dist/elements/EndnoteManager.js +6 -7
- package/dist/elements/EndnoteManager.js.map +1 -1
- package/dist/elements/Field.d.ts.map +1 -1
- package/dist/elements/Field.js +82 -25
- package/dist/elements/Field.js.map +1 -1
- package/dist/elements/FieldHelpers.d.ts.map +1 -1
- package/dist/elements/FieldHelpers.js.map +1 -1
- package/dist/elements/FontManager.d.ts.map +1 -1
- package/dist/elements/FontManager.js +1 -1
- package/dist/elements/FontManager.js.map +1 -1
- package/dist/elements/Footer.js +2 -2
- package/dist/elements/Footer.js.map +1 -1
- package/dist/elements/Footnote.d.ts.map +1 -1
- package/dist/elements/Footnote.js +6 -6
- package/dist/elements/Footnote.js.map +1 -1
- package/dist/elements/FootnoteManager.d.ts.map +1 -1
- package/dist/elements/FootnoteManager.js +6 -7
- package/dist/elements/FootnoteManager.js.map +1 -1
- package/dist/elements/Header.js +2 -2
- package/dist/elements/Header.js.map +1 -1
- package/dist/elements/HeaderFooterManager.js.map +1 -1
- package/dist/elements/Hyperlink.d.ts +5 -3
- package/dist/elements/Hyperlink.d.ts.map +1 -1
- package/dist/elements/Hyperlink.js +134 -76
- package/dist/elements/Hyperlink.js.map +1 -1
- package/dist/elements/Image.d.ts.map +1 -1
- package/dist/elements/Image.js +238 -106
- package/dist/elements/Image.js.map +1 -1
- package/dist/elements/ImageManager.d.ts.map +1 -1
- package/dist/elements/ImageManager.js +1 -1
- package/dist/elements/ImageManager.js.map +1 -1
- package/dist/elements/ImageRun.js +1 -1
- package/dist/elements/ImageRun.js.map +1 -1
- package/dist/elements/MathElement.js.map +1 -1
- package/dist/elements/Paragraph.d.ts +24 -24
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +181 -188
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/elements/PreservedElement.js.map +1 -1
- package/dist/elements/PropertyChangeTypes.d.ts.map +1 -1
- package/dist/elements/PropertyChangeTypes.js +6 -6
- package/dist/elements/PropertyChangeTypes.js.map +1 -1
- package/dist/elements/RangeMarker.d.ts.map +1 -1
- package/dist/elements/RangeMarker.js.map +1 -1
- package/dist/elements/Revision.d.ts.map +1 -1
- package/dist/elements/Revision.js +4 -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 +40 -48
- package/dist/elements/RevisionManager.js.map +1 -1
- package/dist/elements/Run.d.ts +16 -16
- package/dist/elements/Run.d.ts.map +1 -1
- package/dist/elements/Run.js +256 -238
- package/dist/elements/Run.js.map +1 -1
- package/dist/elements/Section.d.ts.map +1 -1
- package/dist/elements/Section.js +36 -11
- package/dist/elements/Section.js.map +1 -1
- package/dist/elements/Shape.d.ts.map +1 -1
- package/dist/elements/Shape.js.map +1 -1
- package/dist/elements/StructuredDocumentTag.d.ts +6 -6
- package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
- package/dist/elements/StructuredDocumentTag.js +99 -104
- package/dist/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/elements/Table.d.ts +11 -11
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +102 -107
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableCell.d.ts +10 -10
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +105 -106
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableGridChange.d.ts.map +1 -1
- package/dist/elements/TableGridChange.js.map +1 -1
- package/dist/elements/TableOfContents.d.ts.map +1 -1
- package/dist/elements/TableOfContents.js +4 -4
- 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 +13 -6
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/elements/TextBox.d.ts.map +1 -1
- package/dist/elements/TextBox.js +3 -5
- package/dist/elements/TextBox.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts +4 -4
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +54 -49
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingInstance.d.ts.map +1 -1
- package/dist/formatting/NumberingInstance.js +1 -3
- package/dist/formatting/NumberingInstance.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts +5 -5
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +119 -125
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/NumberingManager.d.ts.map +1 -1
- package/dist/formatting/NumberingManager.js +9 -9
- package/dist/formatting/NumberingManager.js.map +1 -1
- package/dist/formatting/Style.d.ts +11 -11
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +219 -247
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +2 -2
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js +96 -102
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/helpers/CleanupHelper.d.ts +1 -1
- package/dist/helpers/CleanupHelper.d.ts.map +1 -1
- package/dist/helpers/CleanupHelper.js +6 -6
- package/dist/helpers/CleanupHelper.js.map +1 -1
- package/dist/images/ImageOptimizer.js +7 -7
- package/dist/images/ImageOptimizer.js.map +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/managers/DrawingManager.js.map +1 -1
- package/dist/tracking/DocumentTrackingContext.d.ts.map +1 -1
- package/dist/tracking/DocumentTrackingContext.js +23 -7
- package/dist/tracking/DocumentTrackingContext.js.map +1 -1
- package/dist/tracking/TrackingContext.d.ts.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 +6 -6
- package/dist/types/list-types.js.map +1 -1
- package/dist/types/settings-types.js.map +1 -1
- package/dist/types/styleConfig.d.ts +2 -2
- package/dist/types/styleConfig.js.map +1 -1
- package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
- package/dist/utils/ChangelogGenerator.js +97 -101
- package/dist/utils/ChangelogGenerator.js.map +1 -1
- package/dist/utils/CompatibilityUpgrader.d.ts.map +1 -1
- package/dist/utils/CompatibilityUpgrader.js +1 -1
- package/dist/utils/CompatibilityUpgrader.js.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.js +1 -6
- package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/utils/MoveOperationHelper.d.ts.map +1 -1
- package/dist/utils/MoveOperationHelper.js +1 -1
- package/dist/utils/MoveOperationHelper.js.map +1 -1
- package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
- package/dist/utils/RevisionAwareProcessor.js +2 -4
- package/dist/utils/RevisionAwareProcessor.js.map +1 -1
- package/dist/utils/RevisionWalker.d.ts.map +1 -1
- package/dist/utils/RevisionWalker.js +4 -12
- package/dist/utils/RevisionWalker.js.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.js +2 -6
- package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/utils/ShadingResolver.d.ts.map +1 -1
- package/dist/utils/ShadingResolver.js +1 -1
- package/dist/utils/ShadingResolver.js.map +1 -1
- package/dist/utils/acceptRevisions.d.ts.map +1 -1
- package/dist/utils/acceptRevisions.js +23 -12
- package/dist/utils/acceptRevisions.js.map +1 -1
- package/dist/utils/cnfStyleDecoder.d.ts +1 -1
- package/dist/utils/cnfStyleDecoder.d.ts.map +1 -1
- package/dist/utils/cnfStyleDecoder.js +40 -40
- package/dist/utils/cnfStyleDecoder.js.map +1 -1
- package/dist/utils/corruptionDetection.d.ts.map +1 -1
- package/dist/utils/corruptionDetection.js.map +1 -1
- package/dist/utils/dateFormatting.js.map +1 -1
- package/dist/utils/deepClone.js +1 -1
- package/dist/utils/deepClone.js.map +1 -1
- package/dist/utils/diagnostics.d.ts.map +1 -1
- package/dist/utils/diagnostics.js +1 -1
- package/dist/utils/diagnostics.js.map +1 -1
- package/dist/utils/errorHandling.js.map +1 -1
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/formatting.js +10 -2
- 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 +21 -23
- package/dist/utils/list-detection.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +12 -7
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/parsingHelpers.js.map +1 -1
- package/dist/utils/stripTrackedChanges.d.ts.map +1 -1
- package/dist/utils/stripTrackedChanges.js +3 -3
- package/dist/utils/stripTrackedChanges.js.map +1 -1
- package/dist/utils/textDiff.d.ts +1 -1
- package/dist/utils/textDiff.js +8 -8
- 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 +24 -7
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/xmlSanitization.d.ts.map +1 -1
- package/dist/utils/xmlSanitization.js +3 -3
- package/dist/utils/xmlSanitization.js.map +1 -1
- package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
- package/dist/validation/RevisionAutoFixer.js +5 -5
- package/dist/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/validation/RevisionValidator.d.ts.map +1 -1
- package/dist/validation/RevisionValidator.js +7 -9
- package/dist/validation/RevisionValidator.js.map +1 -1
- package/dist/validation/ValidationRules.js +3 -3
- package/dist/validation/ValidationRules.js.map +1 -1
- package/dist/validation/index.js.map +1 -1
- package/dist/xml/XMLBuilder.d.ts +1 -1
- package/dist/xml/XMLBuilder.d.ts.map +1 -1
- package/dist/xml/XMLBuilder.js +98 -100
- package/dist/xml/XMLBuilder.js.map +1 -1
- package/dist/xml/XMLParser.d.ts.map +1 -1
- package/dist/xml/XMLParser.js +61 -66
- package/dist/xml/XMLParser.js.map +1 -1
- package/dist/zip/ZipHandler.d.ts.map +1 -1
- package/dist/zip/ZipHandler.js.map +1 -1
- package/dist/zip/ZipReader.d.ts.map +1 -1
- package/dist/zip/ZipReader.js +1 -3
- package/dist/zip/ZipReader.js.map +1 -1
- package/dist/zip/ZipWriter.d.ts +1 -1
- package/dist/zip/ZipWriter.d.ts.map +1 -1
- package/dist/zip/ZipWriter.js +28 -36
- package/dist/zip/ZipWriter.js.map +1 -1
- package/dist/zip/types.js +1 -1
- package/dist/zip/types.js.map +1 -1
- package/package.json +92 -92
- package/src/__tests__/helper-methods.test.ts +512 -512
- package/src/constants/legacyCompatFlags.ts +138 -138
- package/src/constants/limits.ts +50 -50
- package/src/core/Document.ts +985 -1145
- package/src/core/DocumentContent.ts +461 -467
- package/src/core/DocumentGenerator.ts +1133 -1104
- package/src/core/DocumentIdManager.ts +158 -158
- package/src/core/DocumentParser.ts +2347 -2716
- package/src/core/DocumentValidator.ts +363 -372
- package/src/core/Relationship.ts +367 -367
- package/src/core/RelationshipManager.ts +429 -428
- package/src/elements/AlternateContent.ts +42 -42
- package/src/elements/Bookmark.ts +212 -210
- package/src/elements/BookmarkManager.ts +247 -250
- package/src/elements/Comment.ts +356 -359
- package/src/elements/CommentManager.ts +499 -502
- package/src/elements/CommonTypes.ts +524 -549
- package/src/elements/CustomXml.ts +36 -36
- package/src/elements/Endnote.ts +221 -217
- package/src/elements/EndnoteManager.ts +246 -249
- package/src/elements/Field.ts +1292 -1233
- package/src/elements/FieldHelpers.ts +329 -333
- package/src/elements/FontManager.ts +336 -339
- package/src/elements/Footer.ts +269 -269
- package/src/elements/Footnote.ts +221 -217
- package/src/elements/FootnoteManager.ts +246 -249
- package/src/elements/Header.ts +269 -269
- package/src/elements/HeaderFooterManager.ts +219 -219
- package/src/elements/Hyperlink.ts +1288 -1193
- package/src/elements/Image.ts +1982 -1756
- package/src/elements/ImageManager.ts +437 -432
- package/src/elements/ImageRun.ts +59 -59
- package/src/elements/MathElement.ts +65 -65
- package/src/elements/Paragraph.ts +4347 -4287
- package/src/elements/PreservedElement.ts +53 -53
- package/src/elements/PropertyChangeTypes.ts +458 -442
- package/src/elements/RangeMarker.ts +382 -400
- package/src/elements/Revision.ts +1198 -1217
- package/src/elements/RevisionContent.ts +73 -73
- package/src/elements/RevisionManager.ts +1070 -1070
- package/src/elements/Run.ts +3103 -3073
- package/src/elements/Section.ts +1521 -1421
- package/src/elements/Shape.ts +884 -873
- package/src/elements/StructuredDocumentTag.ts +1176 -1207
- package/src/elements/Table.ts +2468 -2524
- package/src/elements/TableCell.ts +1617 -1621
- package/src/elements/TableGridChange.ts +149 -151
- package/src/elements/TableOfContents.ts +701 -691
- package/src/elements/TableOfContentsElement.ts +89 -89
- package/src/elements/TableRow.ts +960 -929
- package/src/elements/TextBox.ts +766 -768
- package/src/formatting/AbstractNumbering.ts +580 -579
- package/src/formatting/NumberingInstance.ts +295 -299
- package/src/formatting/NumberingLevel.ts +981 -1040
- package/src/formatting/NumberingManager.ts +833 -827
- package/src/formatting/Style.ts +1785 -1879
- package/src/formatting/StylesManager.ts +1090 -1130
- package/src/helpers/CleanupHelper.ts +524 -524
- package/src/images/ImageOptimizer.ts +274 -274
- package/src/index.ts +559 -554
- package/src/managers/DrawingManager.ts +319 -319
- package/src/tracking/DocumentTrackingContext.ts +687 -674
- package/src/tracking/TrackingContext.ts +175 -173
- package/src/types/compatibility-types.ts +49 -49
- package/src/types/formatting.ts +210 -210
- package/src/types/list-types.ts +14 -14
- package/src/types/settings-types.ts +59 -59
- package/src/types/styleConfig.ts +189 -189
- package/src/utils/ChangelogGenerator.ts +1583 -1581
- package/src/utils/CompatibilityUpgrader.ts +235 -237
- package/src/utils/InMemoryRevisionAcceptor.ts +691 -696
- package/src/utils/MoveOperationHelper.ts +233 -238
- package/src/utils/RevisionAwareProcessor.ts +518 -526
- package/src/utils/RevisionWalker.ts +427 -457
- package/src/utils/SelectiveRevisionAcceptor.ts +662 -683
- package/src/utils/ShadingResolver.ts +105 -107
- package/src/utils/acceptRevisions.ts +723 -714
- package/src/utils/cnfStyleDecoder.ts +212 -217
- package/src/utils/corruptionDetection.ts +346 -345
- package/src/utils/dateFormatting.ts +20 -20
- package/src/utils/deepClone.ts +77 -78
- package/src/utils/diagnostics.ts +125 -129
- package/src/utils/errorHandling.ts +80 -80
- package/src/utils/formatting.ts +220 -213
- package/src/utils/list-detection.ts +32 -42
- package/src/utils/logger.ts +412 -404
- package/src/utils/parsingHelpers.ts +190 -190
- package/src/utils/stripTrackedChanges.ts +356 -353
- package/src/utils/textDiff.ts +100 -100
- package/src/utils/units.ts +421 -421
- package/src/utils/validation.ts +553 -542
- package/src/utils/xmlSanitization.ts +179 -182
- package/src/validation/RevisionAutoFixer.ts +541 -542
- package/src/validation/RevisionValidator.ts +470 -460
- package/src/validation/ValidationRules.ts +338 -338
- package/src/validation/index.ts +30 -30
- package/src/xml/XMLBuilder.ts +857 -871
- package/src/xml/XMLParser.ts +877 -919
- package/src/zip/ZipHandler.ts +629 -637
- package/src/zip/ZipReader.ts +295 -299
- package/src/zip/ZipWriter.ts +374 -390
- package/src/zip/types.ts +116 -116
|
@@ -1,542 +1,541 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RevisionAutoFixer - Automatically fixes revision validation issues
|
|
3
|
-
*
|
|
4
|
-
* Provides auto-fix capabilities for common revision compliance issues,
|
|
5
|
-
* helping to prevent document corruption while preserving user intent.
|
|
6
|
-
*
|
|
7
|
-
* @module RevisionAutoFixer
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { Document } from '../core/Document';
|
|
11
|
-
import type { Revision } from '../elements/Revision';
|
|
12
|
-
import {
|
|
13
|
-
REVISION_RULES,
|
|
14
|
-
AutoFixOptions,
|
|
15
|
-
AutoFixResult,
|
|
16
|
-
FixAction,
|
|
17
|
-
ValidationIssue,
|
|
18
|
-
} from './ValidationRules';
|
|
19
|
-
import { RevisionValidator } from './RevisionValidator';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Automatically fixes revision validation issues.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```typescript
|
|
26
|
-
* // Auto-fix all issues
|
|
27
|
-
* const result = RevisionAutoFixer.fix(doc);
|
|
28
|
-
* console.log(`Fixed ${result.issuesFixed} issues`);
|
|
29
|
-
*
|
|
30
|
-
* // Dry run (preview fixes without applying)
|
|
31
|
-
* const preview = RevisionAutoFixer.fix(doc, { dryRun: true });
|
|
32
|
-
* for (const action of preview.actions) {
|
|
33
|
-
* console.log(`Would fix: ${action.action}`);
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
export class RevisionAutoFixer {
|
|
38
|
-
/**
|
|
39
|
-
* Auto-fix all fixable issues in a document.
|
|
40
|
-
*
|
|
41
|
-
* @param doc - Document to fix
|
|
42
|
-
* @param options - Fix options
|
|
43
|
-
* @returns Result with details of all fixes applied
|
|
44
|
-
*/
|
|
45
|
-
static fix(doc: Document, options?: AutoFixOptions): AutoFixResult {
|
|
46
|
-
const actions: FixAction[] = [];
|
|
47
|
-
const errors: string[] = [];
|
|
48
|
-
const revisionManager = doc.getRevisionManager();
|
|
49
|
-
|
|
50
|
-
if (!revisionManager) {
|
|
51
|
-
return {
|
|
52
|
-
allFixed: true,
|
|
53
|
-
issuesFixed: 0,
|
|
54
|
-
issuesRemaining: 0,
|
|
55
|
-
actions: [],
|
|
56
|
-
errors: [],
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const revisions = revisionManager.getAllRevisions();
|
|
61
|
-
const skipRules = new Set(options?.skipRules || []);
|
|
62
|
-
const onlyRules = options?.onlyRules ? new Set(options.onlyRules) : null;
|
|
63
|
-
|
|
64
|
-
// Helper to check if a rule should be processed
|
|
65
|
-
const shouldProcess = (ruleCode: string) => {
|
|
66
|
-
if (skipRules.has(ruleCode)) return false;
|
|
67
|
-
if (onlyRules && !onlyRules.has(ruleCode)) return false;
|
|
68
|
-
return true;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
// Fix duplicate IDs (REV001)
|
|
73
|
-
if (shouldProcess('REV001')) {
|
|
74
|
-
actions.push(...this.fixDuplicateIds(revisions, options?.dryRun));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Fix missing authors (REV002)
|
|
78
|
-
if (shouldProcess('REV002')) {
|
|
79
|
-
const defaultAuthor = options?.defaultAuthor || 'Unknown Author';
|
|
80
|
-
actions.push(...this.fixMissingAuthors(revisions, defaultAuthor, options?.dryRun));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Fix orphaned move markers (REV003, REV004)
|
|
84
|
-
if (shouldProcess('REV003') || shouldProcess('REV004')) {
|
|
85
|
-
actions.push(...this.fixOrphanedMoveMarkers(revisionManager, revisions, options?.dryRun));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Fix missing dates (REV101)
|
|
89
|
-
if (shouldProcess('REV101')) {
|
|
90
|
-
actions.push(...this.fixMissingDates(revisions, options?.dryRun));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Fix invalid dates (REV102)
|
|
94
|
-
if (shouldProcess('REV102')) {
|
|
95
|
-
actions.push(...this.fixInvalidDates(revisions, options?.dryRun));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Fix empty revisions (REV103)
|
|
99
|
-
if (shouldProcess('REV103')) {
|
|
100
|
-
actions.push(...this.fixEmptyRevisions(revisionManager, revisions, options?.dryRun));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Fix non-sequential IDs (REV104)
|
|
104
|
-
if (shouldProcess('REV104')) {
|
|
105
|
-
actions.push(...this.fixNonSequentialIds(revisions, options?.dryRun));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* @param
|
|
137
|
-
* @
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* @param
|
|
180
|
-
* @param
|
|
181
|
-
* @
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* @param
|
|
224
|
-
* @
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* @param
|
|
264
|
-
* @
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
* @param
|
|
304
|
-
* @param
|
|
305
|
-
* @
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
* @param
|
|
386
|
-
* @param
|
|
387
|
-
* @
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
'
|
|
399
|
-
'
|
|
400
|
-
'
|
|
401
|
-
'
|
|
402
|
-
'
|
|
403
|
-
'
|
|
404
|
-
'
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* @param
|
|
449
|
-
* @
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
* @param
|
|
506
|
-
* @
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
* @
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
lines.push(`
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* RevisionAutoFixer - Automatically fixes revision validation issues
|
|
3
|
+
*
|
|
4
|
+
* Provides auto-fix capabilities for common revision compliance issues,
|
|
5
|
+
* helping to prevent document corruption while preserving user intent.
|
|
6
|
+
*
|
|
7
|
+
* @module RevisionAutoFixer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Document } from '../core/Document';
|
|
11
|
+
import type { Revision } from '../elements/Revision';
|
|
12
|
+
import {
|
|
13
|
+
REVISION_RULES,
|
|
14
|
+
AutoFixOptions,
|
|
15
|
+
AutoFixResult,
|
|
16
|
+
FixAction,
|
|
17
|
+
ValidationIssue,
|
|
18
|
+
} from './ValidationRules';
|
|
19
|
+
import { RevisionValidator } from './RevisionValidator';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Automatically fixes revision validation issues.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Auto-fix all issues
|
|
27
|
+
* const result = RevisionAutoFixer.fix(doc);
|
|
28
|
+
* console.log(`Fixed ${result.issuesFixed} issues`);
|
|
29
|
+
*
|
|
30
|
+
* // Dry run (preview fixes without applying)
|
|
31
|
+
* const preview = RevisionAutoFixer.fix(doc, { dryRun: true });
|
|
32
|
+
* for (const action of preview.actions) {
|
|
33
|
+
* console.log(`Would fix: ${action.action}`);
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export class RevisionAutoFixer {
|
|
38
|
+
/**
|
|
39
|
+
* Auto-fix all fixable issues in a document.
|
|
40
|
+
*
|
|
41
|
+
* @param doc - Document to fix
|
|
42
|
+
* @param options - Fix options
|
|
43
|
+
* @returns Result with details of all fixes applied
|
|
44
|
+
*/
|
|
45
|
+
static fix(doc: Document, options?: AutoFixOptions): AutoFixResult {
|
|
46
|
+
const actions: FixAction[] = [];
|
|
47
|
+
const errors: string[] = [];
|
|
48
|
+
const revisionManager = doc.getRevisionManager();
|
|
49
|
+
|
|
50
|
+
if (!revisionManager) {
|
|
51
|
+
return {
|
|
52
|
+
allFixed: true,
|
|
53
|
+
issuesFixed: 0,
|
|
54
|
+
issuesRemaining: 0,
|
|
55
|
+
actions: [],
|
|
56
|
+
errors: [],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const revisions = revisionManager.getAllRevisions();
|
|
61
|
+
const skipRules = new Set(options?.skipRules || []);
|
|
62
|
+
const onlyRules = options?.onlyRules ? new Set(options.onlyRules) : null;
|
|
63
|
+
|
|
64
|
+
// Helper to check if a rule should be processed
|
|
65
|
+
const shouldProcess = (ruleCode: string) => {
|
|
66
|
+
if (skipRules.has(ruleCode)) return false;
|
|
67
|
+
if (onlyRules && !onlyRules.has(ruleCode)) return false;
|
|
68
|
+
return true;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
// Fix duplicate IDs (REV001)
|
|
73
|
+
if (shouldProcess('REV001')) {
|
|
74
|
+
actions.push(...this.fixDuplicateIds(revisions, options?.dryRun));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Fix missing authors (REV002)
|
|
78
|
+
if (shouldProcess('REV002')) {
|
|
79
|
+
const defaultAuthor = options?.defaultAuthor || 'Unknown Author';
|
|
80
|
+
actions.push(...this.fixMissingAuthors(revisions, defaultAuthor, options?.dryRun));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Fix orphaned move markers (REV003, REV004)
|
|
84
|
+
if (shouldProcess('REV003') || shouldProcess('REV004')) {
|
|
85
|
+
actions.push(...this.fixOrphanedMoveMarkers(revisionManager, revisions, options?.dryRun));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Fix missing dates (REV101)
|
|
89
|
+
if (shouldProcess('REV101')) {
|
|
90
|
+
actions.push(...this.fixMissingDates(revisions, options?.dryRun));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Fix invalid dates (REV102)
|
|
94
|
+
if (shouldProcess('REV102')) {
|
|
95
|
+
actions.push(...this.fixInvalidDates(revisions, options?.dryRun));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Fix empty revisions (REV103)
|
|
99
|
+
if (shouldProcess('REV103')) {
|
|
100
|
+
actions.push(...this.fixEmptyRevisions(revisionManager, revisions, options?.dryRun));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Fix non-sequential IDs (REV104)
|
|
104
|
+
if (shouldProcess('REV104')) {
|
|
105
|
+
actions.push(...this.fixNonSequentialIds(revisions, options?.dryRun));
|
|
106
|
+
}
|
|
107
|
+
} catch (error: unknown) {
|
|
108
|
+
errors.push(`Fix error: ${error instanceof Error ? error.message : String(error)}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Validate after fixes
|
|
112
|
+
const postValidation = RevisionValidator.validate(doc);
|
|
113
|
+
|
|
114
|
+
// Log actions if verbose
|
|
115
|
+
if (options?.verbose) {
|
|
116
|
+
for (const action of actions) {
|
|
117
|
+
console.log(`[AutoFix] ${action.action}: ${action.issue.code}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
allFixed: postValidation.valid,
|
|
123
|
+
issuesFixed: actions.filter((a) => a.success).length,
|
|
124
|
+
issuesRemaining: postValidation.summary.errorCount + postValidation.summary.warningCount,
|
|
125
|
+
actions,
|
|
126
|
+
errors,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Fix duplicate revision IDs by reassigning.
|
|
132
|
+
*
|
|
133
|
+
* Assigns new unique IDs to revisions with duplicate IDs.
|
|
134
|
+
*
|
|
135
|
+
* @param revisions - Array of revisions
|
|
136
|
+
* @param dryRun - If true, only report changes without applying
|
|
137
|
+
* @returns Array of fix actions
|
|
138
|
+
*/
|
|
139
|
+
static fixDuplicateIds(revisions: Revision[], dryRun?: boolean): FixAction[] {
|
|
140
|
+
const actions: FixAction[] = [];
|
|
141
|
+
const usedIds = new Set<number>();
|
|
142
|
+
let nextId = Math.max(...revisions.map((r) => r.getId()), 0) + 1;
|
|
143
|
+
|
|
144
|
+
for (const rev of revisions) {
|
|
145
|
+
const id = rev.getId();
|
|
146
|
+
|
|
147
|
+
if (usedIds.has(id)) {
|
|
148
|
+
const newId = nextId++;
|
|
149
|
+
const issue: ValidationIssue = {
|
|
150
|
+
code: REVISION_RULES.DUPLICATE_ID.code,
|
|
151
|
+
severity: 'error',
|
|
152
|
+
message: `Duplicate ID ${id}`,
|
|
153
|
+
location: { revisionId: id },
|
|
154
|
+
autoFixable: true,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
actions.push({
|
|
158
|
+
issue,
|
|
159
|
+
action: `Reassigned duplicate ID ${id} to ${newId}`,
|
|
160
|
+
before: id,
|
|
161
|
+
after: newId,
|
|
162
|
+
success: true,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (!dryRun) {
|
|
166
|
+
rev.setId(newId);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
usedIds.add(rev.getId());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return actions;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Fix missing authors by setting a default value.
|
|
177
|
+
*
|
|
178
|
+
* @param revisions - Array of revisions
|
|
179
|
+
* @param defaultAuthor - Default author name to use
|
|
180
|
+
* @param dryRun - If true, only report changes without applying
|
|
181
|
+
* @returns Array of fix actions
|
|
182
|
+
*/
|
|
183
|
+
static fixMissingAuthors(
|
|
184
|
+
revisions: Revision[],
|
|
185
|
+
defaultAuthor: string,
|
|
186
|
+
dryRun?: boolean
|
|
187
|
+
): FixAction[] {
|
|
188
|
+
const actions: FixAction[] = [];
|
|
189
|
+
|
|
190
|
+
for (const rev of revisions) {
|
|
191
|
+
const author = rev.getAuthor();
|
|
192
|
+
|
|
193
|
+
if (!author || author.trim() === '') {
|
|
194
|
+
const issue: ValidationIssue = {
|
|
195
|
+
code: REVISION_RULES.MISSING_AUTHOR.code,
|
|
196
|
+
severity: 'error',
|
|
197
|
+
message: `Missing author for revision ${rev.getId()}`,
|
|
198
|
+
location: { revisionId: rev.getId() },
|
|
199
|
+
autoFixable: true,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
actions.push({
|
|
203
|
+
issue,
|
|
204
|
+
action: `Set author to "${defaultAuthor}" for revision ${rev.getId()}`,
|
|
205
|
+
before: author,
|
|
206
|
+
after: defaultAuthor,
|
|
207
|
+
success: true,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (!dryRun) {
|
|
211
|
+
rev.setAuthor(defaultAuthor);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return actions;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Fix missing dates by setting current date.
|
|
221
|
+
*
|
|
222
|
+
* @param revisions - Array of revisions
|
|
223
|
+
* @param dryRun - If true, only report changes without applying
|
|
224
|
+
* @returns Array of fix actions
|
|
225
|
+
*/
|
|
226
|
+
static fixMissingDates(revisions: Revision[], dryRun?: boolean): FixAction[] {
|
|
227
|
+
const actions: FixAction[] = [];
|
|
228
|
+
const now = new Date();
|
|
229
|
+
|
|
230
|
+
for (const rev of revisions) {
|
|
231
|
+
const date = rev.getDate();
|
|
232
|
+
|
|
233
|
+
if (!date) {
|
|
234
|
+
const issue: ValidationIssue = {
|
|
235
|
+
code: REVISION_RULES.MISSING_DATE.code,
|
|
236
|
+
severity: 'warning',
|
|
237
|
+
message: `Missing date for revision ${rev.getId()}`,
|
|
238
|
+
location: { revisionId: rev.getId() },
|
|
239
|
+
autoFixable: true,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
actions.push({
|
|
243
|
+
issue,
|
|
244
|
+
action: `Set date to ${now.toISOString()} for revision ${rev.getId()}`,
|
|
245
|
+
before: null,
|
|
246
|
+
after: now,
|
|
247
|
+
success: true,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
if (!dryRun) {
|
|
251
|
+
rev.setDate(now);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return actions;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Fix invalid dates by replacing with current date.
|
|
261
|
+
*
|
|
262
|
+
* @param revisions - Array of revisions
|
|
263
|
+
* @param dryRun - If true, only report changes without applying
|
|
264
|
+
* @returns Array of fix actions
|
|
265
|
+
*/
|
|
266
|
+
static fixInvalidDates(revisions: Revision[], dryRun?: boolean): FixAction[] {
|
|
267
|
+
const actions: FixAction[] = [];
|
|
268
|
+
const now = new Date();
|
|
269
|
+
|
|
270
|
+
for (const rev of revisions) {
|
|
271
|
+
const date = rev.getDate();
|
|
272
|
+
|
|
273
|
+
if (date && isNaN(date.getTime())) {
|
|
274
|
+
const issue: ValidationIssue = {
|
|
275
|
+
code: REVISION_RULES.INVALID_DATE_FORMAT.code,
|
|
276
|
+
severity: 'warning',
|
|
277
|
+
message: `Invalid date for revision ${rev.getId()}`,
|
|
278
|
+
location: { revisionId: rev.getId() },
|
|
279
|
+
autoFixable: true,
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
actions.push({
|
|
283
|
+
issue,
|
|
284
|
+
action: `Replaced invalid date with ${now.toISOString()} for revision ${rev.getId()}`,
|
|
285
|
+
before: date,
|
|
286
|
+
after: now,
|
|
287
|
+
success: true,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
if (!dryRun) {
|
|
291
|
+
rev.setDate(now);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return actions;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Fix orphaned move markers by removing them.
|
|
301
|
+
*
|
|
302
|
+
* @param revisionManager - RevisionManager instance
|
|
303
|
+
* @param revisions - Array of revisions
|
|
304
|
+
* @param dryRun - If true, only report changes without applying
|
|
305
|
+
* @returns Array of fix actions
|
|
306
|
+
*/
|
|
307
|
+
static fixOrphanedMoveMarkers(
|
|
308
|
+
revisionManager: { removeById(id: number): boolean },
|
|
309
|
+
revisions: Revision[],
|
|
310
|
+
dryRun?: boolean
|
|
311
|
+
): FixAction[] {
|
|
312
|
+
const actions: FixAction[] = [];
|
|
313
|
+
|
|
314
|
+
const moveFromIds = new Map<string, Revision>();
|
|
315
|
+
const moveToIds = new Map<string, Revision>();
|
|
316
|
+
|
|
317
|
+
for (const rev of revisions) {
|
|
318
|
+
const moveId = rev.getMoveId();
|
|
319
|
+
if (!moveId) continue;
|
|
320
|
+
|
|
321
|
+
if (rev.getType() === 'moveFrom') {
|
|
322
|
+
moveFromIds.set(moveId, rev);
|
|
323
|
+
} else if (rev.getType() === 'moveTo') {
|
|
324
|
+
moveToIds.set(moveId, rev);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Remove orphaned moveFrom
|
|
329
|
+
for (const [moveId, rev] of moveFromIds) {
|
|
330
|
+
if (!moveToIds.has(moveId)) {
|
|
331
|
+
const issue: ValidationIssue = {
|
|
332
|
+
code: REVISION_RULES.ORPHANED_MOVE_FROM.code,
|
|
333
|
+
severity: 'error',
|
|
334
|
+
message: `Orphaned moveFrom with moveId="${moveId}"`,
|
|
335
|
+
location: { revisionId: rev.getId() },
|
|
336
|
+
autoFixable: true,
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
actions.push({
|
|
340
|
+
issue,
|
|
341
|
+
action: `Removed orphaned moveFrom (ID: ${rev.getId()}, moveId: ${moveId})`,
|
|
342
|
+
before: { type: 'moveFrom', moveId },
|
|
343
|
+
after: null,
|
|
344
|
+
success: true,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
if (!dryRun) {
|
|
348
|
+
revisionManager.removeById(rev.getId());
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Remove orphaned moveTo
|
|
354
|
+
for (const [moveId, rev] of moveToIds) {
|
|
355
|
+
if (!moveFromIds.has(moveId)) {
|
|
356
|
+
const issue: ValidationIssue = {
|
|
357
|
+
code: REVISION_RULES.ORPHANED_MOVE_TO.code,
|
|
358
|
+
severity: 'error',
|
|
359
|
+
message: `Orphaned moveTo with moveId="${moveId}"`,
|
|
360
|
+
location: { revisionId: rev.getId() },
|
|
361
|
+
autoFixable: true,
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
actions.push({
|
|
365
|
+
issue,
|
|
366
|
+
action: `Removed orphaned moveTo (ID: ${rev.getId()}, moveId: ${moveId})`,
|
|
367
|
+
before: { type: 'moveTo', moveId },
|
|
368
|
+
after: null,
|
|
369
|
+
success: true,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
if (!dryRun) {
|
|
373
|
+
revisionManager.removeById(rev.getId());
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return actions;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Fix empty revisions by removing them.
|
|
383
|
+
*
|
|
384
|
+
* @param revisionManager - RevisionManager instance
|
|
385
|
+
* @param revisions - Array of revisions
|
|
386
|
+
* @param dryRun - If true, only report changes without applying
|
|
387
|
+
* @returns Array of fix actions
|
|
388
|
+
*/
|
|
389
|
+
static fixEmptyRevisions(
|
|
390
|
+
revisionManager: any,
|
|
391
|
+
revisions: Revision[],
|
|
392
|
+
dryRun?: boolean
|
|
393
|
+
): FixAction[] {
|
|
394
|
+
const actions: FixAction[] = [];
|
|
395
|
+
|
|
396
|
+
const propertyChangeTypes = [
|
|
397
|
+
'runPropertiesChange',
|
|
398
|
+
'paragraphPropertiesChange',
|
|
399
|
+
'tablePropertiesChange',
|
|
400
|
+
'tableExceptionPropertiesChange',
|
|
401
|
+
'tableRowPropertiesChange',
|
|
402
|
+
'tableCellPropertiesChange',
|
|
403
|
+
'sectionPropertiesChange',
|
|
404
|
+
'numberingChange',
|
|
405
|
+
];
|
|
406
|
+
|
|
407
|
+
for (const rev of revisions) {
|
|
408
|
+
const type = rev.getType();
|
|
409
|
+
|
|
410
|
+
// Skip property changes
|
|
411
|
+
if (propertyChangeTypes.includes(type)) {
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const runs = rev.getRuns();
|
|
416
|
+
const hasContent = runs.length > 0 && runs.some((r) => r.getText().length > 0);
|
|
417
|
+
|
|
418
|
+
if (!hasContent) {
|
|
419
|
+
const issue: ValidationIssue = {
|
|
420
|
+
code: REVISION_RULES.EMPTY_REVISION.code,
|
|
421
|
+
severity: 'warning',
|
|
422
|
+
message: `Empty revision ${rev.getId()} (type: ${type})`,
|
|
423
|
+
location: { revisionId: rev.getId() },
|
|
424
|
+
autoFixable: true,
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
actions.push({
|
|
428
|
+
issue,
|
|
429
|
+
action: `Removed empty revision (ID: ${rev.getId()}, type: ${type})`,
|
|
430
|
+
before: { id: rev.getId(), type },
|
|
431
|
+
after: null,
|
|
432
|
+
success: true,
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
if (!dryRun) {
|
|
436
|
+
revisionManager.removeById(rev.getId());
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return actions;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Fix non-sequential IDs by reassigning.
|
|
446
|
+
*
|
|
447
|
+
* @param revisions - Array of revisions
|
|
448
|
+
* @param dryRun - If true, only report changes without applying
|
|
449
|
+
* @returns Array of fix actions
|
|
450
|
+
*/
|
|
451
|
+
static fixNonSequentialIds(revisions: Revision[], dryRun?: boolean): FixAction[] {
|
|
452
|
+
const actions: FixAction[] = [];
|
|
453
|
+
|
|
454
|
+
if (revisions.length === 0) return actions;
|
|
455
|
+
|
|
456
|
+
// Check if IDs are already sequential
|
|
457
|
+
const ids = revisions.map((r) => r.getId()).sort((a, b) => a - b);
|
|
458
|
+
let isSequential = true;
|
|
459
|
+
|
|
460
|
+
for (let i = 1; i < ids.length; i++) {
|
|
461
|
+
const currentId = ids[i]!;
|
|
462
|
+
const prevId = ids[i - 1]!;
|
|
463
|
+
if (currentId !== prevId + 1) {
|
|
464
|
+
isSequential = false;
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (!isSequential) {
|
|
470
|
+
const issue: ValidationIssue = {
|
|
471
|
+
code: REVISION_RULES.NON_SEQUENTIAL_IDS.code,
|
|
472
|
+
severity: 'warning',
|
|
473
|
+
message: 'Revision IDs are not sequential',
|
|
474
|
+
autoFixable: true,
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
const oldIds = revisions.map((r) => r.getId());
|
|
478
|
+
const newIds: number[] = [];
|
|
479
|
+
|
|
480
|
+
revisions.forEach((rev, index) => {
|
|
481
|
+
newIds.push(index);
|
|
482
|
+
if (!dryRun) {
|
|
483
|
+
rev.setId(index);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
actions.push({
|
|
488
|
+
issue,
|
|
489
|
+
action: `Reassigned ${revisions.length} revision IDs to be sequential (0 to ${revisions.length - 1})`,
|
|
490
|
+
before: oldIds,
|
|
491
|
+
after: newIds,
|
|
492
|
+
success: true,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return actions;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Preview fixes without applying them.
|
|
501
|
+
*
|
|
502
|
+
* Convenience method that calls fix() with dryRun: true.
|
|
503
|
+
*
|
|
504
|
+
* @param doc - Document to preview fixes for
|
|
505
|
+
* @param options - Fix options (dryRun is forced to true)
|
|
506
|
+
* @returns Result showing what would be fixed
|
|
507
|
+
*/
|
|
508
|
+
static preview(doc: Document, options?: Omit<AutoFixOptions, 'dryRun'>): AutoFixResult {
|
|
509
|
+
return this.fix(doc, { ...options, dryRun: true });
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Format fix result as a human-readable string.
|
|
514
|
+
*
|
|
515
|
+
* @param result - AutoFixResult to format
|
|
516
|
+
* @returns Formatted string
|
|
517
|
+
*/
|
|
518
|
+
static formatResult(result: AutoFixResult): string {
|
|
519
|
+
const lines: string[] = [];
|
|
520
|
+
|
|
521
|
+
lines.push(`Auto-Fix ${result.allFixed ? 'COMPLETE' : 'PARTIAL'}`);
|
|
522
|
+
lines.push(`Fixed: ${result.issuesFixed}, Remaining: ${result.issuesRemaining}`);
|
|
523
|
+
|
|
524
|
+
if (result.actions.length > 0) {
|
|
525
|
+
lines.push('\nActions taken:');
|
|
526
|
+
for (const action of result.actions) {
|
|
527
|
+
const status = action.success ? 'OK' : 'FAILED';
|
|
528
|
+
lines.push(` [${status}] ${action.action}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (result.errors.length > 0) {
|
|
533
|
+
lines.push('\nErrors:');
|
|
534
|
+
for (const error of result.errors) {
|
|
535
|
+
lines.push(` - ${error}`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return lines.join('\n');
|
|
540
|
+
}
|
|
541
|
+
}
|