docrev 0.10.2 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +2 -0
  3. package/dist/lib/anchor-match.d.ts +3 -1
  4. package/dist/lib/anchor-match.d.ts.map +1 -1
  5. package/dist/lib/anchor-match.js +5 -7
  6. package/dist/lib/anchor-match.js.map +1 -1
  7. package/dist/lib/annotations.d.ts +0 -6
  8. package/dist/lib/annotations.d.ts.map +1 -1
  9. package/dist/lib/annotations.js +26 -8
  10. package/dist/lib/annotations.js.map +1 -1
  11. package/dist/lib/build.d.ts +52 -0
  12. package/dist/lib/build.d.ts.map +1 -1
  13. package/dist/lib/build.js +135 -6
  14. package/dist/lib/build.js.map +1 -1
  15. package/dist/lib/commands/build.d.ts.map +1 -1
  16. package/dist/lib/commands/build.js +39 -12
  17. package/dist/lib/commands/build.js.map +1 -1
  18. package/dist/lib/commands/doi.d.ts.map +1 -1
  19. package/dist/lib/commands/doi.js +14 -2
  20. package/dist/lib/commands/doi.js.map +1 -1
  21. package/dist/lib/commands/sync.d.ts.map +1 -1
  22. package/dist/lib/commands/sync.js +24 -11
  23. package/dist/lib/commands/sync.js.map +1 -1
  24. package/dist/lib/comment-realign.d.ts +12 -21
  25. package/dist/lib/comment-realign.d.ts.map +1 -1
  26. package/dist/lib/comment-realign.js +40 -348
  27. package/dist/lib/comment-realign.js.map +1 -1
  28. package/dist/lib/dependencies.d.ts +10 -0
  29. package/dist/lib/dependencies.d.ts.map +1 -1
  30. package/dist/lib/dependencies.js +41 -9
  31. package/dist/lib/dependencies.js.map +1 -1
  32. package/dist/lib/doi.d.ts.map +1 -1
  33. package/dist/lib/doi.js +68 -80
  34. package/dist/lib/doi.js.map +1 -1
  35. package/dist/lib/errors.d.ts.map +1 -1
  36. package/dist/lib/errors.js +3 -1
  37. package/dist/lib/errors.js.map +1 -1
  38. package/dist/lib/import.d.ts +7 -4
  39. package/dist/lib/import.d.ts.map +1 -1
  40. package/dist/lib/import.js +58 -62
  41. package/dist/lib/import.js.map +1 -1
  42. package/dist/lib/ooxml.d.ts +207 -0
  43. package/dist/lib/ooxml.d.ts.map +1 -0
  44. package/dist/lib/ooxml.js +634 -0
  45. package/dist/lib/ooxml.js.map +1 -0
  46. package/dist/lib/rate-limiter.d.ts +8 -0
  47. package/dist/lib/rate-limiter.d.ts.map +1 -1
  48. package/dist/lib/rate-limiter.js +41 -4
  49. package/dist/lib/rate-limiter.js.map +1 -1
  50. package/dist/lib/trackchanges.d.ts +41 -25
  51. package/dist/lib/trackchanges.d.ts.map +1 -1
  52. package/dist/lib/trackchanges.js +90 -151
  53. package/dist/lib/trackchanges.js.map +1 -1
  54. package/dist/lib/types.d.ts +9 -8
  55. package/dist/lib/types.d.ts.map +1 -1
  56. package/dist/lib/word-extraction.d.ts.map +1 -1
  57. package/dist/lib/word-extraction.js +48 -307
  58. package/dist/lib/word-extraction.js.map +1 -1
  59. package/dist/lib/word.d.ts.map +1 -1
  60. package/dist/lib/word.js +80 -175
  61. package/dist/lib/word.js.map +1 -1
  62. package/dist/lib/wordcomments.d.ts.map +1 -1
  63. package/dist/lib/wordcomments.js +53 -92
  64. package/dist/lib/wordcomments.js.map +1 -1
  65. package/lib/anchor-match.ts +6 -7
  66. package/lib/annotations.ts +28 -8
  67. package/lib/build.ts +196 -6
  68. package/lib/commands/build.ts +42 -12
  69. package/lib/commands/doi.ts +17 -1
  70. package/lib/commands/sync.ts +26 -13
  71. package/lib/comment-realign.ts +46 -464
  72. package/lib/dependencies.ts +43 -9
  73. package/lib/doi.ts +76 -94
  74. package/lib/errors.ts +5 -1
  75. package/lib/import.ts +65 -70
  76. package/lib/ooxml.ts +768 -0
  77. package/lib/rate-limiter.ts +37 -4
  78. package/lib/trackchanges.ts +102 -183
  79. package/lib/types.ts +9 -13
  80. package/lib/word-extraction.ts +49 -330
  81. package/lib/word.ts +86 -203
  82. package/lib/wordcomments.ts +53 -104
  83. package/package.json +137 -137
  84. package/skill/REFERENCE.md +14 -3
  85. package/skill/SKILL.md +12 -5
  86. package/types/index.d.ts +16 -10
