lighthouse 12.8.2-dev.20250923 → 12.8.2-dev.20250925
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/test/smokehouse/version-check.d.ts +1 -1
- package/core/audits/accessibility/aria-allowed-role.js +1 -0
- package/core/audits/accessibility/image-redundant-alt.js +1 -0
- package/core/audits/accessibility/landmark-one-main.js +0 -1
- package/core/audits/accessibility/table-duplicate-name.js +1 -0
- package/core/config/default-config.js +90 -71
- package/core/gather/gatherers/image-elements.js +32 -6
- package/core/lib/emulation.d.ts +10 -0
- package/core/lib/emulation.js +21 -6
- package/core/lib/legacy-javascript/legacy-javascript.js +4 -11
- package/core/lib/proto-preprocessor.js +5 -3
- package/core/scoring.js +1 -1
- package/package.json +3 -4
- package/readme.md +1 -1
- package/report/renderer/details-renderer.d.ts +1 -2
- package/report/renderer/details-renderer.js +0 -1
- package/shared/localization/locales/ar-XB.json +0 -30
- package/shared/localization/locales/ar.json +0 -30
- package/shared/localization/locales/bg.json +0 -30
- package/shared/localization/locales/ca.json +0 -30
- package/shared/localization/locales/cs.json +0 -30
- package/shared/localization/locales/da.json +0 -30
- package/shared/localization/locales/de.json +0 -30
- package/shared/localization/locales/el.json +0 -30
- package/shared/localization/locales/en-GB.json +0 -30
- package/shared/localization/locales/en-US.json +0 -30
- package/shared/localization/locales/en-XA.json +0 -30
- package/shared/localization/locales/en-XL.json +0 -30
- package/shared/localization/locales/es-419.json +0 -30
- package/shared/localization/locales/es.json +0 -30
- package/shared/localization/locales/fi.json +0 -30
- package/shared/localization/locales/fil.json +0 -30
- package/shared/localization/locales/fr.json +0 -30
- package/shared/localization/locales/he.json +0 -30
- package/shared/localization/locales/hi.json +0 -30
- package/shared/localization/locales/hr.json +0 -30
- package/shared/localization/locales/hu.json +0 -30
- package/shared/localization/locales/id.json +0 -30
- package/shared/localization/locales/it.json +0 -30
- package/shared/localization/locales/ja.json +0 -30
- package/shared/localization/locales/ko.json +0 -30
- package/shared/localization/locales/lt.json +0 -30
- package/shared/localization/locales/lv.json +0 -30
- package/shared/localization/locales/nl.json +0 -30
- package/shared/localization/locales/no.json +0 -30
- package/shared/localization/locales/pl.json +0 -30
- package/shared/localization/locales/pt-PT.json +0 -30
- package/shared/localization/locales/pt.json +0 -30
- package/shared/localization/locales/ro.json +0 -30
- package/shared/localization/locales/ru.json +0 -30
- package/shared/localization/locales/sk.json +0 -30
- package/shared/localization/locales/sl.json +0 -30
- package/shared/localization/locales/sr-Latn.json +0 -30
- package/shared/localization/locales/sr.json +0 -30
- package/shared/localization/locales/sv.json +0 -30
- package/shared/localization/locales/ta.json +0 -30
- package/shared/localization/locales/te.json +0 -30
- package/shared/localization/locales/th.json +0 -30
- package/shared/localization/locales/tr.json +0 -30
- package/shared/localization/locales/uk.json +0 -30
- package/shared/localization/locales/vi.json +0 -30
- package/shared/localization/locales/zh-HK.json +0 -30
- package/shared/localization/locales/zh-TW.json +0 -30
- package/shared/localization/locales/zh.json +0 -30
- package/shared/localization/locales.d.ts +2 -0
- package/shared/localization/locales.js +130 -139
- package/shared/tsconfig.json +2 -0
- package/tsconfig-base.json +1 -1
- package/tsconfig.json +1 -1
- package/types/artifacts.d.ts +0 -33
- package/core/audits/seo/font-size.d.ts +0 -24
- package/core/audits/seo/font-size.js +0 -344
- package/core/gather/gatherers/seo/font-size.d.ts +0 -131
- package/core/gather/gatherers/seo/font-size.js +0 -347
|
@@ -11,5 +11,5 @@ export function chromiumVersionCheck(opts: {
|
|
|
11
11
|
* @param {number[]} versionA
|
|
12
12
|
* @param {number[]} versionB
|
|
13
13
|
*/
|
|
14
|
-
export function compareVersions(versionA: number[], versionB: number[]):
|
|
14
|
+
export function compareVersions(versionA: number[], versionB: number[]): 1 | 0 | -1;
|
|
15
15
|
//# sourceMappingURL=version-check.d.ts.map
|
|
@@ -35,6 +35,7 @@ class ARIAAllowedRole extends AxeAudit {
|
|
|
35
35
|
title: str_(UIStrings.title),
|
|
36
36
|
failureTitle: str_(UIStrings.failureTitle),
|
|
37
37
|
description: str_(UIStrings.description),
|
|
38
|
+
scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
|
|
38
39
|
requiredArtifacts: ['Accessibility'],
|
|
39
40
|
};
|
|
40
41
|
}
|
|
@@ -36,6 +36,7 @@ class ImageRedundantAlt extends AxeAudit {
|
|
|
36
36
|
title: str_(UIStrings.title),
|
|
37
37
|
failureTitle: str_(UIStrings.failureTitle),
|
|
38
38
|
description: str_(UIStrings.description),
|
|
39
|
+
scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
|
|
39
40
|
requiredArtifacts: ['Accessibility'],
|
|
40
41
|
};
|
|
41
42
|
}
|
|
@@ -34,7 +34,6 @@ class LandmarkOneMain extends AxeAudit {
|
|
|
34
34
|
title: str_(UIStrings.title),
|
|
35
35
|
failureTitle: str_(UIStrings.failureTitle),
|
|
36
36
|
description: str_(UIStrings.description),
|
|
37
|
-
scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
|
|
38
37
|
requiredArtifacts: ['Accessibility'],
|
|
39
38
|
};
|
|
40
39
|
}
|
|
@@ -35,6 +35,7 @@ class TableDuplicateName extends AxeAudit {
|
|
|
35
35
|
title: str_(UIStrings.title),
|
|
36
36
|
failureTitle: str_(UIStrings.failureTitle),
|
|
37
37
|
description: str_(UIStrings.description),
|
|
38
|
+
scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
|
|
38
39
|
requiredArtifacts: ['Accessibility'],
|
|
39
40
|
};
|
|
40
41
|
}
|
|
@@ -119,7 +119,6 @@ const defaultConfig = {
|
|
|
119
119
|
{id: 'CSSUsage', gatherer: 'css-usage'},
|
|
120
120
|
{id: 'Doctype', gatherer: 'dobetterweb/doctype'},
|
|
121
121
|
{id: 'DOMStats', gatherer: 'dobetterweb/domstats'},
|
|
122
|
-
{id: 'FontSize', gatherer: 'seo/font-size'},
|
|
123
122
|
{id: 'Inputs', gatherer: 'inputs'},
|
|
124
123
|
{id: 'IFrameElements', gatherer: 'iframe-elements'},
|
|
125
124
|
{id: 'ImageElements', gatherer: 'image-elements'},
|
|
@@ -302,7 +301,6 @@ const defaultConfig = {
|
|
|
302
301
|
'dobetterweb/uses-passive-event-listeners',
|
|
303
302
|
'seo/meta-description',
|
|
304
303
|
'seo/http-status-code',
|
|
305
|
-
'seo/font-size',
|
|
306
304
|
'seo/link-text',
|
|
307
305
|
'seo/crawlable-anchors',
|
|
308
306
|
'seo/is-crawlable',
|
|
@@ -496,68 +494,86 @@ const defaultConfig = {
|
|
|
496
494
|
description: str_(UIStrings.a11yCategoryDescription),
|
|
497
495
|
manualDescription: str_(UIStrings.a11yCategoryManualDescription),
|
|
498
496
|
supportedModes: ['navigation', 'snapshot'],
|
|
499
|
-
// Audit weights are
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
497
|
+
// Audit weights weights are derived from the axe-core "Impact",
|
|
498
|
+
// with adjustments based on axe-core "Tags":
|
|
499
|
+
//
|
|
500
|
+
// ┌────────────┬───────────────────────────────────────────────┐
|
|
501
|
+
// │ Impact │ Weight Based on Tags │
|
|
502
|
+
// │ ├──────────────┬─────────────────┬──────────────┤
|
|
503
|
+
// │ │ wcag A+AA │ best-practice │ experimental │
|
|
504
|
+
// │ │ (ex: wcag2aa)│ (w/o wcag tag) │ │
|
|
505
|
+
// ├────────────┼──────────────┼─────────────────┼──────────────┤
|
|
506
|
+
// │ Minor │ 1 │ 0 │ 0 │
|
|
507
|
+
// │ Moderate │ 3 │ 3 │ 0 │
|
|
508
|
+
// │ Serious │ 7 │ 7 │ 0 │
|
|
509
|
+
// │ Critical │ 10 │ 10 │ 0 │
|
|
510
|
+
// └────────────┴──────────────┴─────────────────┴──────────────┘
|
|
511
|
+
//
|
|
512
|
+
// Notes:
|
|
513
|
+
// • Experimental rules always have weight 0
|
|
514
|
+
// • Best practice rules only affect scores when tagged with wcagA+AA
|
|
515
|
+
// and are moderate, serious, or critical.
|
|
516
|
+
//
|
|
517
|
+
// To find the latest axe-core Impact and Tag values:
|
|
518
|
+
// 1. Browse to https://dequeuniversity.com/rules/axe/html.
|
|
519
|
+
// 2. Click on the latest rule set (ex: https://dequeuniversity.com/rules/axe/html/4.10)
|
|
520
|
+
// 3. Review the tables
|
|
503
521
|
auditRefs: [
|
|
504
|
-
{id: 'accesskeys', weight: 7, group: 'a11y-navigation'},
|
|
505
|
-
{id: 'aria-allowed-attr', weight: 10, group: 'a11y-aria'},
|
|
506
|
-
{id: 'aria-
|
|
507
|
-
{id: 'aria-
|
|
508
|
-
{id: 'aria-
|
|
509
|
-
{id: 'aria-
|
|
510
|
-
{id: 'aria-
|
|
511
|
-
{id: 'aria-hidden-
|
|
512
|
-
{id: 'aria-
|
|
513
|
-
{id: 'aria-
|
|
514
|
-
{id: 'aria-
|
|
515
|
-
{id: 'aria-
|
|
516
|
-
{id: 'aria-
|
|
517
|
-
{id: 'aria-required-
|
|
518
|
-
{id: 'aria-required-
|
|
519
|
-
{id: 'aria-
|
|
520
|
-
{id: 'aria-
|
|
521
|
-
{id: 'aria-
|
|
522
|
-
{id: 'aria-
|
|
523
|
-
{id: 'aria-
|
|
524
|
-
{id: 'aria-
|
|
525
|
-
{id: 'aria-valid-attr
|
|
526
|
-
{id: '
|
|
527
|
-
{id: '
|
|
528
|
-
{id: '
|
|
529
|
-
{id: '
|
|
530
|
-
{id: '
|
|
531
|
-
{id: '
|
|
532
|
-
{id: '
|
|
533
|
-
{id: '
|
|
534
|
-
{id: '
|
|
535
|
-
{id: '
|
|
536
|
-
{id: '
|
|
537
|
-
{id: 'html-
|
|
538
|
-
{id: 'html-lang-
|
|
539
|
-
{id: '
|
|
540
|
-
{id: '
|
|
541
|
-
{id: 'image-
|
|
542
|
-
{id: '
|
|
543
|
-
{id: '
|
|
544
|
-
{id: '
|
|
545
|
-
{id: '
|
|
546
|
-
{id: '
|
|
547
|
-
{id: '
|
|
548
|
-
{id: '
|
|
549
|
-
{id: '
|
|
550
|
-
{id: '
|
|
551
|
-
{id: '
|
|
552
|
-
{id: '
|
|
553
|
-
{id: '
|
|
554
|
-
{id: '
|
|
555
|
-
{id: '
|
|
556
|
-
{id: '
|
|
557
|
-
{id: '
|
|
558
|
-
{id: '
|
|
559
|
-
{id: 'valid-lang', weight: 7, group: 'a11y-language'},
|
|
560
|
-
{id: 'video-caption', weight: 10, group: 'a11y-audio-video'},
|
|
522
|
+
{id: 'accesskeys', weight: 7, group: 'a11y-navigation'}, // Serious, best-practice
|
|
523
|
+
{id: 'aria-allowed-attr', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
524
|
+
{id: 'aria-command-name', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
525
|
+
{id: 'aria-conditional-attr', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
526
|
+
{id: 'aria-deprecated-role', weight: 1, group: 'a11y-aria'}, // Minor, wcag2a
|
|
527
|
+
{id: 'aria-dialog-name', weight: 7, group: 'a11y-aria'}, // Serious, best-practice
|
|
528
|
+
{id: 'aria-hidden-body', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
529
|
+
{id: 'aria-hidden-focus', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
530
|
+
{id: 'aria-input-field-name', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
531
|
+
{id: 'aria-meter-name', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
532
|
+
{id: 'aria-progressbar-name', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
533
|
+
{id: 'aria-prohibited-attr', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
534
|
+
{id: 'aria-required-attr', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
535
|
+
{id: 'aria-required-children', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
536
|
+
{id: 'aria-required-parent', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
537
|
+
{id: 'aria-roles', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
538
|
+
{id: 'aria-text', weight: 7, group: 'a11y-aria'}, // Serious, best-practice
|
|
539
|
+
{id: 'aria-toggle-field-name', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
540
|
+
{id: 'aria-tooltip-name', weight: 7, group: 'a11y-aria'}, // Serious, wcag2a
|
|
541
|
+
{id: 'aria-treeitem-name', weight: 7, group: 'a11y-aria'}, // Serious, best-practice
|
|
542
|
+
{id: 'aria-valid-attr-value', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
543
|
+
{id: 'aria-valid-attr', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
544
|
+
{id: 'button-name', weight: 10, group: 'a11y-names-labels'}, // Critical, wcag2a
|
|
545
|
+
{id: 'bypass', weight: 7, group: 'a11y-navigation'}, // Serious, wcag2a
|
|
546
|
+
{id: 'color-contrast', weight: 7, group: 'a11y-color-contrast'}, // Serious, wcag2aa
|
|
547
|
+
{id: 'definition-list', weight: 7, group: 'a11y-tables-lists'}, // Serious, wcag2a
|
|
548
|
+
{id: 'dlitem', weight: 7, group: 'a11y-tables-lists'}, // Serious, wcag2a
|
|
549
|
+
{id: 'document-title', weight: 7, group: 'a11y-names-labels'}, // Serious, wcag2a
|
|
550
|
+
{id: 'duplicate-id-aria', weight: 10, group: 'a11y-aria'}, // Critical, wcag2a
|
|
551
|
+
{id: 'form-field-multiple-labels', weight: 3, group: 'a11y-names-labels'}, // Moderate, wcag2a
|
|
552
|
+
{id: 'frame-title', weight: 7, group: 'a11y-names-labels'}, // Serious, wcag2a
|
|
553
|
+
{id: 'heading-order', weight: 3, group: 'a11y-navigation'}, // Moderate, best-practice
|
|
554
|
+
{id: 'html-has-lang', weight: 7, group: 'a11y-language'}, // Serious, wcag2a
|
|
555
|
+
{id: 'html-lang-valid', weight: 7, group: 'a11y-language'}, // Serious, wcag2a
|
|
556
|
+
{id: 'html-xml-lang-mismatch', weight: 3, group: 'a11y-language'}, // Moderate, wcag2a
|
|
557
|
+
{id: 'image-alt', weight: 10, group: 'a11y-names-labels'}, // Critical, wcag2a
|
|
558
|
+
{id: 'input-button-name', weight: 10, group: 'a11y-names-labels'}, // Critical, wcag2a
|
|
559
|
+
{id: 'input-image-alt', weight: 10, group: 'a11y-names-labels'}, // Critical, wcag2a
|
|
560
|
+
{id: 'label', weight: 10, group: 'a11y-names-labels'}, // Critical, wcag2a
|
|
561
|
+
{id: 'link-in-text-block', weight: 7, group: 'a11y-color-contrast'}, // Serious, wcag2a
|
|
562
|
+
{id: 'link-name', weight: 7, group: 'a11y-names-labels'}, // Serious, wcag2a
|
|
563
|
+
{id: 'list', weight: 7, group: 'a11y-tables-lists'}, // Serious, wcag2a
|
|
564
|
+
{id: 'listitem', weight: 7, group: 'a11y-tables-lists'}, // Serious, wcag2a
|
|
565
|
+
{id: 'meta-refresh', weight: 10, group: 'a11y-best-practices'}, // Critical, wcag2a
|
|
566
|
+
{id: 'meta-viewport', weight: 10, group: 'a11y-best-practices'}, // Critical, wcag2aa
|
|
567
|
+
{id: 'object-alt', weight: 7, group: 'a11y-names-labels'}, // Serious, wcag2a
|
|
568
|
+
{id: 'select-name', weight: 10, group: 'a11y-names-labels'}, // Critical, wcag2a
|
|
569
|
+
{id: 'skip-link', weight: 3, group: 'a11y-names-labels'}, // Moderate, best-practice
|
|
570
|
+
{id: 'tabindex', weight: 7, group: 'a11y-navigation'}, // Serious, best-practice
|
|
571
|
+
{id: 'target-size', weight: 7, group: 'a11y-best-practices'}, // Serious, wcag22aa
|
|
572
|
+
{id: 'td-headers-attr', weight: 7, group: 'a11y-tables-lists'}, // Serious, wcag2a
|
|
573
|
+
{id: 'th-has-data-cells', weight: 7, group: 'a11y-tables-lists'}, // Serious, wcag2a
|
|
574
|
+
{id: 'valid-lang', weight: 7, group: 'a11y-language'}, // Serious, wcag2aa
|
|
575
|
+
{id: 'video-caption', weight: 10, group: 'a11y-audio-video'}, // Critical, wcag2a
|
|
576
|
+
{id: 'landmark-one-main', weight: 3, group: 'a11y-best-practices'}, // Moderate, best-practice
|
|
561
577
|
// Manual audits
|
|
562
578
|
{id: 'focusable-controls', weight: 0},
|
|
563
579
|
{id: 'interactive-element-affordance', weight: 0},
|
|
@@ -569,13 +585,17 @@ const defaultConfig = {
|
|
|
569
585
|
{id: 'offscreen-content-hidden', weight: 0},
|
|
570
586
|
{id: 'custom-controls-labels', weight: 0},
|
|
571
587
|
{id: 'custom-controls-roles', weight: 0},
|
|
572
|
-
//
|
|
573
|
-
{id: '
|
|
574
|
-
{id: '
|
|
575
|
-
{id: '
|
|
576
|
-
{id: '
|
|
577
|
-
|
|
578
|
-
{id: '
|
|
588
|
+
// Low-impact best-practices
|
|
589
|
+
{id: 'table-duplicate-name', weight: 0, group: 'a11y-best-practices'}, // Minor, best-practice
|
|
590
|
+
{id: 'empty-heading', weight: 0, group: 'a11y-best-practices'}, // Minor, best-practice
|
|
591
|
+
{id: 'aria-allowed-role', weight: 0, group: 'a11y-best-practices'}, // Minor, best-practice
|
|
592
|
+
{id: 'image-redundant-alt', weight: 0, group: 'a11y-names-labels'}, // Minor, best-practice
|
|
593
|
+
// WCAG AAA
|
|
594
|
+
{id: 'identical-links-same-purpose', weight: 0, group: 'a11y-best-practices'}, // Minor, wcag2aaa
|
|
595
|
+
// Hidden audits (ie. experimental)
|
|
596
|
+
{id: 'label-content-name-mismatch', weight: 0, group: 'hidden'}, // Serious, experimental
|
|
597
|
+
{id: 'table-fake-caption', weight: 0, group: 'hidden'}, // Serious, experimental
|
|
598
|
+
{id: 'td-has-header', weight: 0, group: 'hidden'}, // Critical, experimental
|
|
579
599
|
],
|
|
580
600
|
},
|
|
581
601
|
'best-practices': {
|
|
@@ -597,7 +617,6 @@ const defaultConfig = {
|
|
|
597
617
|
{id: 'image-aspect-ratio', weight: 1, group: 'best-practices-ux'},
|
|
598
618
|
{id: 'image-size-responsive', weight: 1, group: 'best-practices-ux'},
|
|
599
619
|
{id: 'viewport', weight: 1, group: 'best-practices-ux'},
|
|
600
|
-
{id: 'font-size', weight: 1, group: 'best-practices-ux'},
|
|
601
620
|
// Browser Compatibility
|
|
602
621
|
{id: 'doctype', weight: 1, group: 'best-practices-browser-compat'},
|
|
603
622
|
{id: 'charset', weight: 1, group: 'best-practices-browser-compat'},
|
|
@@ -3,17 +3,16 @@
|
|
|
3
3
|
* Copyright 2017 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
/**
|
|
7
|
-
* @fileoverview Gathers all images used on the page with their src, size,
|
|
8
|
-
* and attribute information. Executes script in the context of the page.
|
|
9
|
-
*/
|
|
10
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @fileoverview Gathers all images used on the page with their src, size,
|
|
9
|
+
* and attribute information. Executes script in the context of the page.
|
|
10
|
+
*/
|
|
11
11
|
|
|
12
12
|
import log from 'lighthouse-logger';
|
|
13
13
|
|
|
14
14
|
import BaseGatherer from '../base-gatherer.js';
|
|
15
15
|
import {pageFunctions} from '../../lib/page-functions.js';
|
|
16
|
-
import * as FontSize from './seo/font-size.js';
|
|
17
16
|
|
|
18
17
|
/* global getElementsInDocument, getNodeDetails */
|
|
19
18
|
|
|
@@ -186,6 +185,33 @@ function findSizeDeclaration(rule, property) {
|
|
|
186
185
|
return definedProp.value;
|
|
187
186
|
}
|
|
188
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Finds the most specific directly matched CSS font-size rule from the list.
|
|
190
|
+
*
|
|
191
|
+
* @param {Array<LH.Crdp.CSS.RuleMatch>} matchedCSSRules
|
|
192
|
+
* @param {function(LH.Crdp.CSS.CSSStyle):boolean|string|undefined} isDeclarationOfInterest
|
|
193
|
+
*/
|
|
194
|
+
function findMostSpecificMatchedCSSRule(matchedCSSRules = [], isDeclarationOfInterest) {
|
|
195
|
+
let mostSpecificRule;
|
|
196
|
+
for (let i = matchedCSSRules.length - 1; i >= 0; i--) {
|
|
197
|
+
if (isDeclarationOfInterest(matchedCSSRules[i].rule.style)) {
|
|
198
|
+
mostSpecificRule = matchedCSSRules[i].rule;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (mostSpecificRule) {
|
|
204
|
+
return {
|
|
205
|
+
type: 'Regular',
|
|
206
|
+
...mostSpecificRule.style,
|
|
207
|
+
parentRule: {
|
|
208
|
+
origin: mostSpecificRule.origin,
|
|
209
|
+
selectors: mostSpecificRule.selectorList.selectors,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
189
215
|
/**
|
|
190
216
|
* Finds the most specific directly matched CSS font-size rule from the list.
|
|
191
217
|
*
|
|
@@ -196,7 +222,7 @@ function findSizeDeclaration(rule, property) {
|
|
|
196
222
|
function findMostSpecificCSSRule(matchedCSSRules, property) {
|
|
197
223
|
/** @param {LH.Crdp.CSS.CSSStyle} declaration */
|
|
198
224
|
const isDeclarationofInterest = (declaration) => findSizeDeclaration(declaration, property);
|
|
199
|
-
const rule =
|
|
225
|
+
const rule = findMostSpecificMatchedCSSRule(matchedCSSRules, isDeclarationofInterest);
|
|
200
226
|
if (!rule) return;
|
|
201
227
|
|
|
202
228
|
return findSizeDeclaration(rule, property);
|
package/core/lib/emulation.d.ts
CHANGED
|
@@ -40,4 +40,14 @@ export function enableCPUThrottling(session: LH.Gatherer.ProtocolSession, thrott
|
|
|
40
40
|
* @return {Promise<void>}
|
|
41
41
|
*/
|
|
42
42
|
export function clearCPUThrottling(session: LH.Gatherer.ProtocolSession): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Tweak a useragent to have the milestone match the host's Chrome version.
|
|
45
|
+
* @param {LH.Gatherer.ProtocolSession} session
|
|
46
|
+
* @param {string} userAgent
|
|
47
|
+
* @returns {Promise<{tweakedUA: string, fullVersion: string}>}
|
|
48
|
+
*/
|
|
49
|
+
export function matchHostUAVersion(session: LH.Gatherer.ProtocolSession, userAgent: string): Promise<{
|
|
50
|
+
tweakedUA: string;
|
|
51
|
+
fullVersion: string;
|
|
52
|
+
}>;
|
|
43
53
|
//# sourceMappingURL=emulation.d.ts.map
|
package/core/lib/emulation.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import {getBrowserVersion} from '../gather/driver/environment.js';
|
|
8
|
+
|
|
7
9
|
const NO_THROTTLING_METRICS = {
|
|
8
10
|
latency: 0,
|
|
9
11
|
downloadThroughput: 0,
|
|
@@ -16,13 +18,11 @@ const NO_CPU_THROTTLE_METRICS = {
|
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
|
-
* @param {string}
|
|
21
|
+
* @param {string} fullVersion
|
|
20
22
|
* @param {LH.Config.Settings['formFactor']} formFactor
|
|
21
23
|
* @return {LH.Crdp.Emulation.SetUserAgentOverrideRequest['userAgentMetadata']}
|
|
22
24
|
*/
|
|
23
|
-
function parseUseragentIntoMetadata(
|
|
24
|
-
const match = userAgent.match(/Chrome\/([\d.]+)/); // eg 'Chrome/(71.0.3577.0)'
|
|
25
|
-
const fullVersion = match?.[1] || '99.0.1234.0';
|
|
25
|
+
function parseUseragentIntoMetadata(fullVersion, formFactor) {
|
|
26
26
|
const [version] = fullVersion.split('.', 1);
|
|
27
27
|
const brands = [
|
|
28
28
|
{brand: 'Chromium', version},
|
|
@@ -54,6 +54,19 @@ function parseUseragentIntoMetadata(userAgent, formFactor) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Tweak a useragent to have the milestone match the host's Chrome version.
|
|
59
|
+
* @param {LH.Gatherer.ProtocolSession} session
|
|
60
|
+
* @param {string} userAgent
|
|
61
|
+
* @returns {Promise<{tweakedUA: string, fullVersion: string}>}
|
|
62
|
+
*/
|
|
63
|
+
async function matchHostUAVersion(session, userAgent) {
|
|
64
|
+
const {milestone} = await getBrowserVersion(session);
|
|
65
|
+
const tweakedUA = userAgent.replace(/(Chrome\/)[\d.]+/, `$1${milestone}.0.0.0`);
|
|
66
|
+
const fullVersion = `${milestone}.0.0.0`;
|
|
67
|
+
return {tweakedUA, fullVersion};
|
|
68
|
+
}
|
|
69
|
+
|
|
57
70
|
/**
|
|
58
71
|
* @param {LH.Gatherer.ProtocolSession} session
|
|
59
72
|
* @param {LH.Config.Settings} settings
|
|
@@ -62,9 +75,10 @@ function parseUseragentIntoMetadata(userAgent, formFactor) {
|
|
|
62
75
|
async function emulate(session, settings) {
|
|
63
76
|
if (settings.emulatedUserAgent !== false) {
|
|
64
77
|
const userAgent = /** @type {string} */ (settings.emulatedUserAgent);
|
|
78
|
+
const {tweakedUA, fullVersion} = await matchHostUAVersion(session, userAgent);
|
|
65
79
|
await session.sendCommand('Network.setUserAgentOverride', {
|
|
66
|
-
userAgent,
|
|
67
|
-
userAgentMetadata: parseUseragentIntoMetadata(
|
|
80
|
+
userAgent: tweakedUA,
|
|
81
|
+
userAgentMetadata: parseUseragentIntoMetadata(fullVersion, settings.formFactor),
|
|
68
82
|
});
|
|
69
83
|
}
|
|
70
84
|
// See devtools-entry for one usecase for disabling screenEmulation
|
|
@@ -157,4 +171,5 @@ export {
|
|
|
157
171
|
clearNetworkThrottling,
|
|
158
172
|
enableCPUThrottling,
|
|
159
173
|
clearCPUThrottling,
|
|
174
|
+
matchHostUAVersion,
|
|
160
175
|
};
|
|
@@ -15,21 +15,14 @@
|
|
|
15
15
|
/** @typedef {{name: string, line: number, column: number}} PatternMatchResult */
|
|
16
16
|
/** @typedef {{matches: PatternMatchResult[], estimatedByteSavings: number}} Result */
|
|
17
17
|
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
import {LH_ROOT} from '../../../shared/root.js';
|
|
21
|
-
|
|
22
|
-
const polyfillModuleDataJson = fs.readFileSync(
|
|
23
|
-
`${LH_ROOT}/core/lib/legacy-javascript/polyfill-module-data.json`, 'utf-8');
|
|
18
|
+
import polyfillModuleData_ from './polyfill-module-data.json' with { type: 'json' };
|
|
19
|
+
import graph_ from './polyfill-graph-data.json' with { type: 'json' };
|
|
24
20
|
|
|
25
21
|
/** @type {import('../../scripts/legacy-javascript/create-polyfill-module-data.js').PolyfillModuleData} */
|
|
26
|
-
const polyfillModuleData =
|
|
27
|
-
|
|
28
|
-
const graphJson = fs.readFileSync(
|
|
29
|
-
`${LH_ROOT}/core/lib/legacy-javascript/polyfill-graph-data.json`, 'utf-8');
|
|
22
|
+
const polyfillModuleData = polyfillModuleData_;
|
|
30
23
|
|
|
31
24
|
/** @type {import('../../scripts/legacy-javascript/create-polyfill-size-estimation.js').PolyfillSizeEstimator} */
|
|
32
|
-
const graph =
|
|
25
|
+
const graph = graph_;
|
|
33
26
|
|
|
34
27
|
/**
|
|
35
28
|
* Takes a list of patterns (consisting of a name identifier and a RegExp expression string)
|
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
|
|
9
|
-
import esMain from 'es-main';
|
|
10
|
-
|
|
11
9
|
/**
|
|
12
10
|
* @fileoverview Helper functions to transform an LHR into a proto-ready LHR.
|
|
13
11
|
*
|
|
@@ -126,7 +124,7 @@ function processForProto(lhr) {
|
|
|
126
124
|
}
|
|
127
125
|
|
|
128
126
|
// Test if called from the CLI or as a module.
|
|
129
|
-
if (
|
|
127
|
+
if (import.meta.main) {
|
|
130
128
|
// read in the argv for the input & output
|
|
131
129
|
const args = process.argv.slice(2);
|
|
132
130
|
let input;
|
|
@@ -143,6 +141,10 @@ if (esMain(import.meta)) {
|
|
|
143
141
|
const report = processForProto(JSON.parse(fs.readFileSync(input, 'utf-8')));
|
|
144
142
|
// write to output from argv
|
|
145
143
|
fs.writeFileSync(output, JSON.stringify(report), 'utf-8');
|
|
144
|
+
// eslint-disable-next-line no-console
|
|
145
|
+
console.log(`file written to ${output}`);
|
|
146
|
+
} else {
|
|
147
|
+
process.exit(1);
|
|
146
148
|
}
|
|
147
149
|
}
|
|
148
150
|
|
package/core/scoring.js
CHANGED
|
@@ -57,7 +57,7 @@ class ReportScoring {
|
|
|
57
57
|
const member = {...configMember};
|
|
58
58
|
|
|
59
59
|
// If a result was not applicable, meaning its checks did not run against anything on
|
|
60
|
-
// the page, force
|
|
60
|
+
// the page, force its weight to 0. It will not count during the arithmeticMean() but
|
|
61
61
|
// will still be included in the final report json and displayed in the report as
|
|
62
62
|
// "Not Applicable".
|
|
63
63
|
const result = resultsByAuditId[member.id];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "12.8.2-dev.
|
|
4
|
+
"version": "12.8.2-dev.20250925",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"smokehouse": "./cli/test/smokehouse/frontends/smokehouse-bin.js"
|
|
11
11
|
},
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
13
|
+
"node": ">=22.19"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
16
|
"prepack": "yarn build-report --standalone --flow --esm && yarn build-types",
|
|
@@ -147,7 +147,6 @@
|
|
|
147
147
|
"core-js-compat": "^3.44.0",
|
|
148
148
|
"cpy": "^8.1.2",
|
|
149
149
|
"csv-validator": "^0.0.3",
|
|
150
|
-
"es-main": "^1.2.0",
|
|
151
150
|
"esbuild": "0.25.9",
|
|
152
151
|
"eslint": "^9.28.0",
|
|
153
152
|
"eslint-config-google": "^0.14.0",
|
|
@@ -185,7 +184,7 @@
|
|
|
185
184
|
"@paulirish/trace_engine": "0.0.59",
|
|
186
185
|
"@sentry/node": "^9.28.1",
|
|
187
186
|
"axe-core": "^4.10.3",
|
|
188
|
-
"chrome-launcher": "^1.2.
|
|
187
|
+
"chrome-launcher": "^1.2.1",
|
|
189
188
|
"configstore": "^7.0.0",
|
|
190
189
|
"csp_evaluator": "1.1.5",
|
|
191
190
|
"devtools-protocol": "0.0.1507524",
|
package/readme.md
CHANGED
|
@@ -53,7 +53,7 @@ The Chrome extension was available prior to Lighthouse being available in Chrome
|
|
|
53
53
|
The Node CLI provides the most flexibility in how Lighthouse runs can be configured and reported. Users who want more advanced usage, or want to run Lighthouse in an automated fashion should use the Node CLI.
|
|
54
54
|
|
|
55
55
|
> [!NOTE]
|
|
56
|
-
> Lighthouse requires Node
|
|
56
|
+
> Lighthouse requires Node 22 (LTS) or later.
|
|
57
57
|
|
|
58
58
|
**Installation**:
|
|
59
59
|
|
|
@@ -146,9 +146,8 @@ export class DetailsRenderer {
|
|
|
146
146
|
/**
|
|
147
147
|
* @param {LH.Audit.Details.SourceLocationValue} item
|
|
148
148
|
* @return {Element|null}
|
|
149
|
-
* @protected
|
|
150
149
|
*/
|
|
151
|
-
|
|
150
|
+
renderSourceLocation(item: LH.Audit.Details.SourceLocationValue): Element | null;
|
|
152
151
|
/**
|
|
153
152
|
* @param {LH.Audit.Details.Filmstrip} details
|
|
154
153
|
* @return {Element}
|
|
@@ -1316,36 +1316,6 @@
|
|
|
1316
1316
|
"core/audits/seo/crawlable-anchors.js | title": {
|
|
1317
1317
|
"message": "Links are crawlable"
|
|
1318
1318
|
},
|
|
1319
|
-
"core/audits/seo/font-size.js | additionalIllegibleText": {
|
|
1320
|
-
"message": "Add'l illegible text"
|
|
1321
|
-
},
|
|
1322
|
-
"core/audits/seo/font-size.js | columnFontSize": {
|
|
1323
|
-
"message": "Font Size"
|
|
1324
|
-
},
|
|
1325
|
-
"core/audits/seo/font-size.js | columnPercentPageText": {
|
|
1326
|
-
"message": "% of Page Text"
|
|
1327
|
-
},
|
|
1328
|
-
"core/audits/seo/font-size.js | columnSelector": {
|
|
1329
|
-
"message": "Selector"
|
|
1330
|
-
},
|
|
1331
|
-
"core/audits/seo/font-size.js | description": {
|
|
1332
|
-
"message": "Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more about legible font sizes](https://developer.chrome.com/docs/lighthouse/seo/font-size/)."
|
|
1333
|
-
},
|
|
1334
|
-
"core/audits/seo/font-size.js | displayValue": {
|
|
1335
|
-
"message": "{decimalProportion, number, extendedPercent} legible text"
|
|
1336
|
-
},
|
|
1337
|
-
"core/audits/seo/font-size.js | explanationViewport": {
|
|
1338
|
-
"message": "Text is illegible because there's no viewport meta tag optimized for mobile screens."
|
|
1339
|
-
},
|
|
1340
|
-
"core/audits/seo/font-size.js | failureTitle": {
|
|
1341
|
-
"message": "Document doesn't use legible font sizes"
|
|
1342
|
-
},
|
|
1343
|
-
"core/audits/seo/font-size.js | legibleText": {
|
|
1344
|
-
"message": "Legible text"
|
|
1345
|
-
},
|
|
1346
|
-
"core/audits/seo/font-size.js | title": {
|
|
1347
|
-
"message": "Document uses legible font sizes"
|
|
1348
|
-
},
|
|
1349
1319
|
"core/audits/seo/hreflang.js | description": {
|
|
1350
1320
|
"message": "hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more about `hreflang`](https://developer.chrome.com/docs/lighthouse/seo/hreflang/)."
|
|
1351
1321
|
},
|
|
@@ -1316,36 +1316,6 @@
|
|
|
1316
1316
|
"core/audits/seo/crawlable-anchors.js | title": {
|
|
1317
1317
|
"message": "يمكن الزحف إلى الروابط"
|
|
1318
1318
|
},
|
|
1319
|
-
"core/audits/seo/font-size.js | additionalIllegibleText": {
|
|
1320
|
-
"message": "نص إضافي غير قابل للقراءة"
|
|
1321
|
-
},
|
|
1322
|
-
"core/audits/seo/font-size.js | columnFontSize": {
|
|
1323
|
-
"message": "حجم الخط"
|
|
1324
|
-
},
|
|
1325
|
-
"core/audits/seo/font-size.js | columnPercentPageText": {
|
|
1326
|
-
"message": "% من نص الصفحة"
|
|
1327
|
-
},
|
|
1328
|
-
"core/audits/seo/font-size.js | columnSelector": {
|
|
1329
|
-
"message": "أداة الاختيار"
|
|
1330
|
-
},
|
|
1331
|
-
"core/audits/seo/font-size.js | description": {
|
|
1332
|
-
"message": "تكون أحجام الخطوط الأقل من 12 بكسل صغيرة جدًا بحيث لا يمكن قراءتها بسهولة وتتطلب من مستخدمي الأجهزة الجوّالة \"استخدام الإصبعين للتكبير\" من أجل قراءتها. يُرجى بذل قصارى جهدك لضبط الخطوط في أكثر من 60% من نص الصفحة على حجم أكبر من أو يساوي 12 بكسل. [مزيد من المعلومات حول أحجام الخطوط القابلة للقراءة](https://developer.chrome.com/docs/lighthouse/seo/font-size/)"
|
|
1333
|
-
},
|
|
1334
|
-
"core/audits/seo/font-size.js | displayValue": {
|
|
1335
|
-
"message": "نص {decimalProportion, number, extendedPercent} قابل للقراءة"
|
|
1336
|
-
},
|
|
1337
|
-
"core/audits/seo/font-size.js | explanationViewport": {
|
|
1338
|
-
"message": "النص غير مقروء لأنه لا تتوفّر علامة وصفية لإطار العرض محسنة لشاشات الجوّال."
|
|
1339
|
-
},
|
|
1340
|
-
"core/audits/seo/font-size.js | failureTitle": {
|
|
1341
|
-
"message": "لا يستخدم المستند أحجام الخطوط القابلة للقراءة"
|
|
1342
|
-
},
|
|
1343
|
-
"core/audits/seo/font-size.js | legibleText": {
|
|
1344
|
-
"message": "نص قابل للقراءة"
|
|
1345
|
-
},
|
|
1346
|
-
"core/audits/seo/font-size.js | title": {
|
|
1347
|
-
"message": "يستخدم المستند أحجام الخط القابلة للقراءة"
|
|
1348
|
-
},
|
|
1349
1319
|
"core/audits/seo/hreflang.js | description": {
|
|
1350
1320
|
"message": "توضّح روابط hreflang لمحركات البحث إصدار الصفحة الذي يجب إدراجه في نتائج البحث للغة أو منطقة معيّنة. [مزيد من المعلومات حول `hreflang`](https://developer.chrome.com/docs/lighthouse/seo/hreflang/)"
|
|
1351
1321
|
},
|