chrome-devtools-frontend 1.0.1702515 → 1.0.1704172
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/AUTHORS +1 -0
- package/front_end/core/common/ParsedURL.ts +59 -1
- package/front_end/core/platform/StringUtilities.ts +65 -0
- package/front_end/core/sdk/CPUThrottlingManager.ts +3 -3
- package/front_end/core/sdk/SourceMap.ts +3 -3
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +4 -3
- package/front_end/core/sdk/SourceMapScopesInfo.ts +17 -5
- package/front_end/core/text_utils/Markdown.ts +73 -0
- package/front_end/core/text_utils/text_utils.ts +2 -0
- package/front_end/entrypoints/main/MainImpl.ts +3 -3
- package/front_end/generated/InspectorBackendCommands.ts +3 -1
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +6 -0
- package/front_end/generated/protocol.ts +22 -0
- package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
- package/front_end/models/comment_manager/CD4ABridge.ts +5 -0
- package/front_end/models/har/HARFormat.ts +7 -2
- package/front_end/models/issues_manager/MarkdownIssueDescription.ts +4 -47
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +1 -1
- package/front_end/models/source_map_scopes/NamesResolver.ts +13 -5
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingListView.ts +33 -1
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +4 -12
- package/front_end/panels/application/ApplicationPanelSidebar.ts +58 -60
- package/front_end/panels/application/BackForwardCacheTreeElement.ts +1 -1
- package/front_end/panels/application/FrameDetailsView.ts +64 -82
- package/front_end/panels/application/OpenedWindowDetailsView.ts +20 -21
- package/front_end/panels/application/PreloadingTreeElement.ts +3 -3
- package/front_end/panels/common/CommentsOverlayWidget.ts +145 -72
- package/front_end/panels/common/CommentsStatusBarPill.ts +40 -7
- package/front_end/panels/common/commentsOverlay.css +34 -23
- package/front_end/panels/common/commentsStatusBarPill.css +13 -0
- package/front_end/panels/elements/DOMTreeWidget.ts +29 -10
- package/front_end/panels/issues/IssueView.ts +5 -1
- package/front_end/panels/network/RequestPayloadView.ts +7 -2
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +12 -9
- package/front_end/panels/sources/DebuggerPlugin.ts +49 -16
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/SourcesView.ts +119 -148
- package/front_end/panels/sources/TabbedEditorContainer.ts +263 -207
- package/front_end/panels/sources/components/HeadersView.ts +193 -123
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +24 -32
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js +15 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +0 -8
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +0 -24
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts +12 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +79 -17
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/ElementHandle.ts +15 -2
- package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +10 -1
- package/front_end/third_party/puppeteer/package/src/common/Debug.ts +0 -27
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +96 -17
- package/front_end/third_party/puppeteer/package/src/node-env-setup.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +60 -22
- package/front_end/ui/comments/CommentOverlayManager.ts +78 -25
- package/front_end/ui/components/markdown_view/MarkdownPlaceholderLitRenderer.ts +7 -65
- package/front_end/ui/legacy/TabbedPane.ts +51 -40
- package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +7 -13
- package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +51 -57
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +342 -373
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +101 -42
- package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +8 -0
- package/package.json +2 -1
|
@@ -55,59 +55,67 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLEl
|
|
|
55
55
|
<div
|
|
56
56
|
class="comment-hover-highlight"
|
|
57
57
|
style=${styleMap({
|
|
58
|
-
|
|
59
|
-
left: `${input.hoverHighlight.left}px`,
|
|
58
|
+
transform: `translate3d(${input.hoverHighlight.left}px, ${input.hoverHighlight.top}px, 0)`,
|
|
60
59
|
width: `${input.hoverHighlight.width}px`,
|
|
61
60
|
height: `${input.hoverHighlight.height}px`,
|
|
62
61
|
})}>
|
|
63
62
|
</div>
|
|
64
63
|
` : nothing}
|
|
65
|
-
${
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
top: `${h.top}px`,
|
|
70
|
-
left: `${h.left}px`,
|
|
71
|
-
width: `${h.width}px`,
|
|
72
|
-
height: `${h.height}px`,
|
|
73
|
-
})}>
|
|
74
|
-
</div>
|
|
75
|
-
` : nothing)}
|
|
76
|
-
${input.pins.map(p => p.visible ? html`
|
|
77
|
-
<div
|
|
78
|
-
class="comment-pin"
|
|
79
|
-
style=${styleMap({
|
|
80
|
-
top: `${p.top}px`,
|
|
81
|
-
left: `${p.left}px`,
|
|
82
|
-
})}
|
|
83
|
-
@click=${() => input.onPinClick(p.id)}>
|
|
84
|
-
<div class="comment-cursor">${p.index}</div>
|
|
85
|
-
</div>
|
|
86
|
-
` : nothing)}
|
|
87
|
-
${input.activePin && input.activeThread ? repeat(
|
|
88
|
-
[{pin: input.activePin, thread: input.activeThread}],
|
|
89
|
-
item => item.thread.id,
|
|
90
|
-
item => html`
|
|
64
|
+
${repeat(
|
|
65
|
+
input.highlights.filter(h => h.visible),
|
|
66
|
+
h => h.id,
|
|
67
|
+
h => html`
|
|
91
68
|
<div
|
|
92
|
-
class="comment-
|
|
69
|
+
class="comment-anchor-highlight"
|
|
93
70
|
style=${styleMap({
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)}px`,
|
|
98
|
-
left: `${Math.min(
|
|
99
|
-
Math.max(POPUP_MARGIN, item.pin.left),
|
|
100
|
-
Math.max(POPUP_MARGIN, target.clientWidth - POPUP_WIDTH - POPUP_MARGIN),
|
|
101
|
-
)}px`,
|
|
71
|
+
transform: `translate3d(${h.left}px, ${h.top}px, 0)`,
|
|
72
|
+
width: `${h.width}px`,
|
|
73
|
+
height: `${h.height}px`,
|
|
102
74
|
})}>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
75
|
+
</div>
|
|
76
|
+
`,
|
|
77
|
+
)}
|
|
78
|
+
${repeat(
|
|
79
|
+
input.pins.filter(p => p.visible),
|
|
80
|
+
p => p.id,
|
|
81
|
+
p => html`
|
|
82
|
+
<div
|
|
83
|
+
class="comment-pin"
|
|
84
|
+
style=${styleMap({
|
|
85
|
+
transform: `translate3d(${p.left}px, ${p.top}px, 0)`,
|
|
108
86
|
})}
|
|
87
|
+
@click=${() => input.onPinClick(p.id)}>
|
|
88
|
+
<div class="comment-cursor">${p.index}</div>
|
|
109
89
|
</div>
|
|
110
90
|
`,
|
|
91
|
+
)}
|
|
92
|
+
${input.activePin && input.activeThread ? repeat(
|
|
93
|
+
[{pin: input.activePin, thread: input.activeThread}],
|
|
94
|
+
item => item.thread.id,
|
|
95
|
+
item => {
|
|
96
|
+
const popupTop = Math.min(
|
|
97
|
+
Math.max(POPUP_MARGIN, item.pin.top + PIN_HEIGHT),
|
|
98
|
+
Math.max(POPUP_MARGIN, target.clientHeight - POPUP_HEIGHT),
|
|
99
|
+
);
|
|
100
|
+
const popupLeft = Math.min(
|
|
101
|
+
Math.max(POPUP_MARGIN, item.pin.left),
|
|
102
|
+
Math.max(POPUP_MARGIN, target.clientWidth - POPUP_WIDTH - POPUP_MARGIN),
|
|
103
|
+
);
|
|
104
|
+
return html`
|
|
105
|
+
<div
|
|
106
|
+
class="comment-popup-widget"
|
|
107
|
+
style=${styleMap({
|
|
108
|
+
transform: `translate3d(${popupLeft}px, ${popupTop}px, 0)`,
|
|
109
|
+
})}>
|
|
110
|
+
${UI.Widget.widget(CommentThreadWidget, {
|
|
111
|
+
title: input.title,
|
|
112
|
+
comments: [...item.thread.comments],
|
|
113
|
+
onAddComment: input.onAddComment,
|
|
114
|
+
onClose: input.onCloseCommentThread,
|
|
115
|
+
})}
|
|
116
|
+
</div>
|
|
117
|
+
`;
|
|
118
|
+
},
|
|
111
119
|
) : nothing}
|
|
112
120
|
</div>
|
|
113
121
|
`, target);
|
|
@@ -160,12 +168,12 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
|
|
|
160
168
|
this.#commentOverlayManager.start();
|
|
161
169
|
this.#commentOverlayManager.addEventListener(
|
|
162
170
|
Comments.CommentOverlayManager.Events.POSITIONS_UPDATED,
|
|
163
|
-
this.#
|
|
171
|
+
this.#onPositionsUpdated,
|
|
164
172
|
this,
|
|
165
173
|
);
|
|
166
174
|
this.#commentOverlayManager.addEventListener(
|
|
167
175
|
Comments.CommentOverlayManager.Events.HOVER_HIGHLIGHT_CHANGED,
|
|
168
|
-
this.#
|
|
176
|
+
this.#onHoverHighlightChanged,
|
|
169
177
|
this,
|
|
170
178
|
);
|
|
171
179
|
|
|
@@ -197,12 +205,12 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
|
|
|
197
205
|
this.#commentOverlayManager.stop();
|
|
198
206
|
this.#commentOverlayManager.removeEventListener(
|
|
199
207
|
Comments.CommentOverlayManager.Events.POSITIONS_UPDATED,
|
|
200
|
-
this.#
|
|
208
|
+
this.#onPositionsUpdated,
|
|
201
209
|
this,
|
|
202
210
|
);
|
|
203
211
|
this.#commentOverlayManager.removeEventListener(
|
|
204
212
|
Comments.CommentOverlayManager.Events.HOVER_HIGHLIGHT_CHANGED,
|
|
205
|
-
this.#
|
|
213
|
+
this.#onHoverHighlightChanged,
|
|
206
214
|
this,
|
|
207
215
|
);
|
|
208
216
|
|
|
@@ -257,16 +265,60 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
|
|
|
257
265
|
this.requestUpdate();
|
|
258
266
|
}
|
|
259
267
|
|
|
260
|
-
#
|
|
268
|
+
#syncActiveThreadFromManager(): void {
|
|
261
269
|
const draftThread = this.#commentManager.getCommentThreads().find(t => t.status === 'DRAFT');
|
|
262
270
|
if (draftThread) {
|
|
263
271
|
this.#setActiveThreadId(draftThread.id);
|
|
264
272
|
} else if (this.#activeThreadId && !this.#commentManager.getCommentThread(this.#activeThreadId)) {
|
|
265
273
|
this.#setActiveThreadId(null);
|
|
266
274
|
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
#onPositionsUpdated(
|
|
278
|
+
event: Common.EventTarget.EventTargetEvent<
|
|
279
|
+
Comments.CommentOverlayManager.EventTypes[Comments.CommentOverlayManager.Events.POSITIONS_UPDATED]>,
|
|
280
|
+
): void {
|
|
281
|
+
this.#syncActiveThreadFromManager();
|
|
282
|
+
if (event.data.isRealtimeSync && this.isShowing() && this.#trySynchronousRender()) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
this.requestUpdate();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
#onHoverHighlightChanged(): void {
|
|
289
|
+
this.#syncActiveThreadFromManager();
|
|
290
|
+
if (this.isShowing() && this.#trySynchronousRender()) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
this.requestUpdate();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
#onStateChanged(): void {
|
|
297
|
+
this.#syncActiveThreadFromManager();
|
|
267
298
|
this.requestUpdate();
|
|
268
299
|
}
|
|
269
300
|
|
|
301
|
+
#trySynchronousRender(): boolean {
|
|
302
|
+
if (!this.#commentManager.isAgentAttached()) {
|
|
303
|
+
this.#renderDisconnectedView();
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
const activeThread =
|
|
307
|
+
this.#activeThreadId ? this.#commentManager.getCommentThread(this.#activeThreadId) ?? null : null;
|
|
308
|
+
const anchor = activeThread?.anchor ?? null;
|
|
309
|
+
if (anchor === null) {
|
|
310
|
+
this.#cachedTitleAnchor = null;
|
|
311
|
+
this.#cachedTitle = {text: ''};
|
|
312
|
+
this.#renderWithTitle(activeThread, this.#cachedTitle);
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
if (anchor === this.#cachedTitleAnchor) {
|
|
316
|
+
this.#renderWithTitle(activeThread, this.#cachedTitle);
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
|
|
270
322
|
async #getOrComputeTitle(anchor: CommentManager.CommentManager.CommentAnchorSignature|null): Promise<Title> {
|
|
271
323
|
if (anchor === this.#cachedTitleAnchor) {
|
|
272
324
|
return this.#cachedTitle;
|
|
@@ -333,32 +385,29 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
|
|
|
333
385
|
}
|
|
334
386
|
};
|
|
335
387
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const activeThread =
|
|
358
|
-
this.#activeThreadId ? this.#commentManager.getCommentThread(this.#activeThreadId) ?? null : null;
|
|
359
|
-
const title = await this.#getOrComputeTitle(activeThread?.anchor ?? null);
|
|
360
|
-
signal?.throwIfAborted();
|
|
388
|
+
#renderDisconnectedView(): void {
|
|
389
|
+
this.#view(
|
|
390
|
+
{
|
|
391
|
+
pins: [],
|
|
392
|
+
highlights: [],
|
|
393
|
+
hoverHighlight: null,
|
|
394
|
+
commentMode: false,
|
|
395
|
+
onPinClick: this.#handlePinClick,
|
|
396
|
+
activeThread: null,
|
|
397
|
+
activePin: null,
|
|
398
|
+
title: {text: ''},
|
|
399
|
+
onAddComment: () => {},
|
|
400
|
+
onCloseCommentThread: this.#handleCloseCommentThread,
|
|
401
|
+
},
|
|
402
|
+
undefined,
|
|
403
|
+
this.contentElement,
|
|
404
|
+
);
|
|
405
|
+
}
|
|
361
406
|
|
|
407
|
+
#renderWithTitle(
|
|
408
|
+
activeThread: CommentManager.CommentManager.CommentThread|null,
|
|
409
|
+
title: Title,
|
|
410
|
+
): void {
|
|
362
411
|
const pins = this.#commentOverlayManager.getPinPositions();
|
|
363
412
|
const highlights = this.#commentOverlayManager.getHighlightRects();
|
|
364
413
|
const activePin = this.#activeThreadId ? pins.find(p => p.id === this.#activeThreadId) ?? null : null;
|
|
@@ -391,6 +440,30 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
|
|
|
391
440
|
};
|
|
392
441
|
this.#view(viewInput, undefined, this.contentElement);
|
|
393
442
|
}
|
|
443
|
+
|
|
444
|
+
override async performUpdate(signal?: AbortSignal): Promise<void> {
|
|
445
|
+
if (!this.#commentManager.isAgentAttached()) {
|
|
446
|
+
this.#renderDisconnectedView();
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const activeThread =
|
|
451
|
+
this.#activeThreadId ? this.#commentManager.getCommentThread(this.#activeThreadId) ?? null : null;
|
|
452
|
+
const anchor = activeThread?.anchor ?? null;
|
|
453
|
+
let title: Title;
|
|
454
|
+
if (anchor === null) {
|
|
455
|
+
this.#cachedTitleAnchor = null;
|
|
456
|
+
this.#cachedTitle = {text: ''};
|
|
457
|
+
title = this.#cachedTitle;
|
|
458
|
+
} else if (anchor === this.#cachedTitleAnchor) {
|
|
459
|
+
title = this.#cachedTitle;
|
|
460
|
+
} else {
|
|
461
|
+
title = await this.#getOrComputeTitle(anchor);
|
|
462
|
+
signal?.throwIfAborted();
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
this.#renderWithTitle(activeThread, title);
|
|
466
|
+
}
|
|
394
467
|
}
|
|
395
468
|
|
|
396
469
|
let widgetInstance: CommentsOverlayWidget|null = null;
|
|
@@ -4,16 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
6
6
|
import * as CommentManager from '../../models/comment_manager/comment_manager.js';
|
|
7
|
+
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
7
8
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
8
9
|
import * as Lit from '../../ui/lit/lit.js';
|
|
9
10
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
10
11
|
|
|
12
|
+
import commentsStatusBarPillStyles from './commentsStatusBarPill.css.js';
|
|
13
|
+
|
|
11
14
|
const UIStrings = {
|
|
12
15
|
/**
|
|
13
16
|
* @description Button text for the comments status bar pill showing the number of open comments.
|
|
14
17
|
* @example {2} PH1
|
|
15
18
|
*/
|
|
16
19
|
commentsCount: 'Comments ({PH1})',
|
|
20
|
+
/**
|
|
21
|
+
* @description Button text for sending all draft comments to the agent in the comments status bar pill.
|
|
22
|
+
* @example {2} PH1
|
|
23
|
+
*/
|
|
24
|
+
sendToAgentCount: 'Send to agent ({PH1})',
|
|
17
25
|
} as const;
|
|
18
26
|
const str_ = i18n.i18n.registerUIStrings('panels/common/CommentsStatusBarPill.ts', UIStrings);
|
|
19
27
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -23,22 +31,38 @@ const {html, render} = Lit;
|
|
|
23
31
|
export interface ViewInput {
|
|
24
32
|
threads: CommentManager.CommentManager.CommentThread[];
|
|
25
33
|
onPillClick: () => void;
|
|
34
|
+
onSendToAgentClick?: () => void;
|
|
26
35
|
disabled?: boolean;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
export type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
|
|
30
39
|
|
|
31
40
|
export const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLElement): void => {
|
|
41
|
+
const unsentCount = input.threads.filter(thread => thread.status === 'ACTIVE').length;
|
|
42
|
+
const tooltip = input.threads.flatMap(thread => thread.comments.map(comment => comment.text)).join('\n');
|
|
32
43
|
// clang-format off
|
|
33
44
|
render(html`
|
|
45
|
+
<style>${commentsStatusBarPillStyles}</style>
|
|
34
46
|
${input.threads.length <= 0 ? Lit.nothing : html`
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
<div class="pill-container">
|
|
48
|
+
<button
|
|
49
|
+
class="devtools-pill"
|
|
50
|
+
title=${tooltip}
|
|
51
|
+
?disabled=${input.disabled}
|
|
52
|
+
@click=${input.onPillClick}
|
|
53
|
+
jslog=${VisualLogging.action('comments-status-bar-pill').track({click: true})}>
|
|
54
|
+
${i18nString(UIStrings.commentsCount, {PH1: input.threads.length})}
|
|
55
|
+
</button>
|
|
56
|
+
${unsentCount > 0 ? html`
|
|
57
|
+
<devtools-button
|
|
58
|
+
.variant=${Buttons.Button.Variant.PRIMARY}
|
|
59
|
+
.disabled=${Boolean(input.disabled)}
|
|
60
|
+
.jslogContext=${'comments-send-to-agent'}
|
|
61
|
+
@click=${input.onSendToAgentClick}>
|
|
62
|
+
${i18nString(UIStrings.sendToAgentCount, {PH1: unsentCount})}
|
|
63
|
+
</devtools-button>
|
|
64
|
+
` : Lit.nothing}
|
|
65
|
+
</div>
|
|
42
66
|
`}
|
|
43
67
|
`, target);
|
|
44
68
|
// clang-format on
|
|
@@ -100,9 +124,18 @@ export class CommentsStatusBarPill extends UI.Widget.Widget {
|
|
|
100
124
|
this.#commentManager.getCommentThreads().filter(thread => thread.status !== 'DRAFT') :
|
|
101
125
|
[],
|
|
102
126
|
onPillClick: this.#handlePillClick,
|
|
127
|
+
onSendToAgentClick: this.#handleSendToAgentClick,
|
|
103
128
|
};
|
|
104
129
|
this.#view(viewInput, undefined, this.contentElement);
|
|
105
130
|
}
|
|
106
131
|
|
|
107
132
|
#handlePillClick = (): void => {};
|
|
133
|
+
|
|
134
|
+
#handleSendToAgentClick = (): void => {
|
|
135
|
+
for (const thread of this.#commentManager.getCommentThreads()) {
|
|
136
|
+
if (thread.status === 'ACTIVE') {
|
|
137
|
+
thread.sendToAgent();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
108
141
|
}
|
|
@@ -20,57 +20,68 @@
|
|
|
20
20
|
|
|
21
21
|
.comment-pin {
|
|
22
22
|
position: absolute;
|
|
23
|
+
top: 0;
|
|
24
|
+
left: 0;
|
|
23
25
|
pointer-events: auto;
|
|
24
26
|
cursor: pointer;
|
|
25
27
|
user-select: none;
|
|
26
|
-
|
|
27
|
-
transform-origin: center center;
|
|
28
|
-
will-change: transform;
|
|
28
|
+
will-change: transform;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
.comment-pin:hover {
|
|
31
|
+
.comment-pin:hover .comment-cursor {
|
|
32
32
|
transform: scale(1.15);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
35
|
+
.comment-cursor {
|
|
36
|
+
display: flex;
|
|
37
|
+
width: var(--sys-size-9);
|
|
38
|
+
height: var(--sys-size-9);
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
padding: 0;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
align-items: center;
|
|
44
|
+
flex-shrink: 0;
|
|
45
|
+
box-shadow: var(--sys-elevation-level2);
|
|
46
|
+
border-radius: 100px 100px 100px var(--sys-shape-corner-extra-small, 4px);
|
|
47
|
+
background: var(--sys-color-primary);
|
|
48
|
+
color: var(--sys-color-on-primary);
|
|
49
|
+
font-family: var(--default-font-family);
|
|
50
|
+
font-size: var(--sys-typescale-body5-size);
|
|
51
|
+
font-weight: var(--ref-typeface-weight-bold, 600);
|
|
52
|
+
line-height: 1;
|
|
53
|
+
transition: transform 0.1s ease;
|
|
54
|
+
transform-origin: center center;
|
|
55
|
+
}
|
|
54
56
|
|
|
55
57
|
.comment-anchor-highlight {
|
|
56
58
|
position: absolute;
|
|
59
|
+
top: 0;
|
|
60
|
+
left: 0;
|
|
57
61
|
pointer-events: none;
|
|
58
62
|
border: var(--sys-size-2) dashed var(--sys-color-primary);
|
|
59
63
|
background-color: color-mix(in srgb, var(--sys-color-primary), transparent 90%);
|
|
60
64
|
box-sizing: border-box;
|
|
65
|
+
will-change: transform;
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
.comment-hover-highlight {
|
|
64
69
|
position: absolute;
|
|
70
|
+
top: 0;
|
|
71
|
+
left: 0;
|
|
65
72
|
pointer-events: none;
|
|
66
73
|
border: var(--sys-size-2) solid var(--sys-color-primary);
|
|
67
74
|
background-color: color-mix(in srgb, var(--sys-color-primary), transparent 85%);
|
|
68
75
|
box-sizing: border-box;
|
|
76
|
+
will-change: transform;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
.comment-popup-widget {
|
|
72
80
|
position: absolute;
|
|
81
|
+
top: 0;
|
|
82
|
+
left: 0;
|
|
73
83
|
z-index: 2501;
|
|
74
84
|
pointer-events: auto;
|
|
85
|
+
will-change: transform;
|
|
75
86
|
}
|
|
76
87
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 The Chromium Authors
|
|
3
|
+
* Use of this source code is governed by a BSD-style license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
@scope to (devtools-widget > *) {
|
|
8
|
+
.pill-container {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: var(--sys-size-3);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -426,6 +426,11 @@ function nodeHasVisibleChildren(node: SDK.DOMModel.DOMNode, rootDOMNode: SDK.DOM
|
|
|
426
426
|
return Boolean(node.childNodeCount()) && !ElementsTreeWidget.canShowInlineText(node);
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
+
function nodeNeedsClosingTag(node: SDK.DOMModel.DOMNode, hasChildren: boolean): boolean {
|
|
430
|
+
return hasChildren && node.nodeType() === Node.ELEMENT_NODE &&
|
|
431
|
+
!ForbiddenClosingTagElements.has(node.nodeName().toLowerCase()) && !node.pseudoType();
|
|
432
|
+
}
|
|
433
|
+
|
|
429
434
|
function getVisibleChildren(node: SDK.DOMModel.DOMNode, showComments = true): SDK.DOMModel.DOMNode[] {
|
|
430
435
|
const children: SDK.DOMModel.DOMNode[] = [];
|
|
431
436
|
children.push(...ElementsTreeWidget.visibleShadowRoots(node));
|
|
@@ -778,10 +783,7 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
778
783
|
if (node instanceof SDK.DOMModel.DOMDocument) {
|
|
779
784
|
rows += countTopLayerRows(node);
|
|
780
785
|
}
|
|
781
|
-
|
|
782
|
-
const needsClosingTag = node.nodeType() === Node.ELEMENT_NODE && !ForbiddenClosingTagElements.has(tagName) &&
|
|
783
|
-
!node.pseudoType() && (hasChildren || !ElementsTreeWidget.canShowInlineText(node));
|
|
784
|
-
if (needsClosingTag) {
|
|
786
|
+
if (nodeNeedsClosingTag(node, hasChildren)) {
|
|
785
787
|
rows += 1;
|
|
786
788
|
}
|
|
787
789
|
}
|
|
@@ -827,9 +829,7 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
827
829
|
const limit = input.expandedChildrenLimit ? input.expandedChildrenLimit(node) : InitialChildrenLimit;
|
|
828
830
|
const children = allVisibleChildren.slice(0, limit);
|
|
829
831
|
const remainingChildrenCount = allVisibleChildren.length - children.length;
|
|
830
|
-
const
|
|
831
|
-
const needsClosingTag = node.nodeType() === Node.ELEMENT_NODE && !ForbiddenClosingTagElements.has(tagName) &&
|
|
832
|
-
!node.pseudoType() && (hasChildren || !ElementsTreeWidget.canShowInlineText(node));
|
|
832
|
+
const needsClosingTag = nodeNeedsClosingTag(node, hasChildren);
|
|
833
833
|
|
|
834
834
|
const on = Lit.Directive.directive(Lit.CustomDirectives.InterceptBindingDirective);
|
|
835
835
|
|
|
@@ -1461,6 +1461,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1461
1461
|
const domModel = event.data;
|
|
1462
1462
|
if (this.#view === DECLARATIVE_VIEW) {
|
|
1463
1463
|
this.#selectedDOMNode = null;
|
|
1464
|
+
this.#selectedClosingTag = false;
|
|
1464
1465
|
this.#expandedNodes.clear();
|
|
1465
1466
|
this.#currentHighlightedNode = null;
|
|
1466
1467
|
this.#updateRecords.clear();
|
|
@@ -1679,9 +1680,6 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1679
1680
|
!getVisibleChildren(node.parentNode, this.#showComments).includes(node))) {
|
|
1680
1681
|
node = node.parentNode;
|
|
1681
1682
|
}
|
|
1682
|
-
const isSameNode = this.#selectedDOMNode === node && this.#selectedClosingTag === Boolean(isClosingTag);
|
|
1683
|
-
this.#selectedDOMNode = node;
|
|
1684
|
-
this.#selectedClosingTag = Boolean(isClosingTag);
|
|
1685
1683
|
if (node) {
|
|
1686
1684
|
const ancestors: SDK.DOMModel.DOMNode[] = [];
|
|
1687
1685
|
for (let current: (SDK.DOMModel.DOMNode|null) = node.parentNode; current; current = current.parentNode) {
|
|
@@ -1707,7 +1705,14 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1707
1705
|
});
|
|
1708
1706
|
}
|
|
1709
1707
|
}
|
|
1708
|
+
if (isClosingTag && nodeHasVisibleChildren(node, this.rootDOMNode, this.maxTreeDepth, this.omitRootDOMNode)) {
|
|
1709
|
+
this.#expandedNodes.add(node);
|
|
1710
|
+
}
|
|
1710
1711
|
}
|
|
1712
|
+
const selectClosingTag = Boolean(isClosingTag) && Boolean(node && this.#hasClosingTag(node));
|
|
1713
|
+
const isSameNode = this.#selectedDOMNode === node && this.#selectedClosingTag === selectClosingTag;
|
|
1714
|
+
this.#selectedDOMNode = node;
|
|
1715
|
+
this.#selectedClosingTag = selectClosingTag;
|
|
1711
1716
|
this.#clearHighlightedNode();
|
|
1712
1717
|
if (!isSameNode) {
|
|
1713
1718
|
this.onSelectedNodeChanged(
|
|
@@ -2014,8 +2019,19 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
2014
2019
|
return current === this.#rootDOMNode ? selectedNode : (fallback ?? this.#rootDOMNode);
|
|
2015
2020
|
}
|
|
2016
2021
|
|
|
2022
|
+
#hasClosingTag(node: SDK.DOMModel.DOMNode): boolean {
|
|
2023
|
+
const isEditingAsHTML = this.#multilineEditingNode === node ||
|
|
2024
|
+
(this.#nodeToEdit?.node === node && Boolean(this.#nodeToEdit.isEditAsHTML));
|
|
2025
|
+
if (isEditingAsHTML || !this.isNodeExpanded(node)) {
|
|
2026
|
+
return false;
|
|
2027
|
+
}
|
|
2028
|
+
const hasChildren = nodeHasVisibleChildren(node, this.#rootDOMNode, this.#maxTreeDepth, this.omitRootDOMNode);
|
|
2029
|
+
return nodeNeedsClosingTag(node, hasChildren);
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2017
2032
|
#validateSelectedNode(): void {
|
|
2018
2033
|
if (!this.#selectedDOMNode) {
|
|
2034
|
+
this.#selectedClosingTag = false;
|
|
2019
2035
|
return;
|
|
2020
2036
|
}
|
|
2021
2037
|
const validNode = this.#findValidSelectedNode(this.#selectedDOMNode);
|
|
@@ -2026,6 +2042,8 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
2026
2042
|
this.onSelectedNodeChanged(
|
|
2027
2043
|
{data: {node: validNode, focus: false}} as
|
|
2028
2044
|
Common.EventTarget.EventTargetEvent<{node: SDK.DOMModel.DOMNode | null, focus: boolean}>);
|
|
2045
|
+
} else if (this.#selectedClosingTag && !this.#hasClosingTag(this.#selectedDOMNode)) {
|
|
2046
|
+
this.#selectedClosingTag = false;
|
|
2029
2047
|
}
|
|
2030
2048
|
}
|
|
2031
2049
|
|
|
@@ -2276,6 +2294,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
2276
2294
|
if (this.#rootDOMNode?.domModel() === domModel) {
|
|
2277
2295
|
this.#rootDOMNode = null;
|
|
2278
2296
|
this.#selectedDOMNode = null;
|
|
2297
|
+
this.#selectedClosingTag = false;
|
|
2279
2298
|
this.#expandedNodes.clear();
|
|
2280
2299
|
this.#updateRecords.clear();
|
|
2281
2300
|
}
|
|
@@ -435,7 +435,11 @@ export class IssueView extends UI.TreeOutline.TreeElement {
|
|
|
435
435
|
messageElement.setCollapsible(false);
|
|
436
436
|
messageElement.selectable = false;
|
|
437
437
|
const markdownComponent = new MarkdownView.MarkdownView.MarkdownView();
|
|
438
|
-
markdownComponent.data = {
|
|
438
|
+
markdownComponent.data = {
|
|
439
|
+
tokens: this.#description.markdown,
|
|
440
|
+
renderer: new MarkdownView.MarkdownPlaceholderLitRenderer.MarkdownPlaceholderLitRenderer(
|
|
441
|
+
this.#description.substitutions),
|
|
442
|
+
};
|
|
439
443
|
messageElement.listItemElement.appendChild(markdownComponent);
|
|
440
444
|
UI.ARIAUtils.setPositionInSet(messageElement.listItemElement, 1);
|
|
441
445
|
UI.ARIAUtils.setSetSize(messageElement.listItemElement, this.#description.links.length === 0 ? 2 : 3);
|
|
@@ -154,11 +154,16 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
154
154
|
void contextMenu.show();
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
const createSourceText = (text: string): TemplateResult =>
|
|
157
|
+
const createSourceText = (text: string): TemplateResult => {
|
|
158
|
+
const copy = (): void => input.copyValue(text);
|
|
159
|
+
// clang-format off
|
|
160
|
+
return html`<li role=treeitem
|
|
158
161
|
@contextmenu=${copyValueContextmenu(i18nString(UIStrings.copyPayload), () => text, 'copy-payload')}>
|
|
159
|
-
<devtools-widget class='payload-value source-code' ${widget(ShowMoreDetailsWidget, {text})}>
|
|
162
|
+
<devtools-widget class='payload-value source-code' ${widget(ShowMoreDetailsWidget, {text, copy})}>
|
|
160
163
|
</devtools-widget>
|
|
161
164
|
</li>`;
|
|
165
|
+
// clang-format on
|
|
166
|
+
};
|
|
162
167
|
|
|
163
168
|
const createParsedParams = (params: SDK.NetworkRequest.NameValue[],
|
|
164
169
|
decodeParameters: boolean): TemplateResult[] => params.map(param => {
|
|
@@ -11,6 +11,10 @@ const UIStrings = {
|
|
|
11
11
|
* @description Text to show more content
|
|
12
12
|
*/
|
|
13
13
|
showMore: 'Show more',
|
|
14
|
+
/**
|
|
15
|
+
* @description Context menu item to copy the shown text to the clipboard
|
|
16
|
+
*/
|
|
17
|
+
copy: 'Copy',
|
|
14
18
|
} as const;
|
|
15
19
|
const str_ = i18n.i18n.registerUIStrings('panels/network/ShowMoreDetailsWidget.ts', UIStrings);
|
|
16
20
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -20,7 +24,7 @@ interface ViewInput {
|
|
|
20
24
|
text: string;
|
|
21
25
|
showMore: boolean;
|
|
22
26
|
onToggle: () => void;
|
|
23
|
-
copy:
|
|
27
|
+
copy: (() => void)|null;
|
|
24
28
|
}
|
|
25
29
|
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
26
30
|
const MAX_LENGTH = 3000;
|
|
@@ -29,7 +33,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
29
33
|
const onContextMenuShowMore = (event: Event): void => {
|
|
30
34
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
31
35
|
if (input.copy) {
|
|
32
|
-
contextMenu.clipboardSection().appendItem(
|
|
36
|
+
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copy), input.copy, {jslogContext: 'copy'});
|
|
33
37
|
}
|
|
34
38
|
if (!input.showMore) {
|
|
35
39
|
contextMenu.newSection().appendItem(i18nString(UIStrings.showMore), input.onToggle, {jslogContext: 'show-more'});
|
|
@@ -51,16 +55,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
51
55
|
target);
|
|
52
56
|
};
|
|
53
57
|
|
|
54
|
-
interface CopyMenuItem {
|
|
55
|
-
menuItem: UI.ContextMenu.Item;
|
|
56
|
-
handler: () => void;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
58
|
export class ShowMoreDetailsWidget extends UI.Widget.Widget {
|
|
60
59
|
readonly #view: View;
|
|
61
60
|
#text = '';
|
|
62
61
|
#showMore = false;
|
|
63
|
-
#copy:
|
|
62
|
+
#copy: (() => void)|null = null;
|
|
64
63
|
constructor(target?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
65
64
|
super(target);
|
|
66
65
|
this.#view = view;
|
|
@@ -75,7 +74,11 @@ export class ShowMoreDetailsWidget extends UI.Widget.Widget {
|
|
|
75
74
|
this.requestUpdate();
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
get copy(): (() => void)|null {
|
|
78
|
+
return this.#copy;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
set copy(copy: () => void) {
|
|
79
82
|
this.#copy = copy;
|
|
80
83
|
this.requestUpdate();
|
|
81
84
|
}
|