lighthouse 11.7.0 → 12.0.0-dev.20240422

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 (334) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/cli/bin.js +0 -7
  3. package/cli/cli-flags.d.ts +1 -5
  4. package/cli/cli-flags.js +4 -8
  5. package/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +14 -14
  6. package/cli/test/smokehouse/config/exclusions.js +3 -0
  7. package/cli/test/smokehouse/core-tests.js +6 -20
  8. package/cli/test/smokehouse/frontends/smokehouse-bin.js +2 -2
  9. package/core/audits/accessibility/accesskeys.js +1 -1
  10. package/core/audits/accessibility/aria-allowed-attr.js +1 -1
  11. package/core/audits/accessibility/aria-allowed-role.js +1 -1
  12. package/core/audits/accessibility/aria-command-name.js +1 -1
  13. package/core/audits/accessibility/aria-conditional-attr.d.ts +10 -0
  14. package/core/audits/accessibility/aria-conditional-attr.js +43 -0
  15. package/core/audits/accessibility/{duplicate-id-active.d.ts → aria-deprecated-role.d.ts} +3 -3
  16. package/core/audits/accessibility/aria-deprecated-role.js +43 -0
  17. package/core/audits/accessibility/aria-dialog-name.js +1 -1
  18. package/core/audits/accessibility/aria-hidden-body.js +1 -1
  19. package/core/audits/accessibility/aria-hidden-focus.js +1 -1
  20. package/core/audits/accessibility/aria-input-field-name.js +1 -1
  21. package/core/audits/accessibility/aria-meter-name.js +1 -1
  22. package/core/audits/accessibility/aria-progressbar-name.js +1 -1
  23. package/core/audits/accessibility/aria-prohibited-attr.d.ts +10 -0
  24. package/core/audits/accessibility/aria-prohibited-attr.js +44 -0
  25. package/core/audits/accessibility/aria-required-attr.js +1 -1
  26. package/core/audits/accessibility/aria-required-children.js +1 -1
  27. package/core/audits/accessibility/aria-required-parent.js +1 -1
  28. package/core/audits/accessibility/aria-roles.js +1 -1
  29. package/core/audits/accessibility/aria-text.js +1 -1
  30. package/core/audits/accessibility/aria-toggle-field-name.js +1 -1
  31. package/core/audits/accessibility/aria-tooltip-name.js +1 -1
  32. package/core/audits/accessibility/aria-treeitem-name.js +1 -1
  33. package/core/audits/accessibility/aria-valid-attr-value.js +1 -1
  34. package/core/audits/accessibility/aria-valid-attr.js +1 -1
  35. package/core/audits/accessibility/button-name.js +1 -1
  36. package/core/audits/accessibility/bypass.js +1 -1
  37. package/core/audits/accessibility/color-contrast.js +1 -1
  38. package/core/audits/accessibility/definition-list.js +1 -1
  39. package/core/audits/accessibility/dlitem.js +1 -1
  40. package/core/audits/accessibility/document-title.js +1 -1
  41. package/core/audits/accessibility/duplicate-id-aria.js +1 -1
  42. package/core/audits/accessibility/empty-heading.js +1 -1
  43. package/core/audits/accessibility/form-field-multiple-labels.js +1 -1
  44. package/core/audits/accessibility/frame-title.js +1 -1
  45. package/core/audits/accessibility/heading-order.js +1 -1
  46. package/core/audits/accessibility/html-has-lang.js +1 -1
  47. package/core/audits/accessibility/html-lang-valid.js +1 -1
  48. package/core/audits/accessibility/html-xml-lang-mismatch.js +1 -1
  49. package/core/audits/accessibility/identical-links-same-purpose.js +1 -1
  50. package/core/audits/accessibility/image-alt.js +1 -1
  51. package/core/audits/accessibility/image-redundant-alt.js +1 -1
  52. package/core/audits/accessibility/input-button-name.js +1 -1
  53. package/core/audits/accessibility/input-image-alt.js +1 -1
  54. package/core/audits/accessibility/label-content-name-mismatch.js +1 -1
  55. package/core/audits/accessibility/label.js +1 -1
  56. package/core/audits/accessibility/landmark-one-main.js +1 -1
  57. package/core/audits/accessibility/link-in-text-block.js +1 -1
  58. package/core/audits/accessibility/link-name.js +1 -1
  59. package/core/audits/accessibility/list.js +1 -1
  60. package/core/audits/accessibility/listitem.js +1 -1
  61. package/core/audits/accessibility/meta-refresh.js +1 -1
  62. package/core/audits/accessibility/meta-viewport.js +1 -1
  63. package/core/audits/accessibility/object-alt.js +1 -1
  64. package/core/audits/accessibility/select-name.js +1 -1
  65. package/core/audits/accessibility/skip-link.js +1 -1
  66. package/core/audits/accessibility/tabindex.js +1 -1
  67. package/core/audits/accessibility/table-duplicate-name.js +1 -1
  68. package/core/audits/accessibility/table-fake-caption.js +1 -1
  69. package/core/audits/accessibility/target-size.js +1 -2
  70. package/core/audits/accessibility/td-has-header.js +1 -1
  71. package/core/audits/accessibility/td-headers-attr.js +1 -1
  72. package/core/audits/accessibility/th-has-data-cells.js +1 -1
  73. package/core/audits/accessibility/valid-lang.js +1 -1
  74. package/core/audits/accessibility/video-caption.js +1 -1
  75. package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +0 -16
  76. package/core/audits/byte-efficiency/byte-efficiency-audit.js +1 -38
  77. package/core/audits/byte-efficiency/offscreen-images.d.ts +0 -11
  78. package/core/audits/byte-efficiency/offscreen-images.js +0 -15
  79. package/core/audits/byte-efficiency/render-blocking-resources.js +27 -26
  80. package/core/audits/byte-efficiency/unminified-css.js +2 -2
  81. package/core/audits/byte-efficiency/unused-css-rules.js +3 -1
  82. package/core/audits/dobetterweb/uses-http2.d.ts +0 -13
  83. package/core/audits/dobetterweb/uses-http2.js +4 -38
  84. package/core/audits/font-display.js +2 -2
  85. package/core/audits/layout-shifts.js +2 -2
  86. package/core/audits/preload-fonts.d.ts +1 -5
  87. package/core/audits/preload-fonts.js +1 -10
  88. package/core/audits/prioritize-lcp-image.js +2 -2
  89. package/core/audits/redirects-http.d.ts +19 -0
  90. package/core/audits/redirects-http.js +75 -0
  91. package/core/audits/resource-summary.d.ts +2 -0
  92. package/core/audits/resource-summary.js +5 -4
  93. package/core/audits/seo/is-crawlable.d.ts +2 -1
  94. package/core/audits/seo/link-text.js +12 -0
  95. package/core/audits/uses-rel-preload.d.ts +1 -5
  96. package/core/audits/uses-rel-preload.js +5 -15
  97. package/core/audits/work-during-interaction.d.ts +2 -2
  98. package/core/audits/work-during-interaction.js +2 -2
  99. package/core/computed/js-bundles.d.ts +1 -1
  100. package/core/computed/metrics/cumulative-layout-shift.js +2 -2
  101. package/core/computed/metrics/lantern-first-contentful-paint.d.ts +13 -82
  102. package/core/computed/metrics/lantern-first-contentful-paint.js +16 -178
  103. package/core/computed/metrics/lantern-first-meaningful-paint.d.ts +13 -12
  104. package/core/computed/metrics/lantern-first-meaningful-paint.js +11 -49
  105. package/core/computed/metrics/lantern-interactive.d.ts +13 -21
  106. package/core/computed/metrics/lantern-interactive.js +12 -84
  107. package/core/computed/metrics/lantern-largest-contentful-paint.d.ts +13 -25
  108. package/core/computed/metrics/lantern-largest-contentful-paint.js +13 -80
  109. package/core/computed/metrics/lantern-max-potential-fid.d.ts +13 -24
  110. package/core/computed/metrics/lantern-max-potential-fid.js +12 -64
  111. package/core/computed/metrics/lantern-metric.d.ts +14 -18
  112. package/core/computed/metrics/lantern-metric.js +34 -30
  113. package/core/computed/metrics/lantern-speed-index.d.ts +13 -32
  114. package/core/computed/metrics/lantern-speed-index.js +13 -116
  115. package/core/computed/metrics/lantern-total-blocking-time.d.ts +13 -25
  116. package/core/computed/metrics/lantern-total-blocking-time.js +10 -94
  117. package/core/computed/metrics/metric.js +1 -3
  118. package/core/computed/module-duplication.d.ts +1 -1
  119. package/core/computed/navigation-insights.d.ts +36 -0
  120. package/core/computed/navigation-insights.js +35 -0
  121. package/core/computed/page-dependency-graph.js +3 -7
  122. package/core/computed/resource-summary.d.ts +10 -12
  123. package/core/computed/resource-summary.js +12 -19
  124. package/core/computed/trace-engine-result.d.ts +16 -3
  125. package/core/computed/trace-engine-result.js +19 -14
  126. package/core/computed/unused-css.d.ts +3 -1
  127. package/core/computed/unused-css.js +6 -5
  128. package/core/config/config-helpers.js +0 -4
  129. package/core/config/constants.js +0 -1
  130. package/core/config/default-config.js +63 -142
  131. package/core/config/experimental-config.js +11 -0
  132. package/core/config/filters.js +0 -1
  133. package/core/gather/driver/navigation.js +4 -1
  134. package/core/gather/driver/prepare.js +1 -1
  135. package/core/gather/driver/target-manager.js +4 -3
  136. package/core/gather/driver/wait-for-condition.js +2 -3
  137. package/core/gather/driver.d.ts +12 -0
  138. package/core/gather/driver.js +27 -0
  139. package/core/gather/gatherers/accessibility.js +4 -6
  140. package/core/gather/gatherers/css-usage.d.ts +0 -21
  141. package/core/gather/gatherers/css-usage.js +9 -119
  142. package/core/gather/gatherers/root-causes.d.ts +2 -2
  143. package/core/gather/gatherers/root-causes.js +6 -5
  144. package/core/gather/gatherers/stylesheets.d.ts +26 -0
  145. package/core/gather/gatherers/stylesheets.js +138 -0
  146. package/core/gather/gatherers/trace-elements.d.ts +4 -13
  147. package/core/gather/gatherers/trace-elements.js +42 -31
  148. package/core/gather/navigation-runner.js +3 -1
  149. package/core/gather/session.d.ts +8 -0
  150. package/core/gather/session.js +14 -1
  151. package/core/lib/emulation.js +2 -2
  152. package/core/lib/i18n/i18n.d.ts +0 -1
  153. package/core/lib/i18n/i18n.js +0 -2
  154. package/core/lib/lantern/cpu-node.d.ts +7 -1
  155. package/core/lib/lantern/cpu-node.js +12 -2
  156. package/core/lib/lantern/lantern-error.d.ts +8 -0
  157. package/core/lib/lantern/lantern-error.js +9 -0
  158. package/core/lib/lantern/metric.js +2 -6
  159. package/core/lib/lantern/metrics/first-contentful-paint.d.ts +79 -0
  160. package/core/lib/lantern/metrics/first-contentful-paint.js +200 -0
  161. package/core/lib/lantern/metrics/first-meaningful-paint.d.ts +6 -0
  162. package/core/lib/lantern/metrics/first-meaningful-paint.js +64 -0
  163. package/core/lib/lantern/metrics/interactive.d.ts +26 -0
  164. package/core/lib/lantern/metrics/interactive.js +112 -0
  165. package/core/lib/lantern/metrics/largest-contentful-paint.d.ts +19 -0
  166. package/core/lib/lantern/metrics/largest-contentful-paint.js +108 -0
  167. package/core/lib/lantern/metrics/max-potential-fid.d.ts +30 -0
  168. package/core/lib/lantern/metrics/max-potential-fid.js +92 -0
  169. package/core/lib/lantern/metrics/speed-index.d.ts +38 -0
  170. package/core/lib/lantern/metrics/speed-index.js +144 -0
  171. package/core/lib/lantern/metrics/total-blocking-time.d.ts +31 -0
  172. package/core/lib/lantern/metrics/total-blocking-time.js +128 -0
  173. package/core/lib/lantern/network-node.js +28 -4
  174. package/core/lib/lantern/page-dependency-graph.d.ts +4 -4
  175. package/core/lib/lantern/page-dependency-graph.js +19 -7
  176. package/core/lib/lantern/simulator/connection-pool.d.ts +2 -12
  177. package/core/lib/lantern/simulator/connection-pool.js +3 -22
  178. package/core/lib/lantern/simulator/network-analyzer.js +1 -12
  179. package/core/lib/lantern/simulator/simulator.d.ts +2 -4
  180. package/core/lib/lantern/simulator/simulator.js +7 -14
  181. package/core/lib/lantern/types/lantern.d.ts +5 -3
  182. package/core/lib/lantern-trace-saver.js +0 -1
  183. package/core/lib/lh-error.d.ts +9 -0
  184. package/core/lib/lh-error.js +13 -3
  185. package/core/lib/lighthouse-compatibility.js +53 -10
  186. package/core/lib/navigation-error.js +3 -0
  187. package/core/lib/network-request.d.ts +1 -0
  188. package/core/lib/network-request.js +29 -1
  189. package/core/lib/proto-preprocessor.js +24 -8
  190. package/core/lib/tracehouse/trace-processor.js +15 -2
  191. package/core/runner.js +18 -25
  192. package/dist/report/bundle.esm.js +11 -112
  193. package/dist/report/flow.js +16 -117
  194. package/dist/report/standalone.js +12 -113
  195. package/flow-report/src/help-dialog.tsx +0 -1
  196. package/flow-report/src/i18n/i18n.d.ts +0 -4
  197. package/flow-report/src/i18n/ui-strings.d.ts +0 -1
  198. package/flow-report/src/i18n/ui-strings.js +0 -2
  199. package/flow-report/src/summary/category.tsx +10 -12
  200. package/package.json +7 -7
  201. package/readme.md +4 -4
  202. package/report/assets/styles.css +1 -60
  203. package/report/assets/templates.html +0 -95
  204. package/report/renderer/category-renderer.js +1 -1
  205. package/report/renderer/components.d.ts +2 -2
  206. package/report/renderer/components.js +2 -103
  207. package/report/renderer/dom.d.ts +1 -1
  208. package/report/renderer/dom.js +1 -1
  209. package/report/renderer/performance-category-renderer.d.ts +0 -7
  210. package/report/renderer/performance-category-renderer.js +1 -32
  211. package/report/renderer/report-renderer.js +3 -13
  212. package/report/renderer/report-ui-features.js +1 -1
  213. package/report/renderer/report-utils.d.ts +0 -1
  214. package/report/renderer/report-utils.js +13 -13
  215. package/shared/localization/locales/ar-XB.json +62 -329
  216. package/shared/localization/locales/ar.json +62 -329
  217. package/shared/localization/locales/bg.json +62 -329
  218. package/shared/localization/locales/ca.json +62 -329
  219. package/shared/localization/locales/cs.json +62 -329
  220. package/shared/localization/locales/da.json +62 -329
  221. package/shared/localization/locales/de.json +62 -329
  222. package/shared/localization/locales/el.json +62 -329
  223. package/shared/localization/locales/en-GB.json +62 -329
  224. package/shared/localization/locales/en-US.json +101 -332
  225. package/shared/localization/locales/en-XA.json +62 -329
  226. package/shared/localization/locales/en-XL.json +101 -332
  227. package/shared/localization/locales/es-419.json +62 -329
  228. package/shared/localization/locales/es.json +62 -329
  229. package/shared/localization/locales/fi.json +62 -329
  230. package/shared/localization/locales/fil.json +61 -328
  231. package/shared/localization/locales/fr.json +62 -329
  232. package/shared/localization/locales/he.json +62 -329
  233. package/shared/localization/locales/hi.json +62 -329
  234. package/shared/localization/locales/hr.json +63 -330
  235. package/shared/localization/locales/hu.json +62 -329
  236. package/shared/localization/locales/id.json +62 -329
  237. package/shared/localization/locales/it.json +62 -329
  238. package/shared/localization/locales/ja.json +62 -329
  239. package/shared/localization/locales/ko.json +62 -329
  240. package/shared/localization/locales/lt.json +62 -329
  241. package/shared/localization/locales/lv.json +62 -329
  242. package/shared/localization/locales/nl.json +62 -329
  243. package/shared/localization/locales/no.json +62 -329
  244. package/shared/localization/locales/pl.json +61 -328
  245. package/shared/localization/locales/pt-PT.json +62 -329
  246. package/shared/localization/locales/pt.json +64 -331
  247. package/shared/localization/locales/ro.json +62 -329
  248. package/shared/localization/locales/ru.json +62 -329
  249. package/shared/localization/locales/sk.json +62 -329
  250. package/shared/localization/locales/sl.json +62 -329
  251. package/shared/localization/locales/sr-Latn.json +62 -329
  252. package/shared/localization/locales/sr.json +62 -329
  253. package/shared/localization/locales/sv.json +62 -329
  254. package/shared/localization/locales/ta.json +61 -328
  255. package/shared/localization/locales/te.json +62 -329
  256. package/shared/localization/locales/th.json +62 -329
  257. package/shared/localization/locales/tr.json +62 -329
  258. package/shared/localization/locales/uk.json +62 -329
  259. package/shared/localization/locales/vi.json +61 -328
  260. package/shared/localization/locales/zh-HK.json +62 -329
  261. package/shared/localization/locales/zh-TW.json +61 -328
  262. package/shared/localization/locales/zh.json +62 -329
  263. package/tsconfig.json +1 -3
  264. package/types/artifacts.d.ts +21 -110
  265. package/types/audit.d.ts +0 -10
  266. package/types/config.d.ts +0 -1
  267. package/types/externs.d.ts +0 -2
  268. package/types/gatherer.d.ts +3 -0
  269. package/types/internal/smokehouse.d.ts +1 -1
  270. package/types/lh.d.ts +0 -2
  271. package/types/lhr/audit-details.d.ts +9 -4
  272. package/types/lhr/lhr.d.ts +0 -4
  273. package/types/lhr/settings.d.ts +0 -4
  274. package/core/audits/accessibility/duplicate-id-active.js +0 -42
  275. package/core/audits/content-width.d.ts +0 -17
  276. package/core/audits/content-width.js +0 -76
  277. package/core/audits/installable-manifest.d.ts +0 -111
  278. package/core/audits/installable-manifest.js +0 -248
  279. package/core/audits/layout-shift-elements.d.ts +0 -16
  280. package/core/audits/layout-shift-elements.js +0 -101
  281. package/core/audits/manual/pwa-cross-browser.d.ts +0 -12
  282. package/core/audits/manual/pwa-cross-browser.js +0 -40
  283. package/core/audits/manual/pwa-each-page-has-url.d.ts +0 -12
  284. package/core/audits/manual/pwa-each-page-has-url.js +0 -38
  285. package/core/audits/manual/pwa-page-transitions.d.ts +0 -12
  286. package/core/audits/manual/pwa-page-transitions.js +0 -38
  287. package/core/audits/maskable-icon.d.ts +0 -25
  288. package/core/audits/maskable-icon.js +0 -70
  289. package/core/audits/multi-check-audit.d.ts +0 -28
  290. package/core/audits/multi-check-audit.js +0 -82
  291. package/core/audits/no-unload-listeners.d.ts +0 -16
  292. package/core/audits/no-unload-listeners.js +0 -86
  293. package/core/audits/performance-budget.d.ts +0 -39
  294. package/core/audits/performance-budget.js +0 -154
  295. package/core/audits/script-elements-test-audit.d.ts +0 -14
  296. package/core/audits/script-elements-test-audit.js +0 -29
  297. package/core/audits/seo/plugins.d.ts +0 -15
  298. package/core/audits/seo/plugins.js +0 -150
  299. package/core/audits/seo/tap-targets.d.ts +0 -50
  300. package/core/audits/seo/tap-targets.js +0 -352
  301. package/core/audits/splash-screen.d.ts +0 -37
  302. package/core/audits/splash-screen.js +0 -98
  303. package/core/audits/themed-omnibox.d.ts +0 -42
  304. package/core/audits/themed-omnibox.js +0 -102
  305. package/core/audits/timing-budget.d.ts +0 -43
  306. package/core/audits/timing-budget.js +0 -175
  307. package/core/computed/manifest-values.d.ts +0 -24
  308. package/core/computed/manifest-values.js +0 -136
  309. package/core/config/budget.d.ts +0 -74
  310. package/core/config/budget.js +0 -340
  311. package/core/config/metrics-to-audits.d.ts +0 -19
  312. package/core/config/metrics-to-audits.js +0 -62
  313. package/core/gather/driver/service-workers.d.ts +0 -16
  314. package/core/gather/driver/service-workers.js +0 -52
  315. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +0 -47
  316. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +0 -233
  317. package/core/gather/gatherers/global-listeners.d.ts +0 -27
  318. package/core/gather/gatherers/global-listeners.js +0 -108
  319. package/core/gather/gatherers/installability-errors.d.ts +0 -17
  320. package/core/gather/gatherers/installability-errors.js +0 -56
  321. package/core/gather/gatherers/script-elements.d.ts +0 -21
  322. package/core/gather/gatherers/script-elements.js +0 -100
  323. package/core/gather/gatherers/seo/embedded-content.d.ts +0 -10
  324. package/core/gather/gatherers/seo/embedded-content.js +0 -63
  325. package/core/gather/gatherers/seo/tap-targets.d.ts +0 -21
  326. package/core/gather/gatherers/seo/tap-targets.js +0 -389
  327. package/core/gather/gatherers/service-worker.d.ts +0 -10
  328. package/core/gather/gatherers/service-worker.js +0 -32
  329. package/core/gather/gatherers/web-app-manifest.d.ts +0 -32
  330. package/core/gather/gatherers/web-app-manifest.js +0 -106
  331. package/report/renderer/pwa-category-renderer.d.ts +0 -55
  332. package/report/renderer/pwa-category-renderer.js +0 -184
  333. package/third-party/chromium-synchronization/installability-errors-test.js +0 -79
  334. package/types/lhr/budget.d.ts +0 -60
