@kongyo2/ts-comment-scanner 1.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 +34 -1
- package/dist/args.d.ts +1 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +10 -0
- package/dist/args.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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +37 -8
- package/dist/run.js.map +1 -1
- package/package.json +1 -1
package/README.en.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# ts-comment-scanner
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@kongyo2/ts-comment-scanner)
|
|
4
|
+
[](https://www.npmjs.com/package/@kongyo2/ts-comment-scanner)
|
|
5
|
+
[](https://github.com/kongyo2/ts-comment-scanner/actions/workflows/ci.yml)
|
|
6
|
+

|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
[](https://deepwiki.com/kongyo2/ts-comment-scanner)
|
|
10
|
+
|
|
11
|
+
[日本語](./README.md) | **English**
|
|
12
|
+
|
|
13
|
+
A CLI / library that detects, lists, and summarizes comments in a TypeScript project — and can also remove them safely. It analyzes code through the TypeScript AST, so it never mistakes strings, template literals, regular expressions, or JSX text for comments.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- Recursively scans `.ts` `.tsx` `.mts` `.cts` (excluding `node_modules` and `.git`)
|
|
18
|
+
- Reports line comments (`//`) and block comments (`/* */`) with position information
|
|
19
|
+
- Outputs in three formats: text / JSON / **GitHub Actions annotations**
|
|
20
|
+
- **Automatically identifies compiler and linter directives** such as `@ts-ignore` and `eslint-disable`, so you can filter them in or out
|
|
21
|
+
- **Safe comment removal** (code cleanup): directives and license headers are kept by default
|
|
22
|
+
- **Custom ignore patterns** via glob (`--ignore`) and configurable target extensions (`--ext`)
|
|
23
|
+
- **git integration (`--diff`)**: narrow the scan to files touched between specific commits or in uncommitted work
|
|
24
|
+
- `--fail-on-comment` for CI (exit code 1 when comments are detected)
|
|
25
|
+
- Usable both as a CLI and as a library
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @kongyo2/ts-comment-scanner
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To run without installing:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx @kongyo2/ts-comment-scanner src
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## CLI usage
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
ts-comment-scanner [options] [paths...]
|
|
43
|
+
|
|
44
|
+
Output:
|
|
45
|
+
--format <fmt> Output format: text / json / github (default: text)
|
|
46
|
+
--json Shorthand for --format json
|
|
47
|
+
|
|
48
|
+
Filtering:
|
|
49
|
+
--ignore <glob> Exclude files/directories matching the glob (repeatable)
|
|
50
|
+
--ext <list> Extensions to scan (comma-separated, default: .ts,.tsx,.mts,.cts)
|
|
51
|
+
--diff <range> Only files git reports changed (e.g. HEAD, main..HEAD)
|
|
52
|
+
--skip-directives Exclude compiler/linter directives from the results
|
|
53
|
+
--only-directives Report only directives
|
|
54
|
+
|
|
55
|
+
CI:
|
|
56
|
+
--fail-on-comment Exit with code 1 if any comment is reported
|
|
57
|
+
|
|
58
|
+
Removal:
|
|
59
|
+
--remove Remove reported comments from files (in place)
|
|
60
|
+
--dry-run With --remove: show what would be removed without changing files
|
|
61
|
+
--remove-directives With --remove: also remove directive comments
|
|
62
|
+
--remove-legal With --remove: also remove license/legal comments
|
|
63
|
+
|
|
64
|
+
Other:
|
|
65
|
+
-h, --help Show help
|
|
66
|
+
-v, --version Show version
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
If no paths are given, the current directory is used. A glob without a slash (e.g. `*.test.ts`) matches against file names, while one that contains a slash (e.g. `src/legacy/**`) matches against paths. Files passed explicitly are never subject to `--ignore`.
|
|
70
|
+
|
|
71
|
+
**Exit codes**: `0` success / `1` comments detected when `--fail-on-comment` is set / `2` argument or runtime error
|
|
72
|
+
|
|
73
|
+
### Example output
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
$ ts-comment-scanner src
|
|
77
|
+
src/index.ts:1:1 [line] // entry point
|
|
78
|
+
src/scanner.ts:8:3 [block] /* walk the AST */
|
|
79
|
+
src/legacy.ts:3:1 [line] [@ts-ignore] // @ts-ignore fix later
|
|
80
|
+
|
|
81
|
+
3 comments across 3 files
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
JSON output:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
$ ts-comment-scanner --json src
|
|
88
|
+
{
|
|
89
|
+
"summary": { "files": 1, "comments": 1, "directives": 0 },
|
|
90
|
+
"files": [
|
|
91
|
+
{
|
|
92
|
+
"file": "src/index.ts",
|
|
93
|
+
"comments": [
|
|
94
|
+
{
|
|
95
|
+
"kind": "line",
|
|
96
|
+
"text": "// entry point",
|
|
97
|
+
"start": 0,
|
|
98
|
+
"end": 12,
|
|
99
|
+
"line": 1,
|
|
100
|
+
"column": 1,
|
|
101
|
+
"endLine": 1,
|
|
102
|
+
"endColumn": 13
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Comments identified as directives get a name attached, such as `"directive": "@ts-ignore"`.
|
|
111
|
+
|
|
112
|
+
### Using it in GitHub Actions
|
|
113
|
+
|
|
114
|
+
`--format github` emits each comment as a [workflow command](https://docs.github.com/actions/reference/workflow-commands-for-github-actions), so annotations appear on the relevant lines of a PR.
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
- name: Check for stray comments
|
|
118
|
+
run: npx @kongyo2/ts-comment-scanner --format github --skip-directives --fail-on-comment src
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
::notice file=src/index.ts,line=1,endLine=1,col=1,endColumn=13,title=line comment::// entry point
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Bulk comment removal (code cleanup)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# First, check what would be removed
|
|
129
|
+
ts-comment-scanner --remove --dry-run src
|
|
130
|
+
|
|
131
|
+
# Actually remove (directives and license headers are kept)
|
|
132
|
+
ts-comment-scanner --remove src
|
|
133
|
+
|
|
134
|
+
# Remove everything, including directives and legal comments
|
|
135
|
+
ts-comment-scanner --remove --remove-directives --remove-legal src
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Removal is driven by the AST's comment ranges, so it never touches strings or code. In addition:
|
|
139
|
+
|
|
140
|
+
- Directives such as `@ts-expect-error` / `eslint-disable` are **kept by default**, because removing them would break the build or the linter
|
|
141
|
+
- Legal comments — `/*! ... */` or those containing `@license` / `@preserve` / `@copyright` — are also **kept by default**
|
|
142
|
+
- Whitespace is inserted where removing a block comment would otherwise join tokens together (`a/* x */b` → `a b`)
|
|
143
|
+
- Comment-only lines are removed entirely, and trailing comments are removed together with the preceding whitespace
|
|
144
|
+
- The result is re-scanned to verify it, and if the outcome is unexpected the file is left unchanged and an error is reported
|
|
145
|
+
|
|
146
|
+
### Scanning only changed files (`--diff`)
|
|
147
|
+
|
|
148
|
+
With `--diff <range>`, scanning and removal are limited to the files git reports as changed. The range is exactly what `git diff` accepts as revisions: a single revision compares the working tree against it (untracked new files included, honouring `.gitignore`), while `a..b` / `a...b` compare two commits.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Scan only files with uncommitted changes
|
|
152
|
+
ts-comment-scanner --diff HEAD
|
|
153
|
+
|
|
154
|
+
# Remove comments only from files changed on the branch
|
|
155
|
+
ts-comment-scanner --remove --diff main...HEAD
|
|
156
|
+
|
|
157
|
+
# Check only files changed between two commits in CI
|
|
158
|
+
ts-comment-scanner --fail-on-comment --diff a1b2c3..d4e5f6 src
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
This is designed for workflows like letting a coding agent do some work and then sweeping noise comments out of just the files it touched. Files deleted within the range are excluded, and renames are handled at their new path. git runs in the repository that contains the first input path, so pointing at another repository's checkout works too. Note that unlike `--ignore`, the narrowing also applies to explicitly listed files.
|
|
162
|
+
|
|
163
|
+
### Detectable directives (excerpt)
|
|
164
|
+
|
|
165
|
+
`@ts-ignore` `@ts-expect-error` `@ts-nocheck` `@ts-check` / the `eslint-disable` family, `eslint-env`, `/* global */` / `tslint:` / the `oxlint-disable` family / the `biome-ignore` family / the `deno-lint-ignore` family / `prettier-ignore` / `istanbul ignore`, `c8 ignore`, `v8 ignore`, `node:coverage` / webpack magic comments such as `webpackChunkName:` / `@vite-ignore` / `#__PURE__` / `//# sourceMappingURL=`, `//# sourceURL=` / `@jsx`-family pragmas / `@jest-environment`, `@vitest-environment` / `/// <reference>` / `#region`, `#endregion`
|
|
166
|
+
|
|
167
|
+
## Using it as a library
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { scanPaths, scanComments, removeComments, changedFiles, formatText } from "@kongyo2/ts-comment-scanner";
|
|
171
|
+
|
|
172
|
+
// Scan files / directories together
|
|
173
|
+
const results = await scanPaths(["src"], { ignore: ["**/*.test.ts"] });
|
|
174
|
+
console.log(formatText(results));
|
|
175
|
+
|
|
176
|
+
// Scan a source string directly
|
|
177
|
+
const comments = scanComments("// hello\nconst x = 1;");
|
|
178
|
+
|
|
179
|
+
// Remove comments safely
|
|
180
|
+
const { code, removed, kept } = removeComments("// note\nconst x = 1;\n");
|
|
181
|
+
|
|
182
|
+
// Absolute paths of files changed in a git revision range
|
|
183
|
+
const changed = await changedFiles("main..HEAD");
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Main API
|
|
187
|
+
|
|
188
|
+
| Function | Summary |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `scanComments(source, options?)` | Get an array of comments from a source string (parse TSX with `options.jsx`) |
|
|
191
|
+
| `scanFile(file)` | Scan a single file |
|
|
192
|
+
| `scanPaths(inputs, options?)` | Recursively scan files / directories (supports `ignore` / `extensions`) |
|
|
193
|
+
| `collectFiles(inputs, options?)` | Collect the list of target file paths |
|
|
194
|
+
| `changedFiles(range, cwd?)` | Absolute paths of working-tree files changed in a git revision range |
|
|
195
|
+
| `removeComments(source, options?)` | Remove comments safely (`removeDirectives` / `removeLegal` / `shouldRemove`) |
|
|
196
|
+
| `detectDirective(kind, text)` | Return a normalized name if the comment is a directive |
|
|
197
|
+
| `isLegalComment(text)` | Determine whether a comment is a license/legal comment |
|
|
198
|
+
| `formatText(results)` / `formatJson(results)` / `formatGitHub(results)` | Format scan results |
|
|
199
|
+
|
|
200
|
+
Types: `Comment` / `CommentKind` / `FileScanResult` / `ScanOptions` / `CollectOptions` / `RemoveOptions` / `RemoveResult`
|
|
201
|
+
|
|
202
|
+
## Requirements
|
|
203
|
+
|
|
204
|
+
Node.js 20 or later
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# ts-comment-scanner
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@kongyo2/ts-comment-scanner)
|
|
4
|
+
[](https://www.npmjs.com/package/@kongyo2/ts-comment-scanner)
|
|
5
|
+
[](https://github.com/kongyo2/ts-comment-scanner/actions/workflows/ci.yml)
|
|
6
|
+

|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
[](https://deepwiki.com/kongyo2/ts-comment-scanner)
|
|
10
|
+
|
|
11
|
+
**日本語** | [English](./README.en.md)
|
|
12
|
+
|
|
3
13
|
TypeScript プロジェクト内のコメントを検出・一覧・集計し、安全に削除もできる CLI / ライブラリです。TypeScript の AST を使って解析するため、文字列・テンプレートリテラル・正規表現・JSX テキストを誤検出しません。
|
|
4
14
|
|
|
5
15
|
## 特徴
|
|
@@ -10,6 +20,7 @@ TypeScript プロジェクト内のコメントを検出・一覧・集計し、
|
|
|
10
20
|
- `@ts-ignore` や `eslint-disable` などの**コンパイラ・リンター指示子(ディレクティブ)を自動判別**し、絞り込み・除外が可能
|
|
11
21
|
- **安全なコメント削除**(コードクリーンアップ): ディレクティブとライセンスヘッダーはデフォルトで保持
|
|
12
22
|
- Glob による**カスタム無視パターン** (`--ignore`)、対象拡張子の変更 (`--ext`)
|
|
23
|
+
- **git 連携 (`--diff`)**: 特定コミット間や未コミットの変更で触れられたファイルだけに対象を絞り込み
|
|
13
24
|
- CI 向けの `--fail-on-comment`(コメント検出時に終了コード 1)
|
|
14
25
|
- CLI としても、ライブラリとしても利用可能
|
|
15
26
|
|
|
@@ -37,6 +48,7 @@ ts-comment-scanner [options] [paths...]
|
|
|
37
48
|
フィルタリング:
|
|
38
49
|
--ignore <glob> Glob に一致するファイル・ディレクトリを除外(複数指定可)
|
|
39
50
|
--ext <list> スキャン対象の拡張子(カンマ区切り、既定: .ts,.tsx,.mts,.cts)
|
|
51
|
+
--diff <range> git で変更されたファイルのみを対象(例: HEAD, main..HEAD)
|
|
40
52
|
--skip-directives コンパイラ・リンター指示子を結果から除外
|
|
41
53
|
--only-directives 指示子のみを報告
|
|
42
54
|
|
|
@@ -131,6 +143,23 @@ ts-comment-scanner --remove --remove-directives --remove-legal src
|
|
|
131
143
|
- コメントだけの行は行ごと削除、行末コメントは手前の空白ごと削除
|
|
132
144
|
- 削除後のソースを再スキャンして検証し、想定外の結果になる場合はファイルを変更せずエラー報告
|
|
133
145
|
|
|
146
|
+
### 変更されたファイルだけを対象にする(`--diff`)
|
|
147
|
+
|
|
148
|
+
`--diff <range>` を付けると、git が変更ありと報告するファイルだけにスキャン・削除を絞り込めます。範囲は `git diff` がリビジョンとして受け付ける書式そのままで、単一リビジョンなら作業ツリーとの比較(未追跡の新規ファイルも含む・`.gitignore` は尊重)、`a..b` / `a...b` ならコミット同士の比較になります。
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# 未コミットの変更があるファイルだけをスキャン
|
|
152
|
+
ts-comment-scanner --diff HEAD
|
|
153
|
+
|
|
154
|
+
# ブランチで変更されたファイルだけからコメントを削除
|
|
155
|
+
ts-comment-scanner --remove --diff main...HEAD
|
|
156
|
+
|
|
157
|
+
# 特定コミット間で変更されたファイルのみを CI でチェック
|
|
158
|
+
ts-comment-scanner --fail-on-comment --diff a1b2c3..d4e5f6 src
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
コーディングエージェントに作業させた後、その変更範囲だけを対象にノイズコメントを掃除する、といった使い方を想定しています。範囲内で削除されたファイルは対象外になり、リネームは新しいパスで扱われます。git は最初の入力パスが属するリポジトリで実行されるため、別リポジトリのパスを指定しても動作します。なお `--ignore` と異なり、明示的に指定したファイルにも絞り込みが適用されます。
|
|
162
|
+
|
|
134
163
|
### 検出できるディレクティブ(抜粋)
|
|
135
164
|
|
|
136
165
|
`@ts-ignore` `@ts-expect-error` `@ts-nocheck` `@ts-check` / `eslint-disable` 系・`eslint-env`・`/* global */` / `tslint:` / `oxlint-disable` 系 / `biome-ignore` 系 / `deno-lint-ignore` 系 / `prettier-ignore` / `istanbul ignore`・`c8 ignore`・`v8 ignore`・`node:coverage` / `webpackChunkName:` などの webpack マジックコメント / `@vite-ignore` / `#__PURE__` / `//# sourceMappingURL=`・`//# sourceURL=` / `@jsx` 系プラグマ / `@jest-environment`・`@vitest-environment` / `/// <reference>` / `#region`・`#endregion`
|
|
@@ -138,7 +167,7 @@ ts-comment-scanner --remove --remove-directives --remove-legal src
|
|
|
138
167
|
## ライブラリとして使う
|
|
139
168
|
|
|
140
169
|
```ts
|
|
141
|
-
import { scanPaths, scanComments, removeComments, formatText } from "@kongyo2/ts-comment-scanner";
|
|
170
|
+
import { scanPaths, scanComments, removeComments, changedFiles, formatText } from "@kongyo2/ts-comment-scanner";
|
|
142
171
|
|
|
143
172
|
// ファイル / ディレクトリをまとめてスキャン
|
|
144
173
|
const results = await scanPaths(["src"], { ignore: ["**/*.test.ts"] });
|
|
@@ -149,6 +178,9 @@ const comments = scanComments("// hello\nconst x = 1;");
|
|
|
149
178
|
|
|
150
179
|
// コメントを安全に削除
|
|
151
180
|
const { code, removed, kept } = removeComments("// note\nconst x = 1;\n");
|
|
181
|
+
|
|
182
|
+
// git のリビジョン範囲で変更されたファイルの絶対パスを取得
|
|
183
|
+
const changed = await changedFiles("main..HEAD");
|
|
152
184
|
```
|
|
153
185
|
|
|
154
186
|
### 主な API
|
|
@@ -159,6 +191,7 @@ const { code, removed, kept } = removeComments("// note\nconst x = 1;\n");
|
|
|
159
191
|
| `scanFile(file)` | 1 ファイルをスキャン |
|
|
160
192
|
| `scanPaths(inputs, options?)` | ファイル / ディレクトリ群を再帰的にスキャン(`ignore` / `extensions` 対応) |
|
|
161
193
|
| `collectFiles(inputs, options?)` | 対象ファイルのパス一覧を収集 |
|
|
194
|
+
| `changedFiles(range, cwd?)` | git のリビジョン範囲で変更された作業ツリーのファイルを絶対パスで返す |
|
|
162
195
|
| `removeComments(source, options?)` | コメントを安全に削除(`removeDirectives` / `removeLegal` / `shouldRemove`) |
|
|
163
196
|
| `detectDirective(kind, text)` | コメントがディレクティブなら正規化した名前を返す |
|
|
164
197
|
| `isLegalComment(text)` | ライセンス・法的コメントかどうかを判定 |
|
package/dist/args.d.ts
CHANGED
package/dist/args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AACtD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,aAAa,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qFAAqF;AACrF,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAKD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AACtD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,UAAU,EAAE,aAAa,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qFAAqF;AACrF,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAKD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA+JpD"}
|
package/dist/args.js
CHANGED
|
@@ -12,6 +12,7 @@ export function parseArgs(argv) {
|
|
|
12
12
|
const ignore = [];
|
|
13
13
|
const extensions = [];
|
|
14
14
|
let format = "text";
|
|
15
|
+
let diff;
|
|
15
16
|
let directives = "include";
|
|
16
17
|
let failOnComment = false;
|
|
17
18
|
let remove = false;
|
|
@@ -72,6 +73,14 @@ export function parseArgs(argv) {
|
|
|
72
73
|
extensions.push(...parsed);
|
|
73
74
|
break;
|
|
74
75
|
}
|
|
76
|
+
case "--diff": {
|
|
77
|
+
const value = readValue();
|
|
78
|
+
if (value === "" || value.startsWith("-")) {
|
|
79
|
+
throw new UsageError("option --diff requires a git revision range (e.g. HEAD or main..HEAD)");
|
|
80
|
+
}
|
|
81
|
+
diff = value;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
75
84
|
case "--skip-directives":
|
|
76
85
|
rejectValue();
|
|
77
86
|
if (directives === "only")
|
|
@@ -145,6 +154,7 @@ export function parseArgs(argv) {
|
|
|
145
154
|
format,
|
|
146
155
|
ignore,
|
|
147
156
|
extensions: extensions.length > 0 ? extensions : undefined,
|
|
157
|
+
diff,
|
|
148
158
|
directives,
|
|
149
159
|
failOnComment,
|
|
150
160
|
remove,
|
package/dist/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAmBA,qFAAqF;AACrF,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,GAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpE,MAAM,kBAAkB,GAAG,4DAA4D,CAAC;AAExF,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,MAAM,GAAiB,MAAM,CAAC;IAClC,IAAI,IAAwB,CAAC;IAC7B,IAAI,UAAU,GAAkB,SAAS,CAAC;IAC1C,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAW,CAAC;QAElC,IAAI,SAAS,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,SAAS;QACX,CAAC;QAED,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,GAAW,EAAE;YAC7B,IAAI,WAAW,KAAK,SAAS;gBAAE,OAAO,WAAW,CAAC;YAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC7B,IAAI,IAAI,KAAK,SAAS;gBAAE,MAAM,IAAI,UAAU,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;YAChF,KAAK,IAAI,CAAC,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,GAAS,EAAE;YAC7B,IAAI,WAAW,KAAK,SAAS;gBAAE,MAAM,IAAI,UAAU,CAAC,UAAU,IAAI,wBAAwB,CAAC,CAAC;QAC9F,CAAC,CAAC;QAEF,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,IAAI;gBACP,WAAW,EAAE,CAAC;gBACd,SAAS,GAAG,IAAI,CAAC;gBACjB,MAAM;YACR,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAqB,CAAC,EAAE,CAAC;oBAC7C,MAAM,IAAI,UAAU,CAAC,mBAAmB,KAAK,cAAc,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpF,CAAC;gBACD,MAAM,GAAG,KAAqB,CAAC;gBAC/B,MAAM;YACR,CAAC;YACD,KAAK,QAAQ;gBACX,WAAW,EAAE,CAAC;gBACd,MAAM,GAAG,MAAM,CAAC;gBAChB,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,MAAM,GAAG,SAAS,EAAE;qBACvB,KAAK,CAAC,GAAG,CAAC;qBACV,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;qBACpC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;gBAC3C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACxB,MAAM,IAAI,UAAU,CAAC,8CAA8C,CAAC,CAAC;gBACvE,CAAC;gBACD,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;gBAC3B,MAAM;YACR,CAAC;YACD,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;gBAC1B,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC1C,MAAM,IAAI,UAAU,CAAC,uEAAuE,CAAC,CAAC;gBAChG,CAAC;gBACD,IAAI,GAAG,KAAK,CAAC;gBACb,MAAM;YACR,CAAC;YACD,KAAK,mBAAmB;gBACtB,WAAW,EAAE,CAAC;gBACd,IAAI,UAAU,KAAK,MAAM;oBAAE,MAAM,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAAC;gBACpE,UAAU,GAAG,MAAM,CAAC;gBACpB,MAAM;YACR,KAAK,mBAAmB;gBACtB,WAAW,EAAE,CAAC;gBACd,IAAI,UAAU,KAAK,MAAM;oBAAE,MAAM,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAAC;gBACpE,UAAU,GAAG,MAAM,CAAC;gBACpB,MAAM;YACR,KAAK,mBAAmB;gBACtB,WAAW,EAAE,CAAC;gBACd,aAAa,GAAG,IAAI,CAAC;gBACrB,MAAM;YACR,KAAK,UAAU;gBACb,WAAW,EAAE,CAAC;gBACd,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,qBAAqB;gBACxB,WAAW,EAAE,CAAC;gBACd,gBAAgB,GAAG,IAAI,CAAC;gBACxB,MAAM;YACR,KAAK,gBAAgB;gBACnB,WAAW,EAAE,CAAC;gBACd,WAAW,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,WAAW;gBACd,WAAW,EAAE,CAAC;gBACd,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ;gBACX,WAAW,EAAE,CAAC;gBACd,IAAI,GAAG,IAAI,CAAC;gBACZ,MAAM;YACR,KAAK,IAAI,CAAC;YACV,KAAK,WAAW;gBACd,WAAW,EAAE,CAAC;gBACd,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM;YACR;gBACE,MAAM,IAAI,UAAU,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI;YACxB,CAAC,MAAM,EAAE,WAAW,CAAC;YACrB,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;YACzC,CAAC,WAAW,EAAE,gBAAgB,CAAC;SACvB,EAAE,CAAC;YACX,IAAI,GAAG;gBAAE,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IACD,IAAI,MAAM,IAAI,aAAa,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAAC,oDAAoD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,MAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,UAAU,CAAC,kDAAkD,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,MAAM,IAAI,UAAU,KAAK,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACzD,MAAM,IAAI,UAAU,CAClB,+FAA+F,CAChG,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,IAAI,UAAU,KAAK,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACxD,MAAM,IAAI,UAAU,CAAC,+DAA+D,CAAC,CAAC;IACxF,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACvC,MAAM;QACN,MAAM;QACN,UAAU,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;QAC1D,IAAI;QACJ,UAAU;QACV,aAAa;QACb,MAAM;QACN,gBAAgB;QAChB,WAAW;QACX,MAAM;QACN,IAAI;QACJ,OAAO;KACR,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAC1B,CAAC"}
|
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,6 @@
|
|
|
1
1
|
export { scanComments, type ScanOptions } from "./scanner.js";
|
|
2
2
|
export { collectFiles, isJsxFile, scanFile, scanPaths, type CollectOptions } from "./files.js";
|
|
3
|
+
export { changedFiles } from "./git.js";
|
|
3
4
|
export { removeComments, type RemoveOptions, type RemoveResult } from "./remove.js";
|
|
4
5
|
export { detectDirective, isLegalComment } from "./directives.js";
|
|
5
6
|
export { formatText, formatJson, formatGitHub } from "./report.js";
|
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,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"}
|
|
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,5 +1,6 @@
|
|
|
1
1
|
export { scanComments } from "./scanner.js";
|
|
2
2
|
export { collectFiles, isJsxFile, scanFile, scanPaths } from "./files.js";
|
|
3
|
+
export { changedFiles } from "./git.js";
|
|
3
4
|
export { removeComments } from "./remove.js";
|
|
4
5
|
export { detectDirective, isLegalComment } from "./directives.js";
|
|
5
6
|
export { formatText, formatJson, formatGitHub } from "./report.js";
|
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,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"}
|
|
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/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, 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";
|
|
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 --diff <range> Only files git reports changed in the revision range\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\n--diff narrows any scan or removal to files changed in git: a single revision\ncompares the working tree against it (HEAD covers all uncommitted work,\nuntracked files included), while main..HEAD compares two commits. Handy for\ncleaning up only the files a coding agent just touched.\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 ts-comment-scanner --remove --diff main..HEAD\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":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAWA,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,o+DA6CrB,CAAC;AAEF,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA4CpE"}
|
package/dist/run.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
2
4
|
import { parseArgs, UsageError } from "./args.js";
|
|
3
|
-
import { collectFiles, isJsxFile, mapLimit,
|
|
5
|
+
import { collectFiles, isJsxFile, mapLimit, scanFile, FILE_CONCURRENCY } from "./files.js";
|
|
6
|
+
import { changedFiles } from "./git.js";
|
|
4
7
|
import { removeComments } from "./remove.js";
|
|
5
8
|
import { count, formatGitHub, formatJson, formatText } from "./report.js";
|
|
6
9
|
import { getVersion } from "./version.js";
|
|
@@ -15,6 +18,7 @@ Output:
|
|
|
15
18
|
Filtering:
|
|
16
19
|
--ignore <glob> Skip files/directories matching the glob (repeatable)
|
|
17
20
|
--ext <list> Comma-separated extensions to scan (default: .ts,.tsx,.mts,.cts)
|
|
21
|
+
--diff <range> Only files git reports changed in the revision range
|
|
18
22
|
--skip-directives Hide compiler/linter directives (@ts-ignore, eslint-disable, ...)
|
|
19
23
|
--only-directives Report only compiler/linter directives
|
|
20
24
|
|
|
@@ -35,6 +39,11 @@ Paths default to the current directory. Directories are scanned recursively,
|
|
|
35
39
|
skipping node_modules and .git. Removal keeps directives and license headers
|
|
36
40
|
unless explicitly requested, so builds and linters keep working.
|
|
37
41
|
|
|
42
|
+
--diff narrows any scan or removal to files changed in git: a single revision
|
|
43
|
+
compares the working tree against it (HEAD covers all uncommitted work,
|
|
44
|
+
untracked files included), while main..HEAD compares two commits. Handy for
|
|
45
|
+
cleaning up only the files a coding agent just touched.
|
|
46
|
+
|
|
38
47
|
Exit codes: 0 success, 1 comments reported with --fail-on-comment, 2 error.
|
|
39
48
|
|
|
40
49
|
Examples:
|
|
@@ -42,6 +51,7 @@ Examples:
|
|
|
42
51
|
ts-comment-scanner --format github --fail-on-comment src
|
|
43
52
|
ts-comment-scanner --ignore "**/*.test.ts" --skip-directives src
|
|
44
53
|
ts-comment-scanner --remove --dry-run src
|
|
54
|
+
ts-comment-scanner --remove --diff main..HEAD
|
|
45
55
|
`;
|
|
46
56
|
export async function run(argv, io) {
|
|
47
57
|
// Help always wins, even on an otherwise-invalid command line.
|
|
@@ -72,7 +82,8 @@ export async function run(argv, io) {
|
|
|
72
82
|
if (options.remove) {
|
|
73
83
|
return await runRemove(options, collectOptions, io);
|
|
74
84
|
}
|
|
75
|
-
const
|
|
85
|
+
const files = await collectTargets(options, collectOptions);
|
|
86
|
+
const results = filterDirectives(await mapLimit(files, FILE_CONCURRENCY, scanFile), options.directives);
|
|
76
87
|
io.out(`${render(results, options.format)}\n`);
|
|
77
88
|
const total = results.reduce((sum, result) => sum + result.comments.length, 0);
|
|
78
89
|
return options.failOnComment && total > 0 ? 1 : 0;
|
|
@@ -83,6 +94,24 @@ export async function run(argv, io) {
|
|
|
83
94
|
return 2;
|
|
84
95
|
}
|
|
85
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Collects the input files, narrowed to the files git reports changed when
|
|
99
|
+
* --diff is set. git runs in the repository containing the first input path
|
|
100
|
+
* (not the collected files, which could sit in a nested repository), so
|
|
101
|
+
* scanning another repository's checkout works from anywhere.
|
|
102
|
+
*/
|
|
103
|
+
async function collectTargets(options, collectOptions) {
|
|
104
|
+
const files = await collectFiles(options.paths, collectOptions);
|
|
105
|
+
if (options.diff === undefined)
|
|
106
|
+
return files;
|
|
107
|
+
const first = resolve(options.paths[0]);
|
|
108
|
+
const anchor = (await stat(first)).isDirectory() ? first : dirname(first);
|
|
109
|
+
const changed = new Set(await changedFiles(options.diff, anchor));
|
|
110
|
+
// Realpath only the directory part: spellings through symlinked directories
|
|
111
|
+
// then compare equal, while a tracked symlink still matches the path git
|
|
112
|
+
// reports it at instead of dereferencing to its target.
|
|
113
|
+
return files.filter((file) => changed.has(join(realpathSync(dirname(file)), basename(file))));
|
|
114
|
+
}
|
|
86
115
|
/** True when -h/--help appears before any `--` separator. */
|
|
87
116
|
function wantsHelp(argv) {
|
|
88
117
|
for (const arg of argv) {
|
|
@@ -116,7 +145,7 @@ function filterDirectives(results, mode) {
|
|
|
116
145
|
}));
|
|
117
146
|
}
|
|
118
147
|
async function runRemove(options, collectOptions, io) {
|
|
119
|
-
const files = await
|
|
148
|
+
const files = await collectTargets(options, collectOptions);
|
|
120
149
|
const outcomes = await mapLimit(files, FILE_CONCURRENCY, async (file) => {
|
|
121
150
|
try {
|
|
122
151
|
const source = await readFile(file, "utf8");
|
|
@@ -155,11 +184,11 @@ async function runRemove(options, collectOptions, io) {
|
|
|
155
184
|
function renderRemoval(removals, options) {
|
|
156
185
|
const totalRemoved = removals.reduce((sum, entry) => sum + entry.removed.length, 0);
|
|
157
186
|
const totalKept = removals.reduce((sum, entry) => sum + entry.kept.length, 0);
|
|
158
|
-
const
|
|
187
|
+
const changedEntries = removals.filter((entry) => entry.removed.length > 0);
|
|
159
188
|
const keptNote = totalKept > 0 ? ` Kept ${count(totalKept, "protected comment")}.` : "";
|
|
160
189
|
if (options.format === "json") {
|
|
161
190
|
return JSON.stringify({
|
|
162
|
-
summary: { files:
|
|
191
|
+
summary: { files: changedEntries.length, removed: totalRemoved, kept: totalKept, dryRun: options.dryRun },
|
|
163
192
|
files: removals,
|
|
164
193
|
}, null, 2);
|
|
165
194
|
}
|
|
@@ -167,12 +196,12 @@ function renderRemoval(removals, options) {
|
|
|
167
196
|
return `No removable comments found.${keptNote}`;
|
|
168
197
|
}
|
|
169
198
|
const verb = options.dryRun ? "would remove" : "removed";
|
|
170
|
-
const lines =
|
|
199
|
+
const lines = changedEntries.map((entry) => {
|
|
171
200
|
const kept = entry.kept.length > 0 ? ` (kept ${entry.kept.length})` : "";
|
|
172
201
|
return `${entry.file}: ${verb} ${entry.removed.length}${kept}`;
|
|
173
202
|
});
|
|
174
203
|
const sentenceVerb = verb.charAt(0).toUpperCase() + verb.slice(1);
|
|
175
|
-
lines.push("", `${sentenceVerb} ${count(totalRemoved, "comment")} across ${count(
|
|
204
|
+
lines.push("", `${sentenceVerb} ${count(totalRemoved, "comment")} across ${count(changedEntries.length, "file")}.${keptNote}`);
|
|
176
205
|
return lines.join("\n");
|
|
177
206
|
}
|
|
178
207
|
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|