docrev 0.5.0 → 0.5.2
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/lib/annotations.js +75 -12
- package/lib/import.js +6 -1
- package/package.json +1 -1
- package/skill/SKILL.md +16 -0
package/lib/annotations.js
CHANGED
|
@@ -173,6 +173,7 @@ export function parseAnnotations(text) {
|
|
|
173
173
|
|
|
174
174
|
/**
|
|
175
175
|
* Strip annotations from text, applying changes
|
|
176
|
+
* Handles nested annotations by iterating until stable
|
|
176
177
|
* @param {string} text
|
|
177
178
|
* @param {{keepComments?: boolean}} options
|
|
178
179
|
* @returns {string}
|
|
@@ -180,26 +181,88 @@ export function parseAnnotations(text) {
|
|
|
180
181
|
export function stripAnnotations(text, options = {}) {
|
|
181
182
|
const { keepComments = false } = options;
|
|
182
183
|
|
|
183
|
-
//
|
|
184
|
-
|
|
184
|
+
// Iterate until no more changes (handles nested annotations)
|
|
185
|
+
let prev;
|
|
186
|
+
let iterations = 0;
|
|
187
|
+
const maxIterations = 20; // Safety limit
|
|
185
188
|
|
|
186
|
-
|
|
187
|
-
|
|
189
|
+
do {
|
|
190
|
+
prev = text;
|
|
188
191
|
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
// Apply substitutions: {~~old~>new~~} → new
|
|
193
|
+
text = text.replace(PATTERNS.substitute, '$2');
|
|
191
194
|
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
// Apply insertions: {++text++} → text
|
|
196
|
+
text = text.replace(PATTERNS.insert, '$1');
|
|
194
197
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
// Apply deletions: {--text--} → nothing
|
|
199
|
+
text = text.replace(PATTERNS.delete, '');
|
|
200
|
+
|
|
201
|
+
// Remove highlights: {==text==} → text
|
|
202
|
+
text = text.replace(PATTERNS.highlight, '$1');
|
|
203
|
+
|
|
204
|
+
// Remove comments unless keeping
|
|
205
|
+
if (!keepComments) {
|
|
206
|
+
text = text.replace(PATTERNS.comment, '');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Clean up partial/orphaned markers within the loop
|
|
210
|
+
// This handles cases where nested annotations leave behind fragments
|
|
211
|
+
|
|
212
|
+
// Empty annotations (from nested stripping)
|
|
213
|
+
text = text.replace(/\{----\}/g, '');
|
|
214
|
+
text = text.replace(/\{\+\+\+\+\}/g, '');
|
|
215
|
+
text = text.replace(/\{--\s*--\}/g, '');
|
|
216
|
+
text = text.replace(/\{\+\+\s*\+\+\}/g, '');
|
|
217
|
+
|
|
218
|
+
// Orphaned substitution fragments: ~>text~~} or {~~text (no proper pairs)
|
|
219
|
+
text = text.replace(/~>[^{]*?~~\}/g, '');
|
|
220
|
+
text = text.replace(/\{~~[^~}]*$/gm, '');
|
|
221
|
+
|
|
222
|
+
// Handle malformed substitution from nested: {~~{~~old → just strip the {~~
|
|
223
|
+
text = text.replace(/\{~~\{~~/g, '{~~');
|
|
224
|
+
text = text.replace(/~~\}~~\}/g, '~~}');
|
|
225
|
+
|
|
226
|
+
iterations++;
|
|
227
|
+
} while (text !== prev && iterations < maxIterations);
|
|
228
|
+
|
|
229
|
+
// Final cleanup of any remaining orphaned markers
|
|
230
|
+
// Orphaned closing markers
|
|
231
|
+
text = text.replace(/--\}(?:--\})+/g, '');
|
|
232
|
+
text = text.replace(/\+\+\}(?:\+\+\})+/g, '');
|
|
233
|
+
text = text.replace(/~~\}(?:~~\})+/g, '');
|
|
234
|
+
text = text.replace(/--\}/g, '');
|
|
235
|
+
text = text.replace(/\+\+\}/g, '');
|
|
236
|
+
text = text.replace(/~~\}/g, '');
|
|
237
|
+
|
|
238
|
+
// Orphaned opening markers
|
|
239
|
+
text = text.replace(/\{--(?:\{--)+/g, '');
|
|
240
|
+
text = text.replace(/\{\+\+(?:\{\+\+)+/g, '');
|
|
241
|
+
text = text.replace(/\{~~(?:\{~~)+/g, '');
|
|
242
|
+
text = text.replace(/\{--/g, '');
|
|
243
|
+
text = text.replace(/\{\+\+/g, '');
|
|
244
|
+
text = text.replace(/\{~~/g, '');
|
|
245
|
+
text = text.replace(/~>/g, '');
|
|
246
|
+
|
|
247
|
+
// Clean up multiple spaces (but preserve structure like newlines)
|
|
248
|
+
text = text.replace(/ +/g, ' ');
|
|
199
249
|
|
|
200
250
|
return text;
|
|
201
251
|
}
|
|
202
252
|
|
|
253
|
+
/**
|
|
254
|
+
* Check if text contains any CriticMarkup annotations
|
|
255
|
+
* @param {string} text
|
|
256
|
+
* @returns {boolean}
|
|
257
|
+
*/
|
|
258
|
+
export function hasAnnotations(text) {
|
|
259
|
+
return PATTERNS.insert.test(text) ||
|
|
260
|
+
PATTERNS.delete.test(text) ||
|
|
261
|
+
PATTERNS.substitute.test(text) ||
|
|
262
|
+
PATTERNS.comment.test(text) ||
|
|
263
|
+
PATTERNS.highlight.test(text);
|
|
264
|
+
}
|
|
265
|
+
|
|
203
266
|
/**
|
|
204
267
|
* Apply a decision to a single annotation
|
|
205
268
|
* @param {string} text
|
package/lib/import.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { diffWords } from 'diff';
|
|
8
|
+
import { stripAnnotations } from './annotations.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Extract comments directly from Word docx comments.xml
|
|
@@ -985,7 +986,11 @@ export async function importFromWord(docxPath, originalMdPath, options = {}) {
|
|
|
985
986
|
}
|
|
986
987
|
|
|
987
988
|
// Read original markdown
|
|
988
|
-
|
|
989
|
+
let originalMd = fs.readFileSync(originalMdPath, 'utf-8');
|
|
990
|
+
|
|
991
|
+
// IMPORTANT: Strip any existing annotations to prevent nested annotations
|
|
992
|
+
// This ensures we always diff clean text against Word text
|
|
993
|
+
originalMd = stripAnnotations(originalMd, { keepComments: false });
|
|
989
994
|
|
|
990
995
|
// Generate diff
|
|
991
996
|
let annotated = generateSmartDiff(originalMd, wordText, author);
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -134,4 +134,20 @@ my-paper/
|
|
|
134
134
|
4. **Validation phase**: Run `rev check` before submission (lint + grammar + citations)
|
|
135
135
|
5. **Response letter**: Use `rev response` to generate point-by-point responses
|
|
136
136
|
|
|
137
|
+
## Critical: Ask Questions When Unsure
|
|
138
|
+
|
|
139
|
+
When addressing reviewer comments or editing scientific papers:
|
|
140
|
+
|
|
141
|
+
- **Never guess methods or numbers** - If a comment asks for clarification about methodology, sample sizes, statistical parameters, dates, or any quantitative information, ASK the user rather than inventing values
|
|
142
|
+
- **Placeholders are acceptable** - Use `[???]` or `[TODO: specify X]` when information is missing rather than fabricating data
|
|
143
|
+
- **Search online for references** - When comments request citations, use web search to find appropriate references rather than guessing
|
|
144
|
+
- **Clarify ambiguous requests** - If a reviewer comment could be interpreted multiple ways, ask the user which interpretation they prefer
|
|
145
|
+
- **Verify existing values** - When editing numbers that already exist in the document, confirm changes with the user if there's any doubt
|
|
146
|
+
|
|
147
|
+
Example scenarios requiring user input:
|
|
148
|
+
- "Add a reference for this claim" → Search online OR ask user for specific citation
|
|
149
|
+
- "Clarify the sample size" → Ask user for the correct number
|
|
150
|
+
- "Specify the statistical test used" → Ask user which test was actually used
|
|
151
|
+
- "Add the date of data collection" → Ask user for the actual date
|
|
152
|
+
|
|
137
153
|
For complete command reference, see [REFERENCE.md](REFERENCE.md).
|