@@ -1,389 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2018 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /* global document, window, getComputedStyle, getElementsInDocument, Node, getNodeDetails, getRectCenterPoint */
8
-
9
- import BaseGatherer from '../../base-gatherer.js';
10
- import {pageFunctions} from '../../../lib/page-functions.js';
11
- import * as RectHelpers from '../../../lib/rect-helpers.js';
12
-
13
- const TARGET_SELECTORS = [
14
- 'button',
15
- 'a',
16
- 'input',
17
- 'textarea',
18
- 'select',
19
- 'option',
20
- '[role=button]',
21
- '[role=checkbox]',
22
- '[role=link]',
23
- '[role=menuitem]',
24
- '[role=menuitemcheckbox]',
25
- '[role=menuitemradio]',
26
- '[role=option]',
27
- '[role=scrollbar]',
28
- '[role=slider]',
29
- '[role=spinbutton]',
30
- ];
31
- const tapTargetsSelector = TARGET_SELECTORS.join(',');
32
-
33
- /**
34
- * @param {HTMLElement} element
35
- * @return {boolean}
36
- */
37
- /* c8 ignore start */
38
- function elementIsVisible(element) {
39
- return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
40
- }
41
- /* c8 ignore stop */
42
-
43
- /**
44
- * @param {Element} element
45
- * @return {LH.Artifacts.Rect[]}
46
- */
47
- /* c8 ignore start */
48
- function getClientRects(element) {
49
- const clientRects = Array.from(
50
- element.getClientRects()
51
- ).map(clientRect => {
52
- // Contents of DOMRect get lost when returned from Runtime.evaluate call,
53
- // so we convert them to plain objects.
54
- const {width, height, left, top, right, bottom} = clientRect;
55
- return {width, height, left, top, right, bottom};
56
- });
57
-
58
- for (const child of element.children) {
59
- clientRects.push(...getClientRects(child));
60
- }
61
-
62
- return clientRects;
63
- }
64
- /* c8 ignore stop */
65
-
66
- /**
67
- * @param {Element} element
68
- * @param {string} tapTargetsSelector
69
- * @return {boolean}
70
- */
71
- /* c8 ignore start */
72
- function elementHasAncestorTapTarget(element, tapTargetsSelector) {
73
- if (!element.parentElement) {
74
- return false;
75
- }
76
- if (element.parentElement.matches(tapTargetsSelector)) {
77
- return true;
78
- }
79
- return elementHasAncestorTapTarget(element.parentElement, tapTargetsSelector);
80
- }
81
- /* c8 ignore stop */
82
-
83
- /**
84
- * @param {Element} element
85
- */
86
- /* c8 ignore start */
87
- function hasTextNodeSiblingsFormingTextBlock(element) {
88
- if (!element.parentElement) {
89
- return false;
90
- }
91
-
92
- const parentElement = element.parentElement;
93
-
94
- const nodeText = element.textContent || '';
95
- const parentText = parentElement.textContent || '';
96
- if (parentText.length - nodeText.length < 5) {
97
- // Parent text mostly consists of this node, so the parent
98
- // is not a text block container
99
- return false;
100
- }
101
-
102
- for (const sibling of element.parentElement.childNodes) {
103
- if (sibling === element) {
104
- continue;
105
- }
106
- const siblingTextContent = (sibling.textContent || '').trim();
107
- // Only count text in text nodes so that a series of e.g. buttons isn't counted
108
- // as a text block.
109
- // This works reasonably well, but means we miss text blocks where all text is e.g.
110
- // wrapped in spans
111
- if (sibling.nodeType === Node.TEXT_NODE && siblingTextContent.length > 0) {
112
- return true;
113
- }
114
- }
115
-
116
- return false;
117
- }
118
- /* c8 ignore stop */
119
-
120
- /**
121
- * Check if element is in a block of text, such as paragraph with a bunch of links in it.
122
- * Makes a reasonable guess, but for example gets it wrong if the element is surrounded by other
123
- * HTML elements instead of direct text nodes.
124
- * @param {Element} element
125
- * @return {boolean}
126
- */
127
- /* c8 ignore start */
128
- function elementIsInTextBlock(element) {
129
- const {display} = getComputedStyle(element);
130
- if (display !== 'inline' && display !== 'inline-block') {
131
- return false;
132
- }
133
-
134
- if (hasTextNodeSiblingsFormingTextBlock(element)) {
135
- return true;
136
- } else if (element.parentElement) {
137
- return elementIsInTextBlock(element.parentElement);
138
- } else {
139
- return false;
140
- }
141
- }
142
- /* c8 ignore stop */
143
-
144
- /**
145
- * @param {Element} el
146
- * @param {{x: number, y: number}} elCenterPoint
147
- */
148
- /* c8 ignore start */
149
- function elementCenterIsAtZAxisTop(el, elCenterPoint) {
150
- const viewportHeight = window.innerHeight;
151
- const targetScrollY = Math.floor(elCenterPoint.y / viewportHeight) * viewportHeight;
152
- if (window.scrollY !== targetScrollY) {
153
- window.scrollTo(0, targetScrollY);
154
- }
155
-
156
- const topEl = document.elementFromPoint(
157
- elCenterPoint.x,
158
- elCenterPoint.y - window.scrollY
159
- );
160
-
161
- return topEl === el || el.contains(topEl);
162
- }
163
- /* c8 ignore stop */
164
-
165
- /**
166
- * Finds all position sticky/absolute elements on the page and adds a class
167
- * that disables pointer events on them.
168
- * @param {string} className
169
- * @return {() => void} - undo function to re-enable pointer events
170
- */
171
- /* c8 ignore start */
172
- function disableFixedAndStickyElementPointerEvents(className) {
173
- document.querySelectorAll('*').forEach(el => {
174
- const position = getComputedStyle(el).position;
175
- if (position === 'fixed' || position === 'sticky') {
176
- el.classList.add(className);
177
- }
178
- });
179
-
180
- return function undo() {
181
- Array.from(document.getElementsByClassName(className)).forEach(el => {
182
- el.classList.remove(className);
183
- });
184
- };
185
- }
186
- /* c8 ignore stop */
187
-
188
- /**
189
- * @param {string} tapTargetsSelector
190
- * @param {string} className
191
- * @return {LH.Artifacts.TapTarget[]}
192
- */
193
- /* c8 ignore start */
194
- function gatherTapTargets(tapTargetsSelector, className) {
195
- /** @type {LH.Artifacts.TapTarget[]} */
196
- const targets = [];
197
-
198
- // Capture element positions relative to the top of the page
199
- window.scrollTo(0, 0);
200
-
201
- /** @type {HTMLElement[]} */
202
- // @ts-expect-error - getElementsInDocument put into scope via stringification
203
- const tapTargetElements = getElementsInDocument(tapTargetsSelector);
204
-
205
- /** @type {{
206
- tapTargetElement: Element,
207
- clientRects: LH.Artifacts.Rect[]
208
- }[]} */
209
- const tapTargetsWithClientRects = [];
210
- tapTargetElements.forEach(tapTargetElement => {
211
- // Filter out tap targets that are likely to cause false failures:
212
- if (elementHasAncestorTapTarget(tapTargetElement, tapTargetsSelector)) {
213
- // This is usually intentional, either the tap targets trigger the same action
214
- // or there's a child with a related action (like a delete button for an item)
215
- return;
216
- }
217
- if (elementIsInTextBlock(tapTargetElement)) {
218
- // Links inside text blocks cause a lot of failures, and there's also an exception for them
219
- // in the Web Content Accessibility Guidelines https://www.w3.org/TR/WCAG21/#target-size
220
- return;
221
- }
222
- if (!elementIsVisible(tapTargetElement)) {
223
- return;
224
- }
225
-
226
- tapTargetsWithClientRects.push({
227
- tapTargetElement,
228
- clientRects: getClientRects(tapTargetElement),
229
- });
230
- });
231
-
232
- // Disable pointer events so that tap targets below them don't get
233
- // detected as non-tappable (they are tappable, just not while the viewport
234
- // is at the current scroll position)
235
- const reenableFixedAndStickyElementPointerEvents =
236
- disableFixedAndStickyElementPointerEvents(className);
237
-
238
- /** @type {{
239
- tapTargetElement: Element,
240
- visibleClientRects: LH.Artifacts.Rect[]
241
- }[]} */
242
- const tapTargetsWithVisibleClientRects = [];
243
- // We use separate loop here to get visible client rects because that involves
244
- // scrolling around the page for elementCenterIsAtZAxisTop, which would affect the
245
- // client rect positions.
246
- tapTargetsWithClientRects.forEach(({tapTargetElement, clientRects}) => {
247
- // Filter out empty client rects
248
- let visibleClientRects = clientRects.filter(cr => cr.width !== 0 && cr.height !== 0);
249
-
250
- // Filter out client rects that are invisible, e.g because they are in a position absolute element
251
- // with a lower z-index than the main content.
252
- // This will also filter out all position fixed or sticky tap targets elements because we disable pointer
253
- // events on them before running this. That's the correct behavior because whether a position fixed/stick
254
- // element overlaps with another tap target depends on the scroll position.
255
- visibleClientRects = visibleClientRects.filter(rect => {
256
- // Just checking the center can cause false failures for large partially hidden tap targets,
257
- // but that should be a rare edge case
258
- // @ts-expect-error - put into scope via stringification
259
- const rectCenterPoint = getRectCenterPoint(rect);
260
- return elementCenterIsAtZAxisTop(tapTargetElement, rectCenterPoint);
261
- });
262
-
263
- if (visibleClientRects.length > 0) {
264
- tapTargetsWithVisibleClientRects.push({
265
- tapTargetElement,
266
- visibleClientRects,
267
- });
268
- }
269
- });
270
-
271
- for (const {tapTargetElement, visibleClientRects} of tapTargetsWithVisibleClientRects) {
272
- targets.push({
273
- clientRects: visibleClientRects,
274
- href: /** @type {HTMLAnchorElement} */(tapTargetElement)['href'] || '',
275
- // @ts-expect-error - getNodeDetails put into scope via stringification
276
- node: getNodeDetails(tapTargetElement),
277
- });
278
- }
279
-
280
- reenableFixedAndStickyElementPointerEvents();
281
-
282
- return targets;
283
- }
284
-
285
- /**
286
- * @param {string} tapTargetsSelector
287
- * @param {string} className
288
- * @return {LH.Artifacts.TapTarget[]}
289
- */
290
- function gatherTapTargetsAndResetScroll(tapTargetsSelector, className) {
291
- const originalScrollPosition = {
292
- x: window.scrollX,
293
- y: window.scrollY,
294
- };
295
-
296
- try {
297
- return gatherTapTargets(tapTargetsSelector, className);
298
- } finally {
299
- window.scrollTo(originalScrollPosition.x, originalScrollPosition.y);
300
- }
301
- }
302
- /* c8 ignore stop */
303
-
304
- class TapTargets extends BaseGatherer {
305
- constructor() {
306
- super();
307
- /**
308
- * This needs to be in the constructor.
309
- * https://github.com/GoogleChrome/lighthouse/issues/12134
310
- * @type {LH.Gatherer.GathererMeta}
311
- */
312
- this.meta = {
313
- supportedModes: ['snapshot', 'navigation'],
314
- };
315
- }
316
-
317
- /**
318
- * @param {LH.Gatherer.ProtocolSession} session
319
- * @param {string} className
320
- * @return {Promise<string>}
321
- */
322
- async addStyleRule(session, className) {
323
- const frameTreeResponse = await session.sendCommand('Page.getFrameTree');
324
- const {styleSheetId} = await session.sendCommand('CSS.createStyleSheet', {
325
- frameId: frameTreeResponse.frameTree.frame.id,
326
- });
327
- const ruleText = `.${className} { pointer-events: none !important }`;
328
- await session.sendCommand('CSS.setStyleSheetText', {
329
- styleSheetId,
330
- text: ruleText,
331
- });
332
- return styleSheetId;
333
- }
334
-
335
- /**
336
- * @param {LH.Gatherer.ProtocolSession} session
337
- * @param {string} styleSheetId
338
- */
339
- async removeStyleRule(session, styleSheetId) {
340
- await session.sendCommand('CSS.setStyleSheetText', {
341
- styleSheetId,
342
- text: '',
343
- });
344
- }
345
-
346
- /**
347
- * @param {LH.Gatherer.Context} passContext
348
- * @return {Promise<LH.Artifacts.TapTarget[]>} All visible tap targets with their positions and sizes
349
- */
350
- async getArtifact(passContext) {
351
- const session = passContext.driver.defaultSession;
352
- await session.sendCommand('DOM.enable');
353
- await session.sendCommand('CSS.enable');
354
-
355
- const className = 'lighthouse-disable-pointer-events';
356
- const styleSheetId = await this.addStyleRule(session, className);
357
-
358
- const tapTargets =
359
- await passContext.driver.executionContext.evaluate(gatherTapTargetsAndResetScroll, {
360
- args: [tapTargetsSelector, className],
361
- useIsolation: true,
362
- deps: [
363
- pageFunctions.getNodeDetails,
364
- pageFunctions.getElementsInDocument,
365
- disableFixedAndStickyElementPointerEvents,
366
- elementIsVisible,
367
- elementHasAncestorTapTarget,
368
- elementCenterIsAtZAxisTop,
369
- getClientRects,
370
- hasTextNodeSiblingsFormingTextBlock,
371
- elementIsInTextBlock,
372
- RectHelpers.getRectCenterPoint,
373
- pageFunctions.getNodePath,
374
- pageFunctions.getNodeSelector,
375
- pageFunctions.getNodeLabel,
376
- gatherTapTargets,
377
- ],
378
- });
379
-
380
- await this.removeStyleRule(session, styleSheetId);
381
-
382
- await session.sendCommand('CSS.disable');
383
- await session.sendCommand('DOM.disable');
384
-
385
- return tapTargets;
386
- }
387
- }
388
-
389
- export default TapTargets;
@@ -1,10 +0,0 @@
1
- export default ServiceWorker;
2
- declare class ServiceWorker extends BaseGatherer {
3
- /**
4
- * @param {LH.Gatherer.Context} context
5
- * @return {Promise<LH.Artifacts['ServiceWorker']>}
6
- */
7
- getArtifact(context: LH.Gatherer.Context): Promise<LH.Artifacts['ServiceWorker']>;
8
- }
9
- import BaseGatherer from '../base-gatherer.js';
10
- //# sourceMappingURL=service-worker.d.ts.map
@@ -1,32 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import BaseGatherer from '../base-gatherer.js';
8
- import * as serviceWorkers from '../driver/service-workers.js';
9
-
10
- class ServiceWorker extends BaseGatherer {
11
- /** @type {LH.Gatherer.GathererMeta} */
12
- meta = {
13
- supportedModes: ['navigation'],
14
- };
15
-
16
- /**
17
- * @param {LH.Gatherer.Context} context
18
- * @return {Promise<LH.Artifacts['ServiceWorker']>}
19
- */
20
- async getArtifact(context) {
21
- const session = context.driver.defaultSession;
22
- const {versions} = await serviceWorkers.getServiceWorkerVersions(session);
23
- const {registrations} = await serviceWorkers.getServiceWorkerRegistrations(session);
24
-
25
- return {
26
- versions,
27
- registrations,
28
- };
29
- }
30
- }
31
-
32
- export default ServiceWorker;
@@ -1,32 +0,0 @@
1
- export default WebAppManifest;
2
- declare class WebAppManifest extends BaseGatherer {
3
- /**
4
- * @param {LH.Gatherer.ProtocolSession} session
5
- * @return {Promise<{url: string, data: string}|null>}
6
- */
7
- static fetchAppManifest(session: LH.Gatherer.ProtocolSession): Promise<{
8
- url: string;
9
- data: string;
10
- } | null>;
11
- /**
12
- * Uses the debugger protocol to fetch the manifest from within the context of
13
- * the target page, reusing any credentials, emulation, etc, already established
14
- * there.
15
- *
16
- * Returns the parsed manifest or null if the page had no manifest. If the manifest
17
- * was unparseable as JSON, manifest.value will be undefined and manifest.warning
18
- * will have the reason. See manifest-parser.js for more information.
19
- *
20
- * @param {LH.Gatherer.ProtocolSession} session
21
- * @param {string} pageUrl
22
- * @return {Promise<LH.Artifacts.Manifest|null>}
23
- */
24
- static getWebAppManifest(session: LH.Gatherer.ProtocolSession, pageUrl: string): Promise<LH.Artifacts.Manifest | null>;
25
- /**
26
- * @param {LH.Gatherer.Context} context
27
- * @return {Promise<LH.Artifacts['WebAppManifest']>}
28
- */
29
- getArtifact(context: LH.Gatherer.Context): Promise<LH.Artifacts['WebAppManifest']>;
30
- }
31
- import BaseGatherer from '../base-gatherer.js';
32
- //# sourceMappingURL=web-app-manifest.d.ts.map
@@ -1,106 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import log from 'lighthouse-logger';
8
-
9
- import {parseManifest} from '../../lib/manifest-parser.js';
10
- import BaseGatherer from '../base-gatherer.js';
11
-
12
- class WebAppManifest extends BaseGatherer {
13
- /** @type {LH.Gatherer.GathererMeta} */
14
- meta = {
15
- supportedModes: ['snapshot', 'navigation'],
16
- };
17
-
18
- /**
19
- * @param {LH.Gatherer.ProtocolSession} session
20
- * @return {Promise<{url: string, data: string}|null>}
21
- */
22
- static async fetchAppManifest(session) {
23
- // In all environments but LR, Page.getAppManifest finishes very quickly.
24
- // In LR, there is a bug that causes this command to hang until outgoing
25
- // requests finish. This has been seen in long polling (where it will never
26
- // return) and when other requests take a long time to finish. We allow 10 seconds
27
- // for outgoing requests to finish. Anything more, and we continue the run without
28
- // a manifest.
29
- // Googlers, see: http://b/124008171
30
- session.setNextProtocolTimeout(10000);
31
- let response;
32
- try {
33
- response = await session.sendCommand('Page.getAppManifest');
34
- } catch (err) {
35
- if (err.code === 'PROTOCOL_TIMEOUT') {
36
- // LR will timeout fetching the app manifest in some cases, move on without one.
37
- // https://github.com/GoogleChrome/lighthouse/issues/7147#issuecomment-461210921
38
- log.error('WebAppManifest', 'Failed fetching manifest', err);
39
- return null;
40
- }
41
-
42
- throw err;
43
- }
44
-
45
- let data = response.data;
46
-
47
- // We're not reading `response.errors` however it may contain critical and noncritical
48
- // errors from Blink's manifest parser:
49
- // https://chromedevtools.github.io/debugger-protocol-viewer/tot/Page/#type-AppManifestError
50
- if (!data) {
51
- // If the data is empty, the page had no manifest.
52
- return null;
53
- }
54
-
55
- const BOM_LENGTH = 3;
56
- const BOM_FIRSTCHAR = 65279;
57
- const isBomEncoded = data.charCodeAt(0) === BOM_FIRSTCHAR;
58
-
59
- if (isBomEncoded) {
60
- data = Buffer.from(data)
61
- .slice(BOM_LENGTH)
62
- .toString();
63
- }
64
-
65
- return {...response, data};
66
- }
67
-
68
- /**
69
- * Uses the debugger protocol to fetch the manifest from within the context of
70
- * the target page, reusing any credentials, emulation, etc, already established
71
- * there.
72
- *
73
- * Returns the parsed manifest or null if the page had no manifest. If the manifest
74
- * was unparseable as JSON, manifest.value will be undefined and manifest.warning
75
- * will have the reason. See manifest-parser.js for more information.
76
- *
77
- * @param {LH.Gatherer.ProtocolSession} session
78
- * @param {string} pageUrl
79
- * @return {Promise<LH.Artifacts.Manifest|null>}
80
- */
81
- static async getWebAppManifest(session, pageUrl) {
82
- const status = {msg: 'Get webapp manifest', id: 'lh:gather:getWebAppManifest'};
83
- log.time(status);
84
- const response = await WebAppManifest.fetchAppManifest(session);
85
- if (!response) return null;
86
- const manifest = parseManifest(response.data, response.url, pageUrl);
87
- log.timeEnd(status);
88
- return manifest;
89
- }
90
-
91
- /**
92
- * @param {LH.Gatherer.Context} context
93
- * @return {Promise<LH.Artifacts['WebAppManifest']>}
94
- */
95
- async getArtifact(context) {
96
- const driver = context.driver;
97
- const {finalDisplayedUrl} = context.baseArtifacts.URL;
98
- try {
99
- return await WebAppManifest.getWebAppManifest(driver.defaultSession, finalDisplayedUrl);
100
- } catch {
101
- return null;
102
- }
103
- }
104
- }
105
-
106
- export default WebAppManifest;
@@ -1,55 +0,0 @@
1
- export class PwaCategoryRenderer extends CategoryRenderer {
2
- /**
3
- * Alters SVG id references so multiple instances of an SVG element can coexist
4
- * in a single page. If `svgRoot` has a `<defs>` block, gives all elements defined
5
- * in it unique ids, then updates id references (`<use xlink:href="...">`,
6
- * `fill="url(#...)"`) to the altered ids in all descendents of `svgRoot`.
7
- * @param {SVGElement} svgRoot
8
- */
9
- static _makeSvgReferencesUnique(svgRoot: SVGElement): void;
10
- /**
11
- * @param {LH.ReportResult.Category} category
12
- * @param {Object<string, LH.Result.ReportGroup>} [groupDefinitions]
13
- * @return {Element}
14
- */
15
- render(category: LH.ReportResult.Category, groupDefinitions?: {
16
- [x: string]: import("../../types/lhr/lhr.js").default.ReportGroup;
17
- } | undefined): Element;
18
- /**
19
- * @param {LH.ReportResult.Category} category
20
- * @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
21
- * @return {DocumentFragment}
22
- */
23
- renderCategoryScore(category: LH.ReportResult.Category, groupDefinitions: Record<string, LH.Result.ReportGroup>): DocumentFragment;
24
- /**
25
- * Returns the group IDs found in auditRefs.
26
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
27
- * @return {!Set<string>}
28
- */
29
- _getGroupIds(auditRefs: Array<LH.ReportResult.AuditRef>): Set<string>;
30
- /**
31
- * Returns the group IDs whose audits are all considered passing.
32
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
33
- * @return {Set<string>}
34
- */
35
- _getPassingGroupIds(auditRefs: Array<LH.ReportResult.AuditRef>): Set<string>;
36
- /**
37
- * Returns a tooltip string summarizing group pass rates.
38
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
39
- * @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
40
- * @return {string}
41
- */
42
- _getGaugeTooltip(auditRefs: Array<LH.ReportResult.AuditRef>, groupDefinitions: Record<string, LH.Result.ReportGroup>): string;
43
- /**
44
- * Render non-manual audits in groups, giving a badge to any group that has
45
- * all passing audits.
46
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
47
- * @param {Object<string, LH.Result.ReportGroup>} groupDefinitions
48
- * @return {Element}
49
- */
50
- _renderAudits(auditRefs: Array<LH.ReportResult.AuditRef>, groupDefinitions: {
51
- [x: string]: LH.Result.ReportGroup;
52
- }): Element;
53
- }
54
- import { CategoryRenderer } from './category-renderer.js';
55
- //# sourceMappingURL=pwa-category-renderer.d.ts.map