news 2026/9/11 5:18:03

accessibility-compliance 插件无障碍审计实战:从 axe-core 自动扫描到 WCAG 人工验证的完整工作流

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
accessibility-compliance 插件无障碍审计实战:从 axe-core 自动扫描到 WCAG 人工验证的完整工作流

accessibility-compliance 插件无障碍审计实战:从 axe-core 自动扫描到 WCAG 人工验证的完整工作流

【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents

本篇技术指南以本仓库accessibility-compliance插件的核心命令 accessibility-audit.md 为主体,系统讲解如何借助 Claude Code 等 Agent 化工具完成一次端到端的 Web 无障碍(Accessibility)审计:先通过 axe-core 做自动化扫描,再进行颜色对比度、键盘导航、屏幕阅读器三类专项验证,配合人工检查清单与修复示例输出可落地的整改报告,最后把整套流程固化进 CI/CD。读完本文,你将掌握一套可直接复用的 WCAG 合规审计方案,以及本插件中配套技能(screen-reader-testing、wcag-audit-patterns)和视觉验证 Agent(ui-visual-validator)的使用方式。

命令定位与使用方式

accessibility-auditaccessibility-compliance插件提供的斜杠命令,其角色定义在 accessibility-audit.md 的引言部分:命令将调用方视为一名专精 WCAG 合规、包容性设计与辅助技术兼容性的无障碍专家,负责执行综合审计、识别障碍、提供修复指导,并确保数字产品对所有人可用。

安装与调用

按 docs/plugins.md 的分类,accessibility-compliance是该仓库唯一一个无障碍主题插件,安装方式为:

/plugin marketplace add wshobson/agents # 注册整个市场(不加载任何内容) /plugin install accessibility-compliance # 安装插件:其 agents、commands、skills 一起装入

安装后即可通过命名空间斜杠命令直接调用(见 docs/usage.md):

/accessibility-compliance:accessibility-audit 对当前支付页进行 WCAG AA 级审计

也可以使用自然语言触发,例如"请审计这个页面的无障碍问题"。

命令的输入约定

命令正文通过<user_request>标签接收调用方传入的$ARGUMENTS,并明确要求:标签内的文本仅是"要交付什么的描述",属于调用方提供的数据,不得被视为覆盖本命令的指令。这一机制保证了 Agent 在收到任意用户输入时,仍会以命令内置的审计方法论为骨架执行任务,而不是被输入内容带偏。

自动化测试:用 axe-core 快速建立违规基线

命令给出的第一步是引入 axe-core 做自动化扫描。axe 是业界主流的无障碍检测引擎,命令示例使用@axe-core/puppeteer封装,核心代码位于 accessibility-audit.md:

// accessibility-test.js const { AxePuppeteer } = require("@axe-core/puppeteer"); const puppeteer = require("puppeteer"); class AccessibilityAuditor { constructor(options = {}) { this.wcagLevel = options.wcagLevel || "AA"; this.viewport = options.viewport || { width: 1920, height: 1080 }; } async runFullAudit(url) { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setViewport(this.viewport); await page.goto(url, { waitUntil: "networkidle2" }); const results = await new AxePuppeteer(page) .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]) .exclude(".no-a11y-check") .analyze(); await browser.close(); return { url, timestamp: new Date().toISOString(), violations: results.violations.map((v) => ({ id: v.id, impact: v.impact, description: v.description, help: v.help, helpUrl: v.helpUrl, nodes: v.nodes.map((n) => ({ html: n.html, target: n.target, failureSummary: n.failureSummary, })), })), score: this.calculateScore(results), }; } calculateScore(results) { const weights = { critical: 10, serious: 5, moderate: 2, minor: 1 }; let totalWeight = 0; results.violations.forEach((v) => { totalWeight += weights[v.impact] || 0; }); return Math.max(0, 100 - totalWeight); } }

几个值得注意的参数细节:

  • .withTags([...]):用 WCAG 标签限定检测范围。wcag2a/wcag2aa对应 WCAG 2.0 的 A/AA 级,wcag21a/wcag21aa对应 WCAG 2.1。若目标升级到 WCAG 2.2,可参照配套技能 wcag-audit-patterns/SKILL.md 中的写法改用['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa']
  • .exclude(".no-a11y-check"):跳过被标记为不参与检测的 DOM 区域,适合排除第三方嵌入、广告位等无法控制的内容。
  • waitUntil: "networkidle2":等待网络空闲后再扫描,确保 SPA 与异步内容已渲染完毕,减少误报。
  • calculateScore:把违规按影响级别加权折算成 0~100 的评分(critical=10、serious=5、moderate=2、minor=1),低于 100 说明存在可扣分项,用于后续报告中的总览展示。

