Skip to content

Commit c5f0ee6

Browse files
committedOct 31, 2024
Add disclosure reporter
1 parent 3354e3a commit c5f0ee6

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed
 

‎packages/docs/src/content/docs/features/reporters.md

+51-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ Knip provides the following built-in reporters:
88

99
- `codeowners`
1010
- `compact`
11-
- `json`
12-
- `markdown`
11+
- [`disclosure`](#disclosure)
12+
- [`json`](#json)
13+
- [`markdown`](#markdown)
1314
- `symbol` (default)
1415

1516
Example usage:
@@ -103,6 +104,54 @@ Markdown tables separated by issue types as headings, for example:
103104
| ./unresolved | src/index.ts:10:12 | error |
104105
```
105106

107+
### Disclosure
108+
109+
This reporter is useful for sharing large reports. Groups of issues are rendered
110+
in a closed state initially. The reporter renders this:
111+
112+
````text
113+
$ knip --reporter disclosure
114+
115+
<details><summary>Unused files (2)</summary>
116+
117+
```
118+
unused.ts
119+
dangling.js
120+
```
121+
122+
</details>
123+
124+
<details><summary>Unused dependencies (2)</summary>
125+
126+
```
127+
unused-dep package.json
128+
my-package package.json
129+
```
130+
131+
</details>
132+
````
133+
134+
The above can be copy-pasted where HTML and Markdown is supported, such as a
135+
GitHub issue or pull request, and renders like so:
136+
137+
<details><summary>Unused files (2)</summary>
138+
139+
```
140+
unused.ts
141+
dangling.js
142+
```
143+
144+
</details>
145+
146+
<details><summary>Unused dependencies (2)</summary>
147+
148+
```
149+
unused-dep package.json
150+
my-package package.json
151+
```
152+
153+
</details>
154+
106155
## Custom Reporters
107156

108157
When the provided built-in reporters are not sufficient, a custom local reporter
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import EasyTable from 'easy-table';
2+
import type { Entries } from 'type-fest';
3+
import type { Issue, ReporterOptions } from '../types/issues.js';
4+
import { relative, toRelative } from '../util/path.js';
5+
import { getTitle } from './util.js';
6+
7+
const printHeader = (size: number, title?: string) =>
8+
console.log(`<details>${title ? `<summary>${title} (${size})</summary>` : ''}\n\n\`\`\``);
9+
10+
const printFooter = () => console.log('```\n\n</details>\n');
11+
12+
const logIssueRecord = (issues: Issue[]) => {
13+
const table = new EasyTable();
14+
for (const issue of issues) {
15+
table.cell('symbol', issue.symbols ? issue.symbols.map(s => s.symbol).join(', ') : issue.symbol);
16+
issue.parentSymbol && table.cell('parentSymbol', issue.parentSymbol);
17+
issue.symbolType && table.cell('symbolType', issue.symbolType);
18+
const pos = issue.line === undefined ? '' : `:${issue.line}${issue.col === undefined ? '' : `:${issue.col}`}`;
19+
const cell = `${relative(issue.filePath)}${pos}`;
20+
table.cell('filePath', cell);
21+
table.newRow();
22+
}
23+
console.log(table.sort(['filePath', 'parentSymbol', 'symbol']).print().trim());
24+
};
25+
26+
export default ({ report, issues }: ReporterOptions) => {
27+
const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
28+
let totalIssues = 0;
29+
30+
for (const [reportType, isReportType] of Object.entries(report) as Entries<typeof report>) {
31+
if (reportType === '_files') continue;
32+
33+
if (isReportType) {
34+
const title = reportMultipleGroups ? getTitle(reportType) : undefined;
35+
36+
if (reportType === 'files') {
37+
const issuesForType = Array.from(issues._files);
38+
if (issuesForType.length > 0) {
39+
printHeader(issuesForType.length, title);
40+
const sortedIssues = issuesForType.sort((a, b) => a.filePath.localeCompare(b.filePath));
41+
for (const issue of sortedIssues) console.log(toRelative(issue.filePath));
42+
totalIssues = totalIssues + issuesForType.length;
43+
printFooter();
44+
}
45+
} else {
46+
const issuesForType = Object.values(issues[reportType]).flatMap(Object.values);
47+
if (issuesForType.length > 0) {
48+
printHeader(issuesForType.length, title);
49+
logIssueRecord(issuesForType);
50+
totalIssues = totalIssues + issuesForType.length;
51+
printFooter();
52+
}
53+
}
54+
}
55+
}
56+
};

‎packages/knip/src/reporters/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import codeowners from './codeowners.js';
22
import compact from './compact.js';
3+
import disclosure from './disclosure.js';
34
import json from './json.js';
45
import markdown from './markdown.js';
56
import symbols from './symbols.js';
@@ -8,6 +9,7 @@ export default {
89
symbols,
910
compact,
1011
codeowners,
12+
disclosure,
1113
json,
1214
markdown,
1315
};

0 commit comments

Comments
 (0)
Please sign in to comment.