lighthouse 11.1.0 → 11.2.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.
Files changed (557) hide show
  1. package/CONTRIBUTING.md +3 -5
  2. package/cli/bin.js +4 -3
  3. package/cli/cli-flags.js +3 -3
  4. package/cli/commands/commands.js +3 -3
  5. package/cli/commands/list-audits.js +3 -3
  6. package/cli/commands/list-locales.js +3 -3
  7. package/cli/commands/list-trace-categories.js +3 -3
  8. package/cli/index.js +3 -3
  9. package/cli/printer.js +3 -3
  10. package/cli/run.js +3 -3
  11. package/cli/sentry-prompt.js +3 -3
  12. package/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +8 -0
  13. package/cli/test/smokehouse/config/exclusions.d.ts +3 -3
  14. package/cli/test/smokehouse/config/exclusions.js +3 -3
  15. package/cli/test/smokehouse/core-tests.js +3 -3
  16. package/cli/test/smokehouse/frontends/back-compat-util.d.ts +3 -3
  17. package/cli/test/smokehouse/frontends/back-compat-util.js +3 -3
  18. package/cli/test/smokehouse/frontends/lib.js +3 -3
  19. package/cli/test/smokehouse/frontends/node.js +3 -3
  20. package/cli/test/smokehouse/frontends/smokehouse-bin.js +3 -3
  21. package/cli/test/smokehouse/lib/child-process-error.d.ts +3 -3
  22. package/cli/test/smokehouse/lib/child-process-error.js +3 -3
  23. package/cli/test/smokehouse/lib/concurrent-mapper.d.ts +3 -3
  24. package/cli/test/smokehouse/lib/concurrent-mapper.js +3 -3
  25. package/cli/test/smokehouse/lib/local-console.d.ts +3 -3
  26. package/cli/test/smokehouse/lib/local-console.js +3 -3
  27. package/cli/test/smokehouse/lighthouse-runners/bundle.js +3 -3
  28. package/cli/test/smokehouse/lighthouse-runners/cli.js +3 -3
  29. package/cli/test/smokehouse/lighthouse-runners/devtools.js +3 -3
  30. package/cli/test/smokehouse/report-assert-test.js +3 -3
  31. package/cli/test/smokehouse/report-assert.js +3 -3
  32. package/cli/test/smokehouse/smokehouse.d.ts +0 -1
  33. package/cli/test/smokehouse/smokehouse.js +12 -6
  34. package/cli/test/smokehouse/version-check-test.js +3 -3
  35. package/cli/test/smokehouse/version-check.js +3 -3
  36. package/commitlint.config.js +3 -3
  37. package/core/audits/accessibility/accesskeys.js +3 -3
  38. package/core/audits/accessibility/aria-allowed-attr.js +3 -3
  39. package/core/audits/accessibility/aria-allowed-role.js +3 -3
  40. package/core/audits/accessibility/aria-command-name.js +3 -3
  41. package/core/audits/accessibility/aria-dialog-name.js +3 -3
  42. package/core/audits/accessibility/aria-hidden-body.js +3 -3
  43. package/core/audits/accessibility/aria-hidden-focus.js +3 -3
  44. package/core/audits/accessibility/aria-input-field-name.js +3 -3
  45. package/core/audits/accessibility/aria-meter-name.js +3 -3
  46. package/core/audits/accessibility/aria-progressbar-name.js +3 -3
  47. package/core/audits/accessibility/aria-required-attr.js +3 -3
  48. package/core/audits/accessibility/aria-required-children.js +3 -3
  49. package/core/audits/accessibility/aria-required-parent.js +3 -3
  50. package/core/audits/accessibility/aria-roles.js +3 -3
  51. package/core/audits/accessibility/aria-text.js +3 -3
  52. package/core/audits/accessibility/aria-toggle-field-name.js +3 -3
  53. package/core/audits/accessibility/aria-tooltip-name.js +3 -3
  54. package/core/audits/accessibility/aria-treeitem-name.js +3 -3
  55. package/core/audits/accessibility/aria-valid-attr-value.js +3 -3
  56. package/core/audits/accessibility/aria-valid-attr.js +3 -3
  57. package/core/audits/accessibility/axe-audit.js +3 -3
  58. package/core/audits/accessibility/button-name.js +3 -3
  59. package/core/audits/accessibility/bypass.js +3 -3
  60. package/core/audits/accessibility/color-contrast.js +3 -3
  61. package/core/audits/accessibility/definition-list.js +3 -3
  62. package/core/audits/accessibility/dlitem.js +3 -3
  63. package/core/audits/accessibility/document-title.js +3 -3
  64. package/core/audits/accessibility/duplicate-id-active.js +3 -3
  65. package/core/audits/accessibility/duplicate-id-aria.js +3 -3
  66. package/core/audits/accessibility/empty-heading.js +3 -3
  67. package/core/audits/accessibility/form-field-multiple-labels.js +3 -3
  68. package/core/audits/accessibility/frame-title.js +3 -3
  69. package/core/audits/accessibility/heading-order.js +3 -3
  70. package/core/audits/accessibility/html-has-lang.js +3 -3
  71. package/core/audits/accessibility/html-lang-valid.js +3 -3
  72. package/core/audits/accessibility/html-xml-lang-mismatch.js +3 -3
  73. package/core/audits/accessibility/identical-links-same-purpose.js +3 -3
  74. package/core/audits/accessibility/image-alt.js +3 -3
  75. package/core/audits/accessibility/image-redundant-alt.js +3 -3
  76. package/core/audits/accessibility/input-button-name.js +3 -3
  77. package/core/audits/accessibility/input-image-alt.js +3 -3
  78. package/core/audits/accessibility/label-content-name-mismatch.js +3 -3
  79. package/core/audits/accessibility/label.js +3 -3
  80. package/core/audits/accessibility/landmark-one-main.js +3 -3
  81. package/core/audits/accessibility/link-in-text-block.js +3 -3
  82. package/core/audits/accessibility/link-name.js +3 -3
  83. package/core/audits/accessibility/list.js +3 -3
  84. package/core/audits/accessibility/listitem.js +3 -3
  85. package/core/audits/accessibility/manual/custom-controls-labels.js +3 -3
  86. package/core/audits/accessibility/manual/custom-controls-roles.js +3 -3
  87. package/core/audits/accessibility/manual/focus-traps.js +3 -3
  88. package/core/audits/accessibility/manual/focusable-controls.js +3 -3
  89. package/core/audits/accessibility/manual/interactive-element-affordance.js +3 -3
  90. package/core/audits/accessibility/manual/logical-tab-order.js +3 -3
  91. package/core/audits/accessibility/manual/managed-focus.js +3 -3
  92. package/core/audits/accessibility/manual/offscreen-content-hidden.js +3 -3
  93. package/core/audits/accessibility/manual/use-landmarks.js +3 -3
  94. package/core/audits/accessibility/manual/visual-order-follows-dom.js +3 -3
  95. package/core/audits/accessibility/meta-refresh.js +3 -3
  96. package/core/audits/accessibility/meta-viewport.js +3 -3
  97. package/core/audits/accessibility/object-alt.js +3 -3
  98. package/core/audits/accessibility/select-name.js +3 -3
  99. package/core/audits/accessibility/skip-link.js +3 -3
  100. package/core/audits/accessibility/tabindex.js +3 -3
  101. package/core/audits/accessibility/table-duplicate-name.js +3 -3
  102. package/core/audits/accessibility/table-fake-caption.js +3 -3
  103. package/core/audits/accessibility/target-size.js +3 -3
  104. package/core/audits/accessibility/td-has-header.js +3 -3
  105. package/core/audits/accessibility/td-headers-attr.js +3 -3
  106. package/core/audits/accessibility/th-has-data-cells.js +3 -3
  107. package/core/audits/accessibility/valid-lang.js +3 -3
  108. package/core/audits/accessibility/video-caption.js +3 -3
  109. package/core/audits/audit.js +24 -14
  110. package/core/audits/autocomplete.js +3 -3
  111. package/core/audits/bf-cache.js +4 -3
  112. package/core/audits/bootup-time.js +7 -4
  113. package/core/audits/byte-efficiency/byte-efficiency-audit.js +4 -4
  114. package/core/audits/byte-efficiency/duplicated-javascript.js +4 -4
  115. package/core/audits/byte-efficiency/efficient-animated-content.js +4 -4
  116. package/core/audits/byte-efficiency/legacy-javascript.js +4 -4
  117. package/core/audits/byte-efficiency/modern-image-formats.js +4 -4
  118. package/core/audits/byte-efficiency/offscreen-images.js +4 -4
  119. package/core/audits/byte-efficiency/render-blocking-resources.js +5 -6
  120. package/core/audits/byte-efficiency/total-byte-weight.js +6 -4
  121. package/core/audits/byte-efficiency/unminified-css.js +4 -4
  122. package/core/audits/byte-efficiency/unminified-javascript.js +4 -4
  123. package/core/audits/byte-efficiency/unused-css-rules.js +4 -4
  124. package/core/audits/byte-efficiency/unused-javascript.js +4 -4
  125. package/core/audits/byte-efficiency/uses-long-cache-ttl.js +6 -11
  126. package/core/audits/byte-efficiency/uses-optimized-images.js +4 -4
  127. package/core/audits/byte-efficiency/uses-responsive-images-snapshot.js +4 -3
  128. package/core/audits/byte-efficiency/uses-responsive-images.js +4 -4
  129. package/core/audits/byte-efficiency/uses-text-compression.js +4 -4
  130. package/core/audits/content-width.js +3 -3
  131. package/core/audits/critical-request-chains.js +3 -3
  132. package/core/audits/csp-xss.js +4 -4
  133. package/core/audits/deprecations.js +3 -3
  134. package/core/audits/diagnostics.js +3 -3
  135. package/core/audits/dobetterweb/charset.js +3 -3
  136. package/core/audits/dobetterweb/doctype.js +3 -3
  137. package/core/audits/dobetterweb/dom-size.js +6 -4
  138. package/core/audits/dobetterweb/geolocation-on-start.js +3 -3
  139. package/core/audits/dobetterweb/inspector-issues.js +3 -3
  140. package/core/audits/dobetterweb/js-libraries.js +3 -3
  141. package/core/audits/dobetterweb/no-document-write.js +4 -3
  142. package/core/audits/dobetterweb/notification-on-start.js +3 -3
  143. package/core/audits/dobetterweb/paste-preventing-inputs.js +3 -3
  144. package/core/audits/dobetterweb/uses-http2.js +5 -6
  145. package/core/audits/dobetterweb/uses-passive-event-listeners.js +4 -3
  146. package/core/audits/errors-in-console.js +3 -3
  147. package/core/audits/final-screenshot.js +3 -3
  148. package/core/audits/font-display.js +4 -3
  149. package/core/audits/image-aspect-ratio.js +3 -3
  150. package/core/audits/image-size-responsive.js +3 -3
  151. package/core/audits/installable-manifest.js +5 -5
  152. package/core/audits/is-on-https.js +3 -3
  153. package/core/audits/largest-contentful-paint-element.js +6 -5
  154. package/core/audits/layout-shift-elements.js +10 -7
  155. package/core/audits/lcp-lazy-loaded.js +4 -3
  156. package/core/audits/long-tasks.js +11 -4
  157. package/core/audits/main-thread-tasks.js +3 -3
  158. package/core/audits/mainthread-work-breakdown.js +26 -5
  159. package/core/audits/manual/manual-audit.js +3 -3
  160. package/core/audits/manual/pwa-cross-browser.js +3 -3
  161. package/core/audits/manual/pwa-each-page-has-url.js +3 -3
  162. package/core/audits/manual/pwa-page-transitions.js +3 -3
  163. package/core/audits/maskable-icon.js +3 -3
  164. package/core/audits/metrics/cumulative-layout-shift.js +7 -4
  165. package/core/audits/metrics/first-contentful-paint.js +4 -3
  166. package/core/audits/metrics/first-meaningful-paint.js +3 -3
  167. package/core/audits/metrics/interaction-to-next-paint.js +3 -3
  168. package/core/audits/metrics/interactive.js +3 -3
  169. package/core/audits/metrics/largest-contentful-paint.js +4 -3
  170. package/core/audits/metrics/max-potential-fid.js +3 -3
  171. package/core/audits/metrics/speed-index.js +4 -3
  172. package/core/audits/metrics/total-blocking-time.js +4 -3
  173. package/core/audits/metrics.js +3 -3
  174. package/core/audits/multi-check-audit.js +3 -3
  175. package/core/audits/network-requests.js +3 -3
  176. package/core/audits/network-rtt.js +3 -3
  177. package/core/audits/network-server-latency.js +3 -3
  178. package/core/audits/no-unload-listeners.js +3 -3
  179. package/core/audits/non-composited-animations.js +3 -3
  180. package/core/audits/oopif-iframe-test-audit.js +3 -3
  181. package/core/audits/performance-budget.js +3 -3
  182. package/core/audits/predictive-perf.js +3 -3
  183. package/core/audits/preload-fonts.js +3 -3
  184. package/core/audits/prioritize-lcp-image.js +5 -6
  185. package/core/audits/redirects.js +5 -6
  186. package/core/audits/screenshot-thumbnails.js +3 -3
  187. package/core/audits/script-elements-test-audit.js +3 -3
  188. package/core/audits/script-treemap-data.js +3 -3
  189. package/core/audits/seo/canonical.js +3 -3
  190. package/core/audits/seo/crawlable-anchors.js +3 -3
  191. package/core/audits/seo/font-size.js +3 -3
  192. package/core/audits/seo/hreflang.js +3 -3
  193. package/core/audits/seo/http-status-code.js +3 -3
  194. package/core/audits/seo/is-crawlable.js +3 -3
  195. package/core/audits/seo/link-text.js +3 -3
  196. package/core/audits/seo/manual/structured-data.js +3 -3
  197. package/core/audits/seo/meta-description.js +3 -3
  198. package/core/audits/seo/plugins.js +3 -3
  199. package/core/audits/seo/robots-txt.js +3 -3
  200. package/core/audits/seo/tap-targets.js +3 -3
  201. package/core/audits/server-response-time.js +5 -3
  202. package/core/audits/splash-screen.js +3 -3
  203. package/core/audits/themed-omnibox.js +3 -3
  204. package/core/audits/third-party-facades.js +4 -3
  205. package/core/audits/third-party-summary.js +8 -4
  206. package/core/audits/timing-budget.js +3 -3
  207. package/core/audits/unsized-images.js +4 -4
  208. package/core/audits/user-timings.js +3 -3
  209. package/core/audits/uses-rel-preconnect.js +5 -6
  210. package/core/audits/uses-rel-preload.js +5 -6
  211. package/core/audits/valid-source-maps.js +2 -3
  212. package/core/audits/viewport.js +4 -3
  213. package/core/audits/violation-audit.js +3 -3
  214. package/core/audits/work-during-interaction.js +9 -5
  215. package/core/computed/computed-artifact.js +3 -3
  216. package/core/computed/critical-request-chains.js +3 -3
  217. package/core/computed/document-urls.js +3 -3
  218. package/core/computed/entity-classification.js +3 -3
  219. package/core/computed/image-records.js +3 -3
  220. package/core/computed/js-bundles.js +3 -3
  221. package/core/computed/lcp-image-record.js +3 -3
  222. package/core/computed/load-simulator.js +3 -3
  223. package/core/computed/main-resource.js +3 -3
  224. package/core/computed/main-thread-tasks.js +3 -3
  225. package/core/computed/manifest-values.js +3 -3
  226. package/core/computed/metrics/cumulative-layout-shift.js +3 -3
  227. package/core/computed/metrics/first-contentful-paint-all-frames.js +3 -3
  228. package/core/computed/metrics/first-contentful-paint.js +3 -3
  229. package/core/computed/metrics/first-meaningful-paint.js +3 -3
  230. package/core/computed/metrics/interactive.js +3 -3
  231. package/core/computed/metrics/lantern-first-contentful-paint.js +3 -3
  232. package/core/computed/metrics/lantern-first-meaningful-paint.js +3 -3
  233. package/core/computed/metrics/lantern-interactive.js +3 -3
  234. package/core/computed/metrics/lantern-largest-contentful-paint.js +3 -3
  235. package/core/computed/metrics/lantern-max-potential-fid.js +3 -3
  236. package/core/computed/metrics/lantern-metric.js +3 -3
  237. package/core/computed/metrics/lantern-speed-index.js +3 -3
  238. package/core/computed/metrics/lantern-total-blocking-time.js +3 -3
  239. package/core/computed/metrics/largest-contentful-paint-all-frames.js +3 -3
  240. package/core/computed/metrics/largest-contentful-paint.js +3 -3
  241. package/core/computed/metrics/lcp-breakdown.js +3 -3
  242. package/core/computed/metrics/max-potential-fid.js +3 -3
  243. package/core/computed/metrics/metric.js +3 -3
  244. package/core/computed/metrics/navigation-metric.js +3 -3
  245. package/core/computed/metrics/responsiveness.js +3 -3
  246. package/core/computed/metrics/speed-index.js +3 -3
  247. package/core/computed/metrics/tbt-utils.d.ts +3 -3
  248. package/core/computed/metrics/tbt-utils.js +3 -3
  249. package/core/computed/metrics/time-to-first-byte.js +3 -3
  250. package/core/computed/metrics/timing-summary.js +3 -3
  251. package/core/computed/metrics/total-blocking-time.js +3 -3
  252. package/core/computed/module-duplication.js +3 -3
  253. package/core/computed/network-analysis.js +3 -3
  254. package/core/computed/network-records.js +3 -3
  255. package/core/computed/page-dependency-graph.js +4 -3
  256. package/core/computed/processed-navigation.js +3 -3
  257. package/core/computed/processed-trace.js +3 -3
  258. package/core/computed/resource-summary.js +3 -3
  259. package/core/computed/screenshots.js +3 -3
  260. package/core/computed/speedline.js +3 -3
  261. package/core/computed/tbt-impact-tasks.js +3 -3
  262. package/core/computed/unused-css.js +3 -3
  263. package/core/computed/unused-javascript-summary.js +2 -3
  264. package/core/computed/user-timings.js +3 -3
  265. package/core/computed/viewport-meta.js +3 -3
  266. package/core/config/budget.js +3 -3
  267. package/core/config/config-helpers.js +3 -3
  268. package/core/config/config-plugin.js +3 -3
  269. package/core/config/config.js +3 -3
  270. package/core/config/constants.d.ts +3 -3
  271. package/core/config/constants.js +3 -3
  272. package/core/config/default-config.js +3 -3
  273. package/core/config/desktop-config.js +3 -3
  274. package/core/config/experimental-config.d.ts +3 -3
  275. package/core/config/experimental-config.js +3 -3
  276. package/core/config/filters.js +3 -3
  277. package/core/config/full-config.d.ts +3 -3
  278. package/core/config/full-config.js +3 -3
  279. package/core/config/lr-desktop-config.js +3 -3
  280. package/core/config/lr-mobile-config.d.ts +3 -3
  281. package/core/config/lr-mobile-config.js +3 -3
  282. package/core/config/metrics-to-audits.d.ts +3 -3
  283. package/core/config/metrics-to-audits.js +3 -3
  284. package/core/config/perf-config.d.ts +3 -3
  285. package/core/config/perf-config.js +3 -3
  286. package/core/config/validation.js +3 -3
  287. package/core/gather/base-artifacts.js +3 -3
  288. package/core/gather/base-gatherer.js +3 -3
  289. package/core/gather/driver/dom.js +3 -3
  290. package/core/gather/driver/environment.js +3 -3
  291. package/core/gather/driver/execution-context.js +3 -3
  292. package/core/gather/driver/navigation.js +3 -3
  293. package/core/gather/driver/network-monitor.js +3 -3
  294. package/core/gather/driver/network.js +3 -3
  295. package/core/gather/driver/prepare.js +3 -3
  296. package/core/gather/driver/service-workers.d.ts +3 -3
  297. package/core/gather/driver/service-workers.js +3 -3
  298. package/core/gather/driver/storage.js +3 -3
  299. package/core/gather/driver/target-manager.d.ts +5 -0
  300. package/core/gather/driver/target-manager.js +21 -11
  301. package/core/gather/driver/wait-for-condition.js +3 -3
  302. package/core/gather/driver.js +3 -3
  303. package/core/gather/fetcher.js +2 -3
  304. package/core/gather/gatherers/accessibility.js +3 -3
  305. package/core/gather/gatherers/anchor-elements.js +3 -3
  306. package/core/gather/gatherers/bf-cache-failures.js +3 -3
  307. package/core/gather/gatherers/cache-contents.js +3 -3
  308. package/core/gather/gatherers/console-messages.js +3 -3
  309. package/core/gather/gatherers/css-usage.js +3 -3
  310. package/core/gather/gatherers/devtools-log-compat.js +3 -3
  311. package/core/gather/gatherers/devtools-log.js +3 -3
  312. package/core/gather/gatherers/dobetterweb/doctype.js +3 -3
  313. package/core/gather/gatherers/dobetterweb/domstats.js +3 -3
  314. package/core/gather/gatherers/dobetterweb/optimized-images.js +5 -5
  315. package/core/gather/gatherers/dobetterweb/response-compression.js +4 -4
  316. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +8 -3
  317. package/core/gather/gatherers/full-page-screenshot.js +2 -3
  318. package/core/gather/gatherers/global-listeners.js +3 -3
  319. package/core/gather/gatherers/iframe-elements.js +3 -3
  320. package/core/gather/gatherers/image-elements.js +3 -3
  321. package/core/gather/gatherers/inputs.js +3 -3
  322. package/core/gather/gatherers/inspector-issues.js +4 -3
  323. package/core/gather/gatherers/installability-errors.js +3 -3
  324. package/core/gather/gatherers/js-usage.js +3 -3
  325. package/core/gather/gatherers/link-elements.js +3 -3
  326. package/core/gather/gatherers/main-document-content.js +3 -3
  327. package/core/gather/gatherers/meta-elements.js +3 -3
  328. package/core/gather/gatherers/network-user-agent.js +3 -3
  329. package/core/gather/gatherers/script-elements.js +4 -4
  330. package/core/gather/gatherers/scripts.js +3 -3
  331. package/core/gather/gatherers/seo/embedded-content.js +3 -3
  332. package/core/gather/gatherers/seo/font-size.js +3 -3
  333. package/core/gather/gatherers/seo/robots-txt.js +3 -3
  334. package/core/gather/gatherers/seo/tap-targets.js +3 -3
  335. package/core/gather/gatherers/service-worker.js +3 -3
  336. package/core/gather/gatherers/source-maps.js +3 -3
  337. package/core/gather/gatherers/stacks.js +3 -3
  338. package/core/gather/gatherers/trace-compat.js +3 -3
  339. package/core/gather/gatherers/trace-elements.js +3 -3
  340. package/core/gather/gatherers/trace.js +3 -3
  341. package/core/gather/gatherers/viewport-dimensions.js +3 -3
  342. package/core/gather/gatherers/web-app-manifest.js +3 -3
  343. package/core/gather/navigation-runner.js +3 -3
  344. package/core/gather/runner-helpers.js +3 -3
  345. package/core/gather/session.js +5 -3
  346. package/core/gather/snapshot-runner.js +3 -3
  347. package/core/gather/timespan-runner.js +3 -3
  348. package/core/index.cjs +3 -3
  349. package/core/index.js +3 -3
  350. package/core/lib/arbitrary-equality-map.js +3 -3
  351. package/core/lib/asset-saver.d.ts +4 -4
  352. package/core/lib/asset-saver.js +17 -13
  353. package/core/lib/axe.js +3 -3
  354. package/core/lib/cdt/Common.js +3 -3
  355. package/core/lib/cdt/Platform.d.ts +3 -3
  356. package/core/lib/cdt/Platform.js +3 -3
  357. package/core/lib/cdt/SDK.js +3 -3
  358. package/core/lib/csp-evaluator.js +16 -16
  359. package/core/lib/dependency-graph/base-node.d.ts +3 -3
  360. package/core/lib/dependency-graph/base-node.js +3 -3
  361. package/core/lib/dependency-graph/cpu-node.js +3 -3
  362. package/core/lib/dependency-graph/network-node.js +3 -3
  363. package/core/lib/dependency-graph/simulator/connection-pool.js +3 -3
  364. package/core/lib/dependency-graph/simulator/dns-cache.js +3 -3
  365. package/core/lib/dependency-graph/simulator/network-analyzer.js +3 -3
  366. package/core/lib/dependency-graph/simulator/simulator-timing-map.js +3 -3
  367. package/core/lib/dependency-graph/simulator/simulator.js +3 -3
  368. package/core/lib/dependency-graph/simulator/tcp-connection.js +3 -3
  369. package/core/lib/deprecation-description.js +3 -3
  370. package/core/lib/emulation.js +3 -3
  371. package/core/lib/i18n/i18n.js +3 -3
  372. package/core/lib/icons.d.ts +3 -3
  373. package/core/lib/icons.js +3 -3
  374. package/core/lib/lantern-trace-saver.d.ts +3 -3
  375. package/core/lib/lantern-trace-saver.js +3 -3
  376. package/core/lib/lh-env.js +3 -3
  377. package/core/lib/lh-error.js +3 -3
  378. package/core/lib/lh-trace-processor.js +3 -3
  379. package/core/lib/lighthouse-compatibility.js +3 -3
  380. package/core/lib/manifest-parser.js +3 -3
  381. package/core/lib/median-run.js +3 -3
  382. package/core/lib/minification-estimator.js +3 -3
  383. package/core/lib/minify-devtoolslog.js +3 -3
  384. package/core/lib/navigation-error.js +3 -3
  385. package/core/lib/network-recorder.js +3 -3
  386. package/core/lib/network-request.js +3 -3
  387. package/core/lib/page-functions.js +3 -3
  388. package/core/lib/proto-preprocessor.js +3 -3
  389. package/core/lib/rect-helpers.d.ts +3 -3
  390. package/core/lib/rect-helpers.js +3 -3
  391. package/core/lib/script-helpers.d.ts +3 -3
  392. package/core/lib/script-helpers.js +3 -3
  393. package/core/lib/sentry.d.ts +2 -1
  394. package/core/lib/sentry.js +24 -18
  395. package/core/lib/stack-packs.js +3 -3
  396. package/core/lib/tappable-rects.js +3 -3
  397. package/core/lib/third-party-web.js +3 -3
  398. package/core/lib/timing-trace-saver.d.ts +3 -3
  399. package/core/lib/timing-trace-saver.js +3 -3
  400. package/core/lib/tracehouse/cpu-profile-model.js +3 -3
  401. package/core/lib/tracehouse/main-thread-tasks.js +3 -3
  402. package/core/lib/tracehouse/task-groups.d.ts +3 -3
  403. package/core/lib/tracehouse/task-groups.js +3 -3
  404. package/core/lib/tracehouse/task-summary.js +3 -3
  405. package/core/lib/tracehouse/trace-processor.js +3 -3
  406. package/core/lib/traces/metric-trace-events.js +3 -3
  407. package/core/lib/url-utils.js +3 -3
  408. package/core/runner.js +3 -3
  409. package/core/scoring.js +3 -3
  410. package/core/scripts/download-chrome.sh +2 -3
  411. package/core/user-flow.js +3 -3
  412. package/dist/report/bundle.esm.js +260 -175
  413. package/dist/report/flow.js +265 -181
  414. package/dist/report/standalone.js +261 -176
  415. package/flow-report/api.d.ts +3 -3
  416. package/flow-report/api.ts +3 -3
  417. package/flow-report/assets/standalone-flow-template.html +2 -13
  418. package/flow-report/assets/styles.css +3 -3
  419. package/flow-report/clients/standalone.d.ts +3 -3
  420. package/flow-report/clients/standalone.ts +3 -3
  421. package/flow-report/src/app.d.ts +3 -3
  422. package/flow-report/src/app.tsx +3 -3
  423. package/flow-report/src/common.d.ts +3 -3
  424. package/flow-report/src/common.tsx +3 -3
  425. package/flow-report/src/header.d.ts +3 -3
  426. package/flow-report/src/header.tsx +3 -3
  427. package/flow-report/src/help-dialog.d.ts +3 -3
  428. package/flow-report/src/help-dialog.tsx +3 -3
  429. package/flow-report/src/i18n/i18n.d.ts +3 -3
  430. package/flow-report/src/i18n/i18n.tsx +3 -3
  431. package/flow-report/src/i18n/localized-strings.d.ts +3 -3
  432. package/flow-report/src/i18n/localized-strings.js +3 -3
  433. package/flow-report/src/i18n/ui-strings.js +3 -3
  434. package/flow-report/src/icons.d.ts +3 -3
  435. package/flow-report/src/icons.tsx +3 -3
  436. package/flow-report/src/sidebar/flow.d.ts +3 -3
  437. package/flow-report/src/sidebar/flow.tsx +3 -3
  438. package/flow-report/src/sidebar/sidebar.d.ts +3 -3
  439. package/flow-report/src/sidebar/sidebar.tsx +3 -3
  440. package/flow-report/src/summary/category.d.ts +3 -3
  441. package/flow-report/src/summary/category.tsx +3 -3
  442. package/flow-report/src/summary/summary.d.ts +3 -3
  443. package/flow-report/src/summary/summary.tsx +3 -3
  444. package/flow-report/src/topbar.d.ts +3 -3
  445. package/flow-report/src/topbar.tsx +3 -3
  446. package/flow-report/src/util.d.ts +3 -3
  447. package/flow-report/src/util.ts +3 -3
  448. package/flow-report/src/wrappers/category-score.d.ts +3 -3
  449. package/flow-report/src/wrappers/category-score.tsx +3 -3
  450. package/flow-report/src/wrappers/markdown.d.ts +3 -3
  451. package/flow-report/src/wrappers/markdown.tsx +3 -3
  452. package/flow-report/src/wrappers/report.d.ts +3 -3
  453. package/flow-report/src/wrappers/report.tsx +3 -3
  454. package/flow-report/src/wrappers/styles.d.ts +3 -3
  455. package/flow-report/src/wrappers/styles.tsx +3 -3
  456. package/flow-report/types/flow-report.d.ts +3 -3
  457. package/package.json +11 -11
  458. package/readme.md +1 -1
  459. package/report/assets/standalone-template.html +2 -13
  460. package/report/assets/styles.css +231 -93
  461. package/report/assets/templates.html +24 -52
  462. package/report/clients/bundle.js +3 -3
  463. package/report/clients/standalone.js +3 -3
  464. package/report/generator/file-namer.js +3 -3
  465. package/report/generator/flow-report-assets.js +3 -3
  466. package/report/generator/report-assets.js +3 -3
  467. package/report/generator/report-generator.js +3 -3
  468. package/report/renderer/api.js +3 -3
  469. package/report/renderer/category-renderer.js +2 -13
  470. package/report/renderer/components.d.ts +2 -2
  471. package/report/renderer/components.js +35 -52
  472. package/report/renderer/crc-details-renderer.js +2 -13
  473. package/report/renderer/details-renderer.js +2 -13
  474. package/report/renderer/dom.d.ts +24 -4
  475. package/report/renderer/dom.js +32 -16
  476. package/report/renderer/drop-down-menu.d.ts +3 -3
  477. package/report/renderer/drop-down-menu.js +3 -3
  478. package/report/renderer/element-screenshot-renderer.js +3 -3
  479. package/report/renderer/explodey-gauge.d.ts +11 -0
  480. package/report/renderer/explodey-gauge.js +357 -0
  481. package/report/renderer/features-util.d.ts +3 -3
  482. package/report/renderer/features-util.js +3 -3
  483. package/report/renderer/i18n-formatter.js +3 -3
  484. package/report/renderer/logger.d.ts +2 -13
  485. package/report/renderer/logger.js +2 -13
  486. package/report/renderer/open-tab.js +2 -13
  487. package/report/renderer/performance-category-renderer.d.ts +16 -18
  488. package/report/renderer/performance-category-renderer.js +99 -115
  489. package/report/renderer/pwa-category-renderer.js +2 -13
  490. package/report/renderer/report-globals.js +3 -3
  491. package/report/renderer/report-renderer.js +2 -13
  492. package/report/renderer/report-ui-features.js +2 -13
  493. package/report/renderer/report-utils.js +3 -3
  494. package/report/renderer/snippet-renderer.js +3 -3
  495. package/report/renderer/swap-locale-feature.d.ts +3 -3
  496. package/report/renderer/swap-locale-feature.js +3 -3
  497. package/report/renderer/text-encoding.js +3 -3
  498. package/report/renderer/topbar-features.js +3 -3
  499. package/report/types/augment-dom.d.ts +3 -3
  500. package/report/types/buffer.d.ts +3 -3
  501. package/report/types/html-renderer.d.ts +3 -3
  502. package/report/types/report-renderer.d.ts +3 -3
  503. package/report/types/report-result.d.ts +3 -3
  504. package/shared/esm-utils.js +3 -3
  505. package/shared/localization/format.d.ts +21 -16
  506. package/shared/localization/format.js +76 -39
  507. package/shared/localization/i18n-module.js +2 -3
  508. package/shared/localization/locales/en-US.json +14 -14
  509. package/shared/localization/locales/en-XL.json +14 -14
  510. package/shared/localization/locales.js +3 -3
  511. package/shared/localization/swap-flow-locale.js +3 -3
  512. package/shared/localization/swap-locale.js +3 -3
  513. package/shared/root.js +3 -3
  514. package/{core/lib → shared}/statistics.js +3 -3
  515. package/shared/type-verifiers.d.ts +4 -4
  516. package/shared/type-verifiers.js +3 -3
  517. package/shared/types/shared.d.ts +3 -3
  518. package/shared/util.d.ts +22 -0
  519. package/shared/util.js +33 -13
  520. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +4 -3
  521. package/third-party/chromium-synchronization/installability-errors-test.js +3 -3
  522. package/third-party/download-content-shell/README.md +1 -1
  523. package/types/artifacts.d.ts +4 -3
  524. package/types/audit.d.ts +8 -4
  525. package/types/config.d.ts +3 -3
  526. package/types/externs.d.ts +3 -3
  527. package/types/gatherer.d.ts +3 -3
  528. package/types/internal/cssstyle.d.ts +3 -3
  529. package/types/internal/enquirer.d.ts +3 -3
  530. package/types/internal/global.d.ts +3 -3
  531. package/types/internal/http-link-header.d.ts +3 -3
  532. package/types/internal/lookup-closest-locale.d.ts +3 -3
  533. package/types/internal/metaviewport-parser.d.ts +3 -3
  534. package/types/internal/node.d.ts +3 -3
  535. package/types/internal/parse-cache-control.d.ts +3 -3
  536. package/types/internal/pretty-json-stringify.d.ts +3 -3
  537. package/types/internal/query-selector.d.ts +3 -3
  538. package/types/internal/rollup-plugin-postprocess.d.ts +3 -3
  539. package/types/internal/rxjs.d.ts +6 -3
  540. package/types/internal/smokehouse.d.ts +3 -3
  541. package/types/internal/test.d.ts +3 -3
  542. package/types/lh.d.ts +3 -3
  543. package/types/lh.js +3 -3
  544. package/types/lhr/audit-details.d.ts +3 -3
  545. package/types/lhr/audit-result.d.ts +19 -3
  546. package/types/lhr/budget.d.ts +3 -3
  547. package/types/lhr/flow-result.d.ts +3 -3
  548. package/types/lhr/i18n.d.ts +3 -3
  549. package/types/lhr/lhr.d.ts +3 -3
  550. package/types/lhr/settings.d.ts +3 -3
  551. package/types/lhr/treemap.d.ts +3 -3
  552. package/types/protocol.d.ts +3 -3
  553. package/types/puppeteer.d.ts +3 -3
  554. package/types/user-flow.d.ts +3 -3
  555. package/types/utility-types.d.ts +3 -3
  556. package/AUTHORS +0 -9
  557. /package/{core/lib → shared}/statistics.d.ts +0 -0
