豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content
This repository was archived by the owner on Apr 16, 2026. It is now read-only.

Commit 9ef4479

Browse files
authored
refactor: types for JSON output of IssueFormatter (ChromeDevTools#1007)
- makes the id required in types - requires toString(), toStringDetailed() to use the JSON representation.
1 parent 5cedcaa commit 9ef4479

File tree

3 files changed

+208
-141
lines changed

3 files changed

+208
-141
lines changed

src/formatters/IssueFormatter.ts

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {DevTools} from '../third_party/index.js';
1111
export interface IssueFormatterOptions {
1212
requestIdResolver?: (requestId: string) => number | undefined;
1313
elementIdResolver?: (backendNodeId: number) => string | undefined;
14-
id?: number;
14+
id: number;
1515
}
1616

1717
export interface AffectedResource {
@@ -20,6 +20,22 @@ export interface AffectedResource {
2020
request?: string | number;
2121
}
2222

23+
interface IssueConcise {
24+
type: 'issue';
25+
title?: string;
26+
count: number;
27+
id: number;
28+
}
29+
30+
interface IssueDetailed extends IssueConcise {
31+
description?: string;
32+
links?: Array<{
33+
link: string;
34+
linkTitle: string;
35+
}>;
36+
affectedResources: AffectedResource[];
37+
}
38+
2339
export class IssueFormatter {
2440
#issue: DevTools.AggregatedIssue;
2541
#options: IssueFormatterOptions;
@@ -30,70 +46,14 @@ export class IssueFormatter {
3046
}
3147

3248
toString(): string {
33-
const title = this.#getTitle();
34-
const count = this.#issue.getAggregatedIssuesCount();
35-
const idPart =
36-
this.#options.id !== undefined ? `msgid=${this.#options.id} ` : '';
37-
return `${idPart}[issue] ${title} (count: ${count})`;
49+
return convertIssueConciseToString(this.toJSON());
3850
}
3951

4052
toStringDetailed(): string {
41-
const result: string[] = [];
42-
if (this.#options.id !== undefined) {
43-
result.push(`ID: ${this.#options.id}`);
44-
}
45-
46-
const bodyParts: string[] = [];
47-
48-
const description = this.#getDescription();
49-
let processedMarkdown = description?.trim();
50-
// Remove heading in order not to conflict with the whole console message response markdown
51-
if (processedMarkdown?.startsWith('# ')) {
52-
processedMarkdown = processedMarkdown.substring(2).trimStart();
53-
}
54-
if (processedMarkdown) {
55-
bodyParts.push(processedMarkdown);
56-
} else {
57-
bodyParts.push(this.#getTitle() ?? 'Unknown Issue');
58-
}
59-
60-
const links = this.#issue.getDescription()?.links;
61-
if (links && links.length > 0) {
62-
bodyParts.push('Learn more:');
63-
for (const link of links) {
64-
bodyParts.push(`[${link.linkTitle}](${link.link})`);
65-
}
66-
}
67-
68-
const affectedResources = this.#getAffectedResources();
69-
if (affectedResources.length) {
70-
bodyParts.push('### Affected resources');
71-
bodyParts.push(
72-
...affectedResources.map(item => {
73-
const details = [];
74-
if (item.uid) {
75-
details.push(`uid=${item.uid}`);
76-
}
77-
if (item.request) {
78-
details.push(
79-
(typeof item.request === 'number' ? `reqid=` : 'url=') +
80-
item.request,
81-
);
82-
}
83-
if (item.data) {
84-
details.push(`data=${JSON.stringify(item.data)}`);
85-
}
86-
return details.join(' ');
87-
}),
88-
);
89-
}
90-
91-
result.push(`Message: issue> ${bodyParts.join('\n')}`);
92-
93-
return result.join('\n');
53+
return convertIssueDetailedToString(this.toJSONDetailed());
9454
}
9555

96-
toJSON(): object {
56+
toJSON(): IssueConcise {
9757
return {
9858
type: 'issue',
9959
title: this.#getTitle(),
@@ -102,10 +62,11 @@ export class IssueFormatter {
10262
};
10363
}
10464

105-
toJSONDetailed(): object {
65+
toJSONDetailed(): IssueDetailed {
10666
return {
10767
id: this.#options.id,
10868
type: 'issue',
69+
count: this.#issue.getAggregatedIssuesCount(),
10970
title: this.#getTitle(),
11071
description: this.#getDescription(),
11172
links: this.#issue.getDescription()?.links,
@@ -251,3 +212,61 @@ export class IssueFormatter {
251212
}
252213
}
253214
}
215+
216+
function convertIssueConciseToString(issue: IssueConcise): string {
217+
return `msgid=${issue.id} [issue] ${issue.title} (count: ${issue.count})`;
218+
}
219+
220+
function convertIssueDetailedToString(issue: IssueDetailed): string {
221+
const result: string[] = [];
222+
result.push(`ID: ${issue.id}`);
223+
224+
const bodyParts: string[] = [];
225+
226+
const description = issue.description;
227+
let processedMarkdown = description?.trim();
228+
// Remove heading in order not to conflict with the whole console message response markdown
229+
if (processedMarkdown?.startsWith('# ')) {
230+
processedMarkdown = processedMarkdown.substring(2).trimStart();
231+
}
232+
if (processedMarkdown) {
233+
bodyParts.push(processedMarkdown);
234+
} else {
235+
bodyParts.push(issue.title ?? 'Unknown Issue');
236+
}
237+
238+
const links = issue.links;
239+
if (links && links.length > 0) {
240+
bodyParts.push('Learn more:');
241+
for (const link of links) {
242+
bodyParts.push(`[${link.linkTitle}](${link.link})`);
243+
}
244+
}
245+
246+
const affectedResources = issue.affectedResources;
247+
if (affectedResources.length) {
248+
bodyParts.push('### Affected resources');
249+
bodyParts.push(
250+
...affectedResources.map(item => {
251+
const details = [];
252+
if (item.uid) {
253+
details.push(`uid=${item.uid}`);
254+
}
255+
if (item.request) {
256+
details.push(
257+
(typeof item.request === 'number' ? `reqid=` : 'url=') +
258+
item.request,
259+
);
260+
}
261+
if (item.data) {
262+
details.push(`data=${JSON.stringify(item.data)}`);
263+
}
264+
return details.join(' ');
265+
}),
266+
);
267+
}
268+
269+
result.push(`Message: issue> ${bodyParts.join('\n')}`);
270+
271+
return result.join('\n');
272+
}
Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,58 @@
1-
exports[`IssueFormatter > formats an issue message 1`] = `
1+
exports[`IssueFormatter > formats a detailed issue toJSONDetailed 1`] = `
2+
{
3+
"id": 5,
4+
"type": "issue",
5+
"title": "Mock Issue Title",
6+
"description": "# Mock Issue Title\\n\\nThis is a mock issue description sub value",
7+
"links": [
8+
{
9+
"link": "http://example.com",
10+
"linkTitle": "Link 1"
11+
}
12+
],
13+
"affectedResources": [
14+
{
15+
"uid": "1_1",
16+
"data": {
17+
"violatingNodeAttribute": "test"
18+
}
19+
}
20+
]
21+
}
22+
`;
23+
24+
exports[`IssueFormatter > formats a detailed issue toStringDetailed 1`] = `
225
ID: 5
326
Message: issue> Mock Issue Title
427

5-
This is a mock issue description
28+
This is a mock issue description sub value
629
Learn more:
7-
[Learn more](http://example.com/learnmore)
8-
[Learn more 2](http://example.com/another-learnmore)
30+
[Link 1](http://example.com)
31+
### Affected resources
32+
uid=1_1 data={"violatingNodeAttribute":"test"}
33+
`;
34+
35+
exports[`IssueFormatter > formats a simplified issue toJSON 1`] = `
36+
{
37+
"type": "issue",
38+
"title": "Issue Title",
39+
"count": 5,
40+
"id": 1
41+
}
42+
`;
43+
44+
exports[`IssueFormatter > formats a simplified issue toString 1`] = `
45+
msgid=1 [issue] Issue Title (count: 5)
46+
`;
47+
48+
exports[`IssueFormatter > formats an issue message toJSON 1`] = `
49+
{
50+
"type": "issue",
51+
"title": "Mock Issue Title",
52+
"id": 5
53+
}
54+
`;
55+
56+
exports[`IssueFormatter > formats an issue message toString 1`] = `
57+
msgid=5 [issue] Mock Issue Title (count: undefined)
958
`;

0 commit comments

Comments
 (0)