chrome-devtools-frontend 1.0.975541 → 1.0.976570

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AUTHORS CHANGED
@@ -29,6 +29,7 @@ Feng Lu <lufengd3@gmail.com>
29
29
  Gabriel Luong <gabriel.luong@gmail.com>
30
30
  Gautham Banasandra <gautham.bangalore@gmail.com>
31
31
  Jake Mulhern <mulherje@gmail.com>
32
+ Jan Keitel <jan.keitel@gmail.com>
32
33
  Jeffrey Chen <jeffreyca16@gmail.com>
33
34
  Jesper van den Ende <jespertheend@gmail.com>
34
35
  Juba Borgohain <chromiumjuba@gmail.com>
@@ -114,12 +114,14 @@ grd_files_release_sources = [
114
114
  "front_end/Images/lighthouse_logo.svg",
115
115
  "front_end/Images/link_icon.svg",
116
116
  "front_end/Images/mediumIcons.svg",
117
+ "front_end/Images/minus_icon.svg",
117
118
  "front_end/Images/navigationControls.png",
118
119
  "front_end/Images/navigationControls_2x.png",
119
120
  "front_end/Images/network_conditions_icon.svg",
120
121
  "front_end/Images/network_panel_icon.svg",
121
122
  "front_end/Images/nodeIcon.avif",
122
123
  "front_end/Images/node_search_icon.svg",
124
+ "front_end/Images/plus_icon.svg",
123
125
  "front_end/Images/popoverArrows.png",
124
126
  "front_end/Images/preview_feature_video_thumbnail.svg",
125
127
  "front_end/Images/profileGroupIcon.png",
@@ -480,6 +482,7 @@ grd_files_release_sources = [
480
482
  "front_end/third_party/wasmparser/wasmparser.js",
481
483
  "front_end/ui/components/adorners/adorners.js",
482
484
  "front_end/ui/components/buttons/buttons.js",
485
+ "front_end/ui/components/chrome_link/chrome_link.js",
483
486
  "front_end/ui/components/code_highlighter/code_highlighter.js",
484
487
  "front_end/ui/components/data_grid/data_grid.js",
485
488
  "front_end/ui/components/diff_view/diff_view.js",
@@ -1400,6 +1403,8 @@ grd_files_debug_sources = [
1400
1403
  "front_end/ui/components/adorners/adorner.css.js",
1401
1404
  "front_end/ui/components/buttons/Button.js",
1402
1405
  "front_end/ui/components/buttons/button.css.js",
1406
+ "front_end/ui/components/chrome_link/ChromeLink.js",
1407
+ "front_end/ui/components/chrome_link/chromeLink.css.js",
1403
1408
  "front_end/ui/components/code_highlighter/CodeHighlighter.js",
1404
1409
  "front_end/ui/components/code_highlighter/codeHighlighter.css.js",
1405
1410
  "front_end/ui/components/data_grid/DataGrid.js",
@@ -124,9 +124,11 @@ devtools_svg_sources = [
124
124
  "lighthouse_logo.svg",
125
125
  "link_icon.svg",
126
126
  "mediumIcons.svg",
127
+ "minus_icon.svg",
127
128
  "network_conditions_icon.svg",
128
129
  "network_panel_icon.svg",
129
130
  "node_search_icon.svg",
131
+ "plus_icon.svg",
130
132
  "preview_feature_video_thumbnail.svg",
131
133
  "refresh_12x12_icon.svg",
132
134
  "resizeDiagonal.svg",
@@ -0,0 +1,3 @@
1
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M10 5.5H2V6.5H10V5.5Z" fill="#202124"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 2H5.5V5.5H2V6.5H5.5V10H6.5V6.5H10V5.5H6.5V2Z" fill="#202124"/>
3
+ </svg>
@@ -150,6 +150,10 @@ export class CSSModel extends SDKModel<EventTypes> {
150
150
  return this.#sourceMapManager;
151
151
  }
152
152
 
153
+ static readableLayerName(text: string): string {
154
+ return text || '<anonymous>';
155
+ }
156
+
153
157
  static trimSourceURL(text: string): string {
154
158
  let sourceURLIndex = text.lastIndexOf('/*# sourceURL=');
155
159
  if (sourceURLIndex === -1) {
@@ -1877,7 +1877,7 @@ export function registerCommands(inspectorBackend) {
1877
1877
  // Overlay.
1878
1878
  inspectorBackend.registerEnum('Overlay.LineStylePattern', {Dashed: 'dashed', Dotted: 'dotted'});
1879
1879
  inspectorBackend.registerEnum('Overlay.ContrastAlgorithm', {Aa: 'aa', Aaa: 'aaa', Apca: 'apca'});
1880
- inspectorBackend.registerEnum('Overlay.ColorFormat', {Rgb: 'rgb', Hsl: 'hsl', Hex: 'hex'});
1880
+ inspectorBackend.registerEnum('Overlay.ColorFormat', {Rgb: 'rgb', Hsl: 'hsl', Hwb: 'hwb', Hex: 'hex'});
1881
1881
  inspectorBackend.registerEnum('Overlay.InspectMode', {
1882
1882
  SearchForNode: 'searchForNode',
1883
1883
  SearchForUAShadowDOM: 'searchForUAShadowDOM',
@@ -9587,6 +9587,7 @@ export namespace Overlay {
9587
9587
  export const enum ColorFormat {
9588
9588
  Rgb = 'rgb',
9589
9589
  Hsl = 'hsl',
9590
+ Hwb = 'hwb',
9590
9591
  Hex = 'hex',
9591
9592
  }
9592
9593
 
@@ -84,8 +84,9 @@ export class LayersWidget extends UI.Widget.Widget {
84
84
  const makeTreeNode = (parentId: string) =>
85
85
  (layer: Protocol.CSS.CSSLayerData): TreeOutline.TreeOutlineUtils.TreeNode<string> => {
86
86
  const subLayers = layer.subLayers;
87
- const treeNodeData = layer.order + ': ' + layer.name;
88
- const id = parentId ? parentId + '.' + layer.name : layer.name;
87
+ const name = SDK.CSSModel.CSSModel.readableLayerName(layer.name);
88
+ const treeNodeData = layer.order + ': ' + name;
89
+ const id = parentId ? parentId + '.' + name : name;
89
90
  if (!subLayers) {
90
91
  return {treeNodeData, id};
91
92
  }
@@ -875,7 +875,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
875
875
  if (parentRule instanceof SDK.CSSRule.CSSStyleRule) {
876
876
  const layers = parentRule.layers;
877
877
  if ((layers.length || lastLayers) && lastLayers !== layers) {
878
- const block = SectionBlock.createLayerBlock(layers);
878
+ const block = SectionBlock.createLayerBlock(parentRule);
879
879
  blocks.push(block);
880
880
  sawLayers = true;
881
881
  lastLayers = layers;
@@ -1430,18 +1430,21 @@ export class SectionBlock {
1430
1430
  return new SectionBlock(separatorElement);
1431
1431
  }
1432
1432
 
1433
- static createLayerBlock(layers: SDK.CSSLayer.CSSLayer[]): SectionBlock {
1433
+ static createLayerBlock(rule: SDK.CSSRule.CSSStyleRule): SectionBlock {
1434
1434
  const separatorElement = document.createElement('div');
1435
1435
  separatorElement.className = 'sidebar-separator layer-separator';
1436
1436
  UI.UIUtils.createTextChild(separatorElement.createChild('div'), i18nString(UIStrings.layer));
1437
- if (!layers.length) {
1438
- UI.UIUtils.createTextChild(separatorElement.createChild('div'), '\xa0user\xa0agent\xa0stylesheet');
1437
+ const layers = rule.layers;
1438
+ if (!layers.length && rule.origin === Protocol.CSS.StyleSheetOrigin.UserAgent) {
1439
+ const name = rule.origin === Protocol.CSS.StyleSheetOrigin.UserAgent ? '\xa0user\xa0agent\xa0stylesheet' :
1440
+ '\xa0implicit\xa0outer\xa0layer';
1441
+ UI.UIUtils.createTextChild(separatorElement.createChild('div'), name);
1439
1442
  return new SectionBlock(separatorElement);
1440
1443
  }
1441
1444
  const layerLink = separatorElement.createChild('button') as HTMLButtonElement;
1442
1445
  layerLink.className = 'link';
1443
1446
  layerLink.title = i18nString(UIStrings.clickToRevealLayer);
1444
- const name = layers.map(layer => layer.text || '<anonymous>').join('.');
1447
+ const name = layers.map(layer => SDK.CSSModel.CSSModel.readableLayerName(layer.text)).join('.');
1445
1448
  layerLink.textContent = name;
1446
1449
  layerLink.onclick = (): Promise<void> => LayersWidget.LayersWidget.instance().revealLayer(name);
1447
1450
  return new SectionBlock(separatorElement);
@@ -8,7 +8,7 @@ import type * as Host from '../../../core/host/host.js';
8
8
  import * as i18n from '../../../core/i18n/i18n.js';
9
9
  import * as LitHtml from '../../../ui/lit-html/lit-html.js';
10
10
  import * as Settings from '../../../ui/components/settings/settings.js';
11
- import * as SDK from '../../../core/sdk/sdk.js';
11
+ import * as ChromeLink from '../../../ui/components/chrome_link/chrome_link.js';
12
12
 
13
13
  import syncSectionStyles from './syncSection.css.js';
14
14
 
@@ -92,9 +92,8 @@ function renderAccountInfoOrWarning(syncInfo: Host.InspectorFrontendHostAPI.Sync
92
92
  // clang-format off
93
93
  return LitHtml.html`
94
94
  <span class="warning">
95
- ${i18nString(UIStrings.syncDisabled)} <a href=${link} class="link" target="_blank"
96
- @click=${(e: Event): void => openSettingsTab(link, e)}
97
- @keydown=${(e: Event): void => openSettingsTab(link, e)}>${i18nString(UIStrings.settings)}</x-link>
95
+ ${i18nString(UIStrings.syncDisabled)}
96
+ <${ChromeLink.ChromeLink.ChromeLink.litTagName} .href=${link}>${i18nString(UIStrings.settings)}</${ChromeLink.ChromeLink.ChromeLink.litTagName}>
98
97
  </span>`;
99
98
  // clang-format on
100
99
  }
@@ -104,9 +103,8 @@ function renderAccountInfoOrWarning(syncInfo: Host.InspectorFrontendHostAPI.Sync
104
103
  // clang-format off
105
104
  return LitHtml.html`
106
105
  <span class="warning">
107
- ${i18nString(UIStrings.preferencesSyncDisabled)} <a href=${link} class="link" target="_blank"
108
- @click=${(e: Event): void => openSettingsTab(link, e)}
109
- @keydown=${(e: Event): void => openSettingsTab(link, e)}>${i18nString(UIStrings.settings)}</x-link>
106
+ ${i18nString(UIStrings.preferencesSyncDisabled)}
107
+ <${ChromeLink.ChromeLink.ChromeLink.litTagName} .href=${link}>${i18nString(UIStrings.settings)}</${ChromeLink.ChromeLink.ChromeLink.litTagName}>
110
108
  </span>`;
111
109
  // clang-format on
112
110
  }
@@ -120,16 +118,6 @@ function renderAccountInfoOrWarning(syncInfo: Host.InspectorFrontendHostAPI.Sync
120
118
  </div>`;
121
119
  }
122
120
 
123
- // Navigating to a chrome:// link via a normal anchor doesn't work, so we "navigate"
124
- // there using CDP.
125
- function openSettingsTab(url: string, event: Event): void {
126
- if (event.type === 'click' || (event.type === 'keydown' && self.isEnterOrSpaceKey(event))) {
127
- const mainTarget = SDK.TargetManager.TargetManager.instance().mainTarget();
128
- mainTarget && mainTarget.targetAgent().invoke_createTarget({url});
129
- event.consume(true);
130
- }
131
- }
132
-
133
121
  ComponentHelpers.CustomElements.defineComponent('devtools-sync-section', SyncSection);
134
122
 
135
123
  declare global {
@@ -4,13 +4,17 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
+ import * as Platform from '../../core/platform/platform.js';
7
8
  import * as SDK from '../../core/sdk/sdk.js';
9
+ import type * as Protocol from '../../generated/protocol.js';
8
10
  import type * as Workspace from '../../models/workspace/workspace.js';
9
11
  import * as ColorPicker from '../../ui/legacy/components/color_picker/color_picker.js';
10
12
  import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
11
13
  import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
14
+ import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
12
15
  import * as UI from '../../ui/legacy/legacy.js';
13
16
 
17
+ import {assertNotNullOrUndefined} from '../../core/platform/platform.js';
14
18
  import {Plugin} from './Plugin.js';
15
19
 
16
20
  // Plugin to add CSS completion, shortcuts, and color/curve swatches
@@ -29,17 +33,6 @@ const UIStrings = {
29
33
  const str_ = i18n.i18n.registerUIStrings('panels/sources/CSSPlugin.ts', UIStrings);
30
34
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
31
35
 
32
- export function completion(): CodeMirror.Extension {
33
- const {cssCompletionSource} = CodeMirror.css;
34
- return CodeMirror.autocompletion({
35
- override:
36
- [async(cx: CodeMirror.CompletionContext):
37
- Promise<CodeMirror.CompletionResult|null> => {
38
- return (await specificCssCompletion(cx)) || cssCompletionSource(cx);
39
- }],
40
- });
41
- }
42
-
43
36
  const dontCompleteIn = new Set(['ColorLiteral', 'NumberLiteral', 'StringLiteral', 'Comment', 'Important']);
44
37
 
45
38
  function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.SyntaxNode|null {
@@ -57,18 +50,43 @@ function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.Sy
57
50
  return null;
58
51
  }
59
52
 
60
- function specificCssCompletion(cx: CodeMirror.CompletionContext): CodeMirror.CompletionResult|null {
53
+ function getCurrentStyleSheet(
54
+ url: Platform.DevToolsPath.UrlString, cssModel: SDK.CSSModel.CSSModel): Protocol.CSS.StyleSheetId {
55
+ const currentStyleSheet = cssModel.getStyleSheetIdsForURL(url);
56
+ if (currentStyleSheet.length === 0) {
57
+ Platform.DCHECK(() => currentStyleSheet.length !== 0, 'Can\'t find style sheet ID for current URL');
58
+ }
59
+
60
+ return currentStyleSheet[0];
61
+ }
62
+
63
+ async function specificCssCompletion(
64
+ cx: CodeMirror.CompletionContext, uiSourceCode: Workspace.UISourceCode.UISourceCode,
65
+ cssModel: SDK.CSSModel.CSSModel|undefined): Promise<CodeMirror.CompletionResult|null> {
61
66
  const node = CodeMirror.syntaxTree(cx.state).resolveInner(cx.pos, -1);
67
+ if (node.name === 'ClassName') {
68
+ // Should never happen, but let's code defensively here
69
+ assertNotNullOrUndefined(cssModel);
70
+
71
+ const currentStyleSheet = getCurrentStyleSheet(uiSourceCode.url(), cssModel);
72
+ const existingClassNames = await cssModel.classNamesPromise(currentStyleSheet);
73
+
74
+ return {
75
+ from: node.from,
76
+ options: existingClassNames.map(value => ({type: 'constant', label: value})),
77
+ };
78
+ }
62
79
  const property = findPropertyAt(node, cx.pos);
63
- if (!property) {
64
- return null;
80
+ if (property) {
81
+ const propertyValues =
82
+ SDK.CSSMetadata.cssMetadata().getPropertyValues(cx.state.sliceDoc(property.from, property.to));
83
+ return {
84
+ from: node.name === 'ValueName' ? node.from : cx.pos,
85
+ options: propertyValues.map(value => ({type: 'constant', label: value})),
86
+ span: /^[\w\P{ASCII}\-]+$/u,
87
+ };
65
88
  }
66
- const propertyValues = SDK.CSSMetadata.cssMetadata().getPropertyValues(cx.state.sliceDoc(property.from, property.to));
67
- return {
68
- from: node.name === 'ValueName' ? node.from : cx.pos,
69
- options: propertyValues.map(value => ({type: 'constant', label: value})),
70
- span: /^[\w\P{ASCII}\-]+$/u,
71
- };
89
+ return null;
72
90
  }
73
91
 
74
92
  function findColorsAndCurves(
@@ -380,12 +398,49 @@ export function cssBindings(): CodeMirror.Extension {
380
398
  });
381
399
  }
382
400
 
383
- export class CSSPlugin extends Plugin {
401
+ export class CSSPlugin extends Plugin implements SDK.TargetManager.SDKModelObserver<SDK.CSSModel.CSSModel> {
402
+ #cssModel?: SDK.CSSModel.CSSModel;
403
+
404
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode, _transformer?: SourceFrame.SourceFrame.Transformer) {
405
+ super(uiSourceCode, _transformer);
406
+ SDK.TargetManager.TargetManager.instance().observeModels(SDK.CSSModel.CSSModel, this);
407
+ }
408
+
384
409
  static accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
385
410
  return uiSourceCode.contentType().isStyleSheet();
386
411
  }
387
412
 
413
+ modelAdded(cssModel: SDK.CSSModel.CSSModel): void {
414
+ if (this.#cssModel) {
415
+ return;
416
+ }
417
+ this.#cssModel = cssModel;
418
+ }
419
+ modelRemoved(cssModel: SDK.CSSModel.CSSModel): void {
420
+ if (this.#cssModel === cssModel) {
421
+ this.#cssModel = undefined;
422
+ }
423
+ }
424
+
388
425
  editorExtension(): CodeMirror.Extension {
389
- return [cssBindings(), completion(), cssSwatches()];
426
+ return [cssBindings(), this.#cssCompletion(), cssSwatches()];
427
+ }
428
+
429
+ #cssCompletion(): CodeMirror.Extension {
430
+ const {cssCompletionSource} = CodeMirror.css;
431
+
432
+ // CodeMirror binds the function below to the state object.
433
+ // Therefore, we can't access `this` and retrieve the following properties.
434
+ // Instead, retrieve them up front to bind them to the correct closure.
435
+ const uiSourceCode = this.uiSourceCode;
436
+ const cssModel = this.#cssModel;
437
+
438
+ return CodeMirror.autocompletion({
439
+ override:
440
+ [async(cx: CodeMirror.CompletionContext):
441
+ Promise<CodeMirror.CompletionResult|null> => {
442
+ return (await specificCssCompletion(cx, uiSourceCode, cssModel)) || cssCompletionSource(cx);
443
+ }],
444
+ });
390
445
  }
391
446
  }
@@ -0,0 +1,62 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as SDK from '../../../core/sdk/sdk.js';
6
+ import * as LitHtml from '../../lit-html/lit-html.js';
7
+ import * as ComponentHelpers from '../helpers/helpers.js';
8
+
9
+ import chromeLinkStyles from './chromeLink.css.js';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'devtools-chrome-link': ChromeLink;
14
+ }
15
+ }
16
+
17
+ // Use this component to render links to 'chrome://...'-URLs
18
+ // (for which regular <x-link>s do not work).
19
+ export class ChromeLink extends HTMLElement {
20
+ static readonly litTagName = LitHtml.literal`devtools-chrome-link`;
21
+ readonly #shadow = this.attachShadow({mode: 'open'});
22
+ readonly #boundRender = this.#render.bind(this);
23
+ #href: string = '';
24
+
25
+ connectedCallback(): void {
26
+ this.#shadow.adoptedStyleSheets = [chromeLinkStyles];
27
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
28
+ }
29
+
30
+ set href(href: string) {
31
+ if (!href.startsWith('chrome://')) {
32
+ throw new Error('ChromeLink href needs to start with \'chrome://\'');
33
+ }
34
+ this.#href = href;
35
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
36
+ }
37
+
38
+ // Navigating to a chrome:// link via a normal anchor doesn't work, so we "navigate"
39
+ // there using CDP.
40
+ openSettingsTab(event: Event): void {
41
+ if (event.type === 'click' || (event.type === 'keydown' && self.isEnterOrSpaceKey(event))) {
42
+ const mainTarget = SDK.TargetManager.TargetManager.instance().mainTarget();
43
+ mainTarget && mainTarget.targetAgent().invoke_createTarget({url: this.#href});
44
+ event.consume(true);
45
+ }
46
+ }
47
+
48
+ #render(): void {
49
+ // clang-format off
50
+ LitHtml.render(
51
+ /* x-link doesn't work with custom click/keydown handlers */
52
+ /* eslint-disable rulesdir/ban_a_tags_in_lit_html */
53
+ LitHtml.html`
54
+ <a href=${this.#href} class="link" target="_blank"
55
+ @click=${this.openSettingsTab}
56
+ @keydown=${this.openSettingsTab}><slot></slot></a>
57
+ `, this.#shadow, {host: this});
58
+ // clang-format on
59
+ }
60
+ }
61
+
62
+ ComponentHelpers.CustomElements.defineComponent('devtools-chrome-link', ChromeLink);
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright 2022 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
+ .link {
8
+ color: var(--color-link);
9
+ text-decoration: underline;
10
+ cursor: pointer;
11
+ padding: 2px 0; /* adjust focus ring size */
12
+ }
@@ -0,0 +1,9 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as ChromeLink from './ChromeLink.js';
6
+
7
+ export {
8
+ ChromeLink,
9
+ };
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
55
55
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
56
56
  },
57
- "version": "1.0.975541"
57
+ "version": "1.0.976570"
58
58
  }