chrome-devtools-frontend 1.0.995491 → 1.0.996595
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 +1 -0
- package/front_end/core/i18n/locales/af.json +96 -42
- package/front_end/core/i18n/locales/am.json +97 -43
- package/front_end/core/i18n/locales/ar.json +95 -41
- package/front_end/core/i18n/locales/as.json +95 -41
- package/front_end/core/i18n/locales/az.json +96 -42
- package/front_end/core/i18n/locales/be.json +124 -70
- package/front_end/core/i18n/locales/bg.json +96 -42
- package/front_end/core/i18n/locales/bn.json +95 -41
- package/front_end/core/i18n/locales/bs.json +95 -41
- package/front_end/core/i18n/locales/ca.json +96 -42
- package/front_end/core/i18n/locales/cs.json +95 -41
- package/front_end/core/i18n/locales/cy.json +95 -41
- package/front_end/core/i18n/locales/da.json +97 -43
- package/front_end/core/i18n/locales/de.json +96 -42
- package/front_end/core/i18n/locales/el.json +95 -41
- package/front_end/core/i18n/locales/en-GB.json +95 -41
- package/front_end/core/i18n/locales/en-US.json +26 -5
- package/front_end/core/i18n/locales/en-XL.json +26 -5
- package/front_end/core/i18n/locales/es-419.json +95 -41
- package/front_end/core/i18n/locales/es.json +101 -47
- package/front_end/core/i18n/locales/et.json +95 -41
- package/front_end/core/i18n/locales/eu.json +100 -46
- package/front_end/core/i18n/locales/fa.json +104 -50
- package/front_end/core/i18n/locales/fi.json +95 -41
- package/front_end/core/i18n/locales/fil.json +95 -41
- package/front_end/core/i18n/locales/fr-CA.json +96 -42
- package/front_end/core/i18n/locales/fr.json +95 -41
- package/front_end/core/i18n/locales/gl.json +104 -50
- package/front_end/core/i18n/locales/gu.json +95 -41
- package/front_end/core/i18n/locales/he.json +95 -41
- package/front_end/core/i18n/locales/hi.json +98 -44
- package/front_end/core/i18n/locales/hr.json +96 -42
- package/front_end/core/i18n/locales/hu.json +96 -42
- package/front_end/core/i18n/locales/hy.json +95 -41
- package/front_end/core/i18n/locales/id.json +97 -43
- package/front_end/core/i18n/locales/is.json +95 -41
- package/front_end/core/i18n/locales/it.json +96 -42
- package/front_end/core/i18n/locales/ja.json +95 -41
- package/front_end/core/i18n/locales/ka.json +95 -41
- package/front_end/core/i18n/locales/kk.json +98 -44
- package/front_end/core/i18n/locales/km.json +95 -41
- package/front_end/core/i18n/locales/kn.json +96 -42
- package/front_end/core/i18n/locales/ko.json +96 -42
- package/front_end/core/i18n/locales/ky.json +97 -43
- package/front_end/core/i18n/locales/lo.json +96 -42
- package/front_end/core/i18n/locales/lt.json +95 -41
- package/front_end/core/i18n/locales/lv.json +95 -41
- package/front_end/core/i18n/locales/mk.json +98 -44
- package/front_end/core/i18n/locales/ml.json +96 -42
- package/front_end/core/i18n/locales/mn.json +96 -42
- package/front_end/core/i18n/locales/mr.json +95 -41
- package/front_end/core/i18n/locales/ms.json +95 -41
- package/front_end/core/i18n/locales/my.json +95 -41
- package/front_end/core/i18n/locales/ne.json +100 -46
- package/front_end/core/i18n/locales/nl.json +99 -45
- package/front_end/core/i18n/locales/no.json +95 -41
- package/front_end/core/i18n/locales/or.json +98 -44
- package/front_end/core/i18n/locales/pa.json +95 -41
- package/front_end/core/i18n/locales/pl.json +95 -41
- package/front_end/core/i18n/locales/pt-PT.json +95 -41
- package/front_end/core/i18n/locales/pt.json +98 -44
- package/front_end/core/i18n/locales/ro.json +96 -42
- package/front_end/core/i18n/locales/ru.json +115 -61
- package/front_end/core/i18n/locales/si.json +96 -42
- package/front_end/core/i18n/locales/sk.json +95 -41
- package/front_end/core/i18n/locales/sl.json +95 -41
- package/front_end/core/i18n/locales/sq.json +96 -42
- package/front_end/core/i18n/locales/sr-Latn.json +96 -42
- package/front_end/core/i18n/locales/sr.json +96 -42
- package/front_end/core/i18n/locales/sv.json +96 -42
- package/front_end/core/i18n/locales/sw.json +97 -43
- package/front_end/core/i18n/locales/ta.json +96 -42
- package/front_end/core/i18n/locales/te.json +108 -54
- package/front_end/core/i18n/locales/th.json +95 -41
- package/front_end/core/i18n/locales/tr.json +95 -41
- package/front_end/core/i18n/locales/uk.json +95 -41
- package/front_end/core/i18n/locales/ur.json +95 -41
- package/front_end/core/i18n/locales/uz.json +95 -41
- package/front_end/core/i18n/locales/vi.json +104 -50
- package/front_end/core/i18n/locales/zh-HK.json +96 -42
- package/front_end/core/i18n/locales/zh-TW.json +97 -43
- package/front_end/core/i18n/locales/zh.json +99 -45
- package/front_end/core/i18n/locales/zu.json +95 -41
- package/front_end/core/sdk/CSSMatchedStyles.ts +158 -33
- package/front_end/core/sdk/CSSMetadata.ts +1 -8
- package/front_end/generated/InspectorBackendCommands.js +33 -2
- package/front_end/generated/protocol.ts +42 -7
- package/front_end/models/issues_manager/DeprecationIssue.ts +3 -3
- package/front_end/panels/changes/ChangesView.ts +25 -10
- package/front_end/panels/elements/ElementsPanel.ts +7 -6
- package/front_end/panels/elements/StylesSidebarPane.ts +39 -15
- package/front_end/panels/elements/stylesSectionTree.css +1 -0
- package/front_end/panels/elements/stylesSidebarPane.css +1 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +38 -7
- package/front_end/panels/lighthouse/LighthousePanel.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseStartView.ts +15 -7
- package/front_end/panels/lighthouse/LighthouseStartViewFR.ts +77 -21
- package/front_end/panels/lighthouse/RadioSetting.ts +12 -6
- package/front_end/panels/lighthouse/lighthouseStartView.css +49 -2
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +1 -0
- package/front_end/panels/security/SecurityPanel.ts +2 -2
- package/front_end/ui/components/diff_view/diffView.css +2 -0
- package/front_end/ui/components/tree_outline/TreeOutline.ts +18 -7
- package/front_end/ui/legacy/Toolbar.ts +5 -0
- package/front_end/ui/legacy/softDropDownButton.css +4 -0
- package/package.json +2 -1
- package/scripts/eslint_rules/lib/inline_type_imports.js +158 -0
- package/scripts/eslint_rules/tests/inline_type_imports_test.js +106 -0
- package/scripts/javascript_natives/index.js +1 -2
@@ -10,20 +10,32 @@ import {StartView} from './LighthouseStartView.js';
|
|
10
10
|
import {Events} from './LighthouseController.js';
|
11
11
|
|
12
12
|
const UIStrings = {
|
13
|
+
/**
|
14
|
+
* @description Text displayed as the title of a panel that can be used to audit a web page with Lighthouse.
|
15
|
+
*/
|
16
|
+
generateLighthouseReport: 'Generate a Lighthouse report',
|
13
17
|
/**
|
14
18
|
* @description Text that refers to the Lighthouse mode
|
15
19
|
*/
|
16
20
|
mode: 'Mode',
|
21
|
+
/**
|
22
|
+
* @description Title in the Lighthouse Start View for list of categories to run during audit
|
23
|
+
*/
|
24
|
+
categories: 'Categories',
|
25
|
+
/**
|
26
|
+
* @description Title in the Lighthouse Start View for list of available start plugins
|
27
|
+
*/
|
28
|
+
plugins: 'Plugins',
|
17
29
|
/**
|
18
30
|
* @description Label for a button to start analyzing a page navigation with Lighthouse
|
19
31
|
*/
|
20
|
-
analyzeNavigation: 'Analyze
|
32
|
+
analyzeNavigation: 'Analyze page load',
|
21
33
|
/**
|
22
34
|
* @description Label for a button to start analyzing the current page state with Lighthouse
|
23
35
|
*/
|
24
|
-
analyzeSnapshot: 'Analyze
|
36
|
+
analyzeSnapshot: 'Analyze page state',
|
25
37
|
/**
|
26
|
-
* @description Label for a button that
|
38
|
+
* @description Label for a button that starts a Lighthouse mode that analyzes user interactions over a period of time.
|
27
39
|
*/
|
28
40
|
startTimespan: 'Start timespan',
|
29
41
|
};
|
@@ -35,31 +47,75 @@ export class StartViewFR extends StartView {
|
|
35
47
|
protected render(): void {
|
36
48
|
super.render();
|
37
49
|
const fragment = UI.Fragment.Fragment.build`
|
38
|
-
|
39
|
-
<
|
40
|
-
|
41
|
-
|
42
|
-
|
50
|
+
<form class="lighthouse-start-view-fr">
|
51
|
+
<header class="hbox">
|
52
|
+
<div class="lighthouse-logo"></div>
|
53
|
+
<div class="lighthouse-title">${i18nString(UIStrings.generateLighthouseReport)}</div>
|
54
|
+
<div class="lighthouse-start-button-container">${this.startButton}</div>
|
55
|
+
</header>
|
56
|
+
<div $="help-text" class="lighthouse-help-text hidden"></div>
|
57
|
+
<div class="lighthouse-options hbox">
|
58
|
+
<div class="lighthouse-form-section">
|
59
|
+
<div class="lighthouse-form-elements" $="mode-form-elements"></div>
|
60
|
+
</div>
|
61
|
+
<div class="lighthouse-form-section">
|
62
|
+
<div class="lighthouse-form-elements" $="device-type-form-elements"></div>
|
63
|
+
</div>
|
64
|
+
<div class="lighthouse-form-categories">
|
65
|
+
<div class="lighthouse-form-section">
|
66
|
+
<div class="lighthouse-form-section-label">${i18nString(UIStrings.categories)}</div>
|
67
|
+
<div class="lighthouse-form-elements" $="categories-form-elements"></div>
|
68
|
+
</div>
|
69
|
+
<div class="lighthouse-form-section">
|
70
|
+
<div class="lighthouse-form-section-label">
|
71
|
+
<div class="lighthouse-icon-label">${i18nString(UIStrings.plugins)}</div>
|
72
|
+
</div>
|
73
|
+
<div class="lighthouse-form-elements" $="plugins-form-elements"></div>
|
74
|
+
</div>
|
75
|
+
</div>
|
43
76
|
</div>
|
77
|
+
<div $="warning-text" class="lighthouse-warning-text hidden"></div>
|
78
|
+
</form>
|
44
79
|
`;
|
45
80
|
|
81
|
+
this.helpText = fragment.$('help-text');
|
82
|
+
this.warningText = fragment.$('warning-text');
|
83
|
+
|
84
|
+
// The previous radios are removed later and don't exist on the new fragment yet.
|
85
|
+
this.populateFormControls(fragment);
|
86
|
+
|
46
87
|
// Populate the Lighthouse mode
|
47
88
|
const modeFormElements = fragment.$('mode-form-elements');
|
48
89
|
this.populateRuntimeSettingAsRadio('lighthouse.mode', i18nString(UIStrings.mode), modeFormElements);
|
49
90
|
|
50
|
-
|
51
|
-
|
52
|
-
this.
|
91
|
+
this.contentElement.textContent = '';
|
92
|
+
this.contentElement.append(fragment.element());
|
93
|
+
this.updateMode();
|
94
|
+
}
|
95
|
+
|
96
|
+
onResize(): void {
|
97
|
+
const useNarrowLayout = this.contentElement.offsetWidth < 500;
|
98
|
+
const useWideLayout = this.contentElement.offsetWidth > 800;
|
99
|
+
const headerEl = this.contentElement.querySelector('.lighthouse-start-view-fr header');
|
100
|
+
const optionsEl = this.contentElement.querySelector('.lighthouse-options');
|
101
|
+
if (headerEl) {
|
102
|
+
headerEl.classList.toggle('hbox', !useNarrowLayout);
|
103
|
+
headerEl.classList.toggle('vbox', useNarrowLayout);
|
104
|
+
}
|
105
|
+
if (optionsEl) {
|
106
|
+
optionsEl.classList.toggle('wide', useWideLayout);
|
107
|
+
optionsEl.classList.toggle('narrow', useNarrowLayout);
|
108
|
+
}
|
53
109
|
}
|
54
110
|
|
55
|
-
|
111
|
+
updateMode(): void {
|
56
112
|
const {mode} = this.controller.getFlags();
|
57
113
|
|
58
|
-
let
|
114
|
+
let buttonLabel: Platform.UIString.LocalizedString;
|
59
115
|
let callback: () => void;
|
60
116
|
|
61
117
|
if (mode === 'timespan') {
|
62
|
-
|
118
|
+
buttonLabel = i18nString(UIStrings.startTimespan);
|
63
119
|
callback = (): void => {
|
64
120
|
this.controller.dispatchEventToListeners(
|
65
121
|
Events.RequestLighthouseTimespanStart,
|
@@ -67,7 +123,7 @@ export class StartViewFR extends StartView {
|
|
67
123
|
);
|
68
124
|
};
|
69
125
|
} else if (mode === 'snapshot') {
|
70
|
-
|
126
|
+
buttonLabel = i18nString(UIStrings.analyzeSnapshot);
|
71
127
|
callback = (): void => {
|
72
128
|
this.controller.dispatchEventToListeners(
|
73
129
|
Events.RequestLighthouseStart,
|
@@ -75,7 +131,7 @@ export class StartViewFR extends StartView {
|
|
75
131
|
);
|
76
132
|
};
|
77
133
|
} else {
|
78
|
-
|
134
|
+
buttonLabel = i18nString(UIStrings.analyzeNavigation);
|
79
135
|
callback = (): void => {
|
80
136
|
this.controller.dispatchEventToListeners(
|
81
137
|
Events.RequestLighthouseStart,
|
@@ -85,16 +141,16 @@ export class StartViewFR extends StartView {
|
|
85
141
|
}
|
86
142
|
|
87
143
|
this.startButton = UI.UIUtils.createTextButton(
|
88
|
-
|
144
|
+
buttonLabel,
|
89
145
|
callback,
|
90
146
|
/* className */ '',
|
91
147
|
/* primary */ true,
|
92
148
|
);
|
93
149
|
|
94
|
-
const
|
95
|
-
if (
|
96
|
-
|
97
|
-
|
150
|
+
const startButtonContainerEl = this.contentElement.querySelector('.lighthouse-start-button-container');
|
151
|
+
if (startButtonContainerEl) {
|
152
|
+
startButtonContainerEl.textContent = '';
|
153
|
+
startButtonContainerEl.appendChild(this.startButton);
|
98
154
|
}
|
99
155
|
}
|
100
156
|
}
|
@@ -5,16 +5,20 @@
|
|
5
5
|
import type * as Common from '../../core/common/common.js';
|
6
6
|
import * as UI from '../../ui/legacy/legacy.js';
|
7
7
|
|
8
|
+
interface RadioOption {
|
9
|
+
value: string;
|
10
|
+
label: () => Common.UIString.LocalizedString;
|
11
|
+
tooltip?: () => Common.UIString.LocalizedString;
|
12
|
+
}
|
13
|
+
|
8
14
|
export class RadioSetting {
|
9
15
|
private readonly setting: Common.Settings.Setting<string>;
|
10
|
-
private options:
|
16
|
+
private options: RadioOption[];
|
11
17
|
element: HTMLDivElement;
|
12
18
|
private radioElements: HTMLInputElement[];
|
13
19
|
private ignoreChangeEvents: boolean;
|
14
20
|
private selectedIndex: number;
|
15
|
-
constructor(
|
16
|
-
options: {value: string, label: () => Common.UIString.LocalizedString}[],
|
17
|
-
setting: Common.Settings.Setting<string>, description: string) {
|
21
|
+
constructor(options: RadioOption[], setting: Common.Settings.Setting<string>, description: string) {
|
18
22
|
this.setting = setting;
|
19
23
|
this.options = options;
|
20
24
|
|
@@ -32,9 +36,11 @@ export class RadioSetting {
|
|
32
36
|
`;
|
33
37
|
|
34
38
|
this.element.appendChild(fragment.element());
|
39
|
+
|
40
|
+
const tooltip = option.tooltip?.() || description;
|
35
41
|
if (description) {
|
36
|
-
UI.Tooltip.Tooltip.install(fragment.$('input') as HTMLElement,
|
37
|
-
UI.Tooltip.Tooltip.install(fragment.$('span') as HTMLElement,
|
42
|
+
UI.Tooltip.Tooltip.install(fragment.$('input') as HTMLElement, tooltip);
|
43
|
+
UI.Tooltip.Tooltip.install(fragment.$('span') as HTMLElement, tooltip);
|
38
44
|
}
|
39
45
|
const radioElement = fragment.$('input') as HTMLInputElement;
|
40
46
|
radioElement.addEventListener('change', this.valueChanged.bind(this));
|
@@ -5,7 +5,8 @@
|
|
5
5
|
*/
|
6
6
|
/* <3 */
|
7
7
|
|
8
|
-
.lighthouse-start-view
|
8
|
+
.lighthouse-start-view,
|
9
|
+
.lighthouse-start-view-fr {
|
9
10
|
font-family: Roboto, sans-serif;
|
10
11
|
font-size: var(--font-size);
|
11
12
|
line-height: 18px;
|
@@ -16,6 +17,10 @@
|
|
16
17
|
--report-font-family: roboto, helvetica, arial, sans-serif;
|
17
18
|
}
|
18
19
|
|
20
|
+
.lighthouse-start-view-fr {
|
21
|
+
margin: 24px;
|
22
|
+
}
|
23
|
+
|
19
24
|
.lighthouse-start-view header {
|
20
25
|
flex: 2 1;
|
21
26
|
padding: 16px;
|
@@ -23,6 +28,15 @@
|
|
23
28
|
justify-items: center;
|
24
29
|
}
|
25
30
|
|
31
|
+
.lighthouse-start-view-fr header {
|
32
|
+
display: flex;
|
33
|
+
font-size: 18px;
|
34
|
+
flex-direction: row;
|
35
|
+
align-items: center;
|
36
|
+
column-gap: 16px;
|
37
|
+
margin-bottom: 16px;
|
38
|
+
}
|
39
|
+
|
26
40
|
.lighthouse-logo {
|
27
41
|
width: 75px;
|
28
42
|
height: 75px;
|
@@ -32,6 +46,11 @@
|
|
32
46
|
background-image: var(--image-file-lighthouse_logo);
|
33
47
|
}
|
34
48
|
|
49
|
+
.lighthouse-start-view-fr .lighthouse-logo {
|
50
|
+
width: 45px;
|
51
|
+
height: 45px;
|
52
|
+
}
|
53
|
+
|
35
54
|
.lighthouse-start-view-text {
|
36
55
|
margin: 0 40px;
|
37
56
|
text-align: center;
|
@@ -65,6 +84,10 @@
|
|
65
84
|
top: -4px;
|
66
85
|
}
|
67
86
|
|
87
|
+
.lighthouse-form-section-label .lighthouse-learn-more {
|
88
|
+
padding: 20px;
|
89
|
+
}
|
90
|
+
|
68
91
|
.lighthouse-radio {
|
69
92
|
display: flex;
|
70
93
|
align-items: center;
|
@@ -86,8 +109,16 @@ input[type="radio"]:focus {
|
|
86
109
|
align-items: center;
|
87
110
|
}
|
88
111
|
|
112
|
+
.lighthouse-start-view-fr header.hbox .lighthouse-start-button-container {
|
113
|
+
margin-left: auto;
|
114
|
+
}
|
115
|
+
|
116
|
+
.lighthouse-start-view-fr header.vbox .lighthouse-title {
|
117
|
+
text-align: center;
|
118
|
+
}
|
119
|
+
|
89
120
|
.lighthouse-start-button-container button {
|
90
|
-
margin:
|
121
|
+
margin: 16px auto;
|
91
122
|
font-family: var(--report-font-family);
|
92
123
|
font-weight: 500;
|
93
124
|
font-size: var(--font-size);
|
@@ -136,3 +167,19 @@ input[type="radio"]:focus {
|
|
136
167
|
content: "⚠";
|
137
168
|
margin-right: 10px;
|
138
169
|
}
|
170
|
+
|
171
|
+
.lighthouse-options {
|
172
|
+
display: grid;
|
173
|
+
grid-template-columns: auto auto;
|
174
|
+
grid-template-rows: auto auto;
|
175
|
+
}
|
176
|
+
|
177
|
+
.lighthouse-options.narrow {
|
178
|
+
grid-template-columns: auto;
|
179
|
+
grid-template-rows: auto auto auto;
|
180
|
+
}
|
181
|
+
|
182
|
+
.lighthouse-options.wide {
|
183
|
+
grid-template-columns: auto auto auto;
|
184
|
+
grid-template-rows: auto;
|
185
|
+
}
|
@@ -111,7 +111,7 @@ const UIStrings = {
|
|
111
111
|
*@description Second part of the body of message to display in devtools security tab when you are viewing a page that triggered a safety tip.
|
112
112
|
*/
|
113
113
|
ifYouBelieveThisIsShownIn:
|
114
|
-
'If you believe this is shown in error please visit https://
|
114
|
+
'If you believe this is shown in error please visit https://g.co/chrome/lookalike-warnings.',
|
115
115
|
/**
|
116
116
|
*@description Summary of a warning when the user visits a page that triggered a Safety Tip because the domain looked like another domain.
|
117
117
|
*/
|
@@ -126,7 +126,7 @@ const UIStrings = {
|
|
126
126
|
*@description second part of body of a warning when the user visits a page that triggered a Safety Tip because the domain looked like another domain.
|
127
127
|
*/
|
128
128
|
ifYouBelieveThisIsShownInErrorSafety:
|
129
|
-
'If you believe this is shown in error please visit https://
|
129
|
+
'If you believe this is shown in error please visit https://g.co/chrome/lookalike-warnings.',
|
130
130
|
/**
|
131
131
|
*@description Title of the devtools security tab when the page you are on triggered a safety tip.
|
132
132
|
*/
|
@@ -11,12 +11,14 @@
|
|
11
11
|
font-size: var(--source-code-font-size);
|
12
12
|
white-space: pre;
|
13
13
|
line-height: 1.2em;
|
14
|
+
user-select: text;
|
14
15
|
}
|
15
16
|
|
16
17
|
.diff-line-number {
|
17
18
|
color: var(--color-line-number);
|
18
19
|
padding: 0 3px 0 9px;
|
19
20
|
text-align: right;
|
21
|
+
user-select: none;
|
20
22
|
}
|
21
23
|
|
22
24
|
.diff-line-marker {
|
@@ -255,25 +255,36 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
255
255
|
return this.#selectedTreeNode;
|
256
256
|
}
|
257
257
|
|
258
|
-
async #
|
258
|
+
async #flattenSubtree(node: TreeNodeWithChildren<TreeNodeDataType>, filter: (node: TreeNodeDataType) => FilterOption):
|
259
|
+
Promise<TreeNode<TreeNodeDataType>[]> {
|
259
260
|
const children = await getNodeChildren(node);
|
260
|
-
if (!this.#nodeFilter) {
|
261
|
-
return children;
|
262
|
-
}
|
263
261
|
const filteredChildren = [];
|
264
262
|
for (const child of children) {
|
265
|
-
const filtering =
|
263
|
+
const filtering = filter(child.treeNodeData);
|
266
264
|
// We always include the selected node in the tree, regardless of its filtering status.
|
267
|
-
|
265
|
+
const toBeSelected = this.#isSelectedNode(child) || child.id === this.#nodeIdPendingFocus;
|
266
|
+
// If a node is already expanded we should not flatten it away.
|
267
|
+
const expanded = this.#nodeExpandedMap.get(child.id);
|
268
|
+
if (filtering === FilterOption.SHOW || toBeSelected || expanded) {
|
268
269
|
filteredChildren.push(child);
|
269
270
|
} else if (filtering === FilterOption.FLATTEN && isExpandableNode(child)) {
|
270
|
-
const grandChildren = await this.#
|
271
|
+
const grandChildren = await this.#flattenSubtree(child, filter);
|
271
272
|
filteredChildren.push(...grandChildren);
|
272
273
|
}
|
273
274
|
}
|
274
275
|
return filteredChildren;
|
275
276
|
}
|
276
277
|
|
278
|
+
async #fetchNodeChildren(node: TreeNodeWithChildren<TreeNodeDataType>): Promise<TreeNode<TreeNodeDataType>[]> {
|
279
|
+
const children = await getNodeChildren(node);
|
280
|
+
const filter = this.#nodeFilter;
|
281
|
+
if (!filter) {
|
282
|
+
return children;
|
283
|
+
}
|
284
|
+
const filteredDescendants = await this.#flattenSubtree(node, filter);
|
285
|
+
return filteredDescendants.length ? filteredDescendants : children;
|
286
|
+
}
|
287
|
+
|
277
288
|
#setNodeExpandedState(node: TreeNode<TreeNodeDataType>, newExpandedState: boolean): void {
|
278
289
|
this.#nodeExpandedMap.set(node.id, newExpandedState);
|
279
290
|
}
|
@@ -57,6 +57,10 @@ const UIStrings = {
|
|
57
57
|
*@description Announced screen reader message for ToolbarSettingToggle when the setting is toggled off.
|
58
58
|
*/
|
59
59
|
notPressed: 'not pressed',
|
60
|
+
/**
|
61
|
+
*@description Tooltip shown when the user hovers over the clear icon to empty the text input.
|
62
|
+
*/
|
63
|
+
clearInput: 'Clear input',
|
60
64
|
};
|
61
65
|
const str_ = i18n.i18n.registerUIStrings('ui/legacy/Toolbar.ts', UIStrings);
|
62
66
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
@@ -701,6 +705,7 @@ export class ToolbarInput extends ToolbarItem<ToolbarInput.EventTypes> {
|
|
701
705
|
}
|
702
706
|
|
703
707
|
const clearButton = this.element.createChild('div', 'toolbar-input-clear-button');
|
708
|
+
clearButton.title = UIStrings.clearInput;
|
704
709
|
clearButton.appendChild(Icon.create('mediumicon-gray-cross-active', 'search-cancel-button'));
|
705
710
|
clearButton.addEventListener('click', () => {
|
706
711
|
this.setValue('', true);
|
@@ -23,6 +23,10 @@ button.soft-dropdown > .title {
|
|
23
23
|
text-overflow: ellipsis;
|
24
24
|
}
|
25
25
|
|
26
|
+
button.soft-dropdown:hover:not(:active) > .title {
|
27
|
+
color: var(--color-text-primary);
|
28
|
+
}
|
29
|
+
|
26
30
|
@media (forced-colors: active) {
|
27
31
|
button.soft-dropdown {
|
28
32
|
border: 1px solid ButtonText;
|
package/package.json
CHANGED
@@ -30,6 +30,7 @@
|
|
30
30
|
"check": "npm run check-lint && npm run check-loc",
|
31
31
|
"check-external-links": "vpython third_party/node/node.py --output scripts/check_external_links.js",
|
32
32
|
"check-lint": "vpython third_party/node/node.py --output scripts/test/run_lint_check_js.mjs && vpython third_party/node/node.py --output scripts/test/run_lint_check_css.js",
|
33
|
+
"check-lint-js": "vpython third_party/node/node.py --output scripts/test/run_lint_check_js.mjs",
|
33
34
|
"check-lint-css": "vpython third_party/node/node.py --output scripts/test/run_lint_check_css.js",
|
34
35
|
"collect-strings": "vpython third_party/node/node.py --output third_party/i18n/collect-strings.js front_end",
|
35
36
|
"components-server": "vpython third_party/node/node.py --output scripts/component_server/server.js",
|
@@ -54,5 +55,5 @@
|
|
54
55
|
"unittest": "scripts/test/run_unittests.py --no-text-coverage",
|
55
56
|
"watch": "vpython third_party/node/node.py --output scripts/watch_build.js"
|
56
57
|
},
|
57
|
-
"version": "1.0.
|
58
|
+
"version": "1.0.996595"
|
58
59
|
}
|
@@ -0,0 +1,158 @@
|
|
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
|
+
module.exports = {
|
7
|
+
meta: {
|
8
|
+
type: 'problem',
|
9
|
+
|
10
|
+
docs: {
|
11
|
+
description: 'Inline type imports.',
|
12
|
+
category: 'Possible Errors',
|
13
|
+
},
|
14
|
+
fixable: 'code',
|
15
|
+
messages: {
|
16
|
+
inlineTypeImport: 'Type imports must be imported in the same import statement as values, using the type keyword',
|
17
|
+
convertTypeImport: 'Type imports must use the type modifier on each item, not on the overall import statement',
|
18
|
+
},
|
19
|
+
schema: [] // no options
|
20
|
+
},
|
21
|
+
create: function(context) {
|
22
|
+
// Stores any type imports (import type {} from ...).
|
23
|
+
// The key is the literal import path ("../foo.js");
|
24
|
+
const typeImports = new Map();
|
25
|
+
// Stores any value imports (import {} from ...).
|
26
|
+
// The key is the literal import path ("../foo.js");
|
27
|
+
const valueImports = new Map();
|
28
|
+
|
29
|
+
// Takes the node that represents an import ("Foo", "Foo as Bar") and
|
30
|
+
// return the literal text.
|
31
|
+
function getTextForImportSpecifier(specifier) {
|
32
|
+
// import {Foo as Bar} from 'foo';
|
33
|
+
// Foo = imported name
|
34
|
+
// Bar = local name
|
35
|
+
const localName = specifier.local.name;
|
36
|
+
const importedName = specifier.imported.name;
|
37
|
+
if (localName === importedName) {
|
38
|
+
// No `X as Y`, so just use either name.
|
39
|
+
return localName;
|
40
|
+
}
|
41
|
+
return `${importedName} as ${localName}`;
|
42
|
+
}
|
43
|
+
|
44
|
+
function mergeImports(fixer, typeImportNode, valueImportNode) {
|
45
|
+
// Get all the references from the type import node that we need to add to the value import node.
|
46
|
+
const typeImportSpecifiers = typeImportNode.specifiers.map(spec => {
|
47
|
+
return getTextForImportSpecifier(spec);
|
48
|
+
});
|
49
|
+
|
50
|
+
// Find the last value specifier, which we will then insert the type imports to.
|
51
|
+
const lastValueSpecifier = valueImportNode.specifiers[valueImportNode.specifiers.length - 1];
|
52
|
+
|
53
|
+
// Remember that we don't need to concern ourselves with indentation: in
|
54
|
+
// PRESUBMIT clang-format runs _after_ ESLint, so we can let Clang tidy
|
55
|
+
// up any rough edges.
|
56
|
+
const textToImport = ', ' +
|
57
|
+
typeImportSpecifiers
|
58
|
+
.map(spec => `type ${spec}`)
|
59
|
+
.join(', ');
|
60
|
+
|
61
|
+
return [
|
62
|
+
// Remove the type import
|
63
|
+
fixer.remove(typeImportNode),
|
64
|
+
// Add the type imports to the existing import
|
65
|
+
fixer.insertTextAfter(lastValueSpecifier, textToImport)
|
66
|
+
];
|
67
|
+
}
|
68
|
+
|
69
|
+
function inlineTypeImportKeyword(fixer, typeImportNode) {
|
70
|
+
// We need to remove the " type" text after "import".
|
71
|
+
const importStart = typeImportNode.range[0];
|
72
|
+
const typeImportStart = importStart + 6; // 6 here = length of "import"
|
73
|
+
const typeImportEnd = typeImportStart + 5; // 5 here = length of "type" + 1 to remove the space after it.
|
74
|
+
|
75
|
+
const addTypeToSpecifiersFixers = typeImportNode.specifiers.map(spec => {
|
76
|
+
const newText = getTextForImportSpecifier(spec);
|
77
|
+
|
78
|
+
return fixer.replaceText(spec, `type ${newText}`);
|
79
|
+
});
|
80
|
+
|
81
|
+
return [
|
82
|
+
...addTypeToSpecifiersFixers,
|
83
|
+
fixer.removeRange([typeImportStart, typeImportEnd]),
|
84
|
+
];
|
85
|
+
}
|
86
|
+
|
87
|
+
return {
|
88
|
+
ImportDeclaration(node) {
|
89
|
+
// Note that we only care about named imports: import {} from 'foo.js'.
|
90
|
+
// This is because:
|
91
|
+
// 1: if we have `import type * as SDK from '../` that means we know we
|
92
|
+
// aren't using `SDK` for any values, otherwise we wouldn't have the
|
93
|
+
// `type` modifier.
|
94
|
+
// 2: similarly, `import type Foo from './foo'` follows (1). We also
|
95
|
+
// don't use this pattern in DevTools, but even if we did we don't have
|
96
|
+
// to worry about it.
|
97
|
+
// 3: Any side-effect imports (import './foo.js') are irrelevant.
|
98
|
+
|
99
|
+
if (!node.specifiers || node.specifiers.length < 1) {
|
100
|
+
// import './foo.js';
|
101
|
+
return;
|
102
|
+
}
|
103
|
+
|
104
|
+
if (node.specifiers[0].type === 'ImportDefaultSpecifier') {
|
105
|
+
// import Foo from './foo.js';
|
106
|
+
return;
|
107
|
+
}
|
108
|
+
|
109
|
+
if (node.specifiers[0].type === 'ImportNamespaceSpecifier') {
|
110
|
+
// import * as Foo from './foo.js';
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
|
114
|
+
// Store the import
|
115
|
+
const importFilePath = node.source.value;
|
116
|
+
if (node.importKind === 'type') {
|
117
|
+
typeImports.set(importFilePath, node);
|
118
|
+
} else if (node.importKind === 'value') {
|
119
|
+
valueImports.set(importFilePath, node);
|
120
|
+
}
|
121
|
+
},
|
122
|
+
'Program:exit'() {
|
123
|
+
// Loop over the type imports and see if there are any matching value
|
124
|
+
// imports.
|
125
|
+
// Looping this way means if there are any value imports without a
|
126
|
+
// matching type import, we leave them alone.
|
127
|
+
for (const [typeImportFilePath, typeImportNode] of typeImports) {
|
128
|
+
const valueImportNodeForFilePath = valueImports.get(typeImportFilePath);
|
129
|
+
if (valueImportNodeForFilePath) {
|
130
|
+
// If we've got here, we have two imports for the same file-path, one
|
131
|
+
// for types, and one for values, so let's merge them.
|
132
|
+
context.report({
|
133
|
+
node: typeImportNode,
|
134
|
+
messageId: 'inlineTypeImport',
|
135
|
+
fix(fixer) {
|
136
|
+
return mergeImports(fixer, typeImportNode, valueImportNodeForFilePath);
|
137
|
+
}
|
138
|
+
});
|
139
|
+
continue;
|
140
|
+
}
|
141
|
+
|
142
|
+
// At this point we have just a type import and no matching file
|
143
|
+
// import, but we still want to convert the import so that each
|
144
|
+
// imported reference uses the type modifier:
|
145
|
+
// BEFORE: import type {A, B} from '...';
|
146
|
+
// AFTER: import {type A, type B} from '...';
|
147
|
+
context.report({
|
148
|
+
node: typeImportNode,
|
149
|
+
messageId: 'convertTypeImport',
|
150
|
+
fix(fixer) {
|
151
|
+
return inlineTypeImportKeyword(fixer, typeImportNode);
|
152
|
+
}
|
153
|
+
});
|
154
|
+
}
|
155
|
+
},
|
156
|
+
};
|
157
|
+
}
|
158
|
+
};
|