chrome-devtools-frontend 1.0.1033742 → 1.0.1034881
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/front_end/core/host/InspectorFrontendHostAPI.ts +1 -0
- package/front_end/core/host/UserMetrics.ts +23 -0
- package/front_end/core/root/Runtime.ts +11 -1
- package/front_end/core/sdk/NetworkManager.ts +19 -5
- package/front_end/entrypoints/lighthouse_worker/LighthouseWorkerService.ts +19 -8
- package/front_end/entrypoints/main/MainImpl.ts +5 -1
- package/front_end/models/persistence/NetworkPersistenceManager.ts +6 -2
- package/front_end/panels/elements/CSSRuleValidator.ts +169 -101
- package/front_end/panels/elements/CSSRuleValidatorHelper.ts +13 -7
- package/front_end/panels/elements/StylePropertiesSection.ts +8 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +35 -31
- package/front_end/panels/elements/StylesSidebarPane.ts +24 -0
- package/front_end/panels/elements/components/CSSHintDetailsView.ts +5 -5
- package/front_end/panels/elements/components/LayoutPane.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +9 -6
- package/package.json +1 -1
@@ -277,6 +277,11 @@ export class UserMetrics {
|
|
277
277
|
InspectorFrontendHostInstance.recordEnumeratedHistogram(
|
278
278
|
EnumeratedHistogram.ManifestSectionSelected, code, ManifestSectionCodes.MaxValue);
|
279
279
|
}
|
280
|
+
|
281
|
+
cssHintShown(type: CSSHintType): void {
|
282
|
+
InspectorFrontendHostInstance.recordEnumeratedHistogram(
|
283
|
+
EnumeratedHistogram.CSSHintShown, type, CSSHintType.MaxValue);
|
284
|
+
}
|
280
285
|
}
|
281
286
|
|
282
287
|
/**
|
@@ -993,4 +998,22 @@ export enum ManifestSectionCodes {
|
|
993
998
|
MaxValue = 5,
|
994
999
|
}
|
995
1000
|
|
1001
|
+
// The names here match the CSSRuleValidator names in CSSRuleValidator.ts.
|
1002
|
+
// TODO(crbug.com/1167717): Make this a const enum again
|
1003
|
+
// eslint-disable-next-line rulesdir/const_enum
|
1004
|
+
export enum CSSHintType {
|
1005
|
+
Other = 0,
|
1006
|
+
AlignContent = 1,
|
1007
|
+
FlexItem = 2,
|
1008
|
+
FlexContainer = 3,
|
1009
|
+
GridContainer = 4,
|
1010
|
+
GridItem = 5,
|
1011
|
+
FlexGrid = 6,
|
1012
|
+
MulticolFlexGrid = 7,
|
1013
|
+
Padding = 8,
|
1014
|
+
Position = 9,
|
1015
|
+
ZIndex = 10,
|
1016
|
+
MaxValue = 11,
|
1017
|
+
}
|
1018
|
+
|
996
1019
|
/* eslint-enable @typescript-eslint/naming-convention */
|
@@ -120,18 +120,21 @@ export class ExperimentsSupport {
|
|
120
120
|
#enabledTransiently: Set<string>;
|
121
121
|
readonly #enabledByDefault: Set<string>;
|
122
122
|
readonly #serverEnabled: Set<string>;
|
123
|
+
// Experiments in this set won't be shown to the user
|
124
|
+
readonly #nonConfigurable: Set<string>;
|
123
125
|
constructor() {
|
124
126
|
this.#experiments = [];
|
125
127
|
this.#experimentNames = new Set();
|
126
128
|
this.#enabledTransiently = new Set();
|
127
129
|
this.#enabledByDefault = new Set();
|
128
130
|
this.#serverEnabled = new Set();
|
131
|
+
this.#nonConfigurable = new Set();
|
129
132
|
}
|
130
133
|
|
131
134
|
allConfigurableExperiments(): Experiment[] {
|
132
135
|
const result = [];
|
133
136
|
for (const experiment of this.#experiments) {
|
134
|
-
if (!this.#enabledTransiently.has(experiment.name)) {
|
137
|
+
if (!this.#enabledTransiently.has(experiment.name) && !this.#nonConfigurable.has(experiment.name)) {
|
135
138
|
result.push(experiment);
|
136
139
|
}
|
137
140
|
}
|
@@ -203,6 +206,13 @@ export class ExperimentsSupport {
|
|
203
206
|
}
|
204
207
|
}
|
205
208
|
|
209
|
+
setNonConfigurableExperiments(experimentNames: string[]): void {
|
210
|
+
for (const experiment of experimentNames) {
|
211
|
+
this.checkExperiment(experiment);
|
212
|
+
this.#nonConfigurable.add(experiment);
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
206
216
|
enableForTest(experimentName: string): void {
|
207
217
|
this.checkExperiment(experimentName);
|
208
218
|
this.#enabledTransiently.add(experimentName);
|
@@ -465,10 +465,10 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
|
|
465
465
|
networkRequest.setUrl(response.url as Platform.DevToolsPath.UrlString);
|
466
466
|
}
|
467
467
|
networkRequest.mimeType = (response.mimeType as MIME_TYPE);
|
468
|
-
if (!networkRequest.statusCode) {
|
468
|
+
if (!networkRequest.statusCode || networkRequest.wasIntercepted()) {
|
469
469
|
networkRequest.statusCode = response.status;
|
470
470
|
}
|
471
|
-
if (!networkRequest.statusText) {
|
471
|
+
if (!networkRequest.statusText || networkRequest.wasIntercepted()) {
|
472
472
|
networkRequest.statusText = response.statusText;
|
473
473
|
}
|
474
474
|
if (!networkRequest.hasExtraResponseInfo() || networkRequest.wasIntercepted()) {
|
@@ -1170,6 +1170,10 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
|
|
1170
1170
|
return multiTargetNetworkManagerInstance;
|
1171
1171
|
}
|
1172
1172
|
|
1173
|
+
static dispose(): void {
|
1174
|
+
multiTargetNetworkManagerInstance = null;
|
1175
|
+
}
|
1176
|
+
|
1173
1177
|
static getChromeVersion(): string {
|
1174
1178
|
const chromeRegex = /(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/;
|
1175
1179
|
const chromeMatch = navigator.userAgent.match(chromeRegex);
|
@@ -1523,6 +1527,7 @@ export namespace MultitargetNetworkManager {
|
|
1523
1527
|
InterceptorsChanged = 'InterceptorsChanged',
|
1524
1528
|
AcceptedEncodingsChanged = 'AcceptedEncodingsChanged',
|
1525
1529
|
RequestIntercepted = 'RequestIntercepted',
|
1530
|
+
RequestFulfilled = 'RequestFulfilled',
|
1526
1531
|
}
|
1527
1532
|
|
1528
1533
|
export type EventTypes = {
|
@@ -1532,6 +1537,7 @@ export namespace MultitargetNetworkManager {
|
|
1532
1537
|
[Events.InterceptorsChanged]: void,
|
1533
1538
|
[Events.AcceptedEncodingsChanged]: void,
|
1534
1539
|
[Events.RequestIntercepted]: Platform.DevToolsPath.UrlString,
|
1540
|
+
[Events.RequestFulfilled]: Platform.DevToolsPath.UrlString,
|
1535
1541
|
};
|
1536
1542
|
}
|
1537
1543
|
|
@@ -1565,11 +1571,15 @@ export class InterceptedRequest {
|
|
1565
1571
|
return this.#hasRespondedInternal;
|
1566
1572
|
}
|
1567
1573
|
|
1568
|
-
async continueRequestWithContent(
|
1569
|
-
|
1574
|
+
async continueRequestWithContent(
|
1575
|
+
contentBlob: Blob, encoded: boolean, responseHeaders: Protocol.Fetch.HeaderEntry[],
|
1576
|
+
isBodyOverridden: boolean): Promise<void> {
|
1570
1577
|
this.#hasRespondedInternal = true;
|
1571
1578
|
const body = encoded ? await contentBlob.text() : await blobToBase64(contentBlob);
|
1572
|
-
|
1579
|
+
const responseCode = isBodyOverridden ? 200 : (this.responseStatusCode || 200);
|
1580
|
+
void this.#fetchAgent.invoke_fulfillRequest({requestId: this.requestId, responseCode, body, responseHeaders});
|
1581
|
+
MultitargetNetworkManager.instance().dispatchEventToListeners(
|
1582
|
+
MultitargetNetworkManager.Events.RequestFulfilled, this.request.url as Platform.DevToolsPath.UrlString);
|
1573
1583
|
|
1574
1584
|
async function blobToBase64(blob: Blob): Promise<string> {
|
1575
1585
|
const reader = new FileReader();
|
@@ -1608,6 +1618,10 @@ export class InterceptedRequest {
|
|
1608
1618
|
const error = response.getError() || null;
|
1609
1619
|
return {error: error, content: error ? null : response.body, encoded: response.base64Encoded};
|
1610
1620
|
}
|
1621
|
+
|
1622
|
+
isRedirect(): boolean {
|
1623
|
+
return this.responseStatusCode !== undefined && this.responseStatusCode >= 300 && this.responseStatusCode < 400;
|
1624
|
+
}
|
1611
1625
|
}
|
1612
1626
|
|
1613
1627
|
/**
|
@@ -125,7 +125,7 @@ async function invokeLH(action: string, args: any): Promise<unknown> {
|
|
125
125
|
}
|
126
126
|
|
127
127
|
// @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
|
128
|
-
const config = self.createConfig(args.categoryIDs, flags.emulatedFormFactor);
|
128
|
+
const config = args.config || self.createConfig(args.categoryIDs, flags.emulatedFormFactor);
|
129
129
|
const url = args.url;
|
130
130
|
|
131
131
|
// Handle legacy Lighthouse runner path.
|
@@ -222,25 +222,36 @@ async function fetchLocaleData(locales: string[]): Promise<string|void> {
|
|
222
222
|
*/
|
223
223
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
224
224
|
function notifyFrontendViaWorkerMessage(action: string, args: any): void {
|
225
|
-
self.postMessage(
|
225
|
+
self.postMessage({action, args});
|
226
226
|
}
|
227
227
|
|
228
228
|
async function onFrontendMessage(event: MessageEvent): Promise<void> {
|
229
|
-
const messageFromFrontend =
|
229
|
+
const messageFromFrontend = event.data;
|
230
230
|
switch (messageFromFrontend.action) {
|
231
231
|
case 'startTimespan':
|
232
232
|
case 'endTimespan':
|
233
233
|
case 'snapshot':
|
234
234
|
case 'navigation': {
|
235
235
|
const result = await invokeLH(messageFromFrontend.action, messageFromFrontend.args);
|
236
|
-
|
236
|
+
if (result && typeof result === 'object') {
|
237
|
+
// Report isn't used upstream.
|
238
|
+
if ('report' in result) {
|
239
|
+
// @ts-expect-error
|
240
|
+
delete result.report;
|
241
|
+
}
|
242
|
+
|
243
|
+
// Logger PerformanceTiming objects cannot be cloned by this worker's `postMessage` function.
|
244
|
+
if ('artifacts' in result) {
|
245
|
+
// @ts-expect-error
|
246
|
+
result.artifacts.Timing = JSON.parse(JSON.stringify(result.artifacts.Timing));
|
247
|
+
}
|
248
|
+
}
|
249
|
+
self.postMessage({id: messageFromFrontend.id, result});
|
237
250
|
break;
|
238
251
|
}
|
239
252
|
case 'dispatchProtocolMessage': {
|
240
|
-
cdpConnection?.onMessage?.(
|
241
|
-
|
242
|
-
);
|
243
|
-
legacyPort.onMessage?.(messageFromFrontend.args.message);
|
253
|
+
cdpConnection?.onMessage?.(messageFromFrontend.args.message);
|
254
|
+
legacyPort.onMessage?.(JSON.stringify(messageFromFrontend.args.message));
|
244
255
|
break;
|
245
256
|
}
|
246
257
|
default: {
|
@@ -426,10 +426,14 @@ export class MainImpl {
|
|
426
426
|
'reportingApiDebugging',
|
427
427
|
Root.Runtime.ExperimentName.SYNC_SETTINGS,
|
428
428
|
Root.Runtime.ExperimentName.CSS_LAYERS,
|
429
|
-
Root.Runtime.ExperimentName.EYEDROPPER_COLOR_PICKER,
|
429
|
+
...('EyeDropper' in window ? [Root.Runtime.ExperimentName.EYEDROPPER_COLOR_PICKER] : []),
|
430
430
|
'lighthousePanelFR',
|
431
431
|
]);
|
432
432
|
|
433
|
+
Root.Runtime.experiments.setNonConfigurableExperiments([
|
434
|
+
...(!('EyeDropper' in window) ? [Root.Runtime.ExperimentName.EYEDROPPER_COLOR_PICKER] : []),
|
435
|
+
]);
|
436
|
+
|
433
437
|
Root.Runtime.experiments.cleanUpStaleExperiments();
|
434
438
|
const enabledExperiments = Root.Runtime.Runtime.queryParam('enabledExperiments');
|
435
439
|
if (enabledExperiments) {
|
@@ -731,13 +731,17 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
|
|
731
731
|
const blob = await project.requestFileBlob(fileSystemUISourceCode);
|
732
732
|
if (blob) {
|
733
733
|
void interceptedRequest.continueRequestWithContent(
|
734
|
-
new Blob([blob], {type: mimeType}), /* encoded */ false, responseHeaders);
|
734
|
+
new Blob([blob], {type: mimeType}), /* encoded */ false, responseHeaders, /* isBodyOverridden */ true);
|
735
735
|
}
|
736
|
+
} else if (interceptedRequest.isRedirect()) {
|
737
|
+
void interceptedRequest.continueRequestWithContent(
|
738
|
+
new Blob([], {type: mimeType}), /* encoded */ true, responseHeaders, /* isBodyOverridden */ false);
|
736
739
|
} else {
|
737
740
|
const responseBody = await interceptedRequest.responseBody();
|
738
741
|
if (!responseBody.error && responseBody.content) {
|
739
742
|
void interceptedRequest.continueRequestWithContent(
|
740
|
-
new Blob([responseBody.content], {type: mimeType}), /* encoded */ true, responseHeaders
|
743
|
+
new Blob([responseBody.content], {type: mimeType}), /* encoded */ true, responseHeaders,
|
744
|
+
/* isBodyOverridden */ false);
|
741
745
|
}
|
742
746
|
}
|
743
747
|
}
|
@@ -2,11 +2,12 @@
|
|
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
4
|
|
5
|
+
import * as Host from '../../core/host/host.js';
|
5
6
|
import * as i18n from '../../core/i18n/i18n.js';
|
6
7
|
|
7
8
|
import {
|
8
|
-
|
9
|
-
|
9
|
+
buildPropertyDefinitionText,
|
10
|
+
buildPropertyText,
|
10
11
|
isFlexContainer,
|
11
12
|
isGridContainer,
|
12
13
|
isMulticolContainer,
|
@@ -58,35 +59,34 @@ const UIStrings = {
|
|
58
59
|
const str_ = i18n.i18n.registerUIStrings('panels/elements/CSSRuleValidator.ts', UIStrings);
|
59
60
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
60
61
|
|
61
|
-
export const enum
|
62
|
+
export const enum HintType {
|
62
63
|
INACTIVE_PROPERTY = 'ruleValidation',
|
63
64
|
DEPRECATED_PROPERTY = 'deprecatedProperty',
|
64
65
|
}
|
65
66
|
|
66
|
-
export class
|
67
|
-
readonly #hintType:
|
67
|
+
export class Hint {
|
68
|
+
readonly #hintType: HintType;
|
68
69
|
readonly #hintMessage: string;
|
69
70
|
readonly #possibleFixMessage: string|null;
|
70
71
|
readonly #learnMoreLink: string|undefined;
|
71
72
|
|
72
|
-
constructor(
|
73
|
-
hintType: AuthoringHintType, hintMessage: string, possibleFixMessage: string|null, learnMoreLink?: string) {
|
73
|
+
constructor(hintType: HintType, hintMessage: string, possibleFixMessage: string|null, learnMoreLink?: string) {
|
74
74
|
this.#hintType = hintType;
|
75
75
|
this.#hintMessage = hintMessage;
|
76
76
|
this.#possibleFixMessage = possibleFixMessage;
|
77
77
|
this.#learnMoreLink = learnMoreLink;
|
78
78
|
}
|
79
79
|
|
80
|
-
|
80
|
+
getPrefix(): string {
|
81
81
|
switch (this.#hintType) {
|
82
|
-
case
|
82
|
+
case HintType.INACTIVE_PROPERTY:
|
83
83
|
return i18nString(UIStrings.inactivePropertyHintPrefix);
|
84
|
-
case
|
84
|
+
case HintType.DEPRECATED_PROPERTY:
|
85
85
|
return i18nString(UIStrings.deprecatedPropertyHintPrefix);
|
86
86
|
}
|
87
87
|
}
|
88
88
|
|
89
|
-
|
89
|
+
getMessage(): string {
|
90
90
|
return this.#hintMessage;
|
91
91
|
}
|
92
92
|
|
@@ -100,25 +100,23 @@ export class AuthoringHint {
|
|
100
100
|
}
|
101
101
|
|
102
102
|
export abstract class CSSRuleValidator {
|
103
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
104
|
+
return Host.UserMetrics.CSSHintType.Other;
|
105
|
+
}
|
106
|
+
|
103
107
|
readonly #affectedProperties: string[];
|
104
108
|
|
105
109
|
constructor(affectedProperties: string[]) {
|
106
110
|
this.#affectedProperties = affectedProperties;
|
107
111
|
}
|
108
112
|
|
109
|
-
|
110
|
-
* If `isRuleValid` returns false, it means there is a hint to be shown. The hint is retrieved by invoking `getAuthoringHint`.
|
111
|
-
*/
|
112
|
-
abstract isRuleValid(computedStyles: Map<String, String>|null, parentsComputedStyles?: Map<String, String>|null):
|
113
|
-
boolean;
|
114
|
-
|
115
|
-
getAffectedProperties(): string[] {
|
113
|
+
getApplicableProperties(): string[] {
|
116
114
|
return this.#affectedProperties;
|
117
115
|
}
|
118
116
|
|
119
|
-
abstract
|
120
|
-
propertyName: string, computedStyles
|
121
|
-
|
117
|
+
abstract getHint(
|
118
|
+
propertyName: string, computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): Hint
|
119
|
+
|undefined;
|
122
120
|
}
|
123
121
|
|
124
122
|
export class AlignContentValidator extends CSSRuleValidator {
|
@@ -126,7 +124,11 @@ export class AlignContentValidator extends CSSRuleValidator {
|
|
126
124
|
super(['align-content']);
|
127
125
|
}
|
128
126
|
|
129
|
-
|
127
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
128
|
+
return Host.UserMetrics.CSSHintType.AlignContent;
|
129
|
+
}
|
130
|
+
|
131
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
130
132
|
if (computedStyles === null || computedStyles === undefined) {
|
131
133
|
return true;
|
132
134
|
}
|
@@ -136,12 +138,15 @@ export class AlignContentValidator extends CSSRuleValidator {
|
|
136
138
|
return computedStyles.get('flex-wrap') !== 'nowrap';
|
137
139
|
}
|
138
140
|
|
139
|
-
|
140
|
-
|
141
|
-
|
141
|
+
getHint(_propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
142
|
+
if (this.#isRuleValid(computedStyles)) {
|
143
|
+
return;
|
144
|
+
}
|
145
|
+
const reasonPropertyDeclaration = buildPropertyText('flex-wrap');
|
146
|
+
const affectedPropertyDeclarationCode = buildPropertyText('align-content');
|
142
147
|
|
143
|
-
return new
|
144
|
-
|
148
|
+
return new Hint(
|
149
|
+
HintType.INACTIVE_PROPERTY,
|
145
150
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
146
151
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
147
152
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -158,22 +163,28 @@ export class FlexItemValidator extends CSSRuleValidator {
|
|
158
163
|
super(['flex', 'flex-basis', 'flex-grow', 'flex-shrink']);
|
159
164
|
}
|
160
165
|
|
161
|
-
|
162
|
-
|
166
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
167
|
+
return Host.UserMetrics.CSSHintType.FlexItem;
|
168
|
+
}
|
169
|
+
|
170
|
+
#isRuleValid(computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): boolean {
|
171
|
+
if (parentComputedStyles === null) {
|
163
172
|
return true;
|
164
173
|
}
|
165
|
-
return isFlexContainer(
|
174
|
+
return isFlexContainer(parentComputedStyles);
|
166
175
|
}
|
167
176
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
const
|
177
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): Hint
|
178
|
+
|undefined {
|
179
|
+
if (this.#isRuleValid(computedStyles, parentComputedStyles)) {
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', parentComputedStyles?.get('display'));
|
183
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
184
|
+
const targeParentPropertyDeclaration = buildPropertyDefinitionText('display', 'flex');
|
174
185
|
|
175
|
-
return new
|
176
|
-
|
186
|
+
return new Hint(
|
187
|
+
HintType.INACTIVE_PROPERTY,
|
177
188
|
i18nString(UIStrings.ruleViolatedByParentElementRuleReason, {
|
178
189
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
179
190
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -191,20 +202,27 @@ export class FlexContainerValidator extends CSSRuleValidator {
|
|
191
202
|
super(['flex-direction', 'flex-flow', 'flex-wrap', 'justify-content']);
|
192
203
|
}
|
193
204
|
|
194
|
-
|
205
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
206
|
+
return Host.UserMetrics.CSSHintType.FlexContainer;
|
207
|
+
}
|
208
|
+
|
209
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
195
210
|
if (computedStyles === null) {
|
196
211
|
return true;
|
197
212
|
}
|
198
213
|
return isFlexContainer(computedStyles);
|
199
214
|
}
|
200
215
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
216
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
217
|
+
if (this.#isRuleValid(computedStyles)) {
|
218
|
+
return;
|
219
|
+
}
|
220
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', computedStyles?.get('display'));
|
221
|
+
const targetRuleCode = buildPropertyDefinitionText('display', 'flex');
|
222
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
205
223
|
|
206
|
-
return new
|
207
|
-
|
224
|
+
return new Hint(
|
225
|
+
HintType.INACTIVE_PROPERTY,
|
208
226
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
209
227
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
210
228
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -231,20 +249,24 @@ export class GridContainerValidator extends CSSRuleValidator {
|
|
231
249
|
]);
|
232
250
|
}
|
233
251
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
252
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
253
|
+
return Host.UserMetrics.CSSHintType.GridContainer;
|
254
|
+
}
|
255
|
+
|
256
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
238
257
|
return isGridContainer(computedStyles);
|
239
258
|
}
|
240
259
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
260
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
261
|
+
if (this.#isRuleValid(computedStyles)) {
|
262
|
+
return;
|
263
|
+
}
|
264
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', computedStyles?.get('display'));
|
265
|
+
const targetRuleCode = buildPropertyDefinitionText('display', 'grid');
|
266
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
245
267
|
|
246
|
-
return new
|
247
|
-
|
268
|
+
return new Hint(
|
269
|
+
HintType.INACTIVE_PROPERTY,
|
248
270
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
249
271
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
250
272
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -268,22 +290,28 @@ export class GridItemValidator extends CSSRuleValidator {
|
|
268
290
|
]);
|
269
291
|
}
|
270
292
|
|
271
|
-
|
272
|
-
|
293
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
294
|
+
return Host.UserMetrics.CSSHintType.GridItem;
|
295
|
+
}
|
296
|
+
|
297
|
+
#isRuleValid(computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): boolean {
|
298
|
+
if (!parentComputedStyles) {
|
273
299
|
return true;
|
274
300
|
}
|
275
301
|
return isGridContainer(parentComputedStyles);
|
276
302
|
}
|
277
303
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
const
|
304
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): Hint
|
305
|
+
|undefined {
|
306
|
+
if (this.#isRuleValid(computedStyles, parentComputedStyles)) {
|
307
|
+
return;
|
308
|
+
}
|
309
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', parentComputedStyles?.get('display'));
|
310
|
+
const targeParentPropertyDeclaration = buildPropertyDefinitionText('display', 'grid');
|
311
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
284
312
|
|
285
|
-
return new
|
286
|
-
|
313
|
+
return new Hint(
|
314
|
+
HintType.INACTIVE_PROPERTY,
|
287
315
|
i18nString(UIStrings.ruleViolatedByParentElementRuleReason, {
|
288
316
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
289
317
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -306,19 +334,27 @@ export class FlexGridValidator extends CSSRuleValidator {
|
|
306
334
|
]);
|
307
335
|
}
|
308
336
|
|
309
|
-
|
337
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
338
|
+
return Host.UserMetrics.CSSHintType.FlexGrid;
|
339
|
+
}
|
340
|
+
|
341
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
310
342
|
if (computedStyles === null) {
|
311
343
|
return true;
|
312
344
|
}
|
313
345
|
return isFlexContainer(computedStyles) || isGridContainer(computedStyles);
|
314
346
|
}
|
315
347
|
|
316
|
-
|
317
|
-
|
318
|
-
|
348
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
349
|
+
if (this.#isRuleValid(computedStyles)) {
|
350
|
+
return;
|
351
|
+
}
|
352
|
+
|
353
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', computedStyles?.get('display'));
|
354
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
319
355
|
|
320
|
-
return new
|
321
|
-
|
356
|
+
return new Hint(
|
357
|
+
HintType.INACTIVE_PROPERTY,
|
322
358
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
323
359
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
324
360
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -343,19 +379,27 @@ export class MulticolFlexGridValidator extends CSSRuleValidator {
|
|
343
379
|
]);
|
344
380
|
}
|
345
381
|
|
346
|
-
|
382
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
383
|
+
return Host.UserMetrics.CSSHintType.MulticolFlexGrid;
|
384
|
+
}
|
385
|
+
|
386
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
347
387
|
if (computedStyles === null) {
|
348
388
|
return true;
|
349
389
|
}
|
350
390
|
return isMulticolContainer(computedStyles) || isFlexContainer(computedStyles) || isGridContainer(computedStyles);
|
351
391
|
}
|
352
392
|
|
353
|
-
|
354
|
-
|
355
|
-
|
393
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
394
|
+
if (this.#isRuleValid(computedStyles)) {
|
395
|
+
return;
|
396
|
+
}
|
356
397
|
|
357
|
-
|
358
|
-
|
398
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', computedStyles?.get('display'));
|
399
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
400
|
+
|
401
|
+
return new Hint(
|
402
|
+
HintType.INACTIVE_PROPERTY,
|
359
403
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
360
404
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
361
405
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -378,7 +422,11 @@ export class PaddingValidator extends CSSRuleValidator {
|
|
378
422
|
]);
|
379
423
|
}
|
380
424
|
|
381
|
-
|
425
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
426
|
+
return Host.UserMetrics.CSSHintType.Padding;
|
427
|
+
}
|
428
|
+
|
429
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
382
430
|
const display = computedStyles?.get('display');
|
383
431
|
if (display === null || display === undefined) {
|
384
432
|
return true;
|
@@ -388,12 +436,16 @@ export class PaddingValidator extends CSSRuleValidator {
|
|
388
436
|
.includes(display as string);
|
389
437
|
}
|
390
438
|
|
391
|
-
|
392
|
-
|
393
|
-
|
439
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
440
|
+
if (this.#isRuleValid(computedStyles)) {
|
441
|
+
return;
|
442
|
+
}
|
443
|
+
|
444
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('display', computedStyles?.get('display'));
|
445
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
394
446
|
|
395
|
-
return new
|
396
|
-
|
447
|
+
return new Hint(
|
448
|
+
HintType.INACTIVE_PROPERTY,
|
397
449
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
398
450
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
399
451
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -415,7 +467,11 @@ export class PositionValidator extends CSSRuleValidator {
|
|
415
467
|
]);
|
416
468
|
}
|
417
469
|
|
418
|
-
|
470
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
471
|
+
return Host.UserMetrics.CSSHintType.Position;
|
472
|
+
}
|
473
|
+
|
474
|
+
#isRuleValid(computedStyles?: Map<string, string>): boolean {
|
419
475
|
const position = computedStyles?.get('position');
|
420
476
|
if (position === null || position === undefined) {
|
421
477
|
return true;
|
@@ -423,12 +479,16 @@ export class PositionValidator extends CSSRuleValidator {
|
|
423
479
|
return position !== 'static';
|
424
480
|
}
|
425
481
|
|
426
|
-
|
427
|
-
|
428
|
-
|
482
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>): Hint|undefined {
|
483
|
+
if (this.#isRuleValid(computedStyles)) {
|
484
|
+
return;
|
485
|
+
}
|
429
486
|
|
430
|
-
|
431
|
-
|
487
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('position', computedStyles?.get('position'));
|
488
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
489
|
+
|
490
|
+
return new Hint(
|
491
|
+
HintType.INACTIVE_PROPERTY,
|
432
492
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
433
493
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
434
494
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -447,21 +507,29 @@ export class ZIndexValidator extends CSSRuleValidator {
|
|
447
507
|
]);
|
448
508
|
}
|
449
509
|
|
450
|
-
|
510
|
+
getMetricType(): Host.UserMetrics.CSSHintType {
|
511
|
+
return Host.UserMetrics.CSSHintType.ZIndex;
|
512
|
+
}
|
513
|
+
|
514
|
+
#isRuleValid(computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): boolean {
|
451
515
|
const position = computedStyles?.get('position');
|
452
516
|
if (position === null || position === undefined) {
|
453
517
|
return true;
|
454
518
|
}
|
455
|
-
return ['absolute', 'relative', 'fixed', 'sticky'].includes(position
|
456
|
-
isFlexContainer(parentComputedStyles);
|
519
|
+
return ['absolute', 'relative', 'fixed', 'sticky'].includes(position) || isFlexContainer(parentComputedStyles);
|
457
520
|
}
|
458
521
|
|
459
|
-
|
460
|
-
|
461
|
-
|
522
|
+
getHint(propertyName: string, computedStyles?: Map<string, string>, parentComputedStyles?: Map<string, string>): Hint
|
523
|
+
|undefined {
|
524
|
+
if (this.#isRuleValid(computedStyles, parentComputedStyles)) {
|
525
|
+
return;
|
526
|
+
}
|
527
|
+
|
528
|
+
const reasonPropertyDeclaration = buildPropertyDefinitionText('position', computedStyles?.get('position'));
|
529
|
+
const affectedPropertyDeclarationCode = buildPropertyText(propertyName);
|
462
530
|
|
463
|
-
return new
|
464
|
-
|
531
|
+
return new Hint(
|
532
|
+
HintType.INACTIVE_PROPERTY,
|
465
533
|
i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
|
466
534
|
'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
|
467
535
|
'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
|
@@ -486,11 +554,11 @@ const CSS_RULE_VALIDATORS = [
|
|
486
554
|
ZIndexValidator,
|
487
555
|
];
|
488
556
|
|
489
|
-
const setupCSSRulesValidators = (): Map<
|
490
|
-
const validatorsMap = new Map<
|
557
|
+
const setupCSSRulesValidators = (): Map<string, CSSRuleValidator[]> => {
|
558
|
+
const validatorsMap = new Map<string, CSSRuleValidator[]>();
|
491
559
|
for (const validatorClass of CSS_RULE_VALIDATORS) {
|
492
560
|
const validator = new validatorClass();
|
493
|
-
const affectedProperties = validator.
|
561
|
+
const affectedProperties = validator.getApplicableProperties();
|
494
562
|
|
495
563
|
for (const affectedProperty of affectedProperties) {
|
496
564
|
let propertyValidators = validatorsMap.get(affectedProperty);
|
@@ -505,4 +573,4 @@ const setupCSSRulesValidators = (): Map<String, CSSRuleValidator[]> => {
|
|
505
573
|
return validatorsMap;
|
506
574
|
};
|
507
575
|
|
508
|
-
export const cssRuleValidatorsMap: Map<
|
576
|
+
export const cssRuleValidatorsMap: Map<string, CSSRuleValidator[]> = setupCSSRulesValidators();
|
@@ -2,31 +2,37 @@
|
|
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
4
|
|
5
|
-
export const
|
5
|
+
export const buildPropertyDefinitionText = (property: string, value?: string): string => {
|
6
6
|
if (value === undefined) {
|
7
|
-
return
|
7
|
+
return buildPropertyText(property);
|
8
8
|
}
|
9
9
|
return '<code class="unbreakable-text"><span class="property">' + property + '</span>: ' + value + '</code>';
|
10
10
|
};
|
11
11
|
|
12
|
-
export const
|
12
|
+
export const buildPropertyText = (property: string): string => {
|
13
13
|
return '<code class="unbreakable-text"><span class="property">' + property + '</span></code>';
|
14
14
|
};
|
15
15
|
|
16
|
-
export const isFlexContainer = (computedStyles
|
17
|
-
if (computedStyles
|
16
|
+
export const isFlexContainer = (computedStyles?: Map<string, string>): boolean => {
|
17
|
+
if (!computedStyles) {
|
18
18
|
return false;
|
19
19
|
}
|
20
20
|
const display = computedStyles.get('display');
|
21
21
|
return display === 'flex' || display === 'inline-flex';
|
22
22
|
};
|
23
23
|
|
24
|
-
export const isGridContainer = (computedStyles
|
24
|
+
export const isGridContainer = (computedStyles?: Map<string, string>): boolean => {
|
25
|
+
if (!computedStyles) {
|
26
|
+
return false;
|
27
|
+
}
|
25
28
|
const display = computedStyles.get('display');
|
26
29
|
return display === 'grid' || display === 'inline-grid';
|
27
30
|
};
|
28
31
|
|
29
|
-
export const isMulticolContainer = (computedStyles
|
32
|
+
export const isMulticolContainer = (computedStyles?: Map<string, string>): boolean => {
|
33
|
+
if (!computedStyles) {
|
34
|
+
return false;
|
35
|
+
}
|
30
36
|
const columnWidth = computedStyles.get('column-width');
|
31
37
|
const columnCount = computedStyles.get('column-count');
|
32
38
|
|
@@ -290,6 +290,14 @@ export class StylePropertiesSection {
|
|
290
290
|
this.onpopulate();
|
291
291
|
}
|
292
292
|
|
293
|
+
setComputedStyles(computedStyles: Map<string, string>|null): void {
|
294
|
+
this.computedStyles = computedStyles;
|
295
|
+
}
|
296
|
+
|
297
|
+
setParentsComputedStyles(parentsComputedStyles: Map<string, string>|null): void {
|
298
|
+
this.parentsComputedStyles = parentsComputedStyles;
|
299
|
+
}
|
300
|
+
|
293
301
|
setSectionIdx(sectionIdx: number): void {
|
294
302
|
this.sectionIdx = sectionIdx;
|
295
303
|
this.onpopulate();
|
@@ -21,12 +21,12 @@ import {StyleEditorWidget} from './StyleEditorWidget.js';
|
|
21
21
|
import {type StylePropertiesSection} from './StylePropertiesSection.js';
|
22
22
|
import {CSSPropertyPrompt, StylesSidebarPane, StylesSidebarPropertyRenderer} from './StylesSidebarPane.js';
|
23
23
|
import {getCssDeclarationAsJavascriptProperty} from './StylePropertyUtils.js';
|
24
|
-
import {cssRuleValidatorsMap, type
|
24
|
+
import {cssRuleValidatorsMap, type Hint} from './CSSRuleValidator.js';
|
25
25
|
|
26
26
|
const FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;
|
27
27
|
const GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;
|
28
28
|
|
29
|
-
export const activeHints = new WeakMap<Element,
|
29
|
+
export const activeHints = new WeakMap<Element, Hint>();
|
30
30
|
|
31
31
|
const UIStrings = {
|
32
32
|
/**
|
@@ -717,23 +717,16 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
717
717
|
}
|
718
718
|
}
|
719
719
|
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
activeHints.set(hintIcon, authoringHint);
|
725
|
-
this.listItemElement.append(hintIcon);
|
726
|
-
}
|
727
|
-
|
728
|
-
if (!this.property.parsedOk) {
|
720
|
+
if (this.property.parsedOk) {
|
721
|
+
void this.updateFontVariationSettingsWarning();
|
722
|
+
this.updateAuthoringHint();
|
723
|
+
} else {
|
729
724
|
// Avoid having longhands under an invalid shorthand.
|
730
725
|
this.listItemElement.classList.add('not-parsed-ok');
|
731
726
|
|
732
727
|
// Add a separate exclamation mark IMG element with a tooltip.
|
733
728
|
this.listItemElement.insertBefore(
|
734
729
|
StylesSidebarPane.createExclamationMark(this.property, null), this.listItemElement.firstChild);
|
735
|
-
} else {
|
736
|
-
void this.updateFontVariationSettingsWarning();
|
737
730
|
}
|
738
731
|
|
739
732
|
if (!this.property.activeInStyle()) {
|
@@ -768,6 +761,35 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
768
761
|
}
|
769
762
|
}
|
770
763
|
|
764
|
+
private updateAuthoringHint(): void {
|
765
|
+
if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CSS_AUTHORING_HINTS)) {
|
766
|
+
return;
|
767
|
+
}
|
768
|
+
|
769
|
+
const existingElement = this.listItemElement.querySelector('.hint');
|
770
|
+
if (existingElement) {
|
771
|
+
activeHints.delete(existingElement);
|
772
|
+
existingElement.parentElement?.removeChild(existingElement);
|
773
|
+
}
|
774
|
+
const propertyName = this.property.name;
|
775
|
+
|
776
|
+
if (!cssRuleValidatorsMap.has(propertyName)) {
|
777
|
+
return;
|
778
|
+
}
|
779
|
+
|
780
|
+
for (const validator of cssRuleValidatorsMap.get(propertyName) || []) {
|
781
|
+
const hint =
|
782
|
+
validator.getHint(propertyName, this.computedStyles || undefined, this.parentsComputedStyles || undefined);
|
783
|
+
if (hint) {
|
784
|
+
Host.userMetrics.cssHintShown(validator.getMetricType());
|
785
|
+
const hintIcon = UI.Icon.Icon.create('mediumicon-info', 'hint');
|
786
|
+
activeHints.set(hintIcon, hint);
|
787
|
+
this.listItemElement.append(hintIcon);
|
788
|
+
break;
|
789
|
+
}
|
790
|
+
}
|
791
|
+
}
|
792
|
+
|
771
793
|
private async updateFontVariationSettingsWarning(): Promise<void> {
|
772
794
|
if (this.property.name !== 'font-variation-settings') {
|
773
795
|
return;
|
@@ -816,24 +838,6 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
816
838
|
StylesSidebarPane.createExclamationMark(this.property, warnings.join(' ')), this.listItemElement.firstChild);
|
817
839
|
}
|
818
840
|
|
819
|
-
private getAuthoringHint(computedStyles: Map<string, string>|null, parentComputedStyles: Map<string, string>|null):
|
820
|
-
AuthoringHint|null {
|
821
|
-
const propertyName = this.property.name;
|
822
|
-
|
823
|
-
if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CSS_AUTHORING_HINTS) ||
|
824
|
-
!cssRuleValidatorsMap.has(propertyName)) {
|
825
|
-
return null;
|
826
|
-
}
|
827
|
-
|
828
|
-
for (const validator of cssRuleValidatorsMap.get(propertyName) || []) {
|
829
|
-
if (!validator.isRuleValid(computedStyles, parentComputedStyles)) {
|
830
|
-
return validator.getAuthoringHint(propertyName, this.computedStyles, this.parentsComputedStyles);
|
831
|
-
}
|
832
|
-
}
|
833
|
-
|
834
|
-
return null;
|
835
|
-
}
|
836
|
-
|
837
841
|
private mouseUp(event: MouseEvent): void {
|
838
842
|
const activeTreeElement = parentMap.get(this.parentPaneInternal);
|
839
843
|
parentMap.delete(this.parentPaneInternal);
|
@@ -218,6 +218,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
218
218
|
#urlToChangeTracker: Map<Platform.DevToolsPath.UrlString, ChangeTracker> = new Map();
|
219
219
|
#copyChangesButton?: UI.Toolbar.ToolbarButton;
|
220
220
|
#updateAbortController?: AbortController;
|
221
|
+
#updateComputedStylesAbortController?: AbortController;
|
221
222
|
|
222
223
|
static instance(): StylesSidebarPane {
|
223
224
|
if (!stylesSidebarPaneInstance) {
|
@@ -753,10 +754,12 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
753
754
|
for (const section of this.allSections()) {
|
754
755
|
section.styleSheetEdited(edit);
|
755
756
|
}
|
757
|
+
void this.refreshComputedStyles();
|
756
758
|
return;
|
757
759
|
}
|
758
760
|
|
759
761
|
if (this.userOperation || this.isEditingStyle) {
|
762
|
+
void this.refreshComputedStyles();
|
760
763
|
return;
|
761
764
|
}
|
762
765
|
|
@@ -764,6 +767,27 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
764
767
|
this.update();
|
765
768
|
}
|
766
769
|
|
770
|
+
async refreshComputedStyles(): Promise<void> {
|
771
|
+
this.#updateComputedStylesAbortController?.abort();
|
772
|
+
this.#updateAbortController = new AbortController();
|
773
|
+
const signal = this.#updateAbortController.signal;
|
774
|
+
const matchedStyles = await this.fetchMatchedCascade();
|
775
|
+
const nodeId = this.node()?.id;
|
776
|
+
const parentNodeId = matchedStyles?.getParentLayoutNodeId();
|
777
|
+
|
778
|
+
const [computedStyles, parentsComputedStyles] =
|
779
|
+
await Promise.all([this.fetchComputedStylesFor(nodeId), this.fetchComputedStylesFor(parentNodeId)]);
|
780
|
+
|
781
|
+
if (signal.aborted) {
|
782
|
+
return;
|
783
|
+
}
|
784
|
+
|
785
|
+
for (const section of this.allSections()) {
|
786
|
+
section.setComputedStyles(computedStyles);
|
787
|
+
section.setParentsComputedStyles(parentsComputedStyles);
|
788
|
+
}
|
789
|
+
}
|
790
|
+
|
767
791
|
focusedSectionIndex(): number {
|
768
792
|
let index = 0;
|
769
793
|
for (const block of this.sectionBlocks) {
|
@@ -20,10 +20,10 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
20
20
|
const {render, html, Directives} = LitHtml;
|
21
21
|
|
22
22
|
interface Hint {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
getPrefix(): string;
|
24
|
+
getMessage(): string;
|
25
|
+
getPossibleFixMessage(): string|null;
|
26
|
+
getLearnMoreLink(): string|undefined;
|
27
27
|
}
|
28
28
|
|
29
29
|
export class CSSHintDetailsView extends HTMLElement {
|
@@ -44,7 +44,7 @@ export class CSSHintDetailsView extends HTMLElement {
|
|
44
44
|
render(html`
|
45
45
|
<div class="hint-popup-wrapper">
|
46
46
|
<div class="hint-popup-reason">
|
47
|
-
<strong>${this.#authoringHint.
|
47
|
+
<strong>${this.#authoringHint.getPrefix()}:</strong> ${Directives.unsafeHTML(this.#authoringHint.getMessage())}
|
48
48
|
</div>
|
49
49
|
${this.#authoringHint.getPossibleFixMessage() ? html`
|
50
50
|
<div class="hint-popup-possible-fix">
|
@@ -267,7 +267,7 @@ export class LayoutPane extends HTMLElement {
|
|
267
267
|
} as NodeText.NodeText.NodeTextData}></${NodeText.NodeText.NodeText.litTagName}>
|
268
268
|
</span>
|
269
269
|
</label>
|
270
|
-
<label @keyup=${onColorLabelKeyUp} @keydown=${onColorLabelKeyDown} tabindex="0" title=${i18nString(UIStrings.chooseElementOverlayColor)} class="color-picker-label" style="background: ${element.color};">
|
270
|
+
<label @keyup=${onColorLabelKeyUp} @keydown=${onColorLabelKeyDown} tabindex="0" title=${i18nString(UIStrings.chooseElementOverlayColor)} aria-label=${i18nString(UIStrings.chooseElementOverlayColor)} class="color-picker-label" style="background: ${element.color};">
|
271
271
|
<input @change=${onColorChange} @input=${onColorChange} tabindex="-1" class="color-picker" type="color" value=${element.color} />
|
272
272
|
</label>
|
273
273
|
<button tabindex="0" @click=${onElementClick} title=${i18nString(UIStrings.showElementInTheElementsPanel)} class="show-element"></button>
|
@@ -63,6 +63,7 @@ export class ProtocolService {
|
|
63
63
|
private parallelConnection?: ProtocolClient.InspectorBackend.Connection;
|
64
64
|
private lighthouseWorkerPromise?: Promise<Worker>;
|
65
65
|
private lighthouseMessageUpdateCallback?: ((arg0: string) => void);
|
66
|
+
private configForTesting?: Object;
|
66
67
|
|
67
68
|
async attach(): Promise<void> {
|
68
69
|
await SDK.TargetManager.TargetManager.instance().suspendAllTargets();
|
@@ -113,6 +114,7 @@ export class ProtocolService {
|
|
113
114
|
url: inspectedURL,
|
114
115
|
categoryIDs,
|
115
116
|
flags,
|
117
|
+
config: this.configForTesting,
|
116
118
|
locales: this.getLocales(),
|
117
119
|
target: this.targetInfo,
|
118
120
|
});
|
@@ -134,6 +136,7 @@ export class ProtocolService {
|
|
134
136
|
url: inspectedURL,
|
135
137
|
categoryIDs,
|
136
138
|
flags,
|
139
|
+
config: this.configForTesting,
|
137
140
|
locales: this.getLocales(),
|
138
141
|
target: this.targetInfo,
|
139
142
|
});
|
@@ -178,7 +181,7 @@ export class ProtocolService {
|
|
178
181
|
method?: string,
|
179
182
|
};
|
180
183
|
if (protocolMessage.sessionId || (protocolMessage.method && protocolMessage.method.startsWith('Target'))) {
|
181
|
-
void this.send('dispatchProtocolMessage', {message
|
184
|
+
void this.send('dispatchProtocolMessage', {message});
|
182
185
|
}
|
183
186
|
}
|
184
187
|
|
@@ -215,7 +218,7 @@ export class ProtocolService {
|
|
215
218
|
}
|
216
219
|
|
217
220
|
private onWorkerMessage(event: MessageEvent): void {
|
218
|
-
const lighthouseMessage =
|
221
|
+
const lighthouseMessage = event.data;
|
219
222
|
|
220
223
|
if (lighthouseMessage.action === 'statusUpdate') {
|
221
224
|
if (this.lighthouseMessageUpdateCallback && lighthouseMessage.args && 'message' in lighthouseMessage.args) {
|
@@ -237,17 +240,17 @@ export class ProtocolService {
|
|
237
240
|
private async send(action: string, args: {[x: string]: string|string[]|Object} = {}): Promise<void> {
|
238
241
|
const worker = await this.ensureWorkerExists();
|
239
242
|
const messageId = lastId++;
|
240
|
-
worker.postMessage(
|
243
|
+
worker.postMessage({id: messageId, action, args: {...args, id: messageId}});
|
241
244
|
}
|
242
245
|
|
243
246
|
/** sendWithResponse currently only handles the original startLighthouse request and LHR-filled response. */
|
244
|
-
private async sendWithResponse(action: string, args: {[x: string]: string|string[]|Object} = {}):
|
247
|
+
private async sendWithResponse(action: string, args: {[x: string]: string|string[]|Object|undefined} = {}):
|
245
248
|
Promise<ReportRenderer.RunnerResult> {
|
246
249
|
const worker = await this.ensureWorkerExists();
|
247
250
|
const messageId = lastId++;
|
248
251
|
const messageResult = new Promise<ReportRenderer.RunnerResult>(resolve => {
|
249
252
|
const workerListener = (event: MessageEvent): void => {
|
250
|
-
const lighthouseMessage =
|
253
|
+
const lighthouseMessage = event.data;
|
251
254
|
|
252
255
|
if (lighthouseMessage.id === messageId) {
|
253
256
|
worker.removeEventListener('message', workerListener);
|
@@ -256,7 +259,7 @@ export class ProtocolService {
|
|
256
259
|
};
|
257
260
|
worker.addEventListener('message', workerListener);
|
258
261
|
});
|
259
|
-
worker.postMessage(
|
262
|
+
worker.postMessage({id: messageId, action, args: {...args, id: messageId}});
|
260
263
|
|
261
264
|
return messageResult;
|
262
265
|
}
|
package/package.json
CHANGED