lighthouse 9.5.0-dev.20220607 → 9.6.2
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/dist/report/bundle.esm.js +467 -520
- package/dist/report/flow.js +22 -22
- package/dist/report/standalone.js +19 -19
- package/flow-report/src/summary/category.tsx +1 -1
- package/flow-report/src/topbar.tsx +2 -10
- package/flow-report/src/util.ts +1 -1
- package/flow-report/test/topbar-test.tsx +8 -7
- package/jest.config.js +1 -1
- package/lighthouse-cli/.eslintrc.cjs +4 -3
- package/lighthouse-cli/bin.js +1 -0
- package/lighthouse-cli/cli-flags.js +4 -3
- package/lighthouse-cli/commands/commands.js +1 -0
- package/lighthouse-cli/commands/list-audits.js +1 -0
- package/lighthouse-cli/commands/list-locales.js +1 -0
- package/lighthouse-cli/commands/list-trace-categories.js +1 -0
- package/lighthouse-cli/index.js +1 -0
- package/lighthouse-cli/printer.js +1 -0
- package/lighthouse-cli/run.js +24 -9
- package/lighthouse-cli/sentry-prompt.js +1 -0
- package/lighthouse-cli/test/smokehouse/core-tests.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/lib.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -0
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +23 -109
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +3 -2
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/devtools.js +19 -28
- package/lighthouse-cli/test/smokehouse/report-assert.js +4 -3
- package/lighthouse-cli/test/smokehouse/smokehouse.js +1 -1
- package/lighthouse-cli/test/smokehouse/version-check-test.js +3 -0
- package/lighthouse-cli/test/smokehouse/version-check.js +1 -0
- package/lighthouse-core/audits/accessibility/accesskeys.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-allowed-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-hidden-body.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-hidden-focus.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-input-field-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-children.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-parent.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-roles.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-toggle-field-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-valid-attr-value.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-valid-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/button-name.js +1 -1
- package/lighthouse-core/audits/accessibility/bypass.js +1 -1
- package/lighthouse-core/audits/accessibility/color-contrast.js +1 -1
- package/lighthouse-core/audits/accessibility/definition-list.js +1 -1
- package/lighthouse-core/audits/accessibility/dlitem.js +1 -1
- package/lighthouse-core/audits/accessibility/document-title.js +1 -1
- package/lighthouse-core/audits/accessibility/duplicate-id-active.js +1 -1
- package/lighthouse-core/audits/accessibility/duplicate-id-aria.js +1 -1
- package/lighthouse-core/audits/accessibility/form-field-multiple-labels.js +1 -1
- package/lighthouse-core/audits/accessibility/frame-title.js +1 -1
- package/lighthouse-core/audits/accessibility/heading-order.js +1 -1
- package/lighthouse-core/audits/accessibility/html-has-lang.js +1 -1
- package/lighthouse-core/audits/accessibility/html-lang-valid.js +1 -1
- package/lighthouse-core/audits/accessibility/image-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/input-image-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/label.js +1 -1
- package/lighthouse-core/audits/accessibility/link-name.js +1 -1
- package/lighthouse-core/audits/accessibility/list.js +1 -1
- package/lighthouse-core/audits/accessibility/listitem.js +5 -5
- package/lighthouse-core/audits/accessibility/meta-refresh.js +1 -1
- package/lighthouse-core/audits/accessibility/meta-viewport.js +1 -1
- package/lighthouse-core/audits/accessibility/object-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/tabindex.js +1 -1
- package/lighthouse-core/audits/accessibility/td-headers-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/th-has-data-cells.js +1 -1
- package/lighthouse-core/audits/accessibility/valid-lang.js +1 -1
- package/lighthouse-core/audits/accessibility/video-caption.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +12 -11
- package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +24 -22
- package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +3 -2
- package/lighthouse-core/audits/byte-efficiency/unminified-css.js +5 -3
- package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +11 -10
- package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -0
- package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +8 -11
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
- package/lighthouse-core/audits/deprecations.js +598 -8
- package/lighthouse-core/audits/diagnostics.js +3 -4
- package/lighthouse-core/audits/dobetterweb/doctype.js +9 -20
- package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +1 -1
- package/lighthouse-core/audits/dobetterweb/no-document-write.js +1 -1
- package/lighthouse-core/audits/dobetterweb/notification-on-start.js +1 -1
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -2
- package/lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js +1 -1
- package/lighthouse-core/audits/errors-in-console.js +2 -2
- package/lighthouse-core/audits/long-tasks.js +2 -3
- package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -2
- package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/interactive.js +2 -3
- package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -3
- package/lighthouse-core/audits/metrics/speed-index.js +2 -3
- package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -3
- package/lighthouse-core/audits/metrics.js +2 -3
- package/lighthouse-core/audits/no-unload-listeners.js +15 -7
- package/lighthouse-core/audits/predictive-perf.js +1 -2
- package/lighthouse-core/audits/preload-lcp-image.js +3 -3
- package/lighthouse-core/audits/redirects.js +1 -1
- package/lighthouse-core/audits/script-treemap-data.js +45 -45
- package/lighthouse-core/audits/seo/http-status-code.js +4 -2
- package/lighthouse-core/audits/seo/link-text.js +0 -2
- package/lighthouse-core/audits/server-response-time.js +17 -2
- package/lighthouse-core/audits/service-worker.js +2 -7
- package/lighthouse-core/audits/timing-budget.js +2 -3
- package/lighthouse-core/audits/uses-rel-preconnect.js +1 -1
- package/lighthouse-core/audits/uses-rel-preload.js +1 -1
- package/lighthouse-core/audits/valid-source-maps.js +14 -12
- package/lighthouse-core/audits/violation-audit.js +1 -1
- package/lighthouse-core/audits/work-during-interaction.js +2 -2
- package/lighthouse-core/computed/critical-request-chains.js +9 -5
- package/lighthouse-core/computed/js-bundles.js +11 -11
- package/lighthouse-core/computed/main-resource.js +2 -3
- package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
- package/lighthouse-core/computed/metrics/first-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/first-meaningful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/interactive.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-interactive.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-max-potential-fid.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-metric.js +5 -3
- package/lighthouse-core/computed/metrics/lantern-speed-index.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-total-blocking-time.js +1 -1
- package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
- package/lighthouse-core/computed/metrics/largest-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/max-potential-fid.js +1 -1
- package/lighthouse-core/computed/metrics/metric.js +0 -1
- package/lighthouse-core/computed/metrics/speed-index.js +1 -1
- package/lighthouse-core/computed/metrics/timing-summary.js +6 -13
- package/lighthouse-core/computed/metrics/total-blocking-time.js +1 -1
- package/lighthouse-core/computed/module-duplication.js +5 -6
- package/lighthouse-core/computed/page-dependency-graph.js +28 -55
- package/lighthouse-core/computed/resource-summary.js +5 -5
- package/lighthouse-core/computed/unused-css.js +7 -6
- package/lighthouse-core/computed/unused-javascript-summary.js +36 -16
- package/lighthouse-core/config/budget.js +2 -2
- package/lighthouse-core/config/default-config.js +1 -2
- package/lighthouse-core/fraggle-rock/api.js +1 -1
- package/lighthouse-core/fraggle-rock/config/default-config.js +0 -3
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +3 -6
- package/lighthouse-core/fraggle-rock/gather/driver.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +26 -51
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
- package/lighthouse-core/fraggle-rock/gather/session.js +22 -23
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -5
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +6 -6
- package/lighthouse-core/gather/connections/cri.js +1 -5
- package/lighthouse-core/gather/driver/execution-context.js +2 -5
- package/lighthouse-core/gather/driver/navigation.js +10 -13
- package/lighthouse-core/gather/driver/network-monitor.js +3 -16
- package/lighthouse-core/gather/driver.js +1 -6
- package/lighthouse-core/gather/fetcher.js +210 -34
- package/lighthouse-core/gather/gather-runner.js +17 -13
- package/lighthouse-core/gather/gatherers/accessibility.js +4 -16
- package/lighthouse-core/gather/gatherers/console-messages.js +2 -4
- package/lighthouse-core/gather/gatherers/dobetterweb/doctype.js +2 -4
- package/lighthouse-core/gather/gatherers/full-page-screenshot.js +2 -3
- package/lighthouse-core/gather/gatherers/iframe-elements.js +1 -4
- package/lighthouse-core/gather/gatherers/image-elements.js +0 -2
- package/lighthouse-core/gather/gatherers/js-usage.js +87 -12
- package/lighthouse-core/gather/gatherers/link-elements.js +14 -12
- package/lighthouse-core/gather/gatherers/main-document-content.js +8 -8
- package/lighthouse-core/gather/gatherers/script-elements.js +56 -7
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +30 -2
- package/lighthouse-core/gather/gatherers/source-maps.js +1 -8
- package/lighthouse-core/gather/gatherers/web-app-manifest.js +2 -2
- package/lighthouse-core/index.js +2 -26
- package/lighthouse-core/lib/cdt/generated/SourceMap.js +1 -1
- package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +29 -8
- package/lighthouse-core/lib/navigation-error.js +4 -13
- package/lighthouse-core/lib/page-functions.js +1 -3
- package/lighthouse-core/lib/script-helpers.js +6 -11
- package/lighthouse-core/lib/url-shim.js +2 -2
- package/lighthouse-core/runner.js +5 -0
- package/lighthouse-core/scripts/manual-chrome-launcher.js +1 -0
- package/lighthouse-core/util-commonjs.js +6 -8
- package/package.json +13 -13
- package/readme.md +1 -1
- package/report/.eslintrc.cjs +1 -3
- package/report/assets/styles.css +5 -10
- package/report/assets/templates.html +9 -10
- package/report/clients/bundle.js +1 -0
- package/report/clients/standalone.js +1 -0
- package/report/generator/report-generator.js +21 -46
- package/report/renderer/api.js +2 -0
- package/report/renderer/category-renderer.js +24 -20
- package/report/renderer/components.js +304 -303
- package/report/renderer/crc-details-renderer.js +24 -21
- package/report/renderer/details-renderer.js +12 -12
- package/report/renderer/dom.js +7 -6
- package/report/renderer/drop-down-menu.js +1 -0
- package/report/renderer/element-screenshot-renderer.js +5 -1
- package/report/renderer/features-util.js +1 -0
- package/report/renderer/i18n.js +62 -118
- package/report/renderer/logger.js +1 -0
- package/report/renderer/open-tab.js +3 -1
- package/report/renderer/performance-category-renderer.js +11 -10
- package/report/renderer/pwa-category-renderer.js +4 -3
- package/report/renderer/report-renderer.js +17 -17
- package/report/renderer/report-ui-features.js +1 -0
- package/report/renderer/snippet-renderer.js +3 -2
- package/report/renderer/swap-locale-feature.js +1 -0
- package/report/renderer/text-encoding.js +1 -0
- package/report/renderer/topbar-features.js +1 -0
- package/report/renderer/util.js +6 -7
- package/report/test/clients/bundle-test.js +5 -0
- package/report/test/generator/file-namer-test.js +1 -0
- package/report/test/generator/report-generator-test.js +20 -25
- package/report/test/renderer/category-renderer-test.js +4 -3
- package/report/test/renderer/components-test.js +3 -0
- package/report/test/renderer/crc-details-renderer-test.js +3 -0
- package/report/test/renderer/details-renderer-test.js +3 -49
- package/report/test/renderer/dom-test.js +3 -0
- package/report/test/renderer/element-screenshot-renderer-test.js +6 -3
- package/report/test/renderer/i18n-test.js +25 -70
- package/report/test/renderer/performance-category-renderer-test.js +5 -14
- package/report/test/renderer/pwa-category-renderer-test.js +4 -3
- package/report/test/renderer/report-renderer-axe-test.js +4 -3
- package/report/test/renderer/report-renderer-test.js +4 -3
- package/report/test/renderer/report-ui-features-test.js +4 -3
- package/report/test/renderer/snippet-renderer-test.js +3 -0
- package/report/test/renderer/text-encoding-test.js +3 -0
- package/report/test/renderer/util-test.js +5 -4
- package/report/test-assets/faux-psi.js +1 -2
- package/shared/localization/format.js +3 -7
- package/shared/localization/locales/en-US.json +238 -55
- package/shared/localization/locales/en-XL.json +238 -55
- package/shared/test/localization/format-test.js +2 -8
- package/shared/test/localization/locales-test.js +2 -0
- package/shared/test/localization/swap-locale-test.js +2 -0
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -0
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -0
- package/tsconfig.json +0 -1
- package/types/artifacts.d.ts +8 -47
- package/types/config.d.ts +0 -2
- package/types/externs.d.ts +2 -3
- package/types/gatherer.d.ts +2 -1
- package/types/global-lh.d.ts +0 -3
- package/types/lhr/lhr.d.ts +2 -2
- package/types/lhr/treemap.d.ts +1 -0
- package/changelog.md +0 -5902
- package/lighthouse-core/audits/script-elements-test-audit.js +0 -30
- package/lighthouse-core/gather/gatherers/scripts.js +0 -154
- package/lighthouse-core/scripts/package.json +0 -4
- package/report/test/.eslintrc.cjs +0 -11
- package/shared/test/localization/.eslintrc.cjs +0 -11
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
'use strict';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* @fileoverview This file contains helpers for constructing and rendering the
|
|
@@ -105,33 +106,34 @@ class CriticalRequestChainRenderer {
|
|
|
105
106
|
|
|
106
107
|
// Construct lines and add spacers for sub requests.
|
|
107
108
|
segment.treeMarkers.forEach(separator => {
|
|
108
|
-
|
|
109
|
-
'lh-tree-marker lh-vert'
|
|
110
|
-
'lh-tree-marker';
|
|
111
|
-
|
|
112
|
-
dom.createElement('span',
|
|
113
|
-
dom.createElement('span', 'lh-tree-marker')
|
|
114
|
-
|
|
109
|
+
if (separator) {
|
|
110
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-vert'));
|
|
111
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker'));
|
|
112
|
+
} else {
|
|
113
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker'));
|
|
114
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker'));
|
|
115
|
+
}
|
|
115
116
|
});
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
'lh-tree-marker lh-up-right'
|
|
119
|
-
'lh-tree-marker lh-
|
|
120
|
-
|
|
121
|
-
'lh-tree-marker lh-
|
|
122
|
-
'lh-tree-marker lh-right';
|
|
118
|
+
if (segment.isLastChild) {
|
|
119
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-up-right'));
|
|
120
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-right'));
|
|
121
|
+
} else {
|
|
122
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-vert-right'));
|
|
123
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-right'));
|
|
124
|
+
}
|
|
123
125
|
|
|
124
|
-
|
|
125
|
-
dom.createElement('span',
|
|
126
|
-
|
|
127
|
-
dom.createElement('span',
|
|
128
|
-
|
|
126
|
+
if (segment.hasChildren) {
|
|
127
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-horiz-down'));
|
|
128
|
+
} else {
|
|
129
|
+
treeMarkeEl.appendChild(dom.createElement('span', 'lh-tree-marker lh-right'));
|
|
130
|
+
}
|
|
129
131
|
|
|
130
132
|
// Fill in url, host, and request size information.
|
|
131
133
|
const url = segment.node.request.url;
|
|
132
134
|
const linkEl = detailsRenderer.renderTextURL(url);
|
|
133
135
|
const treevalEl = dom.find('.lh-crc-node__tree-value', chainEl);
|
|
134
|
-
treevalEl.
|
|
136
|
+
treevalEl.appendChild(linkEl);
|
|
135
137
|
|
|
136
138
|
if (!segment.hasChildren) {
|
|
137
139
|
const {startTime, endTime, transferSize} = segment.node.request;
|
|
@@ -140,7 +142,8 @@ class CriticalRequestChainRenderer {
|
|
|
140
142
|
const span2 = dom.createElement('span', 'lh-crc-node__chain-duration');
|
|
141
143
|
span2.textContent = Util.i18n.formatBytesToKiB(transferSize, 0.01);
|
|
142
144
|
|
|
143
|
-
treevalEl.
|
|
145
|
+
treevalEl.appendChild(span);
|
|
146
|
+
treevalEl.appendChild(span2);
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
return chainEl;
|
|
@@ -156,7 +159,7 @@ class CriticalRequestChainRenderer {
|
|
|
156
159
|
* @param {DetailsRenderer} detailsRenderer
|
|
157
160
|
*/
|
|
158
161
|
static buildTree(dom, tmpl, segment, elem, details, detailsRenderer) {
|
|
159
|
-
elem.
|
|
162
|
+
elem.appendChild(CRCRenderer.createChainNode(dom, segment, detailsRenderer));
|
|
160
163
|
if (segment.node.children) {
|
|
161
164
|
for (const key of Object.keys(segment.node.children)) {
|
|
162
165
|
const childSegment = CRCRenderer.createSegment(segment.node.children, key,
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
'use strict';
|
|
17
18
|
|
|
18
19
|
/** @typedef {import('./dom.js').DOM} DOM */
|
|
19
20
|
|
|
@@ -77,8 +78,9 @@ export class DetailsRenderer {
|
|
|
77
78
|
* @return {Element}
|
|
78
79
|
*/
|
|
79
80
|
_renderBytes(details) {
|
|
80
|
-
// TODO: handle displayUnit once we have something other than '
|
|
81
|
-
|
|
81
|
+
// TODO: handle displayUnit once we have something other than 'kb'
|
|
82
|
+
// Note that 'kb' is historical and actually represents KiB.
|
|
83
|
+
const value = Util.i18n.formatBytesToKiB(details.value, details.granularity);
|
|
82
84
|
const textEl = this._renderText(value);
|
|
83
85
|
textEl.title = Util.i18n.formatBytes(details.value);
|
|
84
86
|
return textEl;
|
|
@@ -89,11 +91,9 @@ export class DetailsRenderer {
|
|
|
89
91
|
* @return {Element}
|
|
90
92
|
*/
|
|
91
93
|
_renderMilliseconds(details) {
|
|
92
|
-
let value;
|
|
94
|
+
let value = Util.i18n.formatMilliseconds(details.value, details.granularity);
|
|
93
95
|
if (details.displayUnit === 'duration') {
|
|
94
96
|
value = Util.i18n.formatDuration(details.value);
|
|
95
|
-
} else {
|
|
96
|
-
value = Util.i18n.formatMilliseconds(details.value, details.granularity || 10);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
return this._renderText(value);
|
|
@@ -119,12 +119,12 @@ export class DetailsRenderer {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
const element = this._dom.createElement('div', 'lh-text__url');
|
|
122
|
-
element.
|
|
122
|
+
element.appendChild(this._renderLink({text: displayedPath, url}));
|
|
123
123
|
|
|
124
124
|
if (displayedHost) {
|
|
125
125
|
const hostElem = this._renderText(displayedHost);
|
|
126
126
|
hostElem.classList.add('lh-text__url-host');
|
|
127
|
-
element.
|
|
127
|
+
element.appendChild(hostElem);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
if (title) {
|
|
@@ -172,7 +172,7 @@ export class DetailsRenderer {
|
|
|
172
172
|
* @return {Element}
|
|
173
173
|
*/
|
|
174
174
|
_renderNumeric(details) {
|
|
175
|
-
const value = Util.i18n.formatNumber(details.value, details.granularity
|
|
175
|
+
const value = Util.i18n.formatNumber(details.value, details.granularity);
|
|
176
176
|
const element = this._dom.createElement('div', 'lh-numeric');
|
|
177
177
|
element.textContent = value;
|
|
178
178
|
return element;
|
|
@@ -397,7 +397,7 @@ export class DetailsRenderer {
|
|
|
397
397
|
|
|
398
398
|
if (valueElement) {
|
|
399
399
|
const classes = `lh-table-column--${heading.valueType}`;
|
|
400
|
-
this._dom.createChildOf(rowElem, 'td', classes).
|
|
400
|
+
this._dom.createChildOf(rowElem, 'td', classes).appendChild(valueElement);
|
|
401
401
|
} else {
|
|
402
402
|
// Empty cell is rendered for a column if:
|
|
403
403
|
// - the pair is null
|
|
@@ -452,7 +452,7 @@ export class DetailsRenderer {
|
|
|
452
452
|
const classes = `lh-table-column--${valueType}`;
|
|
453
453
|
const labelEl = this._dom.createElement('div', 'lh-text');
|
|
454
454
|
labelEl.textContent = heading.label;
|
|
455
|
-
this._dom.createChildOf(theadTrElem, 'th', classes).
|
|
455
|
+
this._dom.createChildOf(theadTrElem, 'th', classes).appendChild(labelEl);
|
|
456
456
|
}
|
|
457
457
|
|
|
458
458
|
const tbodyElem = this._dom.createChildOf(tableElem, 'tbody');
|
|
@@ -495,13 +495,13 @@ export class DetailsRenderer {
|
|
|
495
495
|
if (item.nodeLabel) {
|
|
496
496
|
const nodeLabelEl = this._dom.createElement('div');
|
|
497
497
|
nodeLabelEl.textContent = item.nodeLabel;
|
|
498
|
-
element.
|
|
498
|
+
element.appendChild(nodeLabelEl);
|
|
499
499
|
}
|
|
500
500
|
if (item.snippet) {
|
|
501
501
|
const snippetEl = this._dom.createElement('div');
|
|
502
502
|
snippetEl.classList.add('lh-node__snippet');
|
|
503
503
|
snippetEl.textContent = item.snippet;
|
|
504
|
-
element.
|
|
504
|
+
element.appendChild(snippetEl);
|
|
505
505
|
}
|
|
506
506
|
if (item.selector) {
|
|
507
507
|
element.title = item.selector;
|
package/report/renderer/dom.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
'use strict';
|
|
17
18
|
|
|
18
19
|
/* eslint-env browser */
|
|
19
20
|
|
|
@@ -97,7 +98,7 @@ export class DOM {
|
|
|
97
98
|
*/
|
|
98
99
|
createChildOf(parentElem, elementName, className) {
|
|
99
100
|
const element = this.createElement(elementName, className);
|
|
100
|
-
parentElem.
|
|
101
|
+
parentElem.appendChild(element);
|
|
101
102
|
return element;
|
|
102
103
|
}
|
|
103
104
|
|
|
@@ -135,7 +136,7 @@ export class DOM {
|
|
|
135
136
|
for (const segment of Util.splitMarkdownLink(text)) {
|
|
136
137
|
if (!segment.isLink) {
|
|
137
138
|
// Plain text segment.
|
|
138
|
-
element.
|
|
139
|
+
element.appendChild(this._document.createTextNode(segment.text));
|
|
139
140
|
continue;
|
|
140
141
|
}
|
|
141
142
|
|
|
@@ -153,7 +154,7 @@ export class DOM {
|
|
|
153
154
|
a.target = '_blank';
|
|
154
155
|
a.textContent = segment.text;
|
|
155
156
|
this.safelySetHref(a, url.href);
|
|
156
|
-
element.
|
|
157
|
+
element.appendChild(a);
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
return element;
|
|
@@ -210,9 +211,9 @@ export class DOM {
|
|
|
210
211
|
if (segment.isCode) {
|
|
211
212
|
const pre = this.createElement('code');
|
|
212
213
|
pre.textContent = segment.text;
|
|
213
|
-
element.
|
|
214
|
+
element.appendChild(pre);
|
|
214
215
|
} else {
|
|
215
|
-
element.
|
|
216
|
+
element.appendChild(this._document.createTextNode(segment.text));
|
|
216
217
|
}
|
|
217
218
|
}
|
|
218
219
|
|
|
@@ -295,7 +296,7 @@ export class DOM {
|
|
|
295
296
|
const a = this.createElement('a');
|
|
296
297
|
a.download = filename;
|
|
297
298
|
this.safelySetBlobHref(a, blob);
|
|
298
|
-
this._document.body.
|
|
299
|
+
this._document.body.appendChild(a); // Firefox requires anchor to be in the DOM.
|
|
299
300
|
a.click();
|
|
300
301
|
|
|
301
302
|
// cleanup.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
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
4
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
5
|
*/
|
|
6
|
+
'use strict';
|
|
6
7
|
|
|
7
8
|
/* eslint-env browser */
|
|
8
9
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
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
4
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
5
|
*/
|
|
6
|
+
'use strict';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @fileoverview These functions define {Rect}s and {Size}s using two different coordinate spaces:
|
|
@@ -186,7 +187,7 @@ export class ElementScreenshotRenderer {
|
|
|
186
187
|
overlay.remove();
|
|
187
188
|
return;
|
|
188
189
|
}
|
|
189
|
-
overlay.
|
|
190
|
+
overlay.appendChild(screenshotElement);
|
|
190
191
|
overlay.addEventListener('click', () => overlay.remove());
|
|
191
192
|
});
|
|
192
193
|
}
|
|
@@ -252,6 +253,9 @@ export class ElementScreenshotRenderer {
|
|
|
252
253
|
{width: screenshot.width, height: screenshot.height}
|
|
253
254
|
);
|
|
254
255
|
|
|
256
|
+
const contentEl = dom.find('div.lh-element-screenshot__content', containerEl);
|
|
257
|
+
contentEl.style.top = `-${elementPreviewSizeDC.height}px`;
|
|
258
|
+
|
|
255
259
|
const imageEl = dom.find('div.lh-element-screenshot__image', containerEl);
|
|
256
260
|
imageEl.style.width = elementPreviewSizeDC.width + 'px';
|
|
257
261
|
imageEl.style.height = elementPreviewSizeDC.height + 'px';
|
|
@@ -3,6 +3,7 @@
|
|
|
3
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
4
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
5
|
*/
|
|
6
|
+
'use strict';
|
|
6
7
|
|
|
7
8
|
/* eslint-env browser */
|
|
8
9
|
|
package/report/renderer/i18n.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
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
4
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
5
|
*/
|
|
6
|
+
'use strict';
|
|
6
7
|
|
|
7
8
|
// Not named `NBSP` because that creates a duplicate identifier (util.js).
|
|
8
9
|
const NBSP2 = '\xa0';
|
|
@@ -21,7 +22,9 @@ export class I18n {
|
|
|
21
22
|
// When testing, use a locale with more exciting numeric formatting.
|
|
22
23
|
if (locale === 'en-XA') locale = 'de';
|
|
23
24
|
|
|
24
|
-
this.
|
|
25
|
+
this._numberDateLocale = locale;
|
|
26
|
+
this._numberFormatter = new Intl.NumberFormat(locale);
|
|
27
|
+
this._percentFormatter = new Intl.NumberFormat(locale, {style: 'percent'});
|
|
25
28
|
this._strings = strings;
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -29,58 +32,15 @@ export class I18n {
|
|
|
29
32
|
return this._strings;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
/**
|
|
33
|
-
* @param {number} number
|
|
34
|
-
* @param {number|undefined} granularity
|
|
35
|
-
* @param {Intl.NumberFormatOptions=} opts
|
|
36
|
-
* @return {string}
|
|
37
|
-
*/
|
|
38
|
-
_formatNumberWithGranularity(number, granularity, opts = {}) {
|
|
39
|
-
if (granularity !== undefined) {
|
|
40
|
-
const log10 = -Math.log10(granularity);
|
|
41
|
-
if (!Number.isInteger(log10)) {
|
|
42
|
-
console.warn(`granularity of ${granularity} is invalid. Using 1 instead`);
|
|
43
|
-
granularity = 1;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (granularity < 1) {
|
|
47
|
-
opts = {...opts};
|
|
48
|
-
opts.minimumFractionDigits = opts.maximumFractionDigits = Math.ceil(log10);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
number = Math.round(number / granularity) * granularity;
|
|
52
|
-
|
|
53
|
-
// Avoid displaying a negative value that rounds to zero as "0".
|
|
54
|
-
if (Object.is(number, -0)) number = 0;
|
|
55
|
-
} else if (Math.abs(number) < 0.0005) {
|
|
56
|
-
// Also avoids "-0".
|
|
57
|
-
number = 0;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return new Intl.NumberFormat(this._locale, opts).format(number).replace(' ', NBSP2);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
35
|
/**
|
|
64
36
|
* Format number.
|
|
65
37
|
* @param {number} number
|
|
66
|
-
* @param {number=} granularity
|
|
67
|
-
* If undefined, the number will be displayed as described
|
|
68
|
-
* by the Intl defaults: tinyurl.com/7s67w5x7
|
|
69
|
-
* @return {string}
|
|
70
|
-
*/
|
|
71
|
-
formatNumber(number, granularity) {
|
|
72
|
-
return this._formatNumberWithGranularity(number, granularity);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Format integer.
|
|
77
|
-
* Just like {@link formatNumber} but uses a granularity of 1, rounding to the nearest
|
|
78
|
-
* whole number.
|
|
79
|
-
* @param {number} number
|
|
38
|
+
* @param {number=} granularity Number of decimal places to include. Defaults to 0.1.
|
|
80
39
|
* @return {string}
|
|
81
40
|
*/
|
|
82
|
-
|
|
83
|
-
|
|
41
|
+
formatNumber(number, granularity = 0.1) {
|
|
42
|
+
const coarseValue = Math.round(number / granularity) * granularity;
|
|
43
|
+
return this._numberFormatter.format(coarseValue);
|
|
84
44
|
}
|
|
85
45
|
|
|
86
46
|
/**
|
|
@@ -89,99 +49,92 @@ export class I18n {
|
|
|
89
49
|
* @return {string}
|
|
90
50
|
*/
|
|
91
51
|
formatPercent(number) {
|
|
92
|
-
return
|
|
52
|
+
return this._percentFormatter.format(number);
|
|
93
53
|
}
|
|
94
54
|
|
|
95
55
|
/**
|
|
96
56
|
* @param {number} size
|
|
97
|
-
* @param {number=} granularity Controls how coarse the displayed value is.
|
|
98
|
-
* If undefined, the number will be displayed in full.
|
|
57
|
+
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 0.1
|
|
99
58
|
* @return {string}
|
|
100
59
|
*/
|
|
101
|
-
formatBytesToKiB(size, granularity =
|
|
102
|
-
|
|
60
|
+
formatBytesToKiB(size, granularity = 0.1) {
|
|
61
|
+
const formatter = this._byteFormatterForGranularity(granularity);
|
|
62
|
+
const kbs = formatter.format(Math.round(size / 1024 / granularity) * granularity);
|
|
63
|
+
return `${kbs}${NBSP2}KiB`;
|
|
103
64
|
}
|
|
104
65
|
|
|
105
66
|
/**
|
|
106
67
|
* @param {number} size
|
|
107
|
-
* @param {number=} granularity Controls how coarse the displayed value is.
|
|
108
|
-
* If undefined, the number will be displayed in full.
|
|
68
|
+
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 0.1
|
|
109
69
|
* @return {string}
|
|
110
70
|
*/
|
|
111
|
-
formatBytesToMiB(size, granularity =
|
|
112
|
-
|
|
71
|
+
formatBytesToMiB(size, granularity = 0.1) {
|
|
72
|
+
const formatter = this._byteFormatterForGranularity(granularity);
|
|
73
|
+
const kbs = formatter.format(Math.round(size / (1024 ** 2) / granularity) * granularity);
|
|
74
|
+
return `${kbs}${NBSP2}MiB`;
|
|
113
75
|
}
|
|
114
76
|
|
|
115
77
|
/**
|
|
116
78
|
* @param {number} size
|
|
117
|
-
* @param {number=} granularity Controls how coarse the displayed value is
|
|
118
|
-
* If undefined, the number will be displayed in full.
|
|
79
|
+
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 1
|
|
119
80
|
* @return {string}
|
|
120
81
|
*/
|
|
121
82
|
formatBytes(size, granularity = 1) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
unitDisplay: 'long',
|
|
126
|
-
});
|
|
83
|
+
const formatter = this._byteFormatterForGranularity(granularity);
|
|
84
|
+
const kbs = formatter.format(Math.round(size / granularity) * granularity);
|
|
85
|
+
return `${kbs}${NBSP2}bytes`;
|
|
127
86
|
}
|
|
128
87
|
|
|
129
88
|
/**
|
|
130
89
|
* @param {number} size
|
|
131
|
-
* @param {number=} granularity Controls how coarse the displayed value is.
|
|
132
|
-
* If undefined, the number will be displayed in full.
|
|
90
|
+
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 0.1
|
|
133
91
|
* @return {string}
|
|
134
92
|
*/
|
|
135
|
-
formatBytesWithBestUnit(size, granularity =
|
|
93
|
+
formatBytesWithBestUnit(size, granularity = 0.1) {
|
|
136
94
|
if (size >= MiB) return this.formatBytesToMiB(size, granularity);
|
|
137
95
|
if (size >= KiB) return this.formatBytesToKiB(size, granularity);
|
|
138
|
-
return this.
|
|
139
|
-
style: 'unit',
|
|
140
|
-
unit: 'byte',
|
|
141
|
-
unitDisplay: 'narrow',
|
|
142
|
-
});
|
|
96
|
+
return this.formatNumber(size, granularity) + '\xa0B';
|
|
143
97
|
}
|
|
144
98
|
|
|
145
99
|
/**
|
|
146
|
-
*
|
|
147
|
-
* @param {number
|
|
148
|
-
*
|
|
149
|
-
* @return {string}
|
|
100
|
+
* Format bytes with a constant number of fractional digits, i.e. for a granularity of 0.1, 10 becomes '10.0'
|
|
101
|
+
* @param {number} granularity Controls how coarse the displayed value is
|
|
102
|
+
* @return {Intl.NumberFormat}
|
|
150
103
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
104
|
+
_byteFormatterForGranularity(granularity) {
|
|
105
|
+
// assume any granularity above 1 will not contain fractional parts, i.e. will never be 1.5
|
|
106
|
+
let numberOfFractionDigits = 0;
|
|
107
|
+
if (granularity < 1) {
|
|
108
|
+
numberOfFractionDigits = -Math.floor(Math.log10(granularity));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return new Intl.NumberFormat(this._numberDateLocale, {
|
|
112
|
+
...this._numberFormatter.resolvedOptions(),
|
|
113
|
+
maximumFractionDigits: numberOfFractionDigits,
|
|
114
|
+
minimumFractionDigits: numberOfFractionDigits,
|
|
156
115
|
});
|
|
157
116
|
}
|
|
158
117
|
|
|
159
118
|
/**
|
|
160
119
|
* @param {number} ms
|
|
161
|
-
* @param {number=} granularity Controls how coarse the displayed value is
|
|
162
|
-
* If undefined, the number will be displayed in full.
|
|
120
|
+
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 10
|
|
163
121
|
* @return {string}
|
|
164
122
|
*/
|
|
165
|
-
formatMilliseconds(ms, granularity =
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
});
|
|
123
|
+
formatMilliseconds(ms, granularity = 10) {
|
|
124
|
+
const coarseTime = Math.round(ms / granularity) * granularity;
|
|
125
|
+
return coarseTime === 0
|
|
126
|
+
? `${this._numberFormatter.format(0)}${NBSP2}ms`
|
|
127
|
+
: `${this._numberFormatter.format(coarseTime)}${NBSP2}ms`;
|
|
171
128
|
}
|
|
172
129
|
|
|
173
130
|
/**
|
|
174
131
|
* @param {number} ms
|
|
175
|
-
* @param {number=} granularity Controls how coarse the displayed value is.
|
|
176
|
-
* If undefined, the number will be displayed in full.
|
|
132
|
+
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 0.1
|
|
177
133
|
* @return {string}
|
|
178
134
|
*/
|
|
179
|
-
formatSeconds(ms, granularity =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
unit: 'second',
|
|
183
|
-
unitDisplay: 'short',
|
|
184
|
-
});
|
|
135
|
+
formatSeconds(ms, granularity = 0.1) {
|
|
136
|
+
const coarseTime = Math.round(ms / 1000 / granularity) * granularity;
|
|
137
|
+
return `${this._numberFormatter.format(coarseTime)}${NBSP2}s`;
|
|
185
138
|
}
|
|
186
139
|
|
|
187
140
|
/**
|
|
@@ -201,10 +154,10 @@ export class I18n {
|
|
|
201
154
|
// and https://github.com/GoogleChrome/lighthouse/pull/9822
|
|
202
155
|
let formatter;
|
|
203
156
|
try {
|
|
204
|
-
formatter = new Intl.DateTimeFormat(this.
|
|
157
|
+
formatter = new Intl.DateTimeFormat(this._numberDateLocale, options);
|
|
205
158
|
} catch (err) {
|
|
206
159
|
options.timeZone = 'UTC';
|
|
207
|
-
formatter = new Intl.DateTimeFormat(this.
|
|
160
|
+
formatter = new Intl.DateTimeFormat(this._numberDateLocale, options);
|
|
208
161
|
}
|
|
209
162
|
|
|
210
163
|
return formatter.format(new Date(date));
|
|
@@ -216,10 +169,6 @@ export class I18n {
|
|
|
216
169
|
* @return {string}
|
|
217
170
|
*/
|
|
218
171
|
formatDuration(timeInMilliseconds) {
|
|
219
|
-
// There is a proposal for a Intl.DurationFormat.
|
|
220
|
-
// https://github.com/tc39/proposal-intl-duration-format
|
|
221
|
-
// Until then, we do things a bit more manually.
|
|
222
|
-
|
|
223
172
|
let timeInSeconds = timeInMilliseconds / 1000;
|
|
224
173
|
if (Math.round(timeInSeconds) === 0) {
|
|
225
174
|
return 'None';
|
|
@@ -228,24 +177,19 @@ export class I18n {
|
|
|
228
177
|
/** @type {Array<string>} */
|
|
229
178
|
const parts = [];
|
|
230
179
|
/** @type {Record<string, number>} */
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
180
|
+
const unitLabels = {
|
|
181
|
+
d: 60 * 60 * 24,
|
|
182
|
+
h: 60 * 60,
|
|
183
|
+
m: 60,
|
|
184
|
+
s: 1,
|
|
236
185
|
};
|
|
237
186
|
|
|
238
|
-
Object.keys(
|
|
239
|
-
const
|
|
240
|
-
const numberOfUnits = Math.floor(timeInSeconds /
|
|
187
|
+
Object.keys(unitLabels).forEach(label => {
|
|
188
|
+
const unit = unitLabels[label];
|
|
189
|
+
const numberOfUnits = Math.floor(timeInSeconds / unit);
|
|
241
190
|
if (numberOfUnits > 0) {
|
|
242
|
-
timeInSeconds -= numberOfUnits *
|
|
243
|
-
|
|
244
|
-
style: 'unit',
|
|
245
|
-
unit,
|
|
246
|
-
unitDisplay: 'narrow',
|
|
247
|
-
});
|
|
248
|
-
parts.push(part);
|
|
191
|
+
timeInSeconds -= numberOfUnits * unit;
|
|
192
|
+
parts.push(`${numberOfUnits}\xa0${label}`);
|
|
249
193
|
}
|
|
250
194
|
});
|
|
251
195
|
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
'use strict';
|
|
17
18
|
|
|
18
19
|
import {TextEncoding} from './text-encoding.js';
|
|
19
20
|
|
|
@@ -37,7 +38,7 @@ function computeWindowNameSuffix(json) {
|
|
|
37
38
|
// @ts-expect-error - If this is a v2 LHR, use old `generatedTime`.
|
|
38
39
|
const fallbackFetchTime = /** @type {string} */ (json.generatedTime);
|
|
39
40
|
const fetchTime = json.fetchTime || fallbackFetchTime;
|
|
40
|
-
return `${json.lighthouseVersion}-${json.
|
|
41
|
+
return `${json.lighthouseVersion}-${json.requestedUrl}-${fetchTime}`;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
/**
|
|
@@ -119,6 +120,7 @@ function openTreemap(json) {
|
|
|
119
120
|
/** @type {LH.Treemap.Options} */
|
|
120
121
|
const treemapOptions = {
|
|
121
122
|
lhr: {
|
|
123
|
+
requestedUrl: json.requestedUrl,
|
|
122
124
|
finalUrl: json.finalUrl,
|
|
123
125
|
audits: {
|
|
124
126
|
'script-treemap-data': json.audits['script-treemap-data'],
|