docrev 0.8.0 → 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.
Files changed (306) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/PLAN-tables-and-postprocess.md +850 -0
  3. package/README.md +42 -0
  4. package/bin/rev.js +12 -131
  5. package/bin/rev.ts +145 -0
  6. package/dist/bin/rev.d.ts +9 -0
  7. package/dist/bin/rev.d.ts.map +1 -0
  8. package/dist/bin/rev.js +118 -0
  9. package/dist/bin/rev.js.map +1 -0
  10. package/dist/lib/annotations.d.ts +91 -0
  11. package/dist/lib/annotations.d.ts.map +1 -0
  12. package/dist/lib/annotations.js +554 -0
  13. package/dist/lib/annotations.js.map +1 -0
  14. package/dist/lib/build.d.ts +171 -0
  15. package/dist/lib/build.d.ts.map +1 -0
  16. package/dist/lib/build.js +755 -0
  17. package/dist/lib/build.js.map +1 -0
  18. package/dist/lib/citations.d.ts +34 -0
  19. package/dist/lib/citations.d.ts.map +1 -0
  20. package/dist/lib/citations.js +140 -0
  21. package/dist/lib/citations.js.map +1 -0
  22. package/dist/lib/commands/build.d.ts +13 -0
  23. package/dist/lib/commands/build.d.ts.map +1 -0
  24. package/dist/lib/commands/build.js +678 -0
  25. package/dist/lib/commands/build.js.map +1 -0
  26. package/dist/lib/commands/citations.d.ts +11 -0
  27. package/dist/lib/commands/citations.d.ts.map +1 -0
  28. package/dist/lib/commands/citations.js +428 -0
  29. package/dist/lib/commands/citations.js.map +1 -0
  30. package/dist/lib/commands/comments.d.ts +11 -0
  31. package/dist/lib/commands/comments.d.ts.map +1 -0
  32. package/dist/lib/commands/comments.js +883 -0
  33. package/dist/lib/commands/comments.js.map +1 -0
  34. package/dist/lib/commands/context.d.ts +35 -0
  35. package/dist/lib/commands/context.d.ts.map +1 -0
  36. package/dist/lib/commands/context.js +59 -0
  37. package/dist/lib/commands/context.js.map +1 -0
  38. package/dist/lib/commands/core.d.ts +11 -0
  39. package/dist/lib/commands/core.d.ts.map +1 -0
  40. package/dist/lib/commands/core.js +246 -0
  41. package/dist/lib/commands/core.js.map +1 -0
  42. package/dist/lib/commands/doi.d.ts +11 -0
  43. package/dist/lib/commands/doi.d.ts.map +1 -0
  44. package/dist/lib/commands/doi.js +373 -0
  45. package/dist/lib/commands/doi.js.map +1 -0
  46. package/dist/lib/commands/history.d.ts +11 -0
  47. package/dist/lib/commands/history.d.ts.map +1 -0
  48. package/dist/lib/commands/history.js +245 -0
  49. package/dist/lib/commands/history.js.map +1 -0
  50. package/dist/lib/commands/index.d.ts +28 -0
  51. package/dist/lib/commands/index.d.ts.map +1 -0
  52. package/dist/lib/commands/index.js +35 -0
  53. package/dist/lib/commands/index.js.map +1 -0
  54. package/dist/lib/commands/init.d.ts +11 -0
  55. package/dist/lib/commands/init.d.ts.map +1 -0
  56. package/dist/lib/commands/init.js +209 -0
  57. package/dist/lib/commands/init.js.map +1 -0
  58. package/dist/lib/commands/response.d.ts +11 -0
  59. package/dist/lib/commands/response.d.ts.map +1 -0
  60. package/dist/lib/commands/response.js +317 -0
  61. package/dist/lib/commands/response.js.map +1 -0
  62. package/dist/lib/commands/sections.d.ts +11 -0
  63. package/dist/lib/commands/sections.d.ts.map +1 -0
  64. package/dist/lib/commands/sections.js +1071 -0
  65. package/dist/lib/commands/sections.js.map +1 -0
  66. package/dist/lib/commands/utilities.d.ts +19 -0
  67. package/dist/lib/commands/utilities.d.ts.map +1 -0
  68. package/dist/lib/commands/utilities.js +2009 -0
  69. package/dist/lib/commands/utilities.js.map +1 -0
  70. package/dist/lib/comment-realign.d.ts +50 -0
  71. package/dist/lib/comment-realign.d.ts.map +1 -0
  72. package/dist/lib/comment-realign.js +372 -0
  73. package/dist/lib/comment-realign.js.map +1 -0
  74. package/dist/lib/config.d.ts +41 -0
  75. package/dist/lib/config.d.ts.map +1 -0
  76. package/dist/lib/config.js +76 -0
  77. package/dist/lib/config.js.map +1 -0
  78. package/dist/lib/crossref.d.ts +108 -0
  79. package/dist/lib/crossref.d.ts.map +1 -0
  80. package/dist/lib/crossref.js +597 -0
  81. package/dist/lib/crossref.js.map +1 -0
  82. package/dist/lib/dependencies.d.ts +30 -0
  83. package/dist/lib/dependencies.d.ts.map +1 -0
  84. package/dist/lib/dependencies.js +95 -0
  85. package/dist/lib/dependencies.js.map +1 -0
  86. package/dist/lib/doi-cache.d.ts +29 -0
  87. package/dist/lib/doi-cache.d.ts.map +1 -0
  88. package/dist/lib/doi-cache.js +104 -0
  89. package/dist/lib/doi-cache.js.map +1 -0
  90. package/dist/lib/doi.d.ts +65 -0
  91. package/dist/lib/doi.d.ts.map +1 -0
  92. package/dist/lib/doi.js +710 -0
  93. package/dist/lib/doi.js.map +1 -0
  94. package/dist/lib/equations.d.ts +61 -0
  95. package/dist/lib/equations.d.ts.map +1 -0
  96. package/dist/lib/equations.js +445 -0
  97. package/dist/lib/equations.js.map +1 -0
  98. package/dist/lib/errors.d.ts +60 -0
  99. package/dist/lib/errors.d.ts.map +1 -0
  100. package/dist/lib/errors.js +303 -0
  101. package/dist/lib/errors.js.map +1 -0
  102. package/dist/lib/format.d.ts +104 -0
  103. package/dist/lib/format.d.ts.map +1 -0
  104. package/dist/lib/format.js +416 -0
  105. package/dist/lib/format.js.map +1 -0
  106. package/dist/lib/git.d.ts +88 -0
  107. package/dist/lib/git.d.ts.map +1 -0
  108. package/dist/lib/git.js +304 -0
  109. package/dist/lib/git.js.map +1 -0
  110. package/dist/lib/grammar.d.ts +62 -0
  111. package/dist/lib/grammar.d.ts.map +1 -0
  112. package/dist/lib/grammar.js +244 -0
  113. package/dist/lib/grammar.js.map +1 -0
  114. package/dist/lib/image-registry.d.ts +68 -0
  115. package/dist/lib/image-registry.d.ts.map +1 -0
  116. package/dist/lib/image-registry.js +112 -0
  117. package/dist/lib/image-registry.js.map +1 -0
  118. package/dist/lib/import.d.ts +184 -0
  119. package/dist/lib/import.d.ts.map +1 -0
  120. package/dist/lib/import.js +1581 -0
  121. package/dist/lib/import.js.map +1 -0
  122. package/dist/lib/journals.d.ts +55 -0
  123. package/dist/lib/journals.d.ts.map +1 -0
  124. package/dist/lib/journals.js +417 -0
  125. package/dist/lib/journals.js.map +1 -0
  126. package/dist/lib/merge.d.ts +138 -0
  127. package/dist/lib/merge.d.ts.map +1 -0
  128. package/dist/lib/merge.js +603 -0
  129. package/dist/lib/merge.js.map +1 -0
  130. package/dist/lib/orcid.d.ts +36 -0
  131. package/dist/lib/orcid.d.ts.map +1 -0
  132. package/dist/lib/orcid.js +117 -0
  133. package/dist/lib/orcid.js.map +1 -0
  134. package/dist/lib/pdf-comments.d.ts +95 -0
  135. package/dist/lib/pdf-comments.d.ts.map +1 -0
  136. package/dist/lib/pdf-comments.js +192 -0
  137. package/dist/lib/pdf-comments.js.map +1 -0
  138. package/dist/lib/pdf-import.d.ts +118 -0
  139. package/dist/lib/pdf-import.d.ts.map +1 -0
  140. package/dist/lib/pdf-import.js +397 -0
  141. package/dist/lib/pdf-import.js.map +1 -0
  142. package/dist/lib/plugins.d.ts +76 -0
  143. package/dist/lib/plugins.d.ts.map +1 -0
  144. package/dist/lib/plugins.js +235 -0
  145. package/dist/lib/plugins.js.map +1 -0
  146. package/dist/lib/postprocess.d.ts +42 -0
  147. package/dist/lib/postprocess.d.ts.map +1 -0
  148. package/dist/lib/postprocess.js +138 -0
  149. package/dist/lib/postprocess.js.map +1 -0
  150. package/dist/lib/pptx-template.d.ts +59 -0
  151. package/dist/lib/pptx-template.d.ts.map +1 -0
  152. package/dist/lib/pptx-template.js +613 -0
  153. package/dist/lib/pptx-template.js.map +1 -0
  154. package/dist/lib/pptx-themes.d.ts +80 -0
  155. package/dist/lib/pptx-themes.d.ts.map +1 -0
  156. package/dist/lib/pptx-themes.js +818 -0
  157. package/dist/lib/pptx-themes.js.map +1 -0
  158. package/dist/lib/protect-restore.d.ts +137 -0
  159. package/dist/lib/protect-restore.d.ts.map +1 -0
  160. package/dist/lib/protect-restore.js +394 -0
  161. package/dist/lib/protect-restore.js.map +1 -0
  162. package/dist/lib/rate-limiter.d.ts +27 -0
  163. package/dist/lib/rate-limiter.d.ts.map +1 -0
  164. package/dist/lib/rate-limiter.js +79 -0
  165. package/dist/lib/rate-limiter.js.map +1 -0
  166. package/dist/lib/response.d.ts +41 -0
  167. package/dist/lib/response.d.ts.map +1 -0
  168. package/dist/lib/response.js +150 -0
  169. package/dist/lib/response.js.map +1 -0
  170. package/dist/lib/review.d.ts +35 -0
  171. package/dist/lib/review.d.ts.map +1 -0
  172. package/dist/lib/review.js +263 -0
  173. package/dist/lib/review.js.map +1 -0
  174. package/dist/lib/schema.d.ts +66 -0
  175. package/dist/lib/schema.d.ts.map +1 -0
  176. package/dist/lib/schema.js +339 -0
  177. package/dist/lib/schema.js.map +1 -0
  178. package/dist/lib/scientific-words.d.ts +6 -0
  179. package/dist/lib/scientific-words.d.ts.map +1 -0
  180. package/dist/lib/scientific-words.js +66 -0
  181. package/dist/lib/scientific-words.js.map +1 -0
  182. package/dist/lib/sections.d.ts +40 -0
  183. package/dist/lib/sections.d.ts.map +1 -0
  184. package/dist/lib/sections.js +288 -0
  185. package/dist/lib/sections.js.map +1 -0
  186. package/dist/lib/slides.d.ts +86 -0
  187. package/dist/lib/slides.d.ts.map +1 -0
  188. package/dist/lib/slides.js +676 -0
  189. package/dist/lib/slides.js.map +1 -0
  190. package/dist/lib/spelling.d.ts +76 -0
  191. package/dist/lib/spelling.d.ts.map +1 -0
  192. package/dist/lib/spelling.js +272 -0
  193. package/dist/lib/spelling.js.map +1 -0
  194. package/dist/lib/templates.d.ts +30 -0
  195. package/dist/lib/templates.d.ts.map +1 -0
  196. package/dist/lib/templates.js +504 -0
  197. package/dist/lib/templates.js.map +1 -0
  198. package/dist/lib/themes.d.ts +85 -0
  199. package/dist/lib/themes.d.ts.map +1 -0
  200. package/dist/lib/themes.js +652 -0
  201. package/dist/lib/themes.js.map +1 -0
  202. package/dist/lib/trackchanges.d.ts +51 -0
  203. package/dist/lib/trackchanges.d.ts.map +1 -0
  204. package/dist/lib/trackchanges.js +202 -0
  205. package/dist/lib/trackchanges.js.map +1 -0
  206. package/dist/lib/tui.d.ts +76 -0
  207. package/dist/lib/tui.d.ts.map +1 -0
  208. package/dist/lib/tui.js +377 -0
  209. package/dist/lib/tui.js.map +1 -0
  210. package/dist/lib/types.d.ts +447 -0
  211. package/dist/lib/types.d.ts.map +1 -0
  212. package/dist/lib/types.js +6 -0
  213. package/dist/lib/types.js.map +1 -0
  214. package/dist/lib/undo.d.ts +57 -0
  215. package/dist/lib/undo.d.ts.map +1 -0
  216. package/dist/lib/undo.js +185 -0
  217. package/dist/lib/undo.js.map +1 -0
  218. package/dist/lib/utils.d.ts +16 -0
  219. package/dist/lib/utils.d.ts.map +1 -0
  220. package/dist/lib/utils.js +40 -0
  221. package/dist/lib/utils.js.map +1 -0
  222. package/dist/lib/variables.d.ts +42 -0
  223. package/dist/lib/variables.d.ts.map +1 -0
  224. package/dist/lib/variables.js +141 -0
  225. package/dist/lib/variables.js.map +1 -0
  226. package/dist/lib/word.d.ts +80 -0
  227. package/dist/lib/word.d.ts.map +1 -0
  228. package/dist/lib/word.js +360 -0
  229. package/dist/lib/word.js.map +1 -0
  230. package/dist/lib/wordcomments.d.ts +51 -0
  231. package/dist/lib/wordcomments.d.ts.map +1 -0
  232. package/dist/lib/wordcomments.js +587 -0
  233. package/dist/lib/wordcomments.js.map +1 -0
  234. package/eslint.config.js +27 -0
  235. package/lib/annotations.ts +622 -0
  236. package/lib/apply-buildup-colors.py +88 -0
  237. package/lib/build.ts +1013 -0
  238. package/lib/{citations.js → citations.ts} +38 -27
  239. package/lib/commands/{build.js → build.ts} +80 -27
  240. package/lib/commands/{citations.js → citations.ts} +36 -18
  241. package/lib/commands/{comments.js → comments.ts} +187 -54
  242. package/lib/commands/{context.js → context.ts} +18 -8
  243. package/lib/commands/{core.js → core.ts} +34 -20
  244. package/lib/commands/{doi.js → doi.ts} +32 -16
  245. package/lib/commands/{history.js → history.ts} +25 -12
  246. package/lib/commands/{index.js → index.ts} +9 -5
  247. package/lib/commands/{init.js → init.ts} +20 -8
  248. package/lib/commands/{response.js → response.ts} +47 -20
  249. package/lib/commands/{sections.js → sections.ts} +273 -68
  250. package/lib/commands/{utilities.js → utilities.ts} +338 -158
  251. package/lib/{comment-realign.js → comment-realign.ts} +117 -45
  252. package/lib/config.ts +84 -0
  253. package/lib/{crossref.js → crossref.ts} +213 -138
  254. package/lib/dependencies.ts +106 -0
  255. package/lib/doi-cache.ts +115 -0
  256. package/lib/{doi.js → doi.ts} +115 -281
  257. package/lib/{equations.js → equations.ts} +60 -64
  258. package/lib/{errors.js → errors.ts} +56 -48
  259. package/lib/{format.js → format.ts} +137 -63
  260. package/lib/{git.js → git.ts} +66 -63
  261. package/lib/{grammar.js → grammar.ts} +45 -32
  262. package/lib/image-registry.ts +180 -0
  263. package/lib/import.ts +2060 -0
  264. package/lib/journals.ts +505 -0
  265. package/lib/{merge.js → merge.ts} +185 -135
  266. package/lib/{orcid.js → orcid.ts} +17 -22
  267. package/lib/{pdf-comments.js → pdf-comments.ts} +76 -18
  268. package/lib/{pdf-import.js → pdf-import.ts} +148 -70
  269. package/lib/{plugins.js → plugins.ts} +82 -39
  270. package/lib/postprocess.ts +188 -0
  271. package/lib/pptx-color-filter.lua +37 -0
  272. package/lib/pptx-template.ts +625 -0
  273. package/lib/pptx-themes/academic.pptx +0 -0
  274. package/lib/pptx-themes/corporate.pptx +0 -0
  275. package/lib/pptx-themes/dark.pptx +0 -0
  276. package/lib/pptx-themes/default.pptx +0 -0
  277. package/lib/pptx-themes/minimal.pptx +0 -0
  278. package/lib/pptx-themes/plant.pptx +0 -0
  279. package/lib/pptx-themes.ts +896 -0
  280. package/lib/protect-restore.ts +516 -0
  281. package/lib/rate-limiter.ts +94 -0
  282. package/lib/{response.js → response.ts} +36 -21
  283. package/lib/{review.js → review.ts} +53 -43
  284. package/lib/{schema.js → schema.ts} +70 -25
  285. package/lib/{sections.js → sections.ts} +71 -76
  286. package/lib/slides.ts +793 -0
  287. package/lib/{spelling.js → spelling.ts} +43 -59
  288. package/lib/{templates.js → templates.ts} +20 -17
  289. package/lib/themes.ts +742 -0
  290. package/lib/{trackchanges.js → trackchanges.ts} +52 -23
  291. package/lib/types.ts +509 -0
  292. package/lib/{undo.js → undo.ts} +75 -52
  293. package/lib/utils.ts +41 -0
  294. package/lib/{variables.js → variables.ts} +60 -54
  295. package/lib/word.ts +428 -0
  296. package/lib/{wordcomments.js → wordcomments.ts} +94 -40
  297. package/package.json +15 -5
  298. package/skill/REFERENCE.md +67 -0
  299. package/tsconfig.json +26 -0
  300. package/lib/annotations.js +0 -414
  301. package/lib/build.js +0 -639
  302. package/lib/config.js +0 -79
  303. package/lib/import.js +0 -1145
  304. package/lib/journals.js +0 -629
  305. package/lib/word.js +0 -225
  306. /package/lib/{scientific-words.js → scientific-words.ts} +0 -0
