# @a11y-oracle/focus-analyzer 中文文档

规范地址：https://npmcn.com/package/%40a11y-oracle/focus-analyzer/

版本：1\.3\.2
npm 元数据更新时间：2026-03-12T05:47:17.745Z
中文译文更新时间：2026-11-06T02:35:34.942Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40a11y-oracle/focus-analyzer
原文对照：https://npmcn.com/package/%40a11y-oracle/focus-analyzer/?lang=original
项目主页：https://github.com/a11y-oracle/a11y-oracle/tree/main/libs/focus-analyzer
源码仓库：https://github.com/a11y-oracle/a11y-oracle

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：38.9 kB，17 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：3 个
- 首次发布：2026-03-04T19:25:03.932Z
- 最新版本发布：2026-03-12T05:47:17.603Z
- 近 30 天下载量：6255（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：10（近 12 个月 10 个）

## 中文简介

焦点指标 CSS 分析(WCAG 2.4.12),制表指令提取和键盘陷阱检测

## 安装

```sh
npm install @a11y-oracle/focus-analyzer
```

也可以使用：`pnpm add @a11y-oracle/focus-analyzer`、`yarn add @a11y-oracle/focus-analyzer`、`bun add @a11y-oracle/focus-analyzer`

## README

# @a11y-oracle/焦点分析器

无障碍测试的重点状态分析. 提供视觉焦点指标检查,WCAG对比比计算,DOM制取分页指令,以及键盘陷阱检测.

这是内部使用的低层构件 `@a11y-oracle/core-engine`。大多数用户应该使用 Playwright 或 Cypress 插件.

## 安装

```bash
npm install @a11y-oracle/focus-analyzer
```

## 使用量

```typescript
import { FocusAnalyzer } from '@a11y-oracle/focus-analyzer';

const analyzer = new FocusAnalyzer(cdpSession);

// Analyze the focus indicator on the currently focused element
const indicator = await analyzer.getFocusIndicator();
console.log(indicator.isVisible);     // true
console.log(indicator.contrastRatio); // 12.63
console.log(indicator.meetsWCAG_AA);  // true (visible + contrast >= 3.0)
console.log(indicator.outlineColor);  // "rgb(0, 95, 204)"
console.log(indicator.outlineWidth);  // "3px"

// Extract all tabbable elements in DOM tab order
const entries = await analyzer.getTabOrder();
entries.forEach(e => {
  console.log(`${e.index}: ${e.tag}#${e.id} (tabIndex=${e.tabIndex})`);
});

// Detect keyboard traps (WCAG 2.1.2)
const result = await analyzer.detectKeyboardTrap('#modal-container', 20);
if (result.isTrapped) {
  console.log('Focus is trapped!');
} else {
  console.log(`Focus escaped to: ${result.escapeElement?.tag}`);
}
```

## API 参考

### `FocusAnalyzer`

#### `constructor(cdp: CDPSessionLike)`

创建一个新的焦点分析器 。 内部创建 a `KeyboardEngine` 用于探测陷阱.

-   `cdp` - 任何 CDP 兼容的会话(使用 `CDPSessionLike` 界面从 `@a11y-oracle/cdp-types`) (中文(简体) ).

#### `getFocusIndicator(): Promise<FocusIndicator>`

分析当前焦点元素的视觉焦点指标.

提取计算 CSS 属性(`outline`, (中文(简体) ), `box-shadow`, (中文(简体) ), `border-color`, (中文(简体) ), `background-color`)通过 `Runtime.evaluate`,然后对照背景计算焦点指标的对比率.

如果没有元素焦点,则返回默认的“不可见”指标.

**可见度检测 :**

-   元素有可见 **大纲** 若为 `outline-width` 没有 `0px` 和轮廓颜色有一个非零的α通道(探测两个 `transparent` 关键词和 `rgba(0, 0, 0, 0)` 其 Chrome 报告为透明大纲)
-   元素有可见 **框阴影** 若为 `box-shadow` 没有 `none`

**对比计算 :**

-   大纲:对比比 `outline-color` 财务报告和审定财务报表 `background-color`
-   对于框阴影:取出所有颜色 `box-shadow` 值,过滤出透明值,并使用 **最外向可见的颜色** (最后不透明)用于对比计算。 这样可以正确处理Tailwind CSS多环模式,其中装饰的空间器环会先出现而实际的焦点指示环会后出现.
-   回返 `contrastRatio: null` 如果颜色不能可靠地解析(例如梯度、复杂的颜色函数)

**2.4.12 AA 遵守情况:** `meetsWCAG_AA` 实值 `true` 当指标可见,而对比比为 QQ 3.0.

#### `getTabOrder(): Promise<TabOrderEntry[]>`

按标签顺序从 DOM 中提取所有可制表元素 .

可聚焦要素的查询(`a[href]`, (中文(简体) ), `button:not([disabled])`, (中文(简体) ), `input:not([disabled])`, (中文(简体) ), `select:not([disabled])`, (中文(简体) ), `textarea:not([disabled])`, (中文(简体) ), `[tabindex]`,然后过滤出 :

-   要件 `tabIndex < 0`
-   隐藏元素( E)`display: none`, (中文(简体) ), `visibility: hidden`(中文(简体) )
-   无布局的元素( N)`offsetParent === null`(中文(简体) )
-   内部要素 `[inert]` 集装箱

结果按 `tabIndex` 数值:正数 `tabIndex` 数值首先(升起),然后 `tabIndex=0` dOM 顺序中的元素.

#### `detectKeyboardTrap(selector: string, maxTabs?: number): Promise<TraversalResult>`

检测焦点是否被困在容器内(WCAG 2.1.2).

1.  将第一个可制表元素放在容器匹配中 `selector`
2.  多次按下标签(最多 `maxTabs`,默认为50)
3.  每个标签后检查焦点是否离开了容器
4.  如果焦点脱逃,立即返回,或者如果 `maxTabs` 已经用尽

回返 `{ isTrapped: false, tabCount: 0 }` 如果容器不存在或没有可聚焦元素.

### 纯公用函数

软件包还输出纯函数用于色彩解析和WCAG对比计算:

#### `parseColor(css: string): RGBColor | null`

将 CSS 颜色字符串分析为 `RGBColor` 对象。 支持 :

-   `rgb(r, g, b)` 财务报告和审定财务报表 `rgba(r, g, b, a)`
-   十六进制颜色 : `#RGB`, (中文(简体) ), `#RRGGBB`, (中文(简体) ), `#RRGGBBAA`
-   `transparent` (回报) `{ r: 0, g: 0, b: 0, a: 0 }`(中文(简体) )

