chrome-devtools-frontend 1.0.1703574 → 1.0.1705227
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 +2 -0
- package/docs/architecture_of_devtools.md +1 -1
- package/docs/cookbook/localization.md +2 -2
- package/front_end/core/common/ParsedURL.ts +54 -0
- package/front_end/core/common/README.md +4 -3
- package/front_end/core/platform/StringUtilities.ts +65 -0
- package/front_end/core/sdk/CPUThrottlingManager.ts +3 -3
- package/front_end/core/sdk/SourceMap.ts +3 -3
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +4 -3
- package/front_end/core/sdk/SourceMapScopesInfo.ts +17 -5
- package/front_end/entrypoints/formatter_actions/formatter_actions.ts +18 -0
- package/front_end/entrypoints/formatter_worker/Substitute.ts +9 -8
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +2 -2
- package/front_end/entrypoints/main/MainImpl.ts +3 -3
- package/front_end/foundation/Universe.ts +9 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -2
- package/front_end/generated/protocol.ts +16 -0
- package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
- package/front_end/models/formatter/FormatterWorkerPool.ts +8 -3
- package/front_end/models/har/HARFormat.ts +7 -2
- package/front_end/models/source_map_scopes/NamesResolver.ts +75 -38
- package/front_end/models/source_map_scopes/ScopeChainModel.ts +13 -45
- package/front_end/models/source_map_scopes/ScopeChainResolver.ts +101 -0
- package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingListView.ts +33 -1
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +4 -12
- package/front_end/panels/application/ApplicationPanelSidebar.ts +58 -60
- package/front_end/panels/application/BackForwardCacheTreeElement.ts +1 -1
- package/front_end/panels/application/FrameDetailsView.ts +64 -82
- package/front_end/panels/application/OpenedWindowDetailsView.ts +20 -21
- package/front_end/panels/application/PreloadingTreeElement.ts +3 -3
- package/front_end/panels/common/CommentsOverlayWidget.ts +145 -72
- package/front_end/panels/common/commentsOverlay.css +34 -23
- package/front_end/panels/console/ConsolePrompt.ts +2 -1
- package/front_end/panels/elements/DOMTreeWidget.ts +29 -10
- package/front_end/panels/network/RequestPayloadView.ts +7 -2
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +12 -9
- package/front_end/panels/sources/DebuggerPlugin.ts +52 -20
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +2 -2
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/SourcesView.ts +3 -12
- package/front_end/panels/sources/TabbedEditorContainer.ts +0 -3
- package/front_end/panels/sources/components/HeadersView.ts +193 -123
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +24 -32
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js +15 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +0 -8
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +0 -24
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts +12 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +79 -17
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/ElementHandle.ts +15 -2
- package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +10 -1
- package/front_end/third_party/puppeteer/package/src/common/Debug.ts +0 -27
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +96 -17
- package/front_end/third_party/puppeteer/package/src/node-env-setup.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +60 -22
- package/front_end/ui/comments/CommentOverlayManager.ts +78 -25
- package/front_end/ui/legacy/README.md +12 -12
- package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +7 -13
- package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +51 -57
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +101 -42
- package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +7 -0
- package/package.json +1 -1
|
@@ -73,11 +73,11 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
73
73
|
bindings: [
|
|
74
74
|
{
|
|
75
75
|
shortcut: 'Ctrl+E',
|
|
76
|
-
platform: UI.ActionRegistration.Platforms.
|
|
76
|
+
platform: UI.ActionRegistration.Platforms.WINDOWS_LINUX,
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
shortcut: 'Meta+E',
|
|
80
|
-
platform: UI.ActionRegistration.Platforms.
|
|
80
|
+
platform: UI.ActionRegistration.Platforms.MAC,
|
|
81
81
|
},
|
|
82
82
|
],
|
|
83
83
|
});
|
|
@@ -87,7 +87,7 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
87
87
|
|
|
88
88
|
#### Context types
|
|
89
89
|
The `contextTypes` property determines the context under which the action is available.
|
|
90
|
-
A context is defined as set 'flavors' or classes, which usually represent views, that are added and removed to the context as the user interacts with the application (e.g when the user moves across views).
|
|
90
|
+
A context is defined as set of 'flavors' or classes, which usually represent views, that are added and removed to the context as the user interacts with the application (e.g when the user moves across views).
|
|
91
91
|
(See [`UI.Context`](./Context.js)).
|
|
92
92
|
Therefore, an action can only be triggered when one of its respective context types is visible.
|
|
93
93
|
These flavors can be retrieved invoking the method `flavors` inside the class `UI.Context.Context`.
|
|
@@ -97,10 +97,10 @@ In this case, the action will always be available, regardless of which context i
|
|
|
97
97
|
|
|
98
98
|
#### Key bindings
|
|
99
99
|
|
|
100
|
-
The `bindings` property defines
|
|
100
|
+
The `bindings` property defines `platform` and `keybindSets` properties along with the `shortcut` property containing the actual keyboard shortcut.
|
|
101
101
|
These two extra properties add more conditions (additional to the ones introduced by the `contextTypes` property discussed before) that need to be fulfilled to trigger a particular action.
|
|
102
102
|
|
|
103
|
-
- `platform` refers to the OS on which DevTools is running and can be either `
|
|
103
|
+
- `platform` refers to the OS on which DevTools is running and can be either `MAC`, `WINDOWS_LINUX` or `WINDOWS`. (See [`UI.ActionRegistration`](./ActionRegistration.ts)).
|
|
104
104
|
- `keybindSets` refers to the selected shortcut preset, which can be changed in `settings -> shortcuts -> “Match shortcuts from preset”`.
|
|
105
105
|
A key binding will be used when the selected preset matches any of the keybind sets declared by the binding.
|
|
106
106
|
|
|
@@ -125,16 +125,16 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
125
125
|
contextTypes: undefined,
|
|
126
126
|
bindings: [
|
|
127
127
|
{
|
|
128
|
-
platform:
|
|
128
|
+
platform: UI.ActionRegistration.Platforms.WINDOWS_LINUX,
|
|
129
129
|
shortcut: 'Esc',
|
|
130
130
|
},
|
|
131
131
|
],
|
|
132
132
|
});
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
These two key bindings both allocate the same key for the `
|
|
135
|
+
These two key bindings both allocate the same key for the `WINDOWS_LINUX` platform (the first one is global across platforms) in the `ElementsPanel` context (the second one is global across context types) and both are global across keybind sets.
|
|
136
136
|
|
|
137
|
-
If key bindings were declared such that **at least one** of the three variables (`platform
|
|
137
|
+
If key bindings were declared such that **at least one** of the three variables (`platform`, `contextTypes` and `keybindSets`) doesn't overlap, then no duplication would occur.
|
|
138
138
|
For example, the following is **not** a form of duplication:
|
|
139
139
|
|
|
140
140
|
```ts
|
|
@@ -147,7 +147,7 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
147
147
|
bindings: [
|
|
148
148
|
{
|
|
149
149
|
shortcut: 'Esc',
|
|
150
|
-
keybindSets: [
|
|
150
|
+
keybindSets: [UI.ActionRegistration.KeybindSet.DEVTOOLS_DEFAULT],
|
|
151
151
|
},
|
|
152
152
|
],
|
|
153
153
|
});
|
|
@@ -160,12 +160,12 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
160
160
|
contextTypes: undefined,
|
|
161
161
|
bindings: [
|
|
162
162
|
{
|
|
163
|
-
platform:
|
|
163
|
+
platform: UI.ActionRegistration.Platforms.WINDOWS_LINUX,
|
|
164
164
|
shortcut: 'Esc',
|
|
165
|
-
keybindSets: [
|
|
165
|
+
keybindSets: [UI.ActionRegistration.KeybindSet.VS_CODE],
|
|
166
166
|
},
|
|
167
167
|
],
|
|
168
168
|
});
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
In this case,
|
|
171
|
+
In this case, the keybindings are declared for different keybind sets and thus do not result in duplication.
|
|
@@ -2,6 +2,8 @@
|
|
|
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 Platform from '../../../../core/platform/platform.js';
|
|
6
|
+
|
|
5
7
|
import type {DataGridImpl} from './DataGrid.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -72,18 +74,10 @@ function escapeMarkdown(val: string): string {
|
|
|
72
74
|
.replace(/\r?\n/g, '<br>');
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Escapes a string for CSV export (handling both RFC 4180 quoting and
|
|
79
|
+
* prefixing spreadsheet formula characters like `=`, `+`, `-`, `@` with `'`).
|
|
80
|
+
*/
|
|
75
81
|
function escapeCSV(val: string): string {
|
|
76
|
-
|
|
77
|
-
let escaped = val;
|
|
78
|
-
if (escaped.includes('"')) {
|
|
79
|
-
escaped = escaped.replace(/"/g, '""');
|
|
80
|
-
needQuotes = true;
|
|
81
|
-
}
|
|
82
|
-
if (escaped.includes(',') || escaped.includes('\n') || escaped.includes('\r')) {
|
|
83
|
-
needQuotes = true;
|
|
84
|
-
}
|
|
85
|
-
if (needQuotes) {
|
|
86
|
-
return `"${escaped}"`;
|
|
87
|
-
}
|
|
88
|
-
return escaped;
|
|
82
|
+
return Platform.StringUtilities.escapeCsvCell(val);
|
|
89
83
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import * as Common from '../../../../core/common/common.js';
|
|
5
5
|
import * as i18n from '../../../../core/i18n/i18n.js';
|
|
6
6
|
import * as Lit from '../../../../ui/lit/lit.js';
|
|
7
|
+
import * as VisualLogging from '../../../../ui/visual_logging/visual_logging.js';
|
|
7
8
|
import * as UI from '../../legacy.js';
|
|
8
9
|
|
|
9
10
|
import positionAreaEditorStyles from './positionAreaEditor.css.js';
|
|
@@ -19,21 +20,9 @@ const UIStrings = {
|
|
|
19
20
|
*/
|
|
20
21
|
positionAreaGrid: 'position-area grid',
|
|
21
22
|
/**
|
|
22
|
-
* @description Title for the
|
|
23
|
+
* @description Title for the mode section and accessible label for the mode radio button group in the position-area editor.
|
|
23
24
|
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @description Title for the inline axis section in the position-area editor.
|
|
27
|
-
*/
|
|
28
|
-
inline: 'Inline',
|
|
29
|
-
/**
|
|
30
|
-
* @description Accessible label for the block axis mode radio button group.
|
|
31
|
-
*/
|
|
32
|
-
blockAxisMode: 'Block axis mode',
|
|
33
|
-
/**
|
|
34
|
-
* @description Accessible label for the inline axis mode radio button group.
|
|
35
|
-
*/
|
|
36
|
-
inlineAxisMode: 'Inline axis mode',
|
|
25
|
+
mode: 'Mode',
|
|
37
26
|
/**
|
|
38
27
|
* @description Label for physical mode radio button in the position-area editor.
|
|
39
28
|
*/
|
|
@@ -299,14 +288,15 @@ export interface ViewInput {
|
|
|
299
288
|
onSelectStart: (x: number, y: number) => void;
|
|
300
289
|
onSelect: (x: number, y: number) => void;
|
|
301
290
|
onSelectEnd: (x?: number, y?: number) => void;
|
|
302
|
-
onModeChange: (
|
|
303
|
-
onSelfChange: (
|
|
291
|
+
onModeChange: (mode: Mode) => void;
|
|
292
|
+
onSelfChange: (self: boolean) => void;
|
|
304
293
|
}
|
|
305
294
|
export type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
|
|
306
295
|
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
307
296
|
const container = {
|
|
308
297
|
attributes: {
|
|
309
298
|
tabindex: '0',
|
|
299
|
+
jslog: `${VisualLogging.dialog('position-area-editor').parent('mapped').track({keydown: 'Enter|Escape'})}`,
|
|
310
300
|
},
|
|
311
301
|
};
|
|
312
302
|
if (!input.area) {
|
|
@@ -486,35 +476,42 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
486
476
|
|
|
487
477
|
const blockAxis = input.area.primaryAxis === Axis.BLOCK ? input.area.first : input.area.second;
|
|
488
478
|
const inlineAxis = input.area.primaryAxis === Axis.INLINE ? input.area.first : input.area.second;
|
|
479
|
+
const currentMode = blockAxis.mode === inlineAxis.mode ? blockAxis.mode : undefined;
|
|
480
|
+
const selfDisabled = (isGeneric(blockAxis) || blockAxis.mode === Mode.PHYSICAL) &&
|
|
481
|
+
(isGeneric(inlineAxis) || inlineAxis.mode === Mode.PHYSICAL);
|
|
482
|
+
const selfIndeterminate = !isGeneric(blockAxis) && !isGeneric(inlineAxis) && blockAxis.self !== inlineAxis.self;
|
|
483
|
+
const selfChecked = !selfIndeterminate && (blockAxis.self || inlineAxis.self);
|
|
489
484
|
|
|
490
|
-
function renderModeRadioGroup(
|
|
485
|
+
function renderModeRadioGroup(currentMode: Mode|undefined): Lit.TemplateResult {
|
|
491
486
|
const modes = [
|
|
492
487
|
{mode: Mode.PHYSICAL, label: i18nString(UIStrings.physical)},
|
|
493
488
|
{mode: Mode.COORDINATE, label: i18nString(UIStrings.coordinate)},
|
|
494
489
|
{mode: Mode.LOGICAL, label: i18nString(UIStrings.logical)},
|
|
495
490
|
{mode: Mode.AUTO, label: i18nString(UIStrings.auto)},
|
|
496
491
|
];
|
|
497
|
-
const axisModeLabel =
|
|
498
|
-
axis === Axis.BLOCK ? i18nString(UIStrings.blockAxisMode) : i18nString(UIStrings.inlineAxisMode);
|
|
499
492
|
|
|
493
|
+
// clang-format off
|
|
500
494
|
return html`
|
|
501
|
-
<fieldset class="chip-radio-group" aria-label=${
|
|
495
|
+
<fieldset class="chip-radio-group" aria-label=${i18nString(UIStrings.mode)}>
|
|
502
496
|
${modes.map(({mode, label}) => {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
497
|
+
const id = `mode-${mode}`;
|
|
498
|
+
return html`
|
|
499
|
+
<input
|
|
500
|
+
type="radio"
|
|
501
|
+
id=${id}
|
|
502
|
+
name="mode"
|
|
503
|
+
value=${mode}
|
|
504
|
+
.checked=${currentMode === mode}
|
|
505
|
+
@change=${() => input.onModeChange(mode)}
|
|
506
|
+
>
|
|
507
|
+
<label
|
|
508
|
+
for=${id}
|
|
509
|
+
jslog=${VisualLogging.toggle(mode).track({click: true})}
|
|
510
|
+
>${label}</label>
|
|
511
|
+
`;
|
|
512
|
+
})}
|
|
513
|
+
</fieldset>`;
|
|
514
|
+
// clang-format on
|
|
518
515
|
}
|
|
519
516
|
|
|
520
517
|
// clang-format off
|
|
@@ -531,6 +528,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
531
528
|
aria-label=${i18nString(UIStrings.positionAreaGrid)}
|
|
532
529
|
aria-description=${i18nString(UIStrings.positionAreaGridDescription)}
|
|
533
530
|
aria-multiselectable="true"
|
|
531
|
+
jslog=${VisualLogging.canvas('position-area-grid').track({click: true, drag: true, keydown: 'ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Enter|Space'})}
|
|
534
532
|
data-x-start=${x.start} data-x-end=${x.end} data-y-start=${y.start} data-y-end=${y.end}
|
|
535
533
|
@pointerdown=${onPointerDown}
|
|
536
534
|
@pointermove=${onPointerMove}
|
|
@@ -558,27 +556,17 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
558
556
|
<div class=position-area-controls>
|
|
559
557
|
<div class=axis-section>
|
|
560
558
|
<div class=axis-header>
|
|
561
|
-
<span class=axis-title>${i18nString(UIStrings.
|
|
562
|
-
<devtools-checkbox
|
|
563
|
-
.checked=${blockAxis.self}
|
|
564
|
-
?disabled=${isGeneric(blockAxis)}
|
|
565
|
-
@change=${(e: Event) => input.onSelfChange(Axis.BLOCK, (e.target as UI.UIUtils.CheckboxLabel).checked)}>
|
|
566
|
-
<span class="self-checkbox-label source-code">self</span>
|
|
567
|
-
</devtools-checkbox>
|
|
568
|
-
</div>
|
|
569
|
-
${renderModeRadioGroup(Axis.BLOCK, blockAxis.mode)}
|
|
570
|
-
</div>
|
|
571
|
-
<div class=axis-section>
|
|
572
|
-
<div class=axis-header>
|
|
573
|
-
<span class=axis-title>${i18nString(UIStrings.inline)}</span>
|
|
559
|
+
<span class=axis-title>${i18nString(UIStrings.mode)}</span>
|
|
574
560
|
<devtools-checkbox
|
|
575
|
-
.checked=${
|
|
576
|
-
|
|
577
|
-
|
|
561
|
+
.checked=${selfChecked}
|
|
562
|
+
.indeterminate=${selfIndeterminate}
|
|
563
|
+
?disabled=${selfDisabled}
|
|
564
|
+
jslog=${VisualLogging.toggle('self').track({change: true})}
|
|
565
|
+
@change=${(e: Event) => input.onSelfChange((e.target as UI.UIUtils.CheckboxLabel).checked)}>
|
|
578
566
|
<span class="self-checkbox-label source-code">self</span>
|
|
579
567
|
</devtools-checkbox>
|
|
580
568
|
</div>
|
|
581
|
-
${renderModeRadioGroup(
|
|
569
|
+
${renderModeRadioGroup(currentMode)}
|
|
582
570
|
</div>
|
|
583
571
|
</div>
|
|
584
572
|
`,
|
|
@@ -725,10 +713,10 @@ export class PositionAreaEditor extends PositionAreaEditorBase {
|
|
|
725
713
|
other.mode = mode === Mode.COORDINATE ? Mode.COORDINATE : (other.self ? Mode.COORDINATE : Mode.PHYSICAL);
|
|
726
714
|
}
|
|
727
715
|
} else {
|
|
716
|
+
const self = current.self || other.self;
|
|
717
|
+
current.self = !isGeneric(current) && self;
|
|
728
718
|
other.mode = mode;
|
|
729
|
-
|
|
730
|
-
other.self = current.self;
|
|
731
|
-
}
|
|
719
|
+
other.self = !isGeneric(other) && self;
|
|
732
720
|
}
|
|
733
721
|
} else {
|
|
734
722
|
other.mode = mode;
|
|
@@ -779,8 +767,14 @@ export class PositionAreaEditor extends PositionAreaEditorBase {
|
|
|
779
767
|
onSelectStart: this.#startSelection.bind(this),
|
|
780
768
|
onSelect: this.#select.bind(this),
|
|
781
769
|
onSelectEnd: this.#finishSelection.bind(this),
|
|
782
|
-
onModeChange:
|
|
783
|
-
|
|
770
|
+
onModeChange: (mode: Mode) => {
|
|
771
|
+
this.#setAxisMode(Axis.BLOCK, mode);
|
|
772
|
+
this.#setAxisMode(Axis.INLINE, mode);
|
|
773
|
+
},
|
|
774
|
+
onSelfChange: (self: boolean) => {
|
|
775
|
+
this.#setAxisSelf(Axis.BLOCK, self);
|
|
776
|
+
this.#setAxisSelf(Axis.INLINE, self);
|
|
777
|
+
},
|
|
784
778
|
},
|
|
785
779
|
undefined, this.contentElement);
|
|
786
780
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Copyright 2021 The Chromium Authors
|
|
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
|
-
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
4
|
|
|
6
5
|
/*
|
|
7
6
|
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
|
|
@@ -31,13 +30,15 @@
|
|
|
31
30
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
31
|
*/
|
|
33
32
|
|
|
33
|
+
import '../../../kit/kit.js';
|
|
34
|
+
|
|
34
35
|
import * as Common from '../../../../core/common/common.js';
|
|
35
36
|
import * as Host from '../../../../core/host/host.js';
|
|
36
37
|
import * as i18n from '../../../../core/i18n/i18n.js';
|
|
37
38
|
import * as Platform from '../../../../core/platform/platform.js';
|
|
38
39
|
import * as TextUtils from '../../../../core/text_utils/text_utils.js';
|
|
39
40
|
import * as Workspace from '../../../../models/workspace/workspace.js';
|
|
40
|
-
import {
|
|
41
|
+
import {html, render} from '../../../lit/lit.js';
|
|
41
42
|
import * as VisualLogging from '../../../visual_logging/visual_logging.js';
|
|
42
43
|
import * as UI from '../../legacy.js';
|
|
43
44
|
|
|
@@ -90,6 +91,54 @@ const UIStrings = {
|
|
|
90
91
|
} as const;
|
|
91
92
|
const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/source_frame/ImageView.ts', UIStrings);
|
|
92
93
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
94
|
+
|
|
95
|
+
export interface ViewInput {
|
|
96
|
+
url: Platform.DevToolsPath.UrlString;
|
|
97
|
+
imageSrc: string|null;
|
|
98
|
+
isUnavailable: boolean;
|
|
99
|
+
onImageLoad: (event: Event) => void;
|
|
100
|
+
onContextMenu: (event: Event) => void;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
|
|
104
|
+
|
|
105
|
+
// clang-format off
|
|
106
|
+
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
107
|
+
render(html`
|
|
108
|
+
<style>${imageViewStyles}</style>
|
|
109
|
+
<div class="image">
|
|
110
|
+
${input.imageSrc ? html`
|
|
111
|
+
<img
|
|
112
|
+
class="resource-image-view"
|
|
113
|
+
src=${input.imageSrc}
|
|
114
|
+
alt=${i18nString(UIStrings.imageFromS, {PH1: input.url})}
|
|
115
|
+
@load=${input.onImageLoad}
|
|
116
|
+
@contextmenu=${{handleEvent: input.onContextMenu, capture: true}}
|
|
117
|
+
>` : html`
|
|
118
|
+
<img
|
|
119
|
+
class="resource-image-view"
|
|
120
|
+
alt=${i18nString(UIStrings.imageFromS, {PH1: input.url})}
|
|
121
|
+
hidden
|
|
122
|
+
>`}
|
|
123
|
+
<devtools-link
|
|
124
|
+
class="resource-image-unavailable ${input.isUnavailable ? '' : 'hidden'}"
|
|
125
|
+
href=${input.url}
|
|
126
|
+
>
|
|
127
|
+
<devtools-icon name="open-externally"></devtools-icon>
|
|
128
|
+
${i18nString(UIStrings.thisImageIsTooBig)}
|
|
129
|
+
</devtools-link>
|
|
130
|
+
</div>
|
|
131
|
+
`, target, {
|
|
132
|
+
container: {
|
|
133
|
+
classes: ['image-view'],
|
|
134
|
+
attributes: {
|
|
135
|
+
tabindex: '-1',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
// clang-format on
|
|
141
|
+
|
|
93
142
|
export class ImageView extends UI.View.SimpleView {
|
|
94
143
|
private url: Platform.DevToolsPath.UrlString;
|
|
95
144
|
private parsedURL: Common.ParsedURL.ParsedURL;
|
|
@@ -100,47 +149,58 @@ export class ImageView extends UI.View.SimpleView {
|
|
|
100
149
|
private readonly dimensionsLabel: UI.Toolbar.ToolbarText;
|
|
101
150
|
private readonly aspectRatioLabel: UI.Toolbar.ToolbarText;
|
|
102
151
|
private readonly mimeTypeLabel: UI.Toolbar.ToolbarText;
|
|
103
|
-
private readonly container: HTMLElement;
|
|
104
|
-
private imagePreviewElement: HTMLImageElement;
|
|
105
|
-
private imageUnavailableElement: HTMLElement;
|
|
106
152
|
private cachedContent?: TextUtils.ContentData.ContentData;
|
|
107
|
-
|
|
153
|
+
readonly #view: View;
|
|
154
|
+
#imageSrc: string|null = null;
|
|
155
|
+
#isUnavailable = false;
|
|
156
|
+
#loadResolve?: () => void;
|
|
157
|
+
|
|
158
|
+
constructor(mimeType: string, contentProvider: TextUtils.ContentProvider.ContentProvider, view: View = DEFAULT_VIEW) {
|
|
108
159
|
super({
|
|
109
160
|
title: i18nString(UIStrings.image),
|
|
110
161
|
viewId: 'image',
|
|
111
162
|
jslog: `${VisualLogging.pane('image-view')}`,
|
|
112
163
|
});
|
|
113
|
-
this
|
|
114
|
-
this.element.tabIndex = -1;
|
|
115
|
-
this.element.classList.add('image-view');
|
|
164
|
+
this.#view = view;
|
|
116
165
|
this.url = contentProvider.contentURL();
|
|
117
166
|
this.parsedURL = new Common.ParsedURL.ParsedURL(this.url);
|
|
118
167
|
this.contentProvider = contentProvider;
|
|
119
168
|
this.uiSourceCode = contentProvider instanceof Workspace.UISourceCode.UISourceCode ? contentProvider : null;
|
|
120
169
|
if (this.uiSourceCode) {
|
|
121
|
-
this.uiSourceCode.addEventListener(
|
|
122
|
-
|
|
123
|
-
new UI.DropTarget.DropTarget(
|
|
124
|
-
|
|
125
|
-
this.handleDrop.bind(this));
|
|
170
|
+
this.uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted, this.workingCopyCommitted,
|
|
171
|
+
this);
|
|
172
|
+
new UI.DropTarget.DropTarget(this.element, [UI.DropTarget.Type.ImageFile, UI.DropTarget.Type.URI],
|
|
173
|
+
i18nString(UIStrings.dropImageFileHere), this.handleDrop.bind(this));
|
|
126
174
|
}
|
|
127
175
|
this.sizeLabel = new UI.Toolbar.ToolbarText();
|
|
128
176
|
this.dimensionsLabel = new UI.Toolbar.ToolbarText();
|
|
129
177
|
this.aspectRatioLabel = new UI.Toolbar.ToolbarText();
|
|
130
178
|
this.mimeTypeLabel = new UI.Toolbar.ToolbarText(mimeType);
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
this.imagePreviewElement.addEventListener('contextmenu', this.contextMenu.bind(this), true);
|
|
179
|
+
this.performUpdate();
|
|
180
|
+
}
|
|
134
181
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
182
|
+
override performUpdate(): void {
|
|
183
|
+
this.#view(
|
|
184
|
+
{
|
|
185
|
+
url: this.url,
|
|
186
|
+
imageSrc: this.#imageSrc,
|
|
187
|
+
isUnavailable: this.#isUnavailable,
|
|
188
|
+
onImageLoad: this.#onImageLoad,
|
|
189
|
+
onContextMenu: this.contextMenu.bind(this),
|
|
190
|
+
},
|
|
191
|
+
undefined,
|
|
192
|
+
this.contentElement,
|
|
193
|
+
);
|
|
142
194
|
}
|
|
143
195
|
|
|
196
|
+
#onImageLoad = (event: Event): void => {
|
|
197
|
+
const img = event.target as HTMLImageElement;
|
|
198
|
+
this.dimensionsLabel.setText(i18nString(UIStrings.dD, {PH1: img.naturalWidth, PH2: img.naturalHeight}));
|
|
199
|
+
this.aspectRatioLabel.setText(Platform.NumberUtilities.aspectRatio(img.naturalWidth, img.naturalHeight));
|
|
200
|
+
this.#loadResolve?.();
|
|
201
|
+
this.#loadResolve = undefined;
|
|
202
|
+
};
|
|
203
|
+
|
|
144
204
|
override async toolbarItems(): Promise<UI.Toolbar.ToolbarItem[]> {
|
|
145
205
|
await this.updateContentIfNeeded();
|
|
146
206
|
return [
|
|
@@ -156,13 +216,14 @@ export class ImageView extends UI.View.SimpleView {
|
|
|
156
216
|
|
|
157
217
|
override wasShown(): void {
|
|
158
218
|
super.wasShown();
|
|
219
|
+
this.requestUpdate();
|
|
159
220
|
void this.updateContentIfNeeded();
|
|
160
221
|
}
|
|
161
222
|
|
|
162
223
|
override disposeView(): void {
|
|
163
224
|
if (this.uiSourceCode) {
|
|
164
|
-
this.uiSourceCode.removeEventListener(
|
|
165
|
-
|
|
225
|
+
this.uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
|
|
226
|
+
this.workingCopyCommitted, this);
|
|
166
227
|
}
|
|
167
228
|
}
|
|
168
229
|
|
|
@@ -179,37 +240,35 @@ export class ImageView extends UI.View.SimpleView {
|
|
|
179
240
|
this.cachedContent = content;
|
|
180
241
|
const imageSrc = content.asImagePreviewUrl();
|
|
181
242
|
if (imageSrc === null) {
|
|
182
|
-
this
|
|
243
|
+
this.#isUnavailable = true;
|
|
244
|
+
this.#imageSrc = null;
|
|
245
|
+
this.performUpdate();
|
|
183
246
|
return;
|
|
184
247
|
}
|
|
185
|
-
this
|
|
186
|
-
const loadPromise = new Promise(
|
|
187
|
-
this
|
|
248
|
+
this.#isUnavailable = false;
|
|
249
|
+
const loadPromise = new Promise<void>(resolve => {
|
|
250
|
+
this.#loadResolve = resolve;
|
|
188
251
|
});
|
|
189
|
-
this
|
|
190
|
-
this.imagePreviewElement.alt = i18nString(UIStrings.imageFromS, {PH1: this.url});
|
|
252
|
+
this.#imageSrc = imageSrc;
|
|
191
253
|
const size = content.isTextContent ? content.text.length : Platform.StringUtilities.base64ToSize(content.base64);
|
|
192
254
|
this.sizeLabel.setText(i18n.ByteUtilities.bytesToString(size));
|
|
255
|
+
this.performUpdate();
|
|
193
256
|
await loadPromise;
|
|
194
|
-
this.dimensionsLabel.setText(i18nString(
|
|
195
|
-
UIStrings.dD, {PH1: this.imagePreviewElement.naturalWidth, PH2: this.imagePreviewElement.naturalHeight}));
|
|
196
|
-
this.aspectRatioLabel.setText(Platform.NumberUtilities.aspectRatio(
|
|
197
|
-
this.imagePreviewElement.naturalWidth, this.imagePreviewElement.naturalHeight));
|
|
198
257
|
}
|
|
199
258
|
|
|
200
259
|
private contextMenu(event: Event): void {
|
|
201
260
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
202
|
-
const parsedSrc = new Common.ParsedURL.ParsedURL(this
|
|
261
|
+
const parsedSrc = new Common.ParsedURL.ParsedURL(this.#imageSrc ?? '');
|
|
203
262
|
if (!this.parsedURL.isDataURL()) {
|
|
204
263
|
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copyImageUrl), this.copyImageURL.bind(this), {
|
|
205
264
|
jslogContext: 'image-view.copy-image-url',
|
|
206
265
|
});
|
|
207
266
|
}
|
|
208
267
|
if (parsedSrc.isDataURL()) {
|
|
209
|
-
contextMenu.clipboardSection().appendItem(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
268
|
+
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copyImageAsDataUri),
|
|
269
|
+
this.copyImageAsDataURL.bind(this), {
|
|
270
|
+
jslogContext: 'image-view.copy-image-as-data-url',
|
|
271
|
+
});
|
|
213
272
|
}
|
|
214
273
|
|
|
215
274
|
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.openImageInNewTab), this.openInNewTab.bind(this), {
|
|
@@ -223,7 +282,7 @@ export class ImageView extends UI.View.SimpleView {
|
|
|
223
282
|
}
|
|
224
283
|
|
|
225
284
|
private copyImageAsDataURL(): void {
|
|
226
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this
|
|
285
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.#imageSrc ?? '');
|
|
227
286
|
}
|
|
228
287
|
|
|
229
288
|
private copyImageURL(): void {
|
|
@@ -593,8 +593,7 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
|
|
|
593
593
|
const lineNumber = options.lineNumber;
|
|
594
594
|
const columnNumber = options.columnNumber;
|
|
595
595
|
const showColumnNumber = options.showColumnNumber;
|
|
596
|
-
const isPrivileged = Common.ParsedURL.
|
|
597
|
-
Common.ParsedURL.schemeIs(url, 'devtools:');
|
|
596
|
+
const isPrivileged = Common.ParsedURL.isPrivilegedScheme(url);
|
|
598
597
|
const preventClick = options.preventClick;
|
|
599
598
|
const maxLength = options.maxLength || UI.UIUtils.MaxLengthForDisplayedURLs;
|
|
600
599
|
const bypassURLTrimming = options.bypassURLTrimming;
|
|
@@ -1058,6 +1058,7 @@ export const knownContextValues: Set<string> = new Set([
|
|
|
1058
1058
|
'cookies',
|
|
1059
1059
|
'cookies-data',
|
|
1060
1060
|
'cookies-for-frame',
|
|
1061
|
+
'coordinate',
|
|
1061
1062
|
'copy',
|
|
1062
1063
|
'copy-ai-response',
|
|
1063
1064
|
'copy-all-as-curl',
|
|
@@ -1089,12 +1090,14 @@ export const knownContextValues: Set<string> = new Set([
|
|
|
1089
1090
|
'copy-css-declaration-as-js',
|
|
1090
1091
|
'copy-declaration',
|
|
1091
1092
|
'copy-element',
|
|
1093
|
+
'copy-element-html',
|
|
1092
1094
|
'copy-file-name',
|
|
1093
1095
|
'copy-full-xpath',
|
|
1094
1096
|
'copy-initiator-url',
|
|
1095
1097
|
'copy-js-path',
|
|
1096
1098
|
'copy-key',
|
|
1097
1099
|
'copy-link-address',
|
|
1100
|
+
'copy-message',
|
|
1098
1101
|
'copy-object',
|
|
1099
1102
|
'copy-outer-html',
|
|
1100
1103
|
'copy-payload',
|
|
@@ -2716,6 +2719,7 @@ export const knownContextValues: Set<string> = new Set([
|
|
|
2716
2719
|
'location',
|
|
2717
2720
|
'location-dialog',
|
|
2718
2721
|
'log-level',
|
|
2722
|
+
'logical',
|
|
2719
2723
|
'logpoint',
|
|
2720
2724
|
'long',
|
|
2721
2725
|
'long-interaction',
|
|
@@ -3203,6 +3207,7 @@ export const knownContextValues: Set<string> = new Set([
|
|
|
3203
3207
|
'perspective',
|
|
3204
3208
|
'perspective-origin',
|
|
3205
3209
|
'phone',
|
|
3210
|
+
'physical',
|
|
3206
3211
|
'picture-in-picture',
|
|
3207
3212
|
'pill',
|
|
3208
3213
|
'ping',
|
|
@@ -3253,6 +3258,8 @@ export const knownContextValues: Set<string> = new Set([
|
|
|
3253
3258
|
'position',
|
|
3254
3259
|
'position-anchor',
|
|
3255
3260
|
'position-area',
|
|
3261
|
+
'position-area-editor',
|
|
3262
|
+
'position-area-grid',
|
|
3256
3263
|
'position-fallback',
|
|
3257
3264
|
'position-try',
|
|
3258
3265
|
'position-try-fallbacks',
|
package/package.json
CHANGED