lighthouse 8.5.1 → 8.6.0-dev.20211013
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/changelog.md +5490 -0
- package/flow-report/.eslintrc.cjs +49 -0
- package/flow-report/assets/styles.css +272 -9
- package/flow-report/jest.config.js +1 -1
- package/flow-report/package.json +4 -0
- package/flow-report/src/app.tsx +31 -9
- package/flow-report/src/common.tsx +86 -7
- package/flow-report/src/header.tsx +88 -0
- package/flow-report/src/help-dialog.tsx +120 -0
- package/flow-report/src/i18n/i18n.tsx +44 -0
- package/flow-report/src/i18n/localized-strings.js +11 -0
- package/flow-report/src/i18n/ui-strings.js +86 -0
- package/flow-report/src/icons.tsx +20 -3
- package/flow-report/src/sidebar/sidebar.tsx +11 -16
- package/flow-report/src/summary/category.tsx +42 -24
- package/flow-report/src/summary/summary.tsx +32 -29
- package/flow-report/src/topbar.tsx +54 -4
- package/flow-report/src/util.ts +26 -1
- package/flow-report/src/wrappers/report-renderer.tsx +1 -1
- package/flow-report/src/wrappers/report.tsx +6 -21
- package/flow-report/test/app-test.tsx +17 -13
- package/flow-report/test/common-test.tsx +89 -0
- package/flow-report/test/header-test.tsx +55 -0
- package/flow-report/test/sample-flow.ts +17 -0
- package/flow-report/test/setup/env-setup.ts +1 -0
- package/flow-report/test/sidebar/flow-test.tsx +6 -12
- package/flow-report/test/sidebar/sidebar-test.tsx +7 -13
- package/flow-report/test/summary/category-test.tsx +79 -34
- package/flow-report/test/summary/summary-test.tsx +11 -17
- package/flow-report/test/topbar-test.tsx +68 -0
- package/flow-report/test/util-test.tsx +1 -12
- package/flow-report/tsconfig.json +1 -0
- package/flow-report/types/flow-report.d.ts +2 -1
- package/jest.config.js +1 -15
- package/lighthouse-cli/bin.js +5 -0
- package/lighthouse-cli/cli-flags.js +10 -3
- package/lighthouse-cli/commands/commands.js +1 -0
- package/lighthouse-cli/commands/list-locales.js +16 -0
- package/lighthouse-cli/run.js +2 -2
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +0 -0
- package/lighthouse-cli/test/smokehouse/report-assert.js +20 -4
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +2 -1
- package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -1
- package/lighthouse-core/audits/seo/crawlable-anchors.js +10 -12
- package/lighthouse-core/computed/js-bundles.js +1 -2
- package/lighthouse-core/computed/unused-javascript-summary.js +3 -3
- package/lighthouse-core/config/config.js +2 -2
- package/lighthouse-core/config/default-config.js +5 -0
- package/lighthouse-core/fraggle-rock/api.js +10 -0
- package/lighthouse-core/fraggle-rock/config/filters.js +22 -3
- package/lighthouse-core/fraggle-rock/gather/driver.js +4 -0
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +2 -2
- package/lighthouse-core/fraggle-rock/user-flow.js +35 -6
- package/lighthouse-core/gather/driver/navigation.js +5 -0
- package/lighthouse-core/gather/driver/prepare.js +14 -0
- package/lighthouse-core/gather/driver/storage.js +5 -0
- package/lighthouse-core/gather/gather-runner.js +2 -2
- package/lighthouse-core/gather/gatherers/dobetterweb/response-compression.js +5 -1
- package/lighthouse-core/gather/gatherers/full-page-screenshot.js +30 -24
- package/lighthouse-core/lib/cdt/Platform.js +55 -0
- package/lighthouse-core/lib/cdt/SDK.js +3 -123
- package/lighthouse-core/lib/cdt/generated/SourceMap.js +148 -312
- package/lighthouse-core/lib/csp-evaluator.js +2 -1
- package/lighthouse-core/lib/i18n/README.md +6 -6
- package/lighthouse-core/lib/i18n/i18n.js +9 -342
- package/lighthouse-core/lib/page-functions.js +4 -4
- package/lighthouse-core/lib/stack-packs.js +1 -13
- package/lighthouse-core/runner.js +6 -6
- package/lighthouse-core/scripts/manual-chrome-launcher.js +4 -1
- package/lighthouse-core/scripts/package.json +4 -0
- package/lighthouse-core/util-commonjs.js +20 -4
- package/package.json +19 -16
- package/readme.md +1 -1
- package/report/assets/standalone-template.html +0 -1
- package/report/assets/styles.css +16 -41
- package/report/assets/templates.html +42 -4
- package/report/clients/psi.js +1 -0
- package/report/clients/standalone.js +1 -2
- package/report/generator/file-namer.js +17 -8
- package/report/generator/report-generator.js +0 -1
- package/report/renderer/category-renderer.js +4 -16
- package/report/renderer/components.js +107 -71
- package/report/renderer/dom.js +19 -0
- package/report/renderer/logger.js +35 -2
- package/report/renderer/performance-category-renderer.js +23 -21
- package/report/renderer/pwa-category-renderer.js +1 -2
- package/report/renderer/report-renderer.js +21 -0
- package/report/renderer/report-ui-features.js +7 -19
- package/report/renderer/swap-locale-feature.js +82 -0
- package/report/renderer/util.js +20 -4
- package/report/test/clients/psi-test.js +0 -4
- package/report/test/generator/file-namer-test.js +2 -2
- package/report/test/renderer/category-renderer-test.js +1 -1
- package/report/test/renderer/performance-category-renderer-test.js +12 -0
- package/report/test/renderer/report-renderer-axe-test.js +86 -0
- package/report/test/renderer/report-renderer-test.js +0 -55
- package/report/test/renderer/util-test.js +68 -8
- package/report/test-assets/faux-psi-template.html +0 -1
- package/report/tsconfig.json +2 -1
- package/report/types/html-renderer.d.ts +2 -1
- package/root.js +18 -0
- package/shared/localization/format.js +422 -0
- package/{lighthouse-core/lib/cdt/Common.js → shared/localization/i18n-module.js} +3 -8
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ar-XB.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ar.json +141 -6
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/bg.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ca.json +140 -5
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/cs.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/da.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/de.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/el.json +141 -6
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/en-GB.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/en-US.json +111 -0
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/en-XA.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/en-XL.json +111 -0
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/es-419.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/es.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/fi.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/fil.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/fr.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/he.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/hi.json +142 -7
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/hr.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/hu.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/id.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/it.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ja.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ko.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/lt.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/lv.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/nl.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/no.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/pl.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/pt-PT.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/pt.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ro.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ru.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/sk.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/sl.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/sr-Latn.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/sr.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/sv.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/ta.json +146 -11
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/te.json +179 -44
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/th.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/tr.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/uk.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/vi.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/zh-HK.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/zh-TW.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales/zh.json +139 -4
- package/{lighthouse-core/lib/i18n → shared/localization}/locales.js +2 -1
- package/shared/localization/swap-flow-locale.js +20 -0
- package/{lighthouse-core/lib/i18n → shared/localization}/swap-locale.js +9 -7
- package/shared/test/localization/format-test.js +377 -0
- package/shared/test/localization/locales-test.js +47 -0
- package/shared/test/localization/swap-locale-test.js +140 -0
- package/shared/tsconfig.json +22 -0
- package/{lighthouse-core/lib → shared}/type-verifiers.js +0 -0
- package/shared/types/shared.d.ts +24 -0
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +5 -3
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -1
- package/tsconfig-all.json +1 -0
- package/tsconfig-base.json +1 -1
- package/tsconfig.json +2 -3
- package/types/config.d.ts +1 -0
- package/types/es-main.d.ts +18 -0
- package/types/externs.d.ts +2 -0
- package/types/lhr/flow.d.ts +7 -0
- package/types/lhr/i18n.d.ts +0 -3
- package/dist/report/flow.js +0 -149
- package/dist/report/standalone.js +0 -228
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
extends: '../.eslintrc.js',
|
|
9
|
+
env: {
|
|
10
|
+
node: true,
|
|
11
|
+
browser: true,
|
|
12
|
+
},
|
|
13
|
+
plugins: [
|
|
14
|
+
'@typescript-eslint',
|
|
15
|
+
],
|
|
16
|
+
rules: {
|
|
17
|
+
// TODO(esmodules): move to root eslint when all code is ESM
|
|
18
|
+
// or when this is resolved: https://github.com/import-js/eslint-plugin-import/issues/2214
|
|
19
|
+
'import/order': [2, {
|
|
20
|
+
'groups': [
|
|
21
|
+
'builtin',
|
|
22
|
+
'external',
|
|
23
|
+
['sibling', 'parent'],
|
|
24
|
+
'index',
|
|
25
|
+
'object',
|
|
26
|
+
'type',
|
|
27
|
+
],
|
|
28
|
+
'newlines-between': 'always',
|
|
29
|
+
}],
|
|
30
|
+
'@typescript-eslint/type-annotation-spacing': 2,
|
|
31
|
+
},
|
|
32
|
+
overrides: [
|
|
33
|
+
// TS already handles this issue.
|
|
34
|
+
// https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
|
|
35
|
+
{
|
|
36
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.js'],
|
|
37
|
+
rules: {
|
|
38
|
+
'no-undef': 'off',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
parserOptions: {
|
|
43
|
+
ecmaVersion: 2019,
|
|
44
|
+
ecmaFeatures: {
|
|
45
|
+
jsx: true,
|
|
46
|
+
},
|
|
47
|
+
sourceType: 'module',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -10,17 +10,28 @@
|
|
|
10
10
|
--category-summary-font-size: 18px;
|
|
11
11
|
--double-base-spacing: calc(var(--base-spacing) * 2);
|
|
12
12
|
--gather-mode-icon-size: 16px;
|
|
13
|
+
--header-adjacent-title-font-size: 14px;
|
|
14
|
+
--header-adjacent-title-width: minmax(var(--min-text-width), 1fr);
|
|
15
|
+
--header-current-description-font-size: 12px;
|
|
16
|
+
--header-current-title-font-size: 20px;
|
|
17
|
+
--header-margin: minmax(0px, calc(var(--base-spacing) * 4));
|
|
13
18
|
--half-base-spacing: calc(var(--base-spacing) / 2);
|
|
19
|
+
--min-text-width: 20ch;
|
|
20
|
+
--dialog-border-color: var(--color-gray-700);
|
|
14
21
|
--separator-color: var(--color-gray-300);
|
|
15
22
|
--sidebar-flow-step-navigation-font-size: 14px;
|
|
16
23
|
--sidebar-selected-bg-color: #DDEEFF;
|
|
17
24
|
--sidebar-summary-font-size: 14px;
|
|
18
25
|
--sidebar-title-font-size: 16px;
|
|
26
|
+
--sidebar-max-width: 400px;
|
|
19
27
|
--summary-flow-step-label-font-size: 16px;
|
|
20
28
|
--summary-subtitle-font-size: 16px;
|
|
21
29
|
--summary-title-font-size: 32px;
|
|
22
30
|
--summary-tooltip-box-shadow-color: rgba(0, 0, 0, 0.25);
|
|
31
|
+
--topbar-button-font-size: 14px;
|
|
32
|
+
--topbar-button-size: 45px;
|
|
23
33
|
--topbar-title-font-size: 14px;
|
|
34
|
+
--dialog-title-font-size: 20px;
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
.App {
|
|
@@ -41,23 +52,59 @@
|
|
|
41
52
|
display: none;
|
|
42
53
|
}
|
|
43
54
|
|
|
55
|
+
@media print {
|
|
56
|
+
.App {
|
|
57
|
+
grid-template-rows: 0px auto !important;
|
|
58
|
+
grid-template-columns: 0px auto !important;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.Topbar {
|
|
62
|
+
display: none !important;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.Sidebar {
|
|
66
|
+
display: none !important;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.Content {
|
|
70
|
+
overflow-y: visible !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.SummaryFlow {
|
|
74
|
+
grid-template-columns: repeat(7, min-content) !important;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
44
78
|
.Topbar {
|
|
79
|
+
position: relative;
|
|
80
|
+
padding-right: var(--base-spacing);
|
|
45
81
|
grid-area: topbar;
|
|
46
82
|
display: flex;
|
|
47
83
|
align-items: center;
|
|
48
84
|
border-bottom: 1px solid var(--separator-color);
|
|
49
85
|
}
|
|
50
86
|
|
|
51
|
-
.
|
|
52
|
-
|
|
87
|
+
.TopbarButton {
|
|
88
|
+
height: var(--topbar-button-size);
|
|
89
|
+
min-width: var(--topbar-button-size);
|
|
53
90
|
cursor: pointer;
|
|
54
91
|
display: flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
justify-content: center;
|
|
55
94
|
-webkit-touch-callout: none;
|
|
56
95
|
-webkit-user-select: none;
|
|
57
96
|
-khtml-user-select: none;
|
|
58
97
|
-moz-user-select: none;
|
|
59
98
|
-ms-user-select: none;
|
|
60
99
|
user-select: none;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
background: none;
|
|
102
|
+
color: inherit;
|
|
103
|
+
border: none;
|
|
104
|
+
font: inherit;
|
|
105
|
+
outline: inherit;
|
|
106
|
+
font-size: var(--topbar-button-font-size);
|
|
107
|
+
margin-right: var(--base-spacing);
|
|
61
108
|
}
|
|
62
109
|
|
|
63
110
|
.Topbar__logo {
|
|
@@ -68,6 +115,7 @@
|
|
|
68
115
|
.Topbar__title {
|
|
69
116
|
font-size: var(--topbar-title-font-size);
|
|
70
117
|
font-weight: bold;
|
|
118
|
+
margin-right: var(--double-base-spacing);
|
|
71
119
|
}
|
|
72
120
|
|
|
73
121
|
.Content {
|
|
@@ -100,6 +148,10 @@
|
|
|
100
148
|
.Sidebar {
|
|
101
149
|
grid-area: sidebar;
|
|
102
150
|
border-right: 1px solid var(--separator-color);
|
|
151
|
+
width: min-content;
|
|
152
|
+
max-width: var(--sidebar-max-width);
|
|
153
|
+
overflow-x: hidden;
|
|
154
|
+
overflow-y: auto;
|
|
103
155
|
}
|
|
104
156
|
.Sidebar a {
|
|
105
157
|
color: var(--color-gray-800);
|
|
@@ -181,6 +233,8 @@
|
|
|
181
233
|
grid-column: 2;
|
|
182
234
|
margin: var(--half-base-spacing) 0px;
|
|
183
235
|
justify-self: left;
|
|
236
|
+
overflow-x: hidden;
|
|
237
|
+
text-overflow: ellipsis;
|
|
184
238
|
}
|
|
185
239
|
.SidebarFlowStep__label--navigation {
|
|
186
240
|
font-size: var(--sidebar-flow-step-navigation-font-size);
|
|
@@ -223,14 +277,14 @@
|
|
|
223
277
|
|
|
224
278
|
.SummarySectionHeader__content {
|
|
225
279
|
margin: var(--base-spacing) 0px;
|
|
280
|
+
text-transform: uppercase;
|
|
226
281
|
}
|
|
227
282
|
|
|
228
283
|
.SummaryFlow {
|
|
229
284
|
width: 100%;
|
|
230
|
-
max-width: max-content;
|
|
231
285
|
display: grid;
|
|
232
286
|
grid-auto-rows: min-content;
|
|
233
|
-
grid-template-columns: min-content min-content 4fr 1fr 1fr 1fr 1fr;
|
|
287
|
+
grid-template-columns: min-content min-content minmax(var(--min-text-width), 4fr) 1fr 1fr 1fr 1fr;
|
|
234
288
|
align-items: center;
|
|
235
289
|
margin: var(--base-spacing) 0px;
|
|
236
290
|
}
|
|
@@ -266,21 +320,24 @@
|
|
|
266
320
|
.SummaryFlowStep .FlowSegment {
|
|
267
321
|
grid-column: 2;
|
|
268
322
|
}
|
|
323
|
+
.SummaryFlowStep .FlowStepThumbnail {
|
|
324
|
+
margin: var(--base-spacing) var(--half-base-spacing);
|
|
325
|
+
}
|
|
269
326
|
|
|
270
|
-
.
|
|
327
|
+
.FlowStepThumbnail {
|
|
271
328
|
align-self: center;
|
|
272
329
|
justify-self: center;
|
|
273
|
-
margin: var(--base-spacing) var(--half-base-spacing);
|
|
274
330
|
object-fit: cover;
|
|
275
331
|
object-position: top left;
|
|
276
|
-
}
|
|
277
|
-
.SummaryFlowStep__screenshot[src] {
|
|
278
332
|
border: 1px solid var(--color-gray);
|
|
279
333
|
}
|
|
280
334
|
|
|
281
335
|
.SummaryFlowStep__label {
|
|
282
336
|
grid-column: 3;
|
|
283
337
|
margin: var(--half-base-spacing);
|
|
338
|
+
width: 100%;
|
|
339
|
+
overflow-x: hidden;
|
|
340
|
+
text-overflow: ellipsis;
|
|
284
341
|
}
|
|
285
342
|
|
|
286
343
|
.SummaryFlowStep__mode {
|
|
@@ -291,6 +348,8 @@
|
|
|
291
348
|
font-size: var(--summary-flow-step-label-font-size);
|
|
292
349
|
color: var(--color-gray-800);
|
|
293
350
|
text-decoration: underline;
|
|
351
|
+
width: 100%;
|
|
352
|
+
overflow-x: hidden;
|
|
294
353
|
}
|
|
295
354
|
|
|
296
355
|
.SummaryCategory__content {
|
|
@@ -314,7 +373,7 @@
|
|
|
314
373
|
width: max-content;
|
|
315
374
|
background-color: var(--report-background-color);
|
|
316
375
|
border: 1px solid var(--color-gray-900);
|
|
317
|
-
border-radius:
|
|
376
|
+
border-radius: 3px;
|
|
318
377
|
padding: var(--base-spacing);
|
|
319
378
|
right: 0;
|
|
320
379
|
box-shadow: 0px 4px 4px var(--summary-tooltip-box-shadow-color);
|
|
@@ -360,6 +419,7 @@
|
|
|
360
419
|
justify-content: center;
|
|
361
420
|
padding: var(--half-base-spacing);
|
|
362
421
|
background-color: var(--color-gray-100);
|
|
422
|
+
color: var(--color-gray-700);
|
|
363
423
|
border-top: 1px solid var(--color-gray-300);
|
|
364
424
|
text-align: center;
|
|
365
425
|
}
|
|
@@ -367,6 +427,11 @@
|
|
|
367
427
|
justify-content: start;
|
|
368
428
|
text-align: left;
|
|
369
429
|
}
|
|
430
|
+
.SummaryNavigationHeader__url > a {
|
|
431
|
+
color: inherit;
|
|
432
|
+
overflow-x: hidden;
|
|
433
|
+
text-overflow: ellipsis;
|
|
434
|
+
}
|
|
370
435
|
|
|
371
436
|
.SummaryFlowStep__separator {
|
|
372
437
|
display: contents;
|
|
@@ -383,3 +448,201 @@
|
|
|
383
448
|
margin: auto;
|
|
384
449
|
background-color: var(--color-gray-700);
|
|
385
450
|
}
|
|
451
|
+
|
|
452
|
+
.Header {
|
|
453
|
+
display: grid;
|
|
454
|
+
grid-template-areas:
|
|
455
|
+
". . . current-tn . . ."
|
|
456
|
+
"prev-seg prev-tn prev-tn current-tn next-tn next-tn next-seg"
|
|
457
|
+
". prev-title . current-tn . next-title ."
|
|
458
|
+
". prev-title current-title current-title current-title next-title .";
|
|
459
|
+
grid-template-rows: 1fr auto 1fr auto;
|
|
460
|
+
grid-template-columns: var(--header-margin) var(--header-adjacent-title-width) auto auto auto var(--header-adjacent-title-width) var(--header-margin);
|
|
461
|
+
align-items: center;
|
|
462
|
+
margin: var(--double-base-spacing) 0px;
|
|
463
|
+
}
|
|
464
|
+
.Header a {
|
|
465
|
+
color: var(--color-gray-800);
|
|
466
|
+
}
|
|
467
|
+
.Header > .Header__segment:first-child {
|
|
468
|
+
grid-area: prev-seg;
|
|
469
|
+
}
|
|
470
|
+
.Header > .Header__segment:last-child {
|
|
471
|
+
grid-area: next-seg;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.Header__prev-thumbnail {
|
|
475
|
+
display: flex;
|
|
476
|
+
align-items: center;
|
|
477
|
+
grid-area: prev-tn;
|
|
478
|
+
}
|
|
479
|
+
.Header__current-thumbnail {
|
|
480
|
+
display: flex;
|
|
481
|
+
align-items: center;
|
|
482
|
+
grid-area: current-tn;
|
|
483
|
+
}
|
|
484
|
+
.Header__next-thumbnail {
|
|
485
|
+
display: flex;
|
|
486
|
+
align-items: center;
|
|
487
|
+
grid-area: next-tn;
|
|
488
|
+
}
|
|
489
|
+
.Header__prev-thumbnail .Header__segment,
|
|
490
|
+
.Header__next-thumbnail .Header__segment {
|
|
491
|
+
flex-grow: 1;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.Header__segment {
|
|
495
|
+
height: 2px;
|
|
496
|
+
background-color: var(--color-blue-A700);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
.HeaderThumbnail {
|
|
500
|
+
position: relative;
|
|
501
|
+
display: flex;
|
|
502
|
+
margin: var(--base-spacing) 0px;
|
|
503
|
+
}
|
|
504
|
+
.HeaderThumbnail--main .FlowStepThumbnail {
|
|
505
|
+
border: 2px solid var(--color-blue-A700);
|
|
506
|
+
}
|
|
507
|
+
.HeaderThumbnail--prev .HeaderThumbnail__icon {
|
|
508
|
+
top: 50%;
|
|
509
|
+
left: 100%;
|
|
510
|
+
}
|
|
511
|
+
.HeaderThumbnail--next .HeaderThumbnail__icon {
|
|
512
|
+
top: 50%;
|
|
513
|
+
left: 0;
|
|
514
|
+
}
|
|
515
|
+
.HeaderThumbnail--main .HeaderThumbnail__icon {
|
|
516
|
+
top: 100%;
|
|
517
|
+
left: 50%;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.HeaderThumbnail__icon {
|
|
521
|
+
position: absolute;
|
|
522
|
+
display: flex;
|
|
523
|
+
padding: calc(var(--base-spacing) * 0.25);
|
|
524
|
+
background-color: var(--report-background-color);
|
|
525
|
+
border-radius: 50%;
|
|
526
|
+
transform: translate(-50%, -50%);
|
|
527
|
+
color: var(--color-blue-A700)
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.Header__prev-title {
|
|
531
|
+
grid-area: prev-title;
|
|
532
|
+
text-align: left;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
.Header__next-title {
|
|
536
|
+
grid-area: next-title;
|
|
537
|
+
text-align: right;
|
|
538
|
+
justify-self: end;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.Header__prev-title,
|
|
542
|
+
.Header__next-title {
|
|
543
|
+
font-size: var(--header-adjacent-title-font-size);
|
|
544
|
+
align-self: start;
|
|
545
|
+
overflow-x: hidden;
|
|
546
|
+
text-overflow: ellipsis;
|
|
547
|
+
width: 100%;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.Header__current-title {
|
|
551
|
+
grid-area: current-title;
|
|
552
|
+
text-align: center;
|
|
553
|
+
font-size: var(--header-current-title-font-size);
|
|
554
|
+
font-weight: bold;
|
|
555
|
+
overflow-x: hidden;
|
|
556
|
+
text-overflow: ellipsis;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.Header__current-description {
|
|
560
|
+
text-align: center;
|
|
561
|
+
font-size: var(--header-current-description-font-size);
|
|
562
|
+
font-weight: normal;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.HelpDialog {
|
|
566
|
+
position: absolute;
|
|
567
|
+
top: 100%;
|
|
568
|
+
right: var(--base-spacing);
|
|
569
|
+
z-index: 100;
|
|
570
|
+
max-width: 720px;
|
|
571
|
+
|
|
572
|
+
background: var(--color-white);
|
|
573
|
+
color: var(--color-gray-800);
|
|
574
|
+
border-radius: 3px;
|
|
575
|
+
border: 1px solid var(--dialog-border-color);
|
|
576
|
+
box-shadow: 0px 4px 12px var(--summary-tooltip-box-shadow-color);
|
|
577
|
+
|
|
578
|
+
padding: var(--base-spacing) calc(var(--base-spacing) * 1.5);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.HelpDialog__title {
|
|
582
|
+
display: flex;
|
|
583
|
+
align-items: center;
|
|
584
|
+
|
|
585
|
+
font-size: var(--dialog-title-font-size);
|
|
586
|
+
font-weight: bold;
|
|
587
|
+
|
|
588
|
+
margin-bottom: calc(var(--base-spacing) * 2);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.HelpDialog__close {
|
|
592
|
+
background: none;
|
|
593
|
+
border: none;
|
|
594
|
+
cursor: pointer;
|
|
595
|
+
line-height: 0;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.HelpDialog__columns {
|
|
599
|
+
display: grid;
|
|
600
|
+
grid-auto-flow: column;
|
|
601
|
+
grid-template-rows: repeat(4, auto);
|
|
602
|
+
grid-template-columns: repeat(3, 1fr);
|
|
603
|
+
grid-column-gap: var(--base-spacing);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.HelpDialogColumn {
|
|
607
|
+
display: contents;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.HelpDialogColumn__header-title {
|
|
611
|
+
font-size: var(--category-summary-font-size);
|
|
612
|
+
font-weight: bold;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.HelpDialogColumn__legend-label {
|
|
616
|
+
color: var(--color-blue-A700);
|
|
617
|
+
font-weight: bold;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
.HelpDialogColumn ul {
|
|
621
|
+
padding-left: var(--base-spacing);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.HelpDialogColumn__use-cases p,
|
|
625
|
+
.HelpDialogColumn__categories p {
|
|
626
|
+
font-weight: bold;
|
|
627
|
+
color: var(--color-gray-700);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.HelpDialogColumnTimeline {
|
|
631
|
+
display: flex;
|
|
632
|
+
align-items: center;
|
|
633
|
+
|
|
634
|
+
height: var(--double-base-spacing);
|
|
635
|
+
color: var(--color-blue-A700);
|
|
636
|
+
margin-right: calc(var(--base-spacing) * -1);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.HelpDialogColumn:last-child .HelpDialogColumnTimeline {
|
|
640
|
+
margin-right: 0;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.HelpDialogColumnTimeline__line {
|
|
644
|
+
height: 2px;
|
|
645
|
+
flex-grow: 1;
|
|
646
|
+
|
|
647
|
+
background: var(--color-blue-A700);
|
|
648
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export default {
|
|
8
8
|
testEnvironment: 'node',
|
|
9
9
|
preset: 'ts-jest',
|
|
10
10
|
globalSetup: './test/setup/global-setup.ts',
|
package/flow-report/src/app.tsx
CHANGED
|
@@ -5,23 +5,43 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
|
-
import {useState} from 'preact/hooks';
|
|
8
|
+
import {useEffect, useRef, useState} from 'preact/hooks';
|
|
9
9
|
|
|
10
10
|
import {ReportRendererProvider} from './wrappers/report-renderer';
|
|
11
11
|
import {Sidebar} from './sidebar/sidebar';
|
|
12
12
|
import {Summary} from './summary/summary';
|
|
13
|
-
import {classNames, FlowResultContext, useCurrentLhr} from './util';
|
|
13
|
+
import {classNames, FlowResultContext, useCurrentLhr, useHashParam} from './util';
|
|
14
14
|
import {Report} from './wrappers/report';
|
|
15
15
|
import {Topbar} from './topbar';
|
|
16
|
+
import {Header} from './header';
|
|
17
|
+
import {I18nProvider} from './i18n/i18n';
|
|
16
18
|
|
|
17
19
|
const Content: FunctionComponent = () => {
|
|
18
20
|
const currentLhr = useCurrentLhr();
|
|
21
|
+
const anchor = useHashParam('anchor');
|
|
22
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (anchor) {
|
|
26
|
+
const el = document.getElementById(anchor);
|
|
27
|
+
if (el) {
|
|
28
|
+
el.scrollIntoView({behavior: 'smooth'});
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Scroll to top no anchor is found.
|
|
34
|
+
if (ref.current) ref.current.scrollTop = 0;
|
|
35
|
+
}, [anchor, currentLhr]);
|
|
19
36
|
|
|
20
37
|
return (
|
|
21
|
-
<div className="Content">
|
|
38
|
+
<div ref={ref} className="Content">
|
|
22
39
|
{
|
|
23
40
|
currentLhr ?
|
|
24
|
-
|
|
41
|
+
<>
|
|
42
|
+
<Header currentLhr={currentLhr}/>
|
|
43
|
+
<Report currentLhr={currentLhr}/>
|
|
44
|
+
</> :
|
|
25
45
|
<Summary/>
|
|
26
46
|
}
|
|
27
47
|
</div>
|
|
@@ -33,11 +53,13 @@ export const App: FunctionComponent<{flowResult: LH.FlowResult}> = ({flowResult}
|
|
|
33
53
|
return (
|
|
34
54
|
<FlowResultContext.Provider value={flowResult}>
|
|
35
55
|
<ReportRendererProvider>
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
56
|
+
<I18nProvider>
|
|
57
|
+
<div className={classNames('App', {'App--collapsed': collapsed})} data-testid="App">
|
|
58
|
+
<Topbar onMenuClick={() => setCollapsed(c => !c)} />
|
|
59
|
+
<Sidebar/>
|
|
60
|
+
<Content/>
|
|
61
|
+
</div>
|
|
62
|
+
</I18nProvider>
|
|
41
63
|
</ReportRendererProvider>
|
|
42
64
|
</FlowResultContext.Provider>
|
|
43
65
|
);
|
|
@@ -5,27 +5,106 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
|
+
import {useEffect, useState} from 'preact/hooks';
|
|
8
9
|
|
|
9
10
|
import {NavigationIcon, SnapshotIcon, TimespanIcon} from './icons';
|
|
11
|
+
import {getFilmstripFrames, getScreenDimensions, getScreenshot} from './util';
|
|
12
|
+
|
|
13
|
+
const ANIMATION_FRAME_DURATION_MS = 250;
|
|
10
14
|
|
|
11
15
|
export const Separator: FunctionComponent = () => {
|
|
12
16
|
return <div className="Separator" role="separator"></div>;
|
|
13
17
|
};
|
|
14
18
|
|
|
19
|
+
export const FlowStepIcon: FunctionComponent<{mode: LH.Result.GatherMode}> = ({mode}) => {
|
|
20
|
+
return <>
|
|
21
|
+
{
|
|
22
|
+
mode === 'navigation' && <NavigationIcon/>
|
|
23
|
+
}
|
|
24
|
+
{
|
|
25
|
+
mode === 'timespan' && <TimespanIcon/>
|
|
26
|
+
}
|
|
27
|
+
{
|
|
28
|
+
mode === 'snapshot' && <SnapshotIcon/>
|
|
29
|
+
}
|
|
30
|
+
</>;
|
|
31
|
+
};
|
|
32
|
+
|
|
15
33
|
export const FlowSegment: FunctionComponent<{mode?: LH.Result.GatherMode}> = ({mode}) => {
|
|
16
34
|
return (
|
|
17
35
|
<div className="FlowSegment">
|
|
18
36
|
<div className="FlowSegment__top-line"/>
|
|
19
37
|
{
|
|
20
|
-
mode
|
|
21
|
-
}
|
|
22
|
-
{
|
|
23
|
-
mode === 'timespan' && <TimespanIcon/>
|
|
24
|
-
}
|
|
25
|
-
{
|
|
26
|
-
mode === 'snapshot' && <SnapshotIcon/>
|
|
38
|
+
mode && <FlowStepIcon mode={mode}/>
|
|
27
39
|
}
|
|
28
40
|
<div className="FlowSegment__bottom-line"/>
|
|
29
41
|
</div>
|
|
30
42
|
);
|
|
31
43
|
};
|
|
44
|
+
|
|
45
|
+
const FlowStepAnimatedThumbnail: FunctionComponent<{
|
|
46
|
+
frames: Array<{data: string}>,
|
|
47
|
+
width: number,
|
|
48
|
+
height: number,
|
|
49
|
+
}> = ({frames, width, height}) => {
|
|
50
|
+
const [frameIndex, setFrameIndex] = useState(0);
|
|
51
|
+
// Handle a frame array of a different length being set.
|
|
52
|
+
const effectiveFrameIndex = frameIndex % frames.length;
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const interval = setInterval(
|
|
56
|
+
() => setFrameIndex(i => (i + 1) % frames.length),
|
|
57
|
+
ANIMATION_FRAME_DURATION_MS
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return () => clearInterval(interval);
|
|
61
|
+
}, [frames.length]);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<img
|
|
65
|
+
className="FlowStepThumbnail"
|
|
66
|
+
data-testid="FlowStepAnimatedThumbnail"
|
|
67
|
+
src={frames[effectiveFrameIndex].data}
|
|
68
|
+
style={{width, height}}
|
|
69
|
+
alt="Animated screenshots of a page tested by Lighthouse"
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const FlowStepThumbnail: FunctionComponent<{
|
|
75
|
+
reportResult: LH.ReportResult,
|
|
76
|
+
width?: number,
|
|
77
|
+
height?: number,
|
|
78
|
+
}> = ({reportResult, width, height}) => {
|
|
79
|
+
const screenshot = getScreenshot(reportResult);
|
|
80
|
+
const frames = getFilmstripFrames(reportResult);
|
|
81
|
+
|
|
82
|
+
// Resize the image to fit the viewport aspect ratio.
|
|
83
|
+
const dimensions = getScreenDimensions(reportResult);
|
|
84
|
+
if (width && height === undefined) {
|
|
85
|
+
height = dimensions.height * width / dimensions.width;
|
|
86
|
+
} else if (height && width === undefined) {
|
|
87
|
+
width = dimensions.width * height / dimensions.height;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!width || !height) {
|
|
91
|
+
console.warn(new Error('FlowStepThumbnail requested without any dimensions').stack);
|
|
92
|
+
return <></>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (reportResult.gatherMode === 'timespan' && frames && frames.length) {
|
|
96
|
+
return <FlowStepAnimatedThumbnail frames={frames} width={width} height={height} />;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return <>
|
|
100
|
+
{
|
|
101
|
+
screenshot &&
|
|
102
|
+
<img
|
|
103
|
+
className="FlowStepThumbnail"
|
|
104
|
+
src={screenshot}
|
|
105
|
+
style={{width, height}}
|
|
106
|
+
alt="Screenshot of a page tested by Lighthouse"
|
|
107
|
+
/>
|
|
108
|
+
}
|
|
109
|
+
</>;
|
|
110
|
+
};
|