#!/usr/bin/env python3 """ Audit each guide URL in guides.csv for WCAG 2.1 AA accessibility issues (using pa11y). Writes a report that omits issues appearing in *every* guide. Output file: output2.txt Usage: python check_wcag_unique.py Prerequisite: npm install -g pa11y # or have pa11y available via npx """ from __future__ import annotations import csv import json import shutil import subprocess import sys from pathlib import Path from typing import Dict, List, Set GUIDES_CSV = Path(__file__).with_name("guides.csv") OUTPUT_FILE = Path("output2.txt") def run_pa11y(url: str) -> List[dict]: """Run pa11y on the URL and return its JSON‐parsed list of issues.""" cmd_base = ["pa11y"] if shutil.which("pa11y") else ["npx", "pa11y"] result = subprocess.run( [*cmd_base, url, "--standard", "WCAG2AA", "--reporter", "json"], capture_output=True, text=True, check=False, ) # pa11y exits 0 (no issues) or 1 (issues found). Treat both as success. if result.returncode not in (0, 1): print(f"[ERROR] pa11y failed with code {result.returncode} for {url}", file=sys.stderr) return [] try: return json.loads(result.stdout) except json.JSONDecodeError: print(f"[WARN] Could not parse pa11y JSON output for {url}", file=sys.stderr) return [] def read_guides(csv_path: Path) -> List[Dict[str, str]]: with csv_path.open(newline="", encoding="utf-8-sig") as fh: return list(csv.DictReader(fh)) def compute_common_codes(issues_by_guide: Dict[str, List[dict]]) -> Set[str]: """Return set of issue codes present in *every* guide.""" common: Set[str] | None = None for issues in issues_by_guide.values(): codes = {i["code"] for i in issues} common = codes if common is None else common & codes return common or set() def format_issue(issue: dict) -> str: selector = (issue.get("selector") or "").strip() or "N/A" return f"[{issue['type']}] {issue['code']}: {issue['message']} (selector: {selector})" def main() -> None: guides = read_guides(GUIDES_CSV) issues_by_guide: Dict[str, List[dict]] = {} print("Auditing guides with pa11y…\n") for guide in guides: name, url = guide["Name"], guide["URL"] print(f"• {name} — {url}") issues_by_guide[name] = run_pa11y(url) common_codes = compute_common_codes(issues_by_guide) lines: List[str] = [] lines.append("Accessibility report (WCAG 2.1 AA — unique issues only)") lines.append("=" * 50) for name, issues in issues_by_guide.items(): unique = [i for i in issues if i["code"] not in common_codes] lines.append(f"\nGuide: {name}") if not unique: lines.append(" ✔ No unique issues found.") continue for issue in unique: lines.append(f" • {format_issue(issue)}") report = "\n".join(lines) print("\n" + report) OUTPUT_FILE.write_text(report, encoding="utf-8") print(f"\nReport written to {OUTPUT_FILE.resolve()}") if __name__ == "__main__": main()