chrome-devtools-frontend 1.0.978040 → 1.0.979150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/front_end/.eslintrc.js +1 -0
- package/front_end/core/sdk/CSSRule.ts +3 -2
- package/front_end/core/sdk/CSSStyleSheetHeader.ts +21 -9
- package/front_end/core/sdk/ResourceTreeModel.ts +3 -3
- package/front_end/entrypoints/formatter_worker/FormatterActions.ts +1 -0
- package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +2 -2
- package/front_end/entrypoints/formatter_worker/Substitute.ts +8 -3
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +7 -1
- package/front_end/models/formatter/FormatterWorkerPool.ts +11 -3
- package/front_end/panels/application/AppManifestView.ts +13 -16
- package/front_end/panels/console/ConsolePrompt.ts +8 -6
- package/front_end/panels/console/ErrorStackParser.ts +1 -5
- package/front_end/panels/elements/StylesSidebarPane.ts +8 -13
- package/front_end/panels/elements/components/computedStyleProperty.css +1 -0
- package/front_end/panels/elements/components/computedStyleTrace.css +1 -0
- package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +2 -1
- package/front_end/panels/webauthn/webauthnPane.css +6 -2
- package/front_end/ui/legacy/components/utils/ImagePreview.ts +1 -1
- package/package.json +1 -1
- package/scripts/eslint_rules/lib/no_importing_images_from_src.js +61 -0
- package/scripts/eslint_rules/tests/no_importing_images_from_src_test.js +40 -0
package/front_end/.eslintrc.js
CHANGED
@@ -27,6 +27,7 @@ module.exports = {
|
|
27
27
|
'files': ['*.ts'],
|
28
28
|
'rules': {
|
29
29
|
'@typescript-eslint/explicit-function-return-type': 2,
|
30
|
+
'rulesdir/no_importing_images_from_src': 2,
|
30
31
|
'rulesdir/enforce_custom_event_names': 2,
|
31
32
|
'rulesdir/set_data_type_reference': 2,
|
32
33
|
'rulesdir/lit_html_data_as_type': 2,
|
@@ -2,6 +2,7 @@
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
|
+
import type * as Platform from '../platform/platform.js';
|
5
6
|
import * as Protocol from '../../generated/protocol.js';
|
6
7
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
7
8
|
|
@@ -44,9 +45,9 @@ export class CSSRule {
|
|
44
45
|
this.style.rebase(edit);
|
45
46
|
}
|
46
47
|
|
47
|
-
resourceURL():
|
48
|
+
resourceURL(): Platform.DevToolsPath.UrlString {
|
48
49
|
if (!this.styleSheetId) {
|
49
|
-
return '';
|
50
|
+
return '' as Platform.DevToolsPath.UrlString;
|
50
51
|
}
|
51
52
|
const styleSheetHeader = this.getStyleSheetHeader(this.styleSheetId);
|
52
53
|
return styleSheetHeader.resourceURL();
|
@@ -6,6 +6,7 @@ import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
6
6
|
import * as Common from '../common/common.js';
|
7
7
|
import * as i18n from '../i18n/i18n.js';
|
8
8
|
import type * as Platform from '../platform/platform.js';
|
9
|
+
import * as Root from '../root/root.js';
|
9
10
|
import type * as Protocol from '../../generated/protocol.js';
|
10
11
|
|
11
12
|
import type {CSSModel} from './CSSModel.js';
|
@@ -104,27 +105,38 @@ export class CSSStyleSheetHeader implements TextUtils.ContentProvider.ContentPro
|
|
104
105
|
}
|
105
106
|
|
106
107
|
resourceURL(): Platform.DevToolsPath.UrlString {
|
107
|
-
|
108
|
+
const url = this.isViaInspector() ? this.viaInspectorResourceURL() : this.sourceURL;
|
109
|
+
if (!url && Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES)) {
|
110
|
+
return this.dynamicStyleURL();
|
111
|
+
}
|
112
|
+
return url;
|
108
113
|
}
|
109
114
|
|
110
|
-
private
|
115
|
+
private getFrameURLPath(): string {
|
111
116
|
const model = this.#cssModelInternal.target().model(ResourceTreeModel);
|
112
117
|
console.assert(Boolean(model));
|
113
118
|
if (!model) {
|
114
|
-
return ''
|
119
|
+
return '';
|
115
120
|
}
|
116
121
|
const frame = model.frameForId(this.frameId);
|
117
122
|
if (!frame) {
|
118
|
-
return ''
|
123
|
+
return '';
|
119
124
|
}
|
120
125
|
console.assert(Boolean(frame));
|
121
126
|
const parsedURL = new Common.ParsedURL.ParsedURL(frame.url);
|
122
|
-
let
|
123
|
-
if (!
|
124
|
-
|
127
|
+
let urlPath = parsedURL.host + parsedURL.folderPathComponents;
|
128
|
+
if (!urlPath.endsWith('/')) {
|
129
|
+
urlPath += '/';
|
125
130
|
}
|
126
|
-
|
127
|
-
|
131
|
+
return urlPath;
|
132
|
+
}
|
133
|
+
|
134
|
+
private viaInspectorResourceURL(): Platform.DevToolsPath.UrlString {
|
135
|
+
return `inspector://${this.getFrameURLPath()}inspector-stylesheet` as Platform.DevToolsPath.UrlString;
|
136
|
+
}
|
137
|
+
|
138
|
+
private dynamicStyleURL(): Platform.DevToolsPath.UrlString {
|
139
|
+
return `stylesheet://${this.getFrameURLPath()}style#${this.id}` as Platform.DevToolsPath.UrlString;
|
128
140
|
}
|
129
141
|
|
130
142
|
lineNumberInSource(lineNumberInStyleSheet: number): number {
|
@@ -423,15 +423,15 @@ export class ResourceTreeModel extends SDKModel<EventTypes> {
|
|
423
423
|
}
|
424
424
|
|
425
425
|
async fetchAppManifest(): Promise<{
|
426
|
-
url:
|
426
|
+
url: Platform.DevToolsPath.UrlString,
|
427
427
|
data: string|null,
|
428
428
|
errors: Array<Protocol.Page.AppManifestError>,
|
429
429
|
}> {
|
430
430
|
const response = await this.agent.invoke_getAppManifest();
|
431
431
|
if (response.getError()) {
|
432
|
-
return {url: response.url, data: null, errors: []};
|
432
|
+
return {url: response.url as Platform.DevToolsPath.UrlString, data: null, errors: []};
|
433
433
|
}
|
434
|
-
return {url: response.url, data: response.data || null, errors: response.errors};
|
434
|
+
return {url: response.url as Platform.DevToolsPath.UrlString, data: response.data || null, errors: response.errors};
|
435
435
|
}
|
436
436
|
|
437
437
|
async getInstallabilityErrors(): Promise<Protocol.Page.InstallabilityError[]> {
|
@@ -8,6 +8,7 @@ export const enum FormatterActions {
|
|
8
8
|
HTML_OUTLINE = 'htmlOutline',
|
9
9
|
JAVASCRIPT_OUTLINE = 'javaScriptOutline',
|
10
10
|
JAVASCRIPT_IDENTIFIERS = 'javaScriptIdentifiers',
|
11
|
+
JAVASCRIPT_SUBSTITUTE = 'javaScriptSubstitute',
|
11
12
|
EVALUATE_JAVASCRIPT_SUBSTRING = 'evaluatableJavaScriptSubstring',
|
12
13
|
ARGUMENTS_LIST = 'argumentsList',
|
13
14
|
}
|
@@ -42,7 +42,7 @@ import {HTMLFormatter} from './HTMLFormatter.js';
|
|
42
42
|
import {IdentityFormatter} from './IdentityFormatter.js';
|
43
43
|
import {JavaScriptFormatter} from './JavaScriptFormatter.js';
|
44
44
|
import {JSONFormatter} from './JSONFormatter.js';
|
45
|
-
import {
|
45
|
+
import {substituteExpression} from './Substitute.js';
|
46
46
|
|
47
47
|
export interface Chunk {
|
48
48
|
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
|
@@ -306,4 +306,4 @@ export function argumentsList(content: string): string[] {
|
|
306
306
|
}
|
307
307
|
})();
|
308
308
|
|
309
|
-
export {
|
309
|
+
export {substituteExpression};
|
@@ -6,7 +6,12 @@ import * as Acorn from '../../third_party/acorn/acorn.js';
|
|
6
6
|
|
7
7
|
import {ECMA_VERSION} from './AcornTokenizer.js';
|
8
8
|
|
9
|
-
export
|
9
|
+
export function substituteExpression(expression: string, nameMap: Map<string, string>): string {
|
10
|
+
const replacements = computeSubstitution(expression, nameMap);
|
11
|
+
return applySubstitution(expression, replacements);
|
12
|
+
}
|
13
|
+
|
14
|
+
interface Replacement {
|
10
15
|
from: string;
|
11
16
|
to: string;
|
12
17
|
offset: number;
|
@@ -17,7 +22,7 @@ export interface Replacement {
|
|
17
22
|
// function returns a list of replacements sorted by the offset. The function throws if
|
18
23
|
// it cannot parse the expression or the substitution is impossible to perform (for example
|
19
24
|
// if the substitution target is 'this' within a function, it would become bound there).
|
20
|
-
|
25
|
+
function computeSubstitution(expression: string, nameMap: Map<string, string>): Replacement[] {
|
21
26
|
// Parse the expression and find variables and scopes.
|
22
27
|
const root = Acorn.parse(expression, {ecmaVersion: ECMA_VERSION, allowAwaitOutsideFunction: true, ranges: false}) as
|
23
28
|
Acorn.ESTree.Node;
|
@@ -80,7 +85,7 @@ export function computeSubstitution(expression: string, nameMap: Map<string, str
|
|
80
85
|
return result;
|
81
86
|
}
|
82
87
|
|
83
|
-
|
88
|
+
function applySubstitution(expression: string, replacements: Replacement[]): string {
|
84
89
|
const accumulator = [];
|
85
90
|
let last = 0;
|
86
91
|
for (const r of replacements) {
|
@@ -10,7 +10,8 @@ import {FormatterActions} from './FormatterActions.js';
|
|
10
10
|
|
11
11
|
self.onmessage = function(event: MessageEvent): void {
|
12
12
|
const method: FormatterActions = event.data.method;
|
13
|
-
const params: {indentString: string, content: string, mimeType: string} =
|
13
|
+
const params: {indentString: string, content: string, mimeType: string, mapping: [string, string][]} =
|
14
|
+
event.data.params;
|
14
15
|
if (!method) {
|
15
16
|
return;
|
16
17
|
}
|
@@ -31,6 +32,11 @@ self.onmessage = function(event: MessageEvent): void {
|
|
31
32
|
case FormatterActions.JAVASCRIPT_IDENTIFIERS:
|
32
33
|
self.postMessage(FormatterWorker.FormatterWorker.javaScriptIdentifiers(params.content));
|
33
34
|
break;
|
35
|
+
case FormatterActions.JAVASCRIPT_SUBSTITUTE: {
|
36
|
+
const mapping = new Map<string, string>(params.mapping);
|
37
|
+
self.postMessage(FormatterWorker.Substitute.substituteExpression(params.content, mapping));
|
38
|
+
break;
|
39
|
+
}
|
34
40
|
case FormatterActions.EVALUATE_JAVASCRIPT_SUBSTRING:
|
35
41
|
self.postMessage(FormatterWorker.FormatterWorker.evaluatableJavaScriptSubstring(params.content));
|
36
42
|
break;
|
@@ -108,7 +108,7 @@ export class FormatterWorkerPool {
|
|
108
108
|
}
|
109
109
|
|
110
110
|
private runTask(methodName: FormatterActions.FormatterActions, params: {
|
111
|
-
[x: string]: string,
|
111
|
+
[x: string]: string|string[][],
|
112
112
|
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
|
113
113
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
114
114
|
}): Promise<any> {
|
@@ -132,6 +132,14 @@ export class FormatterWorkerPool {
|
|
132
132
|
.then(ids => ids || []);
|
133
133
|
}
|
134
134
|
|
135
|
+
javaScriptSubstitute(expression: string, mapping: Map<string, string>): Promise<string> {
|
136
|
+
return this
|
137
|
+
.runTask(
|
138
|
+
FormatterActions.FormatterActions.JAVASCRIPT_SUBSTITUTE,
|
139
|
+
{content: expression, mapping: Array.from(mapping.entries())})
|
140
|
+
.then(result => result || '');
|
141
|
+
}
|
142
|
+
|
135
143
|
evaluatableJavaScriptSubstring(content: string): Promise<string> {
|
136
144
|
return this.runTask(FormatterActions.FormatterActions.EVALUATE_JAVASCRIPT_SUBSTRING, {content: content})
|
137
145
|
.then(text => text || '');
|
@@ -179,13 +187,13 @@ export class FormatterWorkerPool {
|
|
179
187
|
class Task {
|
180
188
|
method: string;
|
181
189
|
params: {
|
182
|
-
[x: string]: string,
|
190
|
+
[x: string]: string|string[][],
|
183
191
|
};
|
184
192
|
callback: (arg0: MessageEvent|null) => void;
|
185
193
|
isChunked: boolean|undefined;
|
186
194
|
constructor(
|
187
195
|
method: string, params: {
|
188
|
-
[x: string]: string,
|
196
|
+
[x: string]: string|string[][],
|
189
197
|
},
|
190
198
|
callback: (arg0: MessageEvent|null) => void, isChunked?: boolean) {
|
191
199
|
this.method = method;
|
@@ -16,8 +16,6 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
16
16
|
import type * as Protocol from '../../generated/protocol.js';
|
17
17
|
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
18
18
|
|
19
|
-
// TODO(crbug.com/1253323): Casts to UrlString will be removed from this file when migration to branded types is complete.
|
20
|
-
|
21
19
|
const UIStrings = {
|
22
20
|
/**
|
23
21
|
*@description Text in App Manifest View of the Application panel
|
@@ -543,7 +541,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
543
541
|
}
|
544
542
|
|
545
543
|
private async renderManifest(
|
546
|
-
url:
|
544
|
+
url: Platform.DevToolsPath.UrlString, data: string|null, errors: Protocol.Page.AppManifestError[],
|
547
545
|
installabilityErrors: Protocol.Page.InstallabilityError[], manifestIcons: {
|
548
546
|
primaryIcon: string|null,
|
549
547
|
},
|
@@ -642,12 +640,13 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
642
640
|
|
643
641
|
this.startURLField.removeChildren();
|
644
642
|
if (startURL) {
|
645
|
-
const completeURL =
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
643
|
+
const completeURL = Common.ParsedURL.ParsedURL.completeURL(url, startURL);
|
644
|
+
if (completeURL) {
|
645
|
+
const link = Components.Linkifier.Linkifier.linkifyURL(
|
646
|
+
completeURL, ({text: startURL} as Components.Linkifier.LinkifyURLOptions));
|
647
|
+
link.tabIndex = 0;
|
648
|
+
this.startURLField.appendChild(link);
|
649
|
+
}
|
651
650
|
}
|
652
651
|
|
653
652
|
this.themeColorSwatch.classList.toggle('hidden', !stringProperty('theme_color'));
|
@@ -694,8 +693,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
694
693
|
this.newNoteUrlField.parentElement?.classList.toggle('hidden', !hasNewNoteUrl);
|
695
694
|
this.newNoteUrlField.removeChildren();
|
696
695
|
if (hasNewNoteUrl) {
|
697
|
-
const completeURL =
|
698
|
-
(Common.ParsedURL.ParsedURL.completeURL(url as Platform.DevToolsPath.UrlString, newNoteUrl) as string);
|
696
|
+
const completeURL = (Common.ParsedURL.ParsedURL.completeURL(url, newNoteUrl) as string);
|
699
697
|
const link = Components.Linkifier.Linkifier.linkifyURL(
|
700
698
|
completeURL, ({text: newNoteUrl} as Components.Linkifier.LinkifyURLOptions));
|
701
699
|
link.tabIndex = 0;
|
@@ -765,8 +763,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
765
763
|
shortcutSection.appendFlexedField('Description', shortcut.description);
|
766
764
|
}
|
767
765
|
const urlField = shortcutSection.appendFlexedField('URL');
|
768
|
-
const shortcutUrl =
|
769
|
-
(Common.ParsedURL.ParsedURL.completeURL(url as Platform.DevToolsPath.UrlString, shortcut.url) as string);
|
766
|
+
const shortcutUrl = (Common.ParsedURL.ParsedURL.completeURL(url, shortcut.url) as string);
|
770
767
|
const link = Components.Linkifier.Linkifier.linkifyURL(
|
771
768
|
shortcutUrl, ({text: shortcut.url} as Components.Linkifier.LinkifyURLOptions));
|
772
769
|
link.tabIndex = 0;
|
@@ -1018,7 +1015,8 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
1018
1015
|
private async appendImageResourceToSection(
|
1019
1016
|
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
|
1020
1017
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1021
|
-
baseUrl:
|
1018
|
+
baseUrl: Platform.DevToolsPath.UrlString, imageResource: any, section: UI.ReportView.Section,
|
1019
|
+
isScreenshot: boolean):
|
1022
1020
|
Promise<{imageResourceErrors: Platform.UIString.LocalizedString[], squareSizedIconAvailable?: boolean}> {
|
1023
1021
|
const imageResourceErrors: Platform.UIString.LocalizedString[] = [];
|
1024
1022
|
const resourceName = isScreenshot ? i18nString(UIStrings.screenshot) : i18nString(UIStrings.icon);
|
@@ -1026,8 +1024,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
1026
1024
|
imageResourceErrors.push(i18nString(UIStrings.sSrcIsNotSet, {PH1: resourceName}));
|
1027
1025
|
return {imageResourceErrors};
|
1028
1026
|
}
|
1029
|
-
const imageUrl =
|
1030
|
-
Common.ParsedURL.ParsedURL.completeURL(baseUrl as Platform.DevToolsPath.UrlString, imageResource['src']);
|
1027
|
+
const imageUrl = Common.ParsedURL.ParsedURL.completeURL(baseUrl, imageResource['src']);
|
1031
1028
|
if (!imageUrl) {
|
1032
1029
|
imageResourceErrors.push(
|
1033
1030
|
i18nString(UIStrings.sUrlSFailedToParse, {PH1: resourceName, PH2: imageResource['src']}));
|
@@ -7,6 +7,7 @@ import * as Host from '../../core/host/host.js';
|
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
8
8
|
import * as Root from '../../core/root/root.js';
|
9
9
|
import * as SDK from '../../core/sdk/sdk.js';
|
10
|
+
import * as Formatter from '../../models/formatter/formatter.js';
|
10
11
|
import * as SourceMapScopes from '../../models/source_map_scopes/source_map_scopes.js';
|
11
12
|
import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
|
12
13
|
import * as TextEditor from '../../ui/components/text_editor/text_editor.js';
|
@@ -309,7 +310,7 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
309
310
|
const callFrame = executionContext.debuggerModel.selectedCallFrame();
|
310
311
|
if (callFrame) {
|
311
312
|
const nameMap = await SourceMapScopes.NamesResolver.allVariablesInCallFrame(callFrame);
|
312
|
-
expression = this.substituteNames(expression, nameMap);
|
313
|
+
expression = await this.substituteNames(expression, nameMap);
|
313
314
|
}
|
314
315
|
}
|
315
316
|
|
@@ -317,11 +318,12 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
317
318
|
executionContext, message, expression, useCommandLineAPI);
|
318
319
|
}
|
319
320
|
|
320
|
-
private substituteNames(expression: string, mapping: Map<string, string>): string {
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
321
|
+
private async substituteNames(expression: string, mapping: Map<string, string>): Promise<string> {
|
322
|
+
try {
|
323
|
+
return await Formatter.FormatterWorkerPool.formatterWorkerPool().javaScriptSubstitute(expression, mapping);
|
324
|
+
} catch {
|
325
|
+
return expression;
|
326
|
+
}
|
325
327
|
}
|
326
328
|
|
327
329
|
private editorUpdate(update: CodeMirror.ViewUpdate): void {
|
@@ -3,7 +3,6 @@
|
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
6
|
-
import type * as Platform from '../../core/platform/platform.js';
|
7
6
|
import type * as SDK from '../../core/sdk/sdk.js';
|
8
7
|
import type * as Protocol from '../../generated/protocol.js';
|
9
8
|
|
@@ -81,10 +80,7 @@ export function parseSourcePositionsFromErrorStack(
|
|
81
80
|
}
|
82
81
|
let url = parseOrScriptMatch(debuggerModel, splitResult.url);
|
83
82
|
if (!url && Common.ParsedURL.ParsedURL.isRelativeURL(splitResult.url)) {
|
84
|
-
|
85
|
-
url = parseOrScriptMatch(
|
86
|
-
debuggerModel,
|
87
|
-
Common.ParsedURL.ParsedURL.completeURL(baseURL as Platform.DevToolsPath.UrlString, splitResult.url));
|
83
|
+
url = parseOrScriptMatch(debuggerModel, Common.ParsedURL.ParsedURL.completeURL(baseURL, splitResult.url));
|
88
84
|
}
|
89
85
|
if (!url) {
|
90
86
|
return null;
|
@@ -219,9 +219,7 @@ const HIGHLIGHTABLE_PROPERTIES = [
|
|
219
219
|
{mode: 'flexibility', properties: ['flex', 'flex-basis', 'flex-grow', 'flex-shrink']},
|
220
220
|
];
|
221
221
|
|
222
|
-
|
223
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
224
|
-
let _stylesSidebarPaneInstance: StylesSidebarPane;
|
222
|
+
let stylesSidebarPaneInstance: StylesSidebarPane;
|
225
223
|
|
226
224
|
// TODO(crbug.com/1172300) This workaround is needed to keep the linter happy.
|
227
225
|
// Otherwise it complains about: Unknown word CssSyntaxError
|
@@ -258,10 +256,10 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
258
256
|
#urlToChangeTracker: Map<string, ChangeTracker> = new Map();
|
259
257
|
|
260
258
|
static instance(): StylesSidebarPane {
|
261
|
-
if (!
|
262
|
-
|
259
|
+
if (!stylesSidebarPaneInstance) {
|
260
|
+
stylesSidebarPaneInstance = new StylesSidebarPane();
|
263
261
|
}
|
264
|
-
return
|
262
|
+
return stylesSidebarPaneInstance;
|
265
263
|
}
|
266
264
|
|
267
265
|
private constructor() {
|
@@ -292,7 +290,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
292
290
|
this.swatchPopoverHelperInternal = new InlineEditor.SwatchPopoverHelper.SwatchPopoverHelper();
|
293
291
|
this.swatchPopoverHelperInternal.addEventListener(
|
294
292
|
InlineEditor.SwatchPopoverHelper.Events.WillShowPopover, this.hideAllPopovers, this);
|
295
|
-
this.linkifier = new Components.Linkifier.Linkifier(
|
293
|
+
this.linkifier = new Components.Linkifier.Linkifier(MAX_LINK_LENGTH, /* useLinkDecorator */ true);
|
296
294
|
this.decorator = new StylePropertyHighlighter(this);
|
297
295
|
this.lastRevealedProperty = null;
|
298
296
|
this.userOperation = false;
|
@@ -307,7 +305,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
307
305
|
this.sectionBlocks = [];
|
308
306
|
this.idleCallbackManager = null;
|
309
307
|
this.needsForceUpdate = false;
|
310
|
-
|
308
|
+
stylesSidebarPaneInstance = this;
|
311
309
|
UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.forceUpdate, this);
|
312
310
|
this.contentElement.addEventListener('copy', this.clipboardCopy.bind(this));
|
313
311
|
this.resizeThrottler = new Common.Throttler.Throttler(100);
|
@@ -1392,9 +1390,7 @@ async function buildPropertyRuleMaps(content: string):
|
|
1392
1390
|
return {propertyToSelector, ruleToSelector};
|
1393
1391
|
}
|
1394
1392
|
|
1395
|
-
|
1396
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
1397
|
-
export const _maxLinkLength = 23;
|
1393
|
+
const MAX_LINK_LENGTH = 23;
|
1398
1394
|
|
1399
1395
|
export class SectionBlock {
|
1400
1396
|
private readonly titleElementInternal: Element|null;
|
@@ -3461,8 +3457,7 @@ export class StylesSidebarPropertyRenderer {
|
|
3461
3457
|
UI.UIUtils.createTextChild(container, 'url(');
|
3462
3458
|
let hrefUrl: (string|null)|null = null;
|
3463
3459
|
if (this.rule && this.rule.resourceURL()) {
|
3464
|
-
|
3465
|
-
hrefUrl = Common.ParsedURL.ParsedURL.completeURL(this.rule.resourceURL() as Platform.DevToolsPath.UrlString, url);
|
3460
|
+
hrefUrl = Common.ParsedURL.ParsedURL.completeURL(this.rule.resourceURL(), url);
|
3466
3461
|
} else if (this.node) {
|
3467
3462
|
hrefUrl = this.node.resolveURL(url);
|
3468
3463
|
}
|
@@ -13,6 +13,8 @@ import type * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
13
13
|
import * as UI from '../../ui/legacy/legacy.js';
|
14
14
|
import * as Workspace from '../../models/workspace/workspace.js';
|
15
15
|
|
16
|
+
// TODO(crbug.com/1253323): Cast to EncodedPathString will be removed from this file when migration to branded types is complete.
|
17
|
+
|
16
18
|
const UIStrings = {
|
17
19
|
/**
|
18
20
|
*@description Default snippet name when a new snippet is created in the Sources panel
|
@@ -40,7 +42,6 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
40
42
|
private readonly lastSnippetIdentifierSetting: Common.Settings.Setting<number>;
|
41
43
|
private readonly snippetsSetting: Common.Settings.Setting<Snippet[]>;
|
42
44
|
constructor() {
|
43
|
-
// TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
|
44
45
|
super('snippet://', 'snippets');
|
45
46
|
this.lastSnippetIdentifierSetting =
|
46
47
|
Common.Settings.Settings.instance().createSetting('scriptSnippets_lastIdentifier', 0);
|
@@ -75,14 +75,18 @@
|
|
75
75
|
margin: auto;
|
76
76
|
}
|
77
77
|
|
78
|
+
.authenticator-section-header {
|
79
|
+
display: flex;
|
80
|
+
justify-content: space-between;
|
81
|
+
align-items: flex-end;
|
82
|
+
}
|
83
|
+
|
78
84
|
.authenticator-section-title {
|
79
85
|
line-height: 24px;
|
80
|
-
width: 260px;
|
81
86
|
display: inline-block;
|
82
87
|
}
|
83
88
|
|
84
89
|
.authenticator-section-title .authenticator-name-field {
|
85
|
-
width: 220px;
|
86
90
|
display: inline-block;
|
87
91
|
font-weight: bold;
|
88
92
|
border: none;
|
@@ -178,7 +178,7 @@ export class ImagePreview {
|
|
178
178
|
|
179
179
|
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
|
180
180
|
// @ts-expect-error
|
181
|
-
const featuresObject = object.callFunctionJSON(features, undefined);
|
181
|
+
const featuresObject = await object.callFunctionJSON(features, undefined);
|
182
182
|
object.release();
|
183
183
|
return featuresObject;
|
184
184
|
|
package/package.json
CHANGED
@@ -0,0 +1,61 @@
|
|
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
|
+
'use strict';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @fileoverview Prevent importing SVG urls from the `src` directory, and
|
8
|
+
* ensure they are read from `Images/foo.svg`.
|
9
|
+
* Images in the `src/` directory are minified and put into `Images/` as part
|
10
|
+
* of the build process, so we should never import from 'src'.
|
11
|
+
*/
|
12
|
+
|
13
|
+
// ------------------------------------------------------------------------------
|
14
|
+
// Rule Definition
|
15
|
+
// ------------------------------------------------------------------------------
|
16
|
+
|
17
|
+
const SRC_DIRECTORY_PATH_TO_MATCH = 'Images/src/';
|
18
|
+
|
19
|
+
module.exports = {
|
20
|
+
meta: {
|
21
|
+
type: 'problem',
|
22
|
+
|
23
|
+
docs: {
|
24
|
+
description: 'ensure image imports do not include the src/ directory',
|
25
|
+
category: 'Possible Errors',
|
26
|
+
},
|
27
|
+
fixable: 'code',
|
28
|
+
schema: [],
|
29
|
+
messages: {
|
30
|
+
imageImportUsingSrc:
|
31
|
+
'Found an image import containing the `src/` directory. You should always import `Images/foo.svg`.',
|
32
|
+
},
|
33
|
+
},
|
34
|
+
create: function(context) {
|
35
|
+
return {
|
36
|
+
// Matches new URL(...)
|
37
|
+
'NewExpression[callee.name=\'URL\']'(node) {
|
38
|
+
if (!node.arguments || node.arguments.length < 1) {
|
39
|
+
// Invalid code: user is probably mid-way through typing! Just leave
|
40
|
+
// it; TypeScript will error if it ends up being invalid.
|
41
|
+
return;
|
42
|
+
}
|
43
|
+
/** @type {String} */
|
44
|
+
const filePath = node.arguments[0].value;
|
45
|
+
if (!filePath) {
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
if (filePath.includes(SRC_DIRECTORY_PATH_TO_MATCH)) {
|
49
|
+
context.report({
|
50
|
+
node: node.arguments[0],
|
51
|
+
messageId: 'imageImportUsingSrc',
|
52
|
+
fix(fixer) {
|
53
|
+
return fixer.replaceText(
|
54
|
+
node.arguments[0], `'${filePath.replace(SRC_DIRECTORY_PATH_TO_MATCH, 'Images/')}'`);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
}
|
58
|
+
}
|
59
|
+
};
|
60
|
+
}
|
61
|
+
};
|
@@ -0,0 +1,40 @@
|
|
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
|
+
'use strict';
|
5
|
+
|
6
|
+
const rule = require('../lib/no_importing_images_from_src.js');
|
7
|
+
const ruleTester = new (require('eslint').RuleTester)({
|
8
|
+
parser: require.resolve('@typescript-eslint/parser'),
|
9
|
+
parserOptions: {ecmaVersion: 9, sourceType: 'module'},
|
10
|
+
});
|
11
|
+
|
12
|
+
ruleTester.run('no_importing_images_from_src', rule, {
|
13
|
+
valid: [
|
14
|
+
{
|
15
|
+
code: 'const someIcon = new URL(\'../../../Images/test_icon.svg\', import.meta.url).toString()',
|
16
|
+
filename: 'front_end/ui/components/component/file.ts',
|
17
|
+
},
|
18
|
+
],
|
19
|
+
|
20
|
+
invalid: [
|
21
|
+
{
|
22
|
+
code: 'const someIcon = new URL(\'../../../Images/src/test_icon.svg\', import.meta.url).toString()',
|
23
|
+
filename: 'front_end/ui/components/component/file.ts',
|
24
|
+
output: 'const someIcon = new URL(\'../../../Images/test_icon.svg\', import.meta.url).toString()',
|
25
|
+
errors: [{
|
26
|
+
messageId: 'imageImportUsingSrc',
|
27
|
+
}],
|
28
|
+
},
|
29
|
+
{
|
30
|
+
code:
|
31
|
+
'const someIcon = new URL(\'../../../devtools-frontend/front_end/Images/src/test_icon.svg\', import.meta.url).toString()',
|
32
|
+
filename: 'front_end/ui/components/component/file.ts',
|
33
|
+
output:
|
34
|
+
'const someIcon = new URL(\'../../../devtools-frontend/front_end/Images/test_icon.svg\', import.meta.url).toString()',
|
35
|
+
errors: [{
|
36
|
+
messageId: 'imageImportUsingSrc',
|
37
|
+
}],
|
38
|
+
},
|
39
|
+
],
|
40
|
+
});
|