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
@@ -4,22 +4,66 @@
4
4
  * Provides undo/redo functionality during interactive sessions
5
5
  */
6
6
 
7
+ interface StackEntry {
8
+ state: string | object;
9
+ description: string;
10
+ timestamp: number;
11
+ }
12
+
13
+ interface HistoryEntry {
14
+ description: string;
15
+ current: boolean;
16
+ index: number;
17
+ }
18
+
19
+ interface StackInfo {
20
+ position: number;
21
+ size: number;
22
+ undoSteps: number;
23
+ redoSteps: number;
24
+ }
25
+
26
+ interface UndoStack {
27
+ push(state: string | object, description?: string): void;
28
+ undo(): StackEntry | null;
29
+ redo(): StackEntry | null;
30
+ current(): StackEntry | null;
31
+ canUndo(): boolean;
32
+ canRedo(): boolean;
33
+ info(): StackInfo;
34
+ history(limit?: number): HistoryEntry[];
35
+ clear(): void;
36
+ getStack(): StackEntry[];
37
+ }
38
+
39
+ interface DocumentChange {
40
+ text: string;
41
+ description: string;
42
+ }
43
+
44
+ interface DocumentSession {
45
+ getText(): string;
46
+ applyChange(newText: string, description: string): void;
47
+ undo(): DocumentChange | null;
48
+ redo(): DocumentChange | null;
49
+ canUndo(): boolean;
50
+ canRedo(): boolean;
51
+ info(): StackInfo;
52
+ history(limit?: number): HistoryEntry[];
53
+ }
54
+
7
55
  /**
8
56
  * Create an undo stack
9
- * @param {number} maxSize - Maximum number of states to store
10
- * @returns {object} Undo stack controller
11
57
  */
