chrome-devtools-frontend 1.0.980472 → 1.0.982087
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/core/common/ParsedURL.ts +42 -4
- package/front_end/core/host/InspectorFrontendHost.ts +7 -6
- package/front_end/core/host/InspectorFrontendHostAPI.ts +8 -8
- package/front_end/core/i18n/locales/en-US.json +15 -0
- package/front_end/core/i18n/locales/en-XL.json +15 -0
- package/front_end/core/platform/DevToolsPath.ts +3 -0
- package/front_end/core/sdk/CSSRule.ts +2 -2
- package/front_end/core/sdk/DOMDebuggerModel.ts +2 -2
- package/front_end/core/sdk/NetworkRequest.ts +1 -1
- package/front_end/core/sdk/SourceMap.ts +14 -5
- package/front_end/core/sdk/Target.ts +4 -3
- package/front_end/generated/InspectorBackendCommands.js +6 -2
- package/front_end/generated/protocol.ts +16 -0
- package/front_end/legacy_test_runner/bindings_test_runner/BindingsTestRunner.js +5 -0
- package/front_end/models/bindings/BreakpointManager.ts +0 -2
- package/front_end/models/bindings/ContentProviderBasedProject.ts +6 -4
- package/front_end/models/bindings/FileUtils.ts +3 -2
- package/front_end/models/persistence/EditFileSystemView.ts +3 -1
- package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +14 -9
- package/front_end/models/persistence/IsolatedFileSystem.ts +66 -40
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +4 -3
- package/front_end/models/persistence/NetworkPersistenceManager.ts +6 -5
- package/front_end/models/persistence/PlatformFileSystem.ts +15 -10
- package/front_end/models/timeline_model/TimelineModel.ts +1 -0
- package/front_end/models/workspace/FileManager.ts +9 -6
- package/front_end/models/workspace/UISourceCode.ts +4 -2
- package/front_end/models/workspace/WorkspaceImpl.ts +9 -5
- package/front_end/panels/application/BackgroundServiceView.ts +2 -1
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
- package/front_end/panels/console/ConsoleFormat.ts +23 -0
- package/front_end/panels/console/ConsoleView.ts +3 -1
- package/front_end/panels/console/ConsoleViewMessage.ts +3 -19
- package/front_end/panels/coverage/CoverageView.ts +2 -1
- package/front_end/panels/emulation/AdvancedApp.ts +6 -2
- package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -1
- package/front_end/panels/input/InputTimeline.ts +2 -1
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +2 -2
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -2
- package/front_end/panels/profiler/HeapSnapshotView.ts +3 -2
- package/front_end/panels/profiler/ProfileView.ts +2 -2
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +4 -2
- package/front_end/panels/screencast/ScreencastView.ts +4 -1
- package/front_end/panels/settings/SettingsScreen.ts +4 -1
- package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +25 -19
- package/front_end/panels/sources/NavigatorView.ts +9 -5
- package/front_end/panels/sources/SourcesNavigator.ts +2 -2
- package/front_end/panels/sources/components/HeadersView.css +17 -2
- package/front_end/panels/sources/components/HeadersView.ts +102 -0
- package/front_end/panels/timeline/TimelinePanel.ts +2 -1
- package/front_end/panels/timeline/TimelineUIUtils.ts +7 -0
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +963 -886
- package/front_end/third_party/lighthouse/report/bundle.js +3 -2
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
- package/front_end/ui/components/buttons/Button.ts +11 -1
- package/front_end/ui/components/buttons/button.css +31 -10
- package/front_end/ui/components/docs/button/basic.ts +47 -1
- package/front_end/ui/components/panel_feedback/FeedbackButton.ts +4 -1
- package/front_end/ui/legacy/XLink.ts +8 -3
- package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +3 -1
- package/front_end/ui/legacy/components/utils/ImagePreview.ts +6 -2
- package/front_end/ui/legacy/components/utils/Linkifier.ts +7 -2
- package/front_end/ui/legacy/tabbedPane.css +1 -0
- package/front_end/ui/legacy/themeColors.css +4 -0
- package/package.json +1 -1
@@ -53,7 +53,7 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
53
53
|
import objectValueStyles from '../../ui/legacy/components/object_ui/objectValue.css.js';
|
54
54
|
import type {Chrome} from '../../../extension-api/ExtensionAPI.js'; // eslint-disable-line rulesdir/es_modules_import
|
55
55
|
|
56
|
-
import {format} from './ConsoleFormat.js';
|
56
|
+
import {format, updateStyle} from './ConsoleFormat.js';
|
57
57
|
import type {ConsoleViewportElement} from './ConsoleViewport.js';
|
58
58
|
import consoleViewStyles from './consoleView.css.js';
|
59
59
|
import {augmentErrorStackWithScriptIds, parseSourcePositionsFromErrorStack} from './ErrorStackParser.js';
|
@@ -925,26 +925,10 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
|
|
925
925
|
}
|
926
926
|
break;
|
927
927
|
}
|
928
|
-
case 'style':
|
928
|
+
case 'style':
|
929
929
|
// Make sure that allowed properties do not interfere with link visibility.
|
930
|
-
|
931
|
-
['background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text'];
|
932
|
-
|
933
|
-
currentStyle.clear();
|
934
|
-
const buffer = document.createElement('span');
|
935
|
-
buffer.setAttribute('style', token.value);
|
936
|
-
for (const property of buffer.style) {
|
937
|
-
if (!ALLOWED_PROPERTY_PREFIXES.some(
|
938
|
-
prefix => property.startsWith(prefix) || property.startsWith(`-webkit-${prefix}`))) {
|
939
|
-
continue;
|
940
|
-
}
|
941
|
-
currentStyle.set(property, {
|
942
|
-
value: buffer.style.getPropertyValue(property),
|
943
|
-
priority: buffer.style.getPropertyPriority(property),
|
944
|
-
});
|
945
|
-
}
|
930
|
+
updateStyle(currentStyle, token.value);
|
946
931
|
break;
|
947
|
-
}
|
948
932
|
}
|
949
933
|
}
|
950
934
|
return args;
|
@@ -506,7 +506,8 @@ export class CoverageView extends UI.Widget.VBox {
|
|
506
506
|
|
507
507
|
private async exportReport(): Promise<void> {
|
508
508
|
const fos = new Bindings.FileUtils.FileOutputStream();
|
509
|
-
const fileName =
|
509
|
+
const fileName =
|
510
|
+
`Coverage-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as Platform.DevToolsPath.RawPathString;
|
510
511
|
const accepted = await fos.open(fileName);
|
511
512
|
if (!accepted) {
|
512
513
|
return;
|
@@ -2,9 +2,10 @@
|
|
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 * as Common from '../../core/common/common.js';
|
5
|
+
import type * as Common from '../../core/common/common.js';
|
6
6
|
import * as Host from '../../core/host/host.js';
|
7
7
|
import * as UI from '../../ui/legacy/legacy.js';
|
8
|
+
import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
|
8
9
|
|
9
10
|
import {DeviceModeWrapper} from './DeviceModeWrapper.js';
|
10
11
|
import type {Bounds} from './InspectedPagePlaceholder.js';
|
@@ -77,7 +78,10 @@ export class AdvancedApp implements Common.App.App {
|
|
77
78
|
}
|
78
79
|
|
79
80
|
deviceModeEmulationFrameLoaded(toolboxDocument: Document): void {
|
80
|
-
|
81
|
+
ThemeSupport.ThemeSupport.instance().applyTheme(toolboxDocument);
|
82
|
+
ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {
|
83
|
+
ThemeSupport.ThemeSupport.instance().applyTheme(toolboxDocument);
|
84
|
+
});
|
81
85
|
UI.UIUtils.initializeUIUtils(toolboxDocument);
|
82
86
|
UI.UIUtils.installComponentRootStyles((toolboxDocument.body as Element));
|
83
87
|
UI.ContextMenu.ContextMenu.installHandler(toolboxDocument);
|
@@ -6,6 +6,7 @@ import * as Common from '../../core/common/common.js';
|
|
6
6
|
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
|
+
import type * as Platform from '../../core/platform/platform.js';
|
9
10
|
import * as EmulationModel from '../../models/emulation/emulation.js';
|
10
11
|
import * as UI from '../../ui/legacy/legacy.js';
|
11
12
|
import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
|
@@ -389,7 +390,7 @@ export class DeviceModeToolbar {
|
|
389
390
|
|
390
391
|
private experimentalClicked(): void {
|
391
392
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
|
392
|
-
'chrome://flags/#enable-experimental-web-platform-features');
|
393
|
+
'chrome://flags/#enable-experimental-web-platform-features' as Platform.DevToolsPath.UrlString);
|
393
394
|
}
|
394
395
|
|
395
396
|
private fillOptionsToolbar(toolbar: UI.Toolbar.Toolbar): void {
|
@@ -182,7 +182,8 @@ export class InputTimeline extends UI.Widget.VBox implements Timeline.TimelineLo
|
|
182
182
|
return;
|
183
183
|
}
|
184
184
|
|
185
|
-
const fileName = `InputProfile-${Platform.DateUtilities.toISO8601Compact(new Date())}.json
|
185
|
+
const fileName = `InputProfile-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as
|
186
|
+
Platform.DevToolsPath.RawPathString;
|
186
187
|
const stream = new Bindings.FileUtils.FileOutputStream();
|
187
188
|
|
188
189
|
const accepted = await stream.open(fileName);
|
@@ -184,7 +184,7 @@ export class LighthouseReportUIFeatures extends LighthouseReport.ReportUIFeature
|
|
184
184
|
const sanitizedDomain = domain.replace(/[^a-z0-9.-]+/gi, '_');
|
185
185
|
const timestamp = Platform.DateUtilities.toISO8601Compact(new Date(this.json.fetchTime));
|
186
186
|
const ext = blob.type.match('json') ? '.json' : '.html';
|
187
|
-
const basename = `${sanitizedDomain}-${timestamp}${ext}
|
187
|
+
const basename = `${sanitizedDomain}-${timestamp}${ext}` as Platform.DevToolsPath.RawPathString;
|
188
188
|
const text = await blob.text();
|
189
189
|
void Workspace.FileManager.FileManager.instance().save(basename, text, true /* forceSaveAs */);
|
190
190
|
}
|
@@ -1673,10 +1673,10 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
1673
1673
|
}
|
1674
1674
|
const url = mainTarget.inspectedURL();
|
1675
1675
|
const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);
|
1676
|
-
const filename = parsedURL ? parsedURL.host : 'network-log';
|
1676
|
+
const filename = (parsedURL ? parsedURL.host : 'network-log') as Platform.DevToolsPath.RawPathString;
|
1677
1677
|
const stream = new Bindings.FileUtils.FileOutputStream();
|
1678
1678
|
|
1679
|
-
if (!await stream.open(filename
|
1679
|
+
if (!await stream.open(Common.ParsedURL.ParsedURL.concatenate(filename, '.har'))) {
|
1680
1680
|
return;
|
1681
1681
|
}
|
1682
1682
|
|
@@ -462,8 +462,7 @@ export class ResourceWebSocketFrameNode extends DataGrid.SortableDataGrid.Sortab
|
|
462
462
|
if (!this.binaryViewInternal) {
|
463
463
|
if (this.dataTextInternal.length > 0) {
|
464
464
|
this.binaryViewInternal = new BinaryResourceView(
|
465
|
-
this.dataTextInternal,
|
466
|
-
Common.ResourceType.resourceTypes.WebSocket);
|
465
|
+
this.dataTextInternal, Platform.DevToolsPath.EmptyUrlString, Common.ResourceType.resourceTypes.WebSocket);
|
467
466
|
}
|
468
467
|
}
|
469
468
|
return this.binaryViewInternal;
|
@@ -1557,7 +1557,7 @@ export class HeapProfileHeader extends ProfileHeader {
|
|
1557
1557
|
onTempFileReady: (() => void)|null;
|
1558
1558
|
failedToCreateTempFile?: boolean;
|
1559
1559
|
wasDisposed?: boolean;
|
1560
|
-
fileName?:
|
1560
|
+
fileName?: Platform.DevToolsPath.RawPathString;
|
1561
1561
|
|
1562
1562
|
constructor(
|
1563
1563
|
heapProfilerModel: SDK.HeapProfilerModel.HeapProfilerModel|null, type: HeapSnapshotProfileType, title?: string) {
|
@@ -1713,7 +1713,8 @@ export class HeapProfileHeader extends ProfileHeader {
|
|
1713
1713
|
saveToFile(): void {
|
1714
1714
|
const fileOutputStream = new Bindings.FileUtils.FileOutputStream();
|
1715
1715
|
this.fileName = this.fileName ||
|
1716
|
-
'Heap-' + Platform.DateUtilities.toISO8601Compact(new Date()) + this.profileType().fileExtension()
|
1716
|
+
'Heap-' + Platform.DateUtilities.toISO8601Compact(new Date()) + this.profileType().fileExtension() as
|
1717
|
+
Platform.DevToolsPath.RawPathString;
|
1717
1718
|
const onOpen = async(accepted: boolean): Promise<void> => {
|
1718
1719
|
if (!accepted) {
|
1719
1720
|
return;
|
@@ -549,7 +549,7 @@ export const enum ViewTypes {
|
|
549
549
|
|
550
550
|
export class WritableProfileHeader extends ProfileHeader implements Common.StringOutputStream.OutputStream {
|
551
551
|
readonly debuggerModel: SDK.DebuggerModel.DebuggerModel|null;
|
552
|
-
fileName?:
|
552
|
+
fileName?: Platform.DevToolsPath.RawPathString;
|
553
553
|
jsonifiedProfile?: string|null;
|
554
554
|
profile?: Protocol.Profiler.Profile;
|
555
555
|
protocolProfileInternal?: Protocol.Profiler.Profile;
|
@@ -599,7 +599,7 @@ export class WritableProfileHeader extends ProfileHeader implements Common.Strin
|
|
599
599
|
const now = Platform.DateUtilities.toISO8601Compact(new Date());
|
600
600
|
const fileExtension = this.profileType().fileExtension();
|
601
601
|
|
602
|
-
this.fileName = `${this.profileType().typeName()}-${now}${fileExtension}
|
602
|
+
this.fileName = `${this.profileType().typeName()}-${now}${fileExtension}` as Platform.DevToolsPath.RawPathString;
|
603
603
|
}
|
604
604
|
|
605
605
|
const accepted = await fileOutputStream.open(this.fileName);
|
@@ -247,7 +247,8 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
|
|
247
247
|
const [domain, method] = String(methodColumn.value).split('.');
|
248
248
|
const type = typeColumn.value === 'sent' ? 'method' : 'event';
|
249
249
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
|
250
|
-
`https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}`
|
250
|
+
`https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}` as
|
251
|
+
Platform.DevToolsPath.UrlString);
|
251
252
|
});
|
252
253
|
},
|
253
254
|
},
|
@@ -466,7 +467,8 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
|
|
466
467
|
|
467
468
|
private async saveAsFile(): Promise<void> {
|
468
469
|
const now = new Date();
|
469
|
-
const fileName = 'ProtocolMonitor-' + Platform.DateUtilities.toISO8601Compact(now) + '.json'
|
470
|
+
const fileName = 'ProtocolMonitor-' + Platform.DateUtilities.toISO8601Compact(now) + '.json' as
|
471
|
+
Platform.DevToolsPath.RawPathString;
|
470
472
|
const stream = new Bindings.FileUtils.FileOutputStream();
|
471
473
|
|
472
474
|
const accepted = await stream.open(fileName);
|
@@ -32,6 +32,7 @@ import * as Common from '../../core/common/common.js';
|
|
32
32
|
import * as Host from '../../core/host/host.js';
|
33
33
|
import * as i18n from '../../core/i18n/i18n.js';
|
34
34
|
import * as SDK from '../../core/sdk/sdk.js';
|
35
|
+
import type * as Platform from '../../core/platform/platform.js';
|
35
36
|
import * as Protocol from '../../generated/protocol.js';
|
36
37
|
import * as UI from '../../ui/legacy/legacy.js';
|
37
38
|
|
@@ -743,7 +744,9 @@ export class ScreencastView extends UI.Widget.VBox implements SDK.OverlayModel.H
|
|
743
744
|
if (match) {
|
744
745
|
url = match[1];
|
745
746
|
}
|
746
|
-
|
747
|
+
// TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
|
748
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(
|
749
|
+
url as Platform.DevToolsPath.UrlString);
|
747
750
|
this.navigationUrl.value = decodeURI(url);
|
748
751
|
}
|
749
752
|
|
@@ -32,6 +32,7 @@ import * as Common from '../../core/common/common.js';
|
|
32
32
|
import * as Host from '../../core/host/host.js';
|
33
33
|
import * as i18n from '../../core/i18n/i18n.js';
|
34
34
|
import * as Root from '../../core/root/root.js';
|
35
|
+
import type * as Platform from '../../core/platform/platform.js';
|
35
36
|
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
36
37
|
import * as Components from '../../ui/legacy/components/utils/utils.js';
|
37
38
|
import * as UI from '../../ui/legacy/legacy.js';
|
@@ -508,9 +509,11 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
508
509
|
case 'settings.show':
|
509
510
|
void SettingsScreen.showSettingsScreen({focusTabHeader: true} as ShowSettingsScreenOptions);
|
510
511
|
return true;
|
512
|
+
// TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
|
511
513
|
case 'settings.documentation':
|
512
514
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
|
513
|
-
UI.UIUtils.addReferrerToURL('https://developer.chrome.com/docs/devtools/')
|
515
|
+
UI.UIUtils.addReferrerToURL('https://developer.chrome.com/docs/devtools/') as
|
516
|
+
Platform.DevToolsPath.UrlString);
|
514
517
|
return true;
|
515
518
|
case 'settings.shortcuts':
|
516
519
|
void SettingsScreen.showSettingsScreen({name: 'keybinds', focusTabHeader: true});
|
@@ -13,8 +13,6 @@ 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
|
-
|
18
16
|
const UIStrings = {
|
19
17
|
/**
|
20
18
|
*@description Default snippet name when a new snippet is created in the Sources panel
|
@@ -30,12 +28,12 @@ const UIStrings = {
|
|
30
28
|
const str_ = i18n.i18n.registerUIStrings('panels/snippets/ScriptSnippetFileSystem.ts', UIStrings);
|
31
29
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
32
30
|
|
33
|
-
function escapeSnippetName(name:
|
34
|
-
return Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(name
|
31
|
+
function escapeSnippetName(name: Platform.DevToolsPath.RawPathString): Platform.DevToolsPath.EncodedPathString {
|
32
|
+
return Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(name);
|
35
33
|
}
|
36
34
|
|
37
|
-
function unescapeSnippetName(name:
|
38
|
-
return Common.ParsedURL.ParsedURL.encodedPathToRawPathString(name
|
35
|
+
function unescapeSnippetName(name: Platform.DevToolsPath.EncodedPathString): string {
|
36
|
+
return Common.ParsedURL.ParsedURL.encodedPathToRawPathString(name);
|
39
37
|
}
|
40
38
|
|
41
39
|
export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFileSystem {
|
@@ -53,11 +51,13 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
53
51
|
return savedSnippets.map(snippet => escapeSnippetName(snippet.name));
|
54
52
|
}
|
55
53
|
|
56
|
-
async createFile(_path:
|
54
|
+
async createFile(_path: Platform.DevToolsPath.EncodedPathString, _name: Platform.DevToolsPath.RawPathString|null):
|
55
|
+
Promise<Platform.DevToolsPath.EncodedPathString|null> {
|
57
56
|
const nextId = this.lastSnippetIdentifierSetting.get() + 1;
|
58
57
|
this.lastSnippetIdentifierSetting.set(nextId);
|
59
58
|
|
60
|
-
const snippetName =
|
59
|
+
const snippetName =
|
60
|
+
i18nString(UIStrings.scriptSnippet, {PH1: nextId}) as string as Platform.DevToolsPath.RawPathString;
|
61
61
|
const snippets = this.snippetsSetting.get();
|
62
62
|
snippets.push({name: snippetName, content: ''});
|
63
63
|
this.snippetsSetting.set(snippets);
|
@@ -65,8 +65,8 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
65
65
|
return escapeSnippetName(snippetName);
|
66
66
|
}
|
67
67
|
|
68
|
-
async deleteFile(path:
|
69
|
-
const name = unescapeSnippetName(
|
68
|
+
async deleteFile(path: Platform.DevToolsPath.EncodedPathString): Promise<boolean> {
|
69
|
+
const name = unescapeSnippetName(Common.ParsedURL.ParsedURL.substring(path, 1));
|
70
70
|
const allSnippets: Snippet[] = this.snippetsSetting.get();
|
71
71
|
const snippets = allSnippets.filter(snippet => snippet.name !== name);
|
72
72
|
if (allSnippets.length !== snippets.length) {
|
@@ -76,8 +76,9 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
76
76
|
return false;
|
77
77
|
}
|
78
78
|
|
79
|
-
async requestFileContent(path:
|
80
|
-
|
79
|
+
async requestFileContent(path: Platform.DevToolsPath.EncodedPathString):
|
80
|
+
Promise<TextUtils.ContentProvider.DeferredContent> {
|
81
|
+
const name = unescapeSnippetName(Common.ParsedURL.ParsedURL.substring(path, 1));
|
81
82
|
const snippets: Snippet[] = this.snippetsSetting.get();
|
82
83
|
const snippet = snippets.find(snippet => snippet.name === name);
|
83
84
|
if (snippet) {
|
@@ -86,8 +87,9 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
86
87
|
return {content: null, isEncoded: false, error: `A snippet with name '${name}' was not found`};
|
87
88
|
}
|
88
89
|
|
89
|
-
async setFileContent(path:
|
90
|
-
|
90
|
+
async setFileContent(path: Platform.DevToolsPath.EncodedPathString, content: string, _isBase64: boolean):
|
91
|
+
Promise<boolean> {
|
92
|
+
const name = unescapeSnippetName(Common.ParsedURL.ParsedURL.substring(path, 1));
|
91
93
|
const snippets: Snippet[] = this.snippetsSetting.get();
|
92
94
|
const snippet = snippets.find(snippet => snippet.name === name);
|
93
95
|
if (snippet) {
|
@@ -98,11 +100,13 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
98
100
|
return false;
|
99
101
|
}
|
100
102
|
|
101
|
-
renameFile(
|
102
|
-
|
103
|
+
renameFile(
|
104
|
+
path: Platform.DevToolsPath.EncodedPathString, newName: Platform.DevToolsPath.RawPathString,
|
105
|
+
callback: (arg0: boolean, arg1?: string|undefined) => void): void {
|
106
|
+
const name = unescapeSnippetName(Common.ParsedURL.ParsedURL.substring(path, 1));
|
103
107
|
const snippets: Snippet[] = this.snippetsSetting.get();
|
104
108
|
const snippet = snippets.find(snippet => snippet.name === name);
|
105
|
-
newName =
|
109
|
+
newName = Common.ParsedURL.ParsedURL.trim(newName);
|
106
110
|
if (!snippet || newName.length === 0 || snippets.find(snippet => snippet.name === newName)) {
|
107
111
|
callback(false);
|
108
112
|
return;
|
@@ -128,7 +132,9 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
|
|
128
132
|
}
|
129
133
|
|
130
134
|
tooltipForURL(url: Platform.DevToolsPath.UrlString): string {
|
131
|
-
return i18nString(
|
135
|
+
return i18nString(
|
136
|
+
UIStrings.linkedTo,
|
137
|
+
{PH1: unescapeSnippetName(Common.ParsedURL.ParsedURL.sliceUrlToEncodedPathString(url, this.path().length))});
|
132
138
|
}
|
133
139
|
|
134
140
|
supportsAutomapping(): boolean {
|
@@ -215,6 +221,6 @@ export function findSnippetsProject(): Workspace.Workspace.Project {
|
|
215
221
|
return workspaceProject;
|
216
222
|
}
|
217
223
|
export interface Snippet {
|
218
|
-
name:
|
224
|
+
name: Platform.DevToolsPath.RawPathString;
|
219
225
|
content: string;
|
220
226
|
}
|
@@ -28,6 +28,8 @@
|
|
28
28
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
*/
|
30
30
|
|
31
|
+
// TODO(crbug.com/1253323): Casts to Branded Types will be removed from this file when migration to branded types is complete.
|
32
|
+
|
31
33
|
import * as Common from '../../core/common/common.js';
|
32
34
|
import * as Host from '../../core/host/host.js';
|
33
35
|
import * as i18n from '../../core/i18n/i18n.js';
|
@@ -843,7 +845,7 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
|
|
843
845
|
}
|
844
846
|
|
845
847
|
handleFolderContextMenu(event: Event, node: NavigatorTreeNode): void {
|
846
|
-
const path = (node as NavigatorFolderTreeNode).folderPath ||
|
848
|
+
const path = (node as NavigatorFolderTreeNode).folderPath || Platform.DevToolsPath.EmptyEncodedPathString;
|
847
849
|
const project = (node as NavigatorFolderTreeNode).project || null;
|
848
850
|
|
849
851
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
@@ -914,7 +916,7 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
|
|
914
916
|
if (uiSourceCodeToCopy) {
|
915
917
|
content = (await uiSourceCodeToCopy.requestContent()).content || '';
|
916
918
|
}
|
917
|
-
const uiSourceCode = await project.createFile(path, null, content);
|
919
|
+
const uiSourceCode = await project.createFile(path as Platform.DevToolsPath.EncodedPathString, null, content);
|
918
920
|
if (!uiSourceCode) {
|
919
921
|
return;
|
920
922
|
}
|
@@ -1413,7 +1415,9 @@ export class NavigatorUISourceCodeTreeNode extends NavigatorTreeNode {
|
|
1413
1415
|
if (this.treeElement) {
|
1414
1416
|
this.treeElement.title = newTitle;
|
1415
1417
|
}
|
1416
|
-
|
1418
|
+
// necessary cast to RawPathString as alternative would be altering type of Config<T>
|
1419
|
+
void this.uiSourceCodeInternal.rename(newTitle as Platform.DevToolsPath.RawPathString)
|
1420
|
+
.then(renameCallback.bind(this));
|
1417
1421
|
return;
|
1418
1422
|
}
|
1419
1423
|
afterEditing.call(this, true);
|
@@ -1453,7 +1457,7 @@ export class NavigatorUISourceCodeTreeNode extends NavigatorTreeNode {
|
|
1453
1457
|
|
1454
1458
|
export class NavigatorFolderTreeNode extends NavigatorTreeNode {
|
1455
1459
|
project: Workspace.Workspace.Project|null;
|
1456
|
-
readonly folderPath:
|
1460
|
+
readonly folderPath: Platform.DevToolsPath.EncodedPathString;
|
1457
1461
|
title: string;
|
1458
1462
|
treeElement!: NavigatorFolderTreeElement|null;
|
1459
1463
|
constructor(
|
@@ -1461,7 +1465,7 @@ export class NavigatorFolderTreeNode extends NavigatorTreeNode {
|
|
1461
1465
|
folderPath: string, title: string) {
|
1462
1466
|
super(navigatorView, id, type);
|
1463
1467
|
this.project = project;
|
1464
|
-
this.folderPath = folderPath;
|
1468
|
+
this.folderPath = folderPath as Platform.DevToolsPath.EncodedPathString;
|
1465
1469
|
this.title = title;
|
1466
1470
|
}
|
1467
1471
|
|
@@ -31,9 +31,9 @@
|
|
31
31
|
import * as Common from '../../core/common/common.js';
|
32
32
|
import * as Host from '../../core/host/host.js';
|
33
33
|
import * as i18n from '../../core/i18n/i18n.js';
|
34
|
+
import * as Platform from '../../core/platform/platform.js';
|
34
35
|
import * as SDK from '../../core/sdk/sdk.js';
|
35
36
|
import * as Persistence from '../../models/persistence/persistence.js';
|
36
|
-
import type * as Platform from '../../core/platform/platform.js';
|
37
37
|
import * as Workspace from '../../models/workspace/workspace.js';
|
38
38
|
import * as UI from '../../ui/legacy/legacy.js';
|
39
39
|
import * as Snippets from '../snippets/snippets.js';
|
@@ -406,7 +406,7 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
406
406
|
switch (actionId) {
|
407
407
|
case 'sources.create-snippet':
|
408
408
|
void Snippets.ScriptSnippetFileSystem.findSnippetsProject()
|
409
|
-
.createFile(
|
409
|
+
.createFile(Platform.DevToolsPath.EmptyEncodedPathString, null, '')
|
410
410
|
.then(uiSourceCode => Common.Revealer.reveal(uiSourceCode));
|
411
411
|
return true;
|
412
412
|
case 'sources.add-folder-to-workspace':
|
@@ -16,8 +16,7 @@
|
|
16
16
|
font-family: var(--monospace-font-family);
|
17
17
|
font-size: var(--monospace-font-size);
|
18
18
|
align-items: center;
|
19
|
-
line-height:
|
20
|
-
margin-top: 3px;
|
19
|
+
line-height: 24px;
|
21
20
|
}
|
22
21
|
|
23
22
|
.row devtools-button {
|
@@ -57,6 +56,18 @@
|
|
57
56
|
border-radius: 2px;
|
58
57
|
}
|
59
58
|
|
59
|
+
.row .inline-button {
|
60
|
+
opacity: 0%;
|
61
|
+
visibility: hidden;
|
62
|
+
transition: opacity 200ms;
|
63
|
+
}
|
64
|
+
|
65
|
+
.row:focus-within .inline-button,
|
66
|
+
.row:hover .inline-button {
|
67
|
+
opacity: 100%;
|
68
|
+
visibility: visible;
|
69
|
+
}
|
70
|
+
|
60
71
|
.center-wrapper {
|
61
72
|
height: 100%;
|
62
73
|
display: flex;
|
@@ -79,3 +90,7 @@
|
|
79
90
|
line-height: 1.5em;
|
80
91
|
color: var(--color-text-secondary);
|
81
92
|
}
|
93
|
+
|
94
|
+
.add-block {
|
95
|
+
margin-top: 3px;
|
96
|
+
}
|
@@ -5,6 +5,7 @@
|
|
5
5
|
import * as i18n from '../../../core/i18n/i18n.js';
|
6
6
|
import * as Persistence from '../../../models/persistence/persistence.js';
|
7
7
|
import * as Workspace from '../../../models/workspace/workspace.js';
|
8
|
+
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
8
9
|
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
9
10
|
import * as UI from '../../../ui/legacy/legacy.js';
|
10
11
|
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
@@ -12,6 +13,18 @@ import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
|
12
13
|
import HeadersViewStyles from './HeadersView.css.js';
|
13
14
|
|
14
15
|
const UIStrings = {
|
16
|
+
/**
|
17
|
+
*@description The title of a button that adds a field to input a header in the editor form.
|
18
|
+
*/
|
19
|
+
addHeader: 'Add a header',
|
20
|
+
/**
|
21
|
+
*@description The title of a button that removes a field to input a header in the editor form.
|
22
|
+
*/
|
23
|
+
removeHeader: 'Remove this header',
|
24
|
+
/**
|
25
|
+
*@description The title of a button that removes a section for defining header overrides in the editor form.
|
26
|
+
*/
|
27
|
+
removeBlock: 'Remove this \'`ApplyTo`\'-section',
|
15
28
|
/**
|
16
29
|
*@description Error message for files which cannot not be parsed.
|
17
30
|
*@example {.headers} PH1
|
@@ -23,10 +36,17 @@ const UIStrings = {
|
|
23
36
|
*/
|
24
37
|
parsingErrorExplainer:
|
25
38
|
'This is most likely due to a syntax error in \'\'{PH1}\'\'. Try opening this file in an external editor to fix the error or delete the file and re-create the override.',
|
39
|
+
/**
|
40
|
+
*@description Button text for a button which adds an additional header override.
|
41
|
+
*/
|
42
|
+
addHeaderOverride: 'Add header override',
|
26
43
|
};
|
27
44
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/components/HeadersView.ts', UIStrings);
|
28
45
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
29
46
|
|
47
|
+
const plusIconUrl = new URL('../../../Images/plus_icon.svg', import.meta.url).toString();
|
48
|
+
const minusIconUrl = new URL('../../../Images/minus_icon.svg', import.meta.url).toString();
|
49
|
+
|
30
50
|
export class HeadersView extends UI.View.SimpleView {
|
31
51
|
readonly #headersViewComponent = new HeadersViewComponent();
|
32
52
|
#uiSourceCode: Workspace.UISourceCode.UISourceCode;
|
@@ -96,6 +116,10 @@ export class HeadersView extends UI.View.SimpleView {
|
|
96
116
|
this.#setComponentData(this.#uiSourceCode.workingCopy());
|
97
117
|
}
|
98
118
|
|
119
|
+
getComponent(): HeadersViewComponent {
|
120
|
+
return this.#headersViewComponent;
|
121
|
+
}
|
122
|
+
|
99
123
|
dispose(): void {
|
100
124
|
this.#uiSourceCode.removeEventListener(
|
101
125
|
Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged, this);
|
@@ -127,11 +151,13 @@ export class HeadersViewComponent extends HTMLElement {
|
|
127
151
|
#headerOverrides: HeaderOverride[] = [];
|
128
152
|
#uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
|
129
153
|
#parsingError = false;
|
154
|
+
#focusElement: {blockIndex: number, headerIndex?: number}|null = null;
|
130
155
|
|
131
156
|
constructor() {
|
132
157
|
super();
|
133
158
|
this.#shadow.addEventListener('focusin', this.#onFocusIn.bind(this));
|
134
159
|
this.#shadow.addEventListener('focusout', this.#onFocusOut.bind(this));
|
160
|
+
this.#shadow.addEventListener('click', this.#onClick.bind(this));
|
135
161
|
this.#shadow.addEventListener('input', this.#onInput.bind(this));
|
136
162
|
this.#shadow.addEventListener('keydown', this.#onKeyDown.bind(this));
|
137
163
|
}
|
@@ -187,6 +213,43 @@ export class HeadersViewComponent extends HTMLElement {
|
|
187
213
|
selection?.removeAllRanges();
|
188
214
|
}
|
189
215
|
|
216
|
+
#generateNextHeaderName(headers: Header[]): string {
|
217
|
+
const takenNames = new Set<string>(headers.map(header => header.name));
|
218
|
+
let idx = 1;
|
219
|
+
while (takenNames.has('headerName' + idx)) {
|
220
|
+
idx++;
|
221
|
+
}
|
222
|
+
return 'headerName' + idx;
|
223
|
+
}
|
224
|
+
|
225
|
+
#onClick(e: Event): void {
|
226
|
+
const target = e.target as HTMLButtonElement;
|
227
|
+
const rowElement = target.closest('.row') as HTMLElement | null;
|
228
|
+
const blockIndex = Number(rowElement?.dataset.blockIndex || 0);
|
229
|
+
const headerIndex = Number(rowElement?.dataset.headerIndex || 0);
|
230
|
+
if (target.matches('.add-header')) {
|
231
|
+
this.#headerOverrides[blockIndex].headers.splice(
|
232
|
+
headerIndex + 1, 0,
|
233
|
+
{name: this.#generateNextHeaderName(this.#headerOverrides[blockIndex].headers), value: 'headerValue'});
|
234
|
+
this.#focusElement = {blockIndex, headerIndex: headerIndex + 1};
|
235
|
+
this.#onHeadersChanged();
|
236
|
+
} else if (target.matches('.remove-header')) {
|
237
|
+
this.#headerOverrides[blockIndex].headers.splice(headerIndex, 1);
|
238
|
+
if (this.#headerOverrides[blockIndex].headers.length === 0) {
|
239
|
+
this.#headerOverrides[blockIndex].headers.push(
|
240
|
+
{name: this.#generateNextHeaderName(this.#headerOverrides[blockIndex].headers), value: 'headerValue'});
|
241
|
+
}
|
242
|
+
this.#onHeadersChanged();
|
243
|
+
} else if (target.matches('.add-block')) {
|
244
|
+
this.#headerOverrides.push({applyTo: '*', headers: [{name: 'headerName', value: 'headerValue'}]});
|
245
|
+
this.#focusElement = {blockIndex: this.#headerOverrides.length - 1};
|
246
|
+
this.#onHeadersChanged();
|
247
|
+
} else if (target.matches('.remove-block')) {
|
248
|
+
this.#headerOverrides.splice(blockIndex, 1);
|
249
|
+
this.#onHeadersChanged();
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
190
253
|
#onInput(e: Event): void {
|
191
254
|
const target = e.target as HTMLButtonElement;
|
192
255
|
const rowElement = target.closest('.row') as HTMLElement;
|
@@ -252,8 +315,25 @@ export class HeadersViewComponent extends HTMLElement {
|
|
252
315
|
)}
|
253
316
|
`,
|
254
317
|
)}
|
318
|
+
<${Buttons.Button.Button.litTagName} .variant=${Buttons.Button.Variant.SECONDARY} class="add-block">
|
319
|
+
${i18nString(UIStrings.addHeaderOverride)}
|
320
|
+
</${Buttons.Button.Button.litTagName}>
|
255
321
|
`, this.#shadow, {host: this});
|
256
322
|
// clang-format on
|
323
|
+
|
324
|
+
if (this.#focusElement) {
|
325
|
+
let focusElement: Element|null = null;
|
326
|
+
if (this.#focusElement.headerIndex) {
|
327
|
+
focusElement = this.#shadow.querySelector(`[data-block-index="${
|
328
|
+
this.#focusElement.blockIndex}"][data-header-index="${this.#focusElement.headerIndex}"] .header-name`);
|
329
|
+
} else {
|
330
|
+
focusElement = this.#shadow.querySelector(`[data-block-index="${this.#focusElement.blockIndex}"] .apply-to`);
|
331
|
+
}
|
332
|
+
if (focusElement) {
|
333
|
+
(focusElement as HTMLElement).focus();
|
334
|
+
}
|
335
|
+
this.#focusElement = null;
|
336
|
+
}
|
257
337
|
}
|
258
338
|
|
259
339
|
#renderApplyToRow(pattern: string, blockIndex: number): LitHtml.TemplateResult {
|
@@ -263,6 +343,13 @@ export class HeadersViewComponent extends HTMLElement {
|
|
263
343
|
<div>${i18n.i18n.lockedString('Apply to')}</div>
|
264
344
|
<div class="separator">:</div>
|
265
345
|
${this.#renderEditable(pattern, 'apply-to')}
|
346
|
+
<${Buttons.Button.Button.litTagName}
|
347
|
+
title=${i18nString(UIStrings.removeBlock)}
|
348
|
+
.size=${Buttons.Button.Size.SMALL}
|
349
|
+
.iconUrl=${minusIconUrl}
|
350
|
+
.variant=${Buttons.Button.Variant.ROUND}
|
351
|
+
class="remove-block inline-button"
|
352
|
+
></${Buttons.Button.Button.litTagName}>
|
266
353
|
</div>
|
267
354
|
`;
|
268
355
|
// clang-format on
|
@@ -275,6 +362,21 @@ export class HeadersViewComponent extends HTMLElement {
|
|
275
362
|
${this.#renderEditable(header.name, 'header-name red')}
|
276
363
|
<div class="separator">:</div>
|
277
364
|
${this.#renderEditable(header.value, 'header-value')}
|
365
|
+
<${Buttons.Button.Button.litTagName}
|
366
|
+
title=${i18nString(UIStrings.addHeader)}
|
367
|
+
.size=${Buttons.Button.Size.SMALL}
|
368
|
+
.iconUrl=${plusIconUrl}
|
369
|
+
.variant=${Buttons.Button.Variant.ROUND}
|
370
|
+
class="add-header inline-button"
|
371
|
+
></${Buttons.Button.Button.litTagName}>
|
372
|
+
<${Buttons.Button.Button.litTagName}
|
373
|
+
title=${i18nString(UIStrings.removeHeader)}
|
374
|
+
.size=${Buttons.Button.Size.SMALL}
|
375
|
+
.iconUrl=${minusIconUrl}
|
376
|
+
.variant=${Buttons.Button.Variant.ROUND}
|
377
|
+
class="remove-header inline-button"
|
378
|
+
></${Buttons.Button.Button.litTagName}>
|
379
|
+
</div>
|
278
380
|
`;
|
279
381
|
// clang-format on
|
280
382
|
}
|
@@ -636,7 +636,8 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
|
|
636
636
|
}
|
637
637
|
|
638
638
|
const now = new Date();
|
639
|
-
const fileName =
|
639
|
+
const fileName =
|
640
|
+
'Profile-' + Platform.DateUtilities.toISO8601Compact(now) + '.json' as Platform.DevToolsPath.RawPathString;
|
640
641
|
const stream = new Bindings.FileUtils.FileOutputStream();
|
641
642
|
|
642
643
|
const accepted = await stream.open(fileName);
|