agent-reviews 0.4.0 → 0.5.1
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/.claude-plugin/plugin.json +1 -1
- package/README.md +15 -0
- package/bin/agent-reviews.js +8 -0
- package/lib/comments.js +39 -4
- package/lib/format.js +3 -1
- package/package.json +7 -2
- package/skills/agent-reviews/SKILL.md +9 -17
- package/skills/agent-reviews/scripts/agent-reviews.js +9 -1
- package/skills/agent-reviews/scripts/comments.js +39 -4
- package/skills/agent-reviews/scripts/format.js +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-reviews",
|
|
3
3
|
"description": "Manage GitHub PR review comments from Claude Code. Automatically triage, fix, and respond to bot findings.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Paul Bakaus",
|
|
7
7
|
"url": "https://github.com/pbakaus"
|
package/README.md
CHANGED
|
@@ -4,6 +4,14 @@ Manage GitHub PR review comments from the terminal and from AI coding agents.
|
|
|
4
4
|
|
|
5
5
|
PR review bots (Copilot, Cursor Bugbot, CodeRabbit, etc.) leave inline comments on your pull requests. agent-reviews gives you a CLI to list, filter, reply to, and watch those comments, plus a Claude Code skill that automates the entire triage-fix-reply loop.
|
|
6
6
|
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
**`gh` CLI is fragile for review comments.** Agents frequently get the syntax wrong, fail to paginate, and can't reliably detect whether a comment has been replied to. agent-reviews provides a single, purpose-built interface that handles all of this correctly.
|
|
10
|
+
|
|
11
|
+
**Bot reviews create a doom loop.** You fix one round of findings, push, and new comments appear. Fix those, push again, more comments. This cycle can eat hours. The included skill solves it with an integrated watcher that keeps fixing and replying until the bots go quiet.
|
|
12
|
+
|
|
13
|
+
**Works in Claude Code for the web.** Most solutions rely on local tooling that isn't available in cloud environments. agent-reviews works everywhere Claude Code runs, so you can kick off a session in your browser, let it resolve all bot findings autonomously, and come back to a clean PR.
|
|
14
|
+
|
|
7
15
|
## Install
|
|
8
16
|
|
|
9
17
|
### CLI (npm)
|
|
@@ -90,6 +98,7 @@ agent-reviews --pr 42
|
|
|
90
98
|
| `--json` | `-j` | JSON output |
|
|
91
99
|
| `--bots-only` | `-b` | Only bot comments |
|
|
92
100
|
| `--humans-only` | `-H` | Only human comments |
|
|
101
|
+
| `--expanded` | `-e` | Show full detail for each listed comment |
|
|
93
102
|
| `--watch` | `-w` | Poll for new comments |
|
|
94
103
|
| `--interval <sec>` | `-i` | Poll interval in seconds (default: 30) |
|
|
95
104
|
| `--timeout <sec>` | | Inactivity timeout in seconds (default: 600) |
|
|
@@ -150,6 +159,12 @@ Each comment displays its reply status:
|
|
|
150
159
|
|
|
151
160
|
Polls the GitHub API at a configurable interval and reports new comments as they appear. Outputs both formatted text and JSON for AI agent consumption. Exits automatically after a configurable inactivity timeout (default: 10 minutes).
|
|
152
161
|
|
|
162
|
+
## FAQ
|
|
163
|
+
|
|
164
|
+
### How can I make the skill review human comments as well?
|
|
165
|
+
|
|
166
|
+
The skill defaults to `--bots-only` because that's the most common use case, but it's easy to change. Open your local copy of `SKILL.md` (inside `skills/agent-reviews/`) and remove the `--bots-only` flag from the commands in Steps 2, 6, and anywhere else it appears. The skill will then fetch and process all comments, regardless of author.
|
|
167
|
+
|
|
153
168
|
## License
|
|
154
169
|
|
|
155
170
|
MIT
|
package/bin/agent-reviews.js
CHANGED
|
@@ -63,6 +63,7 @@ function parseArgs() {
|
|
|
63
63
|
detail: null,
|
|
64
64
|
help: false,
|
|
65
65
|
version: false,
|
|
66
|
+
expanded: false,
|
|
66
67
|
watch: false,
|
|
67
68
|
watchInterval: 30,
|
|
68
69
|
watchTimeout: 600,
|
|
@@ -118,6 +119,10 @@ function parseArgs() {
|
|
|
118
119
|
case "--timeout":
|
|
119
120
|
result.watchTimeout = Number.parseInt(args[++i], 10);
|
|
120
121
|
break;
|
|
122
|
+
case "--expanded":
|
|
123
|
+
case "-e":
|
|
124
|
+
result.expanded = true;
|
|
125
|
+
break;
|
|
121
126
|
case "--help":
|
|
122
127
|
case "-h":
|
|
123
128
|
result.help = true;
|
|
@@ -146,6 +151,7 @@ ${colors.bright}Usage:${colors.reset}
|
|
|
146
151
|
agent-reviews --unanswered List comments without replies
|
|
147
152
|
agent-reviews --reply <id> "msg" Reply to a specific comment
|
|
148
153
|
agent-reviews --detail <id> Show full detail for a comment
|
|
154
|
+
agent-reviews --expanded Show full detail for each comment
|
|
149
155
|
agent-reviews --watch Watch for new comments (poll mode)
|
|
150
156
|
agent-reviews --json Output as JSON for scripting
|
|
151
157
|
|
|
@@ -158,6 +164,7 @@ ${colors.bright}Options:${colors.reset}
|
|
|
158
164
|
-j, --json Output as JSON instead of formatted text
|
|
159
165
|
-b, --bots-only Only show comments from bots
|
|
160
166
|
-H, --humans-only Only show comments from humans
|
|
167
|
+
-e, --expanded Show full detail (body, diff hunk, replies) for each comment
|
|
161
168
|
-h, --help Show this help
|
|
162
169
|
-v, --version Show version
|
|
163
170
|
|
|
@@ -170,6 +177,7 @@ ${colors.bright}Examples:${colors.reset}
|
|
|
170
177
|
agent-reviews # Show all comments
|
|
171
178
|
agent-reviews -u # Show unresolved only
|
|
172
179
|
agent-reviews -a --bots-only # Unanswered bot comments
|
|
180
|
+
agent-reviews -a --bots-only --expanded # Full detail for unanswered bot comments
|
|
173
181
|
agent-reviews --reply 12345 "Fixed!" # Reply to comment #12345
|
|
174
182
|
agent-reviews --detail 12345 # Full detail for a comment
|
|
175
183
|
agent-reviews --detail 12345 --json # Detail as JSON
|
package/lib/comments.js
CHANGED
|
@@ -130,6 +130,40 @@ function isBot(username) {
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Body cleanup
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Strip bot boilerplate from comment bodies:
|
|
139
|
+
* - HTML comments (<!-- ... -->)
|
|
140
|
+
* - Cursor "Fix in Cursor" / "Fix in Web" button blocks
|
|
141
|
+
* - "Additional Locations" <details> blocks
|
|
142
|
+
* - Collapse leftover blank lines
|
|
143
|
+
*/
|
|
144
|
+
function cleanBody(body) {
|
|
145
|
+
if (!body) return body;
|
|
146
|
+
|
|
147
|
+
let cleaned = body;
|
|
148
|
+
|
|
149
|
+
// Remove HTML comments (single and multi-line)
|
|
150
|
+
cleaned = cleaned.replace(/<!--[\s\S]*?-->/g, "");
|
|
151
|
+
|
|
152
|
+
// Remove <details> blocks containing "Additional Locations"
|
|
153
|
+
cleaned = cleaned.replace(
|
|
154
|
+
/<details>\s*<summary>\s*Additional Locations[\s\S]*?<\/details>/gi,
|
|
155
|
+
""
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Remove <p> blocks containing cursor.com links
|
|
159
|
+
cleaned = cleaned.replace(/<p>\s*<a [^>]*cursor\.com[\s\S]*?<\/p>/gi, "");
|
|
160
|
+
|
|
161
|
+
// Collapse runs of 3+ newlines into 2
|
|
162
|
+
cleaned = cleaned.replace(/\n{3,}/g, "\n\n");
|
|
163
|
+
|
|
164
|
+
return cleaned.trim();
|
|
165
|
+
}
|
|
166
|
+
|
|
133
167
|
// ---------------------------------------------------------------------------
|
|
134
168
|
// Processing
|
|
135
169
|
// ---------------------------------------------------------------------------
|
|
@@ -148,7 +182,7 @@ function processComments(data, options = {}) {
|
|
|
148
182
|
repliesMap.get(comment.in_reply_to_id).push({
|
|
149
183
|
id: comment.id,
|
|
150
184
|
user: comment.user?.login,
|
|
151
|
-
body: comment.body,
|
|
185
|
+
body: cleanBody(comment.body),
|
|
152
186
|
createdAt: comment.created_at,
|
|
153
187
|
isBot: isBot(comment.user?.login),
|
|
154
188
|
});
|
|
@@ -174,7 +208,7 @@ function processComments(data, options = {}) {
|
|
|
174
208
|
path: comment.path,
|
|
175
209
|
line: comment.line || comment.original_line,
|
|
176
210
|
diffHunk: comment.diff_hunk || null,
|
|
177
|
-
body: comment.body,
|
|
211
|
+
body: cleanBody(comment.body),
|
|
178
212
|
createdAt: comment.created_at,
|
|
179
213
|
updatedAt: comment.updated_at,
|
|
180
214
|
url: comment.html_url,
|
|
@@ -197,7 +231,7 @@ function processComments(data, options = {}) {
|
|
|
197
231
|
path: null,
|
|
198
232
|
line: null,
|
|
199
233
|
diffHunk: null,
|
|
200
|
-
body: comment.body,
|
|
234
|
+
body: cleanBody(comment.body),
|
|
201
235
|
createdAt: comment.created_at,
|
|
202
236
|
updatedAt: comment.updated_at,
|
|
203
237
|
url: comment.html_url,
|
|
@@ -221,7 +255,7 @@ function processComments(data, options = {}) {
|
|
|
221
255
|
path: null,
|
|
222
256
|
line: null,
|
|
223
257
|
diffHunk: null,
|
|
224
|
-
body: review.body,
|
|
258
|
+
body: cleanBody(review.body),
|
|
225
259
|
state: review.state,
|
|
226
260
|
createdAt: review.submitted_at,
|
|
227
261
|
updatedAt: review.submitted_at,
|
|
@@ -330,5 +364,6 @@ module.exports = {
|
|
|
330
364
|
replyToComment,
|
|
331
365
|
isBot,
|
|
332
366
|
isMetaComment,
|
|
367
|
+
cleanBody,
|
|
333
368
|
DEFAULT_META_FILTERS,
|
|
334
369
|
};
|
package/lib/format.js
CHANGED
|
@@ -152,7 +152,9 @@ function formatOutput(comments, options) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
const header = `${colors.bright}Found ${comments.length} comment${comments.length === 1 ? "" : "s"}${colors.reset}\n`;
|
|
155
|
-
const
|
|
155
|
+
const formatter = options.expanded ? formatDetailedComment : formatComment;
|
|
156
|
+
const separator = options.expanded ? "\n\n" + "=".repeat(60) + "\n\n" : "\n\n";
|
|
157
|
+
const formatted = comments.map((c) => formatter(c)).join(separator);
|
|
156
158
|
|
|
157
159
|
return `${header}\n${formatted}`;
|
|
158
160
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-reviews",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "CLI and Claude Code skill for managing GitHub PR review comments. List, filter, reply, and watch for bot findings.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Paul Bakaus",
|
|
@@ -28,9 +28,14 @@
|
|
|
28
28
|
".claude-plugin/"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"build:skill": "node scripts/build-skill.js"
|
|
31
|
+
"build:skill": "node scripts/build-skill.js",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest"
|
|
32
34
|
},
|
|
33
35
|
"engines": {
|
|
34
36
|
"node": ">=18"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"vitest": "^4.0.18"
|
|
35
40
|
}
|
|
36
41
|
}
|
|
@@ -5,7 +5,7 @@ license: MIT
|
|
|
5
5
|
compatibility: Requires git and gh (GitHub CLI) installed. Designed for Claude Code.
|
|
6
6
|
metadata:
|
|
7
7
|
author: pbakaus
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.5.1"
|
|
9
9
|
homepage: https://github.com/pbakaus/agent-reviews
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -21,29 +21,21 @@ gh pr view --json number,url,headRefName
|
|
|
21
21
|
|
|
22
22
|
If no PR exists, notify the user and exit.
|
|
23
23
|
|
|
24
|
-
### Step 2: Fetch All Bot Comments
|
|
24
|
+
### Step 2: Fetch All Bot Comments (Expanded)
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
scripts/agent-reviews.js --bots-only --unanswered
|
|
27
|
+
scripts/agent-reviews.js --bots-only --unanswered --expanded
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
This shows only unanswered bot comments. Each comment shows its ID in brackets (e.g., `[12345678]`)
|
|
30
|
+
This shows only unanswered bot comments with full detail: complete comment body (no truncation), diff hunk (code context), and all replies. Each comment shows its ID in brackets (e.g., `[12345678]`).
|
|
31
31
|
|
|
32
32
|
If zero comments are returned, print "No unanswered bot comments found" and skip to Phase 2.
|
|
33
33
|
|
|
34
34
|
### Step 3: Process Each Unanswered Comment
|
|
35
35
|
|
|
36
|
-
For each comment
|
|
36
|
+
For each comment from the expanded output:
|
|
37
37
|
|
|
38
|
-
#### A.
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
scripts/agent-reviews.js --detail <comment_id>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
This shows the full comment body (no truncation), the diff hunk (code context), and all replies. Use this instead of `gh` CLI for comment details.
|
|
45
|
-
|
|
46
|
-
#### B. Evaluate the Finding
|
|
38
|
+
#### A. Evaluate the Finding
|
|
47
39
|
|
|
48
40
|
Read the referenced code and determine:
|
|
49
41
|
|
|
@@ -72,7 +64,7 @@ Read the referenced code and determine:
|
|
|
72
64
|
- Multiple valid interpretations exist
|
|
73
65
|
- The fix could have unintended side effects
|
|
74
66
|
|
|
75
|
-
####
|
|
67
|
+
#### B. Act on Evaluation
|
|
76
68
|
|
|
77
69
|
**If TRUE POSITIVE:** Fix the code. Track the comment ID and a brief description of the fix.
|
|
78
70
|
|
|
@@ -145,8 +137,8 @@ Use `TaskOutput` to wait for the watcher to complete (blocks up to 12 minutes).
|
|
|
145
137
|
### Step 8: Process New Comments (if any)
|
|
146
138
|
|
|
147
139
|
If the watcher found new comments:
|
|
148
|
-
1.
|
|
149
|
-
2.
|
|
140
|
+
1. Use `--detail <id>` to read each new comment's full detail
|
|
141
|
+
2. Process them exactly as in Phase 1, Steps 3-5
|
|
150
142
|
|
|
151
143
|
If no new comments were found, move to the summary.
|
|
152
144
|
|
|
@@ -63,6 +63,7 @@ function parseArgs() {
|
|
|
63
63
|
detail: null,
|
|
64
64
|
help: false,
|
|
65
65
|
version: false,
|
|
66
|
+
expanded: false,
|
|
66
67
|
watch: false,
|
|
67
68
|
watchInterval: 30,
|
|
68
69
|
watchTimeout: 600,
|
|
@@ -118,6 +119,10 @@ function parseArgs() {
|
|
|
118
119
|
case "--timeout":
|
|
119
120
|
result.watchTimeout = Number.parseInt(args[++i], 10);
|
|
120
121
|
break;
|
|
122
|
+
case "--expanded":
|
|
123
|
+
case "-e":
|
|
124
|
+
result.expanded = true;
|
|
125
|
+
break;
|
|
121
126
|
case "--help":
|
|
122
127
|
case "-h":
|
|
123
128
|
result.help = true;
|
|
@@ -146,6 +151,7 @@ ${colors.bright}Usage:${colors.reset}
|
|
|
146
151
|
agent-reviews --unanswered List comments without replies
|
|
147
152
|
agent-reviews --reply <id> "msg" Reply to a specific comment
|
|
148
153
|
agent-reviews --detail <id> Show full detail for a comment
|
|
154
|
+
agent-reviews --expanded Show full detail for each comment
|
|
149
155
|
agent-reviews --watch Watch for new comments (poll mode)
|
|
150
156
|
agent-reviews --json Output as JSON for scripting
|
|
151
157
|
|
|
@@ -158,6 +164,7 @@ ${colors.bright}Options:${colors.reset}
|
|
|
158
164
|
-j, --json Output as JSON instead of formatted text
|
|
159
165
|
-b, --bots-only Only show comments from bots
|
|
160
166
|
-H, --humans-only Only show comments from humans
|
|
167
|
+
-e, --expanded Show full detail (body, diff hunk, replies) for each comment
|
|
161
168
|
-h, --help Show this help
|
|
162
169
|
-v, --version Show version
|
|
163
170
|
|
|
@@ -170,6 +177,7 @@ ${colors.bright}Examples:${colors.reset}
|
|
|
170
177
|
agent-reviews # Show all comments
|
|
171
178
|
agent-reviews -u # Show unresolved only
|
|
172
179
|
agent-reviews -a --bots-only # Unanswered bot comments
|
|
180
|
+
agent-reviews -a --bots-only --expanded # Full detail for unanswered bot comments
|
|
173
181
|
agent-reviews --reply 12345 "Fixed!" # Reply to comment #12345
|
|
174
182
|
agent-reviews --detail 12345 # Full detail for a comment
|
|
175
183
|
agent-reviews --detail 12345 --json # Detail as JSON
|
|
@@ -320,7 +328,7 @@ async function main() {
|
|
|
320
328
|
const options = parseArgs();
|
|
321
329
|
|
|
322
330
|
if (options.version) {
|
|
323
|
-
console.log("0.
|
|
331
|
+
console.log("0.5.1");
|
|
324
332
|
process.exit(0);
|
|
325
333
|
}
|
|
326
334
|
|
|
@@ -130,6 +130,40 @@ function isBot(username) {
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Body cleanup
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Strip bot boilerplate from comment bodies:
|
|
139
|
+
* - HTML comments (<!-- ... -->)
|
|
140
|
+
* - Cursor "Fix in Cursor" / "Fix in Web" button blocks
|
|
141
|
+
* - "Additional Locations" <details> blocks
|
|
142
|
+
* - Collapse leftover blank lines
|
|
143
|
+
*/
|
|
144
|
+
function cleanBody(body) {
|
|
145
|
+
if (!body) return body;
|
|
146
|
+
|
|
147
|
+
let cleaned = body;
|
|
148
|
+
|
|
149
|
+
// Remove HTML comments (single and multi-line)
|
|
150
|
+
cleaned = cleaned.replace(/<!--[\s\S]*?-->/g, "");
|
|
151
|
+
|
|
152
|
+
// Remove <details> blocks containing "Additional Locations"
|
|
153
|
+
cleaned = cleaned.replace(
|
|
154
|
+
/<details>\s*<summary>\s*Additional Locations[\s\S]*?<\/details>/gi,
|
|
155
|
+
""
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Remove <p> blocks containing cursor.com links
|
|
159
|
+
cleaned = cleaned.replace(/<p>\s*<a [^>]*cursor\.com[\s\S]*?<\/p>/gi, "");
|
|
160
|
+
|
|
161
|
+
// Collapse runs of 3+ newlines into 2
|
|
162
|
+
cleaned = cleaned.replace(/\n{3,}/g, "\n\n");
|
|
163
|
+
|
|
164
|
+
return cleaned.trim();
|
|
165
|
+
}
|
|
166
|
+
|
|
133
167
|
// ---------------------------------------------------------------------------
|
|
134
168
|
// Processing
|
|
135
169
|
// ---------------------------------------------------------------------------
|
|
@@ -148,7 +182,7 @@ function processComments(data, options = {}) {
|
|
|
148
182
|
repliesMap.get(comment.in_reply_to_id).push({
|
|
149
183
|
id: comment.id,
|
|
150
184
|
user: comment.user?.login,
|
|
151
|
-
body: comment.body,
|
|
185
|
+
body: cleanBody(comment.body),
|
|
152
186
|
createdAt: comment.created_at,
|
|
153
187
|
isBot: isBot(comment.user?.login),
|
|
154
188
|
});
|
|
@@ -174,7 +208,7 @@ function processComments(data, options = {}) {
|
|
|
174
208
|
path: comment.path,
|
|
175
209
|
line: comment.line || comment.original_line,
|
|
176
210
|
diffHunk: comment.diff_hunk || null,
|
|
177
|
-
body: comment.body,
|
|
211
|
+
body: cleanBody(comment.body),
|
|
178
212
|
createdAt: comment.created_at,
|
|
179
213
|
updatedAt: comment.updated_at,
|
|
180
214
|
url: comment.html_url,
|
|
@@ -197,7 +231,7 @@ function processComments(data, options = {}) {
|
|
|
197
231
|
path: null,
|
|
198
232
|
line: null,
|
|
199
233
|
diffHunk: null,
|
|
200
|
-
body: comment.body,
|
|
234
|
+
body: cleanBody(comment.body),
|
|
201
235
|
createdAt: comment.created_at,
|
|
202
236
|
updatedAt: comment.updated_at,
|
|
203
237
|
url: comment.html_url,
|
|
@@ -221,7 +255,7 @@ function processComments(data, options = {}) {
|
|
|
221
255
|
path: null,
|
|
222
256
|
line: null,
|
|
223
257
|
diffHunk: null,
|
|
224
|
-
body: review.body,
|
|
258
|
+
body: cleanBody(review.body),
|
|
225
259
|
state: review.state,
|
|
226
260
|
createdAt: review.submitted_at,
|
|
227
261
|
updatedAt: review.submitted_at,
|
|
@@ -330,5 +364,6 @@ module.exports = {
|
|
|
330
364
|
replyToComment,
|
|
331
365
|
isBot,
|
|
332
366
|
isMetaComment,
|
|
367
|
+
cleanBody,
|
|
333
368
|
DEFAULT_META_FILTERS,
|
|
334
369
|
};
|
|
@@ -152,7 +152,9 @@ function formatOutput(comments, options) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
const header = `${colors.bright}Found ${comments.length} comment${comments.length === 1 ? "" : "s"}${colors.reset}\n`;
|
|
155
|
-
const
|
|
155
|
+
const formatter = options.expanded ? formatDetailedComment : formatComment;
|
|
156
|
+
const separator = options.expanded ? "\n\n" + "=".repeat(60) + "\n\n" : "\n\n";
|
|
157
|
+
const formatted = comments.map((c) => formatter(c)).join(separator);
|
|
156
158
|
|
|
157
159
|
return `${header}\n${formatted}`;
|
|
158
160
|
}
|