@kongyo2/ts-comment-scanner 0.0.0 → 1.0.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/files.js CHANGED
@@ -1,17 +1,27 @@
1
1
  import { readFile, readdir, stat } from "node:fs/promises";
2
- import { extname, join } from "node:path";
2
+ import { join, normalize, relative, sep } from "node:path";
3
+ import picomatch from "picomatch";
3
4
  import { scanComments } from "./scanner.js";
4
5
  const DEFAULT_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts"];
5
6
  const DEFAULT_IGNORE_DIRS = ["node_modules", ".git"];
6
- const READ_CONCURRENCY = 16;
7
7
  export async function collectFiles(inputs, options = {}) {
8
- const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
8
+ const extensions = normalizeExtensions(options.extensions ?? DEFAULT_EXTENSIONS);
9
9
  const ignoreDirs = new Set(options.ignoreDirs ?? DEFAULT_IGNORE_DIRS);
10
+ const isIgnored = buildIgnoreMatcher(options.ignore ?? []);
10
11
  const found = new Set();
11
- await Promise.all(inputs.map(async (input) => {
12
+ await Promise.all(inputs.map(async (rawInput) => {
13
+ if (rawInput === "") {
14
+ // normalize("") would resolve to "." and silently widen the scan.
15
+ throw new Error("empty path is not a valid input");
16
+ }
17
+ const input = normalize(rawInput);
12
18
  const info = await stat(input);
13
19
  if (info.isDirectory()) {
14
- await walk(input, extensions, ignoreDirs, found);
20
+ // Directory inputs are themselves subject to the ignore patterns;
21
+ // only explicitly listed files bypass them.
22
+ if (!isIgnored(input, input)) {
23
+ await walk(input, { extensions, ignoreDirs, isIgnored, root: input }, found);
24
+ }
15
25
  }
16
26
  else {
17
27
  found.add(input);
@@ -19,38 +29,92 @@ export async function collectFiles(inputs, options = {}) {
19
29
  }));
20
30
  return [...found].sort();
21
31
  }
22
- async function walk(dir, extensions, ignoreDirs, found) {
32
+ async function walk(dir, context, found) {
23
33
  const entries = await readdir(dir, { withFileTypes: true });
24
34
  await Promise.all(entries.map(async (entry) => {
25
35
  const full = join(dir, entry.name);
26
36
  if (entry.isDirectory()) {
27
- if (!ignoreDirs.has(entry.name)) {
28
- await walk(full, extensions, ignoreDirs, found);
37
+ if (!context.ignoreDirs.has(entry.name) && !context.isIgnored(full, context.root)) {
38
+ await walk(full, context, found);
29
39
  }
30
40
  }
31
- else if (entry.isFile() && extensions.includes(extname(entry.name))) {
41
+ else if (entry.isFile() &&
42
+ hasExtension(entry.name, context.extensions) &&
43
+ !context.isIgnored(full, context.root)) {
32
44
  found.add(full);
33
45
  }
34
46
  }));
35
47
  }
48
+ function normalizeExtensions(extensions) {
49
+ return extensions.map((extension) => {
50
+ const withDot = extension.startsWith(".") ? extension : `.${extension}`;
51
+ return withDot.toLowerCase();
52
+ });
53
+ }
54
+ /** Suffix match so compound extensions like `.d.ts` work; `extname` would only see `.ts`. */
55
+ function hasExtension(name, extensions) {
56
+ const lower = name.toLowerCase();
57
+ return extensions.some((extension) => lower.endsWith(extension));
58
+ }
59
+ function buildIgnoreMatcher(patterns) {
60
+ if (patterns.length === 0)
61
+ return () => false;
62
+ // Gitignore-like split: patterns without a slash match base names, patterns
63
+ // with a slash match whole paths. (picomatch's `basename` option would apply
64
+ // to every pattern, breaking path globs, so two matchers are needed.)
65
+ const matchers = [];
66
+ const byBasename = patterns.filter((pattern) => !pattern.includes("/"));
67
+ const byPath = patterns.filter((pattern) => pattern.includes("/"));
68
+ if (byBasename.length > 0)
69
+ matchers.push(picomatch(byBasename, { dot: true, basename: true }));
70
+ if (byPath.length > 0)
71
+ matchers.push(picomatch(byPath, { dot: true }));
72
+ const match = (path) => matchers.some((matcher) => matcher(path));
73
+ // Anchored patterns like `src/legacy/**` are tried against the path as
74
+ // spelled, relative to the scanned root, and relative to the working
75
+ // directory, so they work regardless of where the scan was started from.
76
+ return (path, root) => {
77
+ if (match(toPosix(path)))
78
+ return true;
79
+ return relativeMatches(root, path, match) || relativeMatches(process.cwd(), path, match);
80
+ };
81
+ }
82
+ function relativeMatches(base, path, match) {
83
+ const relativePath = relative(base, path);
84
+ return relativePath !== "" && !relativePath.startsWith("..") && match(toPosix(relativePath));
85
+ }
86
+ function toPosix(path) {
87
+ return sep === "/" ? path : path.split(sep).join("/");
88
+ }
89
+ export function isJsxFile(file) {
90
+ const lower = file.toLowerCase();
91
+ return lower.endsWith(".tsx") || lower.endsWith(".jsx");
92
+ }
36
93
  export async function scanFile(file) {
37
- const source = await readFile(file, "utf8");
38
- return { file, comments: scanComments(source, { jsx: file.endsWith(".tsx") || file.endsWith(".jsx") }) };
94
+ const raw = await readFile(file, "utf8");
95
+ // Positions are reported relative to the content after a leading byte-order
96
+ // mark, matching editors, GitHub annotations and the removal report.
97
+ const source = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
98
+ return { file, comments: scanComments(source, { jsx: isJsxFile(file) }) };
39
99
  }
40
100
  export async function scanPaths(inputs, options = {}) {
41
101
  const files = await collectFiles(inputs, options);
42
- return mapLimit(files, READ_CONCURRENCY, scanFile);
102
+ return mapLimit(files, FILE_CONCURRENCY, scanFile);
43
103
  }
44
- async function mapLimit(items, limit, fn) {
45
- const results = [];
46
- const processFrom = async (start) => {
47
- if (start >= items.length)
104
+ export const FILE_CONCURRENCY = 16;
105
+ /** Concurrency-limited map that keeps input order and starts work as slots free up. */
106
+ export async function mapLimit(items, limit, fn) {
107
+ const results = new Array(items.length);
108
+ let nextIndex = 0;
109
+ const claimNext = async () => {
110
+ const index = nextIndex;
111
+ nextIndex += 1;
112
+ if (index >= items.length)
48
113
  return;
49
- const batch = await Promise.all(items.slice(start, start + limit).map(fn));
50
- results.push(...batch);
51
- await processFrom(start + limit);
114
+ results[index] = await fn(items[index]);
115
+ return claimNext();
52
116
  };
53
- await processFrom(0);
117
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, claimNext));
54
118
  return results;
55
119
  }
56
120
  //# sourceMappingURL=files.js.map
package/dist/files.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { scanComments, type ScanOptions } from "./scanner.js";
2
- export { collectFiles, scanFile, scanPaths, type CollectOptions } from "./files.js";
3
- export { formatText, formatJson } from "./report.js";
2
+ export { collectFiles, isJsxFile, scanFile, scanPaths, type CollectOptions } from "./files.js";
3
+ export { removeComments, type RemoveOptions, type RemoveResult } from "./remove.js";
4
+ export { detectDirective, isLegalComment } from "./directives.js";
5
+ export { formatText, formatJson, formatGitHub } from "./report.js";
4
6
  export type { Comment, CommentKind, FileScanResult } from "./types.js";
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export { scanComments } from "./scanner.js";
2
- export { collectFiles, scanFile, scanPaths } from "./files.js";
3
- export { formatText, formatJson } from "./report.js";
2
+ export { collectFiles, isJsxFile, scanFile, scanPaths } from "./files.js";
3
+ export { removeComments } from "./remove.js";
4
+ export { detectDirective, isLegalComment } from "./directives.js";
5
+ export { formatText, formatJson, formatGitHub } from "./report.js";
4
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAuB,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAuB,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAyC,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { Comment } from "./types.js";
2
+ export interface RemoveOptions {
3
+ jsx?: boolean;
4
+ /** Also remove compiler/linter directive comments. Default: false (kept for safety). */
5
+ removeDirectives?: boolean;
6
+ /** Also remove license/legal comments. Default: false (kept for safety). */
7
+ removeLegal?: boolean;
8
+ /** Extra predicate: return false to leave a comment out of the removal entirely. */
9
+ shouldRemove?: (comment: Comment) => boolean;
10
+ }
11
+ export interface RemoveResult {
12
+ /** Source with the removed comments spliced out. */
13
+ code: string;
14
+ removed: Comment[];
15
+ /**
16
+ * Comments kept because they are protected: directives, license headers,
17
+ * and comments whose removal would shift code under a next-line directive.
18
+ */
19
+ kept: Comment[];
20
+ /** Comments excluded from removal by the `shouldRemove` predicate. */
21
+ skipped: Comment[];
22
+ changed: boolean;
23
+ }
24
+ /**
25
+ * Removes comments from TypeScript source without touching code.
26
+ *
27
+ * Safety properties:
28
+ * - AST-based ranges: strings, template literals and regexes are never affected.
29
+ * - Directives (`@ts-expect-error`, `eslint-disable`, ...) and license headers are
30
+ * kept by default, since deleting them changes build/lint behaviour.
31
+ * - A space is inserted where removing a block comment would merge two tokens,
32
+ * and a line break is kept where the comment acted as one (ASI stays intact).
33
+ * - A leading byte-order mark is preserved.
34
+ * - The result is re-scanned; if the remaining comments do not match the kept
35
+ * set, an error is thrown instead of returning corrupted output.
36
+ */
37
+ export declare function removeComments(source: string, options?: RemoveOptions): RemoveResult;
38
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../src/remove.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,wFAAwF;IACxF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oFAAoF;IACpF,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;CAC9C;AAED,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB;;;OAGG;IACH,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,sEAAsE;IACtE,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,YAAY,CAgCxF"}
package/dist/remove.js ADDED
@@ -0,0 +1,223 @@
1
+ import { isLegalComment } from "./directives.js";
2
+ import { scanComments } from "./scanner.js";
3
+ /**
4
+ * Removes comments from TypeScript source without touching code.
5
+ *
6
+ * Safety properties:
7
+ * - AST-based ranges: strings, template literals and regexes are never affected.
8
+ * - Directives (`@ts-expect-error`, `eslint-disable`, ...) and license headers are
9
+ * kept by default, since deleting them changes build/lint behaviour.
10
+ * - A space is inserted where removing a block comment would merge two tokens,
11
+ * and a line break is kept where the comment acted as one (ASI stays intact).
12
+ * - A leading byte-order mark is preserved.
13
+ * - The result is re-scanned; if the remaining comments do not match the kept
14
+ * set, an error is thrown instead of returning corrupted output.
15
+ */
16
+ export function removeComments(source, options = {}) {
17
+ const jsx = options.jsx === true;
18
+ const bom = source.startsWith("\uFEFF") ? "\uFEFF" : "";
19
+ const body = bom === "" ? source : source.slice(bom.length);
20
+ const comments = scanComments(body, { jsx });
21
+ let removed = [];
22
+ const kept = [];
23
+ const skipped = [];
24
+ for (const comment of comments) {
25
+ if (options.shouldRemove?.(comment) === false) {
26
+ skipped.push(comment);
27
+ }
28
+ else if (isProtected(comment, options)) {
29
+ kept.push(comment);
30
+ }
31
+ else {
32
+ removed.push(comment);
33
+ }
34
+ }
35
+ removed = shieldNextLineDirectives(body, removed, kept, skipped);
36
+ if (removed.length === 0) {
37
+ return { code: source, removed, kept, skipped, changed: false };
38
+ }
39
+ const code = bom + splice(body, removed);
40
+ if (scanComments(code, { jsx }).length !== kept.length + skipped.length) {
41
+ throw new Error("comment removal produced an unexpected result; refusing to continue");
42
+ }
43
+ return { code, removed, kept, skipped, changed: true };
44
+ }
45
+ function isProtected(comment, options) {
46
+ if (comment.directive !== undefined && options.removeDirectives !== true)
47
+ return true;
48
+ if (isLegalComment(comment.text) && options.removeLegal !== true)
49
+ return true;
50
+ return false;
51
+ }
52
+ /**
53
+ * Re-protects whole-line comments sitting directly below a surviving
54
+ * next-line directive (`@ts-expect-error`, `eslint-disable-next-line`, ...).
55
+ * Dropping such a line would shift the following code up, silently changing
56
+ * which line the directive applies to.
57
+ */
58
+ function shieldNextLineDirectives(source, removed, kept, skipped) {
59
+ const shieldedLines = new Set();
60
+ for (const comment of [...kept, ...skipped]) {
61
+ if (comment.directive !== undefined && isNextLineDirective(comment.directive)) {
62
+ // Counted pragmas like `c8 ignore next 3` cover several lines.
63
+ for (let offset = 1; offset <= shieldedLineCount(comment.text); offset += 1) {
64
+ shieldedLines.add(comment.endLine + offset);
65
+ }
66
+ }
67
+ }
68
+ if (shieldedLines.size === 0)
69
+ return removed;
70
+ const stillRemoved = [];
71
+ for (const comment of removed) {
72
+ if (shieldedLines.has(comment.line) && occupiesWholeLines(source, comment)) {
73
+ kept.push(comment);
74
+ }
75
+ else {
76
+ stillRemoved.push(comment);
77
+ }
78
+ }
79
+ if (stillRemoved.length !== removed.length) {
80
+ kept.sort((a, b) => a.start - b.start);
81
+ }
82
+ return stillRemoved;
83
+ }
84
+ // File- and range-scoped pragmas (`c8 ignore start`, `istanbul ignore file`,
85
+ // ...) do not target the following line, so they never shield it.
86
+ function isNextLineDirective(name) {
87
+ return (name.endsWith("-next-line") ||
88
+ [
89
+ "@ts-ignore",
90
+ "@ts-expect-error",
91
+ "biome-ignore",
92
+ "deno-lint-ignore",
93
+ "deno-fmt-ignore",
94
+ "deno-coverage-ignore",
95
+ "prettier-ignore",
96
+ "istanbul-ignore",
97
+ "istanbul-ignore-next",
98
+ "istanbul-ignore-if",
99
+ "istanbul-ignore-else",
100
+ "c8-ignore",
101
+ "c8-ignore-next",
102
+ "v8-ignore",
103
+ "v8-ignore-next",
104
+ "node:coverage-ignore",
105
+ ].includes(name));
106
+ }
107
+ /** Number of following lines a next-line pragma covers (`ignore next 3` → 3). */
108
+ function shieldedLineCount(text) {
109
+ const match = /\bignore\s+next\s+(\d{1,4})\b/.exec(text);
110
+ return match ? Math.max(1, Number(match[1])) : 1;
111
+ }
112
+ /** True when nothing but whitespace shares the comment's first and last lines. */
113
+ function occupiesWholeLines(source, comment) {
114
+ const lineStart = source.lastIndexOf("\n", comment.start - 1) + 1;
115
+ if (!isBlank(source.slice(lineStart, comment.start)))
116
+ return false;
117
+ const newlineIndex = source.indexOf("\n", comment.end);
118
+ const lineEnd = newlineIndex === -1 ? source.length : newlineIndex;
119
+ return isBlank(source.slice(comment.end, lineEnd));
120
+ }
121
+ const isBlank = (text) => /^\s*$/.test(text);
122
+ const isHorizontalSpace = (char) => char === " " || char === "\t";
123
+ const LINE_TERMINATOR = /[\n\r\u2028\u2029]/;
124
+ /**
125
+ * Splices sorted, non-overlapping comment ranges out of the source, tidying lines.
126
+ * Output is accumulated as segments with incremental line-state tracking, so the
127
+ * work stays linear in the source size even for comment-dense files.
128
+ */
129
+ function splice(source, removals) {
130
+ const segments = [];
131
+ let cursor = 0;
132
+ /** Whether the output's current (unterminated) line is all whitespace so far. */
133
+ let lineIsBlank = true;
134
+ /** Last character of the output so far ("" while empty). */
135
+ let lastChar = "";
136
+ const push = (chunk) => {
137
+ if (chunk === "")
138
+ return;
139
+ segments.push(chunk);
140
+ const newlineIndex = chunk.lastIndexOf("\n");
141
+ lineIsBlank = newlineIndex === -1 ? lineIsBlank && isBlank(chunk) : isBlank(chunk.slice(newlineIndex + 1));
142
+ lastChar = chunk.slice(-1);
143
+ };
144
+ /** Deletes everything the output holds after its last line break. */
145
+ const dropCurrentLine = () => {
146
+ while (segments.length > 0) {
147
+ const last = segments[segments.length - 1];
148
+ const newlineIndex = last.lastIndexOf("\n");
149
+ if (newlineIndex === -1) {
150
+ segments.pop();
151
+ continue;
152
+ }
153
+ segments[segments.length - 1] = last.slice(0, newlineIndex + 1);
154
+ lineIsBlank = true;
155
+ lastChar = "\n";
156
+ return;
157
+ }
158
+ lineIsBlank = true;
159
+ lastChar = "";
160
+ };
161
+ /** Deletes trailing spaces/tabs of the output's current line. */
162
+ const trimLineEnd = () => {
163
+ while (segments.length > 0) {
164
+ const last = segments[segments.length - 1];
165
+ let end = last.length;
166
+ while (end > 0 && isHorizontalSpace(last[end - 1]))
167
+ end -= 1;
168
+ if (end === 0) {
169
+ segments.pop();
170
+ continue;
171
+ }
172
+ if (end < last.length)
173
+ segments[segments.length - 1] = last.slice(0, end);
174
+ lastChar = segments[segments.length - 1].slice(-1);
175
+ return;
176
+ }
177
+ lastChar = "";
178
+ };
179
+ for (const comment of removals) {
180
+ push(source.slice(cursor, comment.start));
181
+ cursor = comment.end;
182
+ const newlineIndex = source.indexOf("\n", cursor);
183
+ const lineEnd = newlineIndex === -1 ? source.length : newlineIndex + 1;
184
+ const rest = source.slice(cursor, lineEnd);
185
+ const eolLength = rest.endsWith("\r\n") ? 2 : rest.endsWith("\n") ? 1 : 0;
186
+ const restContent = rest.slice(0, rest.length - eolLength);
187
+ if (lineIsBlank && isBlank(restContent)) {
188
+ // The comment occupied whole line(s): drop them entirely.
189
+ dropCurrentLine();
190
+ cursor = lineEnd;
191
+ }
192
+ else if (isBlank(restContent)) {
193
+ // Trailing comment after code: trim the gap, keep the line break.
194
+ trimLineEnd();
195
+ push(rest.slice(restContent.length));
196
+ cursor = lineEnd;
197
+ }
198
+ else if (!lineIsBlank && LINE_TERMINATOR.test(comment.text)) {
199
+ // Code on both sides of a block comment that spans lines. Per ECMA-262
200
+ // such a comment acts as a line terminator for semicolon insertion, so
201
+ // replace it with a real line break (matching the file's style) instead
202
+ // of merging the lines.
203
+ trimLineEnd();
204
+ push(comment.text.includes("\r\n") ? "\r\n" : "\n");
205
+ }
206
+ else {
207
+ // Inline comment with code after it on the same line.
208
+ const next = source.charAt(cursor);
209
+ if (lastChar !== "" && !isBlank(lastChar) && !isBlank(next)) {
210
+ // `a/* x */b` would merge tokens: keep them apart.
211
+ push(" ");
212
+ }
213
+ else if (lastChar === "" || isBlank(lastChar)) {
214
+ // Collapse the horizontal whitespace that followed the comment.
215
+ while (cursor < lineEnd && isHorizontalSpace(source[cursor]))
216
+ cursor += 1;
217
+ }
218
+ }
219
+ }
220
+ segments.push(source.slice(cursor));
221
+ return segments.join("");
222
+ }
223
+ //# sourceMappingURL=remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../src/remove.ts"],"names":[],"mappings":"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"}
package/dist/report.d.ts CHANGED
@@ -1,4 +1,12 @@
1
1
  import type { FileScanResult } from "./types.js";
2
+ /** Formats `3 comments`, `1 file`, ... with naive pluralization. */
3
+ export declare function count(value: number, noun: string): string;
2
4
  export declare function formatText(results: FileScanResult[]): string;
3
5
  export declare function formatJson(results: FileScanResult[]): string;
6
+ /**
7
+ * Formats results as GitHub Actions workflow commands so each comment shows up
8
+ * as an annotation on the corresponding file and line in CI.
9
+ * See https://docs.github.com/actions/reference/workflow-commands-for-github-actions
10
+ */
11
+ export declare function formatGitHub(results: FileScanResult[]): string;
4
12
  //# sourceMappingURL=report.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAkB5D;AAcD,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAK5D"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1D,oEAAoE;AACpE,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAwBD,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAK5D;AAUD,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAS5D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAE9D"}
package/dist/report.js CHANGED
@@ -1,19 +1,32 @@
1
- export function formatText(results) {
2
- const withComments = results.filter((result) => result.comments.length > 0);
3
- if (withComments.length === 0) {
4
- return "No comments found.";
5
- }
1
+ /** Formats `3 comments`, `1 file`, ... with naive pluralization. */
2
+ export function count(value, noun) {
3
+ return `${value} ${noun}${value === 1 ? "" : "s"}`;
4
+ }
5
+ function renderComments(results, renderLine) {
6
6
  const lines = [];
7
7
  let total = 0;
8
- for (const { file, comments } of withComments) {
8
+ let fileCount = 0;
9
+ for (const { file, comments } of results) {
10
+ if (comments.length === 0)
11
+ continue;
12
+ fileCount += 1;
9
13
  for (const comment of comments) {
10
- lines.push(`${file}:${comment.line}:${comment.column} [${comment.kind}] ${preview(comment.text)}`);
14
+ lines.push(renderLine(file, comment));
11
15
  total += 1;
12
16
  }
13
17
  }
14
- lines.push("", `${count(total, "comment")} across ${count(withComments.length, "file")}`);
18
+ if (total === 0) {
19
+ return "No comments found.";
20
+ }
21
+ lines.push("", `${count(total, "comment")} across ${count(fileCount, "file")}`);
15
22
  return lines.join("\n");
16
23
  }
24
+ export function formatText(results) {
25
+ return renderComments(results, (file, comment) => {
26
+ const tag = comment.directive === undefined ? "" : ` [${comment.directive}]`;
27
+ return `${file}:${comment.line}:${comment.column} [${comment.kind}]${tag} ${preview(comment.text)}`;
28
+ });
29
+ }
17
30
  function preview(text) {
18
31
  return text
19
32
  .split("\n")
@@ -21,12 +34,33 @@ function preview(text) {
21
34
  .join(" ")
22
35
  .trim();
23
36
  }
24
- function count(value, noun) {
25
- return `${value} ${noun}${value === 1 ? "" : "s"}`;
26
- }
27
37
  export function formatJson(results) {
28
38
  const files = results.filter((result) => result.comments.length > 0);
29
39
  const comments = files.reduce((sum, file) => sum + file.comments.length, 0);
30
- return JSON.stringify({ summary: { files: files.length, comments }, files }, null, 2);
40
+ const directives = files.reduce((sum, file) => sum + file.comments.filter((comment) => comment.directive !== undefined).length, 0);
41
+ return JSON.stringify({ summary: { files: files.length, comments, directives }, files }, null, 2);
42
+ }
43
+ /**
44
+ * Formats results as GitHub Actions workflow commands so each comment shows up
45
+ * as an annotation on the corresponding file and line in CI.
46
+ * See https://docs.github.com/actions/reference/workflow-commands-for-github-actions
47
+ */
48
+ export function formatGitHub(results) {
49
+ return renderComments(results, annotation);
50
+ }
51
+ function annotation(file, comment) {
52
+ const title = comment.directive === undefined ? `${comment.kind} comment` : `${comment.kind} comment (${comment.directive})`;
53
+ const properties = [`file=${escapeProperty(file)}`, `line=${comment.line}`, `endLine=${comment.endLine}`];
54
+ if (comment.line === comment.endLine) {
55
+ properties.push(`col=${comment.column}`, `endColumn=${comment.endColumn}`);
56
+ }
57
+ properties.push(`title=${escapeProperty(title)}`);
58
+ return `::notice ${properties.join(",")}::${escapeData(comment.text)}`;
59
+ }
60
+ function escapeData(value) {
61
+ return value.replaceAll("%", "%25").replaceAll("\r", "%0D").replaceAll("\n", "%0A");
62
+ }
63
+ function escapeProperty(value) {
64
+ return escapeData(value).replaceAll(":", "%3A").replaceAll(",", "%2C");
31
65
  }
32
66
  //# sourceMappingURL=report.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,OAAyB;IAClD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE5E,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,YAAY,EAAE,CAAC;QAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnG,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,WAAW,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,IAAI,CAAC,GAAG,CAAC;SACT,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,IAAY;IACxC,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAyB;IAClD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAE5E,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
package/dist/run.d.ts CHANGED
@@ -2,6 +2,6 @@ export interface CliIO {
2
2
  out: (text: string) => void;
3
3
  err: (text: string) => void;
4
4
  }
5
- export declare const HELP_TEXT = "Usage: ts-comment-scanner [options] [paths...]\n\nDetect and report comments across a TypeScript project.\n\nOptions:\n --json Output results as JSON\n -v, --version Print the version number\n -h, --help Show this help\n\nPaths default to the current directory. Directories are scanned recursively\nfor .ts, .tsx, .mts and .cts files, skipping node_modules and .git.\n\nExamples:\n ts-comment-scanner src\n ts-comment-scanner --json src test\n";
5
+ export declare const HELP_TEXT = "Usage: ts-comment-scanner [options] [paths...]\n\nDetect, report and clean up comments across a TypeScript project.\n\nOutput:\n --format <fmt> Output format: text, json or github (default: text)\n --json Shorthand for --format json\n\nFiltering:\n --ignore <glob> Skip files/directories matching the glob (repeatable)\n --ext <list> Comma-separated extensions to scan (default: .ts,.tsx,.mts,.cts)\n --skip-directives Hide compiler/linter directives (@ts-ignore, eslint-disable, ...)\n --only-directives Report only compiler/linter directives\n\nCI:\n --fail-on-comment Exit with code 1 when any comment is reported\n\nRemoval:\n --remove Delete the reported comments from the files (in place)\n --dry-run With --remove: show what would be removed, change nothing\n --remove-directives With --remove: also delete directive comments\n --remove-legal With --remove: also delete license/legal comments\n\nGeneral:\n -h, --help Show this help\n -v, --version Print the version number\n\nPaths default to the current directory. Directories are scanned recursively,\nskipping node_modules and .git. Removal keeps directives and license headers\nunless explicitly requested, so builds and linters keep working.\n\nExit codes: 0 success, 1 comments reported with --fail-on-comment, 2 error.\n\nExamples:\n ts-comment-scanner src\n ts-comment-scanner --format github --fail-on-comment src\n ts-comment-scanner --ignore \"**/*.test.ts\" --skip-directives src\n ts-comment-scanner --remove --dry-run src\n";
6
6
  export declare function run(argv: string[], io: CliIO): Promise<number>;
7
7
  //# sourceMappingURL=run.d.ts.map
package/dist/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,kdAerB,CAAC;AAEF,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBpE"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,skDAsCrB,CAAC;AAEF,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA2CpE"}