@node-cli/comments 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lib.js ADDED
@@ -0,0 +1,444 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_without_holes(arr) {
7
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
8
+ }
9
+ function _iterable_to_array(iter) {
10
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
11
+ }
12
+ function _non_iterable_spread() {
13
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
14
+ }
15
+ function _to_consumable_array(arr) {
16
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
17
+ }
18
+ function _unsupported_iterable_to_array(o, minLen) {
19
+ if (!o) return;
20
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
21
+ var n = Object.prototype.toString.call(o).slice(8, -1);
22
+ if (n === "Object" && o.constructor) n = o.constructor.name;
23
+ if (n === "Map" || n === "Set") return Array.from(n);
24
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
25
+ }
26
+ import { Logger } from "@node-cli/logger";
27
+ export var logger = new Logger({
28
+ boring: process.env.NODE_ENV === "test"
29
+ });
30
+ // Safety guards / limits (defense-in-depth vs pathological or malicious input)
31
+ // Large indentation sequences (e.g. thousands of tabs) aren't meaningful for real
32
+ // source formatting and could be used to inflate processing time if a regex
33
+ // exhibited super-linear behavior. Our pattern is already linear (tempered), but
34
+ // we still cap accepted indentation length to keep work bounded.
35
+ var MAX_JSDOC_INDENT = 256; // characters (tabs + spaces)
36
+ // JSDoc block extraction:
37
+ // Previous pattern used a lazy dot-all: ([\s\S]*?) which could, under
38
+ // pathological inputs, produce excessive backtracking. We replaced it with a
39
+ // tempered pattern that advances linearly by never letting the inner part
40
+ // consume a closing '*/'. This avoids catastrophic behavior while keeping
41
+ // correctness.
42
+ //
43
+ // Reviewer (PR) concern: potential ReDoS on crafted inputs containing many
44
+ // leading tabs then '/**'. Analysis: The inner quantified group
45
+ // (?:[^*]|\*(?!/))*
46
+ // is unambiguous: on each iteration it consumes exactly one character and can
47
+ // never match the closing sentinel '*/' because of the negative lookahead. This
48
+ // means the engine proceeds in O(n) time relative to the block body size.
49
+ // There is no nested ambiguous quantifier (e.g. (a+)*, (.*)+, etc.). The only
50
+ // other quantified part ^[\t ]* is a simple character class that is consumed
51
+ // once per line start with no backtracking explosion potential.
52
+ //
53
+ // Defense-in-depth: we still (1) cap processed body length (see below) and
54
+ // (2) cap accepted indentation length (MAX_JSDOC_INDENT) after match to ensure
55
+ // we skip absurdly indented constructs.
56
+ //
57
+ // Pattern explanation:
58
+ // (^ [\t ]* ) -> capture indentation at start of line (multiline mode)
59
+ // /\*\* -> opening delimiter
60
+ // ( -> capture group 2 body
61
+ // (?:[^*] -> any non-* char
62
+ // |\*(?!/) -> or a * not followed by /
63
+ // )* -> repeated greedily (cannot cross closing */)
64
+ // )
65
+ // \n?[\t ]*\*/ -> optional newline + trailing indent + closing */
66
+ // Complexity: linear in length of the matched block.
67
+ var JSDOC_REGEX = /(^[\t ]*)\/\*\*((?:[^*]|\*(?!\/))*)\n?[\t ]*\*\//gm;
68
+ export function diffLines(a, b) {
69
+ if (a === b) {
70
+ return "";
71
+ }
72
+ var A = a.split(/\n/);
73
+ var B = b.split(/\n/);
74
+ var out = [];
75
+ var m = Math.max(A.length, B.length);
76
+ for(var i = 0; i < m; i++){
77
+ if (A[i] === B[i]) {
78
+ continue;
79
+ }
80
+ if (A[i] !== undefined) {
81
+ out.push("- ".concat(A[i]));
82
+ }
83
+ if (B[i] !== undefined) {
84
+ out.push("+ ".concat(B[i]));
85
+ }
86
+ }
87
+ return out.join("\n");
88
+ }
89
+ function endsSentence(line) {
90
+ return /[.!?](?:['")\]]*)$/.test(line.trim());
91
+ }
92
+ function needsTerminalPunctuation(line) {
93
+ return /[A-Za-z0-9")\]']$/.test(line) && !endsSentence(line);
94
+ }
95
+ function maybeAddPeriod(line) {
96
+ return needsTerminalPunctuation(line) ? line + "." : line;
97
+ }
98
+ function normalizeNote(line) {
99
+ return line.replace(/^note:/i, "NOTE:");
100
+ }
101
+ function isListLike(line) {
102
+ return /^(?:[-*+] |\d+\. )/.test(line.trim());
103
+ }
104
+ function isTagLine(line) {
105
+ return /^@/.test(line.trim());
106
+ }
107
+ function isHeadingLike(line) {
108
+ var t = line.trim();
109
+ return /:$/.test(t) && !isTagLine(t);
110
+ }
111
+ function isCodeFence(line) {
112
+ return /^```/.test(line.trim());
113
+ }
114
+ function isVisuallyIndentedCode(line) {
115
+ return /^\s{2,}\S/.test(line);
116
+ }
117
+ function wrapWords(text, width) {
118
+ var words = text.split(/\s+/).filter(Boolean);
119
+ var lines = [];
120
+ var cur = "";
121
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
122
+ try {
123
+ for(var _iterator = words[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
124
+ var w = _step.value;
125
+ if (!cur.length) {
126
+ cur = w;
127
+ continue;
128
+ }
129
+ if (cur.length + 1 + w.length <= width) {
130
+ cur += " " + w;
131
+ } else {
132
+ lines.push(cur);
133
+ cur = w;
134
+ }
135
+ }
136
+ } catch (err) {
137
+ _didIteratorError = true;
138
+ _iteratorError = err;
139
+ } finally{
140
+ try {
141
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
142
+ _iterator.return();
143
+ }
144
+ } finally{
145
+ if (_didIteratorError) {
146
+ throw _iteratorError;
147
+ }
148
+ }
149
+ }
150
+ if (cur) {
151
+ lines.push(cur);
152
+ }
153
+ return lines.length ? lines : [
154
+ ""
155
+ ];
156
+ }
157
+ function buildJsDoc(indent, rawBody, width) {
158
+ var lines = rawBody.split(/\n/).map(function(l) {
159
+ return l.replace(/^\s*\*? ?/, "");
160
+ });
161
+ var out = [];
162
+ var para = [];
163
+ var inFence = false;
164
+ var prefix = indent + " * ";
165
+ var avail = Math.max(10, width - prefix.length);
166
+ function flush() {
167
+ if (!para.length) {
168
+ return;
169
+ }
170
+ var text = para.join(" ").replace(/\s+/g, " ").trim();
171
+ text = normalizeNote(text);
172
+ text = maybeAddPeriod(text);
173
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
174
+ try {
175
+ for(var _iterator = wrapWords(text, avail)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
176
+ var l = _step.value;
177
+ out.push(prefix + l);
178
+ }
179
+ } catch (err) {
180
+ _didIteratorError = true;
181
+ _iteratorError = err;
182
+ } finally{
183
+ try {
184
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
185
+ _iterator.return();
186
+ }
187
+ } finally{
188
+ if (_didIteratorError) {
189
+ throw _iteratorError;
190
+ }
191
+ }
192
+ }
193
+ para = [];
194
+ }
195
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
196
+ try {
197
+ for(var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
198
+ var raw = _step.value;
199
+ var trimmed = raw.trimEnd();
200
+ if (isCodeFence(trimmed)) {
201
+ flush();
202
+ inFence = !inFence;
203
+ out.push(prefix + trimmed);
204
+ continue;
205
+ }
206
+ if (inFence) {
207
+ out.push(prefix + trimmed);
208
+ continue;
209
+ }
210
+ if (trimmed === "" || isListLike(trimmed) || isTagLine(trimmed) || isHeadingLike(trimmed) || isVisuallyIndentedCode(raw)) {
211
+ flush();
212
+ if (trimmed === "") {
213
+ if (out.length === 0 || /^(?:\s*\*\s*)$/.test(out[out.length - 1]) === false) {
214
+ out.push(prefix.trimEnd());
215
+ }
216
+ } else {
217
+ out.push(prefix + normalizeNote(trimmed));
218
+ }
219
+ continue;
220
+ }
221
+ para.push(trimmed);
222
+ }
223
+ } catch (err) {
224
+ _didIteratorError = true;
225
+ _iteratorError = err;
226
+ } finally{
227
+ try {
228
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
229
+ _iterator.return();
230
+ }
231
+ } finally{
232
+ if (_didIteratorError) {
233
+ throw _iteratorError;
234
+ }
235
+ }
236
+ }
237
+ flush();
238
+ return "".concat(indent, "/**\n").concat(out.join("\n"), "\n").concat(indent, "*/");
239
+ }
240
+ function reflowJsDocBlocks(content, width) {
241
+ JSDOC_REGEX.lastIndex = 0;
242
+ var blocks = [];
243
+ var m = JSDOC_REGEX.exec(content);
244
+ while(m){
245
+ var indent = m[1] || "";
246
+ var body = m[2] || "";
247
+ // Body length guard protects against extremely large comment blocks.
248
+ if (body.length <= 500000 && indent.length <= MAX_JSDOC_INDENT) {
249
+ blocks.push({
250
+ indent: indent,
251
+ body: body,
252
+ start: m.index,
253
+ end: m.index + m[0].length
254
+ });
255
+ }
256
+ m = JSDOC_REGEX.exec(content);
257
+ }
258
+ if (!blocks.length) {
259
+ return {
260
+ content: content,
261
+ blocks: 0
262
+ };
263
+ }
264
+ var delta = 0;
265
+ var out = content;
266
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
267
+ try {
268
+ for(var _iterator = blocks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
269
+ var b = _step.value;
270
+ var original = out.slice(b.start + delta, b.end + delta);
271
+ var built = buildJsDoc(b.indent, b.body, width);
272
+ if (original !== built) {
273
+ out = out.slice(0, b.start + delta) + built + out.slice(b.end + delta);
274
+ delta += built.length - original.length;
275
+ }
276
+ }
277
+ } catch (err) {
278
+ _didIteratorError = true;
279
+ _iteratorError = err;
280
+ } finally{
281
+ try {
282
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
283
+ _iterator.return();
284
+ }
285
+ } finally{
286
+ if (_didIteratorError) {
287
+ throw _iteratorError;
288
+ }
289
+ }
290
+ }
291
+ return {
292
+ content: out,
293
+ blocks: blocks.length
294
+ };
295
+ }
296
+ function wrapLineComments(content, width) {
297
+ var _loop = function(i) {
298
+ var _out;
299
+ var line = lines[i];
300
+ var m = /^(\s*)\/\/( ?)(.*)$/.exec(line);
301
+ if (!m || /^\/\/\//.test(line)) {
302
+ out.push(line);
303
+ return "continue";
304
+ }
305
+ var indent = m[1];
306
+ var body = m[3];
307
+ if (/^(@|eslint|ts-ignore)/.test(body) || /https?:\/\//.test(body)) {
308
+ out.push(line);
309
+ return "continue";
310
+ }
311
+ var prefix = indent + "// ";
312
+ var avail = Math.max(10, width - prefix.length);
313
+ var text = body.replace(/\s+/g, " ").trim();
314
+ text = normalizeNote(text);
315
+ text = maybeAddPeriod(text);
316
+ var wrapped = wrapWords(text, avail).map(function(w) {
317
+ return prefix + w;
318
+ });
319
+ if (wrapped.join("\n") !== line) {
320
+ changed = true;
321
+ }
322
+ (_out = out).push.apply(_out, _to_consumable_array(wrapped));
323
+ };
324
+ var lines = content.split(/\n/);
325
+ var changed = false;
326
+ var out = [];
327
+ for(var i = 0; i < lines.length; i++)_loop(i);
328
+ return {
329
+ content: out.join("\n"),
330
+ applied: changed
331
+ };
332
+ }
333
+ function mergeLineCommentGroups(content) {
334
+ var lines = content.split(/\n/);
335
+ var out = [];
336
+ var i = 0;
337
+ var merged = false;
338
+ while(i < lines.length){
339
+ if (/^\s*\/\//.test(lines[i]) && !/^\s*\/\/\//.test(lines[i])) {
340
+ var prev = i > 0 ? lines[i - 1] : "";
341
+ var prevTrim = prev.trim();
342
+ var contextEligible = prevTrim === "" || /[{}]$/.test(prevTrim);
343
+ if (!contextEligible) {
344
+ out.push(lines[i]);
345
+ i++;
346
+ continue;
347
+ }
348
+ var group = [];
349
+ var j = i;
350
+ while(j < lines.length){
351
+ var lm = /^(\s*)\/\/ ?(.*)$/.exec(lines[j]);
352
+ if (!lm || /^\s*\/\/\//.test(lines[j])) {
353
+ break;
354
+ }
355
+ var txt = lm[2];
356
+ if (/license|copyright/i.test(txt) || /https?:\/\//.test(txt) || /eslint|ts-ignore/.test(txt)) {
357
+ break; // do not merge directive / license groups
358
+ }
359
+ group.push({
360
+ indent: lm[1],
361
+ text: txt
362
+ });
363
+ j++;
364
+ }
365
+ if (group.length >= 2) {
366
+ // Structured explanatory blocks: now we CONVERT them into a multi-line JSDoc block
367
+ // while preserving each original line (instead of merging into a single paragraph).
368
+ // We must escape any raw '*/' inside the body to avoid premature termination.
369
+ // Definition of structured: presence of arrows (->), regex tokens (?:, */), or the phrase 'Pattern explanation:'.
370
+ var structured = group.some(function(g) {
371
+ return /->/.test(g.text) || /(\(\?:|\*\/)/.test(g.text) || /Pattern explanation:/i.test(g.text);
372
+ });
373
+ if (structured) {
374
+ var indent = group[0].indent;
375
+ out.push("".concat(indent, "/**"));
376
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
377
+ try {
378
+ for(var _iterator = group[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
379
+ var ln = _step.value;
380
+ // Escape closing sentinel inside content
381
+ var safe = ln.text.replace(/\*\//g, "*\\/");
382
+ out.push("".concat(indent, " * ").concat(safe));
383
+ }
384
+ } catch (err) {
385
+ _didIteratorError = true;
386
+ _iteratorError = err;
387
+ } finally{
388
+ try {
389
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
390
+ _iterator.return();
391
+ }
392
+ } finally{
393
+ if (_didIteratorError) {
394
+ throw _iteratorError;
395
+ }
396
+ }
397
+ }
398
+ out.push("".concat(indent, " */"));
399
+ merged = true;
400
+ i = j;
401
+ continue;
402
+ }
403
+ var indent1 = group[0].indent;
404
+ merged = true;
405
+ var para = group.map(function(g) {
406
+ return normalizeNote(g.text.trim());
407
+ }).map(function(g) {
408
+ return maybeAddPeriod(g);
409
+ }).join(" ");
410
+ out.push("".concat(indent1, "/**"));
411
+ out.push("".concat(indent1, " * ").concat(para));
412
+ out.push("".concat(indent1, " */"));
413
+ i = j;
414
+ continue;
415
+ }
416
+ }
417
+ out.push(lines[i]);
418
+ i++;
419
+ }
420
+ return {
421
+ content: out.join("\n"),
422
+ merged: merged
423
+ };
424
+ }
425
+ export function parseAndTransformComments(input, options) {
426
+ var working = input;
427
+ if (options.mergeLineComments) {
428
+ var m = mergeLineCommentGroups(working);
429
+ working = m.content;
430
+ }
431
+ var js = reflowJsDocBlocks(working, options.width);
432
+ working = js.content;
433
+ if (options.wrapLineComments) {
434
+ var w = wrapLineComments(working, options.width);
435
+ working = w.content;
436
+ }
437
+ return {
438
+ original: input,
439
+ transformed: working,
440
+ changed: working !== input
441
+ };
442
+ }
443
+
444
+ //# sourceMappingURL=lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib.ts"],"sourcesContent":["import { Logger } from \"@node-cli/logger\";\n\nexport const logger = new Logger({ boring: process.env.NODE_ENV === \"test\" });\n\nexport interface ProcessOptions {\n\twidth: number;\n\twrapLineComments: boolean;\n\tmergeLineComments: boolean;\n}\n\nexport interface FileResult {\n\toriginal: string;\n\ttransformed: string;\n\tchanged: boolean;\n}\n\ninterface JsDocMatch {\n\tindent: string;\n\tbody: string;\n\tstart: number;\n\tend: number;\n}\n\n// Safety guards / limits (defense-in-depth vs pathological or malicious input)\n// Large indentation sequences (e.g. thousands of tabs) aren't meaningful for real\n// source formatting and could be used to inflate processing time if a regex\n// exhibited super-linear behavior. Our pattern is already linear (tempered), but\n// we still cap accepted indentation length to keep work bounded.\nconst MAX_JSDOC_INDENT = 256; // characters (tabs + spaces)\n\n// JSDoc block extraction:\n// Previous pattern used a lazy dot-all: ([\\s\\S]*?) which could, under\n// pathological inputs, produce excessive backtracking. We replaced it with a\n// tempered pattern that advances linearly by never letting the inner part\n// consume a closing '*/'. This avoids catastrophic behavior while keeping\n// correctness.\n//\n// Reviewer (PR) concern: potential ReDoS on crafted inputs containing many\n// leading tabs then '/**'. Analysis: The inner quantified group\n// (?:[^*]|\\*(?!/))*\n// is unambiguous: on each iteration it consumes exactly one character and can\n// never match the closing sentinel '*/' because of the negative lookahead. This\n// means the engine proceeds in O(n) time relative to the block body size.\n// There is no nested ambiguous quantifier (e.g. (a+)*, (.*)+, etc.). The only\n// other quantified part ^[\\t ]* is a simple character class that is consumed\n// once per line start with no backtracking explosion potential.\n//\n// Defense-in-depth: we still (1) cap processed body length (see below) and\n// (2) cap accepted indentation length (MAX_JSDOC_INDENT) after match to ensure\n// we skip absurdly indented constructs.\n//\n// Pattern explanation:\n// (^ [\\t ]* ) -> capture indentation at start of line (multiline mode)\n// /\\*\\* -> opening delimiter\n// ( -> capture group 2 body\n// (?:[^*] -> any non-* char\n// |\\*(?!/) -> or a * not followed by /\n// )* -> repeated greedily (cannot cross closing */)\n// )\n// \\n?[\\t ]*\\*/ -> optional newline + trailing indent + closing */\n// Complexity: linear in length of the matched block.\nconst JSDOC_REGEX = /(^[\\t ]*)\\/\\*\\*((?:[^*]|\\*(?!\\/))*)\\n?[\\t ]*\\*\\//gm;\n\nexport function diffLines(a: string, b: string): string {\n\tif (a === b) {\n\t\treturn \"\";\n\t}\n\tconst A = a.split(/\\n/);\n\tconst B = b.split(/\\n/);\n\tconst out: string[] = [];\n\tconst m = Math.max(A.length, B.length);\n\tfor (let i = 0; i < m; i++) {\n\t\tif (A[i] === B[i]) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (A[i] !== undefined) {\n\t\t\tout.push(`- ${A[i]}`);\n\t\t}\n\t\tif (B[i] !== undefined) {\n\t\t\tout.push(`+ ${B[i]}`);\n\t\t}\n\t}\n\treturn out.join(\"\\n\");\n}\n\nfunction endsSentence(line: string): boolean {\n\treturn /[.!?](?:['\")\\]]*)$/.test(line.trim());\n}\n\nfunction needsTerminalPunctuation(line: string): boolean {\n\treturn /[A-Za-z0-9\")\\]']$/.test(line) && !endsSentence(line);\n}\n\nfunction maybeAddPeriod(line: string): string {\n\treturn needsTerminalPunctuation(line) ? line + \".\" : line;\n}\n\nfunction normalizeNote(line: string): string {\n\treturn line.replace(/^note:/i, \"NOTE:\");\n}\n\nfunction isListLike(line: string): boolean {\n\treturn /^(?:[-*+] |\\d+\\. )/.test(line.trim());\n}\n\nfunction isTagLine(line: string): boolean {\n\treturn /^@/.test(line.trim());\n}\n\nfunction isHeadingLike(line: string): boolean {\n\tconst t = line.trim();\n\treturn /:$/.test(t) && !isTagLine(t);\n}\n\nfunction isCodeFence(line: string): boolean {\n\treturn /^```/.test(line.trim());\n}\n\nfunction isVisuallyIndentedCode(line: string): boolean {\n\treturn /^\\s{2,}\\S/.test(line);\n}\n\nfunction wrapWords(text: string, width: number): string[] {\n\tconst words = text.split(/\\s+/).filter(Boolean);\n\tconst lines: string[] = [];\n\tlet cur = \"\";\n\tfor (const w of words) {\n\t\tif (!cur.length) {\n\t\t\tcur = w;\n\t\t\tcontinue;\n\t\t}\n\t\tif (cur.length + 1 + w.length <= width) {\n\t\t\tcur += \" \" + w;\n\t\t} else {\n\t\t\tlines.push(cur);\n\t\t\tcur = w;\n\t\t}\n\t}\n\tif (cur) {\n\t\tlines.push(cur);\n\t}\n\treturn lines.length ? lines : [\"\"];\n}\n\nfunction buildJsDoc(indent: string, rawBody: string, width: number): string {\n\tconst lines = rawBody.split(/\\n/).map((l) => l.replace(/^\\s*\\*? ?/, \"\"));\n\tconst out: string[] = [];\n\tlet para: string[] = [];\n\tlet inFence = false;\n\tconst prefix = indent + \" * \";\n\tconst avail = Math.max(10, width - prefix.length);\n\n\tfunction flush(): void {\n\t\tif (!para.length) {\n\t\t\treturn;\n\t\t}\n\t\tlet text = para.join(\" \").replace(/\\s+/g, \" \").trim();\n\t\ttext = normalizeNote(text);\n\t\ttext = maybeAddPeriod(text);\n\t\tfor (const l of wrapWords(text, avail)) {\n\t\t\tout.push(prefix + l);\n\t\t}\n\t\tpara = [];\n\t}\n\n\tfor (const raw of lines) {\n\t\tconst trimmed = raw.trimEnd();\n\t\tif (isCodeFence(trimmed)) {\n\t\t\tflush();\n\t\t\tinFence = !inFence;\n\t\t\tout.push(prefix + trimmed);\n\t\t\tcontinue;\n\t\t}\n\t\tif (inFence) {\n\t\t\tout.push(prefix + trimmed);\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\ttrimmed === \"\" ||\n\t\t\tisListLike(trimmed) ||\n\t\t\tisTagLine(trimmed) ||\n\t\t\tisHeadingLike(trimmed) ||\n\t\t\tisVisuallyIndentedCode(raw)\n\t\t) {\n\t\t\tflush();\n\t\t\tif (trimmed === \"\") {\n\t\t\t\tif (\n\t\t\t\t\tout.length === 0 ||\n\t\t\t\t\t/^(?:\\s*\\*\\s*)$/.test(out[out.length - 1]) === false\n\t\t\t\t) {\n\t\t\t\t\tout.push(prefix.trimEnd());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tout.push(prefix + normalizeNote(trimmed));\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tpara.push(trimmed);\n\t}\n\tflush();\n\treturn `${indent}/**\\n${out.join(\"\\n\")}\\n${indent}*/`;\n}\n\nfunction reflowJsDocBlocks(\n\tcontent: string,\n\twidth: number,\n): { content: string; blocks: number } {\n\tJSDOC_REGEX.lastIndex = 0;\n\tconst blocks: JsDocMatch[] = [];\n\tlet m: RegExpExecArray | null = JSDOC_REGEX.exec(content);\n\twhile (m) {\n\t\tconst indent = m[1] || \"\";\n\t\tconst body = m[2] || \"\";\n\t\t// Body length guard protects against extremely large comment blocks.\n\t\tif (body.length <= 500_000 && indent.length <= MAX_JSDOC_INDENT) {\n\t\t\tblocks.push({\n\t\t\t\tindent,\n\t\t\t\tbody,\n\t\t\t\tstart: m.index,\n\t\t\t\tend: m.index + m[0].length,\n\t\t\t});\n\t\t}\n\t\tm = JSDOC_REGEX.exec(content);\n\t}\n\tif (!blocks.length) {\n\t\treturn { content, blocks: 0 };\n\t}\n\tlet delta = 0;\n\tlet out = content;\n\tfor (const b of blocks) {\n\t\tconst original = out.slice(b.start + delta, b.end + delta);\n\t\tconst built = buildJsDoc(b.indent, b.body, width);\n\t\tif (original !== built) {\n\t\t\tout = out.slice(0, b.start + delta) + built + out.slice(b.end + delta);\n\t\t\tdelta += built.length - original.length;\n\t\t}\n\t}\n\treturn { content: out, blocks: blocks.length };\n}\n\nfunction wrapLineComments(\n\tcontent: string,\n\twidth: number,\n): { content: string; applied: boolean } {\n\tconst lines = content.split(/\\n/);\n\tlet changed = false;\n\tconst out: string[] = [];\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tconst m = /^(\\s*)\\/\\/( ?)(.*)$/.exec(line);\n\t\tif (!m || /^\\/\\/\\//.test(line)) {\n\t\t\tout.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\tconst indent = m[1];\n\t\tconst body = m[3];\n\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\tout.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\tconst prefix = indent + \"// \";\n\t\tconst avail = Math.max(10, width - prefix.length);\n\t\tlet text = body.replace(/\\s+/g, \" \").trim();\n\t\ttext = normalizeNote(text);\n\t\ttext = maybeAddPeriod(text);\n\t\tconst wrapped = wrapWords(text, avail).map((w) => prefix + w);\n\t\tif (wrapped.join(\"\\n\") !== line) {\n\t\t\tchanged = true;\n\t\t}\n\t\tout.push(...wrapped);\n\t}\n\treturn { content: out.join(\"\\n\"), applied: changed };\n}\n\nfunction mergeLineCommentGroups(content: string): {\n\tcontent: string;\n\tmerged: boolean;\n} {\n\tconst lines = content.split(/\\n/);\n\tconst out: string[] = [];\n\tlet i = 0;\n\tlet merged = false;\n\twhile (i < lines.length) {\n\t\tif (/^\\s*\\/\\//.test(lines[i]) && !/^\\s*\\/\\/\\//.test(lines[i])) {\n\t\t\tconst prev = i > 0 ? lines[i - 1] : \"\";\n\t\t\tconst prevTrim = prev.trim();\n\t\t\tconst contextEligible = prevTrim === \"\" || /[{}]$/.test(prevTrim);\n\t\t\tif (!contextEligible) {\n\t\t\t\tout.push(lines[i]);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst group: { indent: string; text: string }[] = [];\n\t\t\tlet j = i;\n\t\t\twhile (j < lines.length) {\n\t\t\t\tconst lm = /^(\\s*)\\/\\/ ?(.*)$/.exec(lines[j]);\n\t\t\t\tif (!lm || /^\\s*\\/\\/\\//.test(lines[j])) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tconst txt = lm[2];\n\t\t\t\tif (\n\t\t\t\t\t/license|copyright/i.test(txt) ||\n\t\t\t\t\t/https?:\\/\\//.test(txt) ||\n\t\t\t\t\t/eslint|ts-ignore/.test(txt)\n\t\t\t\t) {\n\t\t\t\t\tbreak; // do not merge directive / license groups\n\t\t\t\t}\n\t\t\t\tgroup.push({ indent: lm[1], text: txt });\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tif (group.length >= 2) {\n\t\t\t\t// Structured explanatory blocks: now we CONVERT them into a multi-line JSDoc block\n\t\t\t\t// while preserving each original line (instead of merging into a single paragraph).\n\t\t\t\t// We must escape any raw '*/' inside the body to avoid premature termination.\n\t\t\t\t// Definition of structured: presence of arrows (->), regex tokens (?:, */), or the phrase 'Pattern explanation:'.\n\t\t\t\tconst structured = group.some(\n\t\t\t\t\t(g) =>\n\t\t\t\t\t\t/->/.test(g.text) ||\n\t\t\t\t\t\t/(\\(\\?:|\\*\\/)/.test(g.text) ||\n\t\t\t\t\t\t/Pattern explanation:/i.test(g.text),\n\t\t\t\t);\n\t\t\t\tif (structured) {\n\t\t\t\t\tconst indent = group[0].indent;\n\t\t\t\t\tout.push(`${indent}/**`);\n\t\t\t\t\tfor (const ln of group) {\n\t\t\t\t\t\t// Escape closing sentinel inside content\n\t\t\t\t\t\tconst safe = ln.text.replace(/\\*\\//g, \"*\\\\/\");\n\t\t\t\t\t\tout.push(`${indent} * ${safe}`);\n\t\t\t\t\t}\n\t\t\t\t\tout.push(`${indent} */`);\n\t\t\t\t\tmerged = true;\n\t\t\t\t\ti = j;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst indent = group[0].indent;\n\t\t\t\tmerged = true;\n\t\t\t\tconst para = group\n\t\t\t\t\t.map((g) => normalizeNote(g.text.trim()))\n\t\t\t\t\t.map((g) => maybeAddPeriod(g))\n\t\t\t\t\t.join(\" \");\n\t\t\t\tout.push(`${indent}/**`);\n\t\t\t\tout.push(`${indent} * ${para}`);\n\t\t\t\tout.push(`${indent} */`);\n\t\t\t\ti = j;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tout.push(lines[i]);\n\t\ti++;\n\t}\n\treturn { content: out.join(\"\\n\"), merged };\n}\n\nexport function parseAndTransformComments(\n\tinput: string,\n\toptions: ProcessOptions,\n): FileResult {\n\tlet working = input;\n\tif (options.mergeLineComments) {\n\t\tconst m = mergeLineCommentGroups(working);\n\t\tworking = m.content;\n\t}\n\tconst js = reflowJsDocBlocks(working, options.width);\n\tworking = js.content;\n\tif (options.wrapLineComments) {\n\t\tconst w = wrapLineComments(working, options.width);\n\t\tworking = w.content;\n\t}\n\treturn { original: input, transformed: working, changed: working !== input };\n}\n"],"names":["Logger","logger","boring","process","env","NODE_ENV","MAX_JSDOC_INDENT","JSDOC_REGEX","diffLines","a","b","A","split","B","out","m","Math","max","length","i","undefined","push","join","endsSentence","line","test","trim","needsTerminalPunctuation","maybeAddPeriod","normalizeNote","replace","isListLike","isTagLine","isHeadingLike","t","isCodeFence","isVisuallyIndentedCode","wrapWords","text","width","words","filter","Boolean","lines","cur","w","buildJsDoc","indent","rawBody","map","l","para","inFence","prefix","avail","flush","raw","trimmed","trimEnd","reflowJsDocBlocks","content","lastIndex","blocks","exec","body","start","index","end","delta","original","slice","built","wrapLineComments","wrapped","changed","applied","mergeLineCommentGroups","merged","prev","prevTrim","contextEligible","group","j","lm","txt","structured","some","g","ln","safe","parseAndTransformComments","input","options","working","mergeLineComments","js","transformed"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type Flags = {
2
+ width?: number;
3
+ dryRun?: boolean;
4
+ stdout?: boolean;
5
+ noLineWrap?: boolean;
6
+ mergeLineComments?: boolean;
7
+ boring?: boolean;
8
+ help?: boolean;
9
+ version?: boolean;
10
+ };
11
+ export type Parameters = {
12
+ files?: string;
13
+ };
14
+ export type Configuration = {
15
+ flags?: Flags;
16
+ parameters?: Parameters;
17
+ showHelp?: () => void;
18
+ };
19
+ export declare const config: Configuration;
package/dist/parse.js ADDED
@@ -0,0 +1,87 @@
1
+ /* v8 ignore start */ import { parser } from "@node-cli/parser";
2
+ import { defaultFlags } from "./defaults.js";
3
+ /* v8 ignore next 120 */ export var config = parser({
4
+ meta: import.meta,
5
+ examples: [
6
+ {
7
+ command: "comments src/**/*.ts",
8
+ comment: "## Reflow comments in all TS source files"
9
+ },
10
+ {
11
+ command: "comments --dry-run src/index.ts",
12
+ comment: "## Show diff for a single file without writing"
13
+ },
14
+ {
15
+ command: "comments --width 100 --merge-line-comments 'src/**/*.ts'",
16
+ comment: "## Use width 100 and merge groups of line comments"
17
+ },
18
+ {
19
+ command: "comments --no-line-wrap src/file.ts",
20
+ comment: "## Disable wrapping of // comments"
21
+ }
22
+ ],
23
+ flags: {
24
+ width: {
25
+ description: "Max output line width (default 80)",
26
+ type: "number",
27
+ default: defaultFlags.width
28
+ },
29
+ dryRun: {
30
+ shortFlag: "D",
31
+ description: "Show diff, don't write files (exit 1 if changes)",
32
+ type: "boolean"
33
+ },
34
+ stdout: {
35
+ description: "Print transformed output of a single file to STDOUT",
36
+ type: "boolean"
37
+ },
38
+ noLineWrap: {
39
+ description: "Disable wrapping of // single-line comments",
40
+ type: "boolean"
41
+ },
42
+ mergeLineComments: {
43
+ description: "Merge consecutive // lines into JSDoc blocks",
44
+ type: "boolean",
45
+ default: defaultFlags.mergeLineComments
46
+ },
47
+ boring: {
48
+ shortFlag: "b",
49
+ description: "Do not use color output",
50
+ type: "boolean"
51
+ },
52
+ help: {
53
+ shortFlag: "h",
54
+ description: "Display help instructions",
55
+ type: "boolean"
56
+ },
57
+ version: {
58
+ shortFlag: "v",
59
+ description: "Output the current version",
60
+ type: "boolean"
61
+ }
62
+ },
63
+ parameters: {
64
+ files: {
65
+ description: "File paths and/or glob patterns to process"
66
+ }
67
+ },
68
+ restrictions: [
69
+ {
70
+ exit: 1,
71
+ message: "You must provide at least one file path or glob pattern",
72
+ test: function(_flags, parameters) {
73
+ return Object.keys(parameters || {}).length === 0;
74
+ }
75
+ },
76
+ {
77
+ exit: 1,
78
+ message: "--stdout can only be used with a single file",
79
+ test: function(flags, parameters) {
80
+ return flags.stdout === true && parameters && Object.keys(parameters).length > 1;
81
+ }
82
+ }
83
+ ],
84
+ usage: "comments [options] <files...>"
85
+ }); /* v8 ignore stop */
86
+
87
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parse.ts"],"sourcesContent":["/* v8 ignore start */\nimport { parser } from \"@node-cli/parser\";\nimport { defaultFlags } from \"./defaults.js\";\n\nexport type Flags = {\n\twidth?: number;\n\tdryRun?: boolean;\n\tstdout?: boolean;\n\tnoLineWrap?: boolean;\n\tmergeLineComments?: boolean;\n\tboring?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n};\nexport type Parameters = {\n\tfiles?: string;\n};\nexport type Configuration = {\n\tflags?: Flags;\n\tparameters?: Parameters;\n\tshowHelp?: () => void;\n};\n\n/* v8 ignore next 120 */\nexport const config: Configuration = parser({\n\tmeta: import.meta,\n\texamples: [\n\t\t{\n\t\t\tcommand: \"comments src/**/*.ts\",\n\t\t\tcomment: \"## Reflow comments in all TS source files\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"comments --dry-run src/index.ts\",\n\t\t\tcomment: \"## Show diff for a single file without writing\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"comments --width 100 --merge-line-comments 'src/**/*.ts'\",\n\t\t\tcomment: \"## Use width 100 and merge groups of line comments\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"comments --no-line-wrap src/file.ts\",\n\t\t\tcomment: \"## Disable wrapping of // comments\",\n\t\t},\n\t],\n\tflags: {\n\t\twidth: {\n\t\t\tdescription: \"Max output line width (default 80)\",\n\t\t\ttype: \"number\",\n\t\t\tdefault: defaultFlags.width,\n\t\t},\n\t\tdryRun: {\n\t\t\tshortFlag: \"D\",\n\t\t\tdescription: \"Show diff, don't write files (exit 1 if changes)\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tstdout: {\n\t\t\tdescription: \"Print transformed output of a single file to STDOUT\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tnoLineWrap: {\n\t\t\tdescription: \"Disable wrapping of // single-line comments\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tmergeLineComments: {\n\t\t\tdescription: \"Merge consecutive // lines into JSDoc blocks\",\n\t\t\ttype: \"boolean\",\n\t\t\tdefault: defaultFlags.mergeLineComments,\n\t\t},\n\t\tboring: {\n\t\t\tshortFlag: \"b\",\n\t\t\tdescription: \"Do not use color output\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\thelp: {\n\t\t\tshortFlag: \"h\",\n\t\t\tdescription: \"Display help instructions\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversion: {\n\t\t\tshortFlag: \"v\",\n\t\t\tdescription: \"Output the current version\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t},\n\tparameters: {\n\t\tfiles: {\n\t\t\tdescription: \"File paths and/or glob patterns to process\",\n\t\t},\n\t},\n\trestrictions: [\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: \"You must provide at least one file path or glob pattern\",\n\t\t\ttest: (_flags: Flags, parameters: Record<string, string>) =>\n\t\t\t\tObject.keys(parameters || {}).length === 0,\n\t\t},\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: \"--stdout can only be used with a single file\",\n\t\t\ttest: (flags: Flags, parameters: Record<string, string>) =>\n\t\t\t\tflags.stdout === true &&\n\t\t\t\tparameters &&\n\t\t\t\tObject.keys(parameters).length > 1,\n\t\t},\n\t],\n\tusage: \"comments [options] <files...>\",\n});\n/* v8 ignore stop */\n"],"names":["parser","defaultFlags","config","meta","examples","command","comment","flags","width","description","type","default","dryRun","shortFlag","stdout","noLineWrap","mergeLineComments","boring","help","version","parameters","files","restrictions","exit","message","test","_flags","Object","keys","length","usage"],"mappings":"AAAA,mBAAmB,GACnB,SAASA,MAAM,QAAQ,mBAAmB;AAC1C,SAASC,YAAY,QAAQ,gBAAgB;AAqB7C,sBAAsB,GACtB,OAAO,IAAMC,SAAwBF,OAAO;IAC3CG,MAAM;IACNC,UAAU;QACT;YACCC,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;KACA;IACDC,OAAO;QACNC,OAAO;YACNC,aAAa;YACbC,MAAM;YACNC,SAASV,aAAaO,KAAK;QAC5B;QACAI,QAAQ;YACPC,WAAW;YACXJ,aAAa;YACbC,MAAM;QACP;QACAI,QAAQ;YACPL,aAAa;YACbC,MAAM;QACP;QACAK,YAAY;YACXN,aAAa;YACbC,MAAM;QACP;QACAM,mBAAmB;YAClBP,aAAa;YACbC,MAAM;YACNC,SAASV,aAAae,iBAAiB;QACxC;QACAC,QAAQ;YACPJ,WAAW;YACXJ,aAAa;YACbC,MAAM;QACP;QACAQ,MAAM;YACLL,WAAW;YACXJ,aAAa;YACbC,MAAM;QACP;QACAS,SAAS;YACRN,WAAW;YACXJ,aAAa;YACbC,MAAM;QACP;IACD;IACAU,YAAY;QACXC,OAAO;YACNZ,aAAa;QACd;IACD;IACAa,cAAc;QACb;YACCC,MAAM;YACNC,SAAS;YACTC,MAAM,SAACC,QAAeN;uBACrBO,OAAOC,IAAI,CAACR,cAAc,CAAC,GAAGS,MAAM,KAAK;;QAC3C;QACA;YACCN,MAAM;YACNC,SAAS;YACTC,MAAM,SAAClB,OAAca;uBACpBb,MAAMO,MAAM,KAAK,QACjBM,cACAO,OAAOC,IAAI,CAACR,YAAYS,MAAM,GAAG;;QACnC;KACA;IACDC,OAAO;AACR,GAAG,CACH,kBAAkB"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@node-cli/comments",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "author": "Arno Versini",
6
+ "description": "CLI tool to reflow and normalize JSDoc and line comments in source files",
7
+ "type": "module",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": "./dist/lib.js",
10
+ "bin": "dist/comments.js",
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "node": ">=18",
16
+ "scripts": {
17
+ "build": "npm-run-all --serial clean build:types build:js build:barrel",
18
+ "build:barrel": "barrelsby --delete --directory dist --pattern \"**/*.d.ts\" --name \"index.d\"",
19
+ "build:js": "swc --strip-leading-paths --source-maps --out-dir dist src",
20
+ "build:types": "tsc",
21
+ "clean": "rimraf dist types coverage",
22
+ "lint": "biome lint src",
23
+ "test": "vitest run --globals",
24
+ "test:coverage": "vitest run --coverage --globals",
25
+ "test:watch": "vitest --globals",
26
+ "watch": "swc --strip-leading-paths --watch --out-dir dist src"
27
+ },
28
+ "dependencies": {
29
+ "@node-cli/logger": "../logger",
30
+ "@node-cli/parser": "../parser",
31
+ "@node-cli/utilities": "../utilities"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "devDependencies": {
37
+ "@vitest/coverage-v8": "3.2.4",
38
+ "vitest": "3.2.4"
39
+ },
40
+ "gitHead": "8fa2b0048fd24b0278b446a9291fb78506041c05"
41
+ }