组件级检测:jest-axe

除整页扫描外,命令还给出面向 React 组件测试的 jest-axe 方案(expect.extend(toHaveNoViolations)),适合在单元测试阶段就拦截无障碍回归,把"页面级检测"下沉为"组件级守门"。

颜色对比度验证:从算法到高对比模式适配

命令第二节给出自研的ColorContrastAnalyzer(accessibility-audit.md),用于扫描页面所有文本节点并计算 WCAG 对比度。

阈值模型与计算逻辑

class ColorContrastAnalyzer { constructor() { this.wcagLevels = { 'AA': { normal: 4.5, large: 3 }, 'AAA': { normal: 7, large: 4.5 } }; } // ... calculateContrast(fg, bg) { const l1 = this.relativeLuminance(this.parseColor(fg)); const l2 = this.relativeLuminance(this.parseColor(bg)); const lighter = Math.max(l1, l2); const darker = Math.min(l1, l2); return (lighter + 0.05) / (darker + 0.05); } relativeLuminance(rgb) { const [r, g, b] = rgb.map(val => { val = val / 255; return val <= 0.03928 ? val / 12.92 : Math.pow((val + 0.055) / 1.055, 2.4); }); return 0.2126 * r + 0.7152 * g + 0.0722 * b; } }

算法要点:

