@node-cli/comments 0.2.0 → 0.2.2

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.
@@ -148,9 +148,12 @@ describe("parseAndTransformComments", function() {
148
148
  expect(out).toMatch(/Overview:/);
149
149
  // Visually indented code line kept as-is (no extra wrapping collapse).
150
150
  expect(out).toMatch(/const\s{3}x = 1;/);
151
- // Trailing blank before closing is optional after recent trimming change.
152
- // (we only keep it when multiple paragraphs exist). Assert closing exists.
153
- expect(/\n\*\/$/.test(out)).toBe(true);
151
+ /**
152
+ * Trailing blank before closing is optional after recent trimming change. (we
153
+ * only keep it when multiple paragraphs exist). Assert closing exists.
154
+ * Closing delimiter should be on its own line; allow optional leading
155
+ * space(s).
156
+ */ expect(/\n\s*\*\/$/.test(out)).toBe(true);
154
157
  // Numeric list lines preserved.
155
158
  expect(out).toMatch(/1\. first/);
156
159
  expect(out).toMatch(/2\. second/);
@@ -314,12 +317,37 @@ describe("parseAndTransformComments", function() {
314
317
  mergeLineComments: true
315
318
  }).transformed;
316
319
  // Expect merged into a JSDoc immediately after the statement.
317
- var re = /compute\(\);\n\/\*\*[\s\S]*?\n\*\//;
320
+ var re = /compute\(\);\n\/\*\*[\s\S]*?\n\s*\*\//;
318
321
  expect(re.test(out)).toBe(true);
319
322
  // Ensure only one sentence-final period appended (present on final 'list.'
320
323
  // already).
321
324
  expect(out.match(/merged\./)).toBeNull();
322
325
  });
326
+ it("keeps a space before closing delimiter for complex multi-paragraph example", function() {
327
+ var input = [
328
+ "/**",
329
+ " * Extract the average from a list of numbers.",
330
+ " *",
331
+ " * @example",
332
+ " * ```js",
333
+ " * const res = extractAverage({ data: [11, 22, 33, 44] });",
334
+ " * console.log(res); // 27.5 -> (11 + 22 + 33 + 44) / 4",
335
+ " * ```",
336
+ " *",
337
+ " * Any value that is not a number or is less than 0 will be ignored.",
338
+ " *",
339
+ " * A formatter function can be passed to format the output. If no formatter is",
340
+ " * provided, the default behavior is to cast the number to the generic Output",
341
+ " * type.",
342
+ " *",
343
+ " */"
344
+ ].join("\n");
345
+ var out = parseAndTransformComments(input, baseOpts).transformed;
346
+ // Closing line should contain a leading space before */ (style consistency)
347
+ expect(/\n \*\/$/.test(out)).toBe(true);
348
+ // Should not regress by emitting no-space variant
349
+ expect(/\n\*\/$/.test(out)).toBe(false);
350
+ });
323
351
  });
324
352
 
