docrev 0.8.1 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +33 -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
@@ -5,14 +5,67 @@
5
5
 
6
6
  import chalk from 'chalk';
7
7
 
8
+ // Type definitions for function parameters
9
+ interface TableOptions {
10
+ align?: Array<'left' | 'right' | 'center'>;
11
+ headerStyle?: (text: string) => string;
12
+ borderStyle?: (text: string) => string;
13
+ cellStyle?: ((value: string, colIndex: number, rowIndex: number) => string) | null;
14
+ }
15
+
16
+ interface SimpleTableOptions {
17
+ headerStyle?: (text: string) => string;
18
+ indent?: string;
19
+ }
20
+
21
+ interface BoxOptions {
22
+ title?: string | null;
23
+ padding?: number;
24
+ borderStyle?: (text: string) => string;
25
+ titleStyle?: (text: string) => string;
26
+ }
27
+
28
+ interface StatsOptions {
29
+ title?: string | null;
30
+ }
31
+
32
+ interface ProgressOptions {
33
+ width?: number;
34
+ label?: string;
35
+ }
36
+
37
+ interface InlineDiffPreviewOptions {
38
+ maxLines?: number;
39
+ contextChars?: number;
40
+ }
41
+
42
+ interface HeaderOptions {
43
+ style?: (text: string) => string;
44
+ width?: number;
45
+ }
46
+
47
+ interface Spinner {
48
+ text: string;
49
+ start: () => Spinner;
50
+ stop: (finalMessage?: string | null) => Spinner;
51
+ success: (msg?: string) => Spinner;
52
+ error: (msg?: string) => Spinner;
53
+ }
54
+
55
+ interface ProgressBar {
56
+ update: (n: number) => ProgressBar;
57
+ increment: () => ProgressBar;
58
+ done: (message?: string) => ProgressBar;
59
+ }
60
+
8
61
  /**
9
62
  * Format a table with borders and alignment
10
- * @param {string[]} headers - Column headers
11
- * @param {string[][]} rows - Row data
12
- * @param {object} options - Formatting options
13
- * @returns {string}
63
+ * @param headers - Column headers
64
+ * @param rows - Row data
65
+ * @param options - Formatting options
66
+ * @returns Formatted table string
14
67
  */
