lighthouse 9.5.0-dev.20230123 → 9.5.0-dev.20230125
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/.codecov.yml +0 -5
- package/core/audits/accessibility/accesskeys.js +1 -1
- package/core/audits/accessibility/aria-allowed-attr.js +1 -1
- package/core/audits/accessibility/aria-command-name.js +1 -1
- package/core/audits/accessibility/aria-hidden-body.js +1 -1
- package/core/audits/accessibility/aria-hidden-focus.js +1 -1
- package/core/audits/accessibility/aria-input-field-name.js +1 -1
- package/core/audits/accessibility/aria-meter-name.js +1 -1
- package/core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/core/audits/accessibility/aria-required-attr.js +1 -1
- package/core/audits/accessibility/aria-required-children.js +1 -1
- package/core/audits/accessibility/aria-required-parent.js +1 -1
- package/core/audits/accessibility/aria-roles.js +1 -1
- package/core/audits/accessibility/aria-toggle-field-name.js +1 -1
- package/core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/core/audits/accessibility/aria-valid-attr-value.js +1 -1
- package/core/audits/accessibility/aria-valid-attr.js +1 -1
- package/core/audits/accessibility/button-name.js +1 -1
- package/core/audits/accessibility/bypass.js +1 -1
- package/core/audits/accessibility/color-contrast.js +1 -1
- package/core/audits/accessibility/definition-list.js +1 -1
- package/core/audits/accessibility/dlitem.js +1 -1
- package/core/audits/accessibility/document-title.js +1 -1
- package/core/audits/accessibility/duplicate-id-active.js +1 -1
- package/core/audits/accessibility/duplicate-id-aria.js +1 -1
- package/core/audits/accessibility/form-field-multiple-labels.js +1 -1
- package/core/audits/accessibility/frame-title.js +1 -1
- package/core/audits/accessibility/heading-order.js +1 -1
- package/core/audits/accessibility/html-has-lang.js +1 -1
- package/core/audits/accessibility/html-lang-valid.js +1 -1
- package/core/audits/accessibility/image-alt.js +1 -1
- package/core/audits/accessibility/input-image-alt.js +1 -1
- package/core/audits/accessibility/label.js +1 -1
- package/core/audits/accessibility/link-name.js +1 -1
- package/core/audits/accessibility/list.js +1 -1
- package/core/audits/accessibility/listitem.js +1 -1
- package/core/audits/accessibility/meta-refresh.js +1 -1
- package/core/audits/accessibility/meta-viewport.js +1 -1
- package/core/audits/accessibility/object-alt.js +1 -1
- package/core/audits/accessibility/tabindex.js +1 -1
- package/core/audits/accessibility/td-headers-attr.js +1 -1
- package/core/audits/accessibility/th-has-data-cells.js +1 -1
- package/core/audits/accessibility/valid-lang.js +1 -1
- package/core/audits/accessibility/video-caption.js +1 -1
- package/core/audits/audit.js +1 -1
- package/core/audits/byte-efficiency/legacy-javascript.d.ts +1 -0
- package/core/audits/byte-efficiency/legacy-javascript.js +7 -3
- package/core/audits/dobetterweb/uses-http2.d.ts +5 -2
- package/core/audits/dobetterweb/uses-http2.js +12 -7
- package/core/audits/network-requests.js +7 -6
- package/core/audits/third-party-facades.d.ts +3 -2
- package/core/audits/third-party-facades.js +12 -9
- package/core/audits/third-party-summary.d.ts +7 -6
- package/core/audits/third-party-summary.js +16 -14
- package/core/audits/valid-source-maps.d.ts +5 -3
- package/core/audits/valid-source-maps.js +11 -9
- package/core/computed/entity-classification.d.ts +29 -0
- package/core/computed/entity-classification.js +102 -0
- package/core/computed/metrics/responsiveness.js +5 -2
- package/core/computed/page-dependency-graph.js +1 -1
- package/core/computed/resource-summary.d.ts +4 -2
- package/core/computed/resource-summary.js +8 -5
- package/core/gather/gatherers/accessibility.js +3 -1
- package/core/lib/network-request.d.ts +2 -0
- package/core/lib/network-request.js +3 -0
- package/core/lib/stack-packs.js +4 -0
- package/core/lib/tracehouse/trace-processor.d.ts +14 -5
- package/core/lib/tracehouse/trace-processor.js +85 -30
- package/core/lib/traces/metric-trace-events.js +1 -1
- package/core/lib/url-utils.js +1 -1
- package/core/runner.d.ts +10 -0
- package/core/runner.js +48 -0
- package/dist/report/bundle.esm.js +724 -687
- package/dist/report/flow.js +25 -15
- package/dist/report/standalone.js +25 -15
- package/flow-report/src/common.tsx +1 -1
- package/flow-report/src/i18n/i18n.tsx +17 -16
- package/flow-report/src/sidebar/sidebar.tsx +2 -2
- package/flow-report/src/summary/category.tsx +6 -6
- package/flow-report/src/summary/summary.tsx +2 -2
- package/package.json +7 -8
- package/report/renderer/category-renderer.js +19 -17
- package/report/renderer/crc-details-renderer.js +6 -6
- package/report/renderer/details-renderer.js +7 -6
- package/report/renderer/dom.js +1 -1
- package/report/renderer/element-screenshot-renderer.js +3 -3
- package/report/renderer/performance-category-renderer.js +17 -15
- package/report/renderer/pwa-category-renderer.js +5 -4
- package/report/renderer/report-globals.d.ts +21 -0
- package/report/renderer/report-globals.js +49 -0
- package/report/renderer/report-renderer.js +22 -20
- package/report/renderer/report-ui-features.js +9 -8
- package/report/renderer/report-utils.d.ts +116 -0
- package/report/renderer/{util.js → report-utils.js} +81 -429
- package/report/renderer/snippet-renderer.js +3 -2
- package/report/test/renderer/category-renderer-test.js +9 -4
- package/report/test/renderer/crc-details-renderer-test.js +7 -3
- package/report/test/renderer/details-renderer-test.js +7 -3
- package/report/test/renderer/dom-test.js +7 -3
- package/report/test/renderer/element-screenshot-renderer-test.js +8 -4
- package/report/test/renderer/performance-category-renderer-test.js +14 -9
- package/report/test/renderer/pwa-category-renderer-test.js +10 -5
- package/report/test/renderer/report-renderer-test.js +2 -2
- package/report/test/renderer/report-ui-features-test.js +3 -3
- package/report/test/renderer/{util-test.js → report-utils-test.js} +36 -234
- package/report/test/renderer/snippet-renderer-test.js +7 -3
- package/shared/localization/format.js +5 -2
- package/shared/localization/locales/ar-XB.json +50 -50
- package/shared/localization/locales/ar.json +50 -50
- package/shared/localization/locales/bg.json +50 -50
- package/shared/localization/locales/ca.json +50 -50
- package/shared/localization/locales/cs.json +50 -50
- package/shared/localization/locales/da.json +50 -50
- package/shared/localization/locales/de.json +50 -50
- package/shared/localization/locales/el.json +50 -50
- package/shared/localization/locales/en-GB.json +50 -50
- package/shared/localization/locales/en-US.json +128 -98
- package/shared/localization/locales/en-XA.json +50 -50
- package/shared/localization/locales/en-XL.json +128 -98
- package/shared/localization/locales/es-419.json +50 -50
- package/shared/localization/locales/es.json +50 -50
- package/shared/localization/locales/fi.json +50 -50
- package/shared/localization/locales/fil.json +50 -50
- package/shared/localization/locales/fr.json +50 -50
- package/shared/localization/locales/he.json +50 -50
- package/shared/localization/locales/hi.json +50 -50
- package/shared/localization/locales/hr.json +50 -50
- package/shared/localization/locales/hu.json +50 -50
- package/shared/localization/locales/id.json +50 -50
- package/shared/localization/locales/it.json +50 -50
- package/shared/localization/locales/ja.json +50 -50
- package/shared/localization/locales/ko.json +50 -50
- package/shared/localization/locales/lt.json +50 -50
- package/shared/localization/locales/lv.json +50 -50
- package/shared/localization/locales/nl.json +50 -50
- package/shared/localization/locales/no.json +50 -50
- package/shared/localization/locales/pl.json +50 -50
- package/shared/localization/locales/pt-PT.json +50 -50
- package/shared/localization/locales/pt.json +50 -50
- package/shared/localization/locales/ro.json +50 -50
- package/shared/localization/locales/ru.json +50 -50
- package/shared/localization/locales/sk.json +50 -50
- package/shared/localization/locales/sl.json +50 -50
- package/shared/localization/locales/sr-Latn.json +50 -50
- package/shared/localization/locales/sr.json +50 -50
- package/shared/localization/locales/sv.json +50 -50
- package/shared/localization/locales/ta.json +50 -50
- package/shared/localization/locales/te.json +50 -50
- package/shared/localization/locales/th.json +50 -50
- package/shared/localization/locales/tr.json +50 -50
- package/shared/localization/locales/uk.json +50 -50
- package/shared/localization/locales/vi.json +50 -50
- package/shared/localization/locales/zh-HK.json +50 -50
- package/shared/localization/locales/zh-TW.json +50 -50
- package/shared/localization/locales/zh.json +50 -50
- package/shared/test/util-test.js +214 -0
- package/shared/util.d.ts +122 -0
- package/shared/util.js +332 -0
- package/tsconfig.json +0 -2
- package/types/artifacts.d.ts +21 -2
- package/types/lhr/lhr.d.ts +33 -0
- package/core/lib/minify-trace.d.ts +0 -6
- package/core/lib/minify-trace.js +0 -172
- package/core/util.cjs +0 -845
- package/core/util.d.cts +0 -342
- package/report/renderer/util.d.ts +0 -342
|
@@ -9,7 +9,7 @@ import {useEffect, useState} from 'preact/hooks';
|
|
|
9
9
|
|
|
10
10
|
import {NavigationIcon, SnapshotIcon, TimespanIcon} from './icons';
|
|
11
11
|
import {getFilmstripFrames, getScreenDimensions} from './util';
|
|
12
|
-
import {Util} from '../../
|
|
12
|
+
import {Util} from '../../shared/util.js';
|
|
13
13
|
|
|
14
14
|
const ANIMATION_FRAME_DURATION_MS = 500;
|
|
15
15
|
|
|
@@ -12,11 +12,12 @@ import {I18nFormatter} from '../../../report/renderer/i18n-formatter';
|
|
|
12
12
|
import {UIStrings} from './ui-strings';
|
|
13
13
|
import {useFlowResult} from '../util';
|
|
14
14
|
import strings from './localized-strings.js';
|
|
15
|
-
import {
|
|
15
|
+
import {UIStrings as ReportUIStrings} from '../../../report/renderer/report-utils.js';
|
|
16
|
+
import {Globals} from '../../../report/renderer/report-globals.js';
|
|
16
17
|
|
|
17
18
|
const I18nContext = createContext({
|
|
18
19
|
formatter: new I18nFormatter('en-US'),
|
|
19
|
-
strings: {...
|
|
20
|
+
strings: {...ReportUIStrings, ...UIStrings},
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
function useLhrLocale() {
|
|
@@ -54,23 +55,23 @@ const I18nProvider: FunctionComponent = ({children}) => {
|
|
|
54
55
|
const {locale, lhrStrings} = useLhrLocale();
|
|
55
56
|
|
|
56
57
|
const i18n = useMemo(() => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
Globals.apply({
|
|
59
|
+
providedStrings: {
|
|
60
|
+
// Preload with strings from the first lhr.
|
|
61
|
+
// Used for legacy report components imported into the flow report.
|
|
62
|
+
...lhrStrings,
|
|
63
|
+
// Set any missing flow strings to default (english) values.
|
|
64
|
+
...UIStrings,
|
|
65
|
+
// `strings` is generated in build/build-report.js
|
|
66
|
+
...strings[locale],
|
|
67
|
+
},
|
|
68
|
+
i18n: new I18nFormatter(locale),
|
|
69
|
+
reportJson: null,
|
|
65
70
|
});
|
|
66
71
|
|
|
67
|
-
// Initialize renderer util i18n for strings rendered in wrapped components.
|
|
68
|
-
// TODO: Don't attach global formatter to `Util`.
|
|
69
|
-
Util.i18n = new I18nFormatter(locale);
|
|
70
|
-
|
|
71
72
|
return {
|
|
72
|
-
formatter:
|
|
73
|
-
strings:
|
|
73
|
+
formatter: Globals.i18n,
|
|
74
|
+
strings: Globals.strings as typeof UIStrings & typeof ReportUIStrings,
|
|
74
75
|
};
|
|
75
76
|
}, [locale, lhrStrings]);
|
|
76
77
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {ReportUtils} from '../../../report/renderer/report-utils.js';
|
|
10
10
|
import {Separator} from '../common';
|
|
11
11
|
import {useI18n, useLocalizedStrings} from '../i18n/i18n';
|
|
12
12
|
import {CpuIcon, EnvIcon, NetworkIcon, SummaryIcon} from '../icons';
|
|
@@ -34,7 +34,7 @@ const SidebarSummary: FunctionComponent = () => {
|
|
|
34
34
|
const SidebarRuntimeSettings: FunctionComponent<{settings: LH.ConfigSettings}> =
|
|
35
35
|
({settings}) => {
|
|
36
36
|
const strings = useLocalizedStrings();
|
|
37
|
-
const env =
|
|
37
|
+
const env = ReportUtils.getEmulationDescriptions(settings);
|
|
38
38
|
const deviceEmulationString = env.screenEmulation ?
|
|
39
39
|
`${env.deviceEmulation} - ${env.screenEmulation}` :
|
|
40
40
|
env.deviceEmulation;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {FunctionComponent} from 'preact';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {ReportUtils} from '../../../report/renderer/report-utils.js';
|
|
10
10
|
import {Separator} from '../common';
|
|
11
11
|
import {CategoryScore} from '../wrappers/category-score';
|
|
12
12
|
import {useI18n, useStringFormatter, useLocalizedStrings} from '../i18n/i18n';
|
|
@@ -48,7 +48,7 @@ function getOverallSavings(audit: LH.ReportResult.AuditRef): number {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
const SummaryTooltipAudit: FunctionComponent<{audit: LH.ReportResult.AuditRef}> = ({audit}) => {
|
|
51
|
-
const rating =
|
|
51
|
+
const rating = ReportUtils.calculateRating(audit.result.score, audit.result.scoreDisplayMode);
|
|
52
52
|
return (
|
|
53
53
|
<div className={`SummaryTooltipAudit SummaryTooltipAudit--${rating}`}>
|
|
54
54
|
<Markdown text={audit.result.title}/>
|
|
@@ -69,7 +69,7 @@ const SummaryTooltipAudits: FunctionComponent<{category: LH.ReportResult.Categor
|
|
|
69
69
|
// We don't want unweighted audits except for opportunities with potential savings.
|
|
70
70
|
(audit.weight > 0 || getOverallSavings(audit) > 0) &&
|
|
71
71
|
// Passing audits should never be high impact.
|
|
72
|
-
!
|
|
72
|
+
!ReportUtils.showAsPassed(audit.result);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
const audits = category.auditRefs
|
|
@@ -107,14 +107,14 @@ const SummaryTooltip: FunctionComponent<{
|
|
|
107
107
|
numPassableAudits,
|
|
108
108
|
numInformative,
|
|
109
109
|
totalWeight,
|
|
110
|
-
} =
|
|
110
|
+
} = ReportUtils.calculateCategoryFraction(category);
|
|
111
111
|
|
|
112
112
|
const i18n = useI18n();
|
|
113
|
-
const displayAsFraction =
|
|
113
|
+
const displayAsFraction = ReportUtils.shouldDisplayAsFraction(gatherMode);
|
|
114
114
|
const score = displayAsFraction ?
|
|
115
115
|
numPassed / numPassableAudits :
|
|
116
116
|
category.score;
|
|
117
|
-
const rating = score === null ? 'error' :
|
|
117
|
+
const rating = score === null ? 'error' : ReportUtils.calculateRating(score);
|
|
118
118
|
|
|
119
119
|
return (
|
|
120
120
|
<div className="SummaryTooltip">
|
|
@@ -9,7 +9,7 @@ import {useMemo} from 'preact/hooks';
|
|
|
9
9
|
|
|
10
10
|
import {FlowSegment, FlowStepThumbnail, Separator} from '../common';
|
|
11
11
|
import {getModeDescription, useFlowResult} from '../util';
|
|
12
|
-
import {
|
|
12
|
+
import {ReportUtils} from '../../../report/renderer/report-utils.js';
|
|
13
13
|
import {SummaryCategory} from './category';
|
|
14
14
|
import {useStringFormatter, useLocalizedStrings} from '../i18n/i18n';
|
|
15
15
|
|
|
@@ -49,7 +49,7 @@ const SummaryFlowStep: FunctionComponent<{
|
|
|
49
49
|
label: string,
|
|
50
50
|
hashIndex: number,
|
|
51
51
|
}> = ({lhr, label, hashIndex}) => {
|
|
52
|
-
const reportResult = useMemo(() =>
|
|
52
|
+
const reportResult = useMemo(() => ReportUtils.prepareReportResult(lhr), [lhr]);
|
|
53
53
|
const strings = useLocalizedStrings();
|
|
54
54
|
const modeDescription = getModeDescription(lhr.gatherMode, strings);
|
|
55
55
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "9.5.0-dev.
|
|
4
|
+
"version": "9.5.0-dev.20230125",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"build-smokehouse-bundle": "node ./build/build-smokehouse-bundle.js",
|
|
27
27
|
"build-lr": "yarn reset-link && node ./build/build-lightrider-bundles.js",
|
|
28
28
|
"build-pack": "bash build/build-pack.sh",
|
|
29
|
-
"build-report": "node build/build-report-components.js &&
|
|
29
|
+
"build-report": "node build/build-report-components.js && node build/build-report.js",
|
|
30
30
|
"build-sample-reports": "yarn build-report && node build/build-sample-reports.js",
|
|
31
31
|
"build-treemap": "node ./build/build-treemap.js",
|
|
32
32
|
"build-viewer": "node ./build/build-viewer.js",
|
|
@@ -86,7 +86,6 @@
|
|
|
86
86
|
"diff:sample-json": "yarn i18n:checks && bash core/scripts/assert-golden-lhr-unchanged.sh",
|
|
87
87
|
"diff:flow-sample-json": "yarn i18n:collect-strings && bash core/scripts/assert-baseline-flow-result-unchanged.sh",
|
|
88
88
|
"computeBenchmarkIndex": "./core/scripts/benchmark.js",
|
|
89
|
-
"minify-latest-run": "./core/scripts/lantern/minify-trace.js ./latest-run/defaultPass.trace.json ./latest-run/defaultPass.trace.min.json && ./core/scripts/lantern/minify-devtoolslog.js ./latest-run/defaultPass.devtoolslog.json ./latest-run/defaultPass.devtoolslog.min.json",
|
|
90
89
|
"save-latest-run": "./core/scripts/save-latest-run.sh",
|
|
91
90
|
"compile-proto": "protoc --python_out=./ ./proto/lighthouse-result.proto && mv ./proto/*_pb2.py ./proto/scripts || (echo \"❌ Install protobuf = 3.20.x to compile the proto file.\" && false)",
|
|
92
91
|
"build-proto-roundtrip": "mkdir -p .tmp && python3 proto/scripts/json_roundtrip_via_proto.py",
|
|
@@ -169,7 +168,7 @@
|
|
|
169
168
|
"pako": "^2.0.3",
|
|
170
169
|
"preact": "^10.7.2",
|
|
171
170
|
"pretty-json-stringify": "^0.0.2",
|
|
172
|
-
"puppeteer": "^
|
|
171
|
+
"puppeteer": "^19.6.0",
|
|
173
172
|
"resolve": "^1.20.0",
|
|
174
173
|
"rollup": "^2.52.7",
|
|
175
174
|
"rollup-plugin-node-resolve": "^5.2.0",
|
|
@@ -187,7 +186,7 @@
|
|
|
187
186
|
},
|
|
188
187
|
"dependencies": {
|
|
189
188
|
"@sentry/node": "^6.17.4",
|
|
190
|
-
"axe-core": "4.
|
|
189
|
+
"axe-core": "4.6.3",
|
|
191
190
|
"chrome-launcher": "^0.15.1",
|
|
192
191
|
"configstore": "^5.0.1",
|
|
193
192
|
"csp_evaluator": "1.1.1",
|
|
@@ -195,16 +194,16 @@
|
|
|
195
194
|
"http-link-header": "^0.8.0",
|
|
196
195
|
"intl-messageformat": "^4.4.0",
|
|
197
196
|
"jpeg-js": "^0.4.4",
|
|
198
|
-
"js-library-detector": "^6.
|
|
197
|
+
"js-library-detector": "^6.6.0",
|
|
199
198
|
"lighthouse-logger": "^1.3.0",
|
|
200
|
-
"lighthouse-stack-packs": "1.
|
|
199
|
+
"lighthouse-stack-packs": "1.9.0",
|
|
201
200
|
"lodash": "^4.17.21",
|
|
202
201
|
"lookup-closest-locale": "6.2.0",
|
|
203
202
|
"metaviewport-parser": "0.3.0",
|
|
204
203
|
"open": "^8.4.0",
|
|
205
204
|
"parse-cache-control": "1.0.1",
|
|
206
205
|
"ps-list": "^8.0.0",
|
|
207
|
-
"puppeteer-core": "^
|
|
206
|
+
"puppeteer-core": "^19.6.0",
|
|
208
207
|
"quibble": "connorjclark/quibble#fork",
|
|
209
208
|
"robots-parser": "^3.0.0",
|
|
210
209
|
"semver": "^5.3.0",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
/** @typedef {import('./details-renderer.js').DetailsRenderer} DetailsRenderer */
|
|
21
21
|
/** @typedef {'failed'|'warning'|'manual'|'passed'|'notApplicable'} TopLevelClumpId */
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import {ReportUtils} from './report-utils.js';
|
|
24
|
+
import {Globals} from './report-globals.js';
|
|
24
25
|
|
|
25
26
|
export class CategoryRenderer {
|
|
26
27
|
/**
|
|
@@ -39,10 +40,10 @@ export class CategoryRenderer {
|
|
|
39
40
|
*/
|
|
40
41
|
get _clumpTitles() {
|
|
41
42
|
return {
|
|
42
|
-
warning:
|
|
43
|
-
manual:
|
|
44
|
-
passed:
|
|
45
|
-
notApplicable:
|
|
43
|
+
warning: Globals.strings.warningAuditsGroupTitle,
|
|
44
|
+
manual: Globals.strings.manualAuditsGroupTitle,
|
|
45
|
+
passed: Globals.strings.passedAuditsGroupTitle,
|
|
46
|
+
notApplicable: Globals.strings.notApplicableAuditsGroupTitle,
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -62,7 +63,7 @@ export class CategoryRenderer {
|
|
|
62
63
|
* @return {!Element}
|
|
63
64
|
*/
|
|
64
65
|
populateAuditValues(audit, component) {
|
|
65
|
-
const strings =
|
|
66
|
+
const strings = Globals.strings;
|
|
66
67
|
const auditEl = this.dom.find('.lh-audit', component);
|
|
67
68
|
auditEl.id = audit.result.id;
|
|
68
69
|
const scoreDisplayMode = audit.result.scoreDisplayMode;
|
|
@@ -185,7 +186,7 @@ export class CategoryRenderer {
|
|
|
185
186
|
* @return {!Element}
|
|
186
187
|
*/
|
|
187
188
|
_setRatingClass(element, score, scoreDisplayMode) {
|
|
188
|
-
const rating =
|
|
189
|
+
const rating = ReportUtils.calculateRating(score, scoreDisplayMode);
|
|
189
190
|
element.classList.add(`lh-audit--${scoreDisplayMode.toLowerCase()}`);
|
|
190
191
|
if (scoreDisplayMode !== 'informative') {
|
|
191
192
|
element.classList.add(`lh-audit--${rating}`);
|
|
@@ -334,8 +335,8 @@ export class CategoryRenderer {
|
|
|
334
335
|
el.append(descriptionEl);
|
|
335
336
|
}
|
|
336
337
|
|
|
337
|
-
this.dom.find('.lh-clump-toggletext--show', el).textContent =
|
|
338
|
-
this.dom.find('.lh-clump-toggletext--hide', el).textContent =
|
|
338
|
+
this.dom.find('.lh-clump-toggletext--show', el).textContent = Globals.strings.show;
|
|
339
|
+
this.dom.find('.lh-clump-toggletext--hide', el).textContent = Globals.strings.hide;
|
|
339
340
|
|
|
340
341
|
clumpElement.classList.add(`lh-clump--${clumpId.toLowerCase()}`);
|
|
341
342
|
return el;
|
|
@@ -349,7 +350,7 @@ export class CategoryRenderer {
|
|
|
349
350
|
*/
|
|
350
351
|
renderCategoryScore(category, groupDefinitions, options) {
|
|
351
352
|
let categoryScore;
|
|
352
|
-
if (options &&
|
|
353
|
+
if (options && ReportUtils.shouldDisplayAsFraction(options.gatherMode)) {
|
|
353
354
|
categoryScore = this.renderCategoryFraction(category);
|
|
354
355
|
} else {
|
|
355
356
|
categoryScore = this.renderScoreGauge(category, groupDefinitions);
|
|
@@ -377,7 +378,7 @@ export class CategoryRenderer {
|
|
|
377
378
|
const tmpl = this.dom.createComponent('gauge');
|
|
378
379
|
const wrapper = this.dom.find('a.lh-gauge__wrapper', tmpl);
|
|
379
380
|
|
|
380
|
-
if (
|
|
381
|
+
if (ReportUtils.isPluginCategory(category.id)) {
|
|
381
382
|
wrapper.classList.add('lh-gauge__wrapper--plugin');
|
|
382
383
|
}
|
|
383
384
|
|
|
@@ -393,16 +394,16 @@ export class CategoryRenderer {
|
|
|
393
394
|
percentageEl.textContent = scoreOutOf100.toString();
|
|
394
395
|
if (category.score === null) {
|
|
395
396
|
percentageEl.textContent = '?';
|
|
396
|
-
percentageEl.title =
|
|
397
|
+
percentageEl.title = Globals.strings.errorLabel;
|
|
397
398
|
}
|
|
398
399
|
|
|
399
400
|
// Render a numerical score if the category has applicable audits, or no audits whatsoever.
|
|
400
401
|
if (category.auditRefs.length === 0 || this.hasApplicableAudits(category)) {
|
|
401
|
-
wrapper.classList.add(`lh-gauge__wrapper--${
|
|
402
|
+
wrapper.classList.add(`lh-gauge__wrapper--${ReportUtils.calculateRating(category.score)}`);
|
|
402
403
|
} else {
|
|
403
404
|
wrapper.classList.add(`lh-gauge__wrapper--not-applicable`);
|
|
404
405
|
percentageEl.textContent = '-';
|
|
405
|
-
percentageEl.title =
|
|
406
|
+
percentageEl.title = Globals.strings.notApplicableAuditsGroupTitle;
|
|
406
407
|
}
|
|
407
408
|
|
|
408
409
|
this.dom.find('.lh-gauge__label', tmpl).textContent = category.title;
|
|
@@ -417,7 +418,8 @@ export class CategoryRenderer {
|
|
|
417
418
|
const tmpl = this.dom.createComponent('fraction');
|
|
418
419
|
const wrapper = this.dom.find('a.lh-fraction__wrapper', tmpl);
|
|
419
420
|
|
|
420
|
-
const {numPassed, numPassableAudits, totalWeight} =
|
|
421
|
+
const {numPassed, numPassableAudits, totalWeight} =
|
|
422
|
+
ReportUtils.calculateCategoryFraction(category);
|
|
421
423
|
|
|
422
424
|
const fraction = numPassed / numPassableAudits;
|
|
423
425
|
const content = this.dom.find('.lh-fraction__content', tmpl);
|
|
@@ -425,7 +427,7 @@ export class CategoryRenderer {
|
|
|
425
427
|
text.textContent = `${numPassed}/${numPassableAudits}`;
|
|
426
428
|
content.append(text);
|
|
427
429
|
|
|
428
|
-
let rating =
|
|
430
|
+
let rating = ReportUtils.calculateRating(fraction);
|
|
429
431
|
|
|
430
432
|
// If none of the available audits can affect the score, a rating isn't useful.
|
|
431
433
|
// The flow report should display the fraction with neutral icon and coloring in this case.
|
|
@@ -490,7 +492,7 @@ export class CategoryRenderer {
|
|
|
490
492
|
return scoreDisplayMode;
|
|
491
493
|
}
|
|
492
494
|
|
|
493
|
-
if (
|
|
495
|
+
if (ReportUtils.showAsPassed(auditRef.result)) {
|
|
494
496
|
if (this._auditHasWarning(auditRef)) {
|
|
495
497
|
return 'warning';
|
|
496
498
|
} else {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* critical request chains network tree.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import {Globals} from './report-globals.js';
|
|
24
24
|
|
|
25
25
|
/** @typedef {import('./dom.js').DOM} DOM */
|
|
26
26
|
/** @typedef {import('./details-renderer.js').DetailsRenderer} DetailsRenderer */
|
|
@@ -137,9 +137,9 @@ class CriticalRequestChainRenderer {
|
|
|
137
137
|
const {startTime, endTime, transferSize} = segment.node.request;
|
|
138
138
|
const span = dom.createElement('span', 'lh-crc-node__chain-duration');
|
|
139
139
|
span.textContent =
|
|
140
|
-
' - ' +
|
|
140
|
+
' - ' + Globals.i18n.formatMilliseconds((endTime - startTime) * 1000) + ', ';
|
|
141
141
|
const span2 = dom.createElement('span', 'lh-crc-node__chain-duration');
|
|
142
|
-
span2.textContent =
|
|
142
|
+
span2.textContent = Globals.i18n.formatBytesToKiB(transferSize, 0.01);
|
|
143
143
|
|
|
144
144
|
treevalEl.append(span, span2);
|
|
145
145
|
}
|
|
@@ -178,11 +178,11 @@ class CriticalRequestChainRenderer {
|
|
|
178
178
|
const containerEl = dom.find('.lh-crc', tmpl);
|
|
179
179
|
|
|
180
180
|
// Fill in top summary.
|
|
181
|
-
dom.find('.lh-crc-initial-nav', tmpl).textContent =
|
|
181
|
+
dom.find('.lh-crc-initial-nav', tmpl).textContent = Globals.strings.crcInitialNavigation;
|
|
182
182
|
dom.find('.lh-crc__longest_duration_label', tmpl).textContent =
|
|
183
|
-
|
|
183
|
+
Globals.strings.crcLongestDurationLabel;
|
|
184
184
|
dom.find('.lh-crc__longest_duration', tmpl).textContent =
|
|
185
|
-
|
|
185
|
+
Globals.i18n.formatMilliseconds(details.longestChain.duration);
|
|
186
186
|
|
|
187
187
|
// Construct visual tree.
|
|
188
188
|
const root = CRCRenderer.initTree(details.chains);
|
|
@@ -25,9 +25,10 @@
|
|
|
25
25
|
/** @typedef {LH.FormattedIcu<LH.Audit.Details.ItemValue>} TableItemValue */
|
|
26
26
|
/** @typedef {LH.FormattedIcu<LH.Audit.Details.TableColumnHeading>} TableColumnHeading */
|
|
27
27
|
|
|
28
|
-
import {Util} from '
|
|
28
|
+
import {Util} from '../../shared/util.js';
|
|
29
29
|
import {CriticalRequestChainRenderer} from './crc-details-renderer.js';
|
|
30
30
|
import {ElementScreenshotRenderer} from './element-screenshot-renderer.js';
|
|
31
|
+
import {Globals} from './report-globals.js';
|
|
31
32
|
|
|
32
33
|
const URL_PREFIXES = ['http://', 'https://', 'data:'];
|
|
33
34
|
|
|
@@ -77,9 +78,9 @@ export class DetailsRenderer {
|
|
|
77
78
|
*/
|
|
78
79
|
_renderBytes(details) {
|
|
79
80
|
// TODO: handle displayUnit once we have something other than 'KiB'
|
|
80
|
-
const value =
|
|
81
|
+
const value = Globals.i18n.formatBytesToKiB(details.value, details.granularity || 0.1);
|
|
81
82
|
const textEl = this._renderText(value);
|
|
82
|
-
textEl.title =
|
|
83
|
+
textEl.title = Globals.i18n.formatBytes(details.value);
|
|
83
84
|
return textEl;
|
|
84
85
|
}
|
|
85
86
|
|
|
@@ -90,9 +91,9 @@ export class DetailsRenderer {
|
|
|
90
91
|
_renderMilliseconds(details) {
|
|
91
92
|
let value;
|
|
92
93
|
if (details.displayUnit === 'duration') {
|
|
93
|
-
value =
|
|
94
|
+
value = Globals.i18n.formatDuration(details.value);
|
|
94
95
|
} else {
|
|
95
|
-
value =
|
|
96
|
+
value = Globals.i18n.formatMilliseconds(details.value, details.granularity || 10);
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
return this._renderText(value);
|
|
@@ -171,7 +172,7 @@ export class DetailsRenderer {
|
|
|
171
172
|
* @return {Element}
|
|
172
173
|
*/
|
|
173
174
|
_renderNumeric(details) {
|
|
174
|
-
const value =
|
|
175
|
+
const value = Globals.i18n.formatNumber(details.value, details.granularity || 0.1);
|
|
175
176
|
const element = this._dom.createElement('div', 'lh-numeric');
|
|
176
177
|
element.textContent = value;
|
|
177
178
|
return element;
|
package/report/renderer/dom.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
/** @typedef {HTMLElementTagNameMap & {[id: string]: HTMLElement}} HTMLElementByTagName */
|
|
21
21
|
/** @template {string} T @typedef {import('typed-query-selector/parser').ParseSelector<T, Element>} ParseSelector */
|
|
22
22
|
|
|
23
|
-
import {Util} from '
|
|
23
|
+
import {Util} from '../../shared/util.js';
|
|
24
24
|
import {createComponent} from './components.js';
|
|
25
25
|
|
|
26
26
|
export class DOM {
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* 2. Display coords (DC suffix): that match the CSS pixel coordinate space of the LH report's page.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import {Globals} from './report-globals.js';
|
|
14
|
+
|
|
13
15
|
/** @typedef {import('./dom.js').DOM} DOM */
|
|
14
16
|
/** @typedef {LH.Audit.Details.Rect} Rect */
|
|
15
17
|
/** @typedef {{width: number, height: number}} Size */
|
|
@@ -22,8 +24,6 @@
|
|
|
22
24
|
* @property {LH.Result.FullPageScreenshot} fullPageScreenshot
|
|
23
25
|
*/
|
|
24
26
|
|
|
25
|
-
import {Util} from './util.js';
|
|
26
|
-
|
|
27
27
|
/**
|
|
28
28
|
* @param {LH.Result.FullPageScreenshot['screenshot']} screenshot
|
|
29
29
|
* @param {LH.Audit.Details.Rect} rect
|
|
@@ -102,7 +102,7 @@ export class ElementScreenshotRenderer {
|
|
|
102
102
|
*/
|
|
103
103
|
static renderClipPathInScreenshot(dom, maskEl, positionClip, elementRect, elementPreviewSize) {
|
|
104
104
|
const clipPathEl = dom.find('clipPath', maskEl);
|
|
105
|
-
const clipId = `clip-${
|
|
105
|
+
const clipId = `clip-${Globals.getUniqueSuffix()}`;
|
|
106
106
|
clipPathEl.id = clipId;
|
|
107
107
|
maskEl.style.clipPath = `url(#${clipId})`;
|
|
108
108
|
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
/** @typedef {import('./dom.js').DOM} DOM */
|
|
19
19
|
|
|
20
|
-
import {Util} from './util.js';
|
|
21
20
|
import {CategoryRenderer} from './category-renderer.js';
|
|
21
|
+
import {ReportUtils} from './report-utils.js';
|
|
22
|
+
import {Globals} from './report-globals.js';
|
|
22
23
|
|
|
23
24
|
export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
24
25
|
/**
|
|
@@ -29,7 +30,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
29
30
|
const tmpl = this.dom.createComponent('metric');
|
|
30
31
|
const element = this.dom.find('.lh-metric', tmpl);
|
|
31
32
|
element.id = audit.result.id;
|
|
32
|
-
const rating =
|
|
33
|
+
const rating = ReportUtils.calculateRating(audit.result.score, audit.result.scoreDisplayMode);
|
|
33
34
|
element.classList.add(`lh-metric--${rating}`);
|
|
34
35
|
|
|
35
36
|
const titleEl = this.dom.find('.lh-metric__title', tmpl);
|
|
@@ -77,7 +78,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
77
78
|
this.dom.find('span.lh-audit__display-text, div.lh-audit__display-text', element);
|
|
78
79
|
const sparklineWidthPct = `${details.overallSavingsMs / scale * 100}%`;
|
|
79
80
|
this.dom.find('div.lh-sparkline__bar', element).style.width = sparklineWidthPct;
|
|
80
|
-
displayEl.textContent =
|
|
81
|
+
displayEl.textContent = Globals.i18n.formatSeconds(details.overallSavingsMs, 0.01);
|
|
81
82
|
|
|
82
83
|
// Set [title] tooltips
|
|
83
84
|
if (audit.result.displayValue) {
|
|
@@ -144,9 +145,9 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
144
145
|
});
|
|
145
146
|
const paramPairs = [...metricPairs];
|
|
146
147
|
|
|
147
|
-
if (
|
|
148
|
-
paramPairs.push(['device',
|
|
149
|
-
paramPairs.push(['version',
|
|
148
|
+
if (Globals.reportJson) {
|
|
149
|
+
paramPairs.push(['device', Globals.reportJson.configSettings.formFactor]);
|
|
150
|
+
paramPairs.push(['version', Globals.reportJson.lighthouseVersion]);
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
const params = new URLSearchParams(paramPairs);
|
|
@@ -178,7 +179,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
178
179
|
* @override
|
|
179
180
|
*/
|
|
180
181
|
render(category, groups, options) {
|
|
181
|
-
const strings =
|
|
182
|
+
const strings = Globals.strings;
|
|
182
183
|
const element = this.dom.createElement('div', 'lh-category');
|
|
183
184
|
element.id = category.id;
|
|
184
185
|
element.append(this.renderCategoryHeader(category, groups, options));
|
|
@@ -190,7 +191,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
190
191
|
|
|
191
192
|
// Metric descriptions toggle.
|
|
192
193
|
const checkboxEl = this.dom.createElement('input', 'lh-metrics-toggle__input');
|
|
193
|
-
const checkboxId = `lh-metrics-toggle${
|
|
194
|
+
const checkboxId = `lh-metrics-toggle${Globals.getUniqueSuffix()}`;
|
|
194
195
|
checkboxEl.setAttribute('aria-label', 'Toggle the display of metric descriptions');
|
|
195
196
|
checkboxEl.type = 'checkbox';
|
|
196
197
|
checkboxEl.id = checkboxId;
|
|
@@ -200,8 +201,8 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
200
201
|
labelEl.htmlFor = checkboxId;
|
|
201
202
|
const showEl = this.dom.createChildOf(labelEl, 'span', 'lh-metrics-toggle__labeltext--show');
|
|
202
203
|
const hideEl = this.dom.createChildOf(labelEl, 'span', 'lh-metrics-toggle__labeltext--hide');
|
|
203
|
-
showEl.textContent =
|
|
204
|
-
hideEl.textContent =
|
|
204
|
+
showEl.textContent = Globals.strings.expandView;
|
|
205
|
+
hideEl.textContent = Globals.strings.collapseView;
|
|
205
206
|
|
|
206
207
|
const metricsBoxesEl = this.dom.createElement('div', 'lh-metrics-container');
|
|
207
208
|
metricsGroupEl.insertBefore(metricsBoxesEl, metricsFooterEl);
|
|
@@ -240,7 +241,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
240
241
|
// Opportunities
|
|
241
242
|
const opportunityAudits = category.auditRefs
|
|
242
243
|
.filter(audit => this._classifyPerformanceAudit(audit) === 'load-opportunity')
|
|
243
|
-
.filter(audit => !
|
|
244
|
+
.filter(audit => !ReportUtils.showAsPassed(audit.result))
|
|
244
245
|
.sort((auditA, auditB) => this._getWastedMs(auditB) - this._getWastedMs(auditA));
|
|
245
246
|
|
|
246
247
|
const filterableMetrics = metricAudits.filter(a => !!a.relevantAudits);
|
|
@@ -274,7 +275,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
274
275
|
// Diagnostics
|
|
275
276
|
const diagnosticAudits = category.auditRefs
|
|
276
277
|
.filter(audit => this._classifyPerformanceAudit(audit) === 'diagnostic')
|
|
277
|
-
.filter(audit => !
|
|
278
|
+
.filter(audit => !ReportUtils.showAsPassed(audit.result))
|
|
278
279
|
.sort((a, b) => {
|
|
279
280
|
const scoreA = a.result.scoreDisplayMode === 'informative' ? 100 : Number(a.result.score);
|
|
280
281
|
const scoreB = b.result.scoreDisplayMode === 'informative' ? 100 : Number(b.result.score);
|
|
@@ -290,7 +291,8 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
290
291
|
|
|
291
292
|
// Passed audits
|
|
292
293
|
const passedAudits = category.auditRefs
|
|
293
|
-
.filter(audit =>
|
|
294
|
+
.filter(audit =>
|
|
295
|
+
this._classifyPerformanceAudit(audit) && ReportUtils.showAsPassed(audit.result));
|
|
294
296
|
|
|
295
297
|
if (!passedAudits.length) return element;
|
|
296
298
|
|
|
@@ -333,7 +335,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
333
335
|
renderMetricAuditFilter(filterableMetrics, categoryEl) {
|
|
334
336
|
const metricFilterEl = this.dom.createElement('div', 'lh-metricfilter');
|
|
335
337
|
const textEl = this.dom.createChildOf(metricFilterEl, 'span', 'lh-metricfilter__text');
|
|
336
|
-
textEl.textContent =
|
|
338
|
+
textEl.textContent = Globals.strings.showRelevantAudits;
|
|
337
339
|
|
|
338
340
|
const filterChoices = /** @type {LH.ReportResult.AuditRef[]} */ ([
|
|
339
341
|
({acronym: 'All'}),
|
|
@@ -342,7 +344,7 @@ export class PerformanceCategoryRenderer extends CategoryRenderer {
|
|
|
342
344
|
|
|
343
345
|
// Form labels need to reference unique IDs, but multiple reports rendered in the same DOM (eg PSI)
|
|
344
346
|
// would mean ID conflict. To address this, we 'scope' these radio inputs with a unique suffix.
|
|
345
|
-
const uniqSuffix =
|
|
347
|
+
const uniqSuffix = Globals.getUniqueSuffix();
|
|
346
348
|
for (const metric of filterChoices) {
|
|
347
349
|
const elemId = `metric-${metric.acronym}-${uniqSuffix}`;
|
|
348
350
|
const radioEl = this.dom.createChildOf(metricFilterEl, 'input', 'lh-metricfilter__radio');
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {Util} from './util.js';
|
|
19
18
|
import {CategoryRenderer} from './category-renderer.js';
|
|
19
|
+
import {ReportUtils} from './report-utils.js';
|
|
20
|
+
import {Globals} from './report-globals.js';
|
|
20
21
|
|
|
21
22
|
export class PwaCategoryRenderer extends CategoryRenderer {
|
|
22
23
|
/**
|
|
@@ -101,7 +102,7 @@ export class PwaCategoryRenderer extends CategoryRenderer {
|
|
|
101
102
|
|
|
102
103
|
// Remove any that have a failing audit.
|
|
103
104
|
for (const auditRef of auditRefs) {
|
|
104
|
-
if (!
|
|
105
|
+
if (!ReportUtils.showAsPassed(auditRef.result) && auditRef.group) {
|
|
105
106
|
uniqueGroupIds.delete(auditRef.group);
|
|
106
107
|
}
|
|
107
108
|
}
|
|
@@ -122,7 +123,7 @@ export class PwaCategoryRenderer extends CategoryRenderer {
|
|
|
122
123
|
for (const groupId of groupIds) {
|
|
123
124
|
const groupAuditRefs = auditRefs.filter(ref => ref.group === groupId);
|
|
124
125
|
const auditCount = groupAuditRefs.length;
|
|
125
|
-
const passedCount = groupAuditRefs.filter(ref =>
|
|
126
|
+
const passedCount = groupAuditRefs.filter(ref => ReportUtils.showAsPassed(ref.result)).length;
|
|
126
127
|
|
|
127
128
|
const title = groupDefinitions[groupId].title;
|
|
128
129
|
tips.push(`${title}: ${passedCount}/${auditCount}`);
|
|
@@ -162,7 +163,7 @@ export class PwaCategoryRenderer extends CategoryRenderer {
|
|
|
162
163
|
const defsEl = svgRoot.querySelector('defs');
|
|
163
164
|
if (!defsEl) return;
|
|
164
165
|
|
|
165
|
-
const idSuffix =
|
|
166
|
+
const idSuffix = Globals.getUniqueSuffix();
|
|
166
167
|
const elementsToUpdate = defsEl.querySelectorAll('[id]');
|
|
167
168
|
for (const el of elementsToUpdate) {
|
|
168
169
|
const oldId = el.id;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type I18nFormatter = import('./i18n-formatter').I18nFormatter;
|
|
2
|
+
export class Globals {
|
|
3
|
+
/** @type {I18nFormatter} */
|
|
4
|
+
static i18n: I18nFormatter;
|
|
5
|
+
/** @type {typeof UIStrings} */
|
|
6
|
+
static strings: typeof UIStrings;
|
|
7
|
+
/** @type {LH.ReportResult | null} */
|
|
8
|
+
static reportJson: LH.ReportResult | null;
|
|
9
|
+
/**
|
|
10
|
+
* @param {{providedStrings: Record<string, string>; i18n: I18nFormatter; reportJson: LH.ReportResult | null}} options
|
|
11
|
+
*/
|
|
12
|
+
static apply(options: {
|
|
13
|
+
providedStrings: Record<string, string>;
|
|
14
|
+
i18n: I18nFormatter;
|
|
15
|
+
reportJson: LH.ReportResult | null;
|
|
16
|
+
}): void;
|
|
17
|
+
static getUniqueSuffix(): number;
|
|
18
|
+
static resetUniqueSuffix(): void;
|
|
19
|
+
}
|
|
20
|
+
import { UIStrings } from "./report-utils.js";
|
|
21
|
+
//# sourceMappingURL=report-globals.d.ts.map
|