docrev 0.8.1 → 0.8.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/.claude/settings.local.json +9 -0
- package/PLAN-tables-and-postprocess.md +850 -0
- package/README.md +33 -0
- package/bin/rev.js +12 -131
- package/bin/rev.ts +145 -0
- package/dist/bin/rev.d.ts +9 -0
- package/dist/bin/rev.d.ts.map +1 -0
- package/dist/bin/rev.js +118 -0
- package/dist/bin/rev.js.map +1 -0
- package/dist/lib/annotations.d.ts +91 -0
- package/dist/lib/annotations.d.ts.map +1 -0
- package/dist/lib/annotations.js +554 -0
- package/dist/lib/annotations.js.map +1 -0
- package/dist/lib/build.d.ts +171 -0
- package/dist/lib/build.d.ts.map +1 -0
- package/dist/lib/build.js +755 -0
- package/dist/lib/build.js.map +1 -0
- package/dist/lib/citations.d.ts +34 -0
- package/dist/lib/citations.d.ts.map +1 -0
- package/dist/lib/citations.js +140 -0
- package/dist/lib/citations.js.map +1 -0
- package/dist/lib/commands/build.d.ts +13 -0
- package/dist/lib/commands/build.d.ts.map +1 -0
- package/dist/lib/commands/build.js +678 -0
- package/dist/lib/commands/build.js.map +1 -0
- package/dist/lib/commands/citations.d.ts +11 -0
- package/dist/lib/commands/citations.d.ts.map +1 -0
- package/dist/lib/commands/citations.js +428 -0
- package/dist/lib/commands/citations.js.map +1 -0
- package/dist/lib/commands/comments.d.ts +11 -0
- package/dist/lib/commands/comments.d.ts.map +1 -0
- package/dist/lib/commands/comments.js +883 -0
- package/dist/lib/commands/comments.js.map +1 -0
- package/dist/lib/commands/context.d.ts +35 -0
- package/dist/lib/commands/context.d.ts.map +1 -0
- package/dist/lib/commands/context.js +59 -0
- package/dist/lib/commands/context.js.map +1 -0
- package/dist/lib/commands/core.d.ts +11 -0
- package/dist/lib/commands/core.d.ts.map +1 -0
- package/dist/lib/commands/core.js +246 -0
- package/dist/lib/commands/core.js.map +1 -0
- package/dist/lib/commands/doi.d.ts +11 -0
- package/dist/lib/commands/doi.d.ts.map +1 -0
- package/dist/lib/commands/doi.js +373 -0
- package/dist/lib/commands/doi.js.map +1 -0
- package/dist/lib/commands/history.d.ts +11 -0
- package/dist/lib/commands/history.d.ts.map +1 -0
- package/dist/lib/commands/history.js +245 -0
- package/dist/lib/commands/history.js.map +1 -0
- package/dist/lib/commands/index.d.ts +28 -0
- package/dist/lib/commands/index.d.ts.map +1 -0
- package/dist/lib/commands/index.js +35 -0
- package/dist/lib/commands/index.js.map +1 -0
- package/dist/lib/commands/init.d.ts +11 -0
- package/dist/lib/commands/init.d.ts.map +1 -0
- package/dist/lib/commands/init.js +209 -0
- package/dist/lib/commands/init.js.map +1 -0
- package/dist/lib/commands/response.d.ts +11 -0
- package/dist/lib/commands/response.d.ts.map +1 -0
- package/dist/lib/commands/response.js +317 -0
- package/dist/lib/commands/response.js.map +1 -0
- package/dist/lib/commands/sections.d.ts +11 -0
- package/dist/lib/commands/sections.d.ts.map +1 -0
- package/dist/lib/commands/sections.js +1071 -0
- package/dist/lib/commands/sections.js.map +1 -0
- package/dist/lib/commands/utilities.d.ts +19 -0
- package/dist/lib/commands/utilities.d.ts.map +1 -0
- package/dist/lib/commands/utilities.js +2009 -0
- package/dist/lib/commands/utilities.js.map +1 -0
- package/dist/lib/comment-realign.d.ts +50 -0
- package/dist/lib/comment-realign.d.ts.map +1 -0
- package/dist/lib/comment-realign.js +372 -0
- package/dist/lib/comment-realign.js.map +1 -0
- package/dist/lib/config.d.ts +41 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +76 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/crossref.d.ts +108 -0
- package/dist/lib/crossref.d.ts.map +1 -0
- package/dist/lib/crossref.js +597 -0
- package/dist/lib/crossref.js.map +1 -0
- package/dist/lib/dependencies.d.ts +30 -0
- package/dist/lib/dependencies.d.ts.map +1 -0
- package/dist/lib/dependencies.js +95 -0
- package/dist/lib/dependencies.js.map +1 -0
- package/dist/lib/doi-cache.d.ts +29 -0
- package/dist/lib/doi-cache.d.ts.map +1 -0
- package/dist/lib/doi-cache.js +104 -0
- package/dist/lib/doi-cache.js.map +1 -0
- package/dist/lib/doi.d.ts +65 -0
- package/dist/lib/doi.d.ts.map +1 -0
- package/dist/lib/doi.js +710 -0
- package/dist/lib/doi.js.map +1 -0
- package/dist/lib/equations.d.ts +61 -0
- package/dist/lib/equations.d.ts.map +1 -0
- package/dist/lib/equations.js +445 -0
- package/dist/lib/equations.js.map +1 -0
- package/dist/lib/errors.d.ts +60 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +303 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/format.d.ts +104 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +416 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/git.d.ts +88 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +304 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/grammar.d.ts +62 -0
- package/dist/lib/grammar.d.ts.map +1 -0
- package/dist/lib/grammar.js +244 -0
- package/dist/lib/grammar.js.map +1 -0
- package/dist/lib/image-registry.d.ts +68 -0
- package/dist/lib/image-registry.d.ts.map +1 -0
- package/dist/lib/image-registry.js +112 -0
- package/dist/lib/image-registry.js.map +1 -0
- package/dist/lib/import.d.ts +184 -0
- package/dist/lib/import.d.ts.map +1 -0
- package/dist/lib/import.js +1581 -0
- package/dist/lib/import.js.map +1 -0
- package/dist/lib/journals.d.ts +55 -0
- package/dist/lib/journals.d.ts.map +1 -0
- package/dist/lib/journals.js +417 -0
- package/dist/lib/journals.js.map +1 -0
- package/dist/lib/merge.d.ts +138 -0
- package/dist/lib/merge.d.ts.map +1 -0
- package/dist/lib/merge.js +603 -0
- package/dist/lib/merge.js.map +1 -0
- package/dist/lib/orcid.d.ts +36 -0
- package/dist/lib/orcid.d.ts.map +1 -0
- package/dist/lib/orcid.js +117 -0
- package/dist/lib/orcid.js.map +1 -0
- package/dist/lib/pdf-comments.d.ts +95 -0
- package/dist/lib/pdf-comments.d.ts.map +1 -0
- package/dist/lib/pdf-comments.js +192 -0
- package/dist/lib/pdf-comments.js.map +1 -0
- package/dist/lib/pdf-import.d.ts +118 -0
- package/dist/lib/pdf-import.d.ts.map +1 -0
- package/dist/lib/pdf-import.js +397 -0
- package/dist/lib/pdf-import.js.map +1 -0
- package/dist/lib/plugins.d.ts +76 -0
- package/dist/lib/plugins.d.ts.map +1 -0
- package/dist/lib/plugins.js +235 -0
- package/dist/lib/plugins.js.map +1 -0
- package/dist/lib/postprocess.d.ts +42 -0
- package/dist/lib/postprocess.d.ts.map +1 -0
- package/dist/lib/postprocess.js +138 -0
- package/dist/lib/postprocess.js.map +1 -0
- package/dist/lib/pptx-template.d.ts +59 -0
- package/dist/lib/pptx-template.d.ts.map +1 -0
- package/dist/lib/pptx-template.js +613 -0
- package/dist/lib/pptx-template.js.map +1 -0
- package/dist/lib/pptx-themes.d.ts +80 -0
- package/dist/lib/pptx-themes.d.ts.map +1 -0
- package/dist/lib/pptx-themes.js +818 -0
- package/dist/lib/pptx-themes.js.map +1 -0
- package/dist/lib/protect-restore.d.ts +137 -0
- package/dist/lib/protect-restore.d.ts.map +1 -0
- package/dist/lib/protect-restore.js +394 -0
- package/dist/lib/protect-restore.js.map +1 -0
- package/dist/lib/rate-limiter.d.ts +27 -0
- package/dist/lib/rate-limiter.d.ts.map +1 -0
- package/dist/lib/rate-limiter.js +79 -0
- package/dist/lib/rate-limiter.js.map +1 -0
- package/dist/lib/response.d.ts +41 -0
- package/dist/lib/response.d.ts.map +1 -0
- package/dist/lib/response.js +150 -0
- package/dist/lib/response.js.map +1 -0
- package/dist/lib/review.d.ts +35 -0
- package/dist/lib/review.d.ts.map +1 -0
- package/dist/lib/review.js +263 -0
- package/dist/lib/review.js.map +1 -0
- package/dist/lib/schema.d.ts +66 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +339 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/lib/scientific-words.d.ts +6 -0
- package/dist/lib/scientific-words.d.ts.map +1 -0
- package/dist/lib/scientific-words.js +66 -0
- package/dist/lib/scientific-words.js.map +1 -0
- package/dist/lib/sections.d.ts +40 -0
- package/dist/lib/sections.d.ts.map +1 -0
- package/dist/lib/sections.js +288 -0
- package/dist/lib/sections.js.map +1 -0
- package/dist/lib/slides.d.ts +86 -0
- package/dist/lib/slides.d.ts.map +1 -0
- package/dist/lib/slides.js +676 -0
- package/dist/lib/slides.js.map +1 -0
- package/dist/lib/spelling.d.ts +76 -0
- package/dist/lib/spelling.d.ts.map +1 -0
- package/dist/lib/spelling.js +272 -0
- package/dist/lib/spelling.js.map +1 -0
- package/dist/lib/templates.d.ts +30 -0
- package/dist/lib/templates.d.ts.map +1 -0
- package/dist/lib/templates.js +504 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/themes.d.ts +85 -0
- package/dist/lib/themes.d.ts.map +1 -0
- package/dist/lib/themes.js +652 -0
- package/dist/lib/themes.js.map +1 -0
- package/dist/lib/trackchanges.d.ts +51 -0
- package/dist/lib/trackchanges.d.ts.map +1 -0
- package/dist/lib/trackchanges.js +202 -0
- package/dist/lib/trackchanges.js.map +1 -0
- package/dist/lib/tui.d.ts +76 -0
- package/dist/lib/tui.d.ts.map +1 -0
- package/dist/lib/tui.js +377 -0
- package/dist/lib/tui.js.map +1 -0
- package/dist/lib/types.d.ts +447 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +6 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/undo.d.ts +57 -0
- package/dist/lib/undo.d.ts.map +1 -0
- package/dist/lib/undo.js +185 -0
- package/dist/lib/undo.js.map +1 -0
- package/dist/lib/utils.d.ts +16 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +40 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/variables.d.ts +42 -0
- package/dist/lib/variables.d.ts.map +1 -0
- package/dist/lib/variables.js +141 -0
- package/dist/lib/variables.js.map +1 -0
- package/dist/lib/word.d.ts +80 -0
- package/dist/lib/word.d.ts.map +1 -0
- package/dist/lib/word.js +360 -0
- package/dist/lib/word.js.map +1 -0
- package/dist/lib/wordcomments.d.ts +51 -0
- package/dist/lib/wordcomments.d.ts.map +1 -0
- package/dist/lib/wordcomments.js +587 -0
- package/dist/lib/wordcomments.js.map +1 -0
- package/eslint.config.js +27 -0
- package/lib/annotations.ts +622 -0
- package/lib/apply-buildup-colors.py +88 -0
- package/lib/build.ts +1013 -0
- package/lib/{citations.js → citations.ts} +38 -27
- package/lib/commands/{build.js → build.ts} +80 -27
- package/lib/commands/{citations.js → citations.ts} +36 -18
- package/lib/commands/{comments.js → comments.ts} +187 -54
- package/lib/commands/{context.js → context.ts} +18 -8
- package/lib/commands/{core.js → core.ts} +34 -20
- package/lib/commands/{doi.js → doi.ts} +32 -16
- package/lib/commands/{history.js → history.ts} +25 -12
- package/lib/commands/{index.js → index.ts} +9 -5
- package/lib/commands/{init.js → init.ts} +20 -8
- package/lib/commands/{response.js → response.ts} +47 -20
- package/lib/commands/{sections.js → sections.ts} +273 -68
- package/lib/commands/{utilities.js → utilities.ts} +338 -158
- package/lib/{comment-realign.js → comment-realign.ts} +117 -45
- package/lib/config.ts +84 -0
- package/lib/{crossref.js → crossref.ts} +213 -138
- package/lib/dependencies.ts +106 -0
- package/lib/doi-cache.ts +115 -0
- package/lib/{doi.js → doi.ts} +115 -281
- package/lib/{equations.js → equations.ts} +60 -64
- package/lib/{errors.js → errors.ts} +56 -48
- package/lib/{format.js → format.ts} +137 -63
- package/lib/{git.js → git.ts} +66 -63
- package/lib/{grammar.js → grammar.ts} +45 -32
- package/lib/image-registry.ts +180 -0
- package/lib/import.ts +2060 -0
- package/lib/journals.ts +505 -0
- package/lib/{merge.js → merge.ts} +185 -135
- package/lib/{orcid.js → orcid.ts} +17 -22
- package/lib/{pdf-comments.js → pdf-comments.ts} +76 -18
- package/lib/{pdf-import.js → pdf-import.ts} +148 -70
- package/lib/{plugins.js → plugins.ts} +82 -39
- package/lib/postprocess.ts +188 -0
- package/lib/pptx-color-filter.lua +37 -0
- package/lib/pptx-template.ts +625 -0
- package/lib/pptx-themes/academic.pptx +0 -0
- package/lib/pptx-themes/corporate.pptx +0 -0
- package/lib/pptx-themes/dark.pptx +0 -0
- package/lib/pptx-themes/default.pptx +0 -0
- package/lib/pptx-themes/minimal.pptx +0 -0
- package/lib/pptx-themes/plant.pptx +0 -0
- package/lib/pptx-themes.ts +896 -0
- package/lib/protect-restore.ts +516 -0
- package/lib/rate-limiter.ts +94 -0
- package/lib/{response.js → response.ts} +36 -21
- package/lib/{review.js → review.ts} +53 -43
- package/lib/{schema.js → schema.ts} +70 -25
- package/lib/{sections.js → sections.ts} +71 -76
- package/lib/slides.ts +793 -0
- package/lib/{spelling.js → spelling.ts} +43 -59
- package/lib/{templates.js → templates.ts} +20 -17
- package/lib/themes.ts +742 -0
- package/lib/{trackchanges.js → trackchanges.ts} +52 -23
- package/lib/types.ts +509 -0
- package/lib/{undo.js → undo.ts} +75 -52
- package/lib/utils.ts +41 -0
- package/lib/{variables.js → variables.ts} +60 -54
- package/lib/word.ts +428 -0
- package/lib/{wordcomments.js → wordcomments.ts} +94 -40
- package/package.json +15 -5
- package/skill/REFERENCE.md +67 -0
- package/tsconfig.json +26 -0
- package/lib/annotations.js +0 -414
- package/lib/build.js +0 -639
- package/lib/config.js +0 -79
- package/lib/import.js +0 -1145
- package/lib/journals.js +0 -629
- package/lib/word.js +0 -225
- /package/lib/{scientific-words.js → scientific-words.ts} +0 -0
|
@@ -18,14 +18,70 @@ import {
|
|
|
18
18
|
convertHardcodedRefs,
|
|
19
19
|
inlineDiffPreview,
|
|
20
20
|
} from './context.js';
|
|
21
|
+
import type { Command } from 'commander';
|
|
22
|
+
import * as readline from 'readline';
|
|
23
|
+
|
|
24
|
+
interface DetectedSection {
|
|
25
|
+
header: string;
|
|
26
|
+
content: string;
|
|
27
|
+
file: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ImportStats {
|
|
31
|
+
insertions: number;
|
|
32
|
+
deletions: number;
|
|
33
|
+
substitutions: number;
|
|
34
|
+
comments: number;
|
|
35
|
+
total: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface BootstrapOptions {
|
|
39
|
+
output: string;
|
|
40
|
+
dryRun?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface ImportOptions {
|
|
44
|
+
output?: string;
|
|
45
|
+
author?: string;
|
|
46
|
+
dryRun?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface ExtractOptions {
|
|
50
|
+
output?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface SplitOptions {
|
|
54
|
+
config: string;
|
|
55
|
+
dir: string;
|
|
56
|
+
dryRun?: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface SyncOptions {
|
|
60
|
+
config: string;
|
|
61
|
+
dir: string;
|
|
62
|
+
crossref?: boolean;
|
|
63
|
+
diff?: boolean;
|
|
64
|
+
force?: boolean;
|
|
65
|
+
dryRun?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface MergeOptions {
|
|
69
|
+
base?: string;
|
|
70
|
+
output?: string;
|
|
71
|
+
names?: string;
|
|
72
|
+
strategy: string;
|
|
73
|
+
diffLevel: 'sentence' | 'word';
|
|
74
|
+
dryRun?: boolean;
|
|
75
|
+
sections?: boolean;
|
|
76
|
+
}
|
|
21
77
|
|
|
22
78
|
/**
|
|
23
79
|
* Detect sections from Word document text
|
|
24
80
|
* Looks for common academic paper section headers
|
|
25
81
|
*/
|
|
26
|
-
function detectSectionsFromWord(text) {
|
|
82
|
+
function detectSectionsFromWord(text: string): DetectedSection[] {
|
|
27
83
|
const lines = text.split('\n');
|
|
28
|
-
const sections = [];
|
|
84
|
+
const sections: DetectedSection[] = [];
|
|
29
85
|
|
|
30
86
|
const headerPatterns = [
|
|
31
87
|
/^(Abstract|Summary)$/i,
|
|
@@ -50,9 +106,9 @@ function detectSectionsFromWord(text) {
|
|
|
50
106
|
|
|
51
107
|
const numberedHeaderPattern = /^(\d+\.?\s+)(Abstract|Introduction|Background|Methods?|Materials|Results?|Discussion|Conclusions?|References|Acknowledgements?|Appendix)/i;
|
|
52
108
|
|
|
53
|
-
let currentSection = null;
|
|
54
|
-
let currentContent = [];
|
|
55
|
-
let preambleContent = [];
|
|
109
|
+
let currentSection: string | null = null;
|
|
110
|
+
let currentContent: string[] = [];
|
|
111
|
+
let preambleContent: string[] = [];
|
|
56
112
|
|
|
57
113
|
for (const line of lines) {
|
|
58
114
|
const trimmed = line.trim();
|
|
@@ -131,7 +187,7 @@ function detectSectionsFromWord(text) {
|
|
|
131
187
|
/**
|
|
132
188
|
* Convert a section header to a filename
|
|
133
189
|
*/
|
|
134
|
-
function headerToFilename(header) {
|
|
190
|
+
function headerToFilename(header: string): string {
|
|
135
191
|
return header
|
|
136
192
|
.toLowerCase()
|
|
137
193
|
.replace(/[^a-z0-9]+/g, '-')
|
|
@@ -142,7 +198,7 @@ function headerToFilename(header) {
|
|
|
142
198
|
/**
|
|
143
199
|
* Bootstrap a new project from a Word document
|
|
144
200
|
*/
|
|
145
|
-
async function bootstrapFromWord(docx, options) {
|
|
201
|
+
async function bootstrapFromWord(docx: string, options: BootstrapOptions): Promise<void> {
|
|
146
202
|
const outputDir = path.resolve(options.output);
|
|
147
203
|
|
|
148
204
|
console.log(chalk.cyan(`Bootstrapping project from ${path.basename(docx)}...\n`));
|
|
@@ -167,7 +223,7 @@ async function bootstrapFromWord(docx, options) {
|
|
|
167
223
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
168
224
|
}
|
|
169
225
|
|
|
170
|
-
const sectionFiles = [];
|
|
226
|
+
const sectionFiles: string[] = [];
|
|
171
227
|
for (const section of sections) {
|
|
172
228
|
const filePath = path.join(outputDir, section.file);
|
|
173
229
|
const content = `# ${section.header}\n\n${section.content.trim()}\n`;
|
|
@@ -231,17 +287,17 @@ async function bootstrapFromWord(docx, options) {
|
|
|
231
287
|
console.log(chalk.dim(' rev build # Build PDF and DOCX'));
|
|
232
288
|
}
|
|
233
289
|
} catch (err) {
|
|
234
|
-
|
|
235
|
-
|
|
290
|
+
const error = err as Error;
|
|
291
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
292
|
+
if (process.env.DEBUG) console.error(error.stack);
|
|
236
293
|
process.exit(1);
|
|
237
294
|
}
|
|
238
295
|
}
|
|
239
296
|
|
|
240
297
|
/**
|
|
241
298
|
* Register section commands with the program
|
|
242
|
-
* @param {import('commander').Command} program
|
|
243
299
|
*/
|
|
244
|
-
export function register(program) {
|
|
300
|
+
export function register(program: Command): void {
|
|
245
301
|
// ==========================================================================
|
|
246
302
|
// IMPORT command - Import from Word (bootstrap or diff mode)
|
|
247
303
|
// ==========================================================================
|
|
@@ -254,14 +310,14 @@ export function register(program) {
|
|
|
254
310
|
.option('-o, --output <dir>', 'Output directory for bootstrap mode', '.')
|
|
255
311
|
.option('-a, --author <name>', 'Author name for changes (diff mode)', 'Reviewer')
|
|
256
312
|
.option('--dry-run', 'Preview without saving')
|
|
257
|
-
.action(async (docx, original, options) => {
|
|
313
|
+
.action(async (docx: string, original: string | undefined, options: ImportOptions) => {
|
|
258
314
|
if (!fs.existsSync(docx)) {
|
|
259
315
|
console.error(chalk.red(`Error: Word file not found: ${docx}`));
|
|
260
316
|
process.exit(1);
|
|
261
317
|
}
|
|
262
318
|
|
|
263
319
|
if (!original) {
|
|
264
|
-
await bootstrapFromWord(docx, options);
|
|
320
|
+
await bootstrapFromWord(docx, options as BootstrapOptions);
|
|
265
321
|
return;
|
|
266
322
|
}
|
|
267
323
|
|
|
@@ -307,8 +363,9 @@ export function register(program) {
|
|
|
307
363
|
console.log(` 3. ${chalk.bold('rev build docx')} - Rebuild Word doc`);
|
|
308
364
|
|
|
309
365
|
} catch (err) {
|
|
310
|
-
|
|
311
|
-
|
|
366
|
+
const error = err as Error;
|
|
367
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
368
|
+
if (process.env.DEBUG) console.error(error.stack);
|
|
312
369
|
process.exit(1);
|
|
313
370
|
}
|
|
314
371
|
});
|
|
@@ -322,7 +379,7 @@ export function register(program) {
|
|
|
322
379
|
.description('Extract plain text from Word document (no diff)')
|
|
323
380
|
.argument('<docx>', 'Word document')
|
|
324
381
|
.option('-o, --output <file>', 'Output file (default: stdout)')
|
|
325
|
-
.action(async (docx, options) => {
|
|
382
|
+
.action(async (docx: string, options: ExtractOptions) => {
|
|
326
383
|
if (!fs.existsSync(docx)) {
|
|
327
384
|
console.error(chalk.red(`Error: File not found: ${docx}`));
|
|
328
385
|
process.exit(1);
|
|
@@ -339,7 +396,8 @@ export function register(program) {
|
|
|
339
396
|
process.stdout.write(result.value);
|
|
340
397
|
}
|
|
341
398
|
} catch (err) {
|
|
342
|
-
|
|
399
|
+
const error = err as Error;
|
|
400
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
343
401
|
process.exit(1);
|
|
344
402
|
}
|
|
345
403
|
});
|
|
@@ -355,7 +413,7 @@ export function register(program) {
|
|
|
355
413
|
.option('-c, --config <file>', 'Sections config file', 'sections.yaml')
|
|
356
414
|
.option('-d, --dir <directory>', 'Output directory for section files', '.')
|
|
357
415
|
.option('--dry-run', 'Preview without writing files')
|
|
358
|
-
.action((file, options) => {
|
|
416
|
+
.action((file: string, options: SplitOptions) => {
|
|
359
417
|
if (!fs.existsSync(file)) {
|
|
360
418
|
console.error(chalk.red(`File not found: ${file}`));
|
|
361
419
|
process.exit(1);
|
|
@@ -389,7 +447,7 @@ export function register(program) {
|
|
|
389
447
|
|
|
390
448
|
console.log(` ${chalk.bold(sectionFile)} (${lines} lines)`);
|
|
391
449
|
if (annotations.total > 0) {
|
|
392
|
-
const parts = [];
|
|
450
|
+
const parts: string[] = [];
|
|
393
451
|
if (annotations.inserts > 0) parts.push(chalk.green(`+${annotations.inserts}`));
|
|
394
452
|
if (annotations.deletes > 0) parts.push(chalk.red(`-${annotations.deletes}`));
|
|
395
453
|
if (annotations.substitutes > 0) parts.push(chalk.yellow(`~${annotations.substitutes}`));
|
|
@@ -426,7 +484,7 @@ export function register(program) {
|
|
|
426
484
|
.option('--no-diff', 'Skip showing diff preview')
|
|
427
485
|
.option('--force', 'Overwrite files without conflict warning')
|
|
428
486
|
.option('--dry-run', 'Preview without writing files')
|
|
429
|
-
.action(async (docx, sections, options) => {
|
|
487
|
+
.action(async (docx: string | undefined, sections: string[], options: SyncOptions) => {
|
|
430
488
|
// Auto-detect most recent docx or pdf if not provided
|
|
431
489
|
if (!docx) {
|
|
432
490
|
const docxFiles = findFiles('.docx');
|
|
@@ -439,7 +497,7 @@ export function register(program) {
|
|
|
439
497
|
}
|
|
440
498
|
const sorted = allFiles
|
|
441
499
|
.map(f => ({ name: f, mtime: fs.statSync(f).mtime }))
|
|
442
|
-
.sort((a, b) => b.mtime - a.mtime);
|
|
500
|
+
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
443
501
|
docx = sorted[0].name;
|
|
444
502
|
console.log(fmt.status('info', `Using most recent: ${docx}`));
|
|
445
503
|
console.log();
|
|
@@ -482,7 +540,7 @@ export function register(program) {
|
|
|
482
540
|
const config = loadConfig(configPath);
|
|
483
541
|
const mainSection = config.sections?.[0];
|
|
484
542
|
|
|
485
|
-
if (mainSection) {
|
|
543
|
+
if (mainSection && typeof mainSection === 'string') {
|
|
486
544
|
const mainPath = path.join(options.dir, mainSection);
|
|
487
545
|
if (fs.existsSync(mainPath)) {
|
|
488
546
|
console.log(chalk.dim(`Use 'rev pdf-comments ${docx} --append ${mainSection}' to add comments to markdown.`));
|
|
@@ -491,8 +549,9 @@ export function register(program) {
|
|
|
491
549
|
}
|
|
492
550
|
} catch (err) {
|
|
493
551
|
spin.stop();
|
|
494
|
-
|
|
495
|
-
|
|
552
|
+
const error = err as Error;
|
|
553
|
+
console.error(fmt.status('error', `Failed to extract PDF comments: ${error.message}`));
|
|
554
|
+
if (process.env.DEBUG) console.error(error.stack);
|
|
496
555
|
process.exit(1);
|
|
497
556
|
}
|
|
498
557
|
return;
|
|
@@ -509,8 +568,7 @@ export function register(program) {
|
|
|
509
568
|
|
|
510
569
|
try {
|
|
511
570
|
const config = loadConfig(configPath);
|
|
512
|
-
const
|
|
513
|
-
const { importFromWord, extractWordComments, extractCommentAnchors, insertCommentsIntoMarkdown } = await import('../import.js');
|
|
571
|
+
const { importFromWord, extractWordComments, extractCommentAnchors, insertCommentsIntoMarkdown, extractFromWord } = await import('../import.js');
|
|
514
572
|
|
|
515
573
|
let registry = null;
|
|
516
574
|
let totalRefConversions = 0;
|
|
@@ -519,10 +577,30 @@ export function register(program) {
|
|
|
519
577
|
}
|
|
520
578
|
|
|
521
579
|
const comments = await extractWordComments(docx);
|
|
522
|
-
const anchors = await extractCommentAnchors(docx);
|
|
580
|
+
const { anchors, fullDocText: xmlDocText } = await extractCommentAnchors(docx);
|
|
581
|
+
|
|
582
|
+
// Use pandoc for extraction to preserve markdown formatting (bold, tables, etc.)
|
|
583
|
+
// Mammoth only extracts plain text which loses all formatting
|
|
584
|
+
const wordExtraction = await extractFromWord(docx, { mediaDir: options.dir });
|
|
585
|
+
let wordText = wordExtraction.text;
|
|
586
|
+
const wordTables = wordExtraction.tables || [];
|
|
587
|
+
|
|
588
|
+
// Restore crossref on FULL text BEFORE splitting into sections
|
|
589
|
+
// This ensures duplicate labels from track changes are handled correctly
|
|
590
|
+
// (the same figure may appear multiple times in old/new versions)
|
|
591
|
+
const { restoreCrossrefFromWord, restoreImagesFromRegistry } = await import('../import.js');
|
|
592
|
+
const crossrefResult = restoreCrossrefFromWord(wordText, options.dir);
|
|
593
|
+
wordText = crossrefResult.text;
|
|
594
|
+
if (crossrefResult.restored > 0) {
|
|
595
|
+
console.log(`Restored ${crossrefResult.restored} crossref reference(s)`);
|
|
596
|
+
}
|
|
523
597
|
|
|
524
|
-
|
|
525
|
-
const
|
|
598
|
+
// Also restore images from registry using shared restoredLabels
|
|
599
|
+
const imageRestoreResult = restoreImagesFromRegistry(wordText, options.dir, crossrefResult.restoredLabels);
|
|
600
|
+
wordText = imageRestoreResult.text;
|
|
601
|
+
if (imageRestoreResult.restored > 0) {
|
|
602
|
+
console.log(`Restored ${imageRestoreResult.restored} image(s) from registry`);
|
|
603
|
+
}
|
|
526
604
|
|
|
527
605
|
let wordSections = extractSectionsFromText(wordText, config.sections);
|
|
528
606
|
|
|
@@ -554,7 +632,7 @@ export function register(program) {
|
|
|
554
632
|
|
|
555
633
|
// Conflict detection
|
|
556
634
|
if (!options.force && !options.dryRun) {
|
|
557
|
-
const conflicts = [];
|
|
635
|
+
const conflicts: Array<{ file: string; annotations: number }> = [];
|
|
558
636
|
for (const section of wordSections) {
|
|
559
637
|
const sectionPath = path.join(options.dir, section.file);
|
|
560
638
|
if (fs.existsSync(sectionPath)) {
|
|
@@ -576,16 +654,15 @@ export function register(program) {
|
|
|
576
654
|
}
|
|
577
655
|
console.log();
|
|
578
656
|
|
|
579
|
-
const rl =
|
|
580
|
-
const readline = rl.createInterface({
|
|
657
|
+
const rl = readline.createInterface({
|
|
581
658
|
input: process.stdin,
|
|
582
659
|
output: process.stdout,
|
|
583
660
|
});
|
|
584
661
|
|
|
585
|
-
const answer = await new Promise((resolve) =>
|
|
586
|
-
|
|
662
|
+
const answer = await new Promise<string>((resolve) =>
|
|
663
|
+
rl.question(chalk.cyan('Continue and overwrite? [y/N] '), resolve)
|
|
587
664
|
);
|
|
588
|
-
|
|
665
|
+
rl.close();
|
|
589
666
|
|
|
590
667
|
if (answer.toLowerCase() !== 'y') {
|
|
591
668
|
console.log(chalk.dim('Aborted. Use --force to skip this check.'));
|
|
@@ -595,9 +672,92 @@ export function register(program) {
|
|
|
595
672
|
}
|
|
596
673
|
}
|
|
597
674
|
|
|
598
|
-
const sectionResults
|
|
675
|
+
const sectionResults: Array<{
|
|
676
|
+
file: string;
|
|
677
|
+
header: string;
|
|
678
|
+
status: string;
|
|
679
|
+
stats?: ImportStats;
|
|
680
|
+
refs?: number;
|
|
681
|
+
}> = [];
|
|
599
682
|
let totalChanges = 0;
|
|
600
683
|
|
|
684
|
+
// Calculate section boundaries in the XML document text for comment filtering
|
|
685
|
+
// Comment positions (docPosition) are relative to xmlDocText, NOT wordText
|
|
686
|
+
// So we must find section headers in xmlDocText to get matching boundaries
|
|
687
|
+
const sectionBoundaries: Array<{ file: string; start: number; end: number }> = [];
|
|
688
|
+
const xmlLower = xmlDocText.toLowerCase();
|
|
689
|
+
|
|
690
|
+
// Standard section header keywords to search for in XML
|
|
691
|
+
// Map from file name pattern to search terms
|
|
692
|
+
const sectionKeywords: Record<string, string[]> = {
|
|
693
|
+
'abstract': ['abstract', 'summary'],
|
|
694
|
+
'introduction': ['introduction', 'background'],
|
|
695
|
+
'methods': ['methods', 'materials and methods', 'methodology'],
|
|
696
|
+
'results': ['results'],
|
|
697
|
+
'discussion': ['discussion'],
|
|
698
|
+
'conclusion': ['conclusion', 'conclusions'],
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
// Helper: find section header (skip labels like "Methods:" in structured abstracts)
|
|
702
|
+
// Real section headers are NOT followed by ":" immediately
|
|
703
|
+
function findSectionHeader(text: string, keyword: string, startFrom: number = 0): number {
|
|
704
|
+
const lower = text.toLowerCase();
|
|
705
|
+
let idx = startFrom;
|
|
706
|
+
while ((idx = lower.indexOf(keyword, idx)) !== -1) {
|
|
707
|
+
// Check what follows the keyword
|
|
708
|
+
const afterKeyword = text.slice(idx + keyword.length, idx + keyword.length + 5);
|
|
709
|
+
// Skip if followed by ":" (this is a label, not a section header)
|
|
710
|
+
// Real headers are followed by text content, a newline, or a subheading
|
|
711
|
+
if (!afterKeyword.startsWith(':') && !afterKeyword.startsWith(' :')) {
|
|
712
|
+
return idx;
|
|
713
|
+
}
|
|
714
|
+
idx++;
|
|
715
|
+
}
|
|
716
|
+
return -1;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
for (const section of wordSections) {
|
|
720
|
+
const fileBase = section.file.replace(/\.md$/i, '').toLowerCase();
|
|
721
|
+
|
|
722
|
+
// Get keywords for this section
|
|
723
|
+
const keywords = sectionKeywords[fileBase] || [fileBase];
|
|
724
|
+
|
|
725
|
+
// Find the first valid keyword that exists in XML (not a label)
|
|
726
|
+
let headerIdx = -1;
|
|
727
|
+
for (const kw of keywords) {
|
|
728
|
+
const idx = findSectionHeader(xmlDocText, kw, 0);
|
|
729
|
+
if (idx >= 0 && (headerIdx < 0 || idx < headerIdx)) {
|
|
730
|
+
headerIdx = idx;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if (headerIdx >= 0) {
|
|
735
|
+
// Find the next section's start to determine end boundary
|
|
736
|
+
let nextHeaderIdx = xmlDocText.length;
|
|
737
|
+
const sectionIdx = wordSections.indexOf(section);
|
|
738
|
+
if (sectionIdx < wordSections.length - 1) {
|
|
739
|
+
const nextFileBase = wordSections[sectionIdx + 1].file.replace(/\.md$/i, '').toLowerCase();
|
|
740
|
+
const nextKeywords = sectionKeywords[nextFileBase] || [nextFileBase];
|
|
741
|
+
for (const nkw of nextKeywords) {
|
|
742
|
+
const foundNext = findSectionHeader(xmlDocText, nkw, headerIdx + 10);
|
|
743
|
+
if (foundNext >= 0 && foundNext < nextHeaderIdx) {
|
|
744
|
+
nextHeaderIdx = foundNext;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
sectionBoundaries.push({
|
|
750
|
+
file: section.file,
|
|
751
|
+
start: headerIdx,
|
|
752
|
+
end: nextHeaderIdx
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// Document length is the XML text length (same coordinate system as docPosition)
|
|
759
|
+
const docLength = xmlDocText.length;
|
|
760
|
+
|
|
601
761
|
for (const section of wordSections) {
|
|
602
762
|
const sectionPath = path.join(options.dir, section.file);
|
|
603
763
|
|
|
@@ -606,7 +766,7 @@ export function register(program) {
|
|
|
606
766
|
file: section.file,
|
|
607
767
|
header: section.header,
|
|
608
768
|
status: 'skipped',
|
|
609
|
-
stats:
|
|
769
|
+
stats: undefined,
|
|
610
770
|
});
|
|
611
771
|
continue;
|
|
612
772
|
}
|
|
@@ -614,11 +774,12 @@ export function register(program) {
|
|
|
614
774
|
const result = await importFromWord(docx, sectionPath, {
|
|
615
775
|
sectionContent: section.content,
|
|
616
776
|
author: 'Reviewer',
|
|
777
|
+
wordTables: wordTables,
|
|
617
778
|
});
|
|
618
779
|
|
|
619
780
|
let { annotated, stats } = result;
|
|
620
781
|
|
|
621
|
-
let refConversions = [];
|
|
782
|
+
let refConversions: Array<{ from: string; to: string }> = [];
|
|
622
783
|
if (registry && options.crossref !== false) {
|
|
623
784
|
const crossrefResult = convertHardcodedRefs(annotated, registry);
|
|
624
785
|
annotated = crossrefResult.converted;
|
|
@@ -628,10 +789,54 @@ export function register(program) {
|
|
|
628
789
|
|
|
629
790
|
let commentsInserted = 0;
|
|
630
791
|
if (comments.length > 0 && anchors.size > 0) {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
792
|
+
// Filter comments to only those that belong to this section
|
|
793
|
+
// Use exact position matching: docPosition is in xmlDocText coordinates,
|
|
794
|
+
// and sectionBoundaries are also in xmlDocText coordinates (same source!)
|
|
795
|
+
const boundary = sectionBoundaries.find(b => b.file === section.file);
|
|
796
|
+
const isFirstSection = wordSections.indexOf(section) === 0;
|
|
797
|
+
const firstBoundaryStart = sectionBoundaries.length > 0 ? Math.min(...sectionBoundaries.map(b => b.start)) : 0;
|
|
798
|
+
|
|
799
|
+
const sectionComments = comments.filter((c: any) => {
|
|
800
|
+
const anchorData = anchors.get(c.id);
|
|
801
|
+
if (!anchorData) return false;
|
|
802
|
+
|
|
803
|
+
// Use exact position - no scaling needed since both are in xmlDocText coordinates
|
|
804
|
+
if (anchorData.docPosition !== undefined && boundary) {
|
|
805
|
+
// Include comments within section boundaries
|
|
806
|
+
if (anchorData.docPosition >= boundary.start && anchorData.docPosition < boundary.end) {
|
|
807
|
+
return true;
|
|
808
|
+
}
|
|
809
|
+
// Also include "outside" comments (before first section) in the first section file
|
|
810
|
+
if (isFirstSection && anchorData.docPosition < firstBoundaryStart) {
|
|
811
|
+
return true;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
return false;
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
if (process.env.DEBUG) {
|
|
819
|
+
console.log(`[DEBUG] ${section.file}: ${sectionComments.length} comments to place (boundary: ${boundary?.start}-${boundary?.end})`);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
if (sectionComments.length > 0) {
|
|
823
|
+
// Use a more robust pattern that handles < in comment text
|
|
824
|
+
const commentPattern = /\{>>.*?<<\}/gs;
|
|
825
|
+
const beforeCount = (annotated.match(commentPattern) || []).length;
|
|
826
|
+
annotated = insertCommentsIntoMarkdown(annotated, sectionComments, anchors, {
|
|
827
|
+
quiet: !process.env.DEBUG,
|
|
828
|
+
sectionBoundary: boundary // Pass section boundary for position-based insertion
|
|
829
|
+
});
|
|
830
|
+
const afterCount = (annotated.match(commentPattern) || []).length;
|
|
831
|
+
commentsInserted = afterCount - beforeCount;
|
|
832
|
+
|
|
833
|
+
if (process.env.DEBUG) {
|
|
834
|
+
console.log(`[DEBUG] ${section.file}: inserted ${commentsInserted} of ${sectionComments.length} comments`);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
if (commentsInserted > 0) {
|
|
838
|
+
stats.comments = (stats.comments || 0) + commentsInserted;
|
|
839
|
+
}
|
|
635
840
|
}
|
|
636
841
|
}
|
|
637
842
|
|
|
@@ -645,7 +850,7 @@ export function register(program) {
|
|
|
645
850
|
refs: refConversions.length,
|
|
646
851
|
});
|
|
647
852
|
|
|
648
|
-
if (!options.dryRun
|
|
853
|
+
if (!options.dryRun) {
|
|
649
854
|
fs.writeFileSync(sectionPath, annotated, 'utf-8');
|
|
650
855
|
}
|
|
651
856
|
}
|
|
@@ -662,7 +867,7 @@ export function register(program) {
|
|
|
662
867
|
'',
|
|
663
868
|
];
|
|
664
869
|
}
|
|
665
|
-
const s = r.stats
|
|
870
|
+
const s = r.stats!;
|
|
666
871
|
return [
|
|
667
872
|
chalk.bold(r.file),
|
|
668
873
|
r.header.length > 25 ? r.header.slice(0, 22) + '...' : r.header,
|
|
@@ -670,7 +875,7 @@ export function register(program) {
|
|
|
670
875
|
s.deletions > 0 ? chalk.red(`-${s.deletions}`) : chalk.dim('-'),
|
|
671
876
|
s.substitutions > 0 ? chalk.yellow(`~${s.substitutions}`) : chalk.dim('-'),
|
|
672
877
|
s.comments > 0 ? chalk.blue(`#${s.comments}`) : chalk.dim('-'),
|
|
673
|
-
r.refs > 0 ? chalk.magenta(`@${r.refs}`) : chalk.dim('-'),
|
|
878
|
+
r.refs! > 0 ? chalk.magenta(`@${r.refs}`) : chalk.dim('-'),
|
|
674
879
|
];
|
|
675
880
|
});
|
|
676
881
|
|
|
@@ -703,7 +908,7 @@ export function register(program) {
|
|
|
703
908
|
if (options.dryRun) {
|
|
704
909
|
console.log(fmt.box(chalk.yellow('Dry run - no files written'), { padding: 0 }));
|
|
705
910
|
} else if (totalChanges > 0 || totalRefConversions > 0 || comments.length > 0) {
|
|
706
|
-
const summaryLines = [];
|
|
911
|
+
const summaryLines: string[] = [];
|
|
707
912
|
summaryLines.push(`${chalk.bold(wordSections.length)} sections processed`);
|
|
708
913
|
if (totalChanges > 0) summaryLines.push(`${chalk.bold(totalChanges)} annotations imported`);
|
|
709
914
|
if (comments.length > 0) summaryLines.push(`${chalk.bold(comments.length)} comments placed`);
|
|
@@ -720,8 +925,9 @@ export function register(program) {
|
|
|
720
925
|
}
|
|
721
926
|
} catch (err) {
|
|
722
927
|
spin.stop();
|
|
723
|
-
|
|
724
|
-
|
|
928
|
+
const error = err as Error;
|
|
929
|
+
console.error(fmt.status('error', error.message));
|
|
930
|
+
if (process.env.DEBUG) console.error(error.stack);
|
|
725
931
|
process.exit(1);
|
|
726
932
|
}
|
|
727
933
|
});
|
|
@@ -741,7 +947,7 @@ export function register(program) {
|
|
|
741
947
|
.option('--diff-level <level>', 'Diff granularity: sentence or word (default: sentence)', 'sentence')
|
|
742
948
|
.option('--dry-run', 'Show conflicts without writing')
|
|
743
949
|
.option('--sections', 'Split merged output back to section files')
|
|
744
|
-
.action(async (docxFiles, options) => {
|
|
950
|
+
.action(async (docxFiles: string[], options: MergeOptions) => {
|
|
745
951
|
const {
|
|
746
952
|
mergeThreeWay,
|
|
747
953
|
formatConflict,
|
|
@@ -766,7 +972,7 @@ export function register(program) {
|
|
|
766
972
|
if (!basePath) {
|
|
767
973
|
// Try to use .rev/base.docx
|
|
768
974
|
const projectDir = process.cwd();
|
|
769
|
-
basePath = getBaseDocument(projectDir);
|
|
975
|
+
basePath = getBaseDocument(projectDir) ?? undefined;
|
|
770
976
|
|
|
771
977
|
if (basePath) {
|
|
772
978
|
baseSource = 'auto (.rev/base.docx)';
|
|
@@ -862,16 +1068,15 @@ export function register(program) {
|
|
|
862
1068
|
console.log(formatConflict(conflict, baseText));
|
|
863
1069
|
console.log();
|
|
864
1070
|
|
|
865
|
-
const rl =
|
|
866
|
-
const readline = rl.createInterface({
|
|
1071
|
+
const rl = readline.createInterface({
|
|
867
1072
|
input: process.stdin,
|
|
868
1073
|
output: process.stdout,
|
|
869
1074
|
});
|
|
870
1075
|
|
|
871
|
-
const answer = await new Promise((resolve) =>
|
|
872
|
-
|
|
1076
|
+
const answer = await new Promise<string>((resolve) =>
|
|
1077
|
+
rl.question(chalk.cyan(` Choose (1-${conflict.changes.length}, s=skip): `), resolve)
|
|
873
1078
|
);
|
|
874
|
-
|
|
1079
|
+
rl.close();
|
|
875
1080
|
|
|
876
1081
|
if (answer.toLowerCase() !== 's' && !isNaN(parseInt(answer))) {
|
|
877
1082
|
const choice = parseInt(answer) - 1;
|
|
@@ -923,8 +1128,9 @@ export function register(program) {
|
|
|
923
1128
|
}
|
|
924
1129
|
} catch (err) {
|
|
925
1130
|
spin.stop();
|
|
926
|
-
|
|
927
|
-
|
|
1131
|
+
const error = err as Error;
|
|
1132
|
+
console.error(fmt.status('error', error.message));
|
|
1133
|
+
if (process.env.DEBUG) console.error(error.stack);
|
|
928
1134
|
process.exit(1);
|
|
929
1135
|
}
|
|
930
1136
|
});
|
|
@@ -946,7 +1152,7 @@ export function register(program) {
|
|
|
946
1152
|
return;
|
|
947
1153
|
}
|
|
948
1154
|
|
|
949
|
-
const unresolved = data.conflicts.filter(c => c.resolved === null);
|
|
1155
|
+
const unresolved = data.conflicts.filter((c: any) => c.resolved === null);
|
|
950
1156
|
|
|
951
1157
|
if (unresolved.length === 0) {
|
|
952
1158
|
console.log(fmt.status('success', 'All conflicts resolved!'));
|
|
@@ -963,7 +1169,7 @@ export function register(program) {
|
|
|
963
1169
|
console.log(chalk.bold(`Conflict ${conflict.id}:`));
|
|
964
1170
|
// Show abbreviated info
|
|
965
1171
|
console.log(chalk.dim(` Original: "${conflict.original.slice(0, 50)}${conflict.original.length > 50 ? '...' : ''}"`));
|
|
966
|
-
console.log(chalk.dim(` Options: ${conflict.changes.map(c => c.reviewer).join(', ')}`));
|
|
1172
|
+
console.log(chalk.dim(` Options: ${conflict.changes.map((c: any) => c.reviewer).join(', ')}`));
|
|
967
1173
|
console.log();
|
|
968
1174
|
}
|
|
969
1175
|
|
|
@@ -980,7 +1186,7 @@ export function register(program) {
|
|
|
980
1186
|
.description('Resolve merge conflicts interactively')
|
|
981
1187
|
.option('--theirs', 'Accept all changes from last reviewer')
|
|
982
1188
|
.option('--ours', 'Accept all changes from first reviewer')
|
|
983
|
-
.action(async (options) => {
|
|
1189
|
+
.action(async (options: { theirs?: boolean; ours?: boolean }) => {
|
|
984
1190
|
const { loadConflicts, saveConflicts, clearConflicts, resolveConflict, formatConflict } = await import('../merge.js');
|
|
985
1191
|
const projectDir = process.cwd();
|
|
986
1192
|
const data = loadConflicts(projectDir);
|
|
@@ -990,7 +1196,7 @@ export function register(program) {
|
|
|
990
1196
|
return;
|
|
991
1197
|
}
|
|
992
1198
|
|
|
993
|
-
const unresolved = data.conflicts.filter(c => c.resolved === null);
|
|
1199
|
+
const unresolved = data.conflicts.filter((c: any) => c.resolved === null);
|
|
994
1200
|
|
|
995
1201
|
if (unresolved.length === 0) {
|
|
996
1202
|
console.log(fmt.status('success', 'All conflicts already resolved!'));
|
|
@@ -1036,16 +1242,15 @@ export function register(program) {
|
|
|
1036
1242
|
console.log(formatConflict(conflict, baseText));
|
|
1037
1243
|
console.log();
|
|
1038
1244
|
|
|
1039
|
-
const rl =
|
|
1040
|
-
const readline = rl.createInterface({
|
|
1245
|
+
const rl = readline.createInterface({
|
|
1041
1246
|
input: process.stdin,
|
|
1042
1247
|
output: process.stdout,
|
|
1043
1248
|
});
|
|
1044
1249
|
|
|
1045
|
-
const answer = await new Promise((resolve) =>
|
|
1046
|
-
|
|
1250
|
+
const answer = await new Promise<string>((resolve) =>
|
|
1251
|
+
rl.question(chalk.cyan(` Choose (1-${conflict.changes.length}, s=skip, q=quit): `), resolve)
|
|
1047
1252
|
);
|
|
1048
|
-
|
|
1253
|
+
rl.close();
|
|
1049
1254
|
|
|
1050
1255
|
if (answer.toLowerCase() === 'q') {
|
|
1051
1256
|
console.log(chalk.dim('\n Saving progress...'));
|
|
@@ -1065,7 +1270,7 @@ export function register(program) {
|
|
|
1065
1270
|
|
|
1066
1271
|
saveConflicts(projectDir, data.conflicts, data.base);
|
|
1067
1272
|
|
|
1068
|
-
const remaining = data.conflicts.filter(c => c.resolved === null).length;
|
|
1273
|
+
const remaining = data.conflicts.filter((c: any) => c.resolved === null).length;
|
|
1069
1274
|
if (remaining === 0) {
|
|
1070
1275
|
console.log(fmt.status('success', '\nAll conflicts resolved!'));
|
|
1071
1276
|
clearConflicts(projectDir);
|