@usejunior/docx-core 0.0.1 → 0.1.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/LICENSE +21 -0
- package/README.md +86 -28
- package/dist/.tsbuildinfo +1 -0
- package/dist/atomizer.d.ts +218 -0
- package/dist/atomizer.d.ts.map +1 -0
- package/dist/atomizer.js +856 -0
- package/dist/atomizer.js.map +1 -0
- package/dist/baselines/atomizer/atomLcs.d.ts +96 -0
- package/dist/baselines/atomizer/atomLcs.d.ts.map +1 -0
- package/dist/baselines/atomizer/atomLcs.js +347 -0
- package/dist/baselines/atomizer/atomLcs.js.map +1 -0
- package/dist/baselines/atomizer/debug.d.ts +41 -0
- package/dist/baselines/atomizer/debug.d.ts.map +1 -0
- package/dist/baselines/atomizer/debug.js +85 -0
- package/dist/baselines/atomizer/debug.js.map +1 -0
- package/dist/baselines/atomizer/documentReconstructor.d.ts +64 -0
- package/dist/baselines/atomizer/documentReconstructor.d.ts.map +1 -0
- package/dist/baselines/atomizer/documentReconstructor.js +939 -0
- package/dist/baselines/atomizer/documentReconstructor.js.map +1 -0
- package/dist/baselines/atomizer/hierarchicalLcs.d.ts +111 -0
- package/dist/baselines/atomizer/hierarchicalLcs.d.ts.map +1 -0
- package/dist/baselines/atomizer/hierarchicalLcs.js +469 -0
- package/dist/baselines/atomizer/hierarchicalLcs.js.map +1 -0
- package/dist/baselines/atomizer/inPlaceModifier.d.ts +183 -0
- package/dist/baselines/atomizer/inPlaceModifier.d.ts.map +1 -0
- package/dist/baselines/atomizer/inPlaceModifier.js +1600 -0
- package/dist/baselines/atomizer/inPlaceModifier.js.map +1 -0
- package/dist/baselines/atomizer/numberingIntegration.d.ts +59 -0
- package/dist/baselines/atomizer/numberingIntegration.d.ts.map +1 -0
- package/dist/baselines/atomizer/numberingIntegration.js +209 -0
- package/dist/baselines/atomizer/numberingIntegration.js.map +1 -0
- package/dist/baselines/atomizer/pipeline.d.ts +65 -0
- package/dist/baselines/atomizer/pipeline.d.ts.map +1 -0
- package/dist/baselines/atomizer/pipeline.js +510 -0
- package/dist/baselines/atomizer/pipeline.js.map +1 -0
- package/dist/baselines/atomizer/premergeRuns.d.ts +26 -0
- package/dist/baselines/atomizer/premergeRuns.d.ts.map +1 -0
- package/dist/baselines/atomizer/premergeRuns.js +150 -0
- package/dist/baselines/atomizer/premergeRuns.js.map +1 -0
- package/dist/baselines/atomizer/trackChangesAcceptor.d.ts +63 -0
- package/dist/baselines/atomizer/trackChangesAcceptor.d.ts.map +1 -0
- package/dist/baselines/atomizer/trackChangesAcceptor.js +254 -0
- package/dist/baselines/atomizer/trackChangesAcceptor.js.map +1 -0
- package/dist/baselines/atomizer/trackChangesAcceptorAst.d.ts +64 -0
- package/dist/baselines/atomizer/trackChangesAcceptorAst.d.ts.map +1 -0
- package/dist/baselines/atomizer/trackChangesAcceptorAst.js +586 -0
- package/dist/baselines/atomizer/trackChangesAcceptorAst.js.map +1 -0
- package/dist/baselines/atomizer/xmlToWmlElement.d.ts +65 -0
- package/dist/baselines/atomizer/xmlToWmlElement.d.ts.map +1 -0
- package/dist/baselines/atomizer/xmlToWmlElement.js +95 -0
- package/dist/baselines/atomizer/xmlToWmlElement.js.map +1 -0
- package/dist/baselines/diffmatch/documentBuilder.d.ts +44 -0
- package/dist/baselines/diffmatch/documentBuilder.d.ts.map +1 -0
- package/dist/baselines/diffmatch/documentBuilder.js +227 -0
- package/dist/baselines/diffmatch/documentBuilder.js.map +1 -0
- package/dist/baselines/diffmatch/paragraphAlignment.d.ts +75 -0
- package/dist/baselines/diffmatch/paragraphAlignment.d.ts.map +1 -0
- package/dist/baselines/diffmatch/paragraphAlignment.js +206 -0
- package/dist/baselines/diffmatch/paragraphAlignment.js.map +1 -0
- package/dist/baselines/diffmatch/pipeline.d.ts +33 -0
- package/dist/baselines/diffmatch/pipeline.d.ts.map +1 -0
- package/dist/baselines/diffmatch/pipeline.js +84 -0
- package/dist/baselines/diffmatch/pipeline.js.map +1 -0
- package/dist/baselines/diffmatch/runDiff.d.ts +53 -0
- package/dist/baselines/diffmatch/runDiff.d.ts.map +1 -0
- package/dist/baselines/diffmatch/runDiff.js +253 -0
- package/dist/baselines/diffmatch/runDiff.js.map +1 -0
- package/dist/baselines/diffmatch/trackChangesRenderer.d.ts +64 -0
- package/dist/baselines/diffmatch/trackChangesRenderer.d.ts.map +1 -0
- package/dist/baselines/diffmatch/trackChangesRenderer.js +178 -0
- package/dist/baselines/diffmatch/trackChangesRenderer.js.map +1 -0
- package/dist/baselines/diffmatch/xmlParser.d.ts +45 -0
- package/dist/baselines/diffmatch/xmlParser.d.ts.map +1 -0
- package/dist/baselines/diffmatch/xmlParser.js +344 -0
- package/dist/baselines/diffmatch/xmlParser.js.map +1 -0
- package/dist/baselines/wmlcomparer/DocxodusWasm.d.ts +51 -0
- package/dist/baselines/wmlcomparer/DocxodusWasm.d.ts.map +1 -0
- package/dist/baselines/wmlcomparer/DocxodusWasm.js +83 -0
- package/dist/baselines/wmlcomparer/DocxodusWasm.js.map +1 -0
- package/dist/baselines/wmlcomparer/DotnetCli.d.ts +40 -0
- package/dist/baselines/wmlcomparer/DotnetCli.d.ts.map +1 -0
- package/dist/baselines/wmlcomparer/DotnetCli.js +135 -0
- package/dist/baselines/wmlcomparer/DotnetCli.js.map +1 -0
- package/dist/benchmark/metrics.d.ts +72 -0
- package/dist/benchmark/metrics.d.ts.map +1 -0
- package/dist/benchmark/metrics.js +45 -0
- package/dist/benchmark/metrics.js.map +1 -0
- package/dist/benchmark/reporter.d.ts +23 -0
- package/dist/benchmark/reporter.d.ts.map +1 -0
- package/dist/benchmark/reporter.js +147 -0
- package/dist/benchmark/reporter.js.map +1 -0
- package/dist/benchmark/runner.d.ts +30 -0
- package/dist/benchmark/runner.d.ts.map +1 -0
- package/dist/benchmark/runner.js +233 -0
- package/dist/benchmark/runner.js.map +1 -0
- package/dist/cli/compare-two.d.ts +28 -0
- package/dist/cli/compare-two.d.ts.map +1 -0
- package/dist/cli/compare-two.js +110 -0
- package/dist/cli/compare-two.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +21 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core-types.d.ts +296 -0
- package/dist/core-types.d.ts.map +1 -0
- package/dist/core-types.js +122 -0
- package/dist/core-types.js.map +1 -0
- package/dist/footnotes.d.ts +144 -0
- package/dist/footnotes.d.ts.map +1 -0
- package/dist/footnotes.js +291 -0
- package/dist/footnotes.js.map +1 -0
- package/dist/format-detection.d.ts +120 -0
- package/dist/format-detection.d.ts.map +1 -0
- package/dist/format-detection.js +338 -0
- package/dist/format-detection.js.map +1 -0
- package/dist/index.d.ts +177 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/output-artifacts.d.ts +6 -0
- package/dist/integration/output-artifacts.d.ts.map +1 -0
- package/dist/integration/output-artifacts.js +30 -0
- package/dist/integration/output-artifacts.js.map +1 -0
- package/dist/move-detection.d.ts +211 -0
- package/dist/move-detection.d.ts.map +1 -0
- package/dist/move-detection.js +391 -0
- package/dist/move-detection.js.map +1 -0
- package/dist/numbering.d.ts +136 -0
- package/dist/numbering.d.ts.map +1 -0
- package/dist/numbering.js +446 -0
- package/dist/numbering.js.map +1 -0
- package/dist/primitives/accept_changes.d.ts +30 -0
- package/dist/primitives/accept_changes.d.ts.map +1 -0
- package/dist/primitives/accept_changes.js +241 -0
- package/dist/primitives/accept_changes.js.map +1 -0
- package/dist/primitives/bookmarks.d.ts +12 -0
- package/dist/primitives/bookmarks.d.ts.map +1 -0
- package/dist/primitives/bookmarks.js +248 -0
- package/dist/primitives/bookmarks.js.map +1 -0
- package/dist/primitives/comments.d.ts +88 -0
- package/dist/primitives/comments.d.ts.map +1 -0
- package/dist/primitives/comments.js +703 -0
- package/dist/primitives/comments.js.map +1 -0
- package/dist/primitives/document.d.ts +168 -0
- package/dist/primitives/document.d.ts.map +1 -0
- package/dist/primitives/document.js +532 -0
- package/dist/primitives/document.js.map +1 -0
- package/dist/primitives/document_view.d.ts +93 -0
- package/dist/primitives/document_view.d.ts.map +1 -0
- package/dist/primitives/document_view.js +722 -0
- package/dist/primitives/document_view.js.map +1 -0
- package/dist/primitives/dom-helpers.d.ts +94 -0
- package/dist/primitives/dom-helpers.d.ts.map +1 -0
- package/dist/primitives/dom-helpers.js +219 -0
- package/dist/primitives/dom-helpers.js.map +1 -0
- package/dist/primitives/errors.d.ts +7 -0
- package/dist/primitives/errors.d.ts.map +1 -0
- package/dist/primitives/errors.js +10 -0
- package/dist/primitives/errors.js.map +1 -0
- package/dist/primitives/extract_revisions.d.ts +50 -0
- package/dist/primitives/extract_revisions.d.ts.map +1 -0
- package/dist/primitives/extract_revisions.js +340 -0
- package/dist/primitives/extract_revisions.js.map +1 -0
- package/dist/primitives/footnotes.d.ts +37 -0
- package/dist/primitives/footnotes.d.ts.map +1 -0
- package/dist/primitives/footnotes.js +552 -0
- package/dist/primitives/footnotes.js.map +1 -0
- package/dist/primitives/formatting_tags.d.ts +30 -0
- package/dist/primitives/formatting_tags.d.ts.map +1 -0
- package/dist/primitives/formatting_tags.js +217 -0
- package/dist/primitives/formatting_tags.js.map +1 -0
- package/dist/primitives/index.d.ts +26 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +26 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/layout.d.ts +53 -0
- package/dist/primitives/layout.d.ts.map +1 -0
- package/dist/primitives/layout.js +178 -0
- package/dist/primitives/layout.js.map +1 -0
- package/dist/primitives/list_labels.d.ts +19 -0
- package/dist/primitives/list_labels.d.ts.map +1 -0
- package/dist/primitives/list_labels.js +57 -0
- package/dist/primitives/list_labels.js.map +1 -0
- package/dist/primitives/matching.d.ts +17 -0
- package/dist/primitives/matching.d.ts.map +1 -0
- package/dist/primitives/matching.js +144 -0
- package/dist/primitives/matching.js.map +1 -0
- package/dist/primitives/merge_runs.d.ts +23 -0
- package/dist/primitives/merge_runs.d.ts.map +1 -0
- package/dist/primitives/merge_runs.js +195 -0
- package/dist/primitives/merge_runs.js.map +1 -0
- package/dist/primitives/namespaces.d.ts +90 -0
- package/dist/primitives/namespaces.d.ts.map +1 -0
- package/dist/primitives/namespaces.js +107 -0
- package/dist/primitives/namespaces.js.map +1 -0
- package/dist/primitives/numbering.d.ts +27 -0
- package/dist/primitives/numbering.d.ts.map +1 -0
- package/dist/primitives/numbering.js +182 -0
- package/dist/primitives/numbering.js.map +1 -0
- package/dist/primitives/prevent_double_elevation.d.ts +18 -0
- package/dist/primitives/prevent_double_elevation.d.ts.map +1 -0
- package/dist/primitives/prevent_double_elevation.js +190 -0
- package/dist/primitives/prevent_double_elevation.js.map +1 -0
- package/dist/primitives/reject_changes.d.ts +27 -0
- package/dist/primitives/reject_changes.d.ts.map +1 -0
- package/dist/primitives/reject_changes.js +371 -0
- package/dist/primitives/reject_changes.js.map +1 -0
- package/dist/primitives/relationships.d.ts +7 -0
- package/dist/primitives/relationships.d.ts.map +1 -0
- package/dist/primitives/relationships.js +24 -0
- package/dist/primitives/relationships.js.map +1 -0
- package/dist/primitives/semantic_tags.d.ts +32 -0
- package/dist/primitives/semantic_tags.d.ts.map +1 -0
- package/dist/primitives/semantic_tags.js +139 -0
- package/dist/primitives/semantic_tags.js.map +1 -0
- package/dist/primitives/simplify_redlines.d.ts +19 -0
- package/dist/primitives/simplify_redlines.d.ts.map +1 -0
- package/dist/primitives/simplify_redlines.js +94 -0
- package/dist/primitives/simplify_redlines.js.map +1 -0
- package/dist/primitives/styles.d.ts +36 -0
- package/dist/primitives/styles.d.ts.map +1 -0
- package/dist/primitives/styles.js +190 -0
- package/dist/primitives/styles.js.map +1 -0
- package/dist/primitives/text.d.ts +27 -0
- package/dist/primitives/text.d.ts.map +1 -0
- package/dist/primitives/text.js +416 -0
- package/dist/primitives/text.js.map +1 -0
- package/dist/primitives/validate_document.d.ts +24 -0
- package/dist/primitives/validate_document.d.ts.map +1 -0
- package/dist/primitives/validate_document.js +147 -0
- package/dist/primitives/validate_document.js.map +1 -0
- package/dist/primitives/xml.d.ts +5 -0
- package/dist/primitives/xml.d.ts.map +1 -0
- package/dist/primitives/xml.js +19 -0
- package/dist/primitives/xml.js.map +1 -0
- package/dist/primitives/zip.d.ts +25 -0
- package/dist/primitives/zip.d.ts.map +1 -0
- package/dist/primitives/zip.js +78 -0
- package/dist/primitives/zip.js.map +1 -0
- package/dist/shared/docx/DocxArchive.d.ts +94 -0
- package/dist/shared/docx/DocxArchive.d.ts.map +1 -0
- package/dist/shared/docx/DocxArchive.js +169 -0
- package/dist/shared/docx/DocxArchive.js.map +1 -0
- package/dist/shared/ooxml/namespaces.d.ts +149 -0
- package/dist/shared/ooxml/namespaces.d.ts.map +1 -0
- package/dist/shared/ooxml/namespaces.js +224 -0
- package/dist/shared/ooxml/namespaces.js.map +1 -0
- package/dist/shared/ooxml/types.d.ts +136 -0
- package/dist/shared/ooxml/types.d.ts.map +1 -0
- package/dist/shared/ooxml/types.js +7 -0
- package/dist/shared/ooxml/types.js.map +1 -0
- package/package.json +63 -6
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move Detection Module
|
|
3
|
+
*
|
|
4
|
+
* Detects relocated content after LCS comparison by matching deleted blocks
|
|
5
|
+
* with inserted blocks using Jaccard word similarity.
|
|
6
|
+
*
|
|
7
|
+
* Pipeline position:
|
|
8
|
+
* LCS() → MarkRowsAsDeletedOrInserted() → FlattenToAtomList() → detectMovesInAtomList() → CoalesceRecurse()
|
|
9
|
+
*
|
|
10
|
+
* @see WmlComparer.cs DetectMovesInAtomList() line 3811
|
|
11
|
+
*/
|
|
12
|
+
import { AtomBlock, ComparisonUnitAtom, CorrelationStatus, MoveDetectionSettings } from './core-types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Extract text content from an atom.
|
|
15
|
+
*
|
|
16
|
+
* @param atom - The atom to extract text from
|
|
17
|
+
* @returns The text content, or empty string for non-text atoms
|
|
18
|
+
*/
|
|
19
|
+
export declare function getAtomText(atom: ComparisonUnitAtom): string;
|
|
20
|
+
/**
|
|
21
|
+
* Extract text from a sequence of atoms.
|
|
22
|
+
*
|
|
23
|
+
* @param atoms - The atoms to extract text from
|
|
24
|
+
* @returns Combined text content
|
|
25
|
+
*/
|
|
26
|
+
export declare function getAtomsText(atoms: ComparisonUnitAtom[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* Count words in text.
|
|
29
|
+
*
|
|
30
|
+
* @param text - The text to count words in
|
|
31
|
+
* @returns Number of words
|
|
32
|
+
*/
|
|
33
|
+
export declare function countWords(text: string): number;
|
|
34
|
+
/**
|
|
35
|
+
* Calculate Jaccard similarity between two texts based on word sets.
|
|
36
|
+
*
|
|
37
|
+
* Jaccard index = |intersection| / |union|
|
|
38
|
+
*
|
|
39
|
+
* Benefits:
|
|
40
|
+
* - Order-independent: "fox quick brown" matches "brown quick fox"
|
|
41
|
+
* - Handles insertions/deletions well: adding one word to a 10-word block only slightly reduces similarity
|
|
42
|
+
* - O(n) complexity where n = total words
|
|
43
|
+
*
|
|
44
|
+
* @param text1 - First text
|
|
45
|
+
* @param text2 - Second text
|
|
46
|
+
* @param caseInsensitive - Whether to ignore case (default: true)
|
|
47
|
+
* @returns Similarity score between 0 and 1
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* jaccardWordSimilarity("The quick brown fox", "The quick brown dog")
|
|
51
|
+
* // Returns 0.6 (3 common words / 5 total unique words)
|
|
52
|
+
*/
|
|
53
|
+
export declare function jaccardWordSimilarity(text1: string, text2: string, caseInsensitive?: boolean): number;
|
|
54
|
+
/**
|
|
55
|
+
* Group consecutive atoms by correlation status.
|
|
56
|
+
*
|
|
57
|
+
* Creates blocks of atoms with the same status (Deleted or Inserted).
|
|
58
|
+
*
|
|
59
|
+
* @param atoms - The atoms to group
|
|
60
|
+
* @returns Array of atom blocks
|
|
61
|
+
*/
|
|
62
|
+
export declare function groupIntoBlocks(atoms: ComparisonUnitAtom[]): AtomBlock[];
|
|
63
|
+
/**
|
|
64
|
+
* Result of finding the best match for a deleted block.
|
|
65
|
+
*/
|
|
66
|
+
interface MatchResult {
|
|
67
|
+
/** The matching inserted block */
|
|
68
|
+
block: AtomBlock;
|
|
69
|
+
/** Similarity score between 0 and 1 */
|
|
70
|
+
similarity: number;
|
|
71
|
+
/** Index in the insertedBlocks array */
|
|
72
|
+
index: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Find the best matching inserted block for a deleted block.
|
|
76
|
+
*
|
|
77
|
+
* @param deleted - The deleted block to match
|
|
78
|
+
* @param insertedBlocks - Available inserted blocks
|
|
79
|
+
* @param settings - Move detection settings
|
|
80
|
+
* @returns The best match, or undefined if no match meets threshold
|
|
81
|
+
*/
|
|
82
|
+
export declare function findBestMatch(deleted: AtomBlock, insertedBlocks: AtomBlock[], settings: MoveDetectionSettings): MatchResult | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Mark atoms as part of a move operation.
|
|
85
|
+
*
|
|
86
|
+
* @param atoms - Atoms to mark
|
|
87
|
+
* @param status - New correlation status (MovedSource or MovedDestination)
|
|
88
|
+
* @param moveGroupId - ID linking source and destination
|
|
89
|
+
* @param moveName - Name for move tracking (e.g., "move1")
|
|
90
|
+
*/
|
|
91
|
+
export declare function markAsMove(atoms: ComparisonUnitAtom[], status: CorrelationStatus.MovedSource | CorrelationStatus.MovedDestination, moveGroupId: number, moveName: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* Detect moves in a flat list of atoms.
|
|
94
|
+
*
|
|
95
|
+
* Runs after LCS comparison to identify deleted blocks that were actually
|
|
96
|
+
* moved to a new location. Updates atoms in place with move status.
|
|
97
|
+
*
|
|
98
|
+
* @param atoms - The atom list to process (modified in place)
|
|
99
|
+
* @param settings - Move detection settings (optional, uses defaults)
|
|
100
|
+
*
|
|
101
|
+
* @see WmlComparer.cs DetectMovesInAtomList() line 3811
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* const atoms = atomizeTree(document, [], part);
|
|
105
|
+
* runLCSComparison(atoms);
|
|
106
|
+
* detectMovesInAtomList(atoms); // Updates atoms in place
|
|
107
|
+
*/
|
|
108
|
+
export declare function detectMovesInAtomList(atoms: ComparisonUnitAtom[], settings?: MoveDetectionSettings): void;
|
|
109
|
+
/**
|
|
110
|
+
* Options for generating move markup.
|
|
111
|
+
*/
|
|
112
|
+
export interface MoveMarkupOptions {
|
|
113
|
+
/** Author name for revision tracking */
|
|
114
|
+
author: string;
|
|
115
|
+
/** Timestamp for revisions */
|
|
116
|
+
dateTime: Date;
|
|
117
|
+
/** Starting ID for range markers */
|
|
118
|
+
startId: number;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Generated move markup for a block.
|
|
122
|
+
*/
|
|
123
|
+
export interface MoveMarkup {
|
|
124
|
+
/** Range start element */
|
|
125
|
+
rangeStart: Element;
|
|
126
|
+
/** Move content wrapper element */
|
|
127
|
+
moveWrapper: Element;
|
|
128
|
+
/** Range end element */
|
|
129
|
+
rangeEnd: Element;
|
|
130
|
+
/** Next available ID after these elements */
|
|
131
|
+
nextId: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Generate move source markup (w:moveFrom with range markers).
|
|
135
|
+
*
|
|
136
|
+
* @param moveName - Name linking source and destination (e.g., "move1")
|
|
137
|
+
* @param content - Child elements to wrap
|
|
138
|
+
* @param options - Markup generation options
|
|
139
|
+
* @returns Move markup elements
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* Output structure:
|
|
143
|
+
* <w:moveFromRangeStart w:id="1" w:name="move1" w:author="..." w:date="..."/>
|
|
144
|
+
* <w:moveFrom w:id="2" w:author="..." w:date="...">
|
|
145
|
+
* <!-- content -->
|
|
146
|
+
* </w:moveFrom>
|
|
147
|
+
* <w:moveFromRangeEnd w:id="1"/>
|
|
148
|
+
*/
|
|
149
|
+
export declare function generateMoveSourceMarkup(moveName: string, content: Element[], options: MoveMarkupOptions): MoveMarkup;
|
|
150
|
+
/**
|
|
151
|
+
* Generate move destination markup (w:moveTo with range markers).
|
|
152
|
+
*
|
|
153
|
+
* @param moveName - Name linking source and destination (e.g., "move1")
|
|
154
|
+
* @param content - Child elements to wrap
|
|
155
|
+
* @param options - Markup generation options
|
|
156
|
+
* @returns Move markup elements
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* Output structure:
|
|
160
|
+
* <w:moveToRangeStart w:id="3" w:name="move1" w:author="..." w:date="..."/>
|
|
161
|
+
* <w:moveTo w:id="4" w:author="..." w:date="...">
|
|
162
|
+
* <!-- content -->
|
|
163
|
+
* </w:moveTo>
|
|
164
|
+
* <w:moveToRangeEnd w:id="3"/>
|
|
165
|
+
*/
|
|
166
|
+
export declare function generateMoveDestinationMarkup(moveName: string, content: Element[], options: MoveMarkupOptions): MoveMarkup;
|
|
167
|
+
/**
|
|
168
|
+
* State for tracking revision IDs during markup generation.
|
|
169
|
+
*/
|
|
170
|
+
export interface RevisionIdState {
|
|
171
|
+
/** Next available ID */
|
|
172
|
+
nextId: number;
|
|
173
|
+
/** Move name to range start ID mapping */
|
|
174
|
+
moveRangeIds: Map<string, {
|
|
175
|
+
sourceRangeId: number;
|
|
176
|
+
destRangeId: number;
|
|
177
|
+
}>;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Create initial revision ID state.
|
|
181
|
+
*
|
|
182
|
+
* @param startId - Starting ID (default: 1)
|
|
183
|
+
* @returns Initial state
|
|
184
|
+
*/
|
|
185
|
+
export declare function createRevisionIdState(startId?: number): RevisionIdState;
|
|
186
|
+
/**
|
|
187
|
+
* Allocate IDs for a move operation.
|
|
188
|
+
*
|
|
189
|
+
* Ensures source and destination use consistent IDs for proper linking.
|
|
190
|
+
*
|
|
191
|
+
* @param state - Revision ID state (modified in place)
|
|
192
|
+
* @param moveName - Move name (e.g., "move1")
|
|
193
|
+
* @returns IDs for source and destination markup
|
|
194
|
+
*/
|
|
195
|
+
export declare function allocateMoveIds(state: RevisionIdState, moveName: string): {
|
|
196
|
+
sourceRangeId: number;
|
|
197
|
+
sourceMoveId: number;
|
|
198
|
+
destRangeId: number;
|
|
199
|
+
destMoveId: number;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Fix up revision IDs after all moves have been processed.
|
|
203
|
+
*
|
|
204
|
+
* Ensures proper ID pairing between source and destination elements.
|
|
205
|
+
* This is a post-processing step after markup generation.
|
|
206
|
+
*
|
|
207
|
+
* @param state - The revision ID state
|
|
208
|
+
*/
|
|
209
|
+
export declare function fixUpRevisionIds(_state: RevisionIdState): void;
|
|
210
|
+
export {};
|
|
211
|
+
//# sourceMappingURL=move-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"move-detection.d.ts","sourceRoot":"","sources":["../src/move-detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move Detection Module
|
|
3
|
+
*
|
|
4
|
+
* Detects relocated content after LCS comparison by matching deleted blocks
|
|
5
|
+
* with inserted blocks using Jaccard word similarity.
|
|
6
|
+
*
|
|
7
|
+
* Pipeline position:
|
|
8
|
+
* LCS() → MarkRowsAsDeletedOrInserted() → FlattenToAtomList() → detectMovesInAtomList() → CoalesceRecurse()
|
|
9
|
+
*
|
|
10
|
+
* @see WmlComparer.cs DetectMovesInAtomList() line 3811
|
|
11
|
+
*/
|
|
12
|
+
import { CorrelationStatus, DEFAULT_MOVE_DETECTION_SETTINGS, } from './core-types.js';
|
|
13
|
+
import { getLeafText } from './primitives/index.js';
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Text Extraction
|
|
16
|
+
// =============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Extract text content from an atom.
|
|
19
|
+
*
|
|
20
|
+
* @param atom - The atom to extract text from
|
|
21
|
+
* @returns The text content, or empty string for non-text atoms
|
|
22
|
+
*/
|
|
23
|
+
export function getAtomText(atom) {
|
|
24
|
+
const element = atom.contentElement;
|
|
25
|
+
// Handle text elements
|
|
26
|
+
if (element.tagName === 'w:t' || element.tagName === 'w:delText') {
|
|
27
|
+
return getLeafText(element) ?? '';
|
|
28
|
+
}
|
|
29
|
+
// Handle break elements
|
|
30
|
+
if (element.tagName === 'w:br' || element.tagName === 'w:cr') {
|
|
31
|
+
return '\n';
|
|
32
|
+
}
|
|
33
|
+
// Handle tab
|
|
34
|
+
if (element.tagName === 'w:tab') {
|
|
35
|
+
return '\t';
|
|
36
|
+
}
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extract text from a sequence of atoms.
|
|
41
|
+
*
|
|
42
|
+
* @param atoms - The atoms to extract text from
|
|
43
|
+
* @returns Combined text content
|
|
44
|
+
*/
|
|
45
|
+
export function getAtomsText(atoms) {
|
|
46
|
+
return atoms.map(getAtomText).join('');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Count words in text.
|
|
50
|
+
*
|
|
51
|
+
* @param text - The text to count words in
|
|
52
|
+
* @returns Number of words
|
|
53
|
+
*/
|
|
54
|
+
export function countWords(text) {
|
|
55
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
56
|
+
return words.length;
|
|
57
|
+
}
|
|
58
|
+
// =============================================================================
|
|
59
|
+
// Jaccard Similarity
|
|
60
|
+
// =============================================================================
|
|
61
|
+
/**
|
|
62
|
+
* Calculate Jaccard similarity between two texts based on word sets.
|
|
63
|
+
*
|
|
64
|
+
* Jaccard index = |intersection| / |union|
|
|
65
|
+
*
|
|
66
|
+
* Benefits:
|
|
67
|
+
* - Order-independent: "fox quick brown" matches "brown quick fox"
|
|
68
|
+
* - Handles insertions/deletions well: adding one word to a 10-word block only slightly reduces similarity
|
|
69
|
+
* - O(n) complexity where n = total words
|
|
70
|
+
*
|
|
71
|
+
* @param text1 - First text
|
|
72
|
+
* @param text2 - Second text
|
|
73
|
+
* @param caseInsensitive - Whether to ignore case (default: true)
|
|
74
|
+
* @returns Similarity score between 0 and 1
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* jaccardWordSimilarity("The quick brown fox", "The quick brown dog")
|
|
78
|
+
* // Returns 0.6 (3 common words / 5 total unique words)
|
|
79
|
+
*/
|
|
80
|
+
export function jaccardWordSimilarity(text1, text2, caseInsensitive = true) {
|
|
81
|
+
const normalize = caseInsensitive
|
|
82
|
+
? (s) => s.toLowerCase()
|
|
83
|
+
: (s) => s;
|
|
84
|
+
const words1 = new Set(normalize(text1)
|
|
85
|
+
.split(/\s+/)
|
|
86
|
+
.filter(Boolean));
|
|
87
|
+
const words2 = new Set(normalize(text2)
|
|
88
|
+
.split(/\s+/)
|
|
89
|
+
.filter(Boolean));
|
|
90
|
+
if (words1.size === 0 && words2.size === 0) {
|
|
91
|
+
return 1; // Both empty = identical
|
|
92
|
+
}
|
|
93
|
+
if (words1.size === 0 || words2.size === 0) {
|
|
94
|
+
return 0; // One empty = completely different
|
|
95
|
+
}
|
|
96
|
+
// Calculate intersection
|
|
97
|
+
let intersectionSize = 0;
|
|
98
|
+
for (const word of words1) {
|
|
99
|
+
if (words2.has(word)) {
|
|
100
|
+
intersectionSize++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Calculate union (|A| + |B| - |A ∩ B|)
|
|
104
|
+
const unionSize = words1.size + words2.size - intersectionSize;
|
|
105
|
+
return intersectionSize / unionSize;
|
|
106
|
+
}
|
|
107
|
+
// =============================================================================
|
|
108
|
+
// Block Grouping
|
|
109
|
+
// =============================================================================
|
|
110
|
+
/**
|
|
111
|
+
* Group consecutive atoms by correlation status.
|
|
112
|
+
*
|
|
113
|
+
* Creates blocks of atoms with the same status (Deleted or Inserted).
|
|
114
|
+
*
|
|
115
|
+
* @param atoms - The atoms to group
|
|
116
|
+
* @returns Array of atom blocks
|
|
117
|
+
*/
|
|
118
|
+
export function groupIntoBlocks(atoms) {
|
|
119
|
+
const blocks = [];
|
|
120
|
+
let currentBlock = null;
|
|
121
|
+
for (const atom of atoms) {
|
|
122
|
+
const status = atom.correlationStatus;
|
|
123
|
+
// Only group Deleted and Inserted atoms for move detection
|
|
124
|
+
if (status !== CorrelationStatus.Deleted && status !== CorrelationStatus.Inserted) {
|
|
125
|
+
// End current block
|
|
126
|
+
if (currentBlock) {
|
|
127
|
+
blocks.push(currentBlock);
|
|
128
|
+
currentBlock = null;
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// Start new block or continue existing
|
|
133
|
+
if (!currentBlock || currentBlock.status !== status) {
|
|
134
|
+
if (currentBlock) {
|
|
135
|
+
blocks.push(currentBlock);
|
|
136
|
+
}
|
|
137
|
+
currentBlock = {
|
|
138
|
+
status,
|
|
139
|
+
atoms: [atom],
|
|
140
|
+
text: getAtomText(atom),
|
|
141
|
+
wordCount: 0, // Calculated at end
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
currentBlock.atoms.push(atom);
|
|
146
|
+
currentBlock.text += getAtomText(atom);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Don't forget the last block
|
|
150
|
+
if (currentBlock) {
|
|
151
|
+
blocks.push(currentBlock);
|
|
152
|
+
}
|
|
153
|
+
// Calculate word counts
|
|
154
|
+
for (const block of blocks) {
|
|
155
|
+
block.wordCount = countWords(block.text);
|
|
156
|
+
}
|
|
157
|
+
return blocks;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Find the best matching inserted block for a deleted block.
|
|
161
|
+
*
|
|
162
|
+
* @param deleted - The deleted block to match
|
|
163
|
+
* @param insertedBlocks - Available inserted blocks
|
|
164
|
+
* @param settings - Move detection settings
|
|
165
|
+
* @returns The best match, or undefined if no match meets threshold
|
|
166
|
+
*/
|
|
167
|
+
export function findBestMatch(deleted, insertedBlocks, settings) {
|
|
168
|
+
let bestMatch;
|
|
169
|
+
for (let i = 0; i < insertedBlocks.length; i++) {
|
|
170
|
+
const inserted = insertedBlocks[i];
|
|
171
|
+
if (!inserted)
|
|
172
|
+
continue;
|
|
173
|
+
// Skip already matched blocks (marked as MovedDestination)
|
|
174
|
+
if (inserted.atoms.length > 0 &&
|
|
175
|
+
inserted.atoms[0]?.correlationStatus === CorrelationStatus.MovedDestination) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const similarity = jaccardWordSimilarity(deleted.text, inserted.text, settings.caseInsensitiveMove);
|
|
179
|
+
if (similarity >= settings.moveSimilarityThreshold) {
|
|
180
|
+
if (!bestMatch || similarity > bestMatch.similarity) {
|
|
181
|
+
bestMatch = { block: inserted, similarity, index: i };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return bestMatch;
|
|
186
|
+
}
|
|
187
|
+
// =============================================================================
|
|
188
|
+
// Move Marking
|
|
189
|
+
// =============================================================================
|
|
190
|
+
/**
|
|
191
|
+
* Mark atoms as part of a move operation.
|
|
192
|
+
*
|
|
193
|
+
* @param atoms - Atoms to mark
|
|
194
|
+
* @param status - New correlation status (MovedSource or MovedDestination)
|
|
195
|
+
* @param moveGroupId - ID linking source and destination
|
|
196
|
+
* @param moveName - Name for move tracking (e.g., "move1")
|
|
197
|
+
*/
|
|
198
|
+
export function markAsMove(atoms, status, moveGroupId, moveName) {
|
|
199
|
+
for (const atom of atoms) {
|
|
200
|
+
atom.correlationStatus = status;
|
|
201
|
+
atom.moveGroupId = moveGroupId;
|
|
202
|
+
atom.moveName = moveName;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// =============================================================================
|
|
206
|
+
// Main Algorithm
|
|
207
|
+
// =============================================================================
|
|
208
|
+
/**
|
|
209
|
+
* Detect moves in a flat list of atoms.
|
|
210
|
+
*
|
|
211
|
+
* Runs after LCS comparison to identify deleted blocks that were actually
|
|
212
|
+
* moved to a new location. Updates atoms in place with move status.
|
|
213
|
+
*
|
|
214
|
+
* @param atoms - The atom list to process (modified in place)
|
|
215
|
+
* @param settings - Move detection settings (optional, uses defaults)
|
|
216
|
+
*
|
|
217
|
+
* @see WmlComparer.cs DetectMovesInAtomList() line 3811
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* const atoms = atomizeTree(document, [], part);
|
|
221
|
+
* runLCSComparison(atoms);
|
|
222
|
+
* detectMovesInAtomList(atoms); // Updates atoms in place
|
|
223
|
+
*/
|
|
224
|
+
export function detectMovesInAtomList(atoms, settings = DEFAULT_MOVE_DETECTION_SETTINGS) {
|
|
225
|
+
if (!settings.detectMoves) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// 1. Group consecutive atoms by status
|
|
229
|
+
const blocks = groupIntoBlocks(atoms);
|
|
230
|
+
// 2. Filter by minimum word count
|
|
231
|
+
const deletedBlocks = blocks.filter((b) => b.status === CorrelationStatus.Deleted &&
|
|
232
|
+
b.wordCount >= settings.moveMinimumWordCount);
|
|
233
|
+
const insertedBlocks = blocks.filter((b) => b.status === CorrelationStatus.Inserted &&
|
|
234
|
+
b.wordCount >= settings.moveMinimumWordCount);
|
|
235
|
+
// 3. Find best matches using Jaccard similarity
|
|
236
|
+
let moveGroupId = 1;
|
|
237
|
+
for (const deleted of deletedBlocks) {
|
|
238
|
+
const bestMatch = findBestMatch(deleted, insertedBlocks, settings);
|
|
239
|
+
if (bestMatch) {
|
|
240
|
+
// 4. Convert to moves
|
|
241
|
+
const moveName = `move${moveGroupId}`;
|
|
242
|
+
markAsMove(deleted.atoms, CorrelationStatus.MovedSource, moveGroupId, moveName);
|
|
243
|
+
markAsMove(bestMatch.block.atoms, CorrelationStatus.MovedDestination, moveGroupId, moveName);
|
|
244
|
+
moveGroupId++;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Format a date as ISO string for w:date attribute.
|
|
250
|
+
*/
|
|
251
|
+
function formatDateTime(date) {
|
|
252
|
+
return date.toISOString();
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Generate move source markup (w:moveFrom with range markers).
|
|
256
|
+
*
|
|
257
|
+
* @param moveName - Name linking source and destination (e.g., "move1")
|
|
258
|
+
* @param content - Child elements to wrap
|
|
259
|
+
* @param options - Markup generation options
|
|
260
|
+
* @returns Move markup elements
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* Output structure:
|
|
264
|
+
* <w:moveFromRangeStart w:id="1" w:name="move1" w:author="..." w:date="..."/>
|
|
265
|
+
* <w:moveFrom w:id="2" w:author="..." w:date="...">
|
|
266
|
+
* <!-- content -->
|
|
267
|
+
* </w:moveFrom>
|
|
268
|
+
* <w:moveFromRangeEnd w:id="1"/>
|
|
269
|
+
*/
|
|
270
|
+
export function generateMoveSourceMarkup(moveName, content, options) {
|
|
271
|
+
const { DOMParser } = require('@xmldom/xmldom');
|
|
272
|
+
const doc = new DOMParser().parseFromString('<root xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>', 'application/xml');
|
|
273
|
+
const W_NS = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
274
|
+
const dateStr = formatDateTime(options.dateTime);
|
|
275
|
+
const rangeId = options.startId.toString();
|
|
276
|
+
const moveId = (options.startId + 1).toString();
|
|
277
|
+
const rangeStart = doc.createElementNS(W_NS, 'w:moveFromRangeStart');
|
|
278
|
+
rangeStart.setAttribute('w:id', rangeId);
|
|
279
|
+
rangeStart.setAttribute('w:name', moveName);
|
|
280
|
+
rangeStart.setAttribute('w:author', options.author);
|
|
281
|
+
rangeStart.setAttribute('w:date', dateStr);
|
|
282
|
+
const moveWrapper = doc.createElementNS(W_NS, 'w:moveFrom');
|
|
283
|
+
moveWrapper.setAttribute('w:id', moveId);
|
|
284
|
+
moveWrapper.setAttribute('w:author', options.author);
|
|
285
|
+
moveWrapper.setAttribute('w:date', dateStr);
|
|
286
|
+
for (const child of content)
|
|
287
|
+
moveWrapper.appendChild(child);
|
|
288
|
+
const rangeEnd = doc.createElementNS(W_NS, 'w:moveFromRangeEnd');
|
|
289
|
+
rangeEnd.setAttribute('w:id', rangeId);
|
|
290
|
+
return {
|
|
291
|
+
rangeStart,
|
|
292
|
+
moveWrapper,
|
|
293
|
+
rangeEnd,
|
|
294
|
+
nextId: options.startId + 2,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Generate move destination markup (w:moveTo with range markers).
|
|
299
|
+
*
|
|
300
|
+
* @param moveName - Name linking source and destination (e.g., "move1")
|
|
301
|
+
* @param content - Child elements to wrap
|
|
302
|
+
* @param options - Markup generation options
|
|
303
|
+
* @returns Move markup elements
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* Output structure:
|
|
307
|
+
* <w:moveToRangeStart w:id="3" w:name="move1" w:author="..." w:date="..."/>
|
|
308
|
+
* <w:moveTo w:id="4" w:author="..." w:date="...">
|
|
309
|
+
* <!-- content -->
|
|
310
|
+
* </w:moveTo>
|
|
311
|
+
* <w:moveToRangeEnd w:id="3"/>
|
|
312
|
+
*/
|
|
313
|
+
export function generateMoveDestinationMarkup(moveName, content, options) {
|
|
314
|
+
const { DOMParser } = require('@xmldom/xmldom');
|
|
315
|
+
const doc = new DOMParser().parseFromString('<root xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>', 'application/xml');
|
|
316
|
+
const W_NS = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
317
|
+
const dateStr = formatDateTime(options.dateTime);
|
|
318
|
+
const rangeId = options.startId.toString();
|
|
319
|
+
const moveId = (options.startId + 1).toString();
|
|
320
|
+
const rangeStart = doc.createElementNS(W_NS, 'w:moveToRangeStart');
|
|
321
|
+
rangeStart.setAttribute('w:id', rangeId);
|
|
322
|
+
rangeStart.setAttribute('w:name', moveName);
|
|
323
|
+
rangeStart.setAttribute('w:author', options.author);
|
|
324
|
+
rangeStart.setAttribute('w:date', dateStr);
|
|
325
|
+
const moveWrapper = doc.createElementNS(W_NS, 'w:moveTo');
|
|
326
|
+
moveWrapper.setAttribute('w:id', moveId);
|
|
327
|
+
moveWrapper.setAttribute('w:author', options.author);
|
|
328
|
+
moveWrapper.setAttribute('w:date', dateStr);
|
|
329
|
+
for (const child of content)
|
|
330
|
+
moveWrapper.appendChild(child);
|
|
331
|
+
const rangeEnd = doc.createElementNS(W_NS, 'w:moveToRangeEnd');
|
|
332
|
+
rangeEnd.setAttribute('w:id', rangeId);
|
|
333
|
+
return {
|
|
334
|
+
rangeStart,
|
|
335
|
+
moveWrapper,
|
|
336
|
+
rangeEnd,
|
|
337
|
+
nextId: options.startId + 2,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Create initial revision ID state.
|
|
342
|
+
*
|
|
343
|
+
* @param startId - Starting ID (default: 1)
|
|
344
|
+
* @returns Initial state
|
|
345
|
+
*/
|
|
346
|
+
export function createRevisionIdState(startId = 1) {
|
|
347
|
+
return {
|
|
348
|
+
nextId: startId,
|
|
349
|
+
moveRangeIds: new Map(),
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Allocate IDs for a move operation.
|
|
354
|
+
*
|
|
355
|
+
* Ensures source and destination use consistent IDs for proper linking.
|
|
356
|
+
*
|
|
357
|
+
* @param state - Revision ID state (modified in place)
|
|
358
|
+
* @param moveName - Move name (e.g., "move1")
|
|
359
|
+
* @returns IDs for source and destination markup
|
|
360
|
+
*/
|
|
361
|
+
export function allocateMoveIds(state, moveName) {
|
|
362
|
+
let ids = state.moveRangeIds.get(moveName);
|
|
363
|
+
if (!ids) {
|
|
364
|
+
// Allocate new IDs: source range, source move, dest range, dest move
|
|
365
|
+
ids = {
|
|
366
|
+
sourceRangeId: state.nextId,
|
|
367
|
+
destRangeId: state.nextId + 2,
|
|
368
|
+
};
|
|
369
|
+
state.moveRangeIds.set(moveName, ids);
|
|
370
|
+
state.nextId += 4;
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
sourceRangeId: ids.sourceRangeId,
|
|
374
|
+
sourceMoveId: ids.sourceRangeId + 1,
|
|
375
|
+
destRangeId: ids.destRangeId,
|
|
376
|
+
destMoveId: ids.destRangeId + 1,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Fix up revision IDs after all moves have been processed.
|
|
381
|
+
*
|
|
382
|
+
* Ensures proper ID pairing between source and destination elements.
|
|
383
|
+
* This is a post-processing step after markup generation.
|
|
384
|
+
*
|
|
385
|
+
* @param state - The revision ID state
|
|
386
|
+
*/
|
|
387
|
+
export function fixUpRevisionIds(_state) {
|
|
388
|
+
// No-op for now - IDs are allocated consistently during generation
|
|
389
|
+
// This function exists for future use if ID renumbering is needed
|
|
390
|
+
}
|
|
391
|
+
//# sourceMappingURL=move-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"move-detection.js","sourceRoot":"","sources":["../src/move-detection.ts"],"names":[],"mappings":"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"}
|