lighthouse 9.0.0 → 9.1.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 +5681 -0
- package/dist/report/bundle.esm.js +36 -7
- package/dist/report/flow.js +97 -30
- package/dist/report/standalone.js +5 -5
- package/flow-report/api.ts +18 -0
- package/flow-report/assets/standalone-flow-template.html +2 -5
- package/flow-report/{standalone-flow.tsx → clients/standalone.ts} +5 -6
- package/flow-report/src/app.tsx +13 -8
- package/flow-report/src/sidebar/flow.tsx +1 -3
- package/flow-report/src/sidebar/sidebar.tsx +1 -3
- package/flow-report/src/topbar.tsx +24 -18
- package/flow-report/src/util.ts +35 -1
- package/flow-report/src/wrappers/category-score.tsx +9 -24
- package/flow-report/src/wrappers/markdown.tsx +4 -13
- package/flow-report/src/wrappers/report.tsx +26 -57
- package/flow-report/src/wrappers/styles.tsx +16 -0
- package/flow-report/test/setup/env-setup.ts +11 -5
- package/flow-report/test/summary/category-test.tsx +3 -6
- package/flow-report/test/summary/summary-test.tsx +3 -6
- package/flow-report/test/topbar-test.tsx +30 -14
- package/flow-report/test/util-test.tsx +38 -1
- package/flow-report/test/wrappers/category-score-test.tsx +3 -6
- package/flow-report/test/wrappers/markdown-test.tsx +1 -13
- package/flow-report/types/flow-report.d.ts +4 -0
- package/lighthouse-cli/cli-flags.js +4 -4
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +0 -0
- package/lighthouse-core/audits/audit.js +39 -7
- package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +1 -26
- package/lighthouse-core/audits/deprecations.js +10 -14
- package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +5 -4
- package/lighthouse-core/audits/dobetterweb/js-libraries.js +1 -1
- package/lighthouse-core/audits/dobetterweb/no-document-write.js +6 -4
- package/lighthouse-core/audits/dobetterweb/notification-on-start.js +6 -4
- package/lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js +6 -4
- package/lighthouse-core/audits/errors-in-console.js +7 -4
- package/lighthouse-core/audits/installable-manifest.js +11 -4
- package/lighthouse-core/audits/no-unload-listeners.js +9 -10
- package/lighthouse-core/audits/seo/canonical.js +0 -14
- package/lighthouse-core/audits/seo/font-size.js +4 -2
- package/lighthouse-core/audits/seo/is-crawlable.js +2 -2
- package/lighthouse-core/audits/third-party-summary.js +2 -2
- package/lighthouse-core/audits/valid-source-maps.js +1 -1
- package/lighthouse-core/audits/violation-audit.js +10 -3
- package/lighthouse-core/computed/js-bundles.js +1 -3
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +3 -3
- package/lighthouse-core/gather/driver/execution-context.js +1 -1
- package/lighthouse-core/gather/gatherers/full-page-screenshot.js +7 -7
- package/lighthouse-core/gather/gatherers/stacks.js +0 -3
- package/lighthouse-core/lib/page-functions.js +2 -1
- package/lighthouse-core/lib/stack-packs.js +12 -8
- package/lighthouse-core/lib/statistics.js +26 -39
- package/lighthouse-core/runner.js +7 -7
- package/lighthouse-core/scripts/package.json +4 -0
- package/package.json +4 -6
- package/report/assets/styles.css +2 -2
- package/report/generator/file-namer.js +12 -1
- package/report/generator/flow-report-assets.js +2 -1
- package/report/generator/report-assets.js +2 -5
- package/report/generator/report-generator.js +0 -1
- package/report/renderer/api.js +49 -1
- package/report/renderer/category-renderer.js +17 -3
- package/report/renderer/components.js +1 -1
- package/report/renderer/report-renderer.js +5 -1
- package/report/renderer/report-ui-features.js +1 -1
- package/report/renderer/swap-locale-feature.js +0 -5
- package/report/test/clients/bundle-test.js +2 -2
- package/report/test/renderer/category-renderer-test.js +28 -0
- package/report/test/renderer/report-renderer-axe-test.js +2 -2
- package/report/test/renderer/report-renderer-test.js +29 -0
- package/report/test/renderer/report-ui-features-test.js +0 -1
- package/report/types/report-renderer.d.ts +7 -0
- package/shared/localization/locales/ar-XB.json +0 -3
- package/shared/localization/locales/ar.json +0 -3
- package/shared/localization/locales/bg.json +17 -20
- package/shared/localization/locales/ca.json +0 -3
- package/shared/localization/locales/cs.json +0 -3
- package/shared/localization/locales/da.json +16 -19
- package/shared/localization/locales/de.json +0 -3
- package/shared/localization/locales/el.json +0 -3
- package/shared/localization/locales/en-GB.json +19 -22
- package/shared/localization/locales/en-US.json +33 -3
- package/shared/localization/locales/en-XA.json +0 -3
- package/shared/localization/locales/en-XL.json +33 -3
- package/shared/localization/locales/es-419.json +17 -20
- package/shared/localization/locales/es.json +0 -3
- package/shared/localization/locales/fi.json +16 -19
- package/shared/localization/locales/fil.json +33 -36
- package/shared/localization/locales/fr.json +16 -19
- package/shared/localization/locales/he.json +16 -19
- package/shared/localization/locales/hi.json +0 -3
- package/shared/localization/locales/hr.json +16 -19
- package/shared/localization/locales/hu.json +16 -19
- package/shared/localization/locales/id.json +16 -19
- package/shared/localization/locales/it.json +37 -40
- package/shared/localization/locales/ja.json +16 -19
- package/shared/localization/locales/ko.json +16 -19
- package/shared/localization/locales/lt.json +17 -20
- package/shared/localization/locales/lv.json +0 -3
- package/shared/localization/locales/nl.json +16 -19
- package/shared/localization/locales/no.json +17 -20
- package/shared/localization/locales/pl.json +16 -19
- package/shared/localization/locales/pt-PT.json +37 -40
- package/shared/localization/locales/pt.json +16 -19
- package/shared/localization/locales/ro.json +0 -3
- package/shared/localization/locales/ru.json +16 -19
- package/shared/localization/locales/sk.json +0 -3
- package/shared/localization/locales/sl.json +0 -3
- package/shared/localization/locales/sr-Latn.json +16 -19
- package/shared/localization/locales/sr.json +16 -19
- package/shared/localization/locales/sv.json +17 -20
- package/shared/localization/locales/ta.json +0 -3
- package/shared/localization/locales/te.json +0 -3
- package/shared/localization/locales/th.json +0 -3
- package/shared/localization/locales/tr.json +0 -3
- package/shared/localization/locales/uk.json +17 -20
- package/shared/localization/locales/vi.json +0 -3
- package/shared/localization/locales/zh-HK.json +0 -3
- package/shared/localization/locales/zh-TW.json +0 -3
- package/shared/localization/locales/zh.json +0 -3
- package/third-party/chromium-synchronization/installability-errors-test.js +1 -2
- package/third-party/snyk/snapshot.json +4 -1
- package/types/externs.d.ts +5 -24
- package/flow-report/src/wrappers/report-renderer.tsx +0 -53
|
@@ -98,9 +98,7 @@ class JSBundles {
|
|
|
98
98
|
|
|
99
99
|
const compiledUrl = SourceMap.scriptUrl || 'compiled.js';
|
|
100
100
|
const mapUrl = SourceMap.sourceMapUrl || 'compiled.js.map';
|
|
101
|
-
|
|
102
|
-
const rawMapForCdt = /** @type {any} */ (rawMap);
|
|
103
|
-
const map = new SDK.TextSourceMap(compiledUrl, mapUrl, rawMapForCdt);
|
|
101
|
+
const map = new SDK.TextSourceMap(compiledUrl, mapUrl, rawMap);
|
|
104
102
|
|
|
105
103
|
const content = scriptElement && scriptElement.content ? scriptElement.content : '';
|
|
106
104
|
const sizes = computeGeneratedFileSizes(map, content);
|
|
@@ -142,8 +142,8 @@ async function _collectDebugData(navigationContext, phaseState) {
|
|
|
142
142
|
/**
|
|
143
143
|
* @param {NavigationContext} navigationContext
|
|
144
144
|
* @param {PhaseState} phaseState
|
|
145
|
-
* @param {
|
|
146
|
-
* @param {
|
|
145
|
+
* @param {Awaited<ReturnType<typeof _setupNavigation>>} setupResult
|
|
146
|
+
* @param {Awaited<ReturnType<typeof _navigate>>} navigateResult
|
|
147
147
|
* @return {Promise<{finalUrl: string, artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
|
|
148
148
|
*/
|
|
149
149
|
async function _computeNavigationResult(
|
|
@@ -195,7 +195,7 @@ async function _computeNavigationResult(
|
|
|
195
195
|
async function _navigation(navigationContext) {
|
|
196
196
|
const artifactState = getEmptyArtifactState();
|
|
197
197
|
const phaseState = {
|
|
198
|
-
gatherMode: /** @type {
|
|
198
|
+
gatherMode: /** @type {const} */ ('navigation'),
|
|
199
199
|
driver: navigationContext.driver,
|
|
200
200
|
computedCache: navigationContext.computedCache,
|
|
201
201
|
artifactDefinitions: navigationContext.navigation.artifacts,
|
|
@@ -166,7 +166,7 @@ class ExecutionContext {
|
|
|
166
166
|
* @param {{args: T, useIsolation?: boolean, deps?: Array<Function|string>}} options `args` should
|
|
167
167
|
* match the args of `mainFn`, and can be any serializable value. `deps` are functions that must be
|
|
168
168
|
* defined for `mainFn` to work.
|
|
169
|
-
* @return {
|
|
169
|
+
* @return {Promise<Awaited<R>>}
|
|
170
170
|
*/
|
|
171
171
|
evaluate(mainFn, options) {
|
|
172
172
|
const argsSerialized = ExecutionContext.serializeArguments(options.args);
|
|
@@ -16,19 +16,19 @@ const pageFunctions = require('../../lib/page-functions.js');
|
|
|
16
16
|
const FULL_PAGE_SCREENSHOT_QUALITY = 30;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* @
|
|
19
|
+
* @template {string} S
|
|
20
|
+
* @param {S} str
|
|
20
21
|
*/
|
|
21
|
-
function
|
|
22
|
-
return str.replace(/(-\w)/g, m => m[1].toUpperCase());
|
|
22
|
+
function kebabCaseToCamelCase(str) {
|
|
23
|
+
return /** @type {KebabToCamelCase<S>} */ (str.replace(/(-\w)/g, m => m[1].toUpperCase()));
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/* c8 ignore start */
|
|
26
27
|
|
|
27
28
|
// eslint-disable-next-line no-inner-declarations
|
|
28
29
|
function getObservedDeviceMetrics() {
|
|
29
|
-
// Convert the Web API's
|
|
30
|
-
const screenOrientationType =
|
|
31
|
-
snakeCaseToCamelCase(window.screen.orientation.type));
|
|
30
|
+
// Convert the Web API's kebab case (landscape-primary) to camel case (landscapePrimary).
|
|
31
|
+
const screenOrientationType = kebabCaseToCamelCase(window.screen.orientation.type);
|
|
32
32
|
return {
|
|
33
33
|
width: document.documentElement.clientWidth,
|
|
34
34
|
height: document.documentElement.clientHeight,
|
|
@@ -168,7 +168,7 @@ class FullPageScreenshot extends FRGatherer {
|
|
|
168
168
|
observedDeviceMetrics = await executionContext.evaluate(getObservedDeviceMetrics, {
|
|
169
169
|
args: [],
|
|
170
170
|
useIsolation: true,
|
|
171
|
-
deps: [
|
|
171
|
+
deps: [kebabCaseToCamelCase],
|
|
172
172
|
});
|
|
173
173
|
}
|
|
174
174
|
|
|
@@ -82,9 +82,6 @@ class Stacks extends FRGatherer {
|
|
|
82
82
|
constructor() {
|
|
83
83
|
super();
|
|
84
84
|
|
|
85
|
-
// Because this file uses `fs.readFile` it gets parsed by a different branch of the browserify internals
|
|
86
|
-
// that cannot handle the latest ECMAScript features.
|
|
87
|
-
// See https://github.com/GoogleChrome/lighthouse/issues/12134
|
|
88
85
|
/** @type {LH.Gatherer.GathererMeta} */
|
|
89
86
|
this.meta = {
|
|
90
87
|
supportedModes: ['snapshot', 'navigation'],
|
|
@@ -208,7 +208,8 @@ function computeBenchmarkIndex() {
|
|
|
208
208
|
|
|
209
209
|
while (Date.now() - start < 500) {
|
|
210
210
|
let s = '';
|
|
211
|
-
for (let j = 0; j < 10000; j++) s += 'a';
|
|
211
|
+
for (let j = 0; j < 10000; j++) s += 'a';
|
|
212
|
+
if (s.length === 1) throw new Error('will never happen, but prevents compiler optimizations');
|
|
212
213
|
|
|
213
214
|
iterations++;
|
|
214
215
|
}
|
|
@@ -23,14 +23,6 @@ const stackPacksToInclude = [
|
|
|
23
23
|
packId: 'drupal',
|
|
24
24
|
requiredStacks: ['js:drupal'],
|
|
25
25
|
},
|
|
26
|
-
{
|
|
27
|
-
packId: 'react',
|
|
28
|
-
requiredStacks: ['js:react'],
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
packId: 'angular',
|
|
32
|
-
requiredStacks: ['js:@angular/core'],
|
|
33
|
-
},
|
|
34
26
|
{
|
|
35
27
|
packId: 'amp',
|
|
36
28
|
requiredStacks: ['js:amp'],
|
|
@@ -47,6 +39,18 @@ const stackPacksToInclude = [
|
|
|
47
39
|
packId: 'joomla',
|
|
48
40
|
requiredStacks: ['js:joomla'],
|
|
49
41
|
},
|
|
42
|
+
{
|
|
43
|
+
packId: 'next.js',
|
|
44
|
+
requiredStacks: ['js:next'],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
packId: 'angular',
|
|
48
|
+
requiredStacks: ['js:@angular/core'],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
packId: 'react',
|
|
52
|
+
requiredStacks: ['js:react'],
|
|
53
|
+
},
|
|
50
54
|
];
|
|
51
55
|
|
|
52
56
|
/**
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
+
// The exact double values for the max and min scores possible in each range.
|
|
9
|
+
const MIN_PASSING_SCORE = 0.90000000000000002220446049250313080847263336181640625;
|
|
10
|
+
const MAX_AVERAGE_SCORE = 0.899999999999999911182158029987476766109466552734375;
|
|
11
|
+
const MIN_AVERAGE_SCORE = 0.5;
|
|
12
|
+
const MAX_FAILING_SCORE = 0.499999999999999944488848768742172978818416595458984375;
|
|
13
|
+
|
|
8
14
|
/**
|
|
9
15
|
* Approximates the Gauss error function, the probability that a random variable
|
|
10
16
|
* from the standard normal distribution lies within [-x, x]. Moved from
|
|
@@ -28,37 +34,6 @@ function erf(x) {
|
|
|
28
34
|
return sign * (1 - y * Math.exp(-x * x));
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
/**
|
|
32
|
-
* Creates a log-normal distribution à la traceviewer's statistics package.
|
|
33
|
-
* Specified by providing the median value, at which the score will be 0.5,
|
|
34
|
-
* and the falloff, the initial point of diminishing returns where any
|
|
35
|
-
* improvement in value will yield increasingly smaller gains in score. Both
|
|
36
|
-
* values should be in the same units (e.g. milliseconds). See
|
|
37
|
-
* https://www.desmos.com/calculator/tx1wcjk8ch
|
|
38
|
-
* for an interactive view of the relationship between these parameters and
|
|
39
|
-
* the typical parameterization (location and shape) of the log-normal
|
|
40
|
-
* distribution.
|
|
41
|
-
* @param {number} median
|
|
42
|
-
* @param {number} falloff
|
|
43
|
-
* @return {{computeComplementaryPercentile: function(number): number}}
|
|
44
|
-
*/
|
|
45
|
-
function getLogNormalDistribution(median, falloff) {
|
|
46
|
-
const location = Math.log(median);
|
|
47
|
-
|
|
48
|
-
// The "falloff" value specified the location of the smaller of the positive
|
|
49
|
-
// roots of the third derivative of the log-normal CDF. Calculate the shape
|
|
50
|
-
// parameter in terms of that value and the median.
|
|
51
|
-
const logRatio = Math.log(falloff / median);
|
|
52
|
-
const shape = Math.sqrt(1 - 3 * logRatio - Math.sqrt((logRatio - 3) * (logRatio - 3) - 8)) / 2;
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
computeComplementaryPercentile(x) {
|
|
56
|
-
const standardizedX = (Math.log(x) - location) / (Math.SQRT2 * shape);
|
|
57
|
-
return (1 - erf(standardizedX)) / 2;
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
37
|
/**
|
|
63
38
|
* Returns the score (1 - percentile) of `value` in a log-normal distribution
|
|
64
39
|
* specified by the `median` value, at which the score will be 0.5, and a 10th
|
|
@@ -76,24 +51,37 @@ function getLogNormalScore({median, p10}, value) {
|
|
|
76
51
|
// Required for the log-normal distribution.
|
|
77
52
|
if (median <= 0) throw new Error('median must be greater than zero');
|
|
78
53
|
if (p10 <= 0) throw new Error('p10 must be greater than zero');
|
|
79
|
-
// Not required, but if p10 > median, it flips around and becomes the p90 point.
|
|
54
|
+
// Not strictly required, but if p10 > median, it flips around and becomes the p90 point.
|
|
80
55
|
if (p10 >= median) throw new Error('p10 must be less than the median');
|
|
81
56
|
|
|
82
57
|
// Non-positive values aren't in the distribution, so always 1.
|
|
83
58
|
if (value <= 0) return 1;
|
|
84
59
|
|
|
85
|
-
// Closest double to `erfc-1(
|
|
60
|
+
// Closest double to `erfc-1(1/5)`.
|
|
86
61
|
const INVERSE_ERFC_ONE_FIFTH = 0.9061938024368232;
|
|
87
62
|
|
|
88
|
-
// Shape (σ) is
|
|
63
|
+
// Shape (σ) is `|log(p10/median) / (sqrt(2)*erfc^-1(1/5))|` and
|
|
89
64
|
// standardizedX is `1/2 erfc(log(value/median) / (sqrt(2)*σ))`, so simplify a bit.
|
|
90
|
-
const
|
|
91
|
-
const
|
|
65
|
+
const xRatio = Math.max(Number.MIN_VALUE, value / median); // value and median are > 0, so is ratio.
|
|
66
|
+
const xLogRatio = Math.log(xRatio);
|
|
67
|
+
const p10Ratio = Math.max(Number.MIN_VALUE, p10 / median); // p10 and median are > 0, so is ratio.
|
|
68
|
+
const p10LogRatio = -Math.log(p10Ratio); // negate to keep σ positive.
|
|
92
69
|
const standardizedX = xLogRatio * INVERSE_ERFC_ONE_FIFTH / p10LogRatio;
|
|
93
70
|
const complementaryPercentile = (1 - erf(standardizedX)) / 2;
|
|
94
71
|
|
|
95
|
-
// Clamp to
|
|
96
|
-
|
|
72
|
+
// Clamp to avoid floating-point out-of-bounds issues and keep score in expected range.
|
|
73
|
+
let score;
|
|
74
|
+
if (value <= p10) {
|
|
75
|
+
// Passing. Clamp to [0.9, 1].
|
|
76
|
+
score = Math.max(MIN_PASSING_SCORE, Math.min(1, complementaryPercentile));
|
|
77
|
+
} else if (value <= median) {
|
|
78
|
+
// Average. Clamp to [0.5, 0.9).
|
|
79
|
+
score = Math.max(MIN_AVERAGE_SCORE, Math.min(MAX_AVERAGE_SCORE, complementaryPercentile));
|
|
80
|
+
} else {
|
|
81
|
+
// Failing. Clamp to [0, 0.5).
|
|
82
|
+
score = Math.max(0, Math.min(MAX_FAILING_SCORE, complementaryPercentile));
|
|
83
|
+
}
|
|
84
|
+
return score;
|
|
97
85
|
}
|
|
98
86
|
|
|
99
87
|
/**
|
|
@@ -112,6 +100,5 @@ function linearInterpolation(x0, y0, x1, y1, x) {
|
|
|
112
100
|
|
|
113
101
|
module.exports = {
|
|
114
102
|
linearInterpolation,
|
|
115
|
-
getLogNormalDistribution,
|
|
116
103
|
getLogNormalScore,
|
|
117
104
|
};
|
|
@@ -132,7 +132,13 @@ class Runner {
|
|
|
132
132
|
|
|
133
133
|
/** @type {LH.RawIcu<LH.Result>} */
|
|
134
134
|
const i18nLhr = {
|
|
135
|
+
lighthouseVersion,
|
|
136
|
+
requestedUrl,
|
|
137
|
+
finalUrl: artifacts.URL.finalUrl,
|
|
138
|
+
fetchTime: artifacts.fetchTime,
|
|
135
139
|
gatherMode: artifacts.GatherContext.gatherMode,
|
|
140
|
+
runtimeError: Runner.getArtifactRuntimeError(artifacts),
|
|
141
|
+
runWarnings: lighthouseRunWarnings,
|
|
136
142
|
userAgent: artifacts.HostUserAgent,
|
|
137
143
|
environment: {
|
|
138
144
|
networkUserAgent: artifacts.NetworkUserAgent,
|
|
@@ -140,22 +146,16 @@ class Runner {
|
|
|
140
146
|
benchmarkIndex: artifacts.BenchmarkIndex,
|
|
141
147
|
credits,
|
|
142
148
|
},
|
|
143
|
-
lighthouseVersion,
|
|
144
|
-
fetchTime: artifacts.fetchTime,
|
|
145
|
-
requestedUrl: requestedUrl,
|
|
146
|
-
finalUrl: artifacts.URL.finalUrl,
|
|
147
|
-
runWarnings: lighthouseRunWarnings,
|
|
148
|
-
runtimeError: Runner.getArtifactRuntimeError(artifacts),
|
|
149
149
|
audits: auditResultsById,
|
|
150
150
|
configSettings: settings,
|
|
151
151
|
categories,
|
|
152
152
|
categoryGroups: runOpts.config.groups || undefined,
|
|
153
|
+
stackPacks: stackPacks.getStackPacks(artifacts.Stacks),
|
|
153
154
|
timing: this._getTiming(artifacts),
|
|
154
155
|
i18n: {
|
|
155
156
|
rendererFormattedStrings: format.getRendererFormattedStrings(settings.locale),
|
|
156
157
|
icuMessagePaths: {},
|
|
157
158
|
},
|
|
158
|
-
stackPacks: stackPacks.getStackPacks(artifacts.Stacks),
|
|
159
159
|
};
|
|
160
160
|
|
|
161
161
|
// Replace ICU message references with localized strings; save replaced paths in lhr.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
5
5
|
"main": "./lighthouse-core/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -108,7 +108,6 @@
|
|
|
108
108
|
"@testing-library/preact": "^2.0.1",
|
|
109
109
|
"@testing-library/preact-hooks": "^1.1.0",
|
|
110
110
|
"@types/archiver": "^2.1.2",
|
|
111
|
-
"@types/browserify": "^12.0.36",
|
|
112
111
|
"@types/chrome": "^0.0.154",
|
|
113
112
|
"@types/configstore": "^4.0.0",
|
|
114
113
|
"@types/cpy": "^5.1.0",
|
|
@@ -138,7 +137,6 @@
|
|
|
138
137
|
"acorn": "^8.5.0",
|
|
139
138
|
"angular": "^1.7.4",
|
|
140
139
|
"archiver": "^3.0.0",
|
|
141
|
-
"browserify": "^17.0.0",
|
|
142
140
|
"c8": "^7.4.0",
|
|
143
141
|
"chalk": "^2.4.1",
|
|
144
142
|
"chrome-devtools-frontend": "1.0.922924",
|
|
@@ -181,8 +179,8 @@
|
|
|
181
179
|
"tabulator-tables": "^4.9.3",
|
|
182
180
|
"terser": "^5.3.8",
|
|
183
181
|
"ts-jest": "^27.0.4",
|
|
184
|
-
"typed-query-selector": "^2.
|
|
185
|
-
"typescript": "4.
|
|
182
|
+
"typed-query-selector": "^2.6.1",
|
|
183
|
+
"typescript": "^4.5.2",
|
|
186
184
|
"wait-for-expect": "^3.0.2",
|
|
187
185
|
"webtreemap-cdt": "^3.2.1"
|
|
188
186
|
},
|
|
@@ -198,7 +196,7 @@
|
|
|
198
196
|
"jpeg-js": "^0.4.1",
|
|
199
197
|
"js-library-detector": "^6.4.0",
|
|
200
198
|
"lighthouse-logger": "^1.3.0",
|
|
201
|
-
"lighthouse-stack-packs": "^1.
|
|
199
|
+
"lighthouse-stack-packs": "^1.6.0",
|
|
202
200
|
"lodash.clonedeep": "^4.5.0",
|
|
203
201
|
"lodash.get": "^4.4.2",
|
|
204
202
|
"lodash.isequal": "^4.5.0",
|
package/report/assets/styles.css
CHANGED
|
@@ -943,7 +943,7 @@
|
|
|
943
943
|
|
|
944
944
|
|
|
945
945
|
.lh-audit--error .lh-audit__display-text {
|
|
946
|
-
color: var(--color-fail);
|
|
946
|
+
color: var(--color-fail-secondary);
|
|
947
947
|
}
|
|
948
948
|
|
|
949
949
|
/* Audit Group */
|
|
@@ -1055,7 +1055,7 @@
|
|
|
1055
1055
|
}
|
|
1056
1056
|
|
|
1057
1057
|
.lh-audit--fail .lh-audit-explanation {
|
|
1058
|
-
color: var(--color-fail);
|
|
1058
|
+
color: var(--color-fail-secondary);
|
|
1059
1059
|
}
|
|
1060
1060
|
|
|
1061
1061
|
/* Report */
|
|
@@ -43,4 +43,15 @@ function getLhrFilenamePrefix(lhr) {
|
|
|
43
43
|
return getFilenamePrefix(hostname, lhr.fetchTime);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Generate a filenamePrefix of name_YYYY-MM-DD_HH-MM-SS.
|
|
48
|
+
* @param {{name: string, steps: Array<{lhr: {fetchTime: string}}>}} flowResult
|
|
49
|
+
* @return {string}
|
|
50
|
+
*/
|
|
51
|
+
function getFlowResultFilenamePrefix(flowResult) {
|
|
52
|
+
const lhr = flowResult.steps[0].lhr;
|
|
53
|
+
const name = flowResult.name.replace(/\s/g, '-');
|
|
54
|
+
return getFilenamePrefix(name, lhr.fetchTime);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = {getLhrFilenamePrefix, getFilenamePrefix, getFlowResultFilenamePrefix};
|
|
@@ -9,12 +9,13 @@ const fs = require('fs');
|
|
|
9
9
|
|
|
10
10
|
/* eslint-disable max-len */
|
|
11
11
|
const FLOW_REPORT_TEMPLATE = fs.readFileSync(`${__dirname}/../../flow-report/assets/standalone-flow-template.html`, 'utf8');
|
|
12
|
+
const REGULAR_REPORT_CSS = fs.readFileSync(__dirname + '/../assets/styles.css', 'utf8');
|
|
12
13
|
const FLOW_REPORT_CSS = fs.readFileSync(`${__dirname}/../../flow-report/assets/styles.css`, 'utf8');
|
|
13
14
|
const FLOW_REPORT_JAVASCRIPT = fs.readFileSync(`${__dirname}/../../dist/report/flow.js`, 'utf8');
|
|
14
15
|
/* eslint-enable max-len */
|
|
15
16
|
|
|
16
17
|
module.exports = {
|
|
17
18
|
FLOW_REPORT_TEMPLATE,
|
|
18
|
-
FLOW_REPORT_CSS,
|
|
19
|
+
FLOW_REPORT_CSS: [REGULAR_REPORT_CSS, FLOW_REPORT_CSS].join('\n'),
|
|
19
20
|
FLOW_REPORT_JAVASCRIPT,
|
|
20
21
|
};
|
|
@@ -12,15 +12,12 @@ const flowReportAssets = require('./flow-report-assets.js');
|
|
|
12
12
|
const REPORT_TEMPLATE = fs.readFileSync(__dirname + '/../assets/standalone-template.html',
|
|
13
13
|
'utf8');
|
|
14
14
|
const REPORT_JAVASCRIPT = fs.readFileSync(__dirname + '/../../dist/report/standalone.js', 'utf8');
|
|
15
|
-
const REPORT_CSS = fs.readFileSync(__dirname + '/../assets/styles.css', 'utf8');
|
|
16
15
|
|
|
17
|
-
// Changes to this export interface should be reflected in build/build-dt-report-resources.js
|
|
18
|
-
// and clients/devtools-report-assets.js
|
|
19
16
|
module.exports = {
|
|
20
17
|
REPORT_TEMPLATE,
|
|
21
18
|
REPORT_JAVASCRIPT,
|
|
22
|
-
REPORT_CSS,
|
|
23
19
|
// Flow report assets are not needed for every bundle.
|
|
24
|
-
//
|
|
20
|
+
// Replacing/ignoring flow-report-assets.js (e.g. `rollupPlugins.shim`) will
|
|
21
|
+
// remove the flow assets from the bundle.
|
|
25
22
|
...flowReportAssets,
|
|
26
23
|
};
|
|
@@ -70,7 +70,6 @@ class ReportGenerator {
|
|
|
70
70
|
{search: '%%LIGHTHOUSE_FLOW_JSON%%', replacement: sanitizedJson},
|
|
71
71
|
{search: '%%LIGHTHOUSE_FLOW_JAVASCRIPT%%', replacement: htmlReportAssets.FLOW_REPORT_JAVASCRIPT},
|
|
72
72
|
{search: '/*%%LIGHTHOUSE_FLOW_CSS%%*/', replacement: htmlReportAssets.FLOW_REPORT_CSS},
|
|
73
|
-
{search: '/*%%LIGHTHOUSE_CSS%%*/', replacement: htmlReportAssets.REPORT_CSS},
|
|
74
73
|
/* eslint-enable max-len */
|
|
75
74
|
]);
|
|
76
75
|
}
|
package/report/renderer/api.js
CHANGED
|
@@ -9,13 +9,15 @@
|
|
|
9
9
|
import {DOM} from '../renderer/dom.js';
|
|
10
10
|
import {ReportRenderer} from '../renderer/report-renderer.js';
|
|
11
11
|
import {ReportUIFeatures} from '../renderer/report-ui-features.js';
|
|
12
|
+
import {CategoryRenderer} from './category-renderer.js';
|
|
13
|
+
import {DetailsRenderer} from './details-renderer.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* @param {LH.Result} lhr
|
|
15
17
|
* @param {LH.Renderer.Options} opts
|
|
16
18
|
* @return {HTMLElement}
|
|
17
19
|
*/
|
|
18
|
-
|
|
20
|
+
function renderReport(lhr, opts = {}) {
|
|
19
21
|
const rootEl = document.createElement('article');
|
|
20
22
|
rootEl.classList.add('lh-root', 'lh-vars');
|
|
21
23
|
|
|
@@ -30,3 +32,49 @@ export function renderReport(lhr, opts = {}) {
|
|
|
30
32
|
features.initFeatures(lhr);
|
|
31
33
|
return rootEl;
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {LH.ReportResult.Category} category
|
|
38
|
+
* @param {Parameters<CategoryRenderer['renderCategoryScore']>[2]=} options
|
|
39
|
+
* @return {DocumentFragment}
|
|
40
|
+
*/
|
|
41
|
+
function renderCategoryScore(category, options) {
|
|
42
|
+
const dom = new DOM(document, document.documentElement);
|
|
43
|
+
const detailsRenderer = new DetailsRenderer(dom);
|
|
44
|
+
const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
|
|
45
|
+
return categoryRenderer.renderCategoryScore(category, {}, options);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {Blob} blob
|
|
50
|
+
* @param {string} filename
|
|
51
|
+
*/
|
|
52
|
+
function saveFile(blob, filename) {
|
|
53
|
+
const dom = new DOM(document, document.documentElement);
|
|
54
|
+
dom.saveFile(blob, filename);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string} markdownText
|
|
59
|
+
* @return {Element}
|
|
60
|
+
*/
|
|
61
|
+
function convertMarkdownCodeSnippets(markdownText) {
|
|
62
|
+
const dom = new DOM(document, document.documentElement);
|
|
63
|
+
return dom.convertMarkdownCodeSnippets(markdownText);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @return {DocumentFragment}
|
|
68
|
+
*/
|
|
69
|
+
function createStylesElement() {
|
|
70
|
+
const dom = new DOM(document, document.documentElement);
|
|
71
|
+
return dom.createComponent('styles');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
renderReport,
|
|
76
|
+
renderCategoryScore,
|
|
77
|
+
saveFile,
|
|
78
|
+
convertMarkdownCodeSnippets,
|
|
79
|
+
createStylesElement,
|
|
80
|
+
};
|
|
@@ -348,14 +348,28 @@ export class CategoryRenderer {
|
|
|
348
348
|
/**
|
|
349
349
|
* @param {LH.ReportResult.Category} category
|
|
350
350
|
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
|
|
351
|
-
* @param {{gatherMode: LH.Result.GatherMode}=} options
|
|
351
|
+
* @param {{gatherMode: LH.Result.GatherMode, omitLabel?: boolean, onPageAnchorRendered?: (link: HTMLAnchorElement) => void}=} options
|
|
352
352
|
* @return {DocumentFragment}
|
|
353
353
|
*/
|
|
354
354
|
renderCategoryScore(category, groupDefinitions, options) {
|
|
355
|
+
let categoryScore;
|
|
355
356
|
if (options && Util.shouldDisplayAsFraction(options.gatherMode)) {
|
|
356
|
-
|
|
357
|
+
categoryScore = this.renderCategoryFraction(category);
|
|
358
|
+
} else {
|
|
359
|
+
categoryScore = this.renderScoreGauge(category, groupDefinitions);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (options?.omitLabel) {
|
|
363
|
+
const label = this.dom.find('.lh-gauge__label,.lh-fraction__label', categoryScore);
|
|
364
|
+
label.remove();
|
|
357
365
|
}
|
|
358
|
-
|
|
366
|
+
|
|
367
|
+
if (options?.onPageAnchorRendered) {
|
|
368
|
+
const anchor = this.dom.find('a', categoryScore);
|
|
369
|
+
options.onPageAnchorRendered(anchor);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return categoryScore;
|
|
359
373
|
}
|
|
360
374
|
|
|
361
375
|
/**
|