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/{tui.js → tui.ts}
RENAMED
|
@@ -5,51 +5,109 @@
|
|
|
5
5
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import * as readline from 'readline';
|
|
8
|
+
import type { Annotation } from './types.js';
|
|
9
|
+
import type { DocumentSession } from './undo.js';
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Interfaces
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
interface BoxOptions {
|
|
16
|
+
title?: string;
|
|
17
|
+
content?: string[];
|
|
18
|
+
width?: number;
|
|
19
|
+
borderColor?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface TuiReviewOptions {
|
|
23
|
+
author?: string;
|
|
24
|
+
addReply?: (text: string, comment: Annotation, author: string, reply: string) => string;
|
|
25
|
+
setStatus?: (text: string, comment: Annotation, resolved: boolean) => string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface TuiReviewResult {
|
|
29
|
+
text: string;
|
|
30
|
+
resolved: number;
|
|
31
|
+
replied: number;
|
|
32
|
+
skipped: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// Utility Functions
|
|
37
|
+
// =============================================================================
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Strip ANSI codes for length calculation
|
|
41
|
+
*/
|
|
42
|
+
export function stripAnsi(str: string): string {
|
|
43
|
+
return str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Word wrap text to fit within width
|
|
48
|
+
*/
|
|
49
|
+
function wordWrap(text: string, width: number): string[] {
|
|
50
|
+
const words = text.split(/\s+/);
|
|
51
|
+
const lines: string[] = [];
|
|
52
|
+
let currentLine = '';
|
|
53
|
+
|
|
54
|
+
for (const word of words) {
|
|
55
|
+
if (currentLine.length + word.length + 1 <= width) {
|
|
56
|
+
currentLine += (currentLine ? ' ' : '') + word;
|
|
57
|
+
} else {
|
|
58
|
+
if (currentLine) lines.push(currentLine);
|
|
59
|
+
currentLine = word;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (currentLine) lines.push(currentLine);
|
|
64
|
+
return lines;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// =============================================================================
|
|
68
|
+
// Screen Functions
|
|
69
|
+
// =============================================================================
|
|
8
70
|
|
|
9
71
|
/**
|
|
10
72
|
* Clear the terminal screen
|
|
11
73
|
*/
|
|
12
|
-
export function clearScreen() {
|
|
74
|
+
export function clearScreen(): void {
|
|
13
75
|
process.stdout.write('\x1B[2J\x1B[H');
|
|
14
76
|
}
|
|
15
77
|
|
|
16
78
|
/**
|
|
17
79
|
* Move cursor to position
|
|
18
|
-
* @param {number} row
|
|
19
|
-
* @param {number} col
|
|
20
80
|
*/
|
|
21
|
-
export function moveCursor(row, col) {
|
|
81
|
+
export function moveCursor(row: number, col: number): void {
|
|
22
82
|
process.stdout.write(`\x1B[${row};${col}H`);
|
|
23
83
|
}
|
|
24
84
|
|
|
25
85
|
/**
|
|
26
86
|
* Get terminal dimensions
|
|
27
|
-
* @returns {{rows: number, cols: number}}
|
|
28
87
|
*/
|
|
29
|
-
export function getTerminalSize() {
|
|
88
|
+
export function getTerminalSize(): { rows: number; cols: number } {
|
|
30
89
|
return {
|
|
31
90
|
rows: process.stdout.rows || 24,
|
|
32
91
|
cols: process.stdout.columns || 80,
|
|
33
92
|
};
|
|
34
93
|
}
|
|
35
94
|
|
|
95
|
+
// =============================================================================
|
|
96
|
+
// Drawing Functions
|
|
97
|
+
// =============================================================================
|
|
98
|
+
|
|
36
99
|
/**
|
|
37
100
|
* Draw a box with content
|
|
38
|
-
* @param {object} options
|
|
39
|
-
* @param {string} options.title
|
|
40
|
-
* @param {string[]} options.content
|
|
41
|
-
* @param {number} options.width
|
|
42
|
-
* @param {string} options.borderColor
|
|
43
|
-
* @returns {string[]}
|
|
44
101
|
*/
|
|
45
|
-
export function drawBox({ title = '', content = [], width = 60, borderColor = 'dim' }) {
|
|
102
|
+
export function drawBox({ title = '', content = [], width = 60, borderColor = 'dim' }: BoxOptions = {}): string[] {
|
|
46
103
|
const border = {
|
|
47
|
-
tl: '
|
|
48
|
-
h: '
|
|
104
|
+
tl: '\u256D', tr: '\u256E', bl: '\u2570', br: '\u256F',
|
|
105
|
+
h: '\u2500', v: '\u2502',
|
|
49
106
|
};
|
|
50
107
|
|
|
51
|
-
|
|
52
|
-
const
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
|
+
const colorFn = ((chalk as any)[borderColor] as ((str: string) => string)) || chalk.dim;
|
|
110
|
+
const lines: string[] = [];
|
|
53
111
|
|
|
54
112
|
// Top border with title
|
|
55
113
|
if (title) {
|
|
@@ -81,11 +139,8 @@ export function drawBox({ title = '', content = [], width = 60, borderColor = 'd
|
|
|
81
139
|
|
|
82
140
|
/**
|
|
83
141
|
* Draw a status bar at the bottom of the screen
|
|
84
|
-
* @param {string} left - Left-aligned text
|
|
85
|
-
* @param {string} right - Right-aligned text
|
|
86
|
-
* @returns {string}
|
|
87
142
|
*/
|
|
88
|
-
export function statusBar(left, right = '') {
|
|
143
|
+
export function statusBar(left: string, right: string = ''): string {
|
|
89
144
|
const { cols } = getTerminalSize();
|
|
90
145
|
const leftLen = stripAnsi(left).length;
|
|
91
146
|
const rightLen = stripAnsi(right).length;
|
|
@@ -96,33 +151,24 @@ export function statusBar(left, right = '') {
|
|
|
96
151
|
|
|
97
152
|
/**
|
|
98
153
|
* Draw a progress indicator
|
|
99
|
-
* @param {number} current
|
|
100
|
-
* @param {number} total
|
|
101
|
-
* @param {number} width
|
|
102
|
-
* @returns {string}
|
|
103
154
|
*/
|
|
104
|
-
export function progressIndicator(current, total, width = 20) {
|
|
155
|
+
export function progressIndicator(current: number, total: number, width: number = 20): string {
|
|
105
156
|
const ratio = current / total;
|
|
106
157
|
const filled = Math.round(ratio * width);
|
|
107
158
|
const empty = width - filled;
|
|
108
159
|
|
|
109
|
-
const bar = chalk.cyan('
|
|
160
|
+
const bar = chalk.cyan('\u2588'.repeat(filled)) + chalk.dim('\u2591'.repeat(empty));
|
|
110
161
|
return `${bar} ${current}/${total}`;
|
|
111
162
|
}
|
|
112
163
|
|
|
113
164
|
/**
|
|
114
165
|
* Format a comment for TUI display
|
|
115
|
-
* @param {object} comment
|
|
116
|
-
* @param {number} index
|
|
117
|
-
* @param {number} total
|
|
118
|
-
* @param {number} width
|
|
119
|
-
* @returns {string[]}
|
|
120
166
|
*/
|
|
121
|
-
export function formatCommentCard(comment, index, total, width = 70) {
|
|
122
|
-
const statusIcon = comment.resolved ? chalk.green('
|
|
167
|
+
export function formatCommentCard(comment: Annotation, index: number, total: number, width: number = 70): string[] {
|
|
168
|
+
const statusIcon = comment.resolved ? chalk.green('\u2713') : chalk.yellow('\u25CB');
|
|
123
169
|
const author = comment.author || 'Anonymous';
|
|
124
170
|
|
|
125
|
-
const content = [];
|
|
171
|
+
const content: string[] = [];
|
|
126
172
|
|
|
127
173
|
// Author and status line
|
|
128
174
|
content.push(chalk.blue(author) + ' ' + statusIcon);
|
|
@@ -155,56 +201,76 @@ export function formatCommentCard(comment, index, total, width = 70) {
|
|
|
155
201
|
|
|
156
202
|
/**
|
|
157
203
|
* Draw the action menu
|
|
158
|
-
* @param {string[]} options - Array of [key, description] tuples
|
|
159
|
-
* @returns {string}
|
|
160
204
|
*/
|
|
161
|
-
export function actionMenu(options) {
|
|
205
|
+
export function actionMenu(options: [string, string][]): string {
|
|
162
206
|
return options
|
|
163
207
|
.map(([key, desc]) => chalk.bold(`[${key}]`) + chalk.dim(desc))
|
|
164
208
|
.join(' ');
|
|
165
209
|
}
|
|
166
210
|
|
|
211
|
+
// =============================================================================
|
|
212
|
+
// Interactive TUI Review
|
|
213
|
+
// =============================================================================
|
|
214
|
+
|
|
167
215
|
/**
|
|
168
|
-
*
|
|
169
|
-
* @param {string} text
|
|
170
|
-
* @param {number} width
|
|
171
|
-
* @returns {string[]}
|
|
216
|
+
* Prompt for a single keypress
|
|
172
217
|
*/
|
|
173
|
-
function
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
218
|
+
function promptKey(validKeys: string[]): Promise<string> {
|
|
219
|
+
return new Promise((resolve) => {
|
|
220
|
+
const rl = readline.createInterface({
|
|
221
|
+
input: process.stdin,
|
|
222
|
+
output: process.stdout,
|
|
223
|
+
});
|
|
177
224
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
currentLine += (currentLine ? ' ' : '') + word;
|
|
181
|
-
} else {
|
|
182
|
-
if (currentLine) lines.push(currentLine);
|
|
183
|
-
currentLine = word;
|
|
225
|
+
if (process.stdin.isTTY) {
|
|
226
|
+
process.stdin.setRawMode(true);
|
|
184
227
|
}
|
|
185
|
-
|
|
228
|
+
process.stdin.resume();
|
|
186
229
|
|
|
187
|
-
|
|
188
|
-
|
|
230
|
+
process.stdin.once('data', (key: Buffer) => {
|
|
231
|
+
const char = key.toString();
|
|
232
|
+
|
|
233
|
+
if (process.stdin.isTTY) {
|
|
234
|
+
process.stdin.setRawMode(false);
|
|
235
|
+
}
|
|
236
|
+
rl.close();
|
|
237
|
+
|
|
238
|
+
if (char === '\u0003') {
|
|
239
|
+
// Ctrl+C
|
|
240
|
+
clearScreen();
|
|
241
|
+
process.exit(0);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (validKeys.includes(char.toLowerCase()) || validKeys.includes(char)) {
|
|
245
|
+
resolve(char);
|
|
246
|
+
} else {
|
|
247
|
+
resolve(promptKey(validKeys));
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
});
|
|
189
251
|
}
|
|
190
252
|
|
|
191
253
|
/**
|
|
192
|
-
*
|
|
193
|
-
* @param {string} str
|
|
194
|
-
* @returns {string}
|
|
254
|
+
* Prompt for text input
|
|
195
255
|
*/
|
|
196
|
-
function
|
|
197
|
-
return
|
|
256
|
+
function promptText(prompt: string): Promise<string> {
|
|
257
|
+
return new Promise((resolve) => {
|
|
258
|
+
const rl = readline.createInterface({
|
|
259
|
+
input: process.stdin,
|
|
260
|
+
output: process.stdout,
|
|
261
|
+
});
|
|
262
|
+
rl.question(prompt, (answer: string) => {
|
|
263
|
+
rl.close();
|
|
264
|
+
resolve(answer);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
198
267
|
}
|
|
199
268
|
|
|
200
269
|
/**
|
|
201
270
|
* Run TUI comment review session
|
|
202
|
-
* @param {string} text
|
|
203
|
-
* @param {object} options
|
|
204
|
-
* @returns {Promise<{text: string, resolved: number, replied: number, skipped: number}>}
|
|
205
271
|
*/
|
|
206
|
-
export async function tuiCommentReview(text, options = {}) {
|
|
207
|
-
const { getComments
|
|
272
|
+
export async function tuiCommentReview(text: string, options: TuiReviewOptions = {}): Promise<TuiReviewResult> {
|
|
273
|
+
const { getComments } = await import('./annotations.js');
|
|
208
274
|
const { createDocumentSession } = await import('./undo.js');
|
|
209
275
|
const { author = 'Author', addReply, setStatus } = options;
|
|
210
276
|
|
|
@@ -216,16 +282,15 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
216
282
|
}
|
|
217
283
|
|
|
218
284
|
// Create session with undo support
|
|
219
|
-
const session = createDocumentSession(text);
|
|
285
|
+
const session: DocumentSession = createDocumentSession(text);
|
|
220
286
|
|
|
221
287
|
let currentIndex = 0;
|
|
222
288
|
let resolved = 0;
|
|
223
289
|
let replied = 0;
|
|
224
290
|
let skipped = 0;
|
|
225
|
-
let message = '';
|
|
291
|
+
let message = '';
|
|
226
292
|
|
|
227
|
-
|
|
228
|
-
const render = () => {
|
|
293
|
+
const render = (): void => {
|
|
229
294
|
clearScreen();
|
|
230
295
|
|
|
231
296
|
const { cols } = getTerminalSize();
|
|
@@ -257,7 +322,7 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
257
322
|
}
|
|
258
323
|
|
|
259
324
|
// Action menu with undo
|
|
260
|
-
const menuItems = [
|
|
325
|
+
const menuItems: [string, string][] = [
|
|
261
326
|
['r', 'eply'],
|
|
262
327
|
['m', 'ark resolved'],
|
|
263
328
|
['s', 'kip'],
|
|
@@ -272,60 +337,9 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
272
337
|
menuItems.push(['A', 'll resolve'], ['q', 'uit']);
|
|
273
338
|
|
|
274
339
|
console.log(' ' + actionMenu(menuItems));
|
|
275
|
-
|
|
276
340
|
console.log();
|
|
277
341
|
};
|
|
278
342
|
|
|
279
|
-
// Prompt for keypress
|
|
280
|
-
const promptKey = (validKeys) => {
|
|
281
|
-
return new Promise((resolve) => {
|
|
282
|
-
const rl = readline.createInterface({
|
|
283
|
-
input: process.stdin,
|
|
284
|
-
output: process.stdout,
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
if (process.stdin.isTTY) {
|
|
288
|
-
process.stdin.setRawMode(true);
|
|
289
|
-
}
|
|
290
|
-
process.stdin.resume();
|
|
291
|
-
|
|
292
|
-
process.stdin.once('data', (key) => {
|
|
293
|
-
const char = key.toString();
|
|
294
|
-
|
|
295
|
-
if (process.stdin.isTTY) {
|
|
296
|
-
process.stdin.setRawMode(false);
|
|
297
|
-
}
|
|
298
|
-
rl.close();
|
|
299
|
-
|
|
300
|
-
if (char === '\u0003') {
|
|
301
|
-
// Ctrl+C
|
|
302
|
-
clearScreen();
|
|
303
|
-
process.exit(0);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (validKeys.includes(char.toLowerCase()) || validKeys.includes(char)) {
|
|
307
|
-
resolve(char);
|
|
308
|
-
} else {
|
|
309
|
-
resolve(promptKey(validKeys));
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
// Prompt for text input
|
|
316
|
-
const promptText = (prompt) => {
|
|
317
|
-
return new Promise((resolve) => {
|
|
318
|
-
const rl = readline.createInterface({
|
|
319
|
-
input: process.stdin,
|
|
320
|
-
output: process.stdout,
|
|
321
|
-
});
|
|
322
|
-
rl.question(prompt, (answer) => {
|
|
323
|
-
rl.close();
|
|
324
|
-
resolve(answer);
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
};
|
|
328
|
-
|
|
329
343
|
// Main loop
|
|
330
344
|
while (currentIndex < comments.length) {
|
|
331
345
|
render();
|
|
@@ -344,12 +358,10 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
344
358
|
return { text: session.getText(), resolved, replied, skipped: comments.length - currentIndex };
|
|
345
359
|
|
|
346
360
|
case 'u':
|
|
347
|
-
// Undo last change
|
|
348
361
|
if (session.canUndo()) {
|
|
349
362
|
const undone = session.undo();
|
|
350
363
|
if (undone) {
|
|
351
364
|
message = chalk.yellow(`Undone: ${undone.description}`);
|
|
352
|
-
// Adjust counters (approximate)
|
|
353
365
|
if (undone.description.includes('Resolved')) resolved = Math.max(0, resolved - 1);
|
|
354
366
|
if (undone.description.includes('Reply')) replied = Math.max(0, replied - 1);
|
|
355
367
|
if (currentIndex > 0) currentIndex--;
|
|
@@ -357,8 +369,7 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
357
369
|
}
|
|
358
370
|
break;
|
|
359
371
|
|
|
360
|
-
case 'A':
|
|
361
|
-
// Resolve all remaining
|
|
372
|
+
case 'A': {
|
|
362
373
|
let newText = session.getText();
|
|
363
374
|
for (let j = currentIndex; j < comments.length; j++) {
|
|
364
375
|
if (setStatus) {
|
|
@@ -369,6 +380,7 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
369
380
|
resolved += comments.length - currentIndex;
|
|
370
381
|
currentIndex = comments.length;
|
|
371
382
|
break;
|
|
383
|
+
}
|
|
372
384
|
|
|
373
385
|
case 'm':
|
|
374
386
|
if (setStatus) {
|
|
@@ -379,7 +391,7 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
379
391
|
currentIndex++;
|
|
380
392
|
break;
|
|
381
393
|
|
|
382
|
-
case 'r':
|
|
394
|
+
case 'r': {
|
|
383
395
|
console.log();
|
|
384
396
|
const replyText = await promptText(chalk.cyan(' Reply: '));
|
|
385
397
|
if (replyText.trim() && addReply) {
|
|
@@ -389,6 +401,7 @@ export async function tuiCommentReview(text, options = {}) {
|
|
|
389
401
|
}
|
|
390
402
|
currentIndex++;
|
|
391
403
|
break;
|
|
404
|
+
}
|
|
392
405
|
|
|
393
406
|
case 's':
|
|
394
407
|
skipped++;
|
package/lib/undo.ts
CHANGED
|
@@ -16,7 +16,7 @@ interface HistoryEntry {
|
|
|
16
16
|
index: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
interface StackInfo {
|
|
19
|
+
export interface StackInfo {
|
|
20
20
|
position: number;
|
|
21
21
|
size: number;
|
|
22
22
|
undoSteps: number;
|
|
@@ -32,16 +32,15 @@ interface UndoStack {
|
|
|
32
32
|
canRedo(): boolean;
|
|
33
33
|
info(): StackInfo;
|
|
34
34
|
history(limit?: number): HistoryEntry[];
|
|
35
|
-
clear(): void;
|
|
36
35
|
getStack(): StackEntry[];
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
interface DocumentChange {
|
|
38
|
+
export interface DocumentChange {
|
|
40
39
|
text: string;
|
|
41
40
|
description: string;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
interface DocumentSession {
|
|
43
|
+
export interface DocumentSession {
|
|
45
44
|
getText(): string;
|
|
46
45
|
applyChange(newText: string, description: string): void;
|
|
47
46
|
undo(): DocumentChange | null;
|
|
@@ -158,14 +157,6 @@ export function createUndoStack(maxSize: number = 50): UndoStack {
|
|
|
158
157
|
}));
|
|
159
158
|
},
|
|
160
159
|
|
|
161
|
-
/**
|
|
162
|
-
* Clear the stack
|
|
163
|
-
*/
|
|
164
|
-
clear(): void {
|
|
165
|
-
stack.length = 0;
|
|
166
|
-
position = -1;
|
|
167
|
-
},
|
|
168
|
-
|
|
169
160
|
/**
|
|
170
161
|
* Get the full stack (for debugging)
|
|
171
162
|
*/
|
package/lib/utils.ts
CHANGED
|
@@ -39,3 +39,31 @@ export function normalizeWhitespace(text: string): string {
|
|
|
39
39
|
.replace(/ +/g, ' ')
|
|
40
40
|
.trim();
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Escape XML special characters
|
|
45
|
+
* @param str - Input string
|
|
46
|
+
* @returns XML-safe string
|
|
47
|
+
*/
|
|
48
|
+
export function escapeXml(str: string): string {
|
|
49
|
+
return str
|
|
50
|
+
.replace(/&/g, '&')
|
|
51
|
+
.replace(/</g, '<')
|
|
52
|
+
.replace(/>/g, '>')
|
|
53
|
+
.replace(/"/g, '"')
|
|
54
|
+
.replace(/'/g, ''');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Escape LaTeX special characters
|
|
59
|
+
* @param text - Text to escape
|
|
60
|
+
* @returns Escaped text
|
|
61
|
+
*/
|
|
62
|
+
export function escapeLatex(text: string): string {
|
|
63
|
+
return text
|
|
64
|
+
.replace(/\\/g, '\\textbackslash{}')
|
|
65
|
+
.replace(/([#$%&_{}])/g, '\\$1')
|
|
66
|
+
.replace(/\^/g, '\\textasciicircum{}')
|
|
67
|
+
.replace(/~/g, '\\textasciitilde{}')
|
|
68
|
+
.replace(/\n/g, ' ');
|
|
69
|
+
}
|