chrome-devtools-frontend 1.0.1007846 → 1.0.1008735
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/config/gni/devtools_grd_files.gni +0 -1
- package/front_end/core/common/ParsedURL.ts +9 -1
- package/front_end/core/i18n/locales/en-US.json +0 -3
- package/front_end/core/i18n/locales/en-XL.json +0 -3
- package/front_end/generated/InspectorBackendCommands.js +2 -2
- package/front_end/generated/protocol.ts +2 -1
- package/front_end/legacy_test_runner/elements_test_runner/ElementsTestRunner.js +8 -8
- package/front_end/models/issues_manager/DeprecationIssue.ts +0 -14
- package/front_end/panels/elements/ComputedStyleWidget.ts +190 -221
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/components/ComputedStyleProperty.ts +14 -2
- package/front_end/panels/elements/components/ComputedStyleTrace.ts +4 -1
- package/front_end/panels/elements/components/computedStyleProperty.css +15 -6
- package/front_end/panels/elements/components/computedStyleTrace.css +12 -1
- package/front_end/panels/elements/computedStyleSidebarPane.css +0 -5
- package/front_end/panels/lighthouse/LighthouseController.ts +1 -1
- package/front_end/ui/components/docs/computed_style_property/basic.ts +12 -10
- package/front_end/ui/components/docs/computed_style_property/traceable.ts +13 -10
- package/front_end/ui/components/tree_outline/TreeOutline.ts +4 -0
- package/front_end/ui/components/tree_outline/treeOutline.css +6 -1
- package/package.json +1 -1
- package/front_end/panels/elements/computedStyleWidgetTree.css +0 -66
@@ -984,7 +984,6 @@ grd_files_debug_sources = [
|
|
984
984
|
"front_end/panels/elements/components/queryContainer.css.js",
|
985
985
|
"front_end/panels/elements/components/stylePropertyEditor.css.js",
|
986
986
|
"front_end/panels/elements/computedStyleSidebarPane.css.js",
|
987
|
-
"front_end/panels/elements/computedStyleWidgetTree.css.js",
|
988
987
|
"front_end/panels/elements/domLinkifier.css.js",
|
989
988
|
"front_end/panels/elements/elementStatePaneWidget.css.js",
|
990
989
|
"front_end/panels/elements/elementsPanel.css.js",
|
@@ -470,8 +470,16 @@ export class ParsedURL {
|
|
470
470
|
return ParsedURL.substring(url as Platform.DevToolsPath.UrlString, 0, wasmFunctionIndex);
|
471
471
|
}
|
472
472
|
|
473
|
+
private static beginsWithWindowsDriveLetter(url: string): boolean {
|
474
|
+
return /^[A-Za-z]:/.test(url);
|
475
|
+
}
|
476
|
+
|
477
|
+
private static beginsWithScheme(url: string): boolean {
|
478
|
+
return /^[A-Za-z][A-Za-z0-9+.-]*:/.test(url);
|
479
|
+
}
|
480
|
+
|
473
481
|
static isRelativeURL(url: string): boolean {
|
474
|
-
return !(
|
482
|
+
return !this.beginsWithScheme(url) || this.beginsWithWindowsDriveLetter(url);
|
475
483
|
}
|
476
484
|
|
477
485
|
get displayName(): string {
|
@@ -1469,9 +1469,6 @@
|
|
1469
1469
|
"models/issues_manager/DeprecationIssue.ts | rtcpMuxPolicyNegotiate": {
|
1470
1470
|
"message": "The rtcpMuxPolicy option is deprecated and will be removed."
|
1471
1471
|
},
|
1472
|
-
"models/issues_manager/DeprecationIssue.ts | rtpDataChannel": {
|
1473
|
-
"message": "RTP data channels are no longer supported. The RtpDataChannels constraint is currently ignored, and may cause an error at a later date."
|
1474
|
-
},
|
1475
1472
|
"models/issues_manager/DeprecationIssue.ts | sharedArrayBufferConstructedWithoutIsolation": {
|
1476
1473
|
"message": "SharedArrayBuffer will require cross-origin isolation. See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details."
|
1477
1474
|
},
|
@@ -1469,9 +1469,6 @@
|
|
1469
1469
|
"models/issues_manager/DeprecationIssue.ts | rtcpMuxPolicyNegotiate": {
|
1470
1470
|
"message": "T̂h́ê rtcpMuxPolicy óp̂t́îón̂ íŝ d́êṕr̂éĉát̂éd̂ án̂d́ ŵíl̂ĺ b̂é r̂ém̂óv̂éd̂."
|
1471
1471
|
},
|
1472
|
-
"models/issues_manager/DeprecationIssue.ts | rtpDataChannel": {
|
1473
|
-
"message": "RTP data channels âŕê ńô ĺôńĝér̂ śûṕp̂ór̂t́êd́. T̂h́ê RtpDataChannels ćôńŝt́r̂áîńt̂ íŝ ćûŕr̂én̂t́l̂ý îǵn̂ór̂éd̂, án̂d́ m̂áŷ ćâúŝé âń êŕr̂ór̂ át̂ á l̂át̂ér̂ d́ât́ê."
|
1474
|
-
},
|
1475
1472
|
"models/issues_manager/DeprecationIssue.ts | sharedArrayBufferConstructedWithoutIsolation": {
|
1476
1473
|
"message": "SharedArrayBuffer ŵíl̂ĺ r̂éq̂úîŕê ćr̂óŝś-ôŕîǵîń îśôĺât́îón̂. Śêé ĥt́t̂ṕŝ://d́êv́êĺôṕêŕ.ĉh́r̂óm̂é.ĉóm̂/b́l̂óĝ/én̂áb̂ĺîńĝ-śĥár̂éd̂-ár̂ŕâý-b̂úf̂f́êŕ/ f̂ór̂ ḿôŕê d́êt́âíl̂ś."
|
1477
1474
|
},
|
@@ -315,7 +315,6 @@ export function registerCommands(inspectorBackend) {
|
|
315
315
|
'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
|
316
316
|
RTCPeerConnectionSdpSemanticsPlanB: 'RTCPeerConnectionSdpSemanticsPlanB',
|
317
317
|
RtcpMuxPolicyNegotiate: 'RtcpMuxPolicyNegotiate',
|
318
|
-
RTPDataChannel: 'RTPDataChannel',
|
319
318
|
SharedArrayBufferConstructedWithoutIsolation: 'SharedArrayBufferConstructedWithoutIsolation',
|
320
319
|
TextToSpeech_DisallowedByAutoplay: 'TextToSpeech_DisallowedByAutoplay',
|
321
320
|
V8SharedArrayBufferConstructedInExtensionWithoutIsolation:
|
@@ -2380,7 +2379,8 @@ export function registerCommands(inspectorBackend) {
|
|
2380
2379
|
inspectorBackend.registerEnum(
|
2381
2380
|
'Page.FileChooserOpenedEventMode', {SelectSingle: 'selectSingle', SelectMultiple: 'selectMultiple'});
|
2382
2381
|
inspectorBackend.registerEvent('Page.fileChooserOpened', ['frameId', 'backendNodeId', 'mode']);
|
2383
|
-
inspectorBackend.registerEvent(
|
2382
|
+
inspectorBackend.registerEvent(
|
2383
|
+
'Page.frameAttached', ['frameId', 'parentFrameId', 'stack', 'adScriptId', 'debuggerId']);
|
2384
2384
|
inspectorBackend.registerEvent('Page.frameClearedScheduledNavigation', ['frameId']);
|
2385
2385
|
inspectorBackend.registerEnum('Page.FrameDetachedEventReason', {Remove: 'remove', Swap: 'swap'});
|
2386
2386
|
inspectorBackend.registerEvent('Page.frameDetached', ['frameId', 'reason']);
|
@@ -1062,7 +1062,6 @@ export namespace Audits {
|
|
1062
1062
|
'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
|
1063
1063
|
RTCPeerConnectionSdpSemanticsPlanB = 'RTCPeerConnectionSdpSemanticsPlanB',
|
1064
1064
|
RtcpMuxPolicyNegotiate = 'RtcpMuxPolicyNegotiate',
|
1065
|
-
RTPDataChannel = 'RTPDataChannel',
|
1066
1065
|
SharedArrayBufferConstructedWithoutIsolation = 'SharedArrayBufferConstructedWithoutIsolation',
|
1067
1066
|
TextToSpeech_DisallowedByAutoplay = 'TextToSpeech_DisallowedByAutoplay',
|
1068
1067
|
V8SharedArrayBufferConstructedInExtensionWithoutIsolation =
|
@@ -11765,6 +11764,8 @@ export namespace Page {
|
|
11765
11764
|
* JavaScript stack trace of when frame was attached, only set if frame initiated from script.
|
11766
11765
|
*/
|
11767
11766
|
stack?: Runtime.StackTrace;
|
11767
|
+
adScriptId?: Runtime.ScriptId;
|
11768
|
+
debuggerId?: Runtime.UniqueDebuggerId;
|
11768
11769
|
}
|
11769
11770
|
|
11770
11771
|
/**
|
@@ -183,20 +183,20 @@ ElementsTestRunner.computedStyleWidget = function() {
|
|
183
183
|
|
184
184
|
ElementsTestRunner.dumpComputedStyle = async function(doNotAutoExpand, printInnerText) {
|
185
185
|
const computed = ElementsTestRunner.computedStyleWidget();
|
186
|
-
const treeOutline = computed.propertiesOutline;
|
187
|
-
const children = treeOutline.
|
186
|
+
const treeOutline = computed.propertiesOutline.querySelector('devtools-tree-outline');
|
187
|
+
const children = treeOutline.shadowRoot.querySelector('[role="treeitem"]');
|
188
188
|
|
189
189
|
for (const treeElement of children) {
|
190
|
-
const property =
|
191
|
-
|
190
|
+
const property = treeElement.querySelector('devtools-computed-style-property')?.shadowRoot;
|
191
|
+
const propertyName = text(property?.querySelector('.webkit-css-property'));
|
192
|
+
const propertyValue = text(property?.querySelector('.value'));
|
193
|
+
if (!property || propertyName === 'width' || propertyName === 'height') {
|
192
194
|
continue;
|
193
195
|
}
|
194
196
|
|
195
|
-
const propertyName = text(treeElement.title.querySelector('.webkit-css-property'));
|
196
|
-
const propertyValue = text(treeElement.title.querySelector('.value'));
|
197
197
|
TestRunner.addResult(`${propertyName}: ${propertyValue};`);
|
198
198
|
|
199
|
-
if (doNotAutoExpand && !treeElement.
|
199
|
+
if (doNotAutoExpand && !treeElement.ariaExpanded) {
|
200
200
|
continue;
|
201
201
|
}
|
202
202
|
|
@@ -211,7 +211,7 @@ ElementsTestRunner.dumpComputedStyle = async function(doNotAutoExpand, printInne
|
|
211
211
|
dumpText += text(trace.querySelector('.value'));
|
212
212
|
dumpText += ' - ';
|
213
213
|
dumpText += text(trace.shadowRoot.querySelector('.trace-selector'));
|
214
|
-
const link = trace.querySelector('
|
214
|
+
const link = trace.shadowRoot.querySelector('.trace-link');
|
215
215
|
|
216
216
|
if (link) {
|
217
217
|
dumpText += ' ' + await extractLinkText(link);
|
@@ -243,16 +243,6 @@ const UIStrings = {
|
|
243
243
|
* `RTCP MUX` policy.
|
244
244
|
*/
|
245
245
|
rtcpMuxPolicyNegotiate: 'The `rtcpMuxPolicy` option is deprecated and will be removed.',
|
246
|
-
/**
|
247
|
-
* @description A deprecation warning shown in the DevTools Issues tab.
|
248
|
-
* It's shown when a video conferencing website attempts to turn on or
|
249
|
-
* off a feature that has been removed, `RTP data channels`.
|
250
|
-
* `RTP data channels` are used to send and receive arbitrary data,
|
251
|
-
* but have been removed in favor of standardized versions of
|
252
|
-
* `data channels`: `SCTP data channels`.
|
253
|
-
*/
|
254
|
-
rtpDataChannel:
|
255
|
-
'`RTP data channels` are no longer supported. The `RtpDataChannels` constraint is currently ignored, and may cause an error at a later date.',
|
256
246
|
/**
|
257
247
|
* @description TODO(crbug.com/1318878): Description needed for translation
|
258
248
|
*/
|
@@ -500,10 +490,6 @@ export class DeprecationIssue extends Issue {
|
|
500
490
|
feature = 5654810086866944;
|
501
491
|
milestone = 62;
|
502
492
|
break;
|
503
|
-
case Protocol.Audits.DeprecationIssueType.RTPDataChannel:
|
504
|
-
messageFunction = i18nLazyString(UIStrings.rtpDataChannel);
|
505
|
-
milestone = 88;
|
506
|
-
break;
|
507
493
|
case Protocol.Audits.DeprecationIssueType.SharedArrayBufferConstructedWithoutIsolation:
|
508
494
|
messageFunction = i18nLazyString(UIStrings.sharedArrayBufferConstructedWithoutIsolation);
|
509
495
|
milestone = 106;
|
@@ -38,9 +38,9 @@ import * as SDK from '../../core/sdk/sdk.js';
|
|
38
38
|
import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
|
39
39
|
import * as Components from '../../ui/legacy/components/utils/utils.js';
|
40
40
|
import * as UI from '../../ui/legacy/legacy.js';
|
41
|
+
|
41
42
|
import * as ElementsComponents from './components/components.js';
|
42
43
|
import computedStyleSidebarPaneStyles from './computedStyleSidebarPane.css.js';
|
43
|
-
import computedStyleWidgetTreeStyles from './computedStyleWidgetTree.css.js';
|
44
44
|
|
45
45
|
import type {ComputedStyle} from './ComputedStyleModel.js';
|
46
46
|
import {ComputedStyleModel, Events} from './ComputedStyleModel.js';
|
@@ -49,7 +49,9 @@ import {PlatformFontsWidget} from './PlatformFontsWidget.js';
|
|
49
49
|
import type {Category} from './PropertyNameCategories.js';
|
50
50
|
import {categorizePropertyName, DefaultCategoryOrder} from './PropertyNameCategories.js';
|
51
51
|
import {StylePropertiesSection} from './StylePropertiesSection.js';
|
52
|
-
import {
|
52
|
+
import {StylesSidebarPane, StylesSidebarPropertyRenderer} from './StylesSidebarPane.js';
|
53
|
+
import * as TreeOutline from '../../ui/components/tree_outline/tree_outline.js';
|
54
|
+
import * as LitHtml from '../../ui/lit-html/lit-html.js';
|
53
55
|
|
54
56
|
const UIStrings = {
|
55
57
|
/**
|
@@ -92,23 +94,24 @@ const UIStrings = {
|
|
92
94
|
const str_ = i18n.i18n.registerUIStrings('panels/elements/ComputedStyleWidget.ts', UIStrings);
|
93
95
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
94
96
|
|
95
|
-
const createPropertyElement =
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
const renderer = new StylesSidebarPropertyRenderer(null, node, propertyName, propertyValue);
|
100
|
-
renderer.setColorHandler(processColor);
|
97
|
+
const createPropertyElement =
|
98
|
+
(node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string, traceable: boolean, inherited: boolean,
|
99
|
+
onNavigateToSource: ((event?: Event) => void)): ElementsComponents.ComputedStyleProperty.ComputedStyleProperty => {
|
100
|
+
const propertyElement = new ElementsComponents.ComputedStyleProperty.ComputedStyleProperty();
|
101
101
|
|
102
|
-
|
103
|
-
|
104
|
-
propertyElement.appendChild(propertyNameElement);
|
102
|
+
const renderer = new StylesSidebarPropertyRenderer(null, node, propertyName, propertyValue);
|
103
|
+
renderer.setColorHandler(processColor);
|
105
104
|
|
106
|
-
|
107
|
-
|
108
|
-
|
105
|
+
propertyElement.data = {
|
106
|
+
propertyNameRenderer: renderer.renderName.bind(renderer),
|
107
|
+
propertyValueRenderer: renderer.renderValue.bind(renderer),
|
108
|
+
traceable,
|
109
|
+
inherited,
|
110
|
+
onNavigateToSource,
|
111
|
+
};
|
109
112
|
|
110
|
-
|
111
|
-
};
|
113
|
+
return propertyElement;
|
114
|
+
};
|
112
115
|
|
113
116
|
const createTraceElement =
|
114
117
|
(node: SDK.DOMModel.DOMNode, property: SDK.CSSProperty.CSSProperty, isPropertyOverloaded: boolean,
|
@@ -123,16 +126,15 @@ const createTraceElement =
|
|
123
126
|
trace.appendChild(valueElement);
|
124
127
|
|
125
128
|
const rule = (property.ownerStyle.parentRule as SDK.CSSRule.CSSStyleRule | null);
|
129
|
+
let ruleOriginNode;
|
126
130
|
if (rule) {
|
127
|
-
|
128
|
-
linkSpan.appendChild(StylePropertiesSection.createRuleOriginNode(matchedStyles, linkifier, rule));
|
129
|
-
linkSpan.slot = 'trace-link';
|
130
|
-
trace.appendChild(linkSpan);
|
131
|
+
ruleOriginNode = StylePropertiesSection.createRuleOriginNode(matchedStyles, linkifier, rule);
|
131
132
|
}
|
132
133
|
trace.data = {
|
133
134
|
selector: rule ? rule.selectorText() : 'element.style',
|
134
135
|
active: !isPropertyOverloaded,
|
135
|
-
onNavigateToSource:
|
136
|
+
onNavigateToSource: navigateToSource.bind(null, property),
|
137
|
+
ruleOriginNode,
|
136
138
|
};
|
137
139
|
|
138
140
|
return trace;
|
@@ -154,7 +156,10 @@ const processColor = (text: string): Node => {
|
|
154
156
|
return swatch;
|
155
157
|
};
|
156
158
|
|
157
|
-
const navigateToSource = (cssProperty: SDK.CSSProperty.CSSProperty, event
|
159
|
+
const navigateToSource = (cssProperty: SDK.CSSProperty.CSSProperty, event?: Event): void => {
|
160
|
+
if (!event) {
|
161
|
+
return;
|
162
|
+
}
|
158
163
|
void Common.Revealer.reveal(cssProperty);
|
159
164
|
event.consume(true);
|
160
165
|
};
|
@@ -171,6 +176,20 @@ const propertySorter = (propA: string, propB: string): number => {
|
|
171
176
|
return Platform.StringUtilities.compare(canonicalA, canonicalB);
|
172
177
|
};
|
173
178
|
|
179
|
+
type ComputedStyleData = {
|
180
|
+
tag: 'property',
|
181
|
+
propertyName: string,
|
182
|
+
propertyValue: string,
|
183
|
+
inherited: boolean,
|
184
|
+
}|{
|
185
|
+
tag: 'traceElement',
|
186
|
+
property: SDK.CSSProperty.CSSProperty,
|
187
|
+
rule: SDK.CSSRule.CSSRule | null,
|
188
|
+
}|{
|
189
|
+
tag: 'category',
|
190
|
+
name: string,
|
191
|
+
};
|
192
|
+
|
174
193
|
export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
175
194
|
private computedStyleModel: ComputedStyleModel;
|
176
195
|
private readonly showInheritedComputedStylePropertiesSetting: Common.Settings.Setting<boolean>;
|
@@ -178,17 +197,11 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
178
197
|
input: Element;
|
179
198
|
private filterRegex: RegExp|null;
|
180
199
|
private readonly noMatchesElement: HTMLElement;
|
181
|
-
private propertiesOutline: UI.TreeOutline.TreeOutlineInShadow;
|
182
|
-
private readonly propertyByTreeElement: WeakMap<UI.TreeOutline.TreeElement, {
|
183
|
-
name: string,
|
184
|
-
value: string,
|
185
|
-
}>;
|
186
|
-
private readonly categoryByTreeElement: WeakMap<UI.TreeOutline.TreeElement, Category>;
|
187
|
-
private readonly expandedProperties: Set<string>;
|
188
|
-
private readonly expandedGroups: Set<Category>;
|
189
200
|
private readonly linkifier: Components.Linkifier.Linkifier;
|
190
201
|
private readonly imagePreviewPopover: ImagePreviewPopover;
|
191
|
-
|
202
|
+
|
203
|
+
#computedStylesTree = new TreeOutline.TreeOutline.TreeOutline<ComputedStyleData>();
|
204
|
+
#treeData?: TreeOutline.TreeOutline.TreeOutlineData<ComputedStyleData>;
|
192
205
|
|
193
206
|
constructor() {
|
194
207
|
super(true);
|
@@ -223,20 +236,7 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
223
236
|
this.noMatchesElement = this.contentElement.createChild('div', 'gray-info-message');
|
224
237
|
this.noMatchesElement.textContent = i18nString(UIStrings.noMatchingProperty);
|
225
238
|
|
226
|
-
this.
|
227
|
-
this.propertiesOutline.hideOverflow();
|
228
|
-
this.propertiesOutline.setShowSelectionOnKeyboardFocus(true);
|
229
|
-
this.propertiesOutline.setFocusable(true);
|
230
|
-
this.propertiesOutline.element.classList.add('monospace', 'computed-properties');
|
231
|
-
this.propertiesOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, this.onTreeElementToggled, this);
|
232
|
-
this.propertiesOutline.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this.onTreeElementToggled, this);
|
233
|
-
this.contentElement.appendChild(this.propertiesOutline.element);
|
234
|
-
|
235
|
-
this.propertyByTreeElement = new WeakMap();
|
236
|
-
this.categoryByTreeElement = new WeakMap();
|
237
|
-
|
238
|
-
this.expandedProperties = new Set();
|
239
|
-
this.expandedGroups = new Set(DefaultCategoryOrder);
|
239
|
+
this.contentElement.appendChild(this.#computedStylesTree);
|
240
240
|
|
241
241
|
this.linkifier = new Components.Linkifier.Linkifier(_maxLinkLength);
|
242
242
|
|
@@ -251,13 +251,12 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
251
251
|
const fontsWidget = new PlatformFontsWidget(this.computedStyleModel);
|
252
252
|
fontsWidget.show(this.contentElement);
|
253
253
|
|
254
|
-
this.idleCallbackManager = new IdleCallbackManager();
|
255
254
|
Common.Settings.Settings.instance().moduleSetting('colorFormat').addChangeListener(this.update.bind(this));
|
256
255
|
}
|
257
256
|
|
258
257
|
onResize(): void {
|
259
258
|
const isNarrow = this.contentElement.offsetWidth < 260;
|
260
|
-
this.
|
259
|
+
this.#computedStylesTree.classList.toggle('computed-narrow', isNarrow);
|
261
260
|
}
|
262
261
|
|
263
262
|
private showInheritedComputedStyleChanged(): void {
|
@@ -265,25 +264,22 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
265
264
|
}
|
266
265
|
|
267
266
|
update(): void {
|
268
|
-
if (this.idleCallbackManager) {
|
269
|
-
this.idleCallbackManager.discard();
|
270
|
-
}
|
271
|
-
this.idleCallbackManager = new IdleCallbackManager();
|
272
267
|
super.update();
|
273
268
|
}
|
274
269
|
|
275
270
|
wasShown(): void {
|
276
271
|
super.wasShown();
|
277
272
|
this.registerCSSFiles([computedStyleSidebarPaneStyles]);
|
278
|
-
this.propertiesOutline.registerCSSFiles([computedStyleWidgetTreeStyles]);
|
279
273
|
}
|
280
274
|
|
281
275
|
async doUpdate(): Promise<void> {
|
282
276
|
const [nodeStyles, matchedStyles] =
|
283
277
|
await Promise.all([this.computedStyleModel.fetchComputedStyle(), this.fetchMatchedCascade()]);
|
278
|
+
if (!nodeStyles || !matchedStyles) {
|
279
|
+
this.noMatchesElement.classList.remove('hidden');
|
280
|
+
return;
|
281
|
+
}
|
284
282
|
const shouldGroupComputedStyles = this.groupComputedStylesSetting.get();
|
285
|
-
this.propertiesOutline.contentElement.classList.toggle('grouped-list', shouldGroupComputedStyles);
|
286
|
-
this.propertiesOutline.contentElement.classList.toggle('alphabetical-list', !shouldGroupComputedStyles);
|
287
283
|
if (shouldGroupComputedStyles) {
|
288
284
|
await this.rebuildGroupedList(nodeStyles, matchedStyles);
|
289
285
|
} else {
|
@@ -310,15 +306,12 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
310
306
|
}
|
311
307
|
}
|
312
308
|
|
313
|
-
private async rebuildAlphabeticalList(
|
314
|
-
|
315
|
-
const hadFocus = this.propertiesOutline.element.hasFocus();
|
309
|
+
private async rebuildAlphabeticalList(nodeStyle: ComputedStyle, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):
|
310
|
+
Promise<void> {
|
316
311
|
this.imagePreviewPopover.hide();
|
317
|
-
this.propertiesOutline.removeChildren();
|
318
312
|
this.linkifier.reset();
|
319
313
|
const cssModel = this.computedStyleModel.cssModel();
|
320
|
-
if (!
|
321
|
-
this.noMatchesElement.classList.remove('hidden');
|
314
|
+
if (!cssModel) {
|
322
315
|
return;
|
323
316
|
}
|
324
317
|
|
@@ -329,8 +322,7 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
329
322
|
const propertyTraces = this.computePropertyTraces(matchedStyles);
|
330
323
|
const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);
|
331
324
|
const showInherited = this.showInheritedComputedStylePropertiesSetting.get();
|
332
|
-
const
|
333
|
-
// filter and preprocess properties to line up in the computed style queue
|
325
|
+
const tree: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
|
334
326
|
for (const propertyName of uniqueProperties) {
|
335
327
|
const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';
|
336
328
|
const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);
|
@@ -344,45 +336,21 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
344
336
|
if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {
|
345
337
|
continue;
|
346
338
|
}
|
347
|
-
|
339
|
+
tree.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));
|
348
340
|
}
|
349
341
|
|
350
|
-
this.
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
const batchSize = 20;
|
358
|
-
const timeoutInterval = 100;
|
359
|
-
let timeout = 100;
|
360
|
-
while (computedStyleQueue.length > 0) {
|
361
|
-
const currentBatch = computedStyleQueue.splice(0, batchSize);
|
362
|
-
|
363
|
-
this.idleCallbackManager.schedule(() => {
|
364
|
-
for (const {propertyName, propertyValue, isInherited} of currentBatch) {
|
365
|
-
const treeElement = this.buildPropertyTreeElement(
|
366
|
-
propertyTraces, node, (matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles), propertyName,
|
367
|
-
propertyValue, isInherited, hadFocus);
|
368
|
-
this.propertiesOutline.appendChild(treeElement);
|
369
|
-
}
|
370
|
-
|
371
|
-
this.filterAlphabeticalList();
|
372
|
-
}, timeout);
|
373
|
-
|
374
|
-
timeout += timeoutInterval;
|
375
|
-
}
|
376
|
-
|
377
|
-
await this.idleCallbackManager.awaitDone();
|
378
|
-
this.propertiesOutline.contentElement.classList.remove('render-flash');
|
342
|
+
const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);
|
343
|
+
this.#treeData = {
|
344
|
+
tree,
|
345
|
+
compact: true,
|
346
|
+
defaultRenderer,
|
347
|
+
};
|
348
|
+
this.filterAlphabeticalList();
|
379
349
|
}
|
380
350
|
|
381
351
|
private async rebuildGroupedList(
|
382
352
|
nodeStyle: ComputedStyle|null, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise<void> {
|
383
|
-
const hadFocus = this.propertiesOutline.element.hasFocus();
|
384
353
|
this.imagePreviewPopover.hide();
|
385
|
-
this.propertiesOutline.removeChildren();
|
386
354
|
this.linkifier.reset();
|
387
355
|
const cssModel = this.computedStyleModel.cssModel();
|
388
356
|
if (!nodeStyle || !matchedStyles || !cssModel) {
|
@@ -395,8 +363,9 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
395
363
|
const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);
|
396
364
|
const showInherited = this.showInheritedComputedStylePropertiesSetting.get();
|
397
365
|
|
398
|
-
const propertiesByCategory = new Map<Category,
|
366
|
+
const propertiesByCategory = new Map<Category, string[]>();
|
399
367
|
|
368
|
+
const tree: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
|
400
369
|
for (const [propertyName, propertyValue] of nodeStyle.computedStyle) {
|
401
370
|
const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);
|
402
371
|
const isInherited = !nonInheritedProperties.has(canonicalName);
|
@@ -412,115 +381,109 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
412
381
|
|
413
382
|
const categories = categorizePropertyName(propertyName);
|
414
383
|
for (const category of categories) {
|
415
|
-
const treeElement = this.buildPropertyTreeElement(
|
416
|
-
propertyTraces, node, matchedStyles, propertyName, propertyValue, isInherited, hadFocus);
|
417
384
|
if (!propertiesByCategory.has(category)) {
|
418
385
|
propertiesByCategory.set(category, []);
|
419
386
|
}
|
420
|
-
|
421
|
-
// @ts-expect-error
|
422
|
-
propertiesByCategory.get(category).push(treeElement);
|
387
|
+
propertiesByCategory.get(category)?.push(propertyName);
|
423
388
|
}
|
424
389
|
}
|
425
390
|
|
391
|
+
this.#computedStylesTree.removeChildren();
|
426
392
|
for (const category of DefaultCategoryOrder) {
|
427
393
|
const properties = propertiesByCategory.get(category);
|
428
394
|
if (properties && properties.length > 0) {
|
429
|
-
const
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
for (const property of properties) {
|
436
|
-
group.appendChild(property);
|
395
|
+
const propertyNodes: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
|
396
|
+
for (const propertyName of properties) {
|
397
|
+
const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';
|
398
|
+
const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);
|
399
|
+
const isInherited = !nonInheritedProperties.has(canonicalName);
|
400
|
+
propertyNodes.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));
|
437
401
|
}
|
438
|
-
|
439
|
-
this.propertiesOutline.appendChild(group);
|
440
|
-
if (this.expandedGroups.has(category)) {
|
441
|
-
group.expand();
|
442
|
-
}
|
443
|
-
|
444
|
-
this.categoryByTreeElement.set(group, category);
|
402
|
+
tree.push({id: category, treeNodeData: {tag: 'category', name: category}, children: async () => propertyNodes});
|
445
403
|
}
|
446
404
|
}
|
405
|
+
const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);
|
406
|
+
this.#treeData = {
|
407
|
+
tree,
|
408
|
+
compact: true,
|
409
|
+
defaultRenderer,
|
410
|
+
};
|
411
|
+
return this.filterGroupLists();
|
412
|
+
}
|
447
413
|
|
448
|
-
|
414
|
+
private buildTraceNode(property: SDK.CSSProperty.CSSProperty):
|
415
|
+
TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData> {
|
416
|
+
const rule = property.ownerStyle.parentRule as SDK.CSSRule.CSSStyleRule;
|
417
|
+
return {
|
418
|
+
treeNodeData: {
|
419
|
+
tag: 'traceElement',
|
420
|
+
property,
|
421
|
+
rule,
|
422
|
+
},
|
423
|
+
id: rule.origin + ': ' + rule.styleSheetId + property.range,
|
424
|
+
};
|
449
425
|
}
|
450
426
|
|
451
|
-
private
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
427
|
+
private createTreeNodeRenderer(
|
428
|
+
propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>,
|
429
|
+
domNode: SDK.DOMModel.DOMNode,
|
430
|
+
matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
|
431
|
+
):
|
432
|
+
(node: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>,
|
433
|
+
state: {isExpanded: boolean}) => LitHtml.TemplateResult {
|
434
|
+
return node => {
|
435
|
+
const data = node.treeNodeData;
|
436
|
+
let navigate: (arg0?: Event) => void = () => {};
|
437
|
+
if (data.tag === 'property') {
|
438
|
+
const trace = propertyTraces.get(data.propertyName);
|
439
|
+
const activeProperty = trace?.find(
|
440
|
+
property => matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Active);
|
441
|
+
if (activeProperty) {
|
442
|
+
navigate = navigateToSource.bind(this, activeProperty);
|
443
|
+
}
|
444
|
+
const propertyElement = createPropertyElement(
|
445
|
+
domNode, data.propertyName, data.propertyValue, propertyTraces.has(data.propertyName), data.inherited,
|
446
|
+
navigate);
|
447
|
+
if (activeProperty) {
|
448
|
+
propertyElement.addEventListener(
|
449
|
+
'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, activeProperty));
|
450
|
+
}
|
451
|
+
return LitHtml.html`${propertyElement}`;
|
460
452
|
}
|
461
|
-
|
453
|
+
if (data.tag === 'traceElement') {
|
454
|
+
const isPropertyOverloaded =
|
455
|
+
matchedStyles.propertyState(data.property) === SDK.CSSMatchedStyles.PropertyState.Overloaded;
|
456
|
+
const traceElement =
|
457
|
+
createTraceElement(domNode, data.property, isPropertyOverloaded, matchedStyles, this.linkifier);
|
458
|
+
traceElement.addEventListener(
|
459
|
+
'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, data.property));
|
460
|
+
return LitHtml.html`${traceElement}`;
|
461
|
+
}
|
462
|
+
return LitHtml.html`<span style="cursor: text; color: var(--color-text-secondary);">${data.name}</span>`;
|
463
|
+
};
|
462
464
|
}
|
463
465
|
|
464
|
-
private
|
465
|
-
propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>,
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
if (trace) {
|
472
|
-
const activeProperty =
|
473
|
-
this.renderPropertyTrace((matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles), node, treeElement, trace);
|
474
|
-
treeElement.setExpandable(true);
|
475
|
-
treeElement.listItemElement.addEventListener('click', event => {
|
476
|
-
treeElement.expanded ? treeElement.collapse() : treeElement.expand();
|
477
|
-
event.consume();
|
478
|
-
}, false);
|
479
|
-
navigate = (navigateToSource.bind(this, activeProperty) as (arg0?: Event|undefined) => void);
|
480
|
-
}
|
481
|
-
|
482
|
-
const propertyElement = createPropertyElement(node, propertyName, propertyValue);
|
483
|
-
propertyElement.data = {
|
484
|
-
traceable: propertyTraces.has(propertyName),
|
466
|
+
private buildTreeNode(
|
467
|
+
propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>, propertyName: string, propertyValue: string,
|
468
|
+
isInherited: boolean): TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData> {
|
469
|
+
const treeNodeData: ComputedStyleData = {
|
470
|
+
tag: 'property',
|
471
|
+
propertyName,
|
472
|
+
propertyValue,
|
485
473
|
inherited: isInherited,
|
486
|
-
onNavigateToSource: navigate,
|
487
474
|
};
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
if (this.expandedProperties.has(propertyName)) {
|
496
|
-
treeElement.expand();
|
497
|
-
}
|
498
|
-
|
499
|
-
return treeElement;
|
500
|
-
}
|
501
|
-
|
502
|
-
private renderPropertyTrace(
|
503
|
-
matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, node: SDK.DOMModel.DOMNode,
|
504
|
-
rootTreeElement: UI.TreeOutline.TreeElement,
|
505
|
-
tracedProperties: SDK.CSSProperty.CSSProperty[]): SDK.CSSProperty.CSSProperty {
|
506
|
-
let activeProperty: SDK.CSSProperty.CSSProperty|null = null;
|
507
|
-
for (const property of tracedProperties) {
|
508
|
-
const isPropertyOverloaded =
|
509
|
-
matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Overloaded;
|
510
|
-
if (!isPropertyOverloaded) {
|
511
|
-
activeProperty = property;
|
512
|
-
rootTreeElement.listItemElement.addEventListener(
|
513
|
-
'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, property));
|
514
|
-
}
|
515
|
-
const trace = createTraceElement(node, property, isPropertyOverloaded, matchedStyles, this.linkifier);
|
516
|
-
const traceTreeElement = new UI.TreeOutline.TreeElement();
|
517
|
-
traceTreeElement.title = trace;
|
518
|
-
traceTreeElement.listItemElement.addEventListener(
|
519
|
-
'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, property));
|
520
|
-
rootTreeElement.appendChild(traceTreeElement);
|
475
|
+
const trace = propertyTraces.get(propertyName);
|
476
|
+
if (!trace) {
|
477
|
+
return {
|
478
|
+
treeNodeData,
|
479
|
+
id: propertyName,
|
480
|
+
};
|
521
481
|
}
|
522
|
-
|
523
|
-
|
482
|
+
return {
|
483
|
+
treeNodeData,
|
484
|
+
id: propertyName,
|
485
|
+
children: async () => trace.map(this.buildTraceNode),
|
486
|
+
};
|
524
487
|
}
|
525
488
|
|
526
489
|
private handleContextMenuEvent(
|
@@ -575,56 +538,62 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
575
538
|
return result;
|
576
539
|
}
|
577
540
|
|
578
|
-
filterComputedStyles(this: ComputedStyleWidget, regex: RegExp|null): void {
|
541
|
+
async filterComputedStyles(this: ComputedStyleWidget, regex: RegExp|null): Promise<void> {
|
579
542
|
this.filterRegex = regex;
|
580
543
|
if (this.groupComputedStylesSetting.get()) {
|
581
|
-
this.filterGroupLists();
|
582
|
-
} else {
|
583
|
-
this.filterAlphabeticalList();
|
544
|
+
return this.filterGroupLists();
|
584
545
|
}
|
546
|
+
return this.filterAlphabeticalList();
|
585
547
|
}
|
586
548
|
|
587
|
-
private
|
549
|
+
private nodeFilter(node: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>): boolean {
|
588
550
|
const regex = this.filterRegex;
|
589
|
-
const
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
if (!property) {
|
594
|
-
continue;
|
595
|
-
}
|
596
|
-
const matched = !regex || regex.test(property.name) || regex.test(property.value);
|
597
|
-
child.hidden = !matched;
|
598
|
-
hasMatch = hasMatch || matched;
|
551
|
+
const data = node.treeNodeData;
|
552
|
+
if (data.tag === 'property') {
|
553
|
+
const matched = !regex || regex.test(data.propertyName) || regex.test(data.propertyValue);
|
554
|
+
return matched;
|
599
555
|
}
|
600
|
-
|
556
|
+
return true;
|
601
557
|
}
|
602
558
|
|
603
|
-
private
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
559
|
+
private filterAlphabeticalList(): void {
|
560
|
+
if (!this.#treeData) {
|
561
|
+
return;
|
562
|
+
}
|
563
|
+
const tree = this.#treeData.tree.filter(this.nodeFilter.bind(this));
|
564
|
+
this.#computedStylesTree.data = {
|
565
|
+
tree,
|
566
|
+
defaultRenderer: this.#treeData.defaultRenderer,
|
567
|
+
compact: this.#treeData.compact,
|
568
|
+
};
|
569
|
+
this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));
|
570
|
+
}
|
571
|
+
|
572
|
+
private async filterGroupLists(): Promise<void> {
|
573
|
+
if (!this.#treeData) {
|
574
|
+
return;
|
575
|
+
}
|
576
|
+
const tree: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>[] = [];
|
577
|
+
for (const group of this.#treeData.tree) {
|
578
|
+
const data = group.treeNodeData;
|
579
|
+
if (data.tag !== 'category' || !group.children) {
|
580
|
+
continue;
|
581
|
+
}
|
582
|
+
const properties = await group.children();
|
583
|
+
const filteredChildren = properties.filter(this.nodeFilter.bind(this));
|
584
|
+
if (filteredChildren.length) {
|
585
|
+
tree.push(
|
586
|
+
{id: data.name, treeNodeData: {tag: 'category', name: data.name}, children: async () => filteredChildren});
|
620
587
|
}
|
621
|
-
group.hidden = !hasGroupMatch;
|
622
|
-
// the first visible group won't have a divider before the group title
|
623
|
-
group.listItemElement.classList.toggle('first-group', hasGroupMatch && !foundFirstGroup);
|
624
|
-
foundFirstGroup = foundFirstGroup || hasGroupMatch;
|
625
588
|
}
|
626
589
|
|
627
|
-
this.
|
590
|
+
this.#computedStylesTree.data = {
|
591
|
+
tree,
|
592
|
+
defaultRenderer: this.#treeData.defaultRenderer,
|
593
|
+
compact: this.#treeData.compact,
|
594
|
+
};
|
595
|
+
await this.#computedStylesTree.expandRecursively(0);
|
596
|
+
this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));
|
628
597
|
}
|
629
598
|
}
|
630
599
|
|
@@ -918,7 +918,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
918
918
|
propertyNamePattern = '^' + this.property.name + '$';
|
919
919
|
}
|
920
920
|
const regex = new RegExp(propertyNamePattern, 'i');
|
921
|
-
computedStyleWidget.filterComputedStyles(regex);
|
921
|
+
await computedStyleWidget.filterComputedStyles(regex);
|
922
922
|
|
923
923
|
const filterInput = (computedStyleWidget.input as HTMLInputElement);
|
924
924
|
filterInput.value = this.property.name;
|
@@ -9,6 +9,8 @@ import computedStylePropertyStyles from './computedStyleProperty.css.js';
|
|
9
9
|
const {render, html} = LitHtml;
|
10
10
|
|
11
11
|
export interface ComputedStylePropertyData {
|
12
|
+
propertyNameRenderer: () => Element;
|
13
|
+
propertyValueRenderer: () => Element;
|
12
14
|
inherited: boolean;
|
13
15
|
traceable: boolean;
|
14
16
|
onNavigateToSource: (event?: Event) => void;
|
@@ -18,6 +20,8 @@ export class ComputedStyleProperty extends HTMLElement {
|
|
18
20
|
static readonly litTagName = LitHtml.literal`devtools-computed-style-property`;
|
19
21
|
readonly #shadow = this.attachShadow({mode: 'open'});
|
20
22
|
|
23
|
+
#propertyNameRenderer?: () => Element = undefined;
|
24
|
+
#propertyValueRenderer?: () => Element = undefined;
|
21
25
|
#inherited = false;
|
22
26
|
#traceable = false;
|
23
27
|
#onNavigateToSource: ((event?: Event) => void) = () => {};
|
@@ -27,6 +31,8 @@ export class ComputedStyleProperty extends HTMLElement {
|
|
27
31
|
}
|
28
32
|
|
29
33
|
set data(data: ComputedStylePropertyData) {
|
34
|
+
this.#propertyNameRenderer = data.propertyNameRenderer;
|
35
|
+
this.#propertyValueRenderer = data.propertyValueRenderer;
|
30
36
|
this.#inherited = data.inherited;
|
31
37
|
this.#traceable = data.traceable;
|
32
38
|
this.#onNavigateToSource = data.onNavigateToSource;
|
@@ -34,16 +40,22 @@ export class ComputedStyleProperty extends HTMLElement {
|
|
34
40
|
}
|
35
41
|
|
36
42
|
#render(): void {
|
43
|
+
const propertyNameElement = this.#propertyNameRenderer?.();
|
44
|
+
const propertyValueElement = this.#propertyValueRenderer?.();
|
37
45
|
// Disabled until https://crbug.com/1079231 is fixed.
|
38
46
|
// clang-format off
|
39
47
|
render(html`
|
40
48
|
<div class="computed-style-property ${this.#inherited ? 'inherited' : ''}">
|
41
|
-
<
|
49
|
+
<div class="property-name">
|
50
|
+
${propertyNameElement}
|
51
|
+
</div>
|
42
52
|
<span class="hidden" aria-hidden="false">: </span>
|
43
53
|
${this.#traceable ?
|
44
54
|
html`<span class="goto" @click=${this.#onNavigateToSource}></span>` :
|
45
55
|
null}
|
46
|
-
<
|
56
|
+
<div class="property-value">
|
57
|
+
${propertyValueElement}
|
58
|
+
</div>
|
47
59
|
<span class="hidden" aria-hidden="false">;</span>
|
48
60
|
</div>
|
49
61
|
`, this.#shadow, {
|
@@ -12,6 +12,7 @@ export interface ComputedStyleTraceData {
|
|
12
12
|
selector: string;
|
13
13
|
active: boolean;
|
14
14
|
onNavigateToSource: (event?: Event) => void;
|
15
|
+
ruleOriginNode?: Node;
|
15
16
|
}
|
16
17
|
|
17
18
|
export class ComputedStyleTrace extends HTMLElement {
|
@@ -21,6 +22,7 @@ export class ComputedStyleTrace extends HTMLElement {
|
|
21
22
|
#selector = '';
|
22
23
|
#active = false;
|
23
24
|
#onNavigateToSource: ((event?: Event) => void) = () => {};
|
25
|
+
#ruleOriginNode?: Node;
|
24
26
|
|
25
27
|
connectedCallback(): void {
|
26
28
|
this.#shadow.adoptedStyleSheets = [computedStyleTraceStyles];
|
@@ -30,6 +32,7 @@ export class ComputedStyleTrace extends HTMLElement {
|
|
30
32
|
this.#selector = data.selector;
|
31
33
|
this.#active = data.active;
|
32
34
|
this.#onNavigateToSource = data.onNavigateToSource;
|
35
|
+
this.#ruleOriginNode = data.ruleOriginNode;
|
33
36
|
this.#render();
|
34
37
|
}
|
35
38
|
|
@@ -41,7 +44,7 @@ export class ComputedStyleTrace extends HTMLElement {
|
|
41
44
|
<span class="goto" @click=${this.#onNavigateToSource}></span>
|
42
45
|
<slot name="trace-value" @click=${this.#onNavigateToSource}></slot>
|
43
46
|
<span class="trace-selector">${this.#selector}</span>
|
44
|
-
<
|
47
|
+
<span class="trace-link">${this.#ruleOriginNode}</span>
|
45
48
|
</div>
|
46
49
|
`, this.#shadow, {
|
47
50
|
host: this,
|
@@ -14,31 +14,40 @@
|
|
14
14
|
.computed-style-property {
|
15
15
|
--goto-size: 16px;
|
16
16
|
|
17
|
+
font-family: var(--monospace-font-family);
|
18
|
+
font-size: var(--monospace-font-size);
|
17
19
|
min-height: 16px;
|
18
20
|
box-sizing: border-box;
|
19
21
|
padding-top: 2px;
|
20
22
|
white-space: nowrap;
|
21
23
|
}
|
22
24
|
|
25
|
+
.computed-style-property:hover {
|
26
|
+
background-color: var(--legacy-focus-bg-color);
|
27
|
+
cursor: text;
|
28
|
+
}
|
29
|
+
|
23
30
|
.computed-style-property.inherited {
|
24
31
|
opacity: 50%;
|
25
32
|
}
|
26
33
|
|
27
|
-
|
28
|
-
|
34
|
+
.property-name,
|
35
|
+
.property-value {
|
36
|
+
display: contents;
|
29
37
|
overflow: hidden;
|
30
38
|
text-overflow: ellipsis;
|
31
39
|
}
|
32
40
|
|
33
|
-
|
41
|
+
.property-name {
|
34
42
|
width: 16em;
|
35
43
|
max-width: 52%;
|
36
44
|
margin-right: calc(var(--goto-size) / 2);
|
37
45
|
display: inline-block;
|
38
46
|
vertical-align: text-top;
|
47
|
+
color: var(--webkit-css-property-color, var(--color-syntax-1)); /* stylelint-disable-line plugin/use_theme_colors */ /* See: crbug.com/1152736 for color variable migration. */
|
39
48
|
}
|
40
49
|
|
41
|
-
|
50
|
+
.property-value {
|
42
51
|
margin-left: 2em;
|
43
52
|
}
|
44
53
|
|
@@ -66,8 +75,8 @@ slot[name="property-value"] {
|
|
66
75
|
white-space: normal;
|
67
76
|
}
|
68
77
|
|
69
|
-
:host-context(.computed-narrow)
|
70
|
-
:host-context(.computed-narrow)
|
78
|
+
:host-context(.computed-narrow) .property-name,
|
79
|
+
:host-context(.computed-narrow) .property-value {
|
71
80
|
display: inline-block;
|
72
81
|
width: 100%;
|
73
82
|
max-width: 100%;
|
@@ -12,6 +12,8 @@
|
|
12
12
|
|
13
13
|
.computed-style-trace {
|
14
14
|
margin-left: 16px;
|
15
|
+
font-family: var(--monospace-font-family);
|
16
|
+
font-size: var(--monospace-font-size);
|
15
17
|
}
|
16
18
|
|
17
19
|
.computed-style-trace:hover {
|
@@ -38,6 +40,15 @@
|
|
38
40
|
display: inline-block;
|
39
41
|
}
|
40
42
|
|
43
|
+
.devtools-link {
|
44
|
+
--override-text-decoration-color: hsl(0deg 0% 60%);
|
45
|
+
|
46
|
+
color: var(--color-text-primary);
|
47
|
+
text-decoration-color: var(--override-text-decoration-color);
|
48
|
+
text-decoration-line: underline;
|
49
|
+
cursor: pointer;
|
50
|
+
}
|
51
|
+
|
41
52
|
.trace-value {
|
42
53
|
margin-left: 16px;
|
43
54
|
}
|
@@ -53,7 +64,7 @@
|
|
53
64
|
padding-left: 2em;
|
54
65
|
}
|
55
66
|
|
56
|
-
|
67
|
+
.trace-link {
|
57
68
|
user-select: none;
|
58
69
|
float: right;
|
59
70
|
padding-left: 1em;
|
@@ -523,7 +523,7 @@ export const RuntimeSettings: RuntimeSetting[] = [
|
|
523
523
|
{
|
524
524
|
// This setting is disabled, but we keep it around to show in the UI.
|
525
525
|
setting: Common.Settings.Settings.instance().createSetting(
|
526
|
-
'lighthouse.throttling', '
|
526
|
+
'lighthouse.throttling', 'simulate', Common.Settings.SettingStorageType.Synced),
|
527
527
|
title: i18nLazyString(UIStrings.throttlingMethod),
|
528
528
|
// We will disable this when we have a Lantern trace viewer within DevTools.
|
529
529
|
learnMore:
|
@@ -10,18 +10,20 @@ await FrontendHelpers.initializeGlobalVars();
|
|
10
10
|
|
11
11
|
const component = new Elements.ComputedStyleProperty.ComputedStyleProperty();
|
12
12
|
|
13
|
-
const propertyName = document.createElement('span');
|
14
|
-
propertyName.textContent = 'display';
|
15
|
-
propertyName.slot = 'property-name';
|
16
|
-
component.appendChild(propertyName);
|
17
|
-
|
18
|
-
const propertyValue = document.createElement('span');
|
19
|
-
propertyValue.textContent = 'block';
|
20
|
-
propertyValue.slot = 'property-value';
|
21
|
-
component.appendChild(propertyValue);
|
22
|
-
|
23
13
|
document.getElementById('container')?.appendChild(component);
|
24
14
|
component.data = {
|
15
|
+
propertyNameRenderer: () => {
|
16
|
+
const propertyName = document.createElement('span');
|
17
|
+
propertyName.textContent = 'display';
|
18
|
+
propertyName.slot = 'property-name';
|
19
|
+
return propertyName;
|
20
|
+
},
|
21
|
+
propertyValueRenderer: () => {
|
22
|
+
const propertyValue = document.createElement('span');
|
23
|
+
propertyValue.textContent = 'block';
|
24
|
+
propertyValue.slot = 'property-value';
|
25
|
+
return propertyValue;
|
26
|
+
},
|
25
27
|
inherited: true,
|
26
28
|
traceable: false,
|
27
29
|
onNavigateToSource: (): void => {},
|
@@ -7,16 +7,6 @@ import * as Elements from '../../../../panels/elements/components/components.js'
|
|
7
7
|
|
8
8
|
const component = new Elements.ComputedStyleProperty.ComputedStyleProperty();
|
9
9
|
|
10
|
-
const propertyName = document.createElement('span');
|
11
|
-
propertyName.textContent = 'display';
|
12
|
-
propertyName.slot = 'property-name';
|
13
|
-
component.appendChild(propertyName);
|
14
|
-
|
15
|
-
const propertyValue = document.createElement('span');
|
16
|
-
propertyValue.textContent = 'grid';
|
17
|
-
propertyValue.slot = 'property-value';
|
18
|
-
component.appendChild(propertyValue);
|
19
|
-
|
20
10
|
const trace = document.createElement('pre');
|
21
11
|
trace.textContent = 'block body (style.css):42';
|
22
12
|
trace.slot = 'property-traces';
|
@@ -24,6 +14,19 @@ component.appendChild(trace);
|
|
24
14
|
|
25
15
|
document.getElementById('container')?.appendChild(component);
|
26
16
|
component.data = {
|
17
|
+
propertyNameRenderer: () => {
|
18
|
+
const propertyName = document.createElement('span');
|
19
|
+
propertyName.textContent = 'display';
|
20
|
+
propertyName.slot = 'property-name';
|
21
|
+
return propertyName;
|
22
|
+
},
|
23
|
+
propertyValueRenderer: () => {
|
24
|
+
const propertyValue = document.createElement('span');
|
25
|
+
propertyValue.textContent = 'grid';
|
26
|
+
propertyValue.slot = 'property-value';
|
27
|
+
|
28
|
+
return propertyValue;
|
29
|
+
},
|
27
30
|
inherited: false,
|
28
31
|
traceable: true,
|
29
32
|
onNavigateToSource: (): void => {},
|
@@ -31,6 +31,7 @@ export interface TreeOutlineData<TreeNodeDataType> {
|
|
31
31
|
*/
|
32
32
|
tree: readonly TreeNode<TreeNodeDataType>[];
|
33
33
|
filter?: (node: TreeNodeDataType) => FilterOption;
|
34
|
+
compact?: boolean;
|
34
35
|
}
|
35
36
|
|
36
37
|
export function defaultRenderer(node: TreeNode<string>): LitHtml.TemplateResult {
|
@@ -111,6 +112,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
111
112
|
return LitHtml.html`${String(node.treeNodeData)}`;
|
112
113
|
};
|
113
114
|
#nodeFilter?: ((node: TreeNodeDataType) => FilterOption);
|
115
|
+
#compact = false;
|
114
116
|
|
115
117
|
/**
|
116
118
|
* scheduledRender = render() has been called and scheduled a render.
|
@@ -155,6 +157,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
155
157
|
this.#defaultRenderer = data.defaultRenderer;
|
156
158
|
this.#treeData = data.tree;
|
157
159
|
this.#nodeFilter = data.filter;
|
160
|
+
this.#compact = data.compact || false;
|
158
161
|
|
159
162
|
if (!this.#hasRenderedAtLeastOnce) {
|
160
163
|
this.#selectedTreeNode = this.#treeData[0];
|
@@ -454,6 +457,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
454
457
|
parent: isExpandableNode(node),
|
455
458
|
selected: this.#isSelectedNode(node),
|
456
459
|
'is-top-level': depth === 0,
|
460
|
+
compact: this.#compact,
|
457
461
|
});
|
458
462
|
const ariaExpandedAttribute =
|
459
463
|
LitHtml.Directives.ifDefined(isExpandableNode(node) ? String(nodeIsExpanded) : undefined);
|
@@ -9,15 +9,21 @@
|
|
9
9
|
}
|
10
10
|
|
11
11
|
li {
|
12
|
+
border: 2px solid transparent;
|
12
13
|
list-style: none;
|
13
14
|
text-overflow: ellipsis;
|
14
15
|
min-height: 12px;
|
15
16
|
}
|
16
17
|
|
18
|
+
.compact {
|
19
|
+
border: 0;
|
20
|
+
}
|
21
|
+
|
17
22
|
.tree-node-key {
|
18
23
|
white-space: var(--override-key-whitespace-wrapping);
|
19
24
|
/* Override the default |min-width: auto| to avoid overflows of flex items */
|
20
25
|
min-width: 0;
|
26
|
+
flex-grow: 1;
|
21
27
|
}
|
22
28
|
|
23
29
|
.arrow-icon {
|
@@ -79,7 +85,6 @@ li.is-top-level:last-child {
|
|
79
85
|
}
|
80
86
|
|
81
87
|
.arrow-and-key-wrapper {
|
82
|
-
border: 2px solid transparent;
|
83
88
|
display: flex;
|
84
89
|
align-content: center;
|
85
90
|
align-items: center;
|
package/package.json
CHANGED
@@ -1,66 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Copyright (c) 2017 The Chromium Authors. All rights reserved.
|
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
|
-
.alphabetical-list.render-flash {
|
8
|
-
min-height: 100vh;
|
9
|
-
}
|
10
|
-
|
11
|
-
.tree-outline,
|
12
|
-
.tree-outline ol {
|
13
|
-
padding-left: 0;
|
14
|
-
}
|
15
|
-
|
16
|
-
.tree-outline li:hover {
|
17
|
-
background-color: var(--legacy-focus-bg-color);
|
18
|
-
cursor: text;
|
19
|
-
}
|
20
|
-
|
21
|
-
.tree-outline li::before {
|
22
|
-
margin: 0 -1px 0 4px;
|
23
|
-
}
|
24
|
-
|
25
|
-
.group-title {
|
26
|
-
/* tree-outline li::before is set to be 16px wide */
|
27
|
-
padding-right: 16px;
|
28
|
-
}
|
29
|
-
|
30
|
-
.tree-outline li.group-title:hover {
|
31
|
-
background-color: transparent;
|
32
|
-
}
|
33
|
-
|
34
|
-
.group-title > h1 {
|
35
|
-
margin: 1px 0 0;
|
36
|
-
padding: 1em 0;
|
37
|
-
width: 100%;
|
38
|
-
cursor: text;
|
39
|
-
color: var(--color-text-secondary);
|
40
|
-
font-size: 11px;
|
41
|
-
font-weight: 400;
|
42
|
-
}
|
43
|
-
|
44
|
-
.group-title:not(.first-group) > h1 {
|
45
|
-
border-top: 1px solid var(--color-details-hairline);
|
46
|
-
}
|
47
|
-
|
48
|
-
.group-title + ol.children {
|
49
|
-
margin-bottom: 1em;
|
50
|
-
}
|
51
|
-
|
52
|
-
@media (forced-colors: active) {
|
53
|
-
:host-context(.monospace.computed-properties) .tree-outline li:hover {
|
54
|
-
forced-color-adjust: none;
|
55
|
-
background-color: Highlight;
|
56
|
-
}
|
57
|
-
|
58
|
-
:host-context(.monospace.computed-properties) .tree-outline:not(.hide-selection-when-blurred) li.parent:hover.selected::before,
|
59
|
-
:host-context(.monospace.computed-properties) .tree-outline-disclosure li.parent:hover::before {
|
60
|
-
background-color: HighlightText;
|
61
|
-
}
|
62
|
-
|
63
|
-
:host-context(.monospace.computed-properties) .tree-outline li:hover * {
|
64
|
-
color: HighlightText;
|
65
|
-
}
|
66
|
-
}
|