lighthouse 8.3.0-dev.20210904 → 8.3.0
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 +1 -1
- package/dist/report/standalone.js +196 -0
- package/jest.config.js +0 -4
- package/lighthouse-cli/cli-flags.js +6 -14
- package/lighthouse-cli/run.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +3 -9
- package/lighthouse-cli/test/smokehouse/report-assert.js +16 -36
- package/lighthouse-core/audits/large-javascript-libraries.js +166 -0
- package/lighthouse-core/audits/seo/http-status-code.js +6 -2
- package/lighthouse-core/audits/viewport.js +1 -2
- package/lighthouse-core/config/config-helpers.js +75 -9
- package/lighthouse-core/config/config.js +50 -6
- package/lighthouse-core/config/constants.js +0 -1
- package/lighthouse-core/config/default-config.js +0 -3
- package/lighthouse-core/config/experimental-config.js +8 -0
- package/lighthouse-core/config/metrics-to-audits.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +4 -3
- package/lighthouse-core/fraggle-rock/config/default-config.js +1 -3
- package/lighthouse-core/fraggle-rock/config/validation.js +0 -201
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +0 -4
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +8 -16
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +0 -4
- package/lighthouse-core/fraggle-rock/gather/session.js +5 -30
- package/lighthouse-core/gather/driver/navigation.js +6 -7
- package/lighthouse-core/gather/driver/wait-for-condition.js +0 -27
- package/lighthouse-core/gather/fetcher.js +7 -17
- package/lighthouse-core/gather/gather-runner.js +0 -1
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +6 -2
- package/lighthouse-core/gather/gatherers/seo/tap-targets.js +2 -2
- package/lighthouse-core/gather/gatherers/stacks.js +1 -1
- package/lighthouse-core/lib/asset-saver.js +2 -2
- package/lighthouse-core/lib/cdt/SDK.js +0 -1
- package/lighthouse-core/lib/csp-evaluator.js +4 -17
- package/{report/generator → lighthouse-core/lib}/file-namer.js +0 -0
- package/lighthouse-core/lib/i18n/README.md +1 -1
- package/lighthouse-core/lib/i18n/i18n.js +7 -7
- package/lighthouse-core/lib/i18n/locales/ar-XB.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ar.json +18 -0
- package/lighthouse-core/lib/i18n/locales/bg.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ca.json +18 -0
- package/lighthouse-core/lib/i18n/locales/cs.json +18 -0
- package/lighthouse-core/lib/i18n/locales/da.json +18 -0
- package/lighthouse-core/lib/i18n/locales/de.json +18 -0
- package/lighthouse-core/lib/i18n/locales/el.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-GB.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-US.json +18 -18
- package/lighthouse-core/lib/i18n/locales/en-XA.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +18 -18
- package/lighthouse-core/lib/i18n/locales/es-419.json +18 -0
- package/lighthouse-core/lib/i18n/locales/es.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fil.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/he.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hu.json +18 -0
- package/lighthouse-core/lib/i18n/locales/id.json +18 -0
- package/lighthouse-core/lib/i18n/locales/it.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ja.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ko.json +18 -0
- package/lighthouse-core/lib/i18n/locales/lt.json +18 -0
- package/lighthouse-core/lib/i18n/locales/lv.json +18 -0
- package/lighthouse-core/lib/i18n/locales/nl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/no.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pt-PT.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pt.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ro.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ru.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sk.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sr-Latn.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sv.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ta.json +18 -0
- package/lighthouse-core/lib/i18n/locales/te.json +18 -0
- package/lighthouse-core/lib/i18n/locales/th.json +18 -0
- package/lighthouse-core/lib/i18n/locales/tr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/uk.json +18 -0
- package/lighthouse-core/lib/i18n/locales/vi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh-HK.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh-TW.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh.json +18 -0
- package/lighthouse-core/lib/large-javascript-libraries/bundlephobia-database.json +62 -0
- package/lighthouse-core/lib/large-javascript-libraries/library-suggestions.js +20 -0
- package/lighthouse-core/lib/network-request.js +1 -3
- package/lighthouse-core/lib/traces/pwmetrics-events.js +2 -2
- package/lighthouse-core/lib/url-shim.js +1 -7
- package/lighthouse-core/runner.js +1 -4
- package/lighthouse-core/util-commonjs.js +2 -2
- package/now.json +1 -1
- package/package.json +13 -20
- package/report/README.md +2 -2
- package/report/assets/standalone-template.html +1 -0
- package/report/assets/styles.css +27 -23
- package/report/assets/templates.html +40 -37
- package/report/clients/bundle.js +0 -1
- package/report/{package.json → clients/package.json} +0 -0
- package/report/clients/psi.js +3 -13
- package/report/clients/standalone.js +1 -1
- package/report/{types/buffer.d.ts → clients/treemap.js} +13 -11
- package/report/renderer/category-renderer.js +2 -2
- package/report/renderer/components.js +48 -46
- package/report/renderer/crc-details-renderer.js +16 -16
- package/report/renderer/details-renderer.js +1 -1
- package/report/renderer/dom.js +0 -17
- package/report/renderer/element-screenshot-renderer.js +9 -9
- package/{flow-report/test/setup/global-setup.ts → report/renderer/file-namer.js} +2 -5
- package/report/renderer/logger.js +4 -4
- package/report/renderer/package.json +4 -0
- package/report/renderer/report-renderer.js +11 -4
- package/report/renderer/report-ui-features.js +656 -43
- package/report/renderer/text-encoding.js +1 -1
- package/report/renderer/util.js +2 -2
- package/report/{generator/report-assets.js → report-assets.js} +3 -9
- package/report/{generator/report-generator.js → report-generator.js} +9 -37
- package/report/test/clients/package.json +4 -0
- package/report/test/clients/psi-test.js +1 -3
- package/report/test/renderer/category-renderer-test.js +1 -2
- package/report/test/renderer/components-test.js +0 -35
- package/report/test/renderer/crc-details-renderer-test.js +4 -5
- package/report/test/renderer/details-renderer-test.js +1 -3
- package/report/test/renderer/dom-test.js +6 -8
- package/report/test/renderer/i18n-test.js +0 -1
- package/report/test/renderer/package.json +4 -0
- package/report/test/renderer/performance-category-renderer-test.js +2 -3
- package/report/test/renderer/pwa-category-renderer-test.js +1 -2
- package/report/test/renderer/report-renderer-test.js +0 -1
- package/report/test/renderer/report-ui-features-test.js +18 -20
- package/report/test/renderer/snippet-renderer-test.js +0 -1
- package/report/test/renderer/text-encoding-test.js +0 -2
- package/report/test/renderer/util-test.js +0 -1
- package/report/test/{generator/report-generator-test.js → report-generator-test.js} +2 -4
- package/third-party/chromium-synchronization/installability-errors-test.js +27 -28
- package/third-party/snyk/snapshot.json +0 -2
- package/tsconfig.json +5 -24
- package/types/artifacts.d.ts +18 -5
- package/types/{lhr/audit-details.d.ts → audit-details.d.ts} +3 -18
- package/types/audit.d.ts +58 -7
- package/types/{lhr/budget.d.ts → budget.d.ts} +0 -0
- package/types/bundle-phobia-cli/index.d.ts +40 -0
- package/types/config.d.ts +8 -3
- package/types/externs.d.ts +119 -5
- package/types/gatherer.d.ts +2 -3
- package/types/global-lh.d.ts +14 -16
- package/{report/types/report-result.d.ts → types/html-renderer.d.ts} +17 -8
- package/types/{lhr/i18n.d.ts → i18n.d.ts} +25 -2
- package/types/{lhr/lhr.d.ts → lhr.d.ts} +9 -41
- package/types/smokehouse.d.ts +3 -3
- package/types/{lhr/treemap.d.ts → treemap.d.ts} +3 -3
- package/flow-report/assets/standalone-flow-template.html +0 -38
- package/flow-report/assets/styles.css +0 -310
- package/flow-report/jest.config.js +0 -24
- package/flow-report/src/app.tsx +0 -40
- package/flow-report/src/common.tsx +0 -72
- package/flow-report/src/icons.tsx +0 -96
- package/flow-report/src/sidebar/flow.tsx +0 -72
- package/flow-report/src/sidebar/sidebar.tsx +0 -89
- package/flow-report/src/summary/summary.tsx +0 -178
- package/flow-report/src/util.ts +0 -160
- package/flow-report/src/wrappers/gauge.tsx +0 -40
- package/flow-report/src/wrappers/report-renderer.tsx +0 -46
- package/flow-report/src/wrappers/report.tsx +0 -71
- package/flow-report/standalone-flow.tsx +0 -23
- package/flow-report/test/app-test.tsx +0 -48
- package/flow-report/test/common-test.tsx +0 -131
- package/flow-report/test/setup/env-setup.ts +0 -25
- package/flow-report/test/sidebar/flow-test.tsx +0 -71
- package/flow-report/test/sidebar/sidebar-test.tsx +0 -53
- package/flow-report/test/summary/summary-test.tsx +0 -132
- package/flow-report/test/util-test.tsx +0 -109
- package/flow-report/tsconfig.json +0 -39
- package/flow-report/types/flow-report.d.ts +0 -27
- package/lighthouse-core/audits/lcp-lazy-loaded.js +0 -83
- package/report/.eslintrc.cjs +0 -33
- package/report/generator/README.md +0 -9
- package/report/generator/flow-report-assets.js +0 -20
- package/report/generator/package.json +0 -4
- package/report/generator/tsconfig.json +0 -28
- package/report/renderer/drop-down-menu.js +0 -215
- package/report/renderer/features-util.js +0 -26
- package/report/renderer/open-tab.js +0 -137
- package/report/renderer/topbar-features.js +0 -309
- package/report/test/generator/file-namer-test.js +0 -28
- package/report/test/generator/package.json +0 -4
- package/report/test-assets/faux-psi-template.html +0 -126
- package/report/test-assets/faux-psi.js +0 -92
- package/report/tsconfig.json +0 -39
- package/report/types/augment-dom.d.ts +0 -24
- package/report/types/html-renderer.d.ts +0 -28
- package/types/lhr/audit-result.d.ts +0 -59
- package/types/lhr/flow.d.ts +0 -16
- package/types/lhr/settings.d.ts +0 -105
- package/types/lhr/tsconfig.json +0 -24
- package/types/query-selector.d.ts +0 -36
|
@@ -1,96 +0,0 @@
|
|
|
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
|
-
import {FunctionComponent} from 'preact';
|
|
8
|
-
|
|
9
|
-
/* eslint-disable max-len */
|
|
10
|
-
|
|
11
|
-
export const SummaryIcon: FunctionComponent = () => {
|
|
12
|
-
return (
|
|
13
|
-
<svg width="14" viewBox="0 0 18 16" fill="none" role="img">
|
|
14
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 2C0 1.17 0.67 0.5 1.5 0.5C2.33 0.5 3 1.17 3 2C3 2.83 2.33 3.5 1.5 3.5C0.67 3.5 0 2.83 0 2ZM0 8C0 7.17 0.67 6.5 1.5 6.5C2.33 6.5 3 7.17 3 8C3 8.83 2.33 9.5 1.5 9.5C0.67 9.5 0 8.83 0 8ZM1.5 12.5C0.67 12.5 0 13.18 0 14C0 14.82 0.68 15.5 1.5 15.5C2.32 15.5 3 14.82 3 14C3 13.18 2.33 12.5 1.5 12.5ZM18 15H5V13H18V15ZM5 9H18V7H5V9ZM5 3V1H18V3H5Z" fill="currentColor"/>
|
|
15
|
-
</svg>
|
|
16
|
-
);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const NavigationIcon: FunctionComponent = () => {
|
|
20
|
-
return (
|
|
21
|
-
<svg
|
|
22
|
-
width="16"
|
|
23
|
-
height="16"
|
|
24
|
-
viewBox="0 0 16 16"
|
|
25
|
-
fill="none"
|
|
26
|
-
role="img"
|
|
27
|
-
aria-label="Icon representing a navigation report">
|
|
28
|
-
<circle
|
|
29
|
-
cx="8"
|
|
30
|
-
cy="8"
|
|
31
|
-
r="7"
|
|
32
|
-
fill="none"
|
|
33
|
-
stroke="currentColor"
|
|
34
|
-
stroke-width="2"/>
|
|
35
|
-
</svg>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const TimespanIcon: FunctionComponent = () => {
|
|
40
|
-
return (
|
|
41
|
-
<svg
|
|
42
|
-
width="16"
|
|
43
|
-
height="16"
|
|
44
|
-
viewBox="0 0 16 16"
|
|
45
|
-
fill="none"
|
|
46
|
-
role="img"
|
|
47
|
-
aria-label="Icon representing a timespan report">
|
|
48
|
-
<circle
|
|
49
|
-
cx="8"
|
|
50
|
-
cy="8"
|
|
51
|
-
r="7"
|
|
52
|
-
fill="none"
|
|
53
|
-
stroke="currentColor"
|
|
54
|
-
stroke-width="2"/>
|
|
55
|
-
<path
|
|
56
|
-
d="m 8,4 v 4 l 4,1.9999998"
|
|
57
|
-
stroke="currentColor"
|
|
58
|
-
stroke-width="1.5"/>
|
|
59
|
-
</svg>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const SnapshotIcon: FunctionComponent = () => {
|
|
64
|
-
return (
|
|
65
|
-
<svg
|
|
66
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
67
|
-
width="16"
|
|
68
|
-
height="16"
|
|
69
|
-
viewBox="0 0 16 16"
|
|
70
|
-
fill="none"
|
|
71
|
-
role="img"
|
|
72
|
-
aria-label="Icon representing a snapshot report">
|
|
73
|
-
<path
|
|
74
|
-
fill-rule="evenodd"
|
|
75
|
-
clip-rule="evenodd"
|
|
76
|
-
d="M 12.2038,12.2812 C 11.1212,13.3443 9.6372,14 8,14 7.81038,14 7.62281,13.9912 7.43768,13.974 L 10.3094,9 Z M 12.8925,11.4741 10.0207,6.5 H 13.811 C 13.9344,6.97943 14,7.48205 14,8 c 0,1.2947 -0.4101,2.4937 -1.1075,3.4741 z M 13.456,5.5 H 7.71135 L 9.6065,2.21749 C 11.3203,2.69259 12.7258,3.90911 13.456,5.5 Z M 8.5624,2.02601 C 8.3772,2.0088 8.1896,2 8,2 6.36282,2 4.8788,2.65572 3.79622,3.71885 L 5.69061,7.00002 Z M 3.10749,4.52594 C 2.4101,5.5063 2,6.70526 2,8 2,8.5179 2.06563,9.0206 2.18903,9.5 H 5.97927 Z M 2.54404,10.5 c 0.73017,1.5909 2.1357,2.8074 3.84949,3.2825 L 8.2887,10.5 Z M 16,8 c 0,4.4183 -3.5817,8 -8,8 C 3.58172,16 0,12.4183 0,8 0,3.58172 3.58172,0 8,0 c 4.4183,0 8,3.58172 8,8 z"
|
|
77
|
-
fill="currentColor"/>
|
|
78
|
-
</svg>
|
|
79
|
-
);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export const EnvIcon: FunctionComponent = () => {
|
|
83
|
-
return (
|
|
84
|
-
<svg width="15" height="12" viewBox="0 0 15 12" fill="none" role="img">
|
|
85
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.33317 2.00008H13.9998V0.666748H3.33317C2.59984 0.666748 1.99984 1.26675 1.99984 2.00008V9.33341H0.666504V11.3334H7.99984V9.33341H3.33317V2.00008ZM13.9998 3.33341H9.99984C9.63317 3.33341 9.33317 3.63341 9.33317 4.00008V10.6667C9.33317 11.0334 9.63317 11.3334 9.99984 11.3334H13.9998C14.3665 11.3334 14.6665 11.0334 14.6665 10.6667V4.00008C14.6665 3.63341 14.3665 3.33341 13.9998 3.33341ZM10.6665 9.33341H13.3332V4.66675H10.6665V9.33341Z" fill="currentColor"/>
|
|
86
|
-
</svg>
|
|
87
|
-
);
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const CpuIcon: FunctionComponent = () => {
|
|
91
|
-
return (
|
|
92
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" role="img">
|
|
93
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.5 7.16667V5.5H13.8333V3.83333C13.8333 2.91667 13.0833 2.16667 12.1667 2.16667H10.5V0.5H8.83333V2.16667H7.16667V0.5H5.5V2.16667H3.83333C2.91667 2.16667 2.16667 2.91667 2.16667 3.83333V5.5H0.5V7.16667H2.16667V8.83333H0.5V10.5H2.16667V12.1667C2.16667 13.0833 2.91667 13.8333 3.83333 13.8333H5.5V15.5H7.16667V13.8333H8.83333V15.5H10.5V13.8333H12.1667C13.0833 13.8333 13.8333 13.0833 13.8333 12.1667V10.5H15.5V8.83333H13.8333V7.16667H15.5ZM10.5 5.5H5.5V10.5H10.5V5.5ZM3.83333 12.1667H12.1667V3.83333H3.83333V12.1667Z" fill="currentColor"/>
|
|
94
|
-
</svg>
|
|
95
|
-
);
|
|
96
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
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
|
-
import {FunctionComponent} from 'preact';
|
|
8
|
-
|
|
9
|
-
import {FlowSegment} from '../common';
|
|
10
|
-
import {classNames, useCurrentLhr, useDerivedStepNames, useFlowResult} from '../util';
|
|
11
|
-
import {Separator} from '../common';
|
|
12
|
-
|
|
13
|
-
const SidebarFlowStep: FunctionComponent<{
|
|
14
|
-
mode: LH.Result.GatherMode,
|
|
15
|
-
href: string,
|
|
16
|
-
label: string,
|
|
17
|
-
isCurrent: boolean,
|
|
18
|
-
}> = ({href, label, mode, isCurrent}) => {
|
|
19
|
-
return (
|
|
20
|
-
<a
|
|
21
|
-
className={classNames('SidebarFlowStep', {'Sidebar--current': isCurrent})}
|
|
22
|
-
href={href}
|
|
23
|
-
>
|
|
24
|
-
<div>
|
|
25
|
-
<FlowSegment mode={mode}/>
|
|
26
|
-
</div>
|
|
27
|
-
<div className={`SidebarFlowStep__label SidebarFlowStep__label--${mode}`}>{label}</div>
|
|
28
|
-
</a>
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const SidebarFlowSeparator: FunctionComponent = () => {
|
|
33
|
-
return (
|
|
34
|
-
<div className="SidebarFlowSeparator">
|
|
35
|
-
<FlowSegment/>
|
|
36
|
-
<Separator/>
|
|
37
|
-
<FlowSegment/>
|
|
38
|
-
</div>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const SidebarFlow: FunctionComponent = () => {
|
|
43
|
-
const flowResult = useFlowResult();
|
|
44
|
-
const currentLhr = useCurrentLhr();
|
|
45
|
-
const stepNames = useDerivedStepNames();
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<div className="SidebarFlow">
|
|
49
|
-
{
|
|
50
|
-
flowResult.lhrs.map((lhr, index) => {
|
|
51
|
-
const stepName = stepNames[index];
|
|
52
|
-
const url = new URL(location.href);
|
|
53
|
-
url.hash = `#index=${index}`;
|
|
54
|
-
return <>
|
|
55
|
-
{
|
|
56
|
-
lhr.gatherMode === 'navigation' && index !== 0 ?
|
|
57
|
-
<SidebarFlowSeparator/> :
|
|
58
|
-
undefined
|
|
59
|
-
}
|
|
60
|
-
<SidebarFlowStep
|
|
61
|
-
key={lhr.fetchTime}
|
|
62
|
-
mode={lhr.gatherMode}
|
|
63
|
-
href={url.href}
|
|
64
|
-
label={stepName}
|
|
65
|
-
isCurrent={index === (currentLhr && currentLhr.index)}
|
|
66
|
-
/>
|
|
67
|
-
</>;
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
@@ -1,89 +0,0 @@
|
|
|
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
|
-
import {FunctionComponent} from 'preact';
|
|
8
|
-
import {useMemo} from 'preact/hooks';
|
|
9
|
-
|
|
10
|
-
import {Separator} from '../common';
|
|
11
|
-
import {CpuIcon, EnvIcon, SummaryIcon} from '../icons';
|
|
12
|
-
import {classNames, useCurrentLhr, useFlowResult, useLocale} from '../util';
|
|
13
|
-
import {SidebarFlow} from './flow';
|
|
14
|
-
|
|
15
|
-
export const SidebarSummary: FunctionComponent = () => {
|
|
16
|
-
const currentLhr = useCurrentLhr();
|
|
17
|
-
const url = new URL(location.href);
|
|
18
|
-
url.hash = '#';
|
|
19
|
-
return (
|
|
20
|
-
<a
|
|
21
|
-
href={url.href}
|
|
22
|
-
className={classNames('SidebarSummary', {'Sidebar--current': currentLhr === null})}
|
|
23
|
-
data-testid="SidebarSummary"
|
|
24
|
-
>
|
|
25
|
-
<div className="SidebarSummary__icon">
|
|
26
|
-
<SummaryIcon/>
|
|
27
|
-
</div>
|
|
28
|
-
<div className="SidebarSummary__label">Summary</div>
|
|
29
|
-
</a>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const SidebarRuntimeSettings: FunctionComponent<{settings: LH.ConfigSettings}> = ({settings}) => {
|
|
34
|
-
return (
|
|
35
|
-
<div className="SidebarRuntimeSettings">
|
|
36
|
-
<div className="SidebarRuntimeSettings__item">
|
|
37
|
-
<div className="SidebarRuntimeSettings__item--icon">
|
|
38
|
-
<EnvIcon/>
|
|
39
|
-
</div>
|
|
40
|
-
{
|
|
41
|
-
`${settings.formFactor === 'desktop' ? 'Desktop' : 'Mobile'} | ` +
|
|
42
|
-
`${settings.screenEmulation.height}x${settings.screenEmulation.width}px`
|
|
43
|
-
}
|
|
44
|
-
</div>
|
|
45
|
-
<div className="SidebarRuntimeSettings__item">
|
|
46
|
-
<div className="SidebarRuntimeSettings__item--icon">
|
|
47
|
-
<CpuIcon/>
|
|
48
|
-
</div>
|
|
49
|
-
{
|
|
50
|
-
`${settings.throttling.cpuSlowdownMultiplier}x slowdown`
|
|
51
|
-
}
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const SidebarHeader: FunctionComponent<{title: string, date: string}> = ({title, date}) => {
|
|
58
|
-
const locale = useLocale();
|
|
59
|
-
const formatter = useMemo(() => {
|
|
60
|
-
const options: Intl.DateTimeFormatOptions = {
|
|
61
|
-
month: 'short', day: 'numeric', year: 'numeric',
|
|
62
|
-
hour: 'numeric', minute: 'numeric', timeZoneName: 'short',
|
|
63
|
-
};
|
|
64
|
-
return new Intl.DateTimeFormat(locale, options);
|
|
65
|
-
}, [locale]);
|
|
66
|
-
const dateString = useMemo(() => formatter.format(new Date(date)), [date, formatter]);
|
|
67
|
-
return (
|
|
68
|
-
<div className="SidebarHeader">
|
|
69
|
-
<div className="SidebarHeader__title">{title}</div>
|
|
70
|
-
<div className="SidebarHeader__date">{dateString}</div>
|
|
71
|
-
</div>
|
|
72
|
-
);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export const Sidebar: FunctionComponent = () => {
|
|
76
|
-
const flowResult = useFlowResult();
|
|
77
|
-
const firstLhr = flowResult.lhrs[0];
|
|
78
|
-
return (
|
|
79
|
-
<div className="Sidebar">
|
|
80
|
-
<SidebarHeader title="Lighthouse User Flow Report" date={firstLhr.fetchTime}/>
|
|
81
|
-
<Separator/>
|
|
82
|
-
<SidebarSummary/>
|
|
83
|
-
<Separator/>
|
|
84
|
-
<SidebarFlow/>
|
|
85
|
-
<Separator/>
|
|
86
|
-
<SidebarRuntimeSettings settings={firstLhr.configSettings}/>
|
|
87
|
-
</div>
|
|
88
|
-
);
|
|
89
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
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
|
-
import {FunctionComponent} from 'preact';
|
|
8
|
-
import {useMemo} from 'preact/hooks';
|
|
9
|
-
|
|
10
|
-
import {Gauge} from '../wrappers/gauge';
|
|
11
|
-
import {FlowSegment} from '../common';
|
|
12
|
-
import {CategoryRatio} from '../common';
|
|
13
|
-
import {getScreenDimensions, getScreenshot, useDerivedStepNames, useFlowResult} from '../util';
|
|
14
|
-
import {Util} from '../../../report/renderer/util';
|
|
15
|
-
|
|
16
|
-
const DISPLAYED_CATEGORIES = ['performance', 'accessibility', 'best-practices', 'seo'];
|
|
17
|
-
const THUMBNAIL_WIDTH = 50;
|
|
18
|
-
|
|
19
|
-
const SummaryNavigationHeader: FunctionComponent<{url: string}> = ({url}) => {
|
|
20
|
-
return (
|
|
21
|
-
<div className="SummaryNavigationHeader" data-testid="SummaryNavigationHeader">
|
|
22
|
-
<FlowSegment/>
|
|
23
|
-
<div className="SummaryNavigationHeader__url">{url}</div>
|
|
24
|
-
<div className="SummaryNavigationHeader__category">Performance</div>
|
|
25
|
-
<div className="SummaryNavigationHeader__category">Accessibility</div>
|
|
26
|
-
<div className="SummaryNavigationHeader__category">Best Practices</div>
|
|
27
|
-
<div className="SummaryNavigationHeader__category">SEO</div>
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const SummaryCategory: FunctionComponent<{
|
|
33
|
-
gatherMode: LH.Result.GatherMode,
|
|
34
|
-
audits: LH.ReportResult['audits'],
|
|
35
|
-
category: LH.ReportResult.Category|undefined,
|
|
36
|
-
href: string,
|
|
37
|
-
}> = ({gatherMode, audits, category, href}) => {
|
|
38
|
-
return (
|
|
39
|
-
<div className="SummaryCategory">
|
|
40
|
-
{
|
|
41
|
-
category ?
|
|
42
|
-
(
|
|
43
|
-
gatherMode === 'navigation' ?
|
|
44
|
-
<Gauge
|
|
45
|
-
category={category}
|
|
46
|
-
href={href}
|
|
47
|
-
/> :
|
|
48
|
-
<CategoryRatio
|
|
49
|
-
category={category}
|
|
50
|
-
audits={audits}
|
|
51
|
-
href={href}
|
|
52
|
-
/>
|
|
53
|
-
) :
|
|
54
|
-
<div
|
|
55
|
-
className="SummaryCategory__null"
|
|
56
|
-
data-testid="SummaryCategory__null"
|
|
57
|
-
/>
|
|
58
|
-
}
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* The div should behave like a JSX <>...</>. This still allows us to identify "rows" with CSS selectors.
|
|
65
|
-
*/
|
|
66
|
-
export const SummaryFlowStep: FunctionComponent<{
|
|
67
|
-
lhr: LH.Result,
|
|
68
|
-
label: string,
|
|
69
|
-
hashIndex: number,
|
|
70
|
-
}> = ({lhr, label, hashIndex}) => {
|
|
71
|
-
// TODO(FR-COMPAT): Store report results globally.
|
|
72
|
-
const reportResult = useMemo(() => Util.prepareReportResult(lhr), [lhr]);
|
|
73
|
-
|
|
74
|
-
const screenshot = reportResult.gatherMode !== 'timespan' ? getScreenshot(reportResult) : null;
|
|
75
|
-
|
|
76
|
-
// Crop the displayed image to the viewport dimensions.
|
|
77
|
-
const {width, height} = getScreenDimensions(reportResult);
|
|
78
|
-
const thumbnailHeight = height * THUMBNAIL_WIDTH / width;
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<div className="SummaryFlowStep">
|
|
82
|
-
{
|
|
83
|
-
lhr.gatherMode === 'navigation' || hashIndex === 0 ?
|
|
84
|
-
<SummaryNavigationHeader url={lhr.finalUrl}/> :
|
|
85
|
-
<div className="SummaryFlowStep__divider">
|
|
86
|
-
<FlowSegment/>
|
|
87
|
-
<div className="SummaryFlowStep__divider--line"/>
|
|
88
|
-
</div>
|
|
89
|
-
}
|
|
90
|
-
<img
|
|
91
|
-
className="SummaryFlowStep__screenshot"
|
|
92
|
-
data-testid="SummaryFlowStep__screenshot"
|
|
93
|
-
src={screenshot || undefined}
|
|
94
|
-
style={{width: THUMBNAIL_WIDTH, maxHeight: thumbnailHeight}}
|
|
95
|
-
/>
|
|
96
|
-
<FlowSegment mode={lhr.gatherMode}/>
|
|
97
|
-
<a className="SummaryFlowStep__label" href={`#index=${hashIndex}`}>{label}</a>
|
|
98
|
-
{
|
|
99
|
-
DISPLAYED_CATEGORIES.map(c => (
|
|
100
|
-
<SummaryCategory
|
|
101
|
-
key={c}
|
|
102
|
-
gatherMode={reportResult.gatherMode}
|
|
103
|
-
category={reportResult.categories[c]}
|
|
104
|
-
audits={reportResult.audits}
|
|
105
|
-
href={`#index=${hashIndex}&anchor=${c}`}
|
|
106
|
-
/>
|
|
107
|
-
))
|
|
108
|
-
}
|
|
109
|
-
</div>
|
|
110
|
-
);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* For the summary flow, there are many different cells with different contents and different display properties.
|
|
115
|
-
* CSS grid makes it easier to enforce things like content alignment and column width (e.g. all category columns have the same width).
|
|
116
|
-
*/
|
|
117
|
-
const SummaryFlow: FunctionComponent = () => {
|
|
118
|
-
const flowResult = useFlowResult();
|
|
119
|
-
const stepNames = useDerivedStepNames();
|
|
120
|
-
return (
|
|
121
|
-
<div className="SummaryFlow">
|
|
122
|
-
{
|
|
123
|
-
flowResult.lhrs.map((lhr, index) =>
|
|
124
|
-
<SummaryFlowStep
|
|
125
|
-
key={lhr.fetchTime}
|
|
126
|
-
lhr={lhr}
|
|
127
|
-
label={stepNames[index]}
|
|
128
|
-
hashIndex={index}
|
|
129
|
-
/>
|
|
130
|
-
)
|
|
131
|
-
}
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export const SummaryHeader: FunctionComponent = () => {
|
|
137
|
-
const flowResult = useFlowResult();
|
|
138
|
-
|
|
139
|
-
let numNavigation = 0;
|
|
140
|
-
let numTimespan = 0;
|
|
141
|
-
let numSnapshot = 0;
|
|
142
|
-
for (const lhr of flowResult.lhrs) {
|
|
143
|
-
switch (lhr.gatherMode) {
|
|
144
|
-
case 'navigation':
|
|
145
|
-
numNavigation++;
|
|
146
|
-
break;
|
|
147
|
-
case 'timespan':
|
|
148
|
-
numTimespan++;
|
|
149
|
-
break;
|
|
150
|
-
case 'snapshot':
|
|
151
|
-
numSnapshot++;
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// TODO(FR-COMPAT): Pluralize UI strings.
|
|
157
|
-
const subtitleCounts = [];
|
|
158
|
-
if (numNavigation) subtitleCounts.push(`${numNavigation} navigation reports`);
|
|
159
|
-
if (numTimespan) subtitleCounts.push(`${numTimespan} timespan reports`);
|
|
160
|
-
if (numSnapshot) subtitleCounts.push(`${numSnapshot} snapshot reports`);
|
|
161
|
-
const subtitle = subtitleCounts.join(' · ');
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<div className="SummaryHeader">
|
|
165
|
-
<div className="SummaryHeader__title">Summary</div>
|
|
166
|
-
<div className="SummaryHeader__subtitle">{subtitle}</div>
|
|
167
|
-
</div>
|
|
168
|
-
);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
export const Summary: FunctionComponent = () => {
|
|
172
|
-
return (
|
|
173
|
-
<div className="Summary" data-testid="Summary">
|
|
174
|
-
<SummaryHeader/>
|
|
175
|
-
<SummaryFlow/>
|
|
176
|
-
</div>
|
|
177
|
-
);
|
|
178
|
-
};
|
package/flow-report/src/util.ts
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
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
|
-
import {createContext} from 'preact';
|
|
8
|
-
import {useContext, useEffect, useMemo, useState} from 'preact/hooks';
|
|
9
|
-
|
|
10
|
-
export const FlowResultContext = createContext<LH.FlowResult|undefined>(undefined);
|
|
11
|
-
|
|
12
|
-
function getHashParam(param: string): string|null {
|
|
13
|
-
const params = new URLSearchParams(location.hash.replace('#', '?'));
|
|
14
|
-
return params.get(param);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function shortenUrl(longUrl: string) {
|
|
18
|
-
const url = new URL(longUrl);
|
|
19
|
-
return `${url.hostname}${url.pathname}`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The step label should be enumerated if there is another report of the same gather mode in the same section.
|
|
24
|
-
* Navigation reports will never be enumerated.
|
|
25
|
-
*/
|
|
26
|
-
function shouldEnumerate(flowResult: LH.FlowResult, index: number) {
|
|
27
|
-
const {lhrs} = flowResult;
|
|
28
|
-
if (lhrs[index].gatherMode === 'navigation') return false;
|
|
29
|
-
|
|
30
|
-
for (let i = index + 1; lhrs[i] && lhrs[i].gatherMode !== 'navigation'; ++i) {
|
|
31
|
-
if (lhrs[i].gatherMode === lhrs[index].gatherMode) {
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
for (let i = index - 1; lhrs[i] && lhrs[i].gatherMode !== 'navigation'; --i) {
|
|
36
|
-
if (lhrs[i].gatherMode === lhrs[index].gatherMode) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
export function classNames(...args: Array<string|undefined|Record<string, boolean>>): string {
|
|
45
|
-
const classes = [];
|
|
46
|
-
for (const arg of args) {
|
|
47
|
-
if (!arg) continue;
|
|
48
|
-
|
|
49
|
-
if (typeof arg === 'string') {
|
|
50
|
-
classes.push(arg);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const applicableClasses = Object.entries(arg)
|
|
55
|
-
.filter(([_, shouldApply]) => shouldApply)
|
|
56
|
-
.map(([className]) => className);
|
|
57
|
-
classes.push(...applicableClasses);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return classes.join(' ');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function getScreenDimensions(reportResult: LH.ReportResult) {
|
|
64
|
-
const {width, height} = reportResult.configSettings.screenEmulation;
|
|
65
|
-
return {width, height};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function getScreenshot(reportResult: LH.ReportResult) {
|
|
69
|
-
const fullPageScreenshotAudit = reportResult.audits['full-page-screenshot'];
|
|
70
|
-
const fullPageScreenshot =
|
|
71
|
-
fullPageScreenshotAudit.details &&
|
|
72
|
-
fullPageScreenshotAudit.details.type === 'full-page-screenshot' &&
|
|
73
|
-
fullPageScreenshotAudit.details.screenshot.data;
|
|
74
|
-
|
|
75
|
-
return fullPageScreenshot || null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function useFlowResult(): LH.FlowResult {
|
|
79
|
-
const flowResult = useContext(FlowResultContext);
|
|
80
|
-
if (!flowResult) throw Error('useFlowResult must be called in the FlowResultContext');
|
|
81
|
-
return flowResult;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function useLocale(): LH.Locale {
|
|
85
|
-
const flowResult = useFlowResult();
|
|
86
|
-
return flowResult.lhrs[0].configSettings.locale;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function useHashParam(param: string) {
|
|
90
|
-
const [paramValue, setParamValue] = useState(getHashParam(param));
|
|
91
|
-
|
|
92
|
-
// Use two-way-binding on the URL hash.
|
|
93
|
-
// Triggers a re-render if the param changes.
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
function hashListener() {
|
|
96
|
-
const newIndexString = getHashParam(param);
|
|
97
|
-
if (newIndexString === paramValue) return;
|
|
98
|
-
setParamValue(newIndexString);
|
|
99
|
-
}
|
|
100
|
-
window.addEventListener('hashchange', hashListener);
|
|
101
|
-
return () => window.removeEventListener('hashchange', hashListener);
|
|
102
|
-
}, [paramValue]);
|
|
103
|
-
|
|
104
|
-
return paramValue;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function useCurrentLhr(): {value: LH.Result, index: number}|null {
|
|
108
|
-
const flowResult = useFlowResult();
|
|
109
|
-
const indexString = useHashParam('index');
|
|
110
|
-
|
|
111
|
-
// Memoize result so a new object is not created on every call.
|
|
112
|
-
return useMemo(() => {
|
|
113
|
-
if (!indexString) return null;
|
|
114
|
-
|
|
115
|
-
const index = Number(indexString);
|
|
116
|
-
if (!Number.isFinite(index)) {
|
|
117
|
-
console.warn(`Invalid hash index: ${indexString}`);
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const value = flowResult.lhrs[index];
|
|
122
|
-
if (!value) {
|
|
123
|
-
console.warn(`No LHR at index ${index}`);
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {value, index};
|
|
128
|
-
}, [indexString, flowResult]);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function useDerivedStepNames() {
|
|
132
|
-
const flowResult = useFlowResult();
|
|
133
|
-
|
|
134
|
-
return useMemo(() => {
|
|
135
|
-
let numTimespan = 1;
|
|
136
|
-
let numSnapshot = 1;
|
|
137
|
-
|
|
138
|
-
// TODO(FR-COMPAT): Override with a provided step name.
|
|
139
|
-
return flowResult.lhrs.map((lhr, index) => {
|
|
140
|
-
const shortUrl = shortenUrl(lhr.finalUrl);
|
|
141
|
-
|
|
142
|
-
switch (lhr.gatherMode) {
|
|
143
|
-
case 'navigation':
|
|
144
|
-
numTimespan = 1;
|
|
145
|
-
numSnapshot = 1;
|
|
146
|
-
return `Navigation report (${shortUrl})`;
|
|
147
|
-
case 'timespan':
|
|
148
|
-
if (shouldEnumerate(flowResult, index)) {
|
|
149
|
-
return `Timespan report ${numTimespan++} (${shortUrl})`;
|
|
150
|
-
}
|
|
151
|
-
return `Timespan report (${shortUrl})`;
|
|
152
|
-
case 'snapshot':
|
|
153
|
-
if (shouldEnumerate(flowResult, index)) {
|
|
154
|
-
return `Snapshot report ${numSnapshot++} (${shortUrl})`;
|
|
155
|
-
}
|
|
156
|
-
return `Snapshot report (${shortUrl})`;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
}, [flowResult]);
|
|
160
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|
-
import {FunctionComponent} from 'preact';
|
|
8
|
-
import {useEffect, useLayoutEffect, useRef} from 'preact/hooks';
|
|
9
|
-
|
|
10
|
-
import {useReportRenderer} from './report-renderer';
|
|
11
|
-
|
|
12
|
-
export const Gauge: FunctionComponent<{category: LH.ReportResult.Category, href: string}> =
|
|
13
|
-
({category, href}) => {
|
|
14
|
-
const {categoryRenderer} = useReportRenderer();
|
|
15
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
16
|
-
|
|
17
|
-
useLayoutEffect(() => {
|
|
18
|
-
const el = categoryRenderer.renderScoreGauge(category, {});
|
|
19
|
-
|
|
20
|
-
// Category label is displayed in the navigation header.
|
|
21
|
-
const label = el.querySelector('.lh-gauge__label');
|
|
22
|
-
if (label) label.remove();
|
|
23
|
-
|
|
24
|
-
if (ref.current) ref.current.append(el);
|
|
25
|
-
return () => {
|
|
26
|
-
if (ref.current && ref.current.contains(el)) {
|
|
27
|
-
ref.current.removeChild(el);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}, [categoryRenderer, category]);
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
const anchor = ref.current && ref.current.querySelector('a') as HTMLAnchorElement;
|
|
34
|
-
if (anchor) anchor.href = href;
|
|
35
|
-
}, [href]);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div ref={ref} data-testid="Gauge"/>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
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
|
-
import {createContext, FunctionComponent} from 'preact';
|
|
8
|
-
import {useContext, useMemo} from 'preact/hooks';
|
|
9
|
-
|
|
10
|
-
import {CategoryRenderer} from '../../../report/renderer/category-renderer';
|
|
11
|
-
import {DetailsRenderer} from '../../../report/renderer/details-renderer';
|
|
12
|
-
import {DOM} from '../../../report/renderer/dom';
|
|
13
|
-
import {ReportRenderer} from '../../../report/renderer/report-renderer';
|
|
14
|
-
|
|
15
|
-
interface ReportRendererGlobals {
|
|
16
|
-
dom: DOM,
|
|
17
|
-
detailsRenderer: DetailsRenderer,
|
|
18
|
-
categoryRenderer: CategoryRenderer,
|
|
19
|
-
reportRenderer: ReportRenderer,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const ReportRendererContext = createContext<ReportRendererGlobals|undefined>(undefined);
|
|
23
|
-
|
|
24
|
-
export function useReportRenderer() {
|
|
25
|
-
const globals = useContext(ReportRendererContext);
|
|
26
|
-
if (!globals) throw Error('Globals not defined');
|
|
27
|
-
return globals;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const ReportRendererProvider: FunctionComponent = ({children}) => {
|
|
31
|
-
const globals = useMemo(() => {
|
|
32
|
-
const dom = new DOM(document);
|
|
33
|
-
const detailsRenderer = new DetailsRenderer(dom);
|
|
34
|
-
const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
|
|
35
|
-
const reportRenderer = new ReportRenderer(dom);
|
|
36
|
-
return {
|
|
37
|
-
dom,
|
|
38
|
-
detailsRenderer,
|
|
39
|
-
categoryRenderer,
|
|
40
|
-
reportRenderer,
|
|
41
|
-
};
|
|
42
|
-
}, []);
|
|
43
|
-
return (
|
|
44
|
-
<ReportRendererContext.Provider value={globals}>{children}</ReportRendererContext.Provider>
|
|
45
|
-
);
|
|
46
|
-
};
|