@kongyo2/ts-comment-scanner 0.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +208 -0
- package/README.md +130 -17
- package/dist/args.d.ts +16 -1
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +156 -6
- package/dist/args.js.map +1 -1
- package/dist/directives.d.ts +12 -0
- package/dist/directives.d.ts.map +1 -0
- package/dist/directives.js +133 -0
- package/dist/directives.js.map +1 -0
- package/dist/files.d.ts +12 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +84 -20
- package/dist/files.js.map +1 -1
- package/dist/git.d.ts +10 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +67 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/remove.d.ts +38 -0
- package/dist/remove.d.ts.map +1 -0
- package/dist/remove.js +223 -0
- package/dist/remove.js.map +1 -0
- package/dist/report.d.ts +8 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +46 -12
- package/dist/report.js.map +1 -1
- package/dist/run.d.ts +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +185 -20
- package/dist/run.js.map +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +31 -7
- package/dist/scanner.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -2
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const RULES = [
|
|
2
|
+
// ESLint
|
|
3
|
+
{ pattern: /^eslint-(?:disable|enable)(?:-next-line|-line)?\b/ },
|
|
4
|
+
{ pattern: /^eslint-env\b/ },
|
|
5
|
+
{ pattern: /^eslint\s+\S/, name: "eslint", blockOnly: true },
|
|
6
|
+
{ pattern: /^(globals?|exported)\s+\S/, name: (match) => match[1] ?? "global", blockOnly: true },
|
|
7
|
+
// TSLint (legacy)
|
|
8
|
+
{ pattern: /^tslint:[a-z-]+/ },
|
|
9
|
+
// oxlint
|
|
10
|
+
{ pattern: /^oxlint-(?:disable|enable)(?:-next-line|-line)?\b/ },
|
|
11
|
+
// Biome
|
|
12
|
+
{ pattern: /^biome-ignore(?:-all|-start|-end)?\b/ },
|
|
13
|
+
// Deno
|
|
14
|
+
{ pattern: /^deno-(?:lint-ignore(?:-file)?|fmt-ignore(?:-file)?|coverage-ignore(?:-file|-start|-stop)?)\b/ },
|
|
15
|
+
// Prettier
|
|
16
|
+
{ pattern: /^prettier-ignore(?:-start|-end)?\b/ },
|
|
17
|
+
// Coverage tools. The mode is part of the name so that consumers can tell
|
|
18
|
+
// next-statement pragmas (`next`, `if`, ...) from file/range ones (`file`,
|
|
19
|
+
// `start`, `stop`). Istanbul hints work in either comment kind; the V8-based
|
|
20
|
+
// tools (c8, v8, node:coverage) only document and parse block comments.
|
|
21
|
+
{ pattern: /^istanbul\s+ignore\s+([a-z]+)/, name: (match) => `istanbul-ignore-${match[1]}` },
|
|
22
|
+
{ pattern: /^istanbul\s+ignore\b/, name: "istanbul-ignore" },
|
|
23
|
+
{ pattern: /^c8\s+ignore\s+([a-z]+)/, name: (match) => `c8-ignore-${match[1]}`, blockOnly: true },
|
|
24
|
+
{ pattern: /^c8\s+ignore\b/, name: "c8-ignore", blockOnly: true },
|
|
25
|
+
{ pattern: /^v8\s+ignore\s+([a-z]+)/, name: (match) => `v8-ignore-${match[1]}`, blockOnly: true },
|
|
26
|
+
{ pattern: /^v8\s+ignore\b/, name: "v8-ignore", blockOnly: true },
|
|
27
|
+
{
|
|
28
|
+
pattern: /^node:coverage\s+(disable|enable|ignore)\b/,
|
|
29
|
+
name: (match) => `node:coverage-${match[1]}`,
|
|
30
|
+
blockOnly: true,
|
|
31
|
+
},
|
|
32
|
+
// Bundlers
|
|
33
|
+
{ pattern: /^webpack[A-Z][A-Za-z]*\s*:/, name: "webpack-magic-comment" },
|
|
34
|
+
{ pattern: /^@vite-ignore\b/ },
|
|
35
|
+
{ pattern: /^[#@]__(?:PURE|NO_SIDE_EFFECTS|INLINE|NOINLINE)__/ },
|
|
36
|
+
// Source maps (`//# sourceMappingURL=`, legacy `//@`, and the block form)
|
|
37
|
+
{ pattern: /^[#@]\s*(source(?:Mapping)?URL)=/, name: (match) => match[1] ?? "sourceMappingURL" },
|
|
38
|
+
// JSX pragmas (docblock pragmas: block comments only, honoured on any line)
|
|
39
|
+
{ pattern: /^@jsx(?:Runtime|ImportSource|Frag)?\b/, blockOnly: true, anyLine: true },
|
|
40
|
+
// Test runners (docblock pragmas as well)
|
|
41
|
+
{ pattern: /^@(?:jest|vitest)-environment\b/, blockOnly: true, anyLine: true },
|
|
42
|
+
// Editor folding
|
|
43
|
+
{ pattern: /^#(?:region|endregion)\b/ },
|
|
44
|
+
];
|
|
45
|
+
const TRIPLE_SLASH = /^\/\/\/\s*<(reference|amd-dependency|amd-module)\b/;
|
|
46
|
+
// Mirrors the TypeScript compiler's own comment-directive matching, verified
|
|
47
|
+
// against tsc: the suppression directives are case-sensitive PREFIX matches
|
|
48
|
+
// (`@ts-ignoreTODO` is active), while the file-wide check pragmas are
|
|
49
|
+
// case-insensitive and must end at a word boundary (`@ts-nocheckfoo` is not).
|
|
50
|
+
const TS_LINE_SUPPRESSION = /^\/\/\/?\s*@ts-(ignore|expect-error)/;
|
|
51
|
+
const TS_LINE_CHECK_PRAGMA = /^\/\/\/?\s*@ts-(nocheck|check)\b/i;
|
|
52
|
+
// Block comments: only the suppression directives, and only on the last line.
|
|
53
|
+
const TS_BLOCK_SUPPRESSION = /^[\s/*]*@ts-(ignore|expect-error)/;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the canonical name of the compiler/linter/tooling directive the
|
|
56
|
+
* comment represents, or `undefined` when the comment is an ordinary comment.
|
|
57
|
+
*/
|
|
58
|
+
export function detectDirective(kind, text) {
|
|
59
|
+
if (kind === "line") {
|
|
60
|
+
const tripleSlash = TRIPLE_SLASH.exec(text);
|
|
61
|
+
if (tripleSlash) {
|
|
62
|
+
return `triple-slash-${tripleSlash[1]}`;
|
|
63
|
+
}
|
|
64
|
+
const suppression = TS_LINE_SUPPRESSION.exec(text);
|
|
65
|
+
if (suppression) {
|
|
66
|
+
return `@ts-${suppression[1]}`;
|
|
67
|
+
}
|
|
68
|
+
const checkPragma = TS_LINE_CHECK_PRAGMA.exec(text);
|
|
69
|
+
if (checkPragma) {
|
|
70
|
+
return `@ts-${checkPragma[1]?.toLowerCase()}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const suppression = TS_BLOCK_SUPPRESSION.exec(lastContentLine(text));
|
|
75
|
+
if (suppression) {
|
|
76
|
+
return `@ts-${suppression[1]}`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const lines = contentLines(kind, text);
|
|
80
|
+
for (const rule of RULES) {
|
|
81
|
+
if (rule.blockOnly === true && kind !== "block")
|
|
82
|
+
continue;
|
|
83
|
+
const candidates = rule.anyLine === true ? lines : lines.slice(0, 1);
|
|
84
|
+
for (const line of candidates) {
|
|
85
|
+
const match = rule.pattern.exec(line);
|
|
86
|
+
if (!match)
|
|
87
|
+
continue;
|
|
88
|
+
if (typeof rule.name === "string")
|
|
89
|
+
return rule.name;
|
|
90
|
+
if (typeof rule.name === "function")
|
|
91
|
+
return rule.name(match);
|
|
92
|
+
return match[0];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* True for license/legal comments (`/*!`, `@license`, `@preserve`, `@copyright`)
|
|
99
|
+
* that build tools conventionally keep when stripping comments.
|
|
100
|
+
*/
|
|
101
|
+
export function isLegalComment(text) {
|
|
102
|
+
if (text.startsWith("/*!") || text.startsWith("//!"))
|
|
103
|
+
return true;
|
|
104
|
+
return /@(?:license|preserve|copyright)\b/i.test(text);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Non-empty content lines of the comment, with comment markers stripped.
|
|
108
|
+
* For line comments only the `//` marker itself is removed: extra slashes or
|
|
109
|
+
* stars are content, so `//// @ts-ignore` and `// * prettier-ignore` stay
|
|
110
|
+
* ordinary. JSDoc-style `*` prefixes are stripped for block comments only.
|
|
111
|
+
*/
|
|
112
|
+
function contentLines(kind, text) {
|
|
113
|
+
const inner = kind === "line" ? text.replace(/^\/\//, "") : text.replace(/^\/\*+/, "").replace(/\*+\/\s*$/, "");
|
|
114
|
+
const lines = [];
|
|
115
|
+
for (const line of inner.split(/\r?\n/)) {
|
|
116
|
+
const stripped = (kind === "block" ? line.replace(/^\s*\*+\s*/, "") : line).trim();
|
|
117
|
+
if (stripped !== "")
|
|
118
|
+
lines.push(stripped);
|
|
119
|
+
}
|
|
120
|
+
return lines;
|
|
121
|
+
}
|
|
122
|
+
/** Last non-blank line of the comment, with the closing comment marker stripped. */
|
|
123
|
+
function lastContentLine(text) {
|
|
124
|
+
const inner = text.replace(/\*+\/\s*$/, "");
|
|
125
|
+
const lines = inner.split(/\r?\n/);
|
|
126
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
127
|
+
const line = lines[index] ?? "";
|
|
128
|
+
if (line.trim() !== "")
|
|
129
|
+
return line;
|
|
130
|
+
}
|
|
131
|
+
return "";
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=directives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"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"}
|
package/dist/files.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import type { FileScanResult } from "./types.js";
|
|
2
2
|
export interface CollectOptions {
|
|
3
|
+
/** File extensions to include (with or without a leading dot, case-insensitive). */
|
|
3
4
|
extensions?: string[];
|
|
5
|
+
/** Directory names that are never traversed. Default: node_modules, .git */
|
|
4
6
|
ignoreDirs?: string[];
|
|
7
|
+
/**
|
|
8
|
+
* Glob patterns for files and directories to skip (picomatch syntax).
|
|
9
|
+
* Patterns without a slash match against base names, e.g. `*.test.ts`.
|
|
10
|
+
* Explicitly listed input files bypass these patterns.
|
|
11
|
+
*/
|
|
12
|
+
ignore?: string[];
|
|
5
13
|
}
|
|
6
14
|
export declare function collectFiles(inputs: string[], options?: CollectOptions): Promise<string[]>;
|
|
15
|
+
export declare function isJsxFile(file: string): boolean;
|
|
7
16
|
export declare function scanFile(file: string): Promise<FileScanResult>;
|
|
8
17
|
export declare function scanPaths(inputs: string[], options?: CollectOptions): Promise<FileScanResult[]>;
|
|
18
|
+
export declare const FILE_CONCURRENCY = 16;
|
|
19
|
+
/** Concurrency-limited map that keeps input order and starts work as slots free up. */
|
|
20
|
+
export declare function mapLimit<T, R>(items: readonly T[], limit: number, fn: (item: T) => Promise<R>): Promise<R[]>;
|
|
9
21
|
//# sourceMappingURL=files.d.ts.map
|
package/dist/files.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjD,MAAM,WAAW,cAAc;IAC7B,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAID,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA2BpG;AA2ED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG/C;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAMpE;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGzG;AAED,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,uFAAuF;AACvF,wBAAsB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAclH"}
|
package/dist/files.js
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
2
|
-
import {
|
|
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 (
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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() &&
|
|
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
|
|
38
|
-
|
|
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,
|
|
102
|
+
return mapLimit(files, FILE_CONCURRENCY, scanFile);
|
|
43
103
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
await processFrom(start + limit);
|
|
114
|
+
results[index] = await fn(items[index]);
|
|
115
|
+
return claimNext();
|
|
52
116
|
};
|
|
53
|
-
await
|
|
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":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Absolute paths of the working-tree files touched in a git revision range.
|
|
3
|
+
* The range is anything `git diff` accepts as revisions: a single commit-ish
|
|
4
|
+
* compares the working tree against it (`HEAD` covers all uncommitted work,
|
|
5
|
+
* untracked files included), while `a..b` and `a...b` compare commits. Files
|
|
6
|
+
* deleted in the range are omitted because they have no working-tree content
|
|
7
|
+
* left, and renames are reported at their new path.
|
|
8
|
+
*/
|
|
9
|
+
export declare function changedFiles(range: string, cwd?: string): Promise<string[]>;
|
|
10
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBhG"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
/** --name-only output stays tiny even for huge diffs; this is pure headroom. */
|
|
7
|
+
const MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
8
|
+
/**
|
|
9
|
+
* Absolute paths of the working-tree files touched in a git revision range.
|
|
10
|
+
* The range is anything `git diff` accepts as revisions: a single commit-ish
|
|
11
|
+
* compares the working tree against it (`HEAD` covers all uncommitted work,
|
|
12
|
+
* untracked files included), while `a..b` and `a...b` compare commits. Files
|
|
13
|
+
* deleted in the range are omitted because they have no working-tree content
|
|
14
|
+
* left, and renames are reported at their new path.
|
|
15
|
+
*/
|
|
16
|
+
export async function changedFiles(range, cwd = process.cwd()) {
|
|
17
|
+
if (range === "" || range.startsWith("-")) {
|
|
18
|
+
// Never let the range reach git where it could parse as an option (--output=...).
|
|
19
|
+
throw new Error(`invalid git revision range: ${JSON.stringify(range)}`);
|
|
20
|
+
}
|
|
21
|
+
const top = (await git(["rev-parse", "--show-toplevel"], cwd)).replace(/\r?\n$/, "");
|
|
22
|
+
const root = await realpath(top);
|
|
23
|
+
// --no-relative pins root-relative output even under diff.relative=true.
|
|
24
|
+
const args = ["diff", "--name-only", "-z", "--no-renames", "--no-relative", "--diff-filter=d", range, "--"];
|
|
25
|
+
const entries = split(await git(args, cwd));
|
|
26
|
+
// A working-tree comparison treats brand-new files as changes too, yet
|
|
27
|
+
// `git diff` never lists them. Runs at the root so the whole repository is
|
|
28
|
+
// covered regardless of cwd; .gitignore still applies.
|
|
29
|
+
if (await comparesWorkingTree(range, cwd)) {
|
|
30
|
+
entries.push(...split(await git(["ls-files", "--others", "--exclude-standard", "--full-name", "-z"], root)));
|
|
31
|
+
}
|
|
32
|
+
return [...new Set(entries)].map((entry) => resolve(root, entry));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* `git diff` compares the working tree only against a lone positive revision;
|
|
36
|
+
* every other shape (`a..b`, `a...b`, `HEAD^!`, multi-parent `HEAD^@`)
|
|
37
|
+
* compares commits. String sniffing cannot tell these apart — `HEAD^!`
|
|
38
|
+
* contains no ".." yet excludes the working tree — so ask rev-parse for the
|
|
39
|
+
* expansion and check for exactly one non-negated revision.
|
|
40
|
+
*/
|
|
41
|
+
async function comparesWorkingTree(range, cwd) {
|
|
42
|
+
const revs = (await git(["rev-parse", "--revs-only", range, "--"], cwd)).split("\n").filter((line) => line !== "");
|
|
43
|
+
return revs.length === 1 && !revs[0].startsWith("^");
|
|
44
|
+
}
|
|
45
|
+
function split(listing) {
|
|
46
|
+
return listing.split("\0").filter((entry) => entry !== "");
|
|
47
|
+
}
|
|
48
|
+
async function git(args, cwd) {
|
|
49
|
+
try {
|
|
50
|
+
const { stdout } = await execFileAsync("git", args, { cwd, maxBuffer: MAX_OUTPUT_BYTES });
|
|
51
|
+
return stdout;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new Error(describeFailure(args[0], error), { cause: error });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function describeFailure(subcommand, error) {
|
|
58
|
+
const failure = error;
|
|
59
|
+
if (failure.code === "ENOENT") {
|
|
60
|
+
return "git executable not found (is git installed and on PATH?)";
|
|
61
|
+
}
|
|
62
|
+
const stderr = typeof failure.stderr === "string" ? failure.stderr.trim() : "";
|
|
63
|
+
const newline = stderr.indexOf("\n");
|
|
64
|
+
const detail = stderr === "" ? String(failure.message ?? error) : newline === -1 ? stderr : stderr.slice(0, newline);
|
|
65
|
+
return `git ${subcommand} failed: ${detail}`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { scanComments, type ScanOptions } from "./scanner.js";
|
|
2
|
-
export { collectFiles, scanFile, scanPaths, type CollectOptions } from "./files.js";
|
|
3
|
-
export {
|
|
2
|
+
export { collectFiles, isJsxFile, scanFile, scanPaths, type CollectOptions } from "./files.js";
|
|
3
|
+
export { changedFiles } from "./git.js";
|
|
4
|
+
export { removeComments, type RemoveOptions, type RemoveResult } from "./remove.js";
|
|
5
|
+
export { detectDirective, isLegalComment } from "./directives.js";
|
|
6
|
+
export { formatText, formatJson, formatGitHub } from "./report.js";
|
|
4
7
|
export type { Comment, CommentKind, FileScanResult } from "./types.js";
|
|
5
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,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,7 @@
|
|
|
1
1
|
export { scanComments } from "./scanner.js";
|
|
2
|
-
export { collectFiles, scanFile, scanPaths } from "./files.js";
|
|
3
|
-
export {
|
|
2
|
+
export { collectFiles, isJsxFile, scanFile, scanPaths } from "./files.js";
|
|
3
|
+
export { changedFiles } from "./git.js";
|
|
4
|
+
export { removeComments } from "./remove.js";
|
|
5
|
+
export { detectDirective, isLegalComment } from "./directives.js";
|
|
6
|
+
export { formatText, formatJson, formatGitHub } from "./report.js";
|
|
4
7
|
//# 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,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,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"}
|
package/dist/remove.d.ts
ADDED
|
@@ -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"}
|