docrev 0.9.4 → 0.9.6
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/dist/lib/commands/comments.d.ts.map +1 -1
- package/dist/lib/commands/comments.js +19 -27
- package/dist/lib/commands/comments.js.map +1 -1
- package/dist/lib/commands/context.d.ts +1 -0
- package/dist/lib/commands/context.d.ts.map +1 -1
- package/dist/lib/commands/context.js +1 -2
- package/dist/lib/commands/context.js.map +1 -1
- package/dist/lib/commands/file-ops.d.ts +11 -0
- package/dist/lib/commands/file-ops.d.ts.map +1 -0
- package/dist/lib/commands/file-ops.js +301 -0
- package/dist/lib/commands/file-ops.js.map +1 -0
- package/dist/lib/commands/index.d.ts +9 -1
- package/dist/lib/commands/index.d.ts.map +1 -1
- package/dist/lib/commands/index.js +17 -1
- package/dist/lib/commands/index.js.map +1 -1
- package/dist/lib/commands/merge-resolve.d.ts +12 -0
- package/dist/lib/commands/merge-resolve.d.ts.map +1 -0
- package/dist/lib/commands/merge-resolve.js +318 -0
- package/dist/lib/commands/merge-resolve.js.map +1 -0
- package/dist/lib/commands/preview.d.ts +11 -0
- package/dist/lib/commands/preview.d.ts.map +1 -0
- package/dist/lib/commands/preview.js +138 -0
- package/dist/lib/commands/preview.js.map +1 -0
- package/dist/lib/commands/project-info.d.ts +11 -0
- package/dist/lib/commands/project-info.d.ts.map +1 -0
- package/dist/lib/commands/project-info.js +187 -0
- package/dist/lib/commands/project-info.js.map +1 -0
- package/dist/lib/commands/quality.d.ts +11 -0
- package/dist/lib/commands/quality.d.ts.map +1 -0
- package/dist/lib/commands/quality.js +384 -0
- package/dist/lib/commands/quality.js.map +1 -0
- package/dist/lib/commands/sections.d.ts +3 -2
- package/dist/lib/commands/sections.d.ts.map +1 -1
- package/dist/lib/commands/sections.js +4 -723
- package/dist/lib/commands/sections.js.map +1 -1
- package/dist/lib/commands/sync.d.ts +11 -0
- package/dist/lib/commands/sync.d.ts.map +1 -0
- package/dist/lib/commands/sync.js +441 -0
- package/dist/lib/commands/sync.js.map +1 -0
- package/dist/lib/commands/text-ops.d.ts +11 -0
- package/dist/lib/commands/text-ops.d.ts.map +1 -0
- package/dist/lib/commands/text-ops.js +357 -0
- package/dist/lib/commands/text-ops.js.map +1 -0
- package/dist/lib/commands/utilities.d.ts +2 -4
- package/dist/lib/commands/utilities.d.ts.map +1 -1
- package/dist/lib/commands/utilities.js +3 -1605
- package/dist/lib/commands/utilities.js.map +1 -1
- package/dist/lib/commands/word-tools.d.ts +11 -0
- package/dist/lib/commands/word-tools.d.ts.map +1 -0
- package/dist/lib/commands/word-tools.js +272 -0
- package/dist/lib/commands/word-tools.js.map +1 -0
- package/dist/lib/comment-realign.d.ts.map +1 -1
- package/dist/lib/comment-realign.js +0 -7
- package/dist/lib/comment-realign.js.map +1 -1
- package/dist/lib/dependencies.d.ts.map +1 -1
- package/dist/lib/dependencies.js +11 -23
- package/dist/lib/dependencies.js.map +1 -1
- package/dist/lib/diff-engine.d.ts +25 -0
- package/dist/lib/diff-engine.d.ts.map +1 -0
- package/dist/lib/diff-engine.js +354 -0
- package/dist/lib/diff-engine.js.map +1 -0
- package/dist/lib/git.d.ts.map +1 -1
- package/dist/lib/git.js +18 -28
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/import.d.ts +37 -117
- package/dist/lib/import.d.ts.map +1 -1
- package/dist/lib/import.js +10 -1039
- package/dist/lib/import.js.map +1 -1
- package/dist/lib/merge.d.ts.map +1 -1
- package/dist/lib/merge.js +29 -117
- package/dist/lib/merge.js.map +1 -1
- package/dist/lib/pdf-comments.d.ts.map +1 -1
- package/dist/lib/pdf-comments.js +1 -13
- package/dist/lib/pdf-comments.js.map +1 -1
- package/dist/lib/pptx-themes.d.ts.map +1 -1
- package/dist/lib/pptx-themes.js +0 -403
- package/dist/lib/pptx-themes.js.map +1 -1
- package/dist/lib/protect-restore.d.ts.map +1 -1
- package/dist/lib/protect-restore.js +34 -36
- package/dist/lib/protect-restore.js.map +1 -1
- package/dist/lib/restore-references.d.ts +35 -0
- package/dist/lib/restore-references.d.ts.map +1 -0
- package/dist/lib/restore-references.js +188 -0
- package/dist/lib/restore-references.js.map +1 -0
- package/dist/lib/slides.d.ts.map +1 -1
- package/dist/lib/slides.js +0 -35
- package/dist/lib/slides.js.map +1 -1
- package/dist/lib/trackchanges.d.ts.map +1 -1
- package/dist/lib/trackchanges.js +1 -11
- package/dist/lib/trackchanges.js.map +1 -1
- package/dist/lib/tui.d.ts +36 -45
- package/dist/lib/tui.d.ts.map +1 -1
- package/dist/lib/tui.js +92 -108
- package/dist/lib/tui.js.map +1 -1
- package/dist/lib/undo.d.ts +3 -4
- package/dist/lib/undo.d.ts.map +1 -1
- package/dist/lib/undo.js +0 -7
- package/dist/lib/undo.js.map +1 -1
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +26 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/word-extraction.d.ts +77 -0
- package/dist/lib/word-extraction.d.ts.map +1 -0
- package/dist/lib/word-extraction.js +515 -0
- package/dist/lib/word-extraction.js.map +1 -0
- package/dist/lib/wordcomments.d.ts.map +1 -1
- package/dist/lib/wordcomments.js +1 -8
- package/dist/lib/wordcomments.js.map +1 -1
- package/dist/package.json +137 -0
- package/lib/commands/comments.ts +20 -25
- package/lib/commands/context.ts +1 -2
- package/lib/commands/file-ops.ts +372 -0
- package/lib/commands/index.ts +24 -0
- package/lib/commands/merge-resolve.ts +378 -0
- package/lib/commands/preview.ts +178 -0
- package/lib/commands/project-info.ts +244 -0
- package/lib/commands/quality.ts +517 -0
- package/lib/commands/sections.ts +3 -857
- package/lib/commands/sync.ts +536 -0
- package/lib/commands/text-ops.ts +449 -0
- package/lib/commands/utilities.ts +62 -2066
- package/lib/commands/word-tools.ts +340 -0
- package/lib/comment-realign.ts +0 -8
- package/lib/dependencies.ts +12 -20
- package/lib/diff-engine.ts +465 -0
- package/lib/git.ts +24 -31
- package/lib/import.ts +78 -1348
- package/lib/merge.ts +42 -132
- package/lib/pdf-comments.ts +2 -14
- package/lib/pptx-themes.ts +0 -413
- package/lib/protect-restore.ts +48 -44
- package/lib/restore-references.ts +240 -0
- package/lib/slides.ts +0 -37
- package/lib/trackchanges.ts +1 -12
- package/lib/{tui.js → tui.ts} +139 -126
- package/lib/undo.ts +3 -12
- package/lib/utils.ts +28 -0
- package/lib/word-extraction.ts +666 -0
- package/lib/wordcomments.ts +1 -9
- package/package.json +1 -1
package/lib/merge.ts
CHANGED
|
@@ -178,18 +178,15 @@ export async function checkBaseMatch(basePath: string, reviewerPath: string): Pr
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
|
-
* Extract changes from
|
|
182
|
-
*
|
|
183
|
-
* @param originalText - Original text (from base document)
|
|
184
|
-
* @param wordText - Text extracted from reviewer's Word doc
|
|
181
|
+
* Extract changes from diffs between original and modified text
|
|
182
|
+
* @param diffs - Array of diff changes
|
|
185
183
|
* @param reviewer - Reviewer identifier
|
|
186
184
|
*/
|
|
187
|
-
|
|
185
|
+
function extractChangesFromDiffs(
|
|
186
|
+
diffs: Array<{ added?: boolean; removed?: boolean; value: string }>,
|
|
187
|
+
reviewer: string,
|
|
188
|
+
): ReviewerChange[] {
|
|
188
189
|
const changes: ReviewerChange[] = [];
|
|
189
|
-
|
|
190
|
-
// Use sentence-level diff for better granularity
|
|
191
|
-
const diffs = diffSentences(originalText, wordText);
|
|
192
|
-
|
|
193
190
|
let originalPos = 0;
|
|
194
191
|
let i = 0;
|
|
195
192
|
|
|
@@ -198,11 +195,9 @@ export function extractChanges(originalText: string, wordText: string, reviewer:
|
|
|
198
195
|
if (!part) break;
|
|
199
196
|
|
|
200
197
|
if (!part.added && !part.removed) {
|
|
201
|
-
// Unchanged
|
|
202
198
|
originalPos += part.value.length;
|
|
203
199
|
i++;
|
|
204
200
|
} else if (part.removed && diffs[i + 1]?.added) {
|
|
205
|
-
// Replacement: removed followed by added
|
|
206
201
|
const nextPart = diffs[i + 1];
|
|
207
202
|
if (!nextPart) break;
|
|
208
203
|
changes.push({
|
|
@@ -216,7 +211,6 @@ export function extractChanges(originalText: string, wordText: string, reviewer:
|
|
|
216
211
|
originalPos += part.value.length;
|
|
217
212
|
i += 2;
|
|
218
213
|
} else if (part.removed) {
|
|
219
|
-
// Pure deletion
|
|
220
214
|
changes.push({
|
|
221
215
|
reviewer,
|
|
222
216
|
type: 'delete',
|
|
@@ -228,7 +222,6 @@ export function extractChanges(originalText: string, wordText: string, reviewer:
|
|
|
228
222
|
originalPos += part.value.length;
|
|
229
223
|
i++;
|
|
230
224
|
} else if (part.added) {
|
|
231
|
-
// Pure insertion
|
|
232
225
|
changes.push({
|
|
233
226
|
reviewer,
|
|
234
227
|
type: 'insert',
|
|
@@ -244,61 +237,22 @@ export function extractChanges(originalText: string, wordText: string, reviewer:
|
|
|
244
237
|
return changes;
|
|
245
238
|
}
|
|
246
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Extract changes from a Word document compared to original
|
|
242
|
+
* Uses sentence-level diffing for better conflict detection
|
|
243
|
+
* @param originalText - Original text (from base document)
|
|
244
|
+
* @param wordText - Text extracted from reviewer's Word doc
|
|
245
|
+
* @param reviewer - Reviewer identifier
|
|
246
|
+
*/
|
|
247
|
+
export function extractChanges(originalText: string, wordText: string, reviewer: string): ReviewerChange[] {
|
|
248
|
+
return extractChangesFromDiffs(diffSentences(originalText, wordText), reviewer);
|
|
249
|
+
}
|
|
250
|
+
|
|
247
251
|
/**
|
|
248
252
|
* Extract changes using word-level diff (more fine-grained)
|
|
249
253
|
*/
|
|
250
254
|
export function extractChangesWordLevel(originalText: string, wordText: string, reviewer: string): ReviewerChange[] {
|
|
251
|
-
|
|
252
|
-
const diffs = diffWords(originalText, wordText);
|
|
253
|
-
|
|
254
|
-
let originalPos = 0;
|
|
255
|
-
let i = 0;
|
|
256
|
-
|
|
257
|
-
while (i < diffs.length) {
|
|
258
|
-
const part = diffs[i];
|
|
259
|
-
if (!part) break;
|
|
260
|
-
|
|
261
|
-
if (!part.added && !part.removed) {
|
|
262
|
-
originalPos += part.value.length;
|
|
263
|
-
i++;
|
|
264
|
-
} else if (part.removed && diffs[i + 1]?.added) {
|
|
265
|
-
const nextPart = diffs[i + 1];
|
|
266
|
-
if (!nextPart) break;
|
|
267
|
-
changes.push({
|
|
268
|
-
reviewer,
|
|
269
|
-
type: 'replace',
|
|
270
|
-
start: originalPos,
|
|
271
|
-
end: originalPos + part.value.length,
|
|
272
|
-
oldText: part.value,
|
|
273
|
-
newText: nextPart.value,
|
|
274
|
-
});
|
|
275
|
-
originalPos += part.value.length;
|
|
276
|
-
i += 2;
|
|
277
|
-
} else if (part.removed) {
|
|
278
|
-
changes.push({
|
|
279
|
-
reviewer,
|
|
280
|
-
type: 'delete',
|
|
281
|
-
start: originalPos,
|
|
282
|
-
end: originalPos + part.value.length,
|
|
283
|
-
oldText: part.value,
|
|
284
|
-
newText: '',
|
|
285
|
-
});
|
|
286
|
-
originalPos += part.value.length;
|
|
287
|
-
i++;
|
|
288
|
-
} else if (part.added) {
|
|
289
|
-
changes.push({
|
|
290
|
-
reviewer,
|
|
291
|
-
type: 'insert',
|
|
292
|
-
start: originalPos,
|
|
293
|
-
end: originalPos,
|
|
294
|
-
oldText: '',
|
|
295
|
-
newText: part.value,
|
|
296
|
-
});
|
|
297
|
-
i++;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return changes;
|
|
255
|
+
return extractChangesFromDiffs(diffWords(originalText, wordText), reviewer);
|
|
302
256
|
}
|
|
303
257
|
|
|
304
258
|
/**
|
|
@@ -563,23 +517,15 @@ export function clearConflicts(projectDir: string): void {
|
|
|
563
517
|
}
|
|
564
518
|
|
|
565
519
|
/**
|
|
566
|
-
*
|
|
520
|
+
* Core merge logic: extract changes from reviewer docs, detect conflicts, apply annotations
|
|
567
521
|
*/
|
|
568
|
-
|
|
569
|
-
|
|
522
|
+
async function mergeReviewerDocsCore(
|
|
523
|
+
baseText: string,
|
|
570
524
|
reviewerDocs: ReviewerDoc[],
|
|
571
|
-
options: MergeOptions = {}
|
|
572
|
-
): Promise<MergeResult
|
|
525
|
+
options: MergeOptions = {},
|
|
526
|
+
): Promise<MergeResult> {
|
|
573
527
|
const { diffLevel = 'sentence' } = options;
|
|
574
528
|
|
|
575
|
-
if (!fs.existsSync(basePath)) {
|
|
576
|
-
throw new Error(`Base document not found: ${basePath}`);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
// Extract text from base document
|
|
580
|
-
const { text: baseText } = await extractFromWord(basePath);
|
|
581
|
-
|
|
582
|
-
// Extract changes from each reviewer relative to base
|
|
583
529
|
const allChanges: ReviewerChange[][] = [];
|
|
584
530
|
const allComments: ReviewerComment[] = [];
|
|
585
531
|
|
|
@@ -590,14 +536,12 @@ export async function mergeThreeWay(
|
|
|
590
536
|
|
|
591
537
|
const { text: wordText } = await extractFromWord(doc.path);
|
|
592
538
|
|
|
593
|
-
// Choose diff level
|
|
594
539
|
const changes = diffLevel === 'word'
|
|
595
540
|
? extractChangesWordLevel(baseText, wordText, doc.name)
|
|
596
541
|
: extractChanges(baseText, wordText, doc.name);
|
|
597
542
|
|
|
598
543
|
allChanges.push(changes);
|
|
599
544
|
|
|
600
|
-
// Also extract comments
|
|
601
545
|
try {
|
|
602
546
|
const comments = await extractWordComments(doc.path);
|
|
603
547
|
allComments.push(...comments.map(c => ({ ...c, reviewer: doc.name })));
|
|
@@ -609,13 +553,10 @@ export async function mergeThreeWay(
|
|
|
609
553
|
}
|
|
610
554
|
}
|
|
611
555
|
|
|
612
|
-
// Detect conflicts
|
|
613
556
|
const { conflicts, nonConflicting } = detectConflicts(allChanges);
|
|
614
557
|
|
|
615
|
-
// Apply non-conflicting changes as annotations
|
|
616
558
|
let merged = applyChangesAsAnnotations(baseText, nonConflicting);
|
|
617
559
|
|
|
618
|
-
// Add comments with reviewer attribution
|
|
619
560
|
for (const comment of allComments) {
|
|
620
561
|
merged += `\n{>>${comment.reviewer}: ${comment.text}<<}`;
|
|
621
562
|
}
|
|
@@ -628,7 +569,24 @@ export async function mergeThreeWay(
|
|
|
628
569
|
comments: allComments.length,
|
|
629
570
|
};
|
|
630
571
|
|
|
631
|
-
return { merged, conflicts, stats,
|
|
572
|
+
return { merged, conflicts, stats, originalText: baseText };
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Merge multiple Word documents using three-way merge
|
|
577
|
+
*/
|
|
578
|
+
export async function mergeThreeWay(
|
|
579
|
+
basePath: string,
|
|
580
|
+
reviewerDocs: ReviewerDoc[],
|
|
581
|
+
options: MergeOptions = {}
|
|
582
|
+
): Promise<MergeResult & { baseText: string }> {
|
|
583
|
+
if (!fs.existsSync(basePath)) {
|
|
584
|
+
throw new Error(`Base document not found: ${basePath}`);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const { text: baseText } = await extractFromWord(basePath);
|
|
588
|
+
const result = await mergeReviewerDocsCore(baseText, reviewerDocs, options);
|
|
589
|
+
return { ...result, baseText };
|
|
632
590
|
}
|
|
633
591
|
|
|
634
592
|
/**
|
|
@@ -640,60 +598,12 @@ export async function mergeReviewerDocs(
|
|
|
640
598
|
reviewerDocs: ReviewerDoc[],
|
|
641
599
|
options: MergeOptions = {}
|
|
642
600
|
): Promise<MergeResult> {
|
|
643
|
-
const { autoResolve = false } = options;
|
|
644
|
-
|
|
645
601
|
if (!fs.existsSync(originalPath)) {
|
|
646
602
|
throw new Error(`Original file not found: ${originalPath}`);
|
|
647
603
|
}
|
|
648
604
|
|
|
649
605
|
const originalText = fs.readFileSync(originalPath, 'utf-8');
|
|
650
|
-
|
|
651
|
-
// Extract changes from each reviewer
|
|
652
|
-
const allChanges: ReviewerChange[][] = [];
|
|
653
|
-
const allComments: ReviewerComment[] = [];
|
|
654
|
-
|
|
655
|
-
for (const doc of reviewerDocs) {
|
|
656
|
-
if (!fs.existsSync(doc.path)) {
|
|
657
|
-
throw new Error(`Reviewer file not found: ${doc.path}`);
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
const { text: wordText } = await extractFromWord(doc.path);
|
|
661
|
-
const changes = extractChanges(originalText, wordText, doc.name);
|
|
662
|
-
allChanges.push(changes);
|
|
663
|
-
|
|
664
|
-
// Also extract comments
|
|
665
|
-
try {
|
|
666
|
-
const comments = await extractWordComments(doc.path);
|
|
667
|
-
allComments.push(...comments.map(c => ({ ...c, reviewer: doc.name })));
|
|
668
|
-
} catch (e) {
|
|
669
|
-
if (process.env.DEBUG) {
|
|
670
|
-
const error = e as Error;
|
|
671
|
-
console.warn(`merge: Failed to extract comments:`, error.message);
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// Detect conflicts
|
|
677
|
-
const { conflicts, nonConflicting } = detectConflicts(allChanges);
|
|
678
|
-
|
|
679
|
-
// Apply non-conflicting changes as annotations
|
|
680
|
-
let merged = applyChangesAsAnnotations(originalText, nonConflicting);
|
|
681
|
-
|
|
682
|
-
// Add comments
|
|
683
|
-
for (const comment of allComments) {
|
|
684
|
-
// Append comments at the end for now (position tracking is complex)
|
|
685
|
-
merged += `\n{>>${comment.reviewer}: ${comment.text}<<}`;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
const stats = {
|
|
689
|
-
reviewers: reviewerDocs.length,
|
|
690
|
-
totalChanges: allChanges.flat().length,
|
|
691
|
-
nonConflicting: nonConflicting.length,
|
|
692
|
-
conflicts: conflicts.length,
|
|
693
|
-
comments: allComments.length,
|
|
694
|
-
};
|
|
695
|
-
|
|
696
|
-
return { merged, conflicts, stats, originalText };
|
|
606
|
+
return mergeReviewerDocsCore(originalText, reviewerDocs, options);
|
|
697
607
|
}
|
|
698
608
|
|
|
699
609
|
/**
|
package/lib/pdf-comments.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Converts CriticMarkup comments to LaTeX margin notes for PDF output
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { escapeLatex } from './utils.js';
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* LaTeX preamble for margin comments
|
|
9
11
|
* Uses todonotes package with custom styling
|
|
@@ -117,20 +119,6 @@ export function convertCommentsToMarginNotes(
|
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
/**
|
|
121
|
-
* Escape LaTeX special characters
|
|
122
|
-
* @param text - Text to escape
|
|
123
|
-
* @returns Escaped text
|
|
124
|
-
*/
|
|
125
|
-
function escapeLatex(text: string): string {
|
|
126
|
-
return text
|
|
127
|
-
.replace(/\\/g, '\\textbackslash{}')
|
|
128
|
-
.replace(/([#$%&_{}])/g, '\\$1')
|
|
129
|
-
.replace(/\^/g, '\\textasciicircum{}')
|
|
130
|
-
.replace(/~/g, '\\textasciitilde{}')
|
|
131
|
-
.replace(/\n/g, ' '); // Replace newlines with spaces
|
|
132
|
-
}
|
|
133
|
-
|
|
134
122
|
/**
|
|
135
123
|
* Result of track changes conversion
|
|
136
124
|
*/
|