12
- export function createUndoStack(maxSize = 50) {
13
- const stack = [];
58
+ export function createUndoStack(maxSize: number = 50): UndoStack {
59
+ const stack: StackEntry[] = [];
14
60
  let position = -1;
15
61
 
16
62
  return {
17
63
  /**
18
64
  * Push a new state onto the stack
19
- * @param {any} state - State to save
20
- * @param {string} description - Description of the change
21
65
  */
22
- push(state, description = '') {
66
+ push(state: string | object, description: string = ''): void {
23
67
  // Remove any states after current position (for redo)
24
68
  if (position < stack.length - 1) {
25
69
  stack.splice(position + 1);
@@ -42,62 +86,56 @@ export function createUndoStack(maxSize = 50) {
42
86
 
43
87
  /**
44
88
  * Undo to previous state
45
- * @returns {{state: any, description: string}|null}
46
89
  */
47
- undo() {
90
+ undo(): StackEntry | null {
48
91
  if (position <= 0) {
49
92
  return null;
50
93
  }
51
94
 
52
95
  position--;
53
- return stack[position];
96
+ return stack[position] || null;
54
97
  },
55
98
 
56
99
  /**
57
100
  * Redo to next state
58
- * @returns {{state: any, description: string}|null}
59
101
  */
60
- redo() {
102
+ redo(): StackEntry | null {
61
103
  if (position >= stack.length - 1) {
62
104
  return null;
63
105
  }
64
106
 
65
107
  position++;
66
- return stack[position];
108
+ return stack[position] || null;
67
109
  },
68
110
 
69
111
  /**
70
112
  * Get current state
71
- * @returns {{state: any, description: string}|null}
72
113
  */
73
- current() {
114
+ current(): StackEntry | null {
74
115
  if (position < 0 || position >= stack.length) {
75
116
  return null;
76
117
  }
77
- return stack[position];
118
+ return stack[position] || null;
78
119
  },
79
120
 
80
121
  /**
81
122
  * Check if undo is available
82
- * @returns {boolean}
83
123
  */
84
- canUndo() {
124
+ canUndo(): boolean {
85
125
  return position > 0;
86
126
  },
87
127
 
88
128
  /**
89
129
  * Check if redo is available
90
- * @returns {boolean}
91
130
  */
92
- canRedo() {
131
+ canRedo(): boolean {
93
132
  return position < stack.length - 1;
94
133
  },
95
134
 
96
135
  /**
97
136
  * Get stack info
98
- * @returns {{position: number, size: number, undoSteps: number, redoSteps: number}}
99
137
  */
100
- info() {
138
+ info(): StackInfo {
101
139
  return {
102
140
  position,
103
141
  size: stack.length,
@@ -108,10 +146,8 @@ export function createUndoStack(maxSize = 50) {
108
146
 
109
147
  /**
110
148
  * Get history of changes
111
- * @param {number} limit - Max items to return
112
- * @returns {Array<{description: string, current: boolean, index: number}>}
113
149
  */
114
- history(limit = 10) {
150
+ history(limit: number = 10): HistoryEntry[] {
115
151
  const start = Math.max(0, position - Math.floor(limit / 2));
116
152
  const end = Math.min(stack.length, start + limit);
117
153
 
@@ -125,16 +161,15 @@ export function createUndoStack(maxSize = 50) {
125
161
  /**
126
162
  * Clear the stack
127
163
  */
128
- clear() {
164
+ clear(): void {
129
165
  stack.length = 0;
130
166
  position = -1;
131
167
  },
132
168
 
133
169
  /**
134
170
  * Get the full stack (for debugging)
135
- * @returns {Array}
136
171
  */
137
- getStack() {
172
+ getStack(): StackEntry[] {
138
173
  return [...stack];
139
174
  },
140
175
  };
@@ -142,10 +177,8 @@ export function createUndoStack(maxSize = 50) {
142
177
 
143
178
  /**
144
179
  * Create a document session with undo support
145
- * @param {string} initialText - Initial document text
146
- * @returns {object} Session controller
147
180
  */
148
- export function createDocumentSession(initialText) {
181
+ export function createDocumentSession(initialText: string): DocumentSession {
149
182
  const undoStack = createUndoStack();
150
183
 
151
184
  // Save initial state
@@ -154,31 +187,27 @@ export function createDocumentSession(initialText) {
154
187
  return {
155
188
  /**
156
189
  * Get current text
157
- * @returns {string}
158
190
  */
159
- getText() {
191
+ getText(): string {
160
192
  const current = undoStack.current();
161
- return current ? current.state : initialText;
193
+ return current ? current.state as string : initialText;
162
194
  },
163
195
 
164
196
  /**
165
197
  * Apply a change
166
- * @param {string} newText - New document text
167
- * @param {string} description - What changed
168
198
  */
169
- applyChange(newText, description) {
199
+ applyChange(newText: string, description: string): void {
170
200
  undoStack.push(newText, description);
171
201
  },
172
202
 
173
203
  /**
174
204
  * Undo last change
175
- * @returns {{text: string, description: string}|null}
176
205
  */
177
- undo() {
206
+ undo(): DocumentChange | null {
178
207
  const result = undoStack.undo();
179
208
  if (result) {
180
209
  return {
181
- text: result.state,
210
+ text: result.state as string,
182
211
  description: result.description,
183
212
  };
184
213
  }
@@ -187,13 +216,12 @@ export function createDocumentSession(initialText) {
187
216
 
188
217
  /**
189
218
  * Redo last undone change
190
- * @returns {{text: string, description: string}|null}
191
219
  */
192
- redo() {
220
+ redo(): DocumentChange | null {
193
221
  const result = undoStack.redo();
194
222
  if (result) {
195
223
  return {
196
- text: result.state,
224
+ text: result.state as string,
197
225
  description: result.description,
198
226
  };
199
227
  }
@@ -202,34 +230,29 @@ export function createDocumentSession(initialText) {
202
230
 
203
231
  /**
204
232
  * Check if undo is available
205
- * @returns {boolean}
206
233
  */
207
- canUndo() {
234
+ canUndo(): boolean {
208
235
  return undoStack.canUndo();
209
236
  },
210
237
 
211
238
  /**
212
239
  * Check if redo is available
213
- * @returns {boolean}
214
240
  */
215
- canRedo() {
241
+ canRedo(): boolean {
216
242
  return undoStack.canRedo();
217
243
  },
218
244
 
219
245
  /**
220
246
  * Get stack info
221
- * @returns {object}
222
247
  */
223
- info() {
248
+ info(): StackInfo {
224
249
  return undoStack.info();
225
250
  },
226
251
 
227
252
  /**
228
253
  * Get change history
229
- * @param {number} limit
230
- * @returns {Array}
231
254
  */
232
- history(limit = 10) {
255
+ history(limit: number = 10): HistoryEntry[] {
233
256
  return undoStack.history(limit);
234
257
  },
235
258
  };
package/lib/utils.ts ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared utility functions
3
+ */
4
+
5
+ /**
6
+ * Count words in text (excluding markdown syntax)
7
+ * @param text - Markdown text
8
+ * @returns Word count
9
+ */
10
+ export function countWords(text: string): number {
11
+ return text
12
+ .replace(/^---[\s\S]*?---/m, '') // Remove YAML frontmatter
13
+ .replace(/!\[.*?\]\(.*?\)/g, '') // Remove images
14
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Keep link text
15
+ .replace(/#+\s*/g, '') // Remove headers
16
+ .replace(/\*\*|__|[*_`]/g, '') // Remove formatting
17
+ .replace(/```[\s\S]*?```/g, '') // Remove code blocks
18
+ .replace(/\{[^}]+\}/g, '') // Remove CriticMarkup and attributes
19
+ .replace(/@\w+:\w+/g, '') // Remove cross-references
20
+ .replace(/@\w+/g, '') // Remove citations
21
+ .replace(/\|[^|]+\|/g, ' ') // Remove table cells
22
+ .replace(/[-=]{3,}/g, '') // Remove horizontal rules
23
+ .replace(/\n+/g, ' ') // Newlines to spaces
24
+ .replace(/\s+/g, ' ') // Collapse multiple spaces
25
+ .trim()
26
+ .split(/\s+/)
27
+ .filter(w => w.length > 0).length;
28
+ }
29
+
30
+ /**
31
+ * Normalize whitespace in text
32
+ * @param text - Input text
33
+ * @returns Normalized text
34
+ */
35
+ export function normalizeWhitespace(text: string): string {
36
+ return text
37
+ .replace(/\r\n/g, '\n')
38
+ .replace(/\t/g, ' ')
39
+ .replace(/ +/g, ' ')
40
+ .trim();
41
+ }
@@ -13,21 +13,40 @@
13
13
  */
14
14
 
15
15
  import * as fs from 'fs';
16
+ import { countWords } from './utils.js';
17
+ import type { Author } from './types.js';
16
18
 
17
19
  /**
18
20
  * Format date with simple pattern
19
- * @param {Date} date
20
- * @param {string} format - Pattern (YYYY, MM, DD, MMMM, MMM, D)
21
- * @returns {string}
22
21
  */
23
- function formatDate(date, format = 'YYYY-MM-DD') {
22
+ function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {
24
23
  const months = [
25
- 'January', 'February', 'March', 'April', 'May', 'June',
26
- 'July', 'August', 'September', 'October', 'November', 'December'
24
+ 'January',
25
+ 'February',
26
+ 'March',
27
+ 'April',
28
+ 'May',
29
+ 'June',
30
+ 'July',
31
+ 'August',
32
+ 'September',
33
+ 'October',
34
+ 'November',
35
+ 'December',
27
36
  ];
28
37
  const monthsShort = [
29
- 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
30
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
38
+ 'Jan',
39
+ 'Feb',
40
+ 'Mar',
41
+ 'Apr',
42
+ 'May',
43
+ 'Jun',
44
+ 'Jul',
45
+ 'Aug',
46
+ 'Sep',
47
+ 'Oct',
48
+ 'Nov',
49
+ 'Dec',
31
50
  ];
32
51
 
33
52
  const year = date.getFullYear();
@@ -35,6 +54,8 @@ function formatDate(date, format = 'YYYY-MM-DD') {
35
54
  const day = date.getDate();
36
55
 
37
56
  // Use placeholders to avoid replacement conflicts (e.g., D in December)
57
+ const monthFull = months[month] || '';
58
+ const monthShort = monthsShort[month] || '';
38
59
  return format
39
60
  .replace('YYYY', '\x00YEAR\x00')
40
61
  .replace('MMMM', '\x00MONTHFULL\x00')
@@ -43,46 +64,22 @@ function formatDate(date, format = 'YYYY-MM-DD') {
43
64
  .replace('DD', '\x00DAYPAD\x00')
44
65
  .replace(/\bD\b/, '\x00DAY\x00')
45
66
  .replace('\x00YEAR\x00', year.toString())
46
- .replace('\x00MONTHFULL\x00', months[month])
47
- .replace('\x00MONTHSHORT\x00', monthsShort[month])
67
+ .replace('\x00MONTHFULL\x00', monthFull)
68
+ .replace('\x00MONTHSHORT\x00', monthShort)
48
69
  .replace('\x00MONTHNUM\x00', (month + 1).toString().padStart(2, '0'))
49
70
  .replace('\x00DAYPAD\x00', day.toString().padStart(2, '0'))
50
71
  .replace('\x00DAY\x00', day.toString());
51
72
  }
52
73
 
53
- /**
54
- * Count words in text (excluding markdown syntax)
55
- * @param {string} text
56
- * @returns {number}
57
- */
58
- function countWords(text) {
59
- return text
60
- .replace(/^---[\s\S]*?---/m, '') // Remove frontmatter
61
- .replace(/!\[.*?\]\(.*?\)/g, '') // Remove images
62
- .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Keep link text
63
- .replace(/#+\s*/g, '') // Remove headers
64
- .replace(/\*\*|__|[*_`]/g, '') // Remove formatting
65
- .replace(/```[\s\S]*?```/g, '') // Remove code blocks
66
- .replace(/\{[^}]+\}/g, '') // Remove annotations
67
- .replace(/@\w+:\w+/g, '') // Remove refs
68
- .replace(/@\w+/g, '') // Remove citations
69
- .replace(/\|[^|]+\|/g, ' ') // Remove tables
70
- .replace(/\n+/g, ' ')
71
- .trim()
72
- .split(/\s+/)
73
- .filter(w => w.length > 0).length;
74
- }
75
-
76
74
  /**
77
75
  * Get first author name from authors array
78
- * @param {Array|string} authors
79
- * @returns {string}
80
76
  */
81
- function getFirstAuthor(authors) {
82
- if (!authors || authors.length === 0) return '';
77
+ function getFirstAuthor(authors: Author[] | string | undefined): string {
78
+ if (!authors || (Array.isArray(authors) && authors.length === 0)) return '';
83
79
 
84
80
  const first = Array.isArray(authors) ? authors[0] : authors;
85
81
 
82
+ if (!first) return '';
86
83
  if (typeof first === 'string') return first;
87
84
  if (first.name) return first.name;
88
85
 
@@ -91,28 +88,41 @@ function getFirstAuthor(authors) {
91
88
 
92
89
  /**
93
90
  * Get all author names
94
- * @param {Array|string} authors
95
- * @returns {string}
96
91
  */
97
- function getAllAuthors(authors) {
92
+ function getAllAuthors(authors: Author[] | string | undefined): string {
98
93
  if (!authors) return '';
99
94
  if (typeof authors === 'string') return authors;
100
95
 
101
96
  return authors
102
- .map(a => typeof a === 'string' ? a : a.name)
97
+ .map((a) => (typeof a === 'string' ? a : (a.name || '')))
103
98
  .filter(Boolean)
104
99
  .join(', ');
105
100
  }
106
101
 
102
+ /**
103
+ * Options for variable processing
104
+ */
105
+ interface ProcessVariablesOptions {
106
+ sectionContents?: string[];
107
+ }
108
+
109
+ /**
110
+ * Config object (minimal subset needed for variables)
111
+ */
112
+ interface Config {
113
+ version?: string;
114
+ title?: string;
115
+ authors?: Author[] | string;
116
+ }
117
+
107
118
  /**
108
119
  * Process template variables in text
109
- * @param {string} text - Text with {{variable}} placeholders
110
- * @param {object} config - rev.yaml config
111
- * @param {object} options - Additional options
112
- * @param {string[]} options.sections - Section file contents for word count
113
- * @returns {string} Text with variables replaced
114
120
  */
115
- export function processVariables(text, config = {}, options = {}) {
121
+ export function processVariables(
122
+ text: string,
123
+ config: Config = {},
124
+ options: ProcessVariablesOptions = {}
125
+ ): string {
116
126
  const now = new Date();
117
127
  let result = text;
118
128
 
@@ -155,19 +165,15 @@ export function processVariables(text, config = {}, options = {}) {
155
165
 
156
166
  /**
157
167
  * Check if text contains any template variables
158
- * @param {string} text
159
- * @returns {boolean}
160
168
  */
161
- export function hasVariables(text) {
169
+ export function hasVariables(text: string): boolean {
162
170
  return /\{\{[^}]+\}\}/.test(text);
163
171
  }
164
172
 
165
173
  /**
166
174
  * List all variables found in text
167
- * @param {string} text
168
- * @returns {string[]}
169
175
  */
170
- export function findVariables(text) {
176
+ export function findVariables(text: string): string[] {
171
177
  const matches = text.match(/\{\{([^}]+)\}\}/g) || [];
172
- return [...new Set(matches.map(m => m.slice(2, -2)))];
178
+ return [...new Set(matches.map((m) => m.slice(2, -2)))];
173
179
  }