325
353
  //# sourceMappingURL=lib.test.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/__tests__/lib.test.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { expandGlobs } from \"../glob.js\";\nimport { diffLines, parseAndTransformComments } from \"../lib.js\";\n\nconst baseOpts = {\n\twidth: 60,\n\twrapLineComments: true,\n\tmergeLineComments: false,\n};\n\ndescribe(\"parseAndTransformComments\", () => {\n\tit(\"reflows a simple jsdoc and adds period\", () => {\n\t\tconst input = \"/**\\n * This function does something\\n * important\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed).toContain(\"does something important.\");\n\t});\n\n\tit(\"normalizes NOTE capitalization\", () => {\n\t\tconst input = \"/**\\n * note: edge case\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(/NOTE: edge case/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"wraps single line comments\", () => {\n\t\tconst input =\n\t\t\t\"// this is a very long comment that should be wrapped across multiple lines to satisfy width\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed.split(/\\n/).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"merges groups of line comments into jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"// first line\",\n\t\t\t\"// second line\",\n\t\t\t\"// third line\",\n\t\t\t\"const x = 1;\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"is idempotent (second pass unchanged)\", () => {\n\t\tconst input = \"/**\\n * Example doc that will be normalized\\n */\";\n\t\tconst first = parseAndTransformComments(input, baseOpts).transformed;\n\t\tconst second = parseAndTransformComments(first, baseOpts).transformed;\n\t\texpect(diffLines(first, second)).toBe(\"\");\n\t});\n\n\tit(\"preserves code fence blocks\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * Before\\n * ```js\\n * const x= 1; \\n * ```\\n * After\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/```js/.test(res)).toBe(true);\n\t\t// ensure spacing inside fence not normalized.\n\t\texpect(/const {2}x= {2}1;/.test(res)).toBe(true);\n\t});\n\n\tit(\"does not merge directive or license groups\", () => {\n\t\tconst input = [\n\t\t\t\"// eslint-disable-next-line\",\n\t\t\t\"// second line should prevent merge due to directive\",\n\t\t\t\"const y = 2;\",\n\t\t\t\"// Copyright 2024 Example\",\n\t\t\t\"// another line\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/eslint-disable/.test(res.transformed)).toBe(true);\n\t\t// Should not have merged into a jsdoc (no /** directly before const).\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(false);\n\t});\n\n\tit(\"list items are not reflowed into a paragraph\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * First line explaining.\\n * - item one more words here\\n * - item two\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// each list item remains on its own line with leading dash.\n\t\tconst lines = res.split(/\\n/).filter((l) => /- item/.test(l));\n\t\texpect(lines.length).toBe(2);\n\t});\n\n\tit(\"tag lines are preserved\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * short description\\n * @param x value\\n * @returns something\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/@param x value/.test(res)).toBe(true);\n\t\texpect(/@returns something/.test(res)).toBe(true);\n\t});\n\n\tit(\"handles heading-like lines with colon and visually indented code & numeric lists\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Overview:\",\n\t\t\t\" * const x = 1;\",\n\t\t\t\" * 1. first\",\n\t\t\t\" * 2. second\",\n\t\t\t\" *\", // blank separation\n\t\t\t\" * Another paragraph without period\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Heading preserved, not merged into previous paragraph.\n\t\texpect(out).toMatch(/Overview:/);\n\t\t// Visually indented code line kept as-is (no extra wrapping collapse).\n\t\texpect(out).toMatch(/const\\s{3}x = 1;/);\n\t\t// Trailing blank before closing is optional after recent trimming change.\n\t\t// (we only keep it when multiple paragraphs exist). Assert closing exists.\n\t\texpect(/\\n\\*\\/$/.test(out)).toBe(true);\n\t\t// Numeric list lines preserved.\n\t\texpect(out).toMatch(/1\\. first/);\n\t\texpect(out).toMatch(/2\\. second/);\n\t\t// Trailing paragraph got terminal period.\n\t\texpect(out).toMatch(/Another paragraph without period\\./);\n\t});\n\n\tit(\"glob expansion matches deep files only with explicit globstar\", () => {\n\t\tconst tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob-\"));\n\t\tconst a = path.join(tmpRoot, \"a.ts\");\n\t\tconst nestedDir = path.join(tmpRoot, \"nested\");\n\t\tfs.mkdirSync(nestedDir, { recursive: true });\n\t\tconst b = path.join(nestedDir, \"b.ts\");\n\t\tfs.writeFileSync(a, \"// file a\", \"utf8\");\n\t\tfs.writeFileSync(b, \"// file b\", \"utf8\");\n\t\t// Shallow pattern should only see top-level a.ts.\n\t\tconst shallow = expandGlobs([`${tmpRoot}/*.ts`]).sort();\n\t\texpect(shallow).toEqual([a]);\n\t\t// Deep pattern matches both.\n\t\tconst deep = expandGlobs([`${tmpRoot}/**/*.ts`]).sort();\n\t\texpect(deep).toEqual([a, b].sort());\n\t});\n\n\t/**\n\t * Added test for preserving multi-line // comment groups that should NOT merge\n\t * when preceded by code.\n\t */\n\tit(\"does not merge an inline explanatory multi-line // comment group following code\", () => {\n\t\tconst src = [\n\t\t\t\"function demo() {\",\n\t\t\t\" const x = 1; // keep\",\n\t\t\t\" // first line explains next block\",\n\t\t\t\" // still explaining\",\n\t\t\t\" // final line\",\n\t\t\t\" return x; // done\",\n\t\t\t\"}\",\n\t\t\t\"\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\tmergeLineComments: true,\n\t\t\twrapLineComments: true,\n\t\t\twidth: 80,\n\t\t}).transformed;\n\t\texpect(out).toContain(\" // first line explains next block\");\n\t\texpect(out).toContain(\" // still explaining\");\n\t\texpect(out).toContain(\" // final line\");\n\t\texpect(out).not.toContain(\"/**\");\n\t});\n\n\tit(\"converts the multi-line explanatory block from lib.ts into a multi-line JSDoc, preserving lines\", () => {\n\t\tconst snippet = [\n\t\t\t\"// JSDoc block extraction:\",\n\t\t\t\"// Previous pattern used a lazy dot-all: ([\\\\s\\\\S]*?) which could, under\",\n\t\t\t\"// pathological inputs, produce excessive backtracking. We replace it with a\",\n\t\t\t\"// tempered pattern that advances linearly by never letting the inner part\",\n\t\t\t\"// consume a closing '*/'. This avoids catastrophic behavior while keeping\",\n\t\t\t\"// correctness.\",\n\t\t\t\"// Pattern explanation:\",\n\t\t\t\"// (^ [\\\\t ]* ) -> capture indentation at start of line (multiline mode)\",\n\t\t\t\"// /\\\\*\\\\* -> opening delimiter\",\n\t\t\t\"// ( -> capture group 2 body\",\n\t\t\t\"// (?:[^*] -> any non-* char\",\n\t\t\t\"// |\\\\*(?!/) -> or a * not followed by /\",\n\t\t\t\"// )* -> repeated greedily (cannot cross closing */)\",\n\t\t\t\"// )\",\n\t\t\t\"// \\\\n?[\\\\t ]*\\\\*/ -> optional newline + trailing indent + closing */\",\n\t\t\t\"// The greedy repetition is safe because the inner alternatives are mutually\",\n\t\t\t\"// exclusive and each consumes at least one char without overlapping on the\",\n\t\t\t\"// closing sentinel.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(snippet, {\n\t\t\twidth: 100,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Should be converted to a JSDoc (first and last lines delimiters).\n\t\tconst lines = out.split(/\\n/);\n\t\texpect(lines[0].trim()).toBe(\"/**\");\n\t\texpect(lines[lines.length - 1].trim()).toBe(\"*/\");\n\t\t// Ensure representative internal lines are present (now without leading //).\n\t\texpect(out).toContain(\"* JSDoc block extraction:\");\n\t\texpect(out).toContain(\"* Pattern explanation:\");\n\t\t// Arrow lines preserved.\n\t\tconst arrowLineCount = lines.filter((l) => /->/.test(l)).length;\n\t\texpect(arrowLineCount).toBeGreaterThanOrEqual(5);\n\t});\n\n\tit(\"does not insert period before list introduced by single lowercase word + colon\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Some utilities have logging capabilities that needs to be\",\n\t\t\t\" * tested a little bit differently:\",\n\t\t\t\" * - mocking process.exit\",\n\t\t\t\" * - console.log\",\n\t\t\t\" * - inquirer.prompt\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Ensure no stray period after 'be'.\n\t\texpect(out).not.toMatch(/needs to be\\./);\n\t\t// Ensure list items unchanged.\n\t\texpect(out).toMatch(/- mocking process\\.exit/);\n\t});\n\n\tit(\"does not add stray period before lowercase colon line inside jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Some utilities have logging capabilities that needs to be\",\n\t\t\t\" * tested a little bit differently:\",\n\t\t\t\" * - one\",\n\t\t\t\" * - two\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(out).not.toMatch(/needs to be\\./);\n\t});\n\n\tit(\"does not append periods to every line of a merged // comment group\", () => {\n\t\tconst original = [\n\t\t\t\"// We only want to add terminal punctuation once at the end of the merged\",\n\t\t\t\"// paragraph, not after every original line (which can create spurious\",\n\t\t\t\"// periods mid-sentence when lines were simple wraps). We also avoid\",\n\t\t\t\"// appending a period if the final line ends with a colon introducing a\",\n\t\t\t\"// list.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(original, {\n\t\t\twidth: 160, // keep wide to avoid secondary wrapping noise\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Ensure it became a JSDoc block.\n\t\texpect(out.startsWith(\"/**\")).toBe(true);\n\t\t// Should not contain stray periods after former line breaks.\n\t\texpect(out).not.toMatch(/merged\\./);\n\t\texpect(out).not.toMatch(/spurious\\./);\n\t\texpect(out).not.toMatch(/introducing a\\./);\n\t\t// Should still retain existing legitimate period after 'wraps).' and final\n\t\t// 'list.'\n\t\texpect(out).toMatch(/wraps\\)\\./);\n\t\texpect(out).toMatch(/list\\./);\n\t});\n\n\tit(\"merges a large explanatory // group after a statement into JSDoc\", () => {\n\t\tconst src = [\n\t\t\t\"const value = compute();\",\n\t\t\t\"// We only want to add terminal punctuation once at the end of the merged\",\n\t\t\t\"// paragraph, not after every original line (which can create spurious\",\n\t\t\t\"// periods mid-sentence when lines were simple wraps). We also avoid\",\n\t\t\t\"// appending a period if the final line ends with a colon introducing a\",\n\t\t\t\"// list.\",\n\t\t\t\"function next() {}\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\twidth: 160,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Expect merged into a JSDoc immediately after the statement.\n\t\tconst re = /compute\\(\\);\\n\\/\\*\\*[\\s\\S]*?\\n\\*\\//;\n\t\texpect(re.test(out)).toBe(true);\n\t\t// Ensure only one sentence-final period appended (present on final 'list.'\n\t\t// already).\n\t\texpect(out.match(/merged\\./)).toBeNull();\n\t});\n});\n"],"names":["fs","os","path","describe","expect","it","expandGlobs","diffLines","parseAndTransformComments","baseOpts","width","wrapLineComments","mergeLineComments","input","res","transformed","toContain","test","toBe","split","length","toBeGreaterThan","join","first","second","lines","filter","l","out","toMatch","tmpRoot","mkdtempSync","tmpdir","a","nestedDir","mkdirSync","recursive","b","writeFileSync","shallow","sort","toEqual","deep","src","not","snippet","trim","arrowLineCount","toBeGreaterThanOrEqual","original","startsWith","re","match","toBeNull"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/__tests__/lib.test.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { expandGlobs } from \"../glob.js\";\nimport { diffLines, parseAndTransformComments } from \"../lib.js\";\n\nconst baseOpts = {\n\twidth: 60,\n\twrapLineComments: true,\n\tmergeLineComments: false,\n};\n\ndescribe(\"parseAndTransformComments\", () => {\n\tit(\"reflows a simple jsdoc and adds period\", () => {\n\t\tconst input = \"/**\\n * This function does something\\n * important\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed).toContain(\"does something important.\");\n\t});\n\n\tit(\"normalizes NOTE capitalization\", () => {\n\t\tconst input = \"/**\\n * note: edge case\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(/NOTE: edge case/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"wraps single line comments\", () => {\n\t\tconst input =\n\t\t\t\"// this is a very long comment that should be wrapped across multiple lines to satisfy width\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed.split(/\\n/).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"merges groups of line comments into jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"// first line\",\n\t\t\t\"// second line\",\n\t\t\t\"// third line\",\n\t\t\t\"const x = 1;\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"is idempotent (second pass unchanged)\", () => {\n\t\tconst input = \"/**\\n * Example doc that will be normalized\\n */\";\n\t\tconst first = parseAndTransformComments(input, baseOpts).transformed;\n\t\tconst second = parseAndTransformComments(first, baseOpts).transformed;\n\t\texpect(diffLines(first, second)).toBe(\"\");\n\t});\n\n\tit(\"preserves code fence blocks\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * Before\\n * ```js\\n * const x= 1; \\n * ```\\n * After\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/```js/.test(res)).toBe(true);\n\t\t// ensure spacing inside fence not normalized.\n\t\texpect(/const {2}x= {2}1;/.test(res)).toBe(true);\n\t});\n\n\tit(\"does not merge directive or license groups\", () => {\n\t\tconst input = [\n\t\t\t\"// eslint-disable-next-line\",\n\t\t\t\"// second line should prevent merge due to directive\",\n\t\t\t\"const y = 2;\",\n\t\t\t\"// Copyright 2024 Example\",\n\t\t\t\"// another line\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/eslint-disable/.test(res.transformed)).toBe(true);\n\t\t// Should not have merged into a jsdoc (no /** directly before const).\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(false);\n\t});\n\n\tit(\"list items are not reflowed into a paragraph\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * First line explaining.\\n * - item one more words here\\n * - item two\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// each list item remains on its own line with leading dash.\n\t\tconst lines = res.split(/\\n/).filter((l) => /- item/.test(l));\n\t\texpect(lines.length).toBe(2);\n\t});\n\n\tit(\"tag lines are preserved\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * short description\\n * @param x value\\n * @returns something\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/@param x value/.test(res)).toBe(true);\n\t\texpect(/@returns something/.test(res)).toBe(true);\n\t});\n\n\tit(\"handles heading-like lines with colon and visually indented code & numeric lists\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Overview:\",\n\t\t\t\" * const x = 1;\",\n\t\t\t\" * 1. first\",\n\t\t\t\" * 2. second\",\n\t\t\t\" *\", // blank separation\n\t\t\t\" * Another paragraph without period\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Heading preserved, not merged into previous paragraph.\n\t\texpect(out).toMatch(/Overview:/);\n\t\t// Visually indented code line kept as-is (no extra wrapping collapse).\n\t\texpect(out).toMatch(/const\\s{3}x = 1;/);\n\t\t/**\n\t\t * Trailing blank before closing is optional after recent trimming change. (we\n\t\t * only keep it when multiple paragraphs exist). Assert closing exists.\n\t\t * Closing delimiter should be on its own line; allow optional leading\n\t\t * space(s).\n\t\t */\n\t\texpect(/\\n\\s*\\*\\/$/.test(out)).toBe(true);\n\t\t// Numeric list lines preserved.\n\t\texpect(out).toMatch(/1\\. first/);\n\t\texpect(out).toMatch(/2\\. second/);\n\t\t// Trailing paragraph got terminal period.\n\t\texpect(out).toMatch(/Another paragraph without period\\./);\n\t});\n\n\tit(\"glob expansion matches deep files only with explicit globstar\", () => {\n\t\tconst tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob-\"));\n\t\tconst a = path.join(tmpRoot, \"a.ts\");\n\t\tconst nestedDir = path.join(tmpRoot, \"nested\");\n\t\tfs.mkdirSync(nestedDir, { recursive: true });\n\t\tconst b = path.join(nestedDir, \"b.ts\");\n\t\tfs.writeFileSync(a, \"// file a\", \"utf8\");\n\t\tfs.writeFileSync(b, \"// file b\", \"utf8\");\n\t\t// Shallow pattern should only see top-level a.ts.\n\t\tconst shallow = expandGlobs([`${tmpRoot}/*.ts`]).sort();\n\t\texpect(shallow).toEqual([a]);\n\t\t// Deep pattern matches both.\n\t\tconst deep = expandGlobs([`${tmpRoot}/**/*.ts`]).sort();\n\t\texpect(deep).toEqual([a, b].sort());\n\t});\n\n\t/**\n\t * Added test for preserving multi-line // comment groups that should NOT merge\n\t * when preceded by code.\n\t */\n\tit(\"does not merge an inline explanatory multi-line // comment group following code\", () => {\n\t\tconst src = [\n\t\t\t\"function demo() {\",\n\t\t\t\" const x = 1; // keep\",\n\t\t\t\" // first line explains next block\",\n\t\t\t\" // still explaining\",\n\t\t\t\" // final line\",\n\t\t\t\" return x; // done\",\n\t\t\t\"}\",\n\t\t\t\"\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\tmergeLineComments: true,\n\t\t\twrapLineComments: true,\n\t\t\twidth: 80,\n\t\t}).transformed;\n\t\texpect(out).toContain(\" // first line explains next block\");\n\t\texpect(out).toContain(\" // still explaining\");\n\t\texpect(out).toContain(\" // final line\");\n\t\texpect(out).not.toContain(\"/**\");\n\t});\n\n\tit(\"converts the multi-line explanatory block from lib.ts into a multi-line JSDoc, preserving lines\", () => {\n\t\tconst snippet = [\n\t\t\t\"// JSDoc block extraction:\",\n\t\t\t\"// Previous pattern used a lazy dot-all: ([\\\\s\\\\S]*?) which could, under\",\n\t\t\t\"// pathological inputs, produce excessive backtracking. We replace it with a\",\n\t\t\t\"// tempered pattern that advances linearly by never letting the inner part\",\n\t\t\t\"// consume a closing '*/'. This avoids catastrophic behavior while keeping\",\n\t\t\t\"// correctness.\",\n\t\t\t\"// Pattern explanation:\",\n\t\t\t\"// (^ [\\\\t ]* ) -> capture indentation at start of line (multiline mode)\",\n\t\t\t\"// /\\\\*\\\\* -> opening delimiter\",\n\t\t\t\"// ( -> capture group 2 body\",\n\t\t\t\"// (?:[^*] -> any non-* char\",\n\t\t\t\"// |\\\\*(?!/) -> or a * not followed by /\",\n\t\t\t\"// )* -> repeated greedily (cannot cross closing */)\",\n\t\t\t\"// )\",\n\t\t\t\"// \\\\n?[\\\\t ]*\\\\*/ -> optional newline + trailing indent + closing */\",\n\t\t\t\"// The greedy repetition is safe because the inner alternatives are mutually\",\n\t\t\t\"// exclusive and each consumes at least one char without overlapping on the\",\n\t\t\t\"// closing sentinel.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(snippet, {\n\t\t\twidth: 100,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Should be converted to a JSDoc (first and last lines delimiters).\n\t\tconst lines = out.split(/\\n/);\n\t\texpect(lines[0].trim()).toBe(\"/**\");\n\t\texpect(lines[lines.length - 1].trim()).toBe(\"*/\");\n\t\t// Ensure representative internal lines are present (now without leading //).\n\t\texpect(out).toContain(\"* JSDoc block extraction:\");\n\t\texpect(out).toContain(\"* Pattern explanation:\");\n\t\t// Arrow lines preserved.\n\t\tconst arrowLineCount = lines.filter((l) => /->/.test(l)).length;\n\t\texpect(arrowLineCount).toBeGreaterThanOrEqual(5);\n\t});\n\n\tit(\"does not insert period before list introduced by single lowercase word + colon\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Some utilities have logging capabilities that needs to be\",\n\t\t\t\" * tested a little bit differently:\",\n\t\t\t\" * - mocking process.exit\",\n\t\t\t\" * - console.log\",\n\t\t\t\" * - inquirer.prompt\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Ensure no stray period after 'be'.\n\t\texpect(out).not.toMatch(/needs to be\\./);\n\t\t// Ensure list items unchanged.\n\t\texpect(out).toMatch(/- mocking process\\.exit/);\n\t});\n\n\tit(\"does not add stray period before lowercase colon line inside jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Some utilities have logging capabilities that needs to be\",\n\t\t\t\" * tested a little bit differently:\",\n\t\t\t\" * - one\",\n\t\t\t\" * - two\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(out).not.toMatch(/needs to be\\./);\n\t});\n\n\tit(\"does not append periods to every line of a merged // comment group\", () => {\n\t\tconst original = [\n\t\t\t\"// We only want to add terminal punctuation once at the end of the merged\",\n\t\t\t\"// paragraph, not after every original line (which can create spurious\",\n\t\t\t\"// periods mid-sentence when lines were simple wraps). We also avoid\",\n\t\t\t\"// appending a period if the final line ends with a colon introducing a\",\n\t\t\t\"// list.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(original, {\n\t\t\twidth: 160, // keep wide to avoid secondary wrapping noise\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Ensure it became a JSDoc block.\n\t\texpect(out.startsWith(\"/**\")).toBe(true);\n\t\t// Should not contain stray periods after former line breaks.\n\t\texpect(out).not.toMatch(/merged\\./);\n\t\texpect(out).not.toMatch(/spurious\\./);\n\t\texpect(out).not.toMatch(/introducing a\\./);\n\t\t// Should still retain existing legitimate period after 'wraps).' and final\n\t\t// 'list.'\n\t\texpect(out).toMatch(/wraps\\)\\./);\n\t\texpect(out).toMatch(/list\\./);\n\t});\n\n\tit(\"merges a large explanatory // group after a statement into JSDoc\", () => {\n\t\tconst src = [\n\t\t\t\"const value = compute();\",\n\t\t\t\"// We only want to add terminal punctuation once at the end of the merged\",\n\t\t\t\"// paragraph, not after every original line (which can create spurious\",\n\t\t\t\"// periods mid-sentence when lines were simple wraps). We also avoid\",\n\t\t\t\"// appending a period if the final line ends with a colon introducing a\",\n\t\t\t\"// list.\",\n\t\t\t\"function next() {}\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\twidth: 160,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Expect merged into a JSDoc immediately after the statement.\n\t\tconst re = /compute\\(\\);\\n\\/\\*\\*[\\s\\S]*?\\n\\s*\\*\\//;\n\t\texpect(re.test(out)).toBe(true);\n\t\t// Ensure only one sentence-final period appended (present on final 'list.'\n\t\t// already).\n\t\texpect(out.match(/merged\\./)).toBeNull();\n\t});\n\n\tit(\"keeps a space before closing delimiter for complex multi-paragraph example\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Extract the average from a list of numbers.\",\n\t\t\t\" *\",\n\t\t\t\" * @example\",\n\t\t\t\" * ```js\",\n\t\t\t\" * const res = extractAverage({ data: [11, 22, 33, 44] });\",\n\t\t\t\" * console.log(res); // 27.5 -> (11 + 22 + 33 + 44) / 4\",\n\t\t\t\" * ```\",\n\t\t\t\" *\",\n\t\t\t\" * Any value that is not a number or is less than 0 will be ignored.\",\n\t\t\t\" *\",\n\t\t\t\" * A formatter function can be passed to format the output. If no formatter is\",\n\t\t\t\" * provided, the default behavior is to cast the number to the generic Output\",\n\t\t\t\" * type.\",\n\t\t\t\" *\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Closing line should contain a leading space before */ (style consistency)\n\t\texpect(/\\n \\*\\/$/.test(out)).toBe(true);\n\t\t// Should not regress by emitting no-space variant\n\t\texpect(/\\n\\*\\/$/.test(out)).toBe(false);\n\t});\n});\n"],"names":["fs","os","path","describe","expect","it","expandGlobs","diffLines","parseAndTransformComments","baseOpts","width","wrapLineComments","mergeLineComments","input","res","transformed","toContain","test","toBe","split","length","toBeGreaterThan","join","first","second","lines","filter","l","out","toMatch","tmpRoot","mkdtempSync","tmpdir","a","nestedDir","mkdirSync","recursive","b","writeFileSync","shallow","sort","toEqual","deep","src","not","snippet","trim","arrowLineCount","toBeGreaterThanOrEqual","original","startsWith","re","match","toBeNull"],"mappings":"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"}