@@ -26,6 +26,13 @@ export class DOM {
26
26
  * @return {Element}
27
27
  */
28
28
  createElementNS(namespaceURI: string, name: string, className?: string | undefined): Element;
29
+ /**
30
+ * @template {string} T
31
+ * @param {T} name
32
+ * @param {string=} className
33
+ * @return {SVGElementByTagName[T]}
34
+ */
35
+ createSVGElement<T_1 extends string>(name: T_1, className?: string | undefined): SVGElementByTagName[T_1];
29
36
  /**
30
37
  * @return {!DocumentFragment}
31
38
  */
@@ -42,7 +49,7 @@ export class DOM {
42
49
  * @param {string=} className
43
50
  * @return {HTMLElementByTagName[T]}
44
51
  */
45
- createChildOf<T_1 extends string>(parentElem: Element, elementName: T_1, className?: string | undefined): HTMLElementByTagName[T_1];
52
+ createChildOf<T_2 extends string>(parentElem: Element, elementName: T_2, className?: string | undefined): HTMLElementByTagName[T_2];
46
53
  /**
47
54
  * @param {import('./components.js').ComponentName} componentName
48
55
  * @return {!DocumentFragment} A clone of the cached component.
@@ -92,21 +99,31 @@ export class DOM {
92
99
  */
93
100
  isDevTools(): boolean;
94
101
  /**
95
- * Guaranteed context.querySelector. Always returns an element or throws if
102
+ * Typed and guaranteed context.querySelector. Always returns an element or throws if
96
103
  * nothing matches query.
104
+ *
97
105
  * @template {string} T
98
106
  * @param {T} query
99
107
  * @param {ParentNode} context
100
108
  * @return {ParseSelector<T>}
101
109
  */
102
- find<T_2 extends string>(query: T_2, context: ParentNode): import("typed-query-selector/parser").ParseSelector<T_2, Element>;
110
+ find<T_3 extends string>(query: T_3, context: ParentNode): import("typed-query-selector/parser").ParseSelector<T_3, Element>;
111
+ /**
112
+ * Typed context.querySelector.
113
+ *
114
+ * @template {string} T
115
+ * @param {T} query
116
+ * @param {ParentNode} context
117
+ * @return {ParseSelector<T> | null}
118
+ */
119
+ maybeFind<T_4 extends string>(query: T_4, context: ParentNode): import("typed-query-selector/parser").ParseSelector<T_4, Element> | null;
103
120
  /**
104
121
  * Helper for context.querySelectorAll. Returns an Array instead of a NodeList.
105
122
  * @template {string} T
106
123
  * @param {T} query
107
124
  * @param {ParentNode} context
108
125
  */
109
- findAll<T_3 extends string>(query: T_3, context: ParentNode): import("../../types/internal/query-selector.js").QuerySelectorParse<T_3>[];
126
+ findAll<T_5 extends string>(query: T_5, context: ParentNode): import("../../types/internal/query-selector.js").QuerySelectorParse<T_5>[];
110
127
  /**
111
128
  * Fires a custom DOM event on target.
112
129
  * @param {string} name Name of the event.
@@ -124,5 +141,8 @@ export class DOM {
124
141
  export type HTMLElementByTagName = HTMLElementTagNameMap & {
125
142
  [id: string]: HTMLElement;
126
143
  };
144
+ export type SVGElementByTagName = SVGElementTagNameMap & {
145
+ [id: string]: SVGElement;
146
+ };
127
147
  export type ParseSelector<T extends string> = import('typed-query-selector/parser').ParseSelector<T, Element>;
128
148
  //# sourceMappingURL=dom.d.ts.map
@@ -1,23 +1,13 @@
1
1
  /**
2
2
  * @license
3
- * Copyright 2017 The Lighthouse Authors. All Rights Reserved.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS-IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
3
+ * Copyright 2017 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
16
5
  */
17
6
 
18
7
  /* eslint-env browser */
19
8
 
20
9
  /** @typedef {HTMLElementTagNameMap & {[id: string]: HTMLElement}} HTMLElementByTagName */
10
+ /** @typedef {SVGElementTagNameMap & {[id: string]: SVGElement}} SVGElementByTagName */
21
11
  /** @template {string} T @typedef {import('typed-query-selector/parser').ParseSelector<T, Element>} ParseSelector */
22
12
 
23
13
  import {Util} from '../../shared/util.js';
@@ -72,6 +62,17 @@ export class DOM {
72
62
  return element;
73
63
  }
74
64
 
65
+ /**
66
+ * @template {string} T
67
+ * @param {T} name
68
+ * @param {string=} className
69
+ * @return {SVGElementByTagName[T]}
70
+ */
71
+ createSVGElement(name, className) {
72
+ return /** @type {SVGElementByTagName[T]} */ (
73
+ this._document.createElementNS('http://www.w3.org/2000/svg', name, className));
74
+ }
75
+
75
76
  /**
76
77
  * @return {!DocumentFragment}
77
78
  */
@@ -250,23 +251,38 @@ export class DOM {
250
251
  }
251
252
 
252
253
  /**
253
- * Guaranteed context.querySelector. Always returns an element or throws if
254
+ * Typed and guaranteed context.querySelector. Always returns an element or throws if
254
255
  * nothing matches query.
256
+ *
255
257
  * @template {string} T
256
258
  * @param {T} query
257
259
  * @param {ParentNode} context
258
260
  * @return {ParseSelector<T>}
259
261
  */
260
262
  find(query, context) {
261
- const result = context.querySelector(query);
263
+ const result = this.maybeFind(query, context);
262
264
  if (result === null) {
263
265
  throw new Error(`query ${query} not found`);
264
266
  }
265
267
 
268
+ return result;
269
+ }
270
+
271
+ /**
272
+ * Typed context.querySelector.
273
+ *
274
+ * @template {string} T
275
+ * @param {T} query
276
+ * @param {ParentNode} context
277
+ * @return {ParseSelector<T> | null}
278
+ */
279
+ maybeFind(query, context) {
280
+ const result = context.querySelector(query);
281
+
266
282
  // Because we control the report layout and templates, use the simpler
267
283
  // `typed-query-selector` types that don't require differentiating between
268
284
  // e.g. HTMLAnchorElement and SVGAElement. See https://github.com/GoogleChrome/lighthouse/issues/12011
269
- return /** @type {ParseSelector<T>} */ (result);
285
+ return /** @type {ParseSelector<T> | null} */ (result);
270
286
  }
271
287
 
272
288
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2
+ * @license
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  /** @typedef {import('./dom.js').DOM} DOM */
7
7
  export class DropDownMenu {
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2
+ * @license
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
7
  /* eslint-env browser */
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @license Copyright 2020 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2
+ * @license
3
+ * Copyright 2020 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
7
  /**
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @param {import('./dom.js').DOM} dom
3
+ */
4
+ export function createGauge(dom: import('./dom.js').DOM): Element;
5
+ /**
6
+ * @param {import('./dom.js').DOM} dom
7
+ * @param {Element} componentEl
8
+ * @param {LH.ReportResult.Category} category
9
+ */
10
+ export function updateGauge(dom: import('./dom.js').DOM, componentEl: Element, category: LH.ReportResult.Category): void;
11
+ //# sourceMappingURL=explodey-gauge.d.ts.map
@@ -0,0 +1,357 @@
1
+ /**
2
+ * @license Copyright 2023 The Lighthouse Authors. All Rights Reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
+ */
6
+
7
+ /* eslint-env browser */
8
+ /* eslint-disable max-len */
9
+
10
+ import {ReportUtils} from './report-utils.js';
11
+
12
+ /**
13
+ * @param {import('./dom.js').DOM} dom
14
+ */
15
+ function createGauge(dom) {
16
+ const docFrag = dom.createComponent('explodeyGauge');
17
+ return dom.find('.lh-exp-gauge-component', docFrag);
18
+ }
19
+
20
+ /**
21
+ * @param {import('./dom.js').DOM} dom
22
+ * @param {Element} componentEl
23
+ * @param {LH.ReportResult.Category} category
24
+ */
25
+ function updateGauge(dom, componentEl, category) {
26
+ const wrapperEl = dom.find('div.lh-exp-gauge__wrapper', componentEl);
27
+ wrapperEl.className = '';
28
+ wrapperEl.classList.add('lh-exp-gauge__wrapper',
29
+ `lh-exp-gauge__wrapper--${ReportUtils.calculateRating(category.score)}`);
30
+ _setPerfGaugeExplodey(dom, wrapperEl, category);
31
+ }
32
+
33
+ /**
34
+ * @param {number} sizeSVG
35
+ * @param {number} percent
36
+ * @param {number=} strokeWidth
37
+ */
38
+ function _determineTrig(sizeSVG, percent, strokeWidth) {
39
+ strokeWidth = strokeWidth || sizeSVG / 32;
40
+
41
+ const radiusInner = sizeSVG / strokeWidth;
42
+ const strokeGap = 0.5 * strokeWidth;
43
+ const radiusOuter = radiusInner + strokeGap + strokeWidth;
44
+
45
+ const circumferenceInner = 2 * Math.PI * radiusInner;
46
+ // arc length we need to subtract
47
+ // for very small strokeWidth:radius ratios this is ≈ strokeWidth
48
+ // angle = acute angle of isosceles △ with 2 edges equal to radius & 3rd equal to strokeWidth
49
+ // angle formula given by law of cosines
50
+ const endDiffInner = Math.acos(1 - 0.5 * Math.pow((0.5 * strokeWidth) / radiusInner, 2)) * radiusInner;
51
+
52
+ const circumferenceOuter = 2 * Math.PI * radiusOuter;
53
+ const endDiffOuter = Math.acos(1 - 0.5 * Math.pow((0.5 * strokeWidth) / radiusOuter, 2)) * radiusOuter;
54
+
55
+ return {
56
+ radiusInner,
57
+ radiusOuter,
58
+ circumferenceInner,
59
+ circumferenceOuter,
60
+ getArcLength: () => Math.max(0, Number((percent * circumferenceInner))),
61
+ /**
62
+ * @param {number} weightingPct
63
+ * @param {boolean} isButt for metricArcHoverTarget
64
+ */
65
+ getMetricArcLength: (weightingPct, isButt = false) => {
66
+ // TODO: this math isn't perfect butt it's very close.
67
+ const linecapFactor = isButt ? 0 : 2 * endDiffOuter;
68
+ return Math.max(0, Number((weightingPct * circumferenceOuter - strokeGap - linecapFactor)));
69
+ },
70
+ endDiffInner,
71
+ endDiffOuter,
72
+ strokeWidth,
73
+ strokeGap,
74
+ };
75
+ }
76
+
77
+ /**
78
+ * @param {import('./dom.js').DOM} dom
79
+ * @param {HTMLElement} wrapperEl
80
+ * @param {LH.ReportResult.Category} category
81
+ */
82
+ function _setPerfGaugeExplodey(dom, wrapperEl, category) {
83
+ const sizeSVG = 128;
84
+ const offsetSVG = -0.5 * sizeSVG;
85
+
86
+ const percent = Number(category.score);
87
+ const {
88
+ radiusInner,
89
+ radiusOuter,
90
+ circumferenceInner,
91
+ circumferenceOuter,
92
+ getArcLength,
93
+ getMetricArcLength,
94
+ endDiffInner,
95
+ endDiffOuter,
96
+ strokeWidth,
97
+ strokeGap,
98
+ } = _determineTrig(sizeSVG, percent);
99
+
100
+ const SVG = dom.find('svg.lh-exp-gauge', wrapperEl);
101
+
102
+ dom.find('.lh-exp-gauge__label', SVG).textContent = category.title;
103
+
104
+ SVG.setAttribute('viewBox', [offsetSVG, offsetSVG / 2, sizeSVG, sizeSVG / 2].join(' '));
105
+ SVG.style.setProperty('--stroke-width', `${strokeWidth}px`);
106
+ SVG.style.setProperty('--circle-meas', (2 * Math.PI).toFixed(4));
107
+
108
+ const groupOuter = dom.find('g.lh-exp-gauge__outer', wrapperEl);
109
+ const groupInner = dom.find('g.lh-exp-gauge__inner', wrapperEl);
110
+ const cover = dom.find('circle.lh-cover', groupOuter);
111
+ const gaugeArc = dom.find('circle.lh-exp-gauge__arc', groupInner);
112
+ const gaugePerc = dom.find('text.lh-exp-gauge__percentage', groupInner);
113
+
114
+ groupOuter.style.setProperty('--scale-initial', String(radiusInner / radiusOuter));
115
+ groupOuter.style.setProperty('--radius', `${radiusOuter}px`);
116
+ cover.style.setProperty('--radius', `${0.5 * (radiusInner + radiusOuter)}px`);
117
+ cover.setAttribute('stroke-width', String(strokeGap));
118
+ SVG.style.setProperty('--radius', `${radiusInner}px`);
119
+
120
+ gaugeArc.setAttribute('stroke-dasharray',
121
+ `${getArcLength()} ${(circumferenceInner - getArcLength()).toFixed(4)}`);
122
+ gaugeArc.setAttribute('stroke-dashoffset', String(0.25 * circumferenceInner - endDiffInner));
123
+
124
+ gaugePerc.textContent = Math.round(percent * 100).toString();
125
+
126
+ const radiusTextOuter = radiusOuter + strokeWidth;
127
+ const radiusTextInner = radiusOuter - strokeWidth;
128
+
129
+ const metrics = category.auditRefs.filter(r => r.group === 'metrics' && r.weight);
130
+ const totalWeight = metrics.reduce((sum, each) => (sum += each.weight), 0);
131
+ let offsetAdder = 0.25 * circumferenceOuter - endDiffOuter - 0.5 * strokeGap;
132
+ let angleAdder = -0.5 * Math.PI;
133
+
134
+ // Extra hack on top of the HACK for element reuse below. Delete any metric elems that aren't needed anymore (happens when the same gauge goes from v5 to v6)
135
+ groupOuter.querySelectorAll('.metric').forEach(metricElem => {
136
+ const classNamesToRetain = metrics.map(metric => `metric--${metric.id}`);
137
+ const match = classNamesToRetain.find(selector => metricElem.classList.contains(selector));
138
+ if (!match) metricElem.remove();
139
+ });
140
+
141
+ metrics.forEach((metric, i) => {
142
+ const alias = metric.acronym ?? metric.id;
143
+
144
+ // Hack
145
+ const needsDomPopulation = !groupOuter.querySelector(`.metric--${alias}`);
146
+
147
+ // HACK:This isn't ideal but it was quick. Create element during initialization or reuse existing during updates
148
+ const metricGroup = dom.maybeFind(`g.metric--${alias}`, groupOuter) || dom.createSVGElement('g');
149
+ const metricArcMax = dom.maybeFind(`.metric--${alias} circle.lh-exp-gauge--faded`, groupOuter) || dom.createSVGElement('circle');
150
+ const metricArc = dom.maybeFind(`.metric--${alias} circle.lh-exp-gauge--miniarc`, groupOuter) || dom.createSVGElement('circle');
151
+ const metricArcHoverTarget = dom.maybeFind(`.metric--${alias} circle.lh-exp-gauge-hovertarget`, groupOuter) || dom.createSVGElement('circle');
152
+ const metricLabel = dom.maybeFind(`.metric--${alias} text.metric__label`, groupOuter) || dom.createSVGElement('text');
153
+ const metricValue = dom.maybeFind(`.metric--${alias} text.metric__value`, groupOuter) || dom.createSVGElement('text');
154
+
155
+ metricGroup.classList.add('metric', `metric--${alias}`);
156
+ metricArcMax.classList.add('lh-exp-gauge__arc', 'lh-exp-gauge__arc--metric', 'lh-exp-gauge--faded');
157
+ metricArc.classList.add('lh-exp-gauge__arc', 'lh-exp-gauge__arc--metric', 'lh-exp-gauge--miniarc');
158
+ metricArcHoverTarget.classList.add('lh-exp-gauge__arc', 'lh-exp-gauge__arc--metric', 'lh-exp-gauge-hovertarget');
159
+
160
+ const weightingPct = metric.weight / totalWeight;
161
+ const metricLengthMax = getMetricArcLength(weightingPct);
162
+ const metricPercent = metric.result.score ? metric.result.score * weightingPct : 0;
163
+ const metricLength = getMetricArcLength(metricPercent);
164
+ const metricOffset = weightingPct * circumferenceOuter;
165
+ const metricHoverLength = getMetricArcLength(weightingPct, true);
166
+ const rating = ReportUtils.calculateRating(metric.result.score, metric.result.scoreDisplayMode);
167
+
168
+ metricGroup.style.setProperty('--metric-rating', rating);
169
+ metricGroup.style.setProperty('--metric-color', `var(--color-${rating})`);
170
+ metricGroup.style.setProperty('--metric-offset', `${offsetAdder}`);
171
+ metricGroup.style.setProperty('--i', i.toString());
172
+
173
+ metricArcMax.setAttribute('stroke-dasharray', `${metricLengthMax} ${circumferenceOuter - metricLengthMax}`);
174
+ metricArc.style.setProperty('--metric-array', `${metricLength} ${circumferenceOuter - metricLength}`);
175
+ metricArcHoverTarget.setAttribute('stroke-dasharray', `${metricHoverLength} ${circumferenceOuter - metricHoverLength - endDiffOuter}`);
176
+
177
+ metricLabel.classList.add('metric__label');
178
+ metricValue.classList.add('metric__value');
179
+ metricLabel.textContent = alias;
180
+ metricValue.textContent = `+${Math.round(metricPercent * 100)}`;
181
+
182
+ const midAngle = angleAdder + weightingPct * Math.PI;
183
+ const cos = Math.cos(midAngle);
184
+ const sin = Math.sin(midAngle);
185
+
186
+ // only set non-default alignments
187
+ switch (true) {
188
+ case cos > 0:
189
+ metricValue.setAttribute('text-anchor', 'end');
190
+ break;
191
+ case cos < 0:
192
+ metricLabel.setAttribute('text-anchor', 'end');
193
+ break;
194
+ case cos === 0:
195
+ metricLabel.setAttribute('text-anchor', 'middle');
196
+ metricValue.setAttribute('text-anchor', 'middle');
197
+ break;
198
+ }
199
+
200
+ switch (true) {
201
+ case sin > 0:
202
+ metricLabel.setAttribute('dominant-baseline', 'hanging');
203
+ break;
204
+ case sin < 0:
205
+ metricValue.setAttribute('dominant-baseline', 'hanging');
206
+ break;
207
+ case sin === 0:
208
+ metricLabel.setAttribute('dominant-baseline', 'middle');
209
+ metricValue.setAttribute('dominant-baseline', 'middle');
210
+ break;
211
+ }
212
+
213
+ metricLabel.setAttribute('x', (radiusTextOuter * cos).toFixed(2));
214
+ metricLabel.setAttribute('y', (radiusTextOuter * sin).toFixed(2));
215
+ metricValue.setAttribute('x', (radiusTextInner * cos).toFixed(2));
216
+ metricValue.setAttribute('y', (radiusTextInner * sin).toFixed(2));
217
+
218
+ if (needsDomPopulation) {
219
+ metricGroup.appendChild(metricArcMax);
220
+ metricGroup.appendChild(metricArc);
221
+ metricGroup.appendChild(metricArcHoverTarget);
222
+ metricGroup.appendChild(metricLabel);
223
+ metricGroup.appendChild(metricValue);
224
+ groupOuter.appendChild(metricGroup);
225
+ }
226
+
227
+ offsetAdder -= metricOffset;
228
+ angleAdder += weightingPct * 2 * Math.PI;
229
+ });
230
+
231
+ // Catch pointerover movement between the hovertarget arcs. Without this the metric-highlights can clear when moving between.
232
+ const underHoverTarget = groupOuter.querySelector(`.lh-exp-gauge-underhovertarget`) || dom.createSVGElement('circle');
233
+ underHoverTarget.classList.add('lh-exp-gauge__arc', 'lh-exp-gauge__arc--metric', 'lh-exp-gauge-hovertarget', 'lh-exp-gauge-underhovertarget');
234
+ const underHoverLength = getMetricArcLength(1, true);
235
+ underHoverTarget.setAttribute('stroke-dasharray', `${underHoverLength} ${circumferenceOuter - underHoverLength - endDiffOuter}`);
236
+ if (!underHoverTarget.isConnected) {
237
+ groupOuter.prepend(underHoverTarget);
238
+ }
239
+
240
+ // Hack. Not ideal.
241
+ if (SVG.dataset.listenersSetup) return;
242
+ // @ts-expect-error
243
+ SVG.dataset.listenersSetup = true;
244
+
245
+ peekGauge(SVG);
246
+
247
+ /*
248
+ wrapperEl.state-expanded: gauge is exploded
249
+ wrapperEl.state-highlight: gauge is exploded and one of the metrics is being highlighted
250
+ metric.metric-highlight: highlight this particular metric
251
+ */
252
+ SVG.addEventListener('pointerover', e => {
253
+ // If hovering outside of the arcs, reset back to unexploded state
254
+ if (e.target === SVG && SVG.classList.contains('state--expanded')) {
255
+ SVG.classList.remove('state--expanded');
256
+
257
+ if (SVG.classList.contains('state--highlight')) {
258
+ SVG.classList.remove('state--highlight');
259
+ dom.find('.metric--highlight', SVG).classList.remove('metric--highlight');
260
+ }
261
+ return;
262
+ }
263
+
264
+ if (!(e.target instanceof Element)) {
265
+ return;
266
+ }
267
+
268
+ const parentEl = e.target.parentNode;
269
+ if (!(parentEl instanceof SVGElement)) {
270
+ return;
271
+ }
272
+
273
+ // if hovering on the primary (inner) part, then explode it but dont highlight
274
+ if (parentEl && parentEl === groupInner) {
275
+ if (!SVG.classList.contains('state--expanded')) SVG.classList.add('state--expanded');
276
+ else if (SVG.classList.contains('state--highlight')) {
277
+ SVG.classList.remove('state--highlight');
278
+ dom.find('.metric--highlight', SVG).classList.remove('metric--highlight');
279
+ }
280
+ return;
281
+ }
282
+
283
+ // if hovering on a metric, highlight that one.
284
+ // TODO: The hover target is a little small. ideally it's thicker.
285
+ if (parentEl && parentEl.classList && parentEl.classList.contains('metric')) {
286
+ // match the bg color of the gauge during a metric highlight
287
+ const metricRating = parentEl.style.getPropertyValue('--metric-rating');
288
+ wrapperEl.style.setProperty('--color-highlight', `var(--color-${metricRating}-secondary)`);
289
+
290
+ if (!SVG.classList.contains('state--highlight')) {
291
+ SVG.classList.add('state--highlight');
292
+ parentEl.classList.add('metric--highlight');
293
+ } else {
294
+ const highlightEl = dom.find('.metric--highlight', SVG);
295
+
296
+ if (parentEl !== highlightEl) {
297
+ highlightEl.classList.remove('metric--highlight');
298
+ parentEl.classList.add('metric--highlight');
299
+ console.log({highlightEl, parent: parentEl});
300
+ }
301
+ }
302
+ }
303
+ });
304
+
305
+ // clear on mouselave even if mousemove didn't catch it.
306
+ SVG.addEventListener('mouseleave', () => {
307
+ // SVG.classList.remove('state--expanded');
308
+ SVG.classList.remove('state--highlight');
309
+ const mh = SVG.querySelector('.metric--highlight');
310
+ mh?.classList.remove('metric--highlight');
311
+ });
312
+
313
+ /**
314
+ * On the first run, tease with a little peek reveal
315
+ * @param {SVGElement} SVG
316
+ */
317
+ async function peekGauge(SVG) {
318
+ // Delay just a tad to let the user aclimatize beforehand.
319
+ await new Promise(resolve => setTimeout(resolve, 1000));
320
+
321
+ // Early exit if it's already engaged
322
+ if (SVG.classList.contains('state--expanded')) return;
323
+
324
+ // To visually get the outer ring to peek on the edge, we need the inner ring on top. This is SVG's equivalent to `innerElem.zIndex = 100`
325
+ const inner = dom.find('.lh-exp-gauge__inner', SVG);
326
+ const id = `uniq-${Math.random()}`;
327
+ inner.setAttribute('id', id);
328
+ const useElem = dom.createSVGElement('use');
329
+ useElem.setAttribute('href', `#${id}`);
330
+ // for paint order this must come _after_ the outer.
331
+ SVG.appendChild(useElem);
332
+
333
+ const peekDurationSec = 2.5;
334
+ SVG.style.setProperty('--peek-dur', `${peekDurationSec}s`);
335
+ SVG.classList.add('state--peek', 'state--expanded');
336
+
337
+ // Fancy double cleanup
338
+ const cleanup = () => {
339
+ SVG.classList.remove('state--peek', 'state--expanded');
340
+ useElem.remove();
341
+ };
342
+ const tId = setTimeout(() => {
343
+ SVG.removeEventListener('mouseenter', handleEarlyInteraction);
344
+ cleanup();
345
+ }, peekDurationSec * 1000 * 1.5); // lil extra time just cuz
346
+ function handleEarlyInteraction() {
347
+ clearTimeout(tId);
348
+ cleanup();
349
+ }
350
+ SVG.addEventListener('mouseenter', handleEarlyInteraction, {once: true});
351
+ }
352
+ }
353
+
354
+ export {
355
+ createGauge,
356
+ updateGauge,
357
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2
+ * @license
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  /** @typedef {import('./dom.js').DOM} DOM */
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2
+ * @license
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
7
  /* eslint-env browser */
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @license Copyright 2020 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2
+ * @license
3
+ * Copyright 2020 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
7
  // Not named `NBSP` because that creates a duplicate identifier (util.js).
@@ -1,18 +1,7 @@
1
1
  /**
2
2
  * @license
3
- * Copyright 2017 The Lighthouse Authors. All Rights Reserved.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS-IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
3
+ * Copyright 2017 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
16
5
  */
17
6
  /**
18
7
  * Logs messages via a UI butter.
@@ -1,18 +1,7 @@
1
1
  /**
2
2
  * @license
3
- * Copyright 2017 The Lighthouse Authors. All Rights Reserved.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS-IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
3
+ * Copyright 2017 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
16
5
  */
17
6
 
18
7
  /**
@@ -1,18 +1,7 @@
1
1
  /**
2
2
  * @license
3
- * Copyright 2021 The Lighthouse Authors. All Rights Reserved.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS-IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
16
5
  */
17
6
 
18
7
  import {TextEncoding} from './text-encoding.js';