chrome-devtools-frontend 1.0.976172 → 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/config/gni/devtools_grd_files.gni +2 -0
- package/config/gni/devtools_image_files.gni +2 -0
- package/front_end/Images/src/minus_icon.svg +3 -0
- package/front_end/Images/src/plus_icon.svg +3 -0
- package/front_end/core/sdk/CSSModel.ts +4 -0
- package/front_end/panels/elements/LayersWidget.ts +3 -2
- package/front_end/panels/elements/StylesSidebarPane.ts +8 -5
- package/front_end/panels/sources/CSSPlugin.ts +77 -22
- package/package.json +1 -1
@@ -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",
|
@@ -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",
|
@@ -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) {
|
@@ -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
|
88
|
-
const
|
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(
|
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(
|
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
|
-
|
1438
|
-
|
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
|
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);
|
@@ -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
|
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 (
|
64
|
-
|
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
|
-
|
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(),
|
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
|
}
|
package/package.json
CHANGED