  • 阈值表:AA 级普通文本需 ≥ 4.5:1、大文本(18pt 及以上,或 14pt 加粗)需 ≥ 3:1;AAA 级对应 7:1 与 4.5:1。这与 wcag-audit-patterns 中 WCAG 2.2 的 1.4.3 成功标准(文本 4.5:1、大文本与 UI 组件 3:1)一致。
  • 相对亮度公式:严格实现 WCAG 2.x 的线性化公式(γ 校正分段函数),再按0.2126R + 0.7152G + 0.0722B加权求和,对比度取(L1+0.05)/(L2+0.05)
  • 页面扫描逻辑:遍历document.querySelectorAll('*')中带文本的元素,读取getComputedStyle得到前景色、背景色、字号与字重,自动判断是否属于"大文本",凡低于 AA 阈值者全部记录(含当前值、要求值、前后景色),便于批量修复。

高对比模式适配

同一节还给出prefers-contrast: high媒体查询示例,将主文本/背景/边框强制为纯黑纯白并加粗边框、强制链接下划线,保证高对比系统偏好下信息不丢失。这与视觉验证 Agent ui-visual-validator.md 的 "High Contrast Mode Testing" 能力(在无障碍覆盖层与高对比环境下做视觉验证)相互呼应:代码层适配 + 视觉层核验缺一不可。

键盘导航测试:发现焦点陷阱与缺失的焦点指示

命令第三节的KeyboardNavigationTester(accessibility-audit.md)模拟真实键盘操作,逐项验证可访问性:

class KeyboardNavigationTester { async testKeyboardNavigation(page) { const results = { focusableElements: [], missingFocusIndicators: [], keyboardTraps: [], }; const focusable = await page.evaluate(() => { const selector = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'; return Array.from(document.querySelectorAll(selector)).map((el) => ({ tagName: el.tagName.toLowerCase(), text: el.innerText || el.value || el.placeholder || "", tabIndex: el.tabIndex, })); }); // 逐元素按 Tab,检查 document.activeElement 的 outline 是否可见 for (let i = 0; i < focusable.length; i++) { await page.keyboard.press("Tab"); const focused = await page.evaluate(() => { const el = document.activeElement; return { tagName: el.tagName.toLowerCase(), hasFocusIndicator: window.getComputedStyle(el).outline !== "none", }; }); if (!focused.hasFocusIndicator) { results.missingFocusIndicators.push(focused); } } return results; } }

它输出的三类结果对应 WCAG 2.2 的 Operable(可操作)原则:可聚焦元素清单(验证 2.1.1 键盘可达)、缺失焦点指示(验证 2.4.7 焦点可见)、键盘陷阱(验证 2.1.2 无键盘陷阱)。配套的修复代码则给出两个高频场景:

  • Escape 关闭模态框:为keydown注册 Escape 处理器,关闭.modal.open
  • 让带onclick的 div 可被键盘操作:自动补tabindex="0"role="button",并监听 Enter/Space 触发点击。

关于焦点管理的完整实现(模态框打开时记忆焦点、关闭时归还焦点、Tab 循环陷阱),可进一步参考 screen-reader-testing/SKILL.md 的 "Modal Dialog" 一节,那里给出了openModal/closeModal/trapFocus的完整 JS 实现。

屏幕阅读器测试:结构与表单语义验证

命令第四节把"自动化能测到的"和"必须靠人听的"衔接起来。ScreenReaderTester(accessibility-audit.md)提供四个自动检测维度:

  1. 地标(Landmarks):验证<main><nav>等语义区域;
  2. 标题结构(Headings):遍历h1~h6,检查是否存在跳级(如 h2 直接跳到 h4)、空标题、以及页面缺失h1——对应 WCAG 2.4.6 标题与标签;
  3. 图片可访问性:检查 alt 文本;
  4. 表单可访问性:遍历form内所有input/textarea/select,确认每个控件要么有匹配的label[for]、要么被label包裹、要么带有aria-label,否则记为 missing-label。

同时,命令给出三组可直接复用的 ARIA 模式:

<!-- 模态框 --> <div role="dialog" aria-labelledby="modal-title" aria-modal="true"> <h2 id="modal-title">Modal Title</h2> <button aria-label="Close">×</button> </div> <!-- 标签页 --> <div role="tablist" aria-label="Navigation"> <button role="tab" aria-selected="true" aria-controls="panel-1">Tab 1</button> </div> <div role="tabpanel" id="panel-1" aria-labelledby="tab-1">Content</div> <!-- 表单错误提示 --> <label for="name">Name <span aria-label="required">*</span></label> <input id="name" required aria-required="true" aria-describedby="name-error"> <span id="name-error" role="alert" aria-live="polite"></span>

用真实屏幕阅读器做人工验证

自动化只能覆盖语义层,真正的"可听性"必须由人验证。本插件配套技能 screen-reader-testing/SKILL.md 给出了五大主流屏幕阅读器的实测方法与优先级:

屏幕阅读器平台常用浏览器覆盖优先级
VoiceOvermacOS/iOSSafari最低覆盖必测(macOS + iOS)
NVDAWindowsFirefox/Chrome最低覆盖必测
JAWSWindowsChrome/IE综合覆盖补充
TalkBackAndroidChrome综合覆盖补充
NarratorWindowsEdge综合覆盖补充

最低覆盖组合为NVDA + Firefox(Windows)VoiceOver + Safari(macOS/iOS)。以 VoiceOver 为例,其核心操作:

  • 修饰键VO = Ctrl + OptionCmd + F5启停;VO + 右箭头下一个元素、VO + Shift + Down进入分组;
  • 转子VO + U:按标题、链接、表单、地标分类跳转;
  • 网页快捷键:VO + Cmd + H下一个标题、VO + Cmd + J下一个表单控件、VO + Cmd + L下一个链接、VO + Cmd + T下一个表格。

NVDA(Insert为修饰键)则支持更细的单键导航:H标题、F表单字段、B按钮、K链接、D地标、T表格,NVDA + F7打开元素列表。技能中还强调 NVDA 的浏览/焦点双模式(NVDA + Space手动切换)——浏览模式下方向键移动阅读光标,焦点模式下方向键操作控件,测试时必须覆盖两种模式。

对于动态内容,技能列出最易踩坑的三类问题与修复:

<!-- 问题:按钮只有图标,不播报用途 --> <button aria-label="Close dialog"><svg aria-hidden="true">...</svg></button> <!-- 问题:动态加载结果不播报 --> <div id="results" role="status" aria-live="polite">New results loaded</div> <!-- 问题:表单错误不被朗读 --> <input type="email" aria-invalid="true" aria-describedby="email-error" /> <span id="email-error" role="alert">Invalid email</span>

live region 的语义差异也在技能中有明确区分:role="status"/aria-live="polite"在当前语音播报完成后告知;role="alert"/aria-live="assertive"立即打断当前播报;role="log"仅播报新增内容;role="progressbar"配合aria-valuenow/min/max播报进度。

人工测试检查清单:键盘、屏幕阅读器、视觉与认知四维

自动化工具只能发现约三到五成问题(这也是 wcag-audit-patterns/SKILL.md 的 Best Practices 中明确提示的边界),因此命令第五节提供了完整的人工检查清单(accessibility-audit.md):

键盘

  • 所有交互元素可用 Tab 到达
  • 按钮可用 Enter/Space 激活
  • Esc 关闭模态框
  • 焦点指示始终可见
  • 无键盘陷阱
  • Tab 顺序符合逻辑

屏幕阅读器

  • 页面标题有描述性
  • 标题构成逻辑大纲
  • 图片有 alt 文本
  • 表单字段有标签
  • 错误信息被播报
  • 动态更新被播报

视觉

  • 文本可放大到 200% 且无内容丢失
  • 颜色不是传递信息的唯一手段
  • 焦点指示对比度足够
  • 320px 宽度下内容可重排
  • 动画可暂停

认知

  • 指令清晰简单
  • 错误提示有助益
  • 表单无时间限制
  • 导航一致
  • 重要操作可撤销

这套清单与 wcag-audit-patterns/references/details.md 中按 WCAG 2.2 四大原则(可感知 Perceivable、可操作 Operable、可理解 Understandable、健壮 Robust,即 POUR)展开的逐条成功标准核对表一一对应,例如:1.4.10 Reflow(400% 缩放无双向滚动、320px 宽可访问)、2.4.11 Focus Not Obscured(WCAG 2.2 新增:焦点元素不被吸顶头遮挡)、4.1.3 Status Messages(状态更新通过 live region 播报)等。需要逐条核对时可打开该参考文件按成功标准编号推进。

修复示例:从扫描结果到可访问组件

命令第六节(accessibility-audit.md)给出批量修复与可访问组件模板:

// 修复缺失 alt 文本:装饰性图片置空 alt,其余取 title 兜底 document.querySelectorAll("img:not([alt])").forEach((img) => { const isDecorative = img.role === "presentation" || img.closest('[role="presentation"]'); img.setAttribute("alt", isDecorative ? "" : img.title || "Image"); }); // 修复缺失标签:无 id 且无 aria-label 的输入框,用 placeholder 兜底 document.querySelectorAll("input:not([aria-label]):not([id])").forEach((input) => { if (input.placeholder) { input.setAttribute("aria-label", input.placeholder); } });

以及 React 组件级的最佳实践:

const AccessibleButton = ({ children, onClick, ariaLabel, ...props }) => ( <button onClick={onClick} aria-label={ariaLabel} {...props}> {children} </button> ); const LiveRegion = ({ message, politeness = "polite" }) => ( <div role="status" aria-live={politeness} aria-atomic="true" className="sr-only" > {message} </div> );

这里的原则与 wcag-audit-patterns/references/details.md 的 Remediation Patterns 一致:优先语义 HTML(<label>),ARIA 是补充而非首选。该文件给出了表单标签缺失的三种修复优先级(可见<label>>aria-label>aria-labelledby)、颜色对比度不足的调色示例(2.5:1 → 4.5:1),以及自定义下拉框role="combobox"+ 键盘事件(Enter/Space 展开、Escape 关闭、方向键切换)的完整实现。

CI/CD 集成:把无障碍检查固化为门禁

命令第七节给出 GitHub Actions 工作流(accessibility-audit.md),实现 push/PR 自动扫描:

# .github/workflows/accessibility.yml name: Accessibility Tests on: [push, pull_request] jobs: a11y-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: "18" - name: Install and build run: | npm ci npm run build - name: Start server run: | npm start & npx wait-on http://localhost:3000 - name: Run axe tests run: npm run test:a11y - name: Run pa11y run: npx pa11y http://localhost:3000 --standard WCAG2AA --threshold 0 - name: Upload report uses: actions/upload-artifact@v4 if: always() with: name: a11y-report path: a11y-report.html

要点:

  • 双层工具:axe(npm run test:a11y,对应前面的 Puppeteer/jest-axe 用例)负责规则级扫描,pa11y(npx pa11y http://localhost:3000 --standard WCAG2AA --threshold 0)负责整页级审计,--threshold 0表示"零容忍",任何违规即失败,形成硬性门禁;
  • if: always():即使审计失败也上传报告 artifact,方便开发者在 PR 中直接查看违规详情;
  • 与之互补的 CLI 工具还包括npx @axe-core/cli <url>lighthouse <url> --only-categories=accessibility(见 wcag-audit-patterns/references/details.md 的 Automated Testing 一节)。

报告输出:结构化的审计结果

命令第八节提供AccessibilityReportGenerator(accessibility-audit.md),将审计结果渲染为自包含 HTML 报告:顶部为总分摘要(${auditResults.score}/100与违规总数),下方按影响级别着色(critical 红、serious 橙)逐条列出每个违规的标题、影响级别、描述与学习链接。

结合命令末尾的Output Format(accessibility-audit.md),一次完整的审计应交付五类产出:

  1. Accessibility Score:整体 WCAG 合规评分;
  2. Violation Report:带严重级别与修复建议的详细问题清单;
  3. Test Results:自动化与人工测试结果;
  4. Remediation Guide:逐问题的分步修复方案;
  5. Code Examples:可访问组件的实现示例。

与配套 Agent、技能的协作分工

在真实工作流中,accessibility-audit命令通常与本插件其他组件协同:

  • 命令(accessibility-audit.md)负责启动整场审计、编排自动化扫描与报告产出;
  • 技能 screen-reader-testing(SKILL.md)在需要真机朗读验证、排查 ARIA 问题时被自动激活,提供 VoiceOver/NVDA/JAWS/TalkBack 的完整操作手册、检查清单与常见问题修复;
  • 技能 wcag-audit-patterns(SKILL.md)在需要按 WCAG 2.2 逐条核对、准备 VPAT/ADA/Section 508 合规材料时激活,其 references/details.md 提供按成功标准编号展开的完整核对表;
  • Agent ui-visual-validator(ui-visual-validator.md)作为视觉侧守门人,通过截图像素级比对、高对比模式验证、焦点指示可见性评估等方式,从"看得见"的维度复核无障碍修复是否真正落地——它与命令的"测得到"维度正好互补。

值得注意的是,命令与技能都反复强调同一原则:自动化(axe/pa11y)只能发现部分问题,屏幕阅读器与真实用户的人工验证不可替代;ARIA 应作为语义 HTML 的补充而非替代;键盘先行(先保证纯键盘可用)是屏幕阅读器测试的地基。将命令的八步方法论、技能的实操手册与本插件(安装后自动发现的 agents/commands/skills)组合使用,即可在企业级项目中建立从"自动扫描 → 专项验证 → 人工复核 → 修复整改 → CI 门禁"的完整无障碍闭环。

【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 5:17:29

RabbitMQ高可用镜像队列实战:从集群搭建到生产故障恢复指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 5:16:59

LLM判官稳定性排查指南:输入、提示、模型、解析四维调优

1. 项目概述&#xff1a;当“判官”开始打摆子&#xff0c;我们到底在评什么&#xff1f;“判官不稳定时&#xff0c;先别换判官”——这句话刚在内部评测群里刷出来&#xff0c;我就盯着屏幕愣了三秒。不是因为措辞犀利&#xff0c;而是它精准戳中了当前LLM-as-Judge实践里最常…

作者头像 李华
网站建设 2026/9/11 5:16:55

Puter Worker 中 me.puter 与 user.puter 两种上下文怎么选择?

Puter Worker 中 me.puter 与 user.puter 两种上下文怎么选择&#xff1f; 【免费下载链接】puter &#x1f310; The Internet Computer! Free, Open-Source, and Self-Hostable. 项目地址: https://gitcode.com/GitHub_Trending/pu/puter 在 Puter 中写 Serverless Wo…

作者头像 李华
网站建设 2026/9/11 5:12:02

破解ZLibrary反爬机制:Python爬虫高级技巧

1. 项目背景与核心挑战ZLibrary作为全球最大的数字图书馆之一&#xff0c;其反爬机制经历了多次迭代升级。2023年最新统计显示&#xff0c;平台日均拦截异常请求超过1200万次&#xff0c;其中针对Python爬虫的识别准确率高达92%。这主要得益于其动态渲染验证、行为指纹分析和请…

作者头像 李华
网站建设 2026/9/11 5:09:45

铸造行业温度控制技术突破与应用实践

1. 铸造行业温度控制的痛点与挑战在铸造生产线上&#xff0c;金属熔液的温度控制精度直接决定了铸件质量和工艺稳定性。以某年产20万吨的大型球墨铸铁厂为例&#xff0c;其熔炼车间每天需要处理超过600吨铁水&#xff0c;温度波动超过15℃就会导致球化不良、缩松等缺陷&#xf…

作者头像 李华