@@ -6,12 +6,20 @@ export interface RateLimiterOptions {
6
6
  maxDelay?: number;
7
7
  maxRetries?: number;
8
8
  backoffFactor?: number;
9
+ /** Per-request timeout in ms; a stalled connection aborts instead of hanging. */
10
+ requestTimeout?: number;
9
11
  }
12
+ /**
13
+ * Parse an HTTP `Retry-After` header, which may be a delay in seconds or an
14
+ * HTTP-date. Returns the delay in milliseconds, or null when unparseable.
15
+ */
16
+ export declare function parseRetryAfter(value: string | null, now?: number): number | null;
10
17
  export declare class RateLimiter {
11
18
  private minDelay;
12
19
  private maxDelay;
13
20
  private maxRetries;
14
21
  private backoffFactor;
22
+ private requestTimeout;
15
23
  private lastRequestTime;
16
24
  private currentDelay;
17
25
  private consecutiveErrors;
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../lib/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,OAAO,GAAE,kBAAuB;IAUtC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,SAAS,IAAI,IAAI;IAMjB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAS9B,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAkChF;AAGD,eAAO,MAAM,eAAe,aAAsD,CAAC;AACnF,eAAO,MAAM,eAAe,aAAsD,CAAC;AACnF,eAAO,MAAM,aAAa,aAAsD,CAAC"}
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../lib/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,GAAG,IAAI,CAO7F;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,OAAO,GAAE,kBAAuB;IAWtC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,SAAS,IAAI,IAAI;IAMjB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAS9B,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAkDhF;AAGD,eAAO,MAAM,eAAe,aAAsD,CAAC;AACnF,eAAO,MAAM,eAAe,aAAsD,CAAC;AACnF,eAAO,MAAM,aAAa,aAAsD,CAAC"}
@@ -1,11 +1,27 @@
1
1
  /**
2
2
  * Rate Limiter - Prevents API abuse with exponential backoff
3
3
  */
4
+ /**
5
+ * Parse an HTTP `Retry-After` header, which may be a delay in seconds or an
6
+ * HTTP-date. Returns the delay in milliseconds, or null when unparseable.
7
+ */
8
+ export function parseRetryAfter(value, now = Date.now()) {
9
+ if (!value)
10
+ return null;
11
+ const seconds = Number(value);
12
+ if (Number.isFinite(seconds))
13
+ return Math.max(0, seconds * 1000);
14
+ const date = Date.parse(value);
15
+ if (!Number.isNaN(date))
16
+ return Math.max(0, date - now);
17
+ return null;
18
+ }
4
19
  export class RateLimiter {
5
20
  minDelay;
6
21
  maxDelay;
7
22
  maxRetries;
8
23
  backoffFactor;
24
+ requestTimeout;
9
25
  lastRequestTime;
10
26
  currentDelay;
11
27
  consecutiveErrors;
@@ -14,6 +30,7 @@ export class RateLimiter {
14
30
  this.maxDelay = options.maxDelay || 30000; // Max delay after backoff (ms)
15
31
  this.maxRetries = options.maxRetries || 3; // Max retry attempts
16
32
  this.backoffFactor = options.backoffFactor || 2;
33
+ this.requestTimeout = options.requestTimeout || 15000; // Abort a stalled request
17
34
  this.lastRequestTime = 0;
18
35
  this.currentDelay = this.minDelay;
19
36
  this.consecutiveErrors = 0;
@@ -41,14 +58,25 @@ export class RateLimiter {
41
58
  }
42
59
  async fetchWithRetry(url, options = {}) {
43
60
  let lastError;
61
+ const callerSignal = options.signal ?? undefined;
44
62
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
45
63
  await this.wait();
64
+ // Bound each attempt so a half-open connection cannot hang the run
65
+ // forever; merge the caller's signal so an external cancel still works.
66
+ const controller = new AbortController();
67
+ const timer = setTimeout(() => controller.abort(new Error('Request timed out')), this.requestTimeout);
68
+ const onCallerAbort = () => controller.abort(callerSignal.reason);
69
+ if (callerSignal) {
70
+ if (callerSignal.aborted)
71
+ controller.abort(callerSignal.reason);
72
+ else
73
+ callerSignal.addEventListener('abort', onCallerAbort, { once: true });
74
+ }
46
75
  try {
47
- const response = await fetch(url, options);
76
+ const response = await fetch(url, { ...options, signal: controller.signal });
48
77
  if (response.status === 429) {
49
- // Rate limited - back off
50
- const retryAfter = response.headers.get('Retry-After');
51
- const delay = retryAfter ? parseInt(retryAfter, 10) * 1000 : this.currentDelay * 2;
78
+ // Rate limited - back off. Retry-After may be seconds or an HTTP-date.
79
+ const delay = parseRetryAfter(response.headers.get('Retry-After')) ?? this.currentDelay * 2;
52
80
  this.currentDelay = Math.min(this.maxDelay, delay);
53
81
  if (!this.onError(429))
54
82
  break;
@@ -64,10 +92,19 @@ export class RateLimiter {
64
92
  return response;
65
93
  }
66
94
  catch (err) {
95
+ // A caller-initiated abort is intentional cancellation, not a failure
96
+ // to retry around.
97
+ if (callerSignal?.aborted)
98
+ throw err;
67
99
  lastError = err;
68
100
  if (!this.onError(0))
69
101
  break;
70
102
  }
103
+ finally {
104
+ clearTimeout(timer);
105
+ if (callerSignal)
106
+ callerSignal.removeEventListener('abort', onCallerAbort);
107
+ }
71
108
  }
72
109
  throw lastError || new Error('Max retries exceeded');
73
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../lib/rate-limiter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../lib/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -1,51 +1,67 @@
1
1
  /**
2
2
  * Track changes module - Apply markdown annotations as Word track changes
3
3
  *
4
- * Converts CriticMarkup annotations to Word OOXML track changes format.
4
+ * Converts CriticMarkup insertions/deletions/substitutions to pandoc-native
5
+ * track-change spans (`[text]{.insertion}` / `[text]{.deletion}`). Pandoc's
6
+ * docx writer emits well-formed `w:ins`/`w:del` run-level revisions from these
7
+ * spans in a single pass, so the output is valid OOXML that Word accepts and
8
+ * that composes with comment injection (see lib/wordcomments.ts).
5
9
  */
6
- import type { TrackChangeMarker } from './types.js';
7
- interface PrepareOptions {
10
+ interface NativeTrackChangeOptions {
8
11
  author?: string;
12
+ /** ISO-8601 timestamp for the revisions. Defaults to now (no milliseconds). */
13
+ date?: string;
9
14
  }
10
- interface PrepareResult {
15
+ export interface NativeTrackChangeStats {
16
+ insertions: number;
17
+ deletions: number;
18
+ substitutions: number;
19
+ }
20
+ interface ConvertResult {
11
21
  text: string;
12
- markers: TrackChangeMarker[];
22
+ stats: NativeTrackChangeStats;
13
23
  }
14
24
  interface ApplyResult {
15
25
  success: boolean;
16
26
  message: string;
17
- stats?: {
18
- insertions: number;
19
- deletions: number;
20
- substitutions: number;
21
- };
27
+ stats?: NativeTrackChangeStats;
22
28
  }
23
29
  /**
24
- * Prepare text with CriticMarkup annotations for track changes
25
- * Replaces annotations with markers that can be processed in DOCX
30
+ * Convert CriticMarkup insertions/deletions/substitutions to pandoc-native
31
+ * track-change spans. Comments (`{>>...<<}`) and highlights (`{==...==}`) are
32
+ * left untouched — the caller decides how to handle those (strip, or thread
33
+ * them via wordcomments.ts).
34
+ *
35
+ * A single pandoc pass over the result emits valid `w:ins`/`w:del` revisions,
36
+ * so this composes with the full rev filter chain (crossref, citeproc,
37
+ * reference-doc, macros) instead of post-processing document.xml by hand.
26
38
  *
27
- * @param text - Text with CriticMarkup annotations
28
- * @param options - Options
29
- * @returns Processed text and marker info
39
+ * @param text - Markdown with CriticMarkup annotations
40
+ * @param options - Author/date for the revisions
41
+ * @returns Converted markdown plus per-type counts
30
42
  */
31
- export declare function prepareForTrackChanges(text: string, options?: PrepareOptions): PrepareResult;
43
+ export declare function criticToNativeTrackChanges(text: string, options?: NativeTrackChangeOptions): ConvertResult;
32
44
  /**
33
- * Apply track changes markers to a Word document
45
+ * Enable tracked-revision display in a docx's settings.xml (in place).
34
46
  *
35
- * @param docxPath - Path to input DOCX file
36
- * @param markers - Markers from prepareForTrackChanges
37
- * @param outputPath - Path for output DOCX file
38
- * @returns Result with success status and message
47
+ * The `w:ins`/`w:del` elements already render as tracked changes without this,
48
+ * but `w:trackRevisions` tells Word to keep tracking the author's further
49
+ * edits the expected state for a "return to author" review document.
39
50
  */
40
- export declare function applyTrackChangesToDocx(docxPath: string, markers: TrackChangeMarker[], outputPath: string): Promise<ApplyResult>;
51
+ export declare function enableTrackRevisions(docxPath: string): void;
41
52
  /**
42
- * Build a Word document with track changes from annotated markdown
53
+ * Build a standalone Word document with track changes from annotated markdown.
54
+ *
55
+ * Used by `rev apply <md> <docx>` for a single markdown file outside a rev
56
+ * project (no crossref/citeproc/reference-doc). Comments are dropped — use the
57
+ * project build (`rev build docx --show-changes`) for the full filter chain and
58
+ * threaded comments.
43
59
  *
44
60
  * @param mdPath - Path to markdown file with CriticMarkup
45
61
  * @param docxPath - Output path for Word document
46
- * @param options - Options
62
+ * @param options - Author name for the revisions
47
63
  * @returns Result with success status and message
48
64
  */
49
- export declare function buildWithTrackChanges(mdPath: string, docxPath: string, options?: PrepareOptions): Promise<ApplyResult>;
65
+ export declare function buildWithTrackChanges(mdPath: string, docxPath: string, options?: NativeTrackChangeOptions): Promise<ApplyResult>;
50
66
  export {};
51
67
  //# sourceMappingURL=trackchanges.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trackchanges.d.ts","sourceRoot":"","sources":["../../lib/trackchanges.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CAiEhG;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,EAAE,EAC5B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CAgEtB;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,WAAW,CAAC,CAiDtB"}
1
+ {"version":3,"file":"trackchanges.d.ts","sourceRoot":"","sources":["../../lib/trackchanges.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,UAAU,wBAAwB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,sBAAsB,CAAC;CAC/B;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,sBAAsB,CAAC;CAChC;AAgBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,wBAA6B,GACrC,aAAa,CA8Bf;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAe3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,WAAW,CAAC,CAuBtB"}
@@ -1,192 +1,131 @@
1
1
  /**
2
2
  * Track changes module - Apply markdown annotations as Word track changes
3
3
  *
4
- * Converts CriticMarkup annotations to Word OOXML track changes format.
4
+ * Converts CriticMarkup insertions/deletions/substitutions to pandoc-native
5
+ * track-change spans (`[text]{.insertion}` / `[text]{.deletion}`). Pandoc's
6
+ * docx writer emits well-formed `w:ins`/`w:del` run-level revisions from these
7
+ * spans in a single pass, so the output is valid OOXML that Word accepts and
8
+ * that composes with comment injection (see lib/wordcomments.ts).
5
9
  */
6
10
  import * as fs from 'fs';
7
11
  import * as path from 'path';
8
12
  import { execSync } from 'child_process';
9
13
  import AdmZip from 'adm-zip';
10
- import { escapeXml } from './utils.js';
14
+ /** Word/pandoc want revision dates without milliseconds: 2026-07-05T08:33:00Z */
15
+ function isoDateNoMillis() {
16
+ return new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
17
+ }
18
+ /**
19
+ * Escape a value for use inside a pandoc span attribute (`author="..."`).
20
+ * Pandoc attribute values are double-quoted; a literal `"` or `\` would break
21
+ * the attribute, so both are backslash-escaped.
22
+ */
23
+ function escapeSpanAttr(value) {
24
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
25
+ }
11
26
  /**
12
- * Prepare text with CriticMarkup annotations for track changes
13
- * Replaces annotations with markers that can be processed in DOCX
27
+ * Convert CriticMarkup insertions/deletions/substitutions to pandoc-native
28
+ * track-change spans. Comments (`{>>...<<}`) and highlights (`{==...==}`) are
29
+ * left untouched — the caller decides how to handle those (strip, or thread
30
+ * them via wordcomments.ts).
14
31
  *
15
- * @param text - Text with CriticMarkup annotations
16
- * @param options - Options
17
- * @returns Processed text and marker info
32
+ * A single pandoc pass over the result emits valid `w:ins`/`w:del` revisions,
33
+ * so this composes with the full rev filter chain (crossref, citeproc,
34
+ * reference-doc, macros) instead of post-processing document.xml by hand.
35
+ *
36
+ * @param text - Markdown with CriticMarkup annotations
37
+ * @param options - Author/date for the revisions
38
+ * @returns Converted markdown plus per-type counts
18
39
  */
19
- export function prepareForTrackChanges(text, options = {}) {
20
- const { author = 'Reviewer' } = options;
21
- const markers = [];
22
- let markerId = 0;
40
+ export function criticToNativeTrackChanges(text, options = {}) {
41
+ const author = escapeSpanAttr(options.author ?? 'Author');
42
+ const date = escapeSpanAttr(options.date ?? isoDateNoMillis());
43
+ const insAttr = `{.insertion author="${author}" date="${date}"}`;
44
+ const delAttr = `{.deletion author="${author}" date="${date}"}`;
45
+ const stats = { insertions: 0, deletions: 0, substitutions: 0 };
23
46
  let result = text;
24
- // Process insertions: {++text++}
25
- result = result.replace(/\{\+\+(.+?)\+\+\}/gs, (match, content) => {
26
- const id = markerId++;
27
- markers.push({
28
- id,
29
- type: 'insert',
30
- content,
31
- author,
32
- });
33
- return `{{TC_${id}}}`;
34
- });
35
- // Process deletions: {--text--}
36
- result = result.replace(/\{--(.+?)--\}/gs, (match, content) => {
37
- const id = markerId++;
38
- markers.push({
39
- id,
40
- type: 'delete',
41
- content,
42
- author,
43
- });
44
- return `{{TC_${id}}}`;
47
+ // Substitutions first so `{~~old~>new~~}` is consumed before the insertion/
48
+ // deletion passes could see its inner delimiters. Emit delete-then-insert so
49
+ // Word shows the struck-through original followed by the replacement.
50
+ result = result.replace(/\{~~([\s\S]+?)~>([\s\S]+?)~~\}/g, (_m, oldText, newText) => {
51
+ stats.substitutions++;
52
+ return `[${oldText}]${delAttr}[${newText}]${insAttr}`;
45
53
  });
46
- // Process substitutions: {~~old~>new~~}
47
- result = result.replace(/\{~~(.+?)~>(.+?)~~\}/gs, (match, old, replacement) => {
48
- const id = markerId++;
49
- markers.push({
50
- id,
51
- type: 'substitute',
52
- content: old,
53
- replacement,
54
- author,
55
- });
56
- return `{{TC_${id}}}`;
54
+ // Insertions: {++text++}
55
+ result = result.replace(/\{\+\+([\s\S]+?)\+\+\}/g, (_m, content) => {
56
+ stats.insertions++;
57
+ return `[${content}]${insAttr}`;
57
58
  });
58
- // Process comments: {>>Author: comment<<}
59
- result = result.replace(/\{>>(.+?)<<\}/gs, (match, content) => {
60
- const id = markerId++;
61
- // Extract author if present (format: "Author: comment")
62
- const colonIdx = content.indexOf(':');
63
- let commentAuthor = author;
64
- let commentText = content;
65
- if (colonIdx > 0 && colonIdx < 30) {
66
- commentAuthor = content.slice(0, colonIdx).trim();
67
- commentText = content.slice(colonIdx + 1).trim();
68
- }
69
- markers.push({
70
- id,
71
- type: 'comment',
72
- content: commentText,
73
- author: commentAuthor,
74
- });
75
- return `{{TC_${id}}}`;
59
+ // Deletions: {--text--}
60
+ result = result.replace(/\{--([\s\S]+?)--\}/g, (_m, content) => {
61
+ stats.deletions++;
62
+ return `[${content}]${delAttr}`;
76
63
  });
77
- return { text: result, markers };
64
+ return { text: result, stats };
78
65
  }
79
66
  /**
80
- * Apply track changes markers to a Word document
67
+ * Enable tracked-revision display in a docx's settings.xml (in place).
81
68
  *
82
- * @param docxPath - Path to input DOCX file
83
- * @param markers - Markers from prepareForTrackChanges
84
- * @param outputPath - Path for output DOCX file
85
- * @returns Result with success status and message
69
+ * The `w:ins`/`w:del` elements already render as tracked changes without this,
70
+ * but `w:trackRevisions` tells Word to keep tracking the author's further
71
+ * edits the expected state for a "return to author" review document.
86
72
  */
87
- export async function applyTrackChangesToDocx(docxPath, markers, outputPath) {
88
- if (!fs.existsSync(docxPath)) {
89
- return { success: false, message: `File not found: ${docxPath}` };
90
- }
91
- let zip;
92
- try {
93
- zip = new AdmZip(docxPath);
94
- }
95
- catch (err) {
96
- const error = err;
97
- return { success: false, message: `Invalid DOCX file: ${error.message}` };
98
- }
99
- // Read document.xml
100
- const docEntry = zip.getEntry('word/document.xml');
101
- if (!docEntry) {
102
- return { success: false, message: 'Invalid DOCX: no document.xml' };
103
- }
104
- let documentXml = zip.readAsText(docEntry);
105
- // Generate ISO date for track changes
106
- const now = new Date().toISOString();
107
- // Replace markers with track change XML
108
- for (const marker of markers) {
109
- const placeholder = `{{TC_${marker.id}}}`;
110
- let replacement = '';
111
- const escapedContent = escapeXml(marker.content);
112
- const escapedAuthor = escapeXml(marker.author);
113
- if (marker.type === 'insert') {
114
- replacement = `<w:ins w:id="${marker.id}" w:author="${escapedAuthor}" w:date="${now}"><w:r><w:t>${escapedContent}</w:t></w:r></w:ins>`;
115
- }
116
- else if (marker.type === 'delete') {
117
- replacement = `<w:del w:id="${marker.id}" w:author="${escapedAuthor}" w:date="${now}"><w:r><w:delText>${escapedContent}</w:delText></w:r></w:del>`;
118
- }
119
- else if (marker.type === 'substitute') {
120
- const escapedReplacement = escapeXml(marker.replacement || '');
121
- replacement = `<w:del w:id="${marker.id}" w:author="${escapedAuthor}" w:date="${now}"><w:r><w:delText>${escapedContent}</w:delText></w:r></w:del><w:ins w:id="${marker.id + 1000}" w:author="${escapedAuthor}" w:date="${now}"><w:r><w:t>${escapedReplacement}</w:t></w:r></w:ins>`;
122
- }
123
- documentXml = documentXml.replace(placeholder, replacement);
124
- }
125
- // Update document.xml
126
- zip.updateFile('word/document.xml', Buffer.from(documentXml));
127
- // Enable track revisions in settings.xml
73
+ export function enableTrackRevisions(docxPath) {
74
+ const zip = new AdmZip(docxPath);
128
75
  const settingsEntry = zip.getEntry('word/settings.xml');
129
- if (settingsEntry) {
130
- let settingsXml = zip.readAsText(settingsEntry);
131
- if (!settingsXml.includes('w:trackRevisions')) {
132
- settingsXml = settingsXml.replace('</w:settings>', '<w:trackRevisions/></w:settings>');
133
- zip.updateFile('word/settings.xml', Buffer.from(settingsXml));
134
- }
76
+ if (!settingsEntry)
77
+ return;
78
+ let settingsXml = zip.readAsText(settingsEntry);
79
+ if (settingsXml.includes('w:trackRevisions'))
80
+ return;
81
+ // trackRevisions must appear early in the ordered settings sequence; placing
82
+ // it right after the opening tag keeps Word from rejecting the schema order.
83
+ settingsXml = settingsXml.replace(/(<w:settings[^>]*>)/, '$1<w:trackRevisions/>');
84
+ if (!settingsXml.includes('<w:trackRevisions/>')) {
85
+ // No opening tag matched (unexpected) — fall back to before the close tag.
86
+ settingsXml = settingsXml.replace('</w:settings>', '<w:trackRevisions/></w:settings>');
135
87
  }
136
- // Write output
137
- zip.writeZip(outputPath);
138
- return { success: true, message: `Created ${outputPath} with track changes` };
88
+ zip.updateFile('word/settings.xml', Buffer.from(settingsXml, 'utf-8'));
89
+ zip.writeZip(docxPath);
139
90
  }
140
91
  /**
141
- * Build a Word document with track changes from annotated markdown
92
+ * Build a standalone Word document with track changes from annotated markdown.
93
+ *
94
+ * Used by `rev apply <md> <docx>` for a single markdown file outside a rev
95
+ * project (no crossref/citeproc/reference-doc). Comments are dropped — use the
96
+ * project build (`rev build docx --show-changes`) for the full filter chain and
97
+ * threaded comments.
142
98
  *
143
99
  * @param mdPath - Path to markdown file with CriticMarkup
144
100
  * @param docxPath - Output path for Word document
145
- * @param options - Options
101
+ * @param options - Author name for the revisions
146
102
  * @returns Result with success status and message
147
103
  */
148
104
  export async function buildWithTrackChanges(mdPath, docxPath, options = {}) {
149
- const { author = 'Author' } = options;
150
105
  if (!fs.existsSync(mdPath)) {
151
106
  return { success: false, message: `File not found: ${mdPath}` };
152
107
  }
108
+ const { author = 'Author' } = options;
153
109
  const content = fs.readFileSync(mdPath, 'utf-8');
154
- // Prepare for track changes
155
- const { text: prepared, markers } = prepareForTrackChanges(content, { author });
156
- // If no annotations, just build normally
157
- if (markers.length === 0) {
158
- try {
159
- execSync(`pandoc "${mdPath}" -o "${docxPath}"`, { encoding: 'utf-8' });
160
- return { success: true, message: `Created ${docxPath}` };
161
- }
162
- catch (err) {
163
- const error = err;
164
- return { success: false, message: error.message };
165
- }
166
- }
167
- // Write prepared content to temp file
168
- const tempDir = path.dirname(mdPath);
169
- const tempMd = path.join(tempDir, `.temp-${Date.now()}.md`);
170
- const tempDocx = path.join(tempDir, `.temp-${Date.now()}.docx`);
110
+ const { text: converted, stats } = criticToNativeTrackChanges(content, { author });
111
+ const total = stats.insertions + stats.deletions + stats.substitutions;
112
+ const tempMd = path.join(path.dirname(mdPath), `.temp-tc-${process.pid}.md`);
171
113
  try {
172
- fs.writeFileSync(tempMd, prepared, 'utf-8');
173
- // Build with pandoc
174
- execSync(`pandoc "${tempMd}" -o "${tempDocx}"`, { encoding: 'utf-8' });
175
- // Apply track changes
176
- const result = await applyTrackChangesToDocx(tempDocx, markers, docxPath);
177
- // Clean up temp files
178
- fs.unlinkSync(tempMd);
179
- fs.unlinkSync(tempDocx);
180
- return result;
114
+ fs.writeFileSync(tempMd, converted, 'utf-8');
115
+ execSync(`pandoc "${tempMd}" -o "${docxPath}"`, { encoding: 'utf-8' });
116
+ if (total > 0)
117
+ enableTrackRevisions(docxPath);
118
+ return { success: true, message: `Created ${docxPath} with track changes`, stats };
181
119
  }
182
120
  catch (err) {
183
- // Clean up on error
184
- if (fs.existsSync(tempMd))
185
- fs.unlinkSync(tempMd);
186
- if (fs.existsSync(tempDocx))
187
- fs.unlinkSync(tempDocx);
188
121
  const error = err;
189
122
  return { success: false, message: error.message };
190
123
  }
124
+ finally {
125
+ try {
126
+ fs.unlinkSync(tempMd);
127
+ }
128
+ catch { /* best-effort cleanup */ }
129
+ }
191
130
  }
192
131
  //# sourceMappingURL=trackchanges.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trackchanges.js","sourceRoot":"","sources":["../../lib/trackchanges.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trackchanges.js","sourceRoot":"","sources":["../../lib/trackchanges.ts"],"names":[],"mappings":"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"}
@@ -188,7 +188,13 @@ export interface BibEntry {
188
188
  }
189
189
  export interface DoiCheckResult {
190
190
  valid: boolean;
191
- source?: 'crossref' | 'datacite';
191
+ source?: 'crossref' | 'datacite' | 'doi.org';
192
+ /**
193
+ * True when the registry could not be reached (network error, timeout, or
194
+ * 5xx) — the DOI's validity is unknown, distinct from a definitive "not
195
+ * found". Callers must not report an unreachable DOI as invalid.
196
+ */
197
+ unreachable?: boolean;
192
198
  metadata?: {
193
199
  title: string;
194
200
  authors: string[];
@@ -229,6 +235,8 @@ export interface BibCheckResult {
229
235
  }>;
230
236
  valid: number;
231
237
  invalid: number;
238
+ /** DOIs whose registry could not be reached (network/timeout) — not invalid. */
239
+ unreachable: number;
232
240
  missing: number;
233
241
  skipped: number;
234
242
  }
@@ -444,13 +452,6 @@ export interface TrackChangesResult {
444
452
  deletions: number;
445
453
  };
446
454
  }
447
- export interface TrackChangeMarker {
448
- id: number;
449
- type: 'insert' | 'delete' | 'substitute' | 'comment';
450
- content: string;
451
- author: string;
452
- replacement?: string;
453
- }
454
455
  export interface SpellingIssue {
455
456
  word: string;
456
457
  line: number;