回返 `null` 用于不支持的格式(名称颜色, `hsl()`, (中文(简体) ), `color()`(见a/c.5/49/70,附件).

#### `srgbToLinear(channel: number): number`

将 sRGB 通道值 (0-255) 转换为线性光.

#### `relativeLuminance(color: RGBColor): number`

计算 WCAG 相对亮度 : `L = 0.2126*R + 0.7152*G + 0.0722*B`

#### `contrastRatio(color1: RGBColor, color2: RGBColor): number`

计算两种颜色之间的WCAG对比比。 返回1(相同)至21(白色黑)之间的值.

#### `meetsAA(ratio: number): boolean`

请检查archive-date=中的日期值 (帮助) WCAG AA对焦指标的对比率是否与 WCAG AA相符合(QQ 3.0).

### 类型

#### `RGBColor`

```typescript
interface RGBColor {
  r: number; // 0-255
  g: number; // 0-255
  b: number; // 0-255
  a: number; // 0-1
}
```

#### `FocusIndicator`

全面重点指标分析:

```typescript
interface FocusIndicator {
  isVisible: boolean;
  outline: string;          // Raw outline shorthand
  outlineColor: string;     // e.g. "rgb(0, 95, 204)"
  outlineWidth: string;     // e.g. "3px"
  outlineOffset: string;    // e.g. "0px"
  boxShadow: string;        // e.g. "0px 0px 0px 3px rgb(52, 152, 219)"
  borderColor: string;
  backgroundColor: string;
  contrastRatio: number | null;
  meetsWCAG_AA: boolean;
}
```

#### `TabOrderEntry`

```typescript
interface TabOrderEntry {
  index: number;     // Position in tab order (0-based)
  tag: string;       // "BUTTON"
  id: string;
  textContent: string;
  tabIndex: number;
  role: string;
  rect: { x: number; y: number; width: number; height: number };
}
```

#### `TabOrderReport`

```typescript
interface TabOrderReport {
  entries: TabOrderEntry[];
  totalCount: number;
}
```

#### `TraversalResult`

```typescript
interface TraversalResult {
  isTrapped: boolean;                  // true if focus never escaped
  tabCount: number;                    // Total Tab presses attempted
  visitedElements: TabOrderEntry[];    // Elements that received focus
  escapeElement: TabOrderEntry | null; // First element outside container
}
```

## 出口

```typescript
export { FocusAnalyzer } from '@a11y-oracle/focus-analyzer';
export { parseColor } from '@a11y-oracle/focus-analyzer';
export { srgbToLinear, relativeLuminance, contrastRatio, meetsAA } from '@a11y-oracle/focus-analyzer';
export type { RGBColor, FocusIndicator, TabOrderEntry, TraversalResult, TabOrderReport } from '@a11y-oracle/focus-analyzer';
```

## 限制

-   **复杂的重点指标** - 梯级,CSS `color-mix()`,其它高级色彩函数返回 `contrastRatio: null` 因为它们无法可靠地解析成单一的颜色值.
-   **键盘陷阱检测** ——仅用 Tab 键进行测试. 故意聚焦陷阱(如模式对话框)应当与"逃生"键导航单独测试.
-   **`tabIndex` 命令** ——制表命令提取遵循了标准算法(正数) `tabIndex` 先说 `tabIndex=0` 在DOM顺序中),但不计入Shadow DOM边界.

## 常见问题

### @a11y-oracle/focus-analyzer 是什么？

焦点指标 CSS 分析\(WCAG 2\.4\.12\),制表指令提取和键盘陷阱检测

### 如何安装 @a11y-oracle/focus-analyzer？

在项目目录运行 npm install @a11y-oracle/focus-analyzer，或使用 pnpm add / yarn add / bun add。

### @a11y-oracle/focus-analyzer 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @a11y-oracle/focus-analyzer 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @a11y-oracle/focus-analyzer 可以商用吗？

@a11y-oracle/focus-analyzer 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @a11y-oracle/focus-analyzer 的下载量有多少？

根据 npm 官方下载统计，@a11y-oracle/focus-analyzer 在 2026/10/05 – 2026/11/03 这 30 天内被下载 6,255 次，日均约 209 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @a11y-oracle/focus-analyzer 还在维护吗？

最新版本 1\.3\.2 发布于 2026/03/12（7 个月前）；至今共发布 10 个版本，其中过去 12 个月发布了 10 个；首次发布于 2026/03/05。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