package/dist/lib.js CHANGED
@@ -232,7 +232,8 @@ function buildJsDoc(indent, rawBody, width) {
232
232
  }
233
233
  }
234
234
  }
235
- return "".concat(indent, "/**\n").concat(out.join("\n"), "\n").concat(indent, "*/");
235
+ // Consistent style: space before closing */
236
+ return "".concat(indent, "/**\n").concat(out.join("\n"), "\n").concat(indent, " */");
236
237
  }
237
238
  function flush() {
238
239
  if (!para.length) {
@@ -306,7 +307,10 @@ function buildJsDoc(indent, rawBody, width) {
306
307
  }
307
308
  }
308
309
  flush();
309
- return "".concat(indent, "/**\n").concat(out.join("\n"), "\n").concat(indent, "*/");
310
+ // Style: ensure a space precedes the closing */ for consistency with blocks
311
+ // generated elsewhere in this tool (merged line comment groups). Previously
312
+ // we emitted `${indent}*/` which produced an off-by-one visual alignment.
313
+ return "".concat(indent, "/**\n").concat(out.join("\n"), "\n").concat(indent, " */");
310
314
  }
311
315
  function reflowJsDocBlocks(content, width) {
312
316
  JSDOC_REGEX.lastIndex = 0;
package/dist/lib.js.map CHANGED
@@ -1 +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/**\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\n * real source formatting and could be used to inflate processing time if a\n * regex exhibited super-linear behavior. Our pattern is already linear\n * (tempered), but we still cap accepted indentation length to keep work\n * bounded.\n */\nconst MAX_JSDOC_INDENT = 256; // characters (tabs + spaces)\n\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.\n *\n */\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\tif (!/:$/.test(t) || isTagLine(t)) {\n\t\treturn false;\n\t}\n\t/**\n\t * New heuristic: treat as heading only if composed of one or more words that\n\t * each start with an uppercase letter (allows Internal IDs with\n\t * dashes/underscores too). Examples considered headings: \"Overview:\",\n\t * \"Performance Notes:\", \"API Surface:\". Non-headings (treated as sentence\n\t * continuation): \"tested a little bit differently:\", \"differently:\".\n\t */\n\treturn /^[A-Z][A-Za-z0-9_-]*(?: [A-Z][A-Za-z0-9_-]*)*:$/.test(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\tlet lines = rawBody.split(/\\n/).map((l) => l.replace(/^\\s*\\*? ?/, \"\"));\n\t// Remove a single leading blank line (artifact of regex capture starting after\n\t// /**) if content follows.\n\twhile (\n\t\tlines.length > 1 &&\n\t\tlines[0].trim() === \"\" &&\n\t\tlines.some((l) => l.trim() !== \"\")\n\t) {\n\t\tlines = lines.slice(1);\n\t}\n\t/**\n\t * Trailing blank handling: keep a single trailing blank only if there are\n\t * multiple paragraphs (i.e., an internal blank separator exists). If the doc\n\t * is a single paragraph, drop the trailing blank to avoid an extra standalone\n\t * '*' line before the closing delimiter.\n\t */\n\tif (lines.length > 1 && lines[lines.length - 1].trim() === \"\") {\n\t\tconst internalBlank = lines.slice(0, -1).some((l) => l.trim() === \"\");\n\t\tif (!internalBlank) {\n\t\t\tlines = lines.slice(0, -1);\n\t\t}\n\t}\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\t/**\n\t * Detect structured explanatory / regex description blocks where we want to\n\t * preserve each original line verbatim (no paragraph joining or sentence\n\t * period insertion) to avoid altering carefully aligned or enumerated lines.\n\t */\n\tconst structured = lines.some(\n\t\t(l) =>\n\t\t\t/->/.test(l) || /(\\(\\?:|\\*\\/)/.test(l) || /Pattern explanation:/i.test(l),\n\t);\n\tif (structured) {\n\t\tfor (const raw of lines) {\n\t\t\tconst trimmed = raw.trimEnd();\n\t\t\tif (trimmed === \"\") {\n\t\t\t\t// ensure a blank line represented by a lone '*'.\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\tcontinue;\n\t\t\t}\n\t\t\tout.push(prefix + normalizeNote(trimmed));\n\t\t}\n\t\treturn `${indent}/**\\n${out.join(\"\\n\")}\\n${indent}*/`;\n\t}\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\tlet i = 0;\n\twhile (i < lines.length) {\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\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\t/**\n\t\t * Collect a group of consecutive simple // lines (not triple slash) that are\n\t\t * eligible.\n\t\t */\n\t\tconst group: { raw: string; indent: string; body: string }[] = [];\n\t\tlet j = i;\n\t\twhile (j < lines.length) {\n\t\t\tconst gm = /^(\\s*)\\/\\/ ?(.*)$/.exec(lines[j]);\n\t\t\tif (!gm || /^\\/\\/\\//.test(lines[j])) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst body = gm[2];\n\t\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\t\tbreak; // stop group before directives/URLs; process current line normally\n\t\t\t}\n\t\t\tgroup.push({ raw: lines[j], indent: gm[1], body });\n\t\t\tj++;\n\t\t}\n\t\tif (group.length <= 1) {\n\t\t\t// Single line: existing logic (add period if needed).\n\t\t\tconst indent = m[1];\n\t\t\tconst body = m[3];\n\t\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\t\tout.push(line);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst prefix = indent + \"// \";\n\t\t\tconst avail = Math.max(10, width - prefix.length);\n\t\t\tlet text = body.replace(/\\s+/g, \" \").trim();\n\t\t\ttext = normalizeNote(text);\n\t\t\ttext = maybeAddPeriod(text);\n\t\t\tconst wrapped = wrapWords(text, avail).map((w) => prefix + w);\n\t\t\tif (wrapped.join(\"\\n\") !== line) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tout.push(...wrapped);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\t/**\n\t\t * Multi-line group: only add terminal punctuation (period) to final line if\n\t\t * needed. Other lines are normalized for NOTE but left without forced\n\t\t * punctuation.\n\t\t */\n\t\tfor (let k = 0; k < group.length; k++) {\n\t\t\tconst { indent, body } = group[k];\n\t\t\tconst prefix = indent + \"// \";\n\t\t\tconst avail = Math.max(10, width - prefix.length);\n\t\t\tlet text = body.replace(/\\s+/g, \" \").trim();\n\t\t\ttext = normalizeNote(text);\n\t\t\tif (k === group.length - 1 && !/:$/.test(text.trim())) {\n\t\t\t\ttext = maybeAddPeriod(text);\n\t\t\t}\n\t\t\tconst wrapped = wrapWords(text, avail).map((w) => prefix + w);\n\t\t\tif (wrapped.join(\"\\n\") !== group[k].raw) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tout.push(...wrapped);\n\t\t}\n\t\ti = j;\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\n\tfunction qualifiesExplanatoryAfterStatement(start: number): boolean {\n\t\t// Peek ahead to collect consecutive // lines (excluding triple slash).\n\t\tconst collected: string[] = [];\n\t\tfor (let k = start; k < lines.length; k++) {\n\t\t\tconst lm = /^(\\s*)\\/\\/( ?)(.*)$/.exec(lines[k]);\n\t\t\tif (!lm || /^\\/\\/\\//.test(lines[k])) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst body = lm[3];\n\t\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcollected.push(body.trim());\n\t\t}\n\t\tif (collected.length < 4) {\n\t\t\treturn false; // require minimum size\n\t\t}\n\t\tif (!/^[A-Z]/.test(collected[0])) {\n\t\t\treturn false; // start with capitalized sentence\n\t\t}\n\t\t/**\n\t\t * Avoid matching directive-like or list-lists: require at least one line with\n\t\t * a space (a sentence).\n\t\t */\n\t\treturn collected.some((c) => /\\s/.test(c));\n\t}\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\tlet contextEligible = prevTrim === \"\" || /[{}]$/.test(prevTrim);\n\t\t\t/**\n\t\t\t * Additional heuristic: allow large explanatory group after a statement\n\t\t\t * ending with ';' (but not inline trailing comment scenario) when it\n\t\t\t * qualifies as explanatory.\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!contextEligible &&\n\t\t\t\t/;\\s*$/.test(prevTrim) &&\n\t\t\t\tqualifiesExplanatoryAfterStatement(i)\n\t\t\t) {\n\t\t\t\tcontextEligible = true;\n\t\t\t}\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/**\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:\n\t\t\t\t * presence of arrows (->), regex tokens (?:, *\\/), or the phrase 'Pattern explanation:'.\n\t\t\t\t */\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\t/**\n\t\t\t\t * We only want to add terminal punctuation once at the end of the merged\n\t\t\t\t * paragraph, not after every original line (which can create spurious\n\t\t\t\t * periods mid-sentence when lines were simple wraps). We also avoid\n\t\t\t\t * appending a period if the final line ends with a colon introducing a\n\t\t\t\t * list.\n\t\t\t\t */\n\t\t\t\tconst norm = group.map((g) => normalizeNote(g.text.trim()));\n\t\t\t\t// Determine index of last non-empty line.\n\t\t\t\tlet lastIdx = norm.length - 1;\n\t\t\t\twhile (lastIdx > 0 && norm[lastIdx].trim() === \"\") {\n\t\t\t\t\tlastIdx--;\n\t\t\t\t}\n\t\t\t\tfor (let k = 0; k < norm.length; k++) {\n\t\t\t\t\tif (k === lastIdx) {\n\t\t\t\t\t\tconst ln = norm[k];\n\t\t\t\t\t\tif (!/:$/.test(ln.trim())) {\n\t\t\t\t\t\t\tnorm[k] = maybeAddPeriod(ln);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst para = norm.join(\" \").replace(/\\s+/g, \" \").trim();\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","some","slice","internalBlank","para","inFence","prefix","avail","structured","raw","trimmed","trimEnd","flush","reflowJsDocBlocks","content","lastIndex","blocks","exec","body","start","index","end","delta","original","built","wrapLineComments","group","k","wrapped","changed","j","gm","applied","mergeLineCommentGroups","merged","qualifiesExplanatoryAfterStatement","collected","lm","c","prev","prevTrim","contextEligible","txt","g","ln","safe","norm","lastIdx","parseAndTransformComments","input","options","working","mergeLineComments","js","transformed"],"mappings":"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"}
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/**\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\n * real source formatting and could be used to inflate processing time if a\n * regex exhibited super-linear behavior. Our pattern is already linear\n * (tempered), but we still cap accepted indentation length to keep work\n * bounded.\n */\nconst MAX_JSDOC_INDENT = 256; // characters (tabs + spaces)\n\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.\n *\n */\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\tif (!/:$/.test(t) || isTagLine(t)) {\n\t\treturn false;\n\t}\n\t/**\n\t * New heuristic: treat as heading only if composed of one or more words that\n\t * each start with an uppercase letter (allows Internal IDs with\n\t * dashes/underscores too). Examples considered headings: \"Overview:\",\n\t * \"Performance Notes:\", \"API Surface:\". Non-headings (treated as sentence\n\t * continuation): \"tested a little bit differently:\", \"differently:\".\n\t */\n\treturn /^[A-Z][A-Za-z0-9_-]*(?: [A-Z][A-Za-z0-9_-]*)*:$/.test(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\tlet lines = rawBody.split(/\\n/).map((l) => l.replace(/^\\s*\\*? ?/, \"\"));\n\t// Remove a single leading blank line (artifact of regex capture starting after\n\t// /**) if content follows.\n\twhile (\n\t\tlines.length > 1 &&\n\t\tlines[0].trim() === \"\" &&\n\t\tlines.some((l) => l.trim() !== \"\")\n\t) {\n\t\tlines = lines.slice(1);\n\t}\n\t/**\n\t * Trailing blank handling: keep a single trailing blank only if there are\n\t * multiple paragraphs (i.e., an internal blank separator exists). If the doc\n\t * is a single paragraph, drop the trailing blank to avoid an extra standalone\n\t * '*' line before the closing delimiter.\n\t */\n\tif (lines.length > 1 && lines[lines.length - 1].trim() === \"\") {\n\t\tconst internalBlank = lines.slice(0, -1).some((l) => l.trim() === \"\");\n\t\tif (!internalBlank) {\n\t\t\tlines = lines.slice(0, -1);\n\t\t}\n\t}\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\t/**\n\t * Detect structured explanatory / regex description blocks where we want to\n\t * preserve each original line verbatim (no paragraph joining or sentence\n\t * period insertion) to avoid altering carefully aligned or enumerated lines.\n\t */\n\tconst structured = lines.some(\n\t\t(l) =>\n\t\t\t/->/.test(l) || /(\\(\\?:|\\*\\/)/.test(l) || /Pattern explanation:/i.test(l),\n\t);\n\tif (structured) {\n\t\tfor (const raw of lines) {\n\t\t\tconst trimmed = raw.trimEnd();\n\t\t\tif (trimmed === \"\") {\n\t\t\t\t// ensure a blank line represented by a lone '*'.\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\tcontinue;\n\t\t\t}\n\t\t\tout.push(prefix + normalizeNote(trimmed));\n\t\t}\n\t\t// Consistent style: space before closing */\n\t\treturn `${indent}/**\\n${out.join(\"\\n\")}\\n${indent} */`;\n\t}\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\t// Style: ensure a space precedes the closing */ for consistency with blocks\n\t// generated elsewhere in this tool (merged line comment groups). Previously\n\t// we emitted `${indent}*/` which produced an off-by-one visual alignment.\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\tlet i = 0;\n\twhile (i < lines.length) {\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\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\t/**\n\t\t * Collect a group of consecutive simple // lines (not triple slash) that are\n\t\t * eligible.\n\t\t */\n\t\tconst group: { raw: string; indent: string; body: string }[] = [];\n\t\tlet j = i;\n\t\twhile (j < lines.length) {\n\t\t\tconst gm = /^(\\s*)\\/\\/ ?(.*)$/.exec(lines[j]);\n\t\t\tif (!gm || /^\\/\\/\\//.test(lines[j])) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst body = gm[2];\n\t\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\t\tbreak; // stop group before directives/URLs; process current line normally\n\t\t\t}\n\t\t\tgroup.push({ raw: lines[j], indent: gm[1], body });\n\t\t\tj++;\n\t\t}\n\t\tif (group.length <= 1) {\n\t\t\t// Single line: existing logic (add period if needed).\n\t\t\tconst indent = m[1];\n\t\t\tconst body = m[3];\n\t\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\t\tout.push(line);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst prefix = indent + \"// \";\n\t\t\tconst avail = Math.max(10, width - prefix.length);\n\t\t\tlet text = body.replace(/\\s+/g, \" \").trim();\n\t\t\ttext = normalizeNote(text);\n\t\t\ttext = maybeAddPeriod(text);\n\t\t\tconst wrapped = wrapWords(text, avail).map((w) => prefix + w);\n\t\t\tif (wrapped.join(\"\\n\") !== line) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tout.push(...wrapped);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\t/**\n\t\t * Multi-line group: only add terminal punctuation (period) to final line if\n\t\t * needed. Other lines are normalized for NOTE but left without forced\n\t\t * punctuation.\n\t\t */\n\t\tfor (let k = 0; k < group.length; k++) {\n\t\t\tconst { indent, body } = group[k];\n\t\t\tconst prefix = indent + \"// \";\n\t\t\tconst avail = Math.max(10, width - prefix.length);\n\t\t\tlet text = body.replace(/\\s+/g, \" \").trim();\n\t\t\ttext = normalizeNote(text);\n\t\t\tif (k === group.length - 1 && !/:$/.test(text.trim())) {\n\t\t\t\ttext = maybeAddPeriod(text);\n\t\t\t}\n\t\t\tconst wrapped = wrapWords(text, avail).map((w) => prefix + w);\n\t\t\tif (wrapped.join(\"\\n\") !== group[k].raw) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tout.push(...wrapped);\n\t\t}\n\t\ti = j;\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\n\tfunction qualifiesExplanatoryAfterStatement(start: number): boolean {\n\t\t// Peek ahead to collect consecutive // lines (excluding triple slash).\n\t\tconst collected: string[] = [];\n\t\tfor (let k = start; k < lines.length; k++) {\n\t\t\tconst lm = /^(\\s*)\\/\\/( ?)(.*)$/.exec(lines[k]);\n\t\t\tif (!lm || /^\\/\\/\\//.test(lines[k])) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst body = lm[3];\n\t\t\tif (/^(@|eslint|ts-ignore)/.test(body) || /https?:\\/\\//.test(body)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcollected.push(body.trim());\n\t\t}\n\t\tif (collected.length < 4) {\n\t\t\treturn false; // require minimum size\n\t\t}\n\t\tif (!/^[A-Z]/.test(collected[0])) {\n\t\t\treturn false; // start with capitalized sentence\n\t\t}\n\t\t/**\n\t\t * Avoid matching directive-like or list-lists: require at least one line with\n\t\t * a space (a sentence).\n\t\t */\n\t\treturn collected.some((c) => /\\s/.test(c));\n\t}\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\tlet contextEligible = prevTrim === \"\" || /[{}]$/.test(prevTrim);\n\t\t\t/**\n\t\t\t * Additional heuristic: allow large explanatory group after a statement\n\t\t\t * ending with ';' (but not inline trailing comment scenario) when it\n\t\t\t * qualifies as explanatory.\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!contextEligible &&\n\t\t\t\t/;\\s*$/.test(prevTrim) &&\n\t\t\t\tqualifiesExplanatoryAfterStatement(i)\n\t\t\t) {\n\t\t\t\tcontextEligible = true;\n\t\t\t}\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/**\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:\n\t\t\t\t * presence of arrows (->), regex tokens (?:, *\\/), or the phrase 'Pattern explanation:'.\n\t\t\t\t */\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\t/**\n\t\t\t\t * We only want to add terminal punctuation once at the end of the merged\n\t\t\t\t * paragraph, not after every original line (which can create spurious\n\t\t\t\t * periods mid-sentence when lines were simple wraps). We also avoid\n\t\t\t\t * appending a period if the final line ends with a colon introducing a\n\t\t\t\t * list.\n\t\t\t\t */\n\t\t\t\tconst norm = group.map((g) => normalizeNote(g.text.trim()));\n\t\t\t\t// Determine index of last non-empty line.\n\t\t\t\tlet lastIdx = norm.length - 1;\n\t\t\t\twhile (lastIdx > 0 && norm[lastIdx].trim() === \"\") {\n\t\t\t\t\tlastIdx--;\n\t\t\t\t}\n\t\t\t\tfor (let k = 0; k < norm.length; k++) {\n\t\t\t\t\tif (k === lastIdx) {\n\t\t\t\t\t\tconst ln = norm[k];\n\t\t\t\t\t\tif (!/:$/.test(ln.trim())) {\n\t\t\t\t\t\t\tnorm[k] = maybeAddPeriod(ln);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst para = norm.join(\" \").replace(/\\s+/g, \" \").trim();\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","some","slice","internalBlank","para","inFence","prefix","avail","structured","raw","trimmed","trimEnd","flush","reflowJsDocBlocks","content","lastIndex","blocks","exec","body","start","index","end","delta","original","built","wrapLineComments","group","k","wrapped","changed","j","gm","applied","mergeLineCommentGroups","merged","qualifiesExplanatoryAfterStatement","collected","lm","c","prev","prevTrim","contextEligible","txt","g","ln","safe","norm","lastIdx","parseAndTransformComments","input","options","working","mergeLineComments","js","transformed"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-cli/comments",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "description": "CLI tool to reflow and normalize JSDoc and line comments in source files",
@@ -40,5 +40,5 @@
40
40
  "@vitest/coverage-v8": "3.2.4",
41
41
  "vitest": "3.2.4"
42
42
  },
43
- "gitHead": "d90392dcb766dd605bc3eeabc7c7a7ab0c8e6da6"
43
+ "gitHead": "50a4c2186a7f985f4bd7fa729735fcd55b42bee9"
44
44
  }