15
- export function table(headers, rows, options = {}) {
68
+ export function table(headers: string[], rows: string[][], options: TableOptions = {}): string {
16
69
  const {
17
70
  align = headers.map(() => 'left'), // 'left', 'right', 'center'
18
71
  headerStyle = chalk.bold.cyan,
@@ -22,8 +75,8 @@ export function table(headers, rows, options = {}) {
22
75
 
23
76
  // Calculate column widths
24
77
  const widths = headers.map((h, i) => {
25
- const cellWidths = rows.map(row => stripAnsi(String(row[i] || '')).length);
26
- return Math.max(stripAnsi(h).length, ...cellWidths);
78
+ const cellWidths = rows.map(row => stripAnsi(String(row[i] || '')));
79
+ return Math.max(stripAnsi(h), ...cellWidths);
27
80
  });
28
81
 
29
82
  // Border characters
@@ -34,7 +87,7 @@ export function table(headers, rows, options = {}) {
34
87
  };
35
88
 
36
89
  // Build lines
37
- const lines = [];
90
+ const lines: string[] = [];
38
91
 
39
92
  // Top border
40
93
  const topBorder = border.topLeft +
@@ -44,10 +97,10 @@ export function table(headers, rows, options = {}) {
44
97
 
45
98
  // Header row
46
99
  const headerRow = border.vertical +
47
- headers.map((h, i) => ' ' + pad(headerStyle(h), widths[i], align[i]) + ' ').join(border.vertical) +
100
+ headers.map((h, i) => ' ' + pad(headerStyle(h), widths[i] || 0, align[i] || 'left') + ' ').join(border.vertical) +
48
101
  border.vertical;
49
102
  lines.push(borderStyle(border.vertical) +
50
- headers.map((h, i) => ' ' + pad(headerStyle(h), widths[i], align[i], stripAnsi(h).length) + ' ').join(borderStyle(border.vertical)) +
103
+ headers.map((h, i) => ' ' + pad(headerStyle(h), widths[i] || 0, align[i] || 'left', stripAnsi(h)) + ' ').join(borderStyle(border.vertical)) +
51
104
  borderStyle(border.vertical));
52
105
 
53
106
  // Header separator
@@ -59,13 +112,14 @@ export function table(headers, rows, options = {}) {
59
112
  // Data rows
60
113
  for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
61
114
  const row = rows[rowIdx];
115
+ if (!row) continue;
62
116
  const cells = row.map((cell, colIdx) => {
63
117
  let value = String(cell || '');
64
118
  if (cellStyle) {
65
119
  value = cellStyle(value, colIdx, rowIdx);
66
120
  }
67
- const plainLen = stripAnsi(String(cell || '')).length;
68
- return ' ' + pad(value, widths[colIdx], align[colIdx], plainLen) + ' ';
121
+ const plainLen = stripAnsi(String(cell || ''));
122
+ return ' ' + pad(value, widths[colIdx] || 0, align[colIdx] || 'left', plainLen) + ' ';
69
123
  });
70
124
  lines.push(borderStyle(border.vertical) + cells.join(borderStyle(border.vertical)) + borderStyle(border.vertical));
71
125
  }
@@ -82,20 +136,20 @@ export function table(headers, rows, options = {}) {
82
136
  /**
83
137
  * Simple table without borders (compact)
84
138
  */
85
- export function simpleTable(headers, rows, options = {}) {
139
+ export function simpleTable(headers: string[], rows: string[][], options: SimpleTableOptions = {}): string {
86
140
  const { headerStyle = chalk.dim, indent = ' ' } = options;
87
141
 
88
142
  const widths = headers.map((h, i) => {
89
- const cellWidths = rows.map(row => stripAnsi(String(row[i] || '')).length);
90
- return Math.max(stripAnsi(h).length, ...cellWidths);
143
+ const cellWidths = rows.map(row => stripAnsi(String(row[i] || '')));
144
+ return Math.max(stripAnsi(h), ...cellWidths);
91
145
  });
92
146
 
93
- const lines = [];
94
- lines.push(indent + headers.map((h, i) => headerStyle(pad(h, widths[i], 'left'))).join(' '));
147
+ const lines: string[] = [];
148
+ lines.push(indent + headers.map((h, i) => headerStyle(pad(h, widths[i] || 0, 'left'))).join(' '));
95
149
  lines.push(indent + widths.map(w => chalk.dim('─'.repeat(w))).join(' '));
96
150
 
97
151
  for (const row of rows) {
98
- lines.push(indent + row.map((cell, i) => pad(String(cell || ''), widths[i], 'left')).join(' '));
152
+ lines.push(indent + row.map((cell, i) => pad(String(cell || ''), widths[i] || 0, 'left')).join(' '));
99
153
  }
100
154
 
101
155
  return lines.join('\n');
@@ -104,7 +158,7 @@ export function simpleTable(headers, rows, options = {}) {
104
158
  /**
105
159
  * Format a box around content
106
160
  */
107
- export function box(content, options = {}) {
161
+ export function box(content: string, options: BoxOptions = {}): string {
108
162
  const {
109
163
  title = null,
110
164
  padding = 1,
@@ -113,15 +167,15 @@ export function box(content, options = {}) {
113
167
  } = options;
114
168
 
115
169
  const lines = content.split('\n');
116
- const maxWidth = Math.max(...lines.map(l => stripAnsi(l).length), title ? stripAnsi(title).length + 4 : 0);
170
+ const maxWidth = Math.max(...lines.map(l => stripAnsi(l)), title ? stripAnsi(title) + 4 : 0);
117
171
 
118
172
  const border = { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│' };
119
- const result = [];
173
+ const result: string[] = [];
120
174
 
121
175
  // Top border with optional title
122
176
  if (title) {
123
177
  const titlePart = ` ${titleStyle(title)} `;
124
- const remaining = maxWidth + 2 - stripAnsi(titlePart).length;
178
+ const remaining = maxWidth + 2 - stripAnsi(titlePart);
125
179
  result.push(borderStyle(border.tl + border.h) + titlePart + borderStyle(border.h.repeat(remaining) + border.tr));
126
180
  } else {
127
181
  result.push(borderStyle(border.tl + border.h.repeat(maxWidth + 2) + border.tr));
@@ -134,7 +188,7 @@ export function box(content, options = {}) {
134
188
 
135
189
  // Content
136
190
  for (const line of lines) {
137
- const plainLen = stripAnsi(line).length;
191
+ const plainLen = stripAnsi(line);
138
192
  const padded = line + ' '.repeat(maxWidth - plainLen);
139
193
  result.push(borderStyle(border.v) + ' ' + padded + ' ' + borderStyle(border.v));
140
194
  }
@@ -153,16 +207,17 @@ export function box(content, options = {}) {
153
207
  /**
154
208
  * Summary stats in a nice format
155
209
  */
156
- export function stats(data, options = {}) {
210
+ export function stats(data: Record<string, string | number>, options: StatsOptions = {}): string {
157
211
  const { title = null } = options;
158
212
 
159
- const lines = [];
213
+ const lines: string[] = [];
160
214
  if (title) {
161
215
  lines.push(chalk.bold.cyan(title));
162
216
  lines.push('');
163
217
  }
164
218
 
165
- const maxKeyLen = Math.max(...Object.keys(data).map(k => k.length));
219
+ const keys = Object.keys(data);
220
+ const maxKeyLen = keys.length > 0 ? Math.max(...keys.map(k => k.length)) : 0;
166
221
 
167
222
  for (const [key, value] of Object.entries(data)) {
168
223
  const label = chalk.dim(key.padEnd(maxKeyLen) + ':');
@@ -175,7 +230,7 @@ export function stats(data, options = {}) {
175
230
  /**
176
231
  * Progress indicator
177
232
  */
178
- export function progress(current, total, options = {}) {
233
+ export function progress(current: number, total: number, options: ProgressOptions = {}): string {
179
234
  const { width = 30, label = '' } = options;
180
235
  const pct = Math.round((current / total) * 100);
181
236
  const filled = Math.round((current / total) * width);
@@ -188,15 +243,15 @@ export function progress(current, total, options = {}) {
188
243
  // Global setting for emoji usage
189
244
  let useEmoji = false;
190
245
 
191
- export function setEmoji(enabled) {
246
+ export function setEmoji(enabled: boolean): void {
192
247
  useEmoji = enabled;
193
248
  }
194
249
 
195
250
  /**
196
251
  * Status line with icon
197
252
  */
198
- export function status(type, message) {
199
- const textIcons = {
253
+ export function status(type: string, message: string): string {
254
+ const textIcons: Record<string, string> = {
200
255
  success: chalk.green('✓'),
201
256
  error: chalk.red('✗'),
202
257
  warning: chalk.yellow('!'),
@@ -209,7 +264,7 @@ export function status(type, message) {
209
264
  export: chalk.cyan('>'),
210
265
  };
211
266
 
212
- const emojiIcons = {
267
+ const emojiIcons: Record<string, string> = {
213
268
  success: chalk.green('✓'),
214
269
  error: chalk.red('✗'),
215
270
  warning: chalk.yellow('⚠'),
@@ -246,21 +301,26 @@ const starColors = [
246
301
  /**
247
302
  * Create a pulsing star spinner for async operations
248
303
  */
249
- export function spinner(message) {
304
+ export function spinner(message: string): Spinner {
250
305
  let frameIndex = 0;
251
- let interval = null;
306
+ let interval: NodeJS.Timeout | null = null;
252
307
 
253
- const spin = {
308
+ const spin: Spinner = {
309
+ text: message,
254
310
  start() {
255
311
  process.stdout.write('\x1B[?25l'); // Hide cursor
256
312
  interval = setInterval(() => {
257
- const frame = starColors[frameIndex](starFrames[frameIndex]);
258
- process.stdout.write(`\r${frame} ${message}`);
313
+ const colorFn = starColors[frameIndex];
314
+ const frameChr = starFrames[frameIndex];
315
+ if (colorFn && frameChr) {
316
+ const frame = colorFn(frameChr);
317
+ process.stdout.write(`\r${frame} ${spin.text}`);
318
+ }
259
319
  frameIndex = (frameIndex + 1) % starFrames.length;
260
320
  }, 120);
261
321
  return spin;
262
322
  },
263
- stop(finalMessage = null) {
323
+ stop(finalMessage: string | null = null) {
264
324
  if (interval) {
265
325
  clearInterval(interval);
266
326
  interval = null;
@@ -272,10 +332,10 @@ export function spinner(message) {
272
332
  }
273
333
  return spin;
274
334
  },
275
- success(msg) {
335
+ success(msg?: string) {
276
336
  return spin.stop(status('success', msg || message));
277
337
  },
278
- error(msg) {
338
+ error(msg?: string) {
279
339
  return spin.stop(status('error', msg || message));
280
340
  },
281
341
  };
@@ -285,16 +345,16 @@ export function spinner(message) {
285
345
 
286
346
  /**
287
347
  * Create a progress bar for batch operations
288
- * @param {number} total - Total number of items
289
- * @param {string} label - Label for the progress bar
290
- * @returns {object} Progress bar controller with update(), increment(), and done()
348
+ * @param total - Total number of items
349
+ * @param label - Label for the progress bar
350
+ * @returns Progress bar controller with update(), increment(), and done()
291
351
  */
292
- export function progressBar(total, label = 'Progress') {
352
+ export function progressBar(total: number, label: string = 'Progress'): ProgressBar {
293
353
  let current = 0;
294
354
  const barWidth = 30;
295
355
 
296
- const bar = {
297
- update(n) {
356
+ const bar: ProgressBar = {
357
+ update(n: number) {
298
358
  current = Math.min(n, total);
299
359
  const percent = Math.floor((current / total) * 100);
300
360
  const filled = Math.floor((current / total) * barWidth);
@@ -307,7 +367,7 @@ export function progressBar(total, label = 'Progress') {
307
367
  increment() {
308
368
  return bar.update(current + 1);
309
369
  },
310
- done(message) {
370
+ done(message?: string) {
311
371
  process.stdout.write('\r\x1B[K'); // Clear line
312
372
  if (message) {
313
373
  console.log(status('success', message));
@@ -322,8 +382,8 @@ export function progressBar(total, label = 'Progress') {
322
382
  /**
323
383
  * Diff display with inline highlighting
324
384
  */
325
- export function diff(insertions, deletions, substitutions) {
326
- const lines = [];
385
+ export function diff(insertions: number, deletions: number, substitutions: number): string {
386
+ const lines: string[] = [];
327
387
 
328
388
  if (insertions > 0) {
329
389
  lines.push(chalk.green(` + ${insertions} insertion${insertions !== 1 ? 's' : ''}`));
@@ -340,20 +400,27 @@ export function diff(insertions, deletions, substitutions) {
340
400
 
341
401
  /**
342
402
  * Show inline diff preview for CriticMarkup changes
343
- * @param {string} text - Text with CriticMarkup annotations
344
- * @param {object} options
345
- * @returns {string}
403
+ * @param text - Text with CriticMarkup annotations
404
+ * @param options - Display options
405
+ * @returns Formatted preview string
346
406
  */
347
- export function inlineDiffPreview(text, options = {}) {
407
+ export function inlineDiffPreview(text: string, options: InlineDiffPreviewOptions = {}): string {
348
408
  const { maxLines = 10, contextChars = 40 } = options;
349
- const lines = [];
409
+ const lines: string[] = [];
350
410
 
351
411
  // Find all changes
352
- const changes = [];
412
+ const changes: Array<{
413
+ type: 'insert' | 'delete' | 'substitute';
414
+ content?: string;
415
+ oldContent?: string;
416
+ newContent?: string;
417
+ index: number;
418
+ fullMatch: string;
419
+ }> = [];
353
420
 
354
421
  // Insertions: {++text++}
355
422
  const insertPattern = /\{\+\+([^+]*)\+\+\}/g;
356
- let match;
423
+ let match: RegExpExecArray | null;
357
424
  while ((match = insertPattern.exec(text)) !== null) {
358
425
  changes.push({
359
426
  type: 'insert',
@@ -409,8 +476,8 @@ export function inlineDiffPreview(text, options = {}) {
409
476
  lines.push(chalk.red(' - ') + truncate(preview, 80));
410
477
  } else if (change.type === 'substitute') {
411
478
  preview = chalk.dim(before) +
412
- chalk.red.strikethrough(change.oldContent) +
413
- chalk.green.bold(change.newContent) +
479
+ chalk.red.strikethrough(change.oldContent || '') +
480
+ chalk.green.bold(change.newContent || '') +
414
481
  chalk.dim(after);
415
482
  lines.push(chalk.yellow(' ~ ') + truncate(preview, 80));
416
483
  }
@@ -426,8 +493,8 @@ export function inlineDiffPreview(text, options = {}) {
426
493
  /**
427
494
  * Truncate string to max length
428
495
  */
429
- function truncate(str, maxLen) {
430
- const plain = stripAnsi(str);
496
+ function truncate(str: string, maxLen: number): string {
497
+ const plain = stripAnsiStr(str);
431
498
  if (plain.length <= maxLen) return str;
432
499
  // This is approximate since we have ANSI codes
433
500
  return str.slice(0, maxLen + (str.length - plain.length)) + chalk.dim('...');
@@ -436,7 +503,7 @@ function truncate(str, maxLen) {
436
503
  /**
437
504
  * Section header
438
505
  */
439
- export function header(text, options = {}) {
506
+ export function header(text: string, options: HeaderOptions = {}): string {
440
507
  const { style = chalk.bold.cyan, width = 60 } = options;
441
508
  const padding = Math.max(0, width - text.length - 4);
442
509
  return style(`── ${text} ${'─'.repeat(padding)}`);
@@ -445,15 +512,22 @@ export function header(text, options = {}) {
445
512
  /**
446
513
  * Strip ANSI codes for length calculation
447
514
  */
448
- function stripAnsi(str) {
515
+ function stripAnsi(str: string): number {
516
+ return str.replace(/\x1b\[[0-9;]*m/g, '').length;
517
+ }
518
+
519
+ /**
520
+ * Strip ANSI codes and return string
521
+ */
522
+ function stripAnsiStr(str: string): string {
449
523
  return str.replace(/\x1b\[[0-9;]*m/g, '');
450
524
  }
451
525
 
452
526
  /**
453
527
  * Pad string with alignment
454
528
  */
455
- function pad(str, width, align, strLen = null) {
456
- const len = strLen !== null ? strLen : stripAnsi(str).length;
529
+ function pad(str: string, width: number, align: 'left' | 'right' | 'center', strLen: number | null = null): string {
530
+ const len = strLen !== null ? strLen : stripAnsi(str);
457
531
  const padding = Math.max(0, width - len);
458
532
 
459
533
  if (align === 'right') {