@@ -0,0 +1,360 @@
1
+ /**
2
+ * Word document extraction utilities
3
+ * Handle reading text, comments, and anchors from .docx files
4
+ */
5
+ import * as fs from 'fs';
6
+ import AdmZip from 'adm-zip';
7
+ import { parseString } from 'xml2js';
8
+ import { promisify } from 'util';
9
+ const parseXml = promisify(parseString);
10
+ // =============================================================================
11
+ // Constants
12
+ // =============================================================================
13
+ /** Characters of context to extract around comment anchors */
14
+ const ANCHOR_CONTEXT_SIZE = 100;
15
+ /** Characters of context before comment range start */
16
+ const CONTEXT_BEFORE_SIZE = 500;
17
+ // =============================================================================
18
+ // Public API
19
+ // =============================================================================
20
+ /**
21
+ * Extract comments from Word document's comments.xml
22
+ * @param docxPath - Path to .docx file
23
+ * @returns Array of extracted comments
24
+ * @throws {TypeError} If docxPath is not a string
25
+ * @throws {Error} If file not found or invalid docx
26
+ */
27
+ export async function extractWordComments(docxPath) {
28
+ if (typeof docxPath !== 'string') {
29
+ throw new TypeError(`docxPath must be a string, got ${typeof docxPath}`);
30
+ }
31
+ if (!fs.existsSync(docxPath)) {
32
+ throw new Error(`File not found: ${docxPath}`);
33
+ }
34
+ const zip = new AdmZip(docxPath);
35
+ const commentsEntry = zip.getEntry('word/comments.xml');
36
+ if (!commentsEntry) {
37
+ return []; // No comments in document
38
+ }
39
+ const commentsXml = zip.readAsText(commentsEntry);
40
+ const parsed = await parseXml(commentsXml);
41
+ if (!parsed?.['w:comments'] || !parsed['w:comments']['w:comment']) {
42
+ return [];
43
+ }
44
+ const comments = [];
45
+ const rawComments = parsed['w:comments']['w:comment'];
46
+ for (const comment of rawComments) {
47
+ const id = comment.$?.['w:id'];
48
+ const author = comment.$?.['w:author'] || 'Unknown';
49
+ const date = comment.$?.['w:date'];
50
+ // Extract text from all paragraphs in comment
51
+ let text = '';
52
+ const paragraphs = comment['w:p'] || [];
53
+ for (const para of paragraphs) {
54
+ const runs = para['w:r'] || [];
55
+ for (const run of runs) {
56
+ const texts = run['w:t'] || [];
57
+ for (const t of texts) {
58
+ text += typeof t === 'string' ? t : (t._ || '');
59
+ }
60
+ }
61
+ }
62
+ if (id && text.trim()) {
63
+ comments.push({
64
+ id,
65
+ author,
66
+ date,
67
+ text: text.trim(),
68
+ });
69
+ }
70
+ }
71
+ return comments;
72
+ }
73
+ /**
74
+ * Extract comment anchors (where comments are attached) from document.xml
75
+ * Returns mapping of comment ID to the text they're anchored to
76
+ * @param docxPath - Path to .docx file
77
+ * @returns Map of comment ID to anchor info
78
+ * @throws {TypeError} If docxPath is not a string
79
+ * @throws {Error} If invalid docx structure
80
+ */
81
+ export async function extractCommentAnchors(docxPath) {
82
+ if (typeof docxPath !== 'string') {
83
+ throw new TypeError(`docxPath must be a string, got ${typeof docxPath}`);
84
+ }
85
+ const zip = new AdmZip(docxPath);
86
+ const documentEntry = zip.getEntry('word/document.xml');
87
+ if (!documentEntry) {
88
+ throw new Error('Invalid docx: no document.xml');
89
+ }
90
+ const documentXml = zip.readAsText(documentEntry);
91
+ const anchors = new Map();
92
+ // Find commentRangeStart and commentRangeEnd pairs
93
+ // The text between them is what the comment is anchored to
94
+ const startPattern = /<w:commentRangeStart w:id="(\d+)"\/>/g;
95
+ const endPattern = /<w:commentRangeEnd w:id="(\d+)"\/>/g;
96
+ let match;
97
+ const starts = new Map();
98
+ const ends = new Map();
99
+ while ((match = startPattern.exec(documentXml)) !== null) {
100
+ if (match[1]) {
101
+ starts.set(match[1], match.index);
102
+ }
103
+ }
104
+ while ((match = endPattern.exec(documentXml)) !== null) {
105
+ if (match[1]) {
106
+ ends.set(match[1], match.index);
107
+ }
108
+ }
109
+ // For each comment, extract the text between start and end
110
+ for (const [id, startPos] of starts) {
111
+ const endPos = ends.get(id);
112
+ if (!endPos)
113
+ continue;
114
+ const segment = documentXml.slice(startPos, endPos);
115
+ // Extract all text content from the segment
116
+ const textPattern = /<w:t[^>]*>([^<]*)<\/w:t>/g;
117
+ let text = '';
118
+ let textMatch;
119
+ while ((textMatch = textPattern.exec(segment)) !== null) {
120
+ text += textMatch[1] ?? '';
121
+ }
122
+ // Get surrounding context (text before the anchor)
123
+ const contextStart = Math.max(0, startPos - CONTEXT_BEFORE_SIZE);
124
+ const contextSegment = documentXml.slice(contextStart, startPos);
125
+ let context = '';
126
+ while ((textMatch = textPattern.exec(contextSegment)) !== null) {
127
+ context += textMatch[1] ?? '';
128
+ }
129
+ anchors.set(id, {
130
+ text: text.trim(),
131
+ context: context.slice(-ANCHOR_CONTEXT_SIZE),
132
+ });
133
+ }
134
+ return anchors;
135
+ }
136
+ /**
137
+ * Extract plain text from Word document using mammoth
138
+ * @param docxPath - Path to .docx file
139
+ * @returns Extracted plain text
140
+ * @throws {TypeError} If docxPath is not a string
141
+ * @throws {Error} If file not found
142
+ */
143
+ export async function extractTextFromWord(docxPath) {
144
+ if (typeof docxPath !== 'string') {
145
+ throw new TypeError(`docxPath must be a string, got ${typeof docxPath}`);
146
+ }
147
+ if (!fs.existsSync(docxPath)) {
148
+ throw new Error(`File not found: ${docxPath}`);
149
+ }
150
+ const mammoth = await import('mammoth');
151
+ const result = await mammoth.extractRawText({ path: docxPath });
152
+ return result.value;
153
+ }
154
+ /**
155
+ * Extract rich content from Word with basic formatting
156
+ * @param docxPath - Path to .docx file
157
+ * @returns Text and HTML content
158
+ * @throws {TypeError} If docxPath is not a string
159
+ * @throws {Error} If file not found
160
+ */
161
+ export async function extractFromWord(docxPath) {
162
+ if (typeof docxPath !== 'string') {
163
+ throw new TypeError(`docxPath must be a string, got ${typeof docxPath}`);
164
+ }
165
+ if (!fs.existsSync(docxPath)) {
166
+ throw new Error(`File not found: ${docxPath}`);
167
+ }
168
+ const mammoth = await import('mammoth');
169
+ const [textResult, htmlResult] = await Promise.all([
170
+ mammoth.extractRawText({ path: docxPath }),
171
+ mammoth.convertToHtml({ path: docxPath }),
172
+ ]);
173
+ return {
174
+ text: textResult.value,
175
+ html: htmlResult.value,
176
+ };
177
+ }
178
+ /**
179
+ * Get document metadata from Word file
180
+ * @param docxPath - Path to .docx file
181
+ * @returns Document metadata
182
+ * @throws {TypeError} If docxPath is not a string
183
+ */
184
+ export async function getWordMetadata(docxPath) {
185
+ if (typeof docxPath !== 'string') {
186
+ throw new TypeError(`docxPath must be a string, got ${typeof docxPath}`);
187
+ }
188
+ const zip = new AdmZip(docxPath);
189
+ const coreEntry = zip.getEntry('docProps/core.xml');
190
+ if (!coreEntry) {
191
+ return {};
192
+ }
193
+ const coreXml = zip.readAsText(coreEntry);
194
+ const metadata = {};
195
+ // Extract common metadata fields
196
+ const patterns = {
197
+ title: /<dc:title>([^<]*)<\/dc:title>/,
198
+ author: /<dc:creator>([^<]*)<\/dc:creator>/,
199
+ created: /<dcterms:created[^>]*>([^<]*)<\/dcterms:created>/,
200
+ modified: /<dcterms:modified[^>]*>([^<]*)<\/dcterms:modified>/,
201
+ };
202
+ for (const [key, pattern] of Object.entries(patterns)) {
203
+ const match = coreXml.match(pattern);
204
+ if (match) {
205
+ metadata[key] = match[1];
206
+ }
207
+ }
208
+ return metadata;
209
+ }
210
+ /**
211
+ * Check if file is a valid Word document
212
+ * @param filePath - Path to file to check
213
+ * @returns True if valid .docx file
214
+ */
215
+ export function isWordDocument(filePath) {
216
+ if (typeof filePath !== 'string')
217
+ return false;
218
+ if (!fs.existsSync(filePath))
219
+ return false;
220
+ if (!filePath.toLowerCase().endsWith('.docx'))
221
+ return false;
222
+ try {
223
+ const zip = new AdmZip(filePath);
224
+ return zip.getEntry('word/document.xml') !== null;
225
+ }
226
+ catch {
227
+ return false;
228
+ }
229
+ }
230
+ /**
231
+ * Extract text content from XML element, handling nested elements
232
+ * @param xml - XML string
233
+ * @returns Plain text content
234
+ */
235
+ function extractTextFromXml(xml) {
236
+ let text = '';
237
+ // Match w:t elements (regular text)
238
+ const textPattern = /<w:t[^>]*>([^<]*)<\/w:t>/g;
239
+ let match;
240
+ while ((match = textPattern.exec(xml)) !== null) {
241
+ text += match[1];
242
+ }
243
+ // Also match w:delText (deleted text)
244
+ const delTextPattern = /<w:delText[^>]*>([^<]*)<\/w:delText>/g;
245
+ while ((match = delTextPattern.exec(xml)) !== null) {
246
+ text += match[1];
247
+ }
248
+ return text;
249
+ }
250
+ /**
251
+ * Extract track changes (insertions and deletions) from Word document
252
+ * Converts Word's w:ins and w:del elements to CriticMarkup format
253
+ *
254
+ * @param docxPath - Path to Word document
255
+ * @returns Track changes result with content and stats
256
+ */
257
+ export async function extractTrackChanges(docxPath) {
258
+ if (!fs.existsSync(docxPath)) {
259
+ throw new Error(`File not found: ${docxPath}`);
260
+ }
261
+ const zip = new AdmZip(docxPath);
262
+ const documentEntry = zip.getEntry('word/document.xml');
263
+ if (!documentEntry) {
264
+ throw new Error('Invalid docx: no document.xml');
265
+ }
266
+ let xml = zip.readAsText(documentEntry);
267
+ let insertions = 0;
268
+ let deletions = 0;
269
+ // Check if there are any track changes
270
+ const hasInsertions = xml.includes('<w:ins ');
271
+ const hasDeletions = xml.includes('<w:del ');
272
+ if (!hasInsertions && !hasDeletions) {
273
+ return { hasTrackChanges: false, content: null, stats: { insertions: 0, deletions: 0 } };
274
+ }
275
+ // Process insertions: <w:ins ...>...</w:ins> -> {++...++}
276
+ // Match the full w:ins element including nested content
277
+ xml = xml.replace(/<w:ins\b[^>]*>([\s\S]*?)<\/w:ins>/g, (match, content) => {
278
+ const text = extractTextFromXml(content);
279
+ if (text.trim()) {
280
+ insertions++;
281
+ return `{++${text}++}`;
282
+ }
283
+ return text;
284
+ });
285
+ // Process deletions: <w:del ...>...</w:del> -> {--...--}
286
+ xml = xml.replace(/<w:del\b[^>]*>([\s\S]*?)<\/w:del>/g, (match, content) => {
287
+ const text = extractTextFromXml(content);
288
+ if (text.trim()) {
289
+ deletions++;
290
+ return `{--${text}--}`;
291
+ }
292
+ return '';
293
+ });
294
+ return {
295
+ hasTrackChanges: true,
296
+ content: xml,
297
+ stats: { insertions, deletions },
298
+ };
299
+ }
300
+ /**
301
+ * Extract Word document content with track changes preserved as CriticMarkup
302
+ * Uses pandoc with track-changes=all option to preserve insertions/deletions
303
+ *
304
+ * @param docxPath - Path to Word document
305
+ * @param options - Options
306
+ * @returns Track changes result with text and stats
307
+ */
308
+ export async function extractWithTrackChanges(docxPath, options = {}) {
309
+ const { mediaDir } = options;
310
+ if (!fs.existsSync(docxPath)) {
311
+ throw new Error(`File not found: ${docxPath}`);
312
+ }
313
+ const { execSync } = await import('child_process');
314
+ // Use pandoc with --track-changes=all to preserve track changes
315
+ // This outputs insertions as [insertion]{.insertion} and deletions as [deletion]{.deletion}
316
+ let pandocArgs = `"${docxPath}" -t markdown --wrap=none --track-changes=all`;
317
+ if (mediaDir) {
318
+ pandocArgs += ` --extract-media="${mediaDir}"`;
319
+ }
320
+ let text;
321
+ try {
322
+ text = execSync(`pandoc ${pandocArgs}`, {
323
+ encoding: 'utf-8',
324
+ maxBuffer: 50 * 1024 * 1024,
325
+ });
326
+ }
327
+ catch (err) {
328
+ throw new Error(`Pandoc extraction failed: ${err.message}`);
329
+ }
330
+ // Count track changes from pandoc output
331
+ let insertions = 0;
332
+ let deletions = 0;
333
+ // Pandoc outputs track changes as:
334
+ // [inserted text]{.insertion author="..."}
335
+ // [deleted text]{.deletion author="..."}
336
+ // Convert pandoc's track change format to CriticMarkup
337
+ // Insertions: [text]{.insertion ...} -> {++text++}
338
+ text = text.replace(/\[([^\]]*)\]\{\.insertion[^}]*\}/g, (match, content) => {
339
+ if (content.trim()) {
340
+ insertions++;
341
+ return `{++${content}++}`;
342
+ }
343
+ return '';
344
+ });
345
+ // Deletions: [text]{.deletion ...} -> {--text--}
346
+ text = text.replace(/\[([^\]]*)\]\{\.deletion[^}]*\}/g, (match, content) => {
347
+ if (content.trim()) {
348
+ deletions++;
349
+ return `{--${content}--}`;
350
+ }
351
+ return '';
352
+ });
353
+ const hasTrackChanges = insertions > 0 || deletions > 0;
354
+ return {
355
+ text,
356
+ hasTrackChanges,
357
+ stats: { insertions, deletions },
358
+ };
359
+ }
360
+ //# sourceMappingURL=word.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"word.js","sourceRoot":"","sources":["../../lib/word.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Word comment injection with reply threading
3
+ *
4
+ * Flow:
5
+ * 1. prepareMarkdownWithMarkers() - Parse comments, detect reply relationships
6
+ * - First comment in a cluster = parent (gets markers: ⟦CMS:n⟧anchor⟦CME:n⟧)
7
+ * - Subsequent adjacent comments = replies (no markers, attach to parent)
8
+ * 2. Pandoc converts to DOCX
9
+ * 3. injectCommentsAtMarkers() - Insert comment ranges for parents only
10
+ * - Replies go in comments.xml with parent reference in commentsExtended.xml
11
+ */
12
+ interface ParsedComment {
13
+ author: string;
14
+ text: string;
15
+ anchor: string | null;
16
+ start: number;
17
+ end: number;
18
+ fullMatch: string;
19
+ }
20
+ interface PreparedComment extends ParsedComment {
21
+ isReply: boolean;
22
+ parentIdx: number | null;
23
+ commentIdx: number;
24
+ anchorFromReply?: boolean;
25
+ placesParentMarkers?: boolean;
26
+ }
27
+ interface PrepareResult {
28
+ markedMarkdown: string;
29
+ comments: PreparedComment[];
30
+ }
31
+ interface InjectionResult {
32
+ success: boolean;
33
+ commentCount: number;
34
+ replyCount?: number;
35
+ skippedComments: number;
36
+ error?: string;
37
+ }
38
+ /**
39
+ * Parse comments and create markers
40
+ *
41
+ * Returns:
42
+ * - markedMarkdown: markdown with markers for parent comments only
43
+ * - comments: array with author, text, isReply, parentIdx
44
+ */
45
+ export declare function prepareMarkdownWithMarkers(markdown: string): PrepareResult;
46
+ /**
47
+ * Inject comments at marker positions
48
+ */
49
+ export declare function injectCommentsAtMarkers(docxPath: string, comments: PreparedComment[], outputPath: string): Promise<InjectionResult>;
50
+ export {};
51
+ //# sourceMappingURL=wordcomments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordcomments.d.ts","sourceRoot":"","sources":["../../lib/wordcomments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,eAAgB,SAAQ,aAAa;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,UAAU,aAAa;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAUD,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmBD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAuJ1E;AA4ID;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,eAAe,EAAE,EAC3B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAwU1B"}