@ a11y- oracle/ 轴桥
Axe-core结果后处理器,通过视觉分析,键盘交互,以及CDP检查来解决"不完全"(Needs Review)结果. 轴- 核心的中间软件 analyze() 还有你的主张.
问题
轴-核标记规则在需要状态变化,相互作用,或空间意识,静态DOM分析无法可靠地进行时被标记为"不完全". 这在CI仪表板中产生噪音,需要人工审查颜色对比,焦点指标,目标大小等规则.
解决办法
resolveAllIncomplete() 取得核心成果,并举行社区发展方案现场会议,然后通过10个专门解决者进行管道工作,促进从 incomplete 改为 passes 或者说 violations数字 :
| {\fn方正粗倩简体\fs12\an8\1cHFFFF00\b0} | 规则ID | WCAG 常设委员会 | 技术 |
|---|---|---|---|
| 1个 | color-contrast | 1.4.3 国家 | CSS 光环热学+像素级截图分析 |
| 2个 | identical-links-same-purpose | 2.4.4 (中文(简体) ) | URL 正常化和比较 |
| 3个 | link-in-text-block | 1.4.1 国家 | 默认状态计算样式检查 |
| 页:1 | target-size | 2.5.8 国家 | 边框测量+间距 |
| 页:1 | scrollable-region-focusable | 2.1.1 国家 | 滚动高度 + 可聚焦儿童转动 |
| 6个 | skip-link | 2.4.1 国家 | 标签焦点能见度验证 |
| 第7条 | aria-hidden-focus | 4.1.2 国家 | 全键盘 Tab 翻转 |
| 第8条 | focus-indicator | 2.4.7 国家 | 截图像素 diff 前后 |
| 第9条 | content-on-hover | 1.4.13 国家 | Hover + 排除交互测试 |
| 10个 | frame-tested | 不详 | 跨原产地iframe轴-核心注射 |
安装
npm install @a11y-oracle/axe-bridge
使用量
解决所有不完整(建议)
import { resolveAllIncomplete } from '@a11y-oracle/axe-bridge';
// After running axe-core while the page is still live:
const axeResults = await axe.run(document);
const resolved = await resolveAllIncomplete(cdpSession, axeResults);
// resolved.incomplete will have fewer (or zero) entries
// resolved.violations and resolved.passes will have the promoted entries
有选项
const resolved = await resolveAllIncomplete(cdpSession, axeResults, {
wcagLevel: 'wcag22aa',
contrast: {
threshold: 4.5, // normal text contrast ratio
largeTextThreshold: 3.0, // large text contrast ratio
supermajorityPassRatio: 0.75, // auto-pass split decisions when 75%+ pixels pass
bestCaseMultiplier: 2.0, // auto-pass when best-case CR exceeds 2× threshold
},
focusIndicator: { focusSettleDelay: 150, diffThreshold: 0.2 },
skipRules: ['frame-tested'], // skip specific resolvers
});
个人解决者
每个解析器可以单独使用:
import { resolveIncompleteContrast } from '@a11y-oracle/axe-bridge';
const resolved = await resolveIncompleteContrast(cdpSession, axeResults, {
wcagLevel: 'wcag22aa',
});
与剧作家
import { test, expect } from '@playwright/test';
import { resolveAllIncomplete } from '@a11y-oracle/axe-bridge';
test('no unresolved accessibility issues', async ({ page }) => {
await page.goto('/my-page.html');
const cdp = await page.context().newCDPSession(page);
const axeResults = await axe.run(document);
const resolved = await resolveAllIncomplete(cdp, axeResults);
expect(resolved.violations).toHaveLength(0);
expect(resolved.incomplete).toHaveLength(0);
await cdp.detach();
});
与赛普斯
// Using Cypress.automation for CDP access:
cy.window().then(async (win) => {
const axeResults = await axeCore.run(win.document);
// cdpSession obtained via Cypress.automation('remote:debugger:protocol', ...)
const resolved = await resolveAllIncomplete(cdpSession, axeResults);
expect(resolved.violations).to.have.length(0);
});
API 参考
resolveAllIncomplete(cdp, axeResults, options?)
管子能按顺序通过所有10个溶液 每个解析器都收到上一个的输出.
- 参数:
cdp: CDPSessionLike—— CDP会话连接到页面axeResults: AxeResults- 轴心核心的原始结果analyze()options?: IncompleteResolutionOptions- 替代选择和skipRules过滤器
- 回返情况:
Promise<AxeResults>——经修改的附解结论的副本 - 管道顺序 : 相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相通相相通相通相通相通相通相通相通相通相通相通相通相通相通相相相通相通相通相相通相通相通相通相通相通相相相通相通相相相相相相相相相通相通相
个人解决者
resolveIncompleteContrast(cdp, axeResults, options?)
决定: color-contrast 使用 CSS 光电图和像素级截图分析的不完整条目. 已解决的节点(通过和违反)在轴检查中以对比数据来丰富 data 字段,包括 contrastRatio, (中文(简体) ), expectedRatio, (中文(简体) ), fgColor, (中文(简体) ), bgColorLightest, (中文(简体) ), bgColorDarkest,以及 algorithm (单位:千美元)'visual-pixel' 或者说 'visual-halo') (中文(简体) ).
- 选项 :
ContrastResolutionOptions数字 :wcagLevel- WCAG 合规级别(默认:'wcag22aa'。阈值是自动得出的(AA → 4.5/3.0)。 A级没有对应的SC,所以解析器被跳过.threshold常规文本的最小对比比(覆盖)wcagLevel(中文(简体) )largeTextThreshold大于大文本的最小对比率(覆盖)wcagLevel(中文(简体) )supermajorityPassRatio——在分出决定(一个极端通过,一个失败)时,如果至少是这个像素通过的比例(默认:0.75(中文(简体) )bestCaseMultiplier——在分拆裁定中,如果最佳案例对比率超过阈值乘以该值,则自动通过(默认:2.0(中文(简体) )
- 从轴-核的检查数据自动检测出大文本(QQ 24px或粗QQ 18.66px)
resolveIdenticalLinksSamePurpose(cdp, axeResults)
决定: identical-links-same-purpose 通过将 URL 正常化( 截取查询参数, 散列, 解析相对路径)并比较目的地 .
- 同一个目的地 过, 不同 ) 违反
resolveLinkInTextBlock(cdp, axeResults, options?)
决定: link-in-text-block 通过检查 默认/恢复状态 非彩色视觉指示器.
- 选项 :
LinkInTextBlockOptions—— 说linkTextContrastThreshold(默认: 3.0) - 检查 :
text-decoration: underline, (中文(简体) ),border-bottom > 0, (中文(简体) ),font-weight与父母的差别 - 如果没有非颜色指标: 比较链接与周围文本颜色对比
resolveTargetSize(cdp, axeResults, options?)
决定: target-size 通过测量边框和中枢间距.
- 选项 :
TargetSizeOptions—— 说minSize(默认:24) - 宽度/高度 = 24px = 过; 24px+相距小于 − 过;否则—— 违反
resolveScrollableRegionFocusable(cdp, axeResults, options?)
决定: scrollable-region-focusable 检查卷轴高度、标签索引和可聚焦儿童.
- 选项 :
ScrollableRegionOptions—— 说maxChildren(默认:50) - 不实际可滚动 ~ 过; 有过
tabindex >= 0→ 过;可聚焦儿童滚动到内容 ~ 过
resolveSkipLink(cdp, axeResults, options?)
决定: skip-link 通过将跳过链接聚焦并验证它变得可见.
- 选项 :
SkipLinkOptions—— 说focusSettleDelay(默认:100) - 检查边框、取景口封存、不透明、剪辑、位置
resolveAriaHiddenFocus(cdp, axeResults, options?)
决定: aria-hidden-focus 通过单一键盘 Tab 横跨所有被标记的节点.
- 选项 :
AriaHiddenFocusOptions—— 说maxTabs(默认:100) - 标有标记的元素上的标签地- 违反穿越完成,没有着陆 过
resolveFocusIndicator(cdp, axeResults, options?)
决定: focus-indicator 由焦点截取前后的像素分解. 元素被滚动到取景口后再被捕获,确保外屏元素产生有效的截图. 启用焦点模拟 Emulation.setFocusEmulationEnabled 因此焦点指标即使在无头浏览器或 Cypress AUT iframes 中也能产生.
- 选项 :
FocusIndicatorOptions—— 说focusSettleDelay(默认:100),diffThreshold(默认:0.1%) - 截图完全相同 – 违反; 像素已更改 ~ 过
resolveContentOnHover(cdp, axeResults, options?)
决定: content-on-hover 与徘徊和解除交互测试.
- 选项 :
ContentOnHoverOptions—— 说hoverDelay(默认:300),dismissDelay(默认: 200) - 测试: 内容出现在悬浮上, 当鼠标移动到内容( 可控) 时会留下, 在 Escape (可解除) 上消失
resolveFrameTested(cdp, axeResults, options?)
决定: frame-tested 通过CDP将轴心投入跨出源的iframes.
- 选项 :
FrameTestedOptions—— 说axeSource(完整的轴-核心脚本),iframeTimeout(默认: 3000) - 用途
Page.createIsolatedWorld绕过同源限制
管道公用事业
所有解析器使用的共享助手 :
import {
getSelector, // Extract innermost CSS selector from axe node target
cloneResults, // Deep-clone AxeResults without mutation
ruleShell, // Create a rule shell (metadata only, no nodes)
findIncompleteRule, // Find a rule by ID in the incomplete array
applyPromotions, // Move nodes between incomplete/passes/violations
} from '@a11y-oracle/axe-bridge';
类型
import type {
// Axe-core compatible types
AxeResults,
AxeRule,
AxeNode,
AxeCheck,
// WCAG level
WcagLevel,
ContrastThresholds,
// Per-resolver options
ContrastResolutionOptions,
LinkInTextBlockOptions,
TargetSizeOptions,
ScrollableRegionOptions,
SkipLinkOptions,
AriaHiddenFocusOptions,
FocusIndicatorOptions,
ContentOnHoverOptions,
FrameTestedOptions,
// Orchestrator options
IncompleteResolutionOptions,
// Pipeline utility types
PromotionResult,
} from '@a11y-oracle/axe-bridge';
说明: Axe-core类型是本地定义的结构相容性而无需将轴-core作为运行时间依赖性.
如何运作
每个解析器都遵循一个共同的管道模式:
- 克隆 ——入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入入出出出出出出出出出出出出入入入入入入入入入入入入入入入入入入入入入入入入入入入
- 查找 目标规则在
incomplete数组 - 分析 ——对于每个被标记的节点,运行解析器的具体技术(CDP查询,截图,键盘转盘等)
- 宣传 — 将已解析的节点移动到
passes或者说violations; 未解决的节点留在incomplete
这个 resolveAllIncomplete 管弦乐团将所有解析器按顺序排列,因此发现结果通过管道积累.
依赖关系
@a11y-oracle/visual-engine——视觉分析引擎(卤素检测,像素分析,PNG解码,CDP捕获)@a11y-oracle/focus-analyzer— 颜色解析和对比比计算@a11y-oracle/keyboard-engine– 本地 CDP 键盘调度用于跳转链接, aria- hidden- focus, 和内容- hover@a11y-oracle/cdp-types—— 说CDPSessionLike用于框架不可知的 CDP 访问的界面