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

Commit de3b159

Browse files
Eric LeeseDevtools-frontend LUCI CQ
authored andcommitted
Link to adopted stylesheets
If a style is a constructed stylesheet with no source url, the text indicating this is now a link that causes the adopted stylesheet to be scrolled into view and highlighted. Bug: 40802935 Change-Id: I4298ea270868f360c14a4ced3f99be00dcc927a7 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7485031 Reviewed-by: Philip Pfaffe <pfaffe@chromium.org> Commit-Queue: Eric Leese <leese@chromium.org>
1 parent 0ea2a88 commit de3b159

File tree

7 files changed

+85
-15
lines changed

7 files changed

+85
-15
lines changed

front_end/core/sdk/DOMModel.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
882882
}
883883

884884
private toAdoptedStyleSheets(ids: Protocol.DOM.StyleSheetId[]): AdoptedStyleSheet[] {
885-
return ids.map(id => (new AdoptedStyleSheet(id, this.#domModel.cssModel())));
885+
return ids.map(id => (new AdoptedStyleSheet(id, this)));
886886
}
887887

888888
setAdoptedStyleSheets(ids: Protocol.DOM.StyleSheetId[]): void {
@@ -1280,7 +1280,11 @@ export class DOMDocument extends DOMNode {
12801280
}
12811281

12821282
export class AdoptedStyleSheet {
1283-
constructor(readonly id: Protocol.DOM.StyleSheetId, readonly cssModel: CSSModel) {
1283+
constructor(readonly id: Protocol.DOM.StyleSheetId, readonly parent: DOMNode) {
1284+
}
1285+
1286+
get cssModel(): CSSModel {
1287+
return this.parent.domModel().cssModel();
12841288
}
12851289
}
12861290

front_end/panels/common/DOMLinkifier.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import * as Common from '../../core/common/common.js';
66
import * as i18n from '../../core/i18n/i18n.js';
77
import * as SDK from '../../core/sdk/sdk.js';
8+
import type * as Protocol from '../../generated/protocol.js';
89
import * as UI from '../../ui/legacy/legacy.js';
910
import {Directives, html, nothing, render} from '../../ui/lit/lit.js';
1011
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
@@ -212,14 +213,16 @@ const DEFERRED_DEFAULT_VIEW: DeferredView = (input, _output, target: HTMLElement
212213
export class DeferredDOMNodeLink extends UI.Widget.Widget {
213214
#deferredNode: SDK.DOMModel.DeferredDOMNode|undefined = undefined;
214215
#options: Options|undefined = undefined;
216+
#styleSheetId: Protocol.DOM.StyleSheetId|undefined = undefined;
215217
#view: DeferredView;
216218

217219
constructor(
218220
element?: HTMLElement, deferredNode?: SDK.DOMModel.DeferredDOMNode, options?: Options,
219-
view: DeferredView = DEFERRED_DEFAULT_VIEW) {
221+
styleSheetId?: Protocol.DOM.StyleSheetId, view: DeferredView = DEFERRED_DEFAULT_VIEW) {
220222
super(element, {useShadowDom: true});
221223
this.element.classList.remove('vbox');
222224
this.#deferredNode = deferredNode;
225+
this.#styleSheetId = styleSheetId;
223226
this.#options = options;
224227
this.#view = view;
225228
this.performUpdate();
@@ -230,6 +233,14 @@ export class DeferredDOMNodeLink extends UI.Widget.Widget {
230233
preventKeyboardFocus: this.#options?.preventKeyboardFocus,
231234
onClick: () => {
232235
this.#deferredNode?.resolve?.(node => {
236+
if (node && this.#styleSheetId) {
237+
for (const adoptedStyle of node.adoptedStyleSheetsForNode) {
238+
if (adoptedStyle.id === this.#styleSheetId) {
239+
void Common.Revealer.reveal(adoptedStyle);
240+
return;
241+
}
242+
}
243+
}
233244
void Common.Revealer.reveal(node);
234245
void node?.scrollIntoView();
235246
});

front_end/panels/elements/AdoptedStyleSheetTreeElement.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import * as CodeHighlighter from '../../ui/components/code_highlighter/code_high
99
import * as Components from '../../ui/legacy/components/utils/utils.js';
1010
import * as UI from '../../ui/legacy/legacy.js';
1111
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
12+
import {PanelUtils} from '../utils/utils.js';
1213

1314
export class AdoptedStyleSheetTreeElement extends UI.TreeOutline.TreeElement {
1415
private eventListener: Common.EventTarget.EventDescriptor|null = null;
1516

16-
constructor(private readonly adoptedStyleSheet: SDK.DOMModel.AdoptedStyleSheet) {
17+
constructor(readonly adoptedStyleSheet: SDK.DOMModel.AdoptedStyleSheet) {
1718
super('');
1819
const header = adoptedStyleSheet.cssModel.styleSheetHeaderForId(adoptedStyleSheet.id);
1920
if (header) {
@@ -50,6 +51,10 @@ export class AdoptedStyleSheetTreeElement extends UI.TreeOutline.TreeElement {
5051
}
5152
treeElement.appendChild(new AdoptedStyleSheetContentsTreeElement(header));
5253
}
54+
55+
highlight(): void {
56+
PanelUtils.highlightElement(this.listItemElement);
57+
}
5358
}
5459

5560
export class AdoptedStyleSheetContentsTreeElement extends UI.TreeOutline.TreeElement {

front_end/panels/elements/ElementsPanel.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
795795
return this.#domTreeWidget.selectedDOMNode();
796796
}
797797

798-
selectDOMNode(node: SDK.DOMModel.DOMNode, focus?: boolean): void {
798+
selectDOMNode(node: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet, focus?: boolean): void {
799799
this.#domTreeWidget.selectDOMNode(node, focus);
800800
}
801801

@@ -899,6 +899,18 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
899899
this.notFirstInspectElement = true;
900900
}
901901

902+
async revealAndSelectAdoptedStyleSheet(nodeToReveal: SDK.DOMModel.AdoptedStyleSheet, opts?: RevealAndSelectNodeOpts):
903+
Promise<void> {
904+
const {showPanel = true, focusNode = false} = opts ?? {};
905+
this.omitDefaultSelection = true;
906+
907+
if (showPanel) {
908+
await UI.ViewManager.ViewManager.instance().showView('elements', false, !focus);
909+
}
910+
this.selectDOMNode(nodeToReveal, focusNode);
911+
delete this.omitDefaultSelection;
912+
}
913+
902914
private showUAShadowDOMChanged(): void {
903915
this.#domTreeWidget.reload();
904916
}
@@ -1309,10 +1321,12 @@ export class ContextMenuProvider implements
13091321
}
13101322
}
13111323

1312-
export class DOMNodeRevealer implements
1313-
Common.Revealer.Revealer<SDK.DOMModel.DOMNode|SDK.DOMModel.DeferredDOMNode|SDK.RemoteObject.RemoteObject> {
1314-
reveal(node: SDK.DOMModel.DOMNode|SDK.DOMModel.DeferredDOMNode|SDK.RemoteObject.RemoteObject, omitFocus?: boolean):
1315-
Promise<void> {
1324+
export class DOMNodeRevealer implements Common.Revealer.Revealer<
1325+
SDK.DOMModel.DOMNode|SDK.DOMModel.DeferredDOMNode|SDK.RemoteObject.RemoteObject|SDK.DOMModel.AdoptedStyleSheet> {
1326+
reveal(
1327+
node: SDK.DOMModel.DOMNode|SDK.DOMModel.DeferredDOMNode|SDK.RemoteObject.RemoteObject|
1328+
SDK.DOMModel.AdoptedStyleSheet,
1329+
omitFocus?: boolean): Promise<void> {
13161330
const panel = ElementsPanel.instance();
13171331
panel.pendingNodeReveal = true;
13181332

@@ -1332,7 +1346,7 @@ export class DOMNodeRevealer implements
13321346

13331347
function revealPromise(
13341348
resolve: () => void, reject: (arg0: Platform.UserVisibleError.UserVisibleError) => void): void {
1335-
if (node instanceof SDK.DOMModel.DOMNode) {
1349+
if (node instanceof SDK.DOMModel.DOMNode || node instanceof SDK.DOMModel.AdoptedStyleSheet) {
13361350
onNodeResolved((node));
13371351
} else if (node instanceof SDK.DOMModel.DeferredDOMNode) {
13381352
(node).resolve(checkDeferredDOMNodeThenReveal);
@@ -1346,14 +1360,15 @@ export class DOMNodeRevealer implements
13461360
}
13471361
}
13481362

1349-
function onNodeResolved(resolvedNode: SDK.DOMModel.DOMNode): void {
1363+
function onNodeResolved(resolvedNode: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet): void {
13501364
panel.pendingNodeReveal = false;
13511365

13521366
// A detached node could still have a parent and ownerDocument
13531367
// properties, which means stepping up through the hierarchy to ensure
13541368
// that the root node is the document itself. Any break implies
13551369
// detachment.
1356-
let currentNode: SDK.DOMModel.DOMNode = resolvedNode;
1370+
let currentNode: SDK.DOMModel.DOMNode =
1371+
resolvedNode instanceof SDK.DOMModel.AdoptedStyleSheet ? resolvedNode.parent : resolvedNode;
13571372
while (currentNode.parentNode) {
13581373
currentNode = currentNode.parentNode;
13591374
}
@@ -1367,7 +1382,11 @@ export class DOMNodeRevealer implements
13671382
}
13681383

13691384
if (resolvedNode) {
1370-
void panel.revealAndSelectNode(resolvedNode, {showPanel: true, focusNode: !omitFocus}).then(resolve);
1385+
const opts: RevealAndSelectNodeOpts = {showPanel: true, focusNode: !omitFocus};
1386+
const promise = resolvedNode instanceof SDK.DOMModel.AdoptedStyleSheet ?
1387+
panel.revealAndSelectAdoptedStyleSheet(resolvedNode, opts) :
1388+
panel.revealAndSelectNode(resolvedNode, opts);
1389+
void promise.then(resolve);
13711390
return;
13721391
}
13731392
const msg = i18nString(UIStrings.nodeCannotBeFoundInTheCurrent);

front_end/panels/elements/ElementsTreeOutline.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,12 @@ export class DOMTreeWidget extends UI.Widget.Widget {
274274
this.performUpdate();
275275
}
276276

277-
selectDOMNode(node: SDK.DOMModel.DOMNode|null, focus?: boolean): void {
278-
this.#viewOutput?.elementsTreeOutline?.selectDOMNode(node, focus);
277+
selectDOMNode(node: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet|null, focus?: boolean): void {
278+
if (node instanceof SDK.DOMModel.AdoptedStyleSheet) {
279+
this.#viewOutput?.elementsTreeOutline?.highlightAdoptedStyleSheet(node);
280+
} else {
281+
this.#viewOutput?.elementsTreeOutline?.selectDOMNode(node, focus);
282+
}
279283
}
280284

281285
highlightNodeAttribute(node: SDK.DOMModel.DOMNode, attribute: string): void {
@@ -911,6 +915,22 @@ export class ElementsTreeOutline extends
911915
}
912916
}
913917

918+
highlightAdoptedStyleSheet(adoptedStyleSheet: SDK.DOMModel.AdoptedStyleSheet): void {
919+
const parentNode = !this.includeRootDOMNode && adoptedStyleSheet.parent === this.rootDOMNode && this.rootDOMNode ?
920+
this.rootElement() :
921+
this.createTreeElementFor(adoptedStyleSheet.parent);
922+
if (!parentNode) {
923+
return;
924+
}
925+
926+
for (const child of parentNode.children()) {
927+
if (child instanceof AdoptedStyleSheetTreeElement && child.adoptedStyleSheet === adoptedStyleSheet) {
928+
child.highlight();
929+
return;
930+
}
931+
}
932+
}
933+
914934
editing(): boolean {
915935
const node = this.selectedDOMNode();
916936
if (!node) {

front_end/panels/elements/StylePropertiesSection.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,16 @@ export class StylePropertiesSection {
409409
link.textContent = label;
410410
return link;
411411
}
412+
if (rule && rule.style.styleSheetId && rule.treeScope) {
413+
// Make link for adopted stylesheet.
414+
const ownerNode = new SDK.DOMModel.DeferredDOMNode(rule.cssModelInternal.target(), rule.treeScope);
415+
const link = document.createElement('devtools-widget') as
416+
UI.Widget.WidgetElement<PanelsCommon.DOMLinkifier.DeferredDOMNodeLink>;
417+
link.widgetConfig = UI.Widget.widgetConfig(
418+
e => new PanelsCommon.DOMLinkifier.DeferredDOMNodeLink(e, ownerNode, undefined, rule.style.styleSheetId));
419+
link.textContent = label;
420+
return link;
421+
}
412422
return null;
413423
}
414424

front_end/panels/elements/elements-meta.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ Common.Revealer.registerRevealer({
617617
SDK.DOMModel.DOMNode,
618618
SDK.DOMModel.DeferredDOMNode,
619619
SDK.RemoteObject.RemoteObject,
620+
SDK.DOMModel.AdoptedStyleSheet,
620621
];
621622
},
622623
destination: Common.Revealer.RevealerDestination.ELEMENTS_PANEL,

0 commit comments

Comments
 (0)