From 061029a423bc1e2ab157d2b76ab9726255dc2eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20=C3=96sterberg?= Date: Thu, 14 May 2026 13:46:33 +0200 Subject: [PATCH] Add showstopper rules that zero out their category score Some rules represent failures so fundamental that the affected category should be considered failed outright, rather than just deducted from. Missing an accessibility statement when it is legally required is one such case: under the current scoring (-25 for severity 'critical'), the site still gets 75/100, which doesn't reflect that a mandatory artifact is entirely absent. This commit introduces a `showstopperRules` set in Score. Any issue whose rule is in the set, with a non-resolved severity, forces its category score to 0 instead of going through the normal severity deduction. Currently only 'no-a11y-statement' is in the set. Other plugins using severity 'critical' (notably the lighthouse converter's crash fallback) are unaffected, since they use different rule names. Sites that have a statement but flag it as partially compliant ('compatible-word-partly', severity 'error') also continue to score as before. --- lib/score.js | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/score.js b/lib/score.js index a2dc224..62ec872 100644 --- a/lib/score.js +++ b/lib/score.js @@ -1,16 +1,43 @@ export class Score { constructor() { + // Regler som direkt sätter sin kategoripoäng till 0 ("showstoppers"), + // i stället för att gå genom det vanliga severity-avdraget. + // + // Används när en specifik regel innebär att kategorin är de facto + // underkänd — t.ex. när en lagstadgad tillgänglighetsredogörelse + // helt saknas. Lista bara regler där frånvaron är ett underkänt + // prov, inte saker som "delvis förenlig" eller liknande, för då + // tappar man nyans i poängsättningen. + // + // Vill man lägga till fler i framtiden (t.ex. om HTTPS helt saknas) + // är detta rätt ställe. + this.showstopperRules = new Set([ + 'no-a11y-statement' + ]); } calculateScore(issues) { let categoryScores = { 'overall': 100, }; + + // Spåra vilka kategorier som ska nollas pga showstopper-regler + const zeroedCategories = new Set(); + issues.forEach(issue => { if (!categoryScores[issue.category]) { categoryScores[issue.category] = 100; } + + // Showstopper-regler nollar kategorin direkt. Kolla att severity + // inte är 'resolved' — då är regeln visserligen med i listan men + // som godkänd, och ska inte trigga nollställning. + if (this.showstopperRules.has(issue.rule) && issue.severity !== 'resolved') { + zeroedCategories.add(issue.category); + return; // Hoppa över vanlig poängdragning för detta issue + } + if (issue.severity === 'critical') { categoryScores[issue.category] -= 25; } else if (issue.severity === 'error') { @@ -19,6 +46,12 @@ export class Score { categoryScores[issue.category] -= 1; } }); + + // Tvinga showstopper-kategorier till 0 + zeroedCategories.forEach(category => { + categoryScores[category] = 0; + }); + const Scores = Object.entries(categoryScores) .filter(([key]) => key !== 'overall') // Exclude 'overall' from the calculation .map(([, value]) => value); @@ -26,4 +59,4 @@ export class Score { categoryScores['overall'] = Scores.length > 0 ? total / Scores.length : 100; // Use average return categoryScores; } -} +} \ No newline at end of file