Spaces:
Sleeping
Sleeping
File size: 5,075 Bytes
50841a0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /**
* Human-impact modeling for accessibility findings.
*
* Maps each WCAG 2.x success criterion to the Section 508 Functional
* Performance Criteria (FPC) it relates to, and each FPC to a disability
* group with a US population prevalence estimate. This lets a finding say
* *who* it affects and roughly *how many people*, instead of an opaque
* "requires manual testing".
*
* Sources:
* - WCAG -> FPC mapping: GSA Section 508 program,
* https://www.section508.gov/develop/mapping-wcag-to-fpc/ (extended to
* WCAG 2.2 criteria here). FPC categories also align with EU EN 301 549
* Table B.2.
* - Prevalence: US Census Bureau American Community Survey (ACS) 2022
* 1-Year Estimates (disability tables), with supplemental CDC/NIDCD/NEI
* figures. These are population-level estimates, not site analytics —
* use them to convey scale, not as precise measurements.
*
* Approach borrowed from mgifford/daily-dap.
*/
// FPC code -> disability group + US prevalence (fraction of population).
export const FPC = {
WV: { code: 'WV', group: 'Without vision', prevalence: 0.010 },
LV: { code: 'LV', group: 'Limited vision', prevalence: 0.024 },
WPC: { code: 'WPC', group: 'Without color perception', prevalence: 0.045 },
WH: { code: 'WH', group: 'Without hearing', prevalence: 0.003 },
LH: { code: 'LH', group: 'Limited hearing', prevalence: 0.035 },
WS: { code: 'WS', group: 'Without speech', prevalence: 0.005 },
LM: { code: 'LM', group: 'Limited manipulation/strength', prevalence: 0.130 },
LR: { code: 'LR', group: 'Limited reach', prevalence: 0.020 },
LCLA: { code: 'LCLA', group: 'Limited cognitive, language, or learning ability', prevalence: 0.110 },
};
// WCAG success criterion -> the FPC codes it most directly affects.
// Covers WCAG 2.0/2.1/2.2 Level A and AA. A criterion with no entry
// returns an empty impact (treated as undetermined rather than guessed).
const SC_TO_FPC = {
// 1.1 Text Alternatives
'1.1.1': ['WV', 'LV', 'LCLA'],
// 1.2 Time-based Media
'1.2.1': ['WV', 'WH'],
'1.2.2': ['WH', 'LH'],
'1.2.3': ['WV', 'LV'],
'1.2.4': ['WH', 'LH'],
'1.2.5': ['WV', 'LV'],
// 1.3 Adaptable
'1.3.1': ['WV', 'LV', 'LCLA'],
'1.3.2': ['WV', 'LCLA'],
'1.3.3': ['WV', 'LV', 'LCLA'],
'1.3.4': ['LV', 'LM'],
'1.3.5': ['LCLA', 'LM'],
// 1.4 Distinguishable
'1.4.1': ['WPC', 'LV'],
'1.4.2': ['WV', 'LV'],
'1.4.3': ['LV', 'WPC'],
'1.4.4': ['LV'],
'1.4.5': ['LV', 'WPC'],
'1.4.10': ['LV', 'LM'],
'1.4.11': ['LV', 'WPC'],
'1.4.12': ['LV', 'LCLA'],
'1.4.13': ['LV', 'LM', 'LCLA'],
// 2.1 Keyboard Accessible
'2.1.1': ['WV', 'LM', 'LR'],
'2.1.2': ['WV', 'LM', 'LR'],
'2.1.4': ['WV', 'LM'],
// 2.2 Enough Time
'2.2.1': ['LM', 'LR', 'LCLA'],
'2.2.2': ['LV', 'LCLA'],
// 2.3 Seizures
'2.3.1': ['LCLA'],
// 2.4 Navigable
'2.4.1': ['WV', 'LM'],
'2.4.2': ['WV', 'LV', 'LCLA'],
'2.4.3': ['WV', 'LM'],
'2.4.4': ['WV', 'LV', 'LCLA'],
'2.4.5': ['WV', 'LV', 'LCLA'],
'2.4.6': ['WV', 'LV', 'LCLA'],
'2.4.7': ['LV', 'LM'],
'2.4.11': ['LV', 'LM'],
// 2.5 Input Modalities
'2.5.1': ['LM', 'LR'],
'2.5.2': ['LM', 'LR'],
'2.5.3': ['WV', 'WS'],
'2.5.4': ['LM', 'LR'],
'2.5.7': ['LM', 'LR'],
'2.5.8': ['LM', 'LR', 'LV'],
// 3.1 Readable
'3.1.1': ['WV', 'LCLA'],
'3.1.2': ['WV', 'LCLA'],
// 3.2 Predictable
'3.2.1': ['WV', 'LV', 'LCLA'],
'3.2.2': ['WV', 'LV', 'LCLA'],
'3.2.3': ['LV', 'LCLA'],
'3.2.4': ['LV', 'LCLA'],
'3.2.6': ['LCLA'],
// 3.3 Input Assistance
'3.3.1': ['WV', 'LV', 'LCLA'],
'3.3.2': ['WV', 'LV', 'LCLA'],
'3.3.3': ['WV', 'LV', 'LCLA'],
'3.3.4': ['LCLA'],
'3.3.7': ['LCLA', 'LM'],
'3.3.8': ['LCLA', 'LM'],
// 4.1 Compatible
'4.1.1': ['WV', 'LV'],
'4.1.2': ['WV', 'LV', 'LM'],
'4.1.3': ['WV', 'LV'],
};
/**
* Impact for a WCAG success criterion: the disability groups affected,
* each with prevalence. Returns { groups: [{code, group, prevalence}],
* maxPrevalence } or null when the SC is unmapped/unknown.
*/
export function impactFor(sc) {
const codes = SC_TO_FPC[sc];
if (!codes || codes.length === 0) return null;
const groups = codes.map((c) => FPC[c]).filter(Boolean);
if (groups.length === 0) return null;
return {
groups,
// The single most-affected group's prevalence — a conservative
// headline figure (groups overlap, so we don't sum them).
maxPrevalence: Math.max(...groups.map((g) => g.prevalence)),
};
}
/**
* Optional people-excluded estimate, when page-load data is supplied.
* prevalence: fraction (0-1)
* pageLoads: loads attributable to the affected pages
* Rough by design — meant to convey scale, not precision.
*/
export function estimateExcluded(prevalence, pageLoads) {
if (!pageLoads || pageLoads <= 0) return null;
return Math.round(prevalence * pageLoads);
}
/** Format a prevalence fraction as a percent string, e.g. 0.024 -> "2.4%". */
export function pct(fraction) {
return `${(fraction * 100).toFixed(1)}%`;
}
|