chrome-devtools-frontend 1.0.1515988 → 1.0.1518653
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/docs/checklist/README.md +2 -2
- package/docs/checklist/javascript.md +1 -1
- package/docs/contributing/README.md +1 -1
- package/docs/contributing/settings-experiments-features.md +9 -8
- package/docs/cookbook/devtools_on_devtools.md +2 -2
- package/docs/cookbook/localization.md +10 -10
- package/docs/devtools-protocol.md +9 -8
- package/docs/ecosystem/automatic_workspace_folders.md +3 -3
- package/docs/get_the_code.md +0 -2
- package/docs/styleguide/ux/components.md +166 -85
- package/docs/styleguide/ux/numbers.md +3 -4
- package/front_end/core/common/README.md +13 -12
- package/front_end/core/host/GdpClient.ts +16 -1
- package/front_end/core/host/UserMetrics.ts +8 -2
- package/front_end/core/root/Runtime.ts +13 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +5 -1
- package/front_end/entrypoints/main/MainImpl.ts +6 -3
- package/front_end/generated/InspectorBackendCommands.js +10 -7
- package/front_end/generated/SupportedCSSProperties.js +21 -7
- package/front_end/generated/protocol-mapping.d.ts +16 -1
- package/front_end/generated/protocol-proxy-api.d.ts +13 -1
- package/front_end/generated/protocol.ts +95 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +170 -54
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +14 -181
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +13 -315
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +224 -50
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +310 -11
- package/front_end/models/ai_assistance/performance/AIContext.ts +15 -2
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +41 -19
- package/front_end/models/badges/Badge.ts +8 -3
- package/front_end/models/badges/CodeWhispererBadge.ts +2 -4
- package/front_end/models/badges/StarterBadge.ts +2 -2
- package/front_end/models/badges/UserBadges.ts +59 -6
- package/front_end/models/formatter/FormatterWorkerPool.ts +3 -3
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/trace/README.md +28 -1
- package/front_end/models/trace/handlers/UserTimingsHandler.ts +1 -1
- package/front_end/models/trace/helpers/Trace.ts +99 -43
- package/front_end/models/trace/types/TraceEvents.ts +9 -0
- package/front_end/panels/accessibility/ARIAAttributesView.ts +113 -191
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +9 -9
- package/front_end/panels/accessibility/AccessibilitySubPane.ts +6 -4
- package/front_end/panels/accessibility/accessibilityProperties.css +2 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +16 -2
- package/front_end/panels/ai_assistance/components/ChatView.ts +9 -10
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +42 -0
- package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +32 -9
- package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +7 -1
- package/front_end/panels/common/BadgeNotification.ts +67 -15
- package/front_end/panels/common/GdpSignUpDialog.ts +18 -9
- package/front_end/panels/console/ConsolePrompt.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +6 -2
- package/front_end/panels/elements/ComputedStyleWidget.ts +1 -2
- package/front_end/panels/elements/ElementsPanel.ts +4 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +18 -0
- package/front_end/panels/elements/ElementsTreeOutline.ts +13 -0
- package/front_end/panels/elements/LayoutPane.ts +1 -1
- package/front_end/panels/elements/StylePropertyTreeElement.ts +21 -6
- package/front_end/panels/media/TickingFlameChart.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +5 -1
- package/front_end/panels/profiler/HeapSnapshotView.ts +34 -19
- package/front_end/panels/search/SearchResultsPane.ts +126 -145
- package/front_end/panels/search/SearchView.ts +43 -59
- package/front_end/panels/settings/components/SyncSection.ts +16 -8
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +6 -1
- package/front_end/panels/sources/OutlineQuickOpen.ts +3 -1
- package/front_end/panels/sources/SourcesPanel.ts +3 -0
- package/front_end/panels/timeline/AppenderUtils.ts +2 -2
- package/front_end/panels/timeline/ExtensionTrackAppender.ts +13 -4
- package/front_end/panels/timeline/GPUTrackAppender.ts +2 -1
- package/front_end/panels/timeline/InteractionsTrackAppender.ts +5 -1
- package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +2 -1
- package/front_end/panels/timeline/ThreadAppender.ts +12 -3
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +9 -4
- package/front_end/panels/timeline/TimelinePanel.ts +3 -2
- package/front_end/panels/timeline/TimelineUIUtils.ts +18 -12
- package/front_end/panels/timeline/TimingsTrackAppender.ts +6 -1
- package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +95 -82
- package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
- package/front_end/panels/timeline/components/cpuThrottlingSelector.css +17 -15
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +3 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.d.ts +6 -9
- package/front_end/third_party/codemirror.next/package.json +2 -1
- package/front_end/third_party/diff/README.chromium +1 -0
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Accessibility.js +0 -20
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +2 -23
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Accessibility.js +0 -20
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/package.json +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +1 -21
- package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/revisions.ts +1 -1
- package/front_end/ui/components/text_editor/config.ts +36 -8
- package/front_end/ui/components/tooltips/Tooltip.ts +71 -34
- package/front_end/ui/legacy/README.md +33 -24
- package/front_end/ui/legacy/SearchableView.ts +19 -26
- package/front_end/ui/legacy/TextPrompt.ts +166 -1
- package/front_end/ui/legacy/Treeoutline.ts +16 -2
- package/front_end/ui/legacy/UIUtils.ts +15 -2
- package/front_end/ui/legacy/XElement.ts +0 -43
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +20 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +24 -6
- package/front_end/ui/visual_logging/README.md +43 -27
- package/package.json +1 -1
@@ -1,14 +1,15 @@
|
|
1
1
|
// Copyright 2016 The Chromium Authors
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
|
-
/* eslint-disable rulesdir/no-imperative-dom-api */
|
5
4
|
|
6
5
|
import * as i18n from '../../core/i18n/i18n.js';
|
7
6
|
import * as Platform from '../../core/platform/platform.js';
|
8
7
|
import * as SDK from '../../core/sdk/sdk.js';
|
9
8
|
import * as UI from '../../ui/legacy/legacy.js';
|
9
|
+
import * as Lit from '../../ui/lit/lit.js';
|
10
10
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
11
11
|
|
12
|
+
import accessibilityPropertiesStyles from './accessibilityProperties.css.js';
|
12
13
|
import {AccessibilitySubPane} from './AccessibilitySubPane.js';
|
13
14
|
import {ariaMetadata} from './ARIAMetadata.js';
|
14
15
|
|
@@ -24,214 +25,135 @@ const UIStrings = {
|
|
24
25
|
} as const;
|
25
26
|
const str_ = i18n.i18n.registerUIStrings('panels/accessibility/ARIAAttributesView.ts', UIStrings);
|
26
27
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
28
|
+
const {render, html} = Lit;
|
29
|
+
|
30
|
+
interface ViewInput {
|
31
|
+
propertyCompletions: Map<SDK.DOMModel.Attribute, string[]>;
|
32
|
+
onStartEditing: (attribute: SDK.DOMModel.Attribute) => void;
|
33
|
+
onCommitEditing: (attribute: SDK.DOMModel.Attribute, result: string) => void;
|
34
|
+
onCancelEditing: (attribute: SDK.DOMModel.Attribute) => void;
|
35
|
+
attributeBeingEdited: SDK.DOMModel.Attribute|null;
|
36
|
+
attributes: SDK.DOMModel.Attribute[];
|
37
|
+
}
|
38
|
+
|
39
|
+
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
40
|
+
export const DEFAULT_VIEW: View = (input, output, target) => {
|
41
|
+
const MAX_CONTENT_LENGTH = 10000;
|
42
|
+
|
43
|
+
const onStartEditing = (attribute: SDK.DOMModel.Attribute, e: MouseEvent): void => {
|
44
|
+
e.consume(true);
|
45
|
+
input.onStartEditing(attribute);
|
46
|
+
};
|
47
|
+
|
48
|
+
const propertyCompletions = (attribute: SDK.DOMModel.Attribute): Lit.LitTemplate => {
|
49
|
+
const values = input.propertyCompletions.get(attribute);
|
50
|
+
if (!values?.length) {
|
51
|
+
return Lit.nothing;
|
52
|
+
}
|
53
|
+
|
54
|
+
return html`<datalist id=completions>
|
55
|
+
${values.map(value => html`<option>${value}</option>`)}
|
56
|
+
</datalist>`;
|
57
|
+
};
|
58
|
+
|
59
|
+
render(
|
60
|
+
// clang-format off
|
61
|
+
input.attributes.length === 0 ?
|
62
|
+
html`
|
63
|
+
<style>${accessibilityPropertiesStyles}</style>
|
64
|
+
<devtools-widget
|
65
|
+
.widgetConfig=${UI.Widget.widgetConfig(UI.EmptyWidget.EmptyWidget,
|
66
|
+
{text: i18nString(UIStrings.noAriaAttributes)})}
|
67
|
+
class="gray-info-message info-message-overflow"></devtools-widget>` :
|
68
|
+
html`<devtools-tree
|
69
|
+
hide-overflow
|
70
|
+
.template=${html`
|
71
|
+
<ul role="tree">
|
72
|
+
${input.attributes?.map(attribute => html`
|
73
|
+
<li role="treeitem">
|
74
|
+
<style>${accessibilityPropertiesStyles}</style>
|
75
|
+
<span class="ax-name monospace" @mousedown=${onStartEditing.bind(null, attribute)}>
|
76
|
+
${attribute.name}
|
77
|
+
</span>
|
78
|
+
<span class="separator" @mousedown=${onStartEditing.bind(null, attribute)}>${':\xA0'}</span>
|
79
|
+
<devtools-prompt
|
80
|
+
completions=completions
|
81
|
+
class="monospace"
|
82
|
+
@mousedown=${onStartEditing.bind(null, attribute)}
|
83
|
+
.completionTimeout=${0}
|
84
|
+
?editing=${input.attributeBeingEdited === attribute}
|
85
|
+
@commit=${(e: UI.TextPrompt.TextPromptElement.CommitEvent) =>
|
86
|
+
input.onCommitEditing(attribute, e.detail)}
|
87
|
+
@cancel=${() => input.onCancelEditing(attribute)}>
|
88
|
+
${Platform.StringUtilities.trimMiddle(attribute.value, MAX_CONTENT_LENGTH)}
|
89
|
+
${propertyCompletions(attribute)}
|
90
|
+
</devtools-prompt>
|
91
|
+
</li>`)}
|
92
|
+
</ul>
|
93
|
+
`}></devtools-tree>`,
|
94
|
+
// clang-format on
|
95
|
+
target);
|
96
|
+
};
|
97
|
+
|
27
98
|
export class ARIAAttributesPane extends AccessibilitySubPane {
|
28
|
-
|
29
|
-
|
99
|
+
readonly #view: View;
|
100
|
+
#attributeBeingEdited: SDK.DOMModel.Attribute|null = null;
|
30
101
|
|
31
|
-
constructor() {
|
102
|
+
constructor(view = DEFAULT_VIEW) {
|
32
103
|
super({
|
33
104
|
title: i18nString(UIStrings.ariaAttributes),
|
34
105
|
viewId: 'aria-attributes',
|
35
106
|
jslog: `${VisualLogging.section('aria-attributes')}`,
|
36
107
|
});
|
37
108
|
|
38
|
-
this
|
39
|
-
this.treeOutline = this.createTreeOutline();
|
109
|
+
this.#view = view;
|
40
110
|
}
|
41
111
|
|
42
112
|
override setNode(node: SDK.DOMModel.DOMNode|null): void {
|
43
113
|
super.setNode(node);
|
44
|
-
this.
|
45
|
-
|
46
|
-
return;
|
47
|
-
}
|
48
|
-
const target = node.domModel().target();
|
49
|
-
const attributes = node.attributes();
|
50
|
-
for (let i = 0; i < attributes.length; ++i) {
|
51
|
-
const attribute = attributes[i];
|
52
|
-
if (!this.isARIAAttribute(attribute)) {
|
53
|
-
continue;
|
54
|
-
}
|
114
|
+
this.requestUpdate();
|
115
|
+
}
|
55
116
|
|
56
|
-
|
57
|
-
|
117
|
+
override performUpdate(): void {
|
118
|
+
const onStartEditing = (attribute: SDK.DOMModel.Attribute): void => {
|
119
|
+
this.#attributeBeingEdited = attribute;
|
120
|
+
this.requestUpdate();
|
121
|
+
};
|
122
|
+
const onCancelEditing = (attribute: SDK.DOMModel.Attribute): void => {
|
123
|
+
if (attribute === this.#attributeBeingEdited) {
|
124
|
+
this.#attributeBeingEdited = null;
|
125
|
+
}
|
126
|
+
this.requestUpdate();
|
127
|
+
};
|
128
|
+
|
129
|
+
const onCommitEditing = (attribute: SDK.DOMModel.Attribute, result: string): void => {
|
130
|
+
// Make the changes to the attribute
|
131
|
+
const node = this.node();
|
132
|
+
if (node && attribute.value !== result) {
|
133
|
+
node.setAttributeValue(attribute.name, result);
|
134
|
+
}
|
135
|
+
if (attribute === this.#attributeBeingEdited) {
|
136
|
+
this.#attributeBeingEdited = null;
|
137
|
+
}
|
138
|
+
this.requestUpdate();
|
139
|
+
};
|
58
140
|
|
59
|
-
const
|
60
|
-
|
61
|
-
|
62
|
-
}
|
141
|
+
const attributes = this.node()?.attributes()?.filter(attribute => this.isARIAAttribute(attribute)) ?? [];
|
142
|
+
const propertyCompletions =
|
143
|
+
new Map(attributes.map(attribute => [attribute, ariaMetadata().valuesForProperty(attribute.name)]));
|
63
144
|
|
64
|
-
|
65
|
-
|
145
|
+
const input: ViewInput = {
|
146
|
+
attributeBeingEdited: this.#attributeBeingEdited,
|
147
|
+
attributes,
|
148
|
+
onStartEditing,
|
149
|
+
onCommitEditing,
|
150
|
+
onCancelEditing,
|
151
|
+
propertyCompletions,
|
152
|
+
};
|
153
|
+
this.#view(input, {}, this.contentElement);
|
66
154
|
}
|
67
155
|
|
68
156
|
private isARIAAttribute(attribute: SDK.DOMModel.Attribute): boolean {
|
69
157
|
return SDK.DOMModel.ARIA_ATTRIBUTES.has(attribute.name);
|
70
158
|
}
|
71
159
|
}
|
72
|
-
|
73
|
-
export class ARIAAttributesTreeElement extends UI.TreeOutline.TreeElement {
|
74
|
-
private readonly parentPane: ARIAAttributesPane;
|
75
|
-
private readonly attribute: SDK.DOMModel.Attribute;
|
76
|
-
private nameElement?: HTMLSpanElement;
|
77
|
-
private valueElement?: Element;
|
78
|
-
private prompt?: ARIAAttributePrompt;
|
79
|
-
|
80
|
-
constructor(parentPane: ARIAAttributesPane, attribute: SDK.DOMModel.Attribute, _target: SDK.Target.Target) {
|
81
|
-
super('');
|
82
|
-
|
83
|
-
this.parentPane = parentPane;
|
84
|
-
this.attribute = attribute;
|
85
|
-
|
86
|
-
this.selectable = false;
|
87
|
-
}
|
88
|
-
|
89
|
-
static createARIAValueElement(value: string): Element {
|
90
|
-
const valueElement = document.createElement('span');
|
91
|
-
valueElement.classList.add('monospace');
|
92
|
-
// TODO(aboxhall): quotation marks?
|
93
|
-
valueElement.setTextContentTruncatedIfNeeded(value || '');
|
94
|
-
return valueElement;
|
95
|
-
}
|
96
|
-
|
97
|
-
override onattach(): void {
|
98
|
-
this.populateListItem();
|
99
|
-
this.listItemElement.addEventListener('click', this.mouseClick.bind(this));
|
100
|
-
}
|
101
|
-
|
102
|
-
getPromptForTesting(): Readonly<ARIAAttributePrompt>|undefined {
|
103
|
-
return this.prompt;
|
104
|
-
}
|
105
|
-
|
106
|
-
private populateListItem(): void {
|
107
|
-
this.listItemElement.removeChildren();
|
108
|
-
this.appendNameElement(this.attribute.name);
|
109
|
-
this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
|
110
|
-
this.appendAttributeValueElement(this.attribute.value);
|
111
|
-
}
|
112
|
-
|
113
|
-
appendNameElement(name: string): void {
|
114
|
-
this.nameElement = document.createElement('span');
|
115
|
-
this.nameElement.textContent = name;
|
116
|
-
this.nameElement.classList.add('ax-name');
|
117
|
-
this.nameElement.classList.add('monospace');
|
118
|
-
this.listItemElement.appendChild(this.nameElement);
|
119
|
-
}
|
120
|
-
|
121
|
-
appendAttributeValueElement(value: string): void {
|
122
|
-
this.valueElement = ARIAAttributesTreeElement.createARIAValueElement(value);
|
123
|
-
this.listItemElement.appendChild(this.valueElement);
|
124
|
-
}
|
125
|
-
|
126
|
-
private mouseClick(event: Event): void {
|
127
|
-
if (event.target === this.listItemElement) {
|
128
|
-
return;
|
129
|
-
}
|
130
|
-
|
131
|
-
event.consume(true);
|
132
|
-
|
133
|
-
this.startEditing();
|
134
|
-
}
|
135
|
-
|
136
|
-
private startEditing(): void {
|
137
|
-
const valueElement = this.valueElement;
|
138
|
-
|
139
|
-
if (!valueElement || UI.UIUtils.isBeingEdited(valueElement)) {
|
140
|
-
return;
|
141
|
-
}
|
142
|
-
|
143
|
-
const previousContent = valueElement.textContent || '';
|
144
|
-
|
145
|
-
function blurListener(this: ARIAAttributesTreeElement, previousContent: string, event: Event): void {
|
146
|
-
const target = event.target as HTMLElement;
|
147
|
-
const text = target.textContent || '';
|
148
|
-
this.editingCommitted(text, previousContent);
|
149
|
-
}
|
150
|
-
|
151
|
-
const attributeName = (this.nameElement as HTMLSpanElement).textContent || '';
|
152
|
-
this.prompt = new ARIAAttributePrompt(ariaMetadata().valuesForProperty(attributeName));
|
153
|
-
this.prompt.setAutocompletionTimeout(0);
|
154
|
-
const proxyElement =
|
155
|
-
this.prompt.attachAndStartEditing(valueElement, blurListener.bind(this, previousContent)) as HTMLElement;
|
156
|
-
|
157
|
-
proxyElement.addEventListener('keydown', event => this.editingValueKeyDown(previousContent, event), false);
|
158
|
-
|
159
|
-
const selection = valueElement.getComponentSelection();
|
160
|
-
if (selection) {
|
161
|
-
selection.selectAllChildren(valueElement);
|
162
|
-
}
|
163
|
-
}
|
164
|
-
|
165
|
-
private removePrompt(): void {
|
166
|
-
if (!this.prompt) {
|
167
|
-
return;
|
168
|
-
}
|
169
|
-
this.prompt.detach();
|
170
|
-
delete this.prompt;
|
171
|
-
}
|
172
|
-
|
173
|
-
private editingCommitted(userInput: string, previousContent: string): void {
|
174
|
-
this.removePrompt();
|
175
|
-
|
176
|
-
// Make the changes to the attribute
|
177
|
-
if (userInput !== previousContent) {
|
178
|
-
const node = this.parentPane.node() as SDK.DOMModel.DOMNode;
|
179
|
-
node.setAttributeValue(this.attribute.name, userInput);
|
180
|
-
}
|
181
|
-
}
|
182
|
-
|
183
|
-
private editingCancelled(): void {
|
184
|
-
this.removePrompt();
|
185
|
-
this.populateListItem();
|
186
|
-
}
|
187
|
-
|
188
|
-
private editingValueKeyDown(previousContent: string, event: KeyboardEvent): void {
|
189
|
-
if (event.handled) {
|
190
|
-
return;
|
191
|
-
}
|
192
|
-
|
193
|
-
if (event.key === 'Enter') {
|
194
|
-
const target = event.target as HTMLElement;
|
195
|
-
this.editingCommitted(target.textContent || '', previousContent);
|
196
|
-
event.consume();
|
197
|
-
return;
|
198
|
-
}
|
199
|
-
|
200
|
-
if (Platform.KeyboardUtilities.isEscKey(event)) {
|
201
|
-
this.editingCancelled();
|
202
|
-
event.consume();
|
203
|
-
return;
|
204
|
-
}
|
205
|
-
}
|
206
|
-
}
|
207
|
-
|
208
|
-
export class ARIAAttributePrompt extends UI.TextPrompt.TextPrompt {
|
209
|
-
private readonly ariaCompletions: string[];
|
210
|
-
constructor(ariaCompletions: string[]) {
|
211
|
-
super();
|
212
|
-
this.initialize(this.buildPropertyCompletions.bind(this));
|
213
|
-
|
214
|
-
this.ariaCompletions = ariaCompletions;
|
215
|
-
}
|
216
|
-
|
217
|
-
private async buildPropertyCompletions(expression: string, prefix: string, force?: boolean):
|
218
|
-
Promise<UI.SuggestBox.Suggestions> {
|
219
|
-
prefix = prefix.toLowerCase();
|
220
|
-
if (!prefix && !force && expression) {
|
221
|
-
return [];
|
222
|
-
}
|
223
|
-
return this.ariaCompletions.filter(value => value.startsWith(prefix)).map(c => {
|
224
|
-
return {
|
225
|
-
text: c,
|
226
|
-
title: undefined,
|
227
|
-
subtitle: undefined,
|
228
|
-
priority: undefined,
|
229
|
-
isSecondary: undefined,
|
230
|
-
subtitleRenderer: undefined,
|
231
|
-
selectionRange: undefined,
|
232
|
-
hideGhostText: undefined,
|
233
|
-
iconElement: undefined,
|
234
|
-
};
|
235
|
-
});
|
236
|
-
}
|
237
|
-
}
|
@@ -120,8 +120,8 @@ const str_ = i18n.i18n.registerUIStrings('panels/accessibility/AccessibilityNode
|
|
120
120
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
121
121
|
export class AXNodeSubPane extends AccessibilitySubPane {
|
122
122
|
override axNode: SDK.AccessibilityModel.AccessibilityNode|null;
|
123
|
-
private readonly noNodeInfo:
|
124
|
-
private readonly ignoredInfo:
|
123
|
+
private readonly noNodeInfo: UI.Widget.Widget;
|
124
|
+
private readonly ignoredInfo: UI.Widget.Widget;
|
125
125
|
private readonly treeOutline: UI.TreeOutline.TreeOutline;
|
126
126
|
private readonly ignoredReasonsTree: UI.TreeOutline.TreeOutline;
|
127
127
|
constructor() {
|
@@ -137,7 +137,7 @@ export class AXNodeSubPane extends AccessibilitySubPane {
|
|
137
137
|
this.contentElement.classList.add('ax-subpane');
|
138
138
|
|
139
139
|
this.noNodeInfo = this.createInfo(i18nString(UIStrings.noAccessibilityNode));
|
140
|
-
this.ignoredInfo = this.createInfo(i18nString(UIStrings.accessibilityNodeNotExposed), 'ax-ignored-info hidden');
|
140
|
+
this.ignoredInfo = this.createInfo(i18nString(UIStrings.accessibilityNodeNotExposed), 'ax-ignored-info', 'hidden');
|
141
141
|
|
142
142
|
this.treeOutline = this.createTreeOutline();
|
143
143
|
this.ignoredReasonsTree = this.createTreeOutline();
|
@@ -160,21 +160,21 @@ export class AXNodeSubPane extends AccessibilitySubPane {
|
|
160
160
|
|
161
161
|
if (!axNode) {
|
162
162
|
treeOutline.element.classList.add('hidden');
|
163
|
-
this.ignoredInfo.classList.add('hidden');
|
163
|
+
this.ignoredInfo.element.classList.add('hidden');
|
164
164
|
ignoredReasons.element.classList.add('hidden');
|
165
165
|
|
166
|
-
this.noNodeInfo.classList.remove('hidden');
|
166
|
+
this.noNodeInfo.element.classList.remove('hidden');
|
167
167
|
this.element.classList.add('ax-ignored-node-pane');
|
168
168
|
|
169
169
|
return;
|
170
170
|
}
|
171
171
|
|
172
172
|
if (axNode.ignored()) {
|
173
|
-
this.noNodeInfo.classList.add('hidden');
|
173
|
+
this.noNodeInfo.element.classList.add('hidden');
|
174
174
|
treeOutline.element.classList.add('hidden');
|
175
175
|
this.element.classList.add('ax-ignored-node-pane');
|
176
176
|
|
177
|
-
this.ignoredInfo.classList.remove('hidden');
|
177
|
+
this.ignoredInfo.element.classList.remove('hidden');
|
178
178
|
ignoredReasons.element.classList.remove('hidden');
|
179
179
|
function addIgnoredReason(property: Protocol.Accessibility.AXProperty): void {
|
180
180
|
ignoredReasons.appendChild(
|
@@ -191,9 +191,9 @@ export class AXNodeSubPane extends AccessibilitySubPane {
|
|
191
191
|
}
|
192
192
|
this.element.classList.remove('ax-ignored-node-pane');
|
193
193
|
|
194
|
-
this.ignoredInfo.classList.add('hidden');
|
194
|
+
this.ignoredInfo.element.classList.add('hidden');
|
195
195
|
ignoredReasons.element.classList.add('hidden');
|
196
|
-
this.noNodeInfo.classList.add('hidden');
|
196
|
+
this.noNodeInfo.element.classList.add('hidden');
|
197
197
|
|
198
198
|
treeOutline.element.classList.remove('hidden');
|
199
199
|
|
@@ -33,10 +33,12 @@ export class AccessibilitySubPane extends UI.View.SimpleView {
|
|
33
33
|
this.nodeInternal = node;
|
34
34
|
}
|
35
35
|
|
36
|
-
createInfo(textContent: string,
|
37
|
-
const info =
|
38
|
-
|
39
|
-
|
36
|
+
createInfo(textContent: string, ...classNames: string[]): UI.Widget.Widget {
|
37
|
+
const info = new UI.EmptyWidget.EmptyWidget(textContent);
|
38
|
+
if (classNames.length === 0) {
|
39
|
+
classNames.push('gray-info-message');
|
40
|
+
}
|
41
|
+
info.element.classList.add(...classNames, 'info-message-overflow');
|
40
42
|
return info;
|
41
43
|
}
|
42
44
|
|
@@ -35,6 +35,8 @@ import {
|
|
35
35
|
type Step
|
36
36
|
} from './components/ChatView.js';
|
37
37
|
import {ExploreWidget} from './components/ExploreWidget.js';
|
38
|
+
import {MarkdownRendererWithCodeBlock} from './components/MarkdownRendererWithCodeBlock.js';
|
39
|
+
import {PerformanceAgentMarkdownRenderer} from './components/PerformanceAgentMarkdownRenderer.js';
|
38
40
|
import {isAiAssistancePatchingEnabled} from './PatchWidget.js';
|
39
41
|
|
40
42
|
const {html} = Lit;
|
@@ -263,6 +265,16 @@ async function getEmptyStateSuggestions(
|
|
263
265
|
}
|
264
266
|
}
|
265
267
|
|
268
|
+
function getMarkdownRenderer(context: AiAssistanceModel.ConversationContext<unknown>|null):
|
269
|
+
MarkdownRendererWithCodeBlock {
|
270
|
+
if (context instanceof AiAssistanceModel.PerformanceTraceContext && !context.external) {
|
271
|
+
const focus = context.getItem();
|
272
|
+
return new PerformanceAgentMarkdownRenderer(focus.lookupEvent.bind(focus));
|
273
|
+
}
|
274
|
+
|
275
|
+
return new MarkdownRendererWithCodeBlock();
|
276
|
+
}
|
277
|
+
|
266
278
|
interface ToolbarViewInput {
|
267
279
|
onNewChatClick: () => void;
|
268
280
|
populateHistoryMenu: (contextMenu: UI.ContextMenu.ContextMenu) => void;
|
@@ -837,6 +849,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
837
849
|
|
838
850
|
override async performUpdate(): Promise<void> {
|
839
851
|
const emptyStateSuggestions = await getEmptyStateSuggestions(this.#selectedContext, this.#conversation);
|
852
|
+
const markdownRenderer = getMarkdownRenderer(this.#selectedContext);
|
840
853
|
|
841
854
|
this.view(
|
842
855
|
{
|
@@ -865,6 +878,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
865
878
|
changeManager: this.#changeManager,
|
866
879
|
uploadImageInputEnabled: isAiAssistanceMultimodalUploadInputEnabled() &&
|
867
880
|
this.#conversation?.type === AiAssistanceModel.ConversationType.STYLING,
|
881
|
+
markdownRenderer,
|
868
882
|
onNewChatClick: this.#handleNewChatRequest.bind(this),
|
869
883
|
populateHistoryMenu: this.#populateHistoryMenu.bind(this),
|
870
884
|
onDeleteClick: this.#onDeleteClicked.bind(this),
|
@@ -1054,8 +1068,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
1054
1068
|
const focus = context.getItem().data;
|
1055
1069
|
if (focus.callTree) {
|
1056
1070
|
const event = focus.callTree.selectedNode?.event ?? focus.callTree.rootNode.event;
|
1057
|
-
const
|
1058
|
-
return Common.Revealer.reveal(
|
1071
|
+
const revealable = new SDK.TraceObject.RevealableEvent(event);
|
1072
|
+
return Common.Revealer.reveal(revealable);
|
1059
1073
|
}
|
1060
1074
|
if (focus.insight) {
|
1061
1075
|
return Common.Revealer.reveal(focus.insight);
|
@@ -18,13 +18,13 @@ import * as PanelUtils from '../../../panels/utils/utils.js';
|
|
18
18
|
import * as Marked from '../../../third_party/marked/marked.js';
|
19
19
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
20
20
|
import type * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';
|
21
|
+
import type {MarkdownLitRenderer} from '../../../ui/components/markdown_view/MarkdownView.js';
|
21
22
|
import * as UI from '../../../ui/legacy/legacy.js';
|
22
23
|
import * as Lit from '../../../ui/lit/lit.js';
|
23
24
|
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
24
25
|
import {PatchWidget} from '../PatchWidget.js';
|
25
26
|
|
26
27
|
import chatViewStyles from './chatView.css.js';
|
27
|
-
import {MarkdownRendererWithCodeBlock} from './MarkdownRendererWithCodeBlock.js';
|
28
28
|
import {UserActionRow} from './UserActionRow.js';
|
29
29
|
|
30
30
|
const {html, Directives: {ifDefined, ref}} = Lit;
|
@@ -303,11 +303,11 @@ export interface Props {
|
|
303
303
|
disclaimerText: Platform.UIString.LocalizedString;
|
304
304
|
isTextInputEmpty: boolean;
|
305
305
|
uploadImageInputEnabled?: boolean;
|
306
|
+
markdownRenderer: MarkdownLitRenderer;
|
306
307
|
}
|
307
308
|
|
308
309
|
export class ChatView extends HTMLElement {
|
309
310
|
readonly #shadow = this.attachShadow({mode: 'open'});
|
310
|
-
#markdownRenderer = new MarkdownRendererWithCodeBlock();
|
311
311
|
#scrollTop?: number;
|
312
312
|
#props: Props;
|
313
313
|
#messagesContainerElement?: Element;
|
@@ -338,7 +338,6 @@ export class ChatView extends HTMLElement {
|
|
338
338
|
}
|
339
339
|
|
340
340
|
set props(props: Props) {
|
341
|
-
this.#markdownRenderer = new MarkdownRendererWithCodeBlock();
|
342
341
|
this.#props = props;
|
343
342
|
this.#render();
|
344
343
|
}
|
@@ -624,7 +623,7 @@ export class ChatView extends HTMLElement {
|
|
624
623
|
isTextInputDisabled: this.#props.isTextInputDisabled,
|
625
624
|
suggestions: this.#props.emptyStateSuggestions,
|
626
625
|
userInfo: this.#props.userInfo,
|
627
|
-
markdownRenderer: this.#markdownRenderer,
|
626
|
+
markdownRenderer: this.#props.markdownRenderer,
|
628
627
|
conversationType: this.#props.conversationType,
|
629
628
|
changeSummary: this.#props.changeSummary,
|
630
629
|
changeManager: this.#props.changeManager,
|
@@ -672,7 +671,7 @@ export class ChatView extends HTMLElement {
|
|
672
671
|
}
|
673
672
|
}
|
674
673
|
|
675
|
-
function renderTextAsMarkdown(text: string, markdownRenderer:
|
674
|
+
function renderTextAsMarkdown(text: string, markdownRenderer: MarkdownLitRenderer, {animate, ref: refFn}: {
|
676
675
|
animate?: boolean,
|
677
676
|
ref?: (element?: Element) => void,
|
678
677
|
} = {}): Lit.TemplateResult {
|
@@ -753,7 +752,7 @@ function renderStepDetails({
|
|
753
752
|
isLast,
|
754
753
|
}: {
|
755
754
|
step: Step,
|
756
|
-
markdownRenderer:
|
755
|
+
markdownRenderer: MarkdownLitRenderer,
|
757
756
|
isLast: boolean,
|
758
757
|
}): Lit.LitTemplate {
|
759
758
|
const sideEffects = isLast && step.sideEffect ? renderSideEffectConfirmationUi(step) : Lit.nothing;
|
@@ -817,7 +816,7 @@ function renderStepBadge({step, isLoading, isLast}: {
|
|
817
816
|
function renderStep({step, isLoading, markdownRenderer, isLast}: {
|
818
817
|
step: Step,
|
819
818
|
isLoading: boolean,
|
820
|
-
markdownRenderer:
|
819
|
+
markdownRenderer: MarkdownLitRenderer,
|
821
820
|
isLast: boolean,
|
822
821
|
}): Lit.LitTemplate {
|
823
822
|
const stepClasses = Lit.Directives.classMap({
|
@@ -926,7 +925,7 @@ function renderChatMessage({
|
|
926
925
|
canShowFeedbackForm: boolean,
|
927
926
|
isLast: boolean,
|
928
927
|
userInfo: Pick<Host.InspectorFrontendHostAPI.SyncInformation, 'accountImage'|'accountFullName'>,
|
929
|
-
markdownRenderer:
|
928
|
+
markdownRenderer: MarkdownLitRenderer,
|
930
929
|
onSuggestionClick: (suggestion: string) => void,
|
931
930
|
onFeedbackSubmit: (rpcId: Host.AidaClient.RpcGlobalId, rate: Host.AidaClient.Rating, feedback?: string) => void,
|
932
931
|
onCopyResponseClick: (message: ModelChatMessage) => void,
|
@@ -1156,7 +1155,7 @@ function renderMessages({
|
|
1156
1155
|
isReadOnly: boolean,
|
1157
1156
|
canShowFeedbackForm: boolean,
|
1158
1157
|
userInfo: Pick<Host.InspectorFrontendHostAPI.SyncInformation, 'accountImage'|'accountFullName'>,
|
1159
|
-
markdownRenderer:
|
1158
|
+
markdownRenderer: MarkdownLitRenderer,
|
1160
1159
|
onSuggestionClick: (suggestion: string) => void,
|
1161
1160
|
onFeedbackSubmit: (rpcId: Host.AidaClient.RpcGlobalId, rate: Host.AidaClient.Rating, feedback?: string) => void,
|
1162
1161
|
onCopyResponseClick: (message: ModelChatMessage) => void,
|
@@ -1657,7 +1656,7 @@ function renderMainContents({
|
|
1657
1656
|
isTextInputDisabled: boolean,
|
1658
1657
|
suggestions: AiAssistanceModel.ConversationSuggestion[],
|
1659
1658
|
userInfo: Pick<Host.InspectorFrontendHostAPI.SyncInformation, 'accountImage'|'accountFullName'>,
|
1660
|
-
markdownRenderer:
|
1659
|
+
markdownRenderer: MarkdownLitRenderer,
|
1661
1660
|
changeManager: AiAssistanceModel.ChangeManager,
|
1662
1661
|
onSuggestionClick: (suggestion: string) => void,
|
1663
1662
|
onFeedbackSubmit: (rpcId: Host.AidaClient.RpcGlobalId, rate: Host.AidaClient.Rating, feedback?: string) => void,
|
@@ -0,0 +1,42 @@
|
|
1
|
+
// Copyright 2025 The Chromium Authors
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
import * as Common from '../../../core/common/common.js';
|
6
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
7
|
+
import * as Trace from '../../../models/trace/trace.js';
|
8
|
+
import type * as Marked from '../../../third_party/marked/marked.js';
|
9
|
+
import * as Lit from '../../../ui/lit/lit.js';
|
10
|
+
|
11
|
+
import {MarkdownRendererWithCodeBlock} from './MarkdownRendererWithCodeBlock.js';
|
12
|
+
|
13
|
+
const {html} = Lit;
|
14
|
+
|
15
|
+
export class PerformanceAgentMarkdownRenderer extends MarkdownRendererWithCodeBlock {
|
16
|
+
constructor(private lookupEvent: (key: Trace.Types.File.SerializableKey) => Trace.Types.Events.Event | null) {
|
17
|
+
super();
|
18
|
+
}
|
19
|
+
|
20
|
+
override templateForToken(token: Marked.Marked.MarkedToken): Lit.TemplateResult|null {
|
21
|
+
if (token.type === 'link' && token.href.startsWith('#')) {
|
22
|
+
const event = this.lookupEvent(token.href.slice(1) as Trace.Types.File.SerializableKey);
|
23
|
+
if (event) {
|
24
|
+
let label = token.text;
|
25
|
+
let title = '';
|
26
|
+
if (Trace.Types.Events.isSyntheticNetworkRequest(event)) {
|
27
|
+
title = event.args.data.url;
|
28
|
+
} else {
|
29
|
+
label += ` (${event.name})`;
|
30
|
+
}
|
31
|
+
|
32
|
+
// eslint-disable-next-line rulesdir/no-a-tags-in-lit
|
33
|
+
return html`<a href="#" draggable=false .title=${title} @click=${(e: Event) => {
|
34
|
+
e.stopPropagation();
|
35
|
+
void Common.Revealer.reveal(new SDK.TraceObject.RevealableEvent(event));
|
36
|
+
}}>${label}</a>`;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
return super.templateForToken(token);
|
41
|
+
}
|
42
|
+
}
|