# @a11y-oracle/core-engine 中文文档

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

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

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

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

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

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

## 中文简介

通过 Chrome DevTools 协议实现框架不可知无障碍语音引擎和统一的 A11y Orchestrator

## 安装

```sh
npm install @a11y-oracle/core-engine
```

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

## README

# @a11y-oracle/ 核心引擎

A11y-Oracle 的框架不可知访问引擎. 提供两个主要的API:

1.  **`SpeechEngine`** ——通过CDP来读取浏览器的"无障碍树"并生成标准化的语音输出.
2.  **`A11yOrchestrator`** ——统一管弦乐器,将语音,键盘调度,焦点指标分析合并为一 `pressKey()` 电话.

这个软件包是Playwright和Cypress插件所建立的基础. 也可以直接与任何CDP兼容的客户端使用.

## 安装

```bash
npm install @a11y-oracle/core-engine
```

## 使用量

### 语音引擎( 只有语音)

语音引擎通过一个 `CDPSessionLike` 接口,任何 CDP 客户端都可以满足 :

```typescript
import { SpeechEngine } from '@a11y-oracle/core-engine';

// Works with Playwright's CDPSession
const cdpSession = await page.context().newCDPSession(page);
const engine = new SpeechEngine(cdpSession);
await engine.enable();

// Get speech for the currently focused element
const result = await engine.getSpeech();
console.log(result?.speech); // "Products, button, collapsed"

// Get speech for every visible element
const all = await engine.getFullTreeSpeech();
const nav = all.find(r => r.speech.includes('navigation landmark'));

// Clean up
await engine.disable();
```

### A11y Orchestrator(统一州)

管弦乐团协调语音引擎,键盘引擎,以及焦点分析器:

```typescript
import { A11yOrchestrator } from '@a11y-oracle/core-engine';

const cdpSession = await page.context().newCDPSession(page);
const orchestrator = new A11yOrchestrator(cdpSession);
await orchestrator.enable();

// Press a key and get unified state
const state = await orchestrator.pressKey('Tab');
console.log(state.speech);                       // "Products, button, collapsed"
console.log(state.focusedElement?.tag);           // "BUTTON"
console.log(state.focusIndicator.meetsWCAG_AA);  // true

// Get state without pressing a key
const current = await orchestrator.getState();

// Tab order extraction
const report = await orchestrator.traverseTabOrder();
console.log(report.totalCount);  // 12

// Keyboard trap detection (WCAG 2.1.2)
const result = await orchestrator.traverseSubTree('#modal', 20);
console.log(result.isTrapped);  // false

await orchestrator.disable();
```

### 配置选项

```typescript
const engine = new SpeechEngine(cdpSession, {
  // Include "landmark" suffix on landmark roles (default: true)
  // true:  "Main, navigation landmark"
  // false: "Main, navigation"
  includeLandmarks: true,

  // Include accessible descriptions in output (default: false)
  // true:  "Submit, button, Submits the form"
  // false: "Submit, button"
  includeDescription: false,
});

const orchestrator = new A11yOrchestrator(cdpSession, {
  // All SpeechEngine options, plus:

  // Milliseconds to wait after key press for focus/CSS to settle (default: 50)
  focusSettleMs: 50,
});
```

## API 参考

### `SpeechEngine`

语音引擎. 所有方法都是协同的,通过CDP会话运行.

#### `constructor(cdp: CDPSessionLike, options?: SpeechEngineOptions)`

创建新引擎实例 .

-   `cdp` - 任何执行 `CDPSessionLike` 接口.
-   `options.includeLandmarks` ——将"地标"附录为地标性角色. 默认 `true`。 。 。 .
-   `options.includeDescription` - 包含 `aria-describedby` 语句。 默认 `false`。 。 。 .

#### `enable(): Promise<void>`

启用 CDP 无障碍域 。 一定要在任何其他方法之前叫出来.

#### `disable(): Promise<void>`

禁用 CDP 无障碍域 。 完成后调用以释放浏览器资源 .

#### `getSpeech(): Promise<SpeechResult | null>`

获取当前焦点元素的语音输出 .

回返 `null` 如果没有元素有焦点或焦点元素被忽略(例如, `role="presentation"`) (中文(简体) ).

```typescript
const result = await engine.getSpeech();
if (result) {
  console.log(result.speech);  // "Products, button, collapsed"
  console.log(result.name);    // "Products"
  console.log(result.role);    // "button"
  console.log(result.states);  // ["collapsed"]
  console.log(result.rawNode); // Full CDP AXNode object
}
```

#### `getFullTreeSpeech(): Promise<SpeechResult[]>`

获得无障碍树上所有非受辱非寂静节点的演说. 用于坚持地标,标题,或结构元素没有焦点.

```typescript
const all = await engine.getFullTreeSpeech();
const headings = all.filter(r => r.role.includes('heading'));
const landmarks = all.filter(r => r.role.includes('landmark'));
```

#### `computeSpeech(node: AXNode): SpeechResult | null`

计算单个 AX 节点的语音 。 回返 `null` 被忽略或沉默的节点.

#### `findFocusedNode(nodes: AXNode[]): AXNode | null`

查找平坦 AXTree 阵列中最具体的焦点节点. 当多个节点报告时 `focused: true` (例如, `RootWebArea` (单位:千美元) `menuitem`),最深的节点被还原.

### `A11yOrchestrator`

协调三个分机的统一指挥员:

| 发动机 | 责任 |
| --- | --- |
| `SpeechEngine` | AXTree 到语音字符串 |
| `KeyboardEngine` | CDP 密钥发送 + `document.activeElement` |
| `FocusAnalyzer` | CSS 焦点指标 + 标签命令 + 陷阱检测 |

#### `constructor(cdp: CDPSessionLike, options?: A11yOrchestratorOptions)`

创建一个新的管弦乐团.

-   `cdp` 任何与协调委员会兼容的会议.
-   `options.includeLandmarks` ——将"地标"附录为地标性角色. 默认 `true`。 。 。 .
-   `options.includeDescription` - 包括说明案文。 默认 `false`。 。 。 .
-   `options.focusSettleMs` ——按键后延迟焦点/CSS结算. 默认 `50`。 。 。 .

#### `enable(): Promise<void>`

启用 CDP 无障碍域 。 必须先用其他方法.

#### `disable(): Promise<void>`

禁用 CDP 无障碍域 .

#### `pressKey(key: string, modifiers?: ModifierKeys): Promise<A11yState>`

调出一个关键媒体 并返回统一无障碍状态.

1.  发送 `keyDown` + 键 `keyUp` 通过CDP `Input.dispatchKeyEvent`
2.  等着 `focusSettleMs` 支助处过渡和重点活动
3.  并行收集语音、重点要素和重点指标

```typescript
const state = await orchestrator.pressKey('Tab');
// state.speech           → "Products, button, collapsed"
// state.focusedElement   → { tag: 'BUTTON', id: 'products-btn', ... }
// state.focusIndicator   → { isVisible: true, contrastRatio: 12.5, meetsWCAG_AA: true }

// With modifier keys
const prev = await orchestrator.pressKey('Tab', { shift: true });
```

#### `getState(): Promise<A11yState>`

获取当前统一状态而不按键 。 方案重点改变后有用.

```typescript
await page.focus('#my-button');
const state = await orchestrator.getState();
```

#### `traverseTabOrder(): Promise<TabOrderReport>`

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

```typescript
const report = await orchestrator.traverseTabOrder();
console.log(report.totalCount);     // 12
console.log(report.entries[0].tag); // "A"
console.log(report.entries[0].id);  // "home-link"
```

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

检测容器是否夹住键盘焦点(WCAG 2.1.2).

聚焦容器中的第一个可制表元素,按下标签至 `maxTabs` 时间(默认值50),并检查焦点是否逃脱.

```typescript
const result = await orchestrator.traverseSubTree('#modal-container', 20);
if (result.isTrapped) {
  console.log('Keyboard trap detected!');
  console.log(`Focus visited ${result.visitedElements.length} elements`);
} else {
  console.log(`Focus escaped to: ${result.escapeElement?.tag}`);
}
```

### 类型

#### `CDPSessionLike`

引擎和测试框架之间的抽象边界:

```typescript
interface CDPSessionLike {
  send(method: 'Accessibility.enable'): Promise<void>;
  send(method: 'Accessibility.disable'): Promise<void>;
  send(
    method: 'Accessibility.getFullAXTree',
    params?: { depth?: number; frameId?: string }
  ): Promise<{ nodes: AXNode[] }>;
  send(method: string, params?: Record<string, unknown>): Promise<unknown>;
}
```

两个剧作家的 `CDPSession` 财务报告和审定财务报表 `chrome-remote-interface` 客户端无需适配器即可满足此接口.

#### `SpeechResult`

归来 `getSpeech()` 财务报告和审定财务报表 `getFullTreeSpeech()`数字 :

```typescript
interface SpeechResult {
  speech: string;              // "Products, button, collapsed"
  name: string;                // "Products"
  role: string;                // "button"
  states: string[];            // ["collapsed"]
  rawNode: Protocol.Accessibility.AXNode;
}
```

#### `A11yState`

归来 `pressKey()` 财务报告和审定财务报表 `getState()`数字 :

```typescript
interface A11yState {
  speech: string;                          // "Products, button, collapsed"
  speechResult: SpeechResult | null;       // Full speech result with raw AXNode
  focusedElement: A11yFocusedElement | null; // DOM info
  focusIndicator: A11yFocusIndicator;      // CSS analysis
}
```

#### `A11yFocusedElement`

```typescript
interface A11yFocusedElement {
  tag: string;        // "BUTTON"
  id: string;         // "submit-btn"
  className: string;  // "btn primary"
  textContent: string; // "Submit"
  role: string;       // "button"
  ariaLabel: string;  // "Submit form"
  tabIndex: number;   // 0
  rect: { x: number; y: number; width: number; height: number };
}
```

#### `A11yFocusIndicator`

```typescript
interface A11yFocusIndicator {
  isVisible: boolean;           // true if outline or box-shadow detected
  contrastRatio: number | null; // null if colors unparseable
  meetsWCAG_AA: boolean;        // true if visible and contrast >= 3.0
}
```

#### `ModifierKeys`

```typescript
interface ModifierKeys {
  shift?: boolean;
  ctrl?: boolean;
  alt?: boolean;
  meta?: boolean;
}
```

#### `TabOrderReport`

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

#### `TabOrderEntry`

```typescript
interface TabOrderEntry {
  index: number;     // Position in tab order (0-based)
  tag: string;       // "BUTTON"
  id: string;        // "submit-btn"
  textContent: string;
  tabIndex: number;
  role: string;
  rect: { x: number; y: number; width: number; height: 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
}
```

## 角色绘图

这个 `ROLE_TO_SPEECH` 记录50+ CDP 角色值到语音字符串。 作用分为四类:

### 互动作用

| CDP 作用 | 发言 |
| --- | --- |
| `button` | `button` |
| `link` | `link` |
| `checkbox` | `checkbox` |
| `radio` | `radio button` |
| `textbox` | `edit text` |
| `combobox` | `combo box` |
| `slider` | `slider` |
| `switch` | `switch` |
| `tab` | `tab` |
| `menuitem` | `menu item` |
| `menuitemcheckbox` | `menu item checkbox` |
| `menuitemradio` | `menu item radio` |
| `option` | `option` |
| `searchbox` | `search text` |
| `spinbutton` | `spin button` |

### 地标角色

地标在 `includeLandmarks` 实值 `true`数字 :

| CDP 作用 | 发言 |
| --- | --- |
| `navigation` | `navigation landmark` |
| `main` | `main landmark` |
| `banner` | `banner landmark` |
| `contentinfo` | `content info landmark` |
| `complementary` | `complementary landmark` |
| `search` | `search landmark` |
| `region` | `region landmark` |
| `form` | `form landmark` |

### 结构作用

| CDP 作用 | 发言 |
| --- | --- |
| `heading` | `heading` |
| `list` | `list` |
| `listitem` | `list item` |
| `img` | `image` |
| `table` | `table` |
| `row` | `row` |
| `cell` | `cell` |
| `dialog` | `dialog` |
| `alert` | `alert` |
| `menu` | `menu` |
| `menubar` | `menu bar` |
| `toolbar` | `toolbar` |
| `tree` | `tree` |
| `treeitem` | `tree item` |
| `tablist` | `tab list` |
| `tabpanel` | `tab panel` |
| `progressbar` | `progress bar` |
| `tooltip` | `tooltip` |

### 寂静的角色

这些角色不会产生语音输出 :

`generic`, (中文(简体) ), `none`, (中文(简体) ), `presentation`, (中文(简体) ), `StaticText`, (中文(简体) ), `InlineTextBox`, (中文(简体) ), `LineBreak`, (中文(简体) ), `RootWebArea`, (中文(简体) ), `WebArea`, (中文(简体) ), `paragraph`, (中文(简体) ), `DescriptionListDetail`, (中文(简体) ), `DescriptionListTerm`, (中文(简体) ), `DescriptionList`

未知角色通过正即,以与新的ARIA角色进行前向相容.

## 国家测绘

这个 `STATE_MAPPINGS` 数组定义了布尔 ARIA 属性如何翻译为口语字符串 。 各国按下列顺序出现在产出中:

| CDP 财产 | `true` | `false` |
| --- | --- | --- |
| `expanded` | `expanded` | `collapsed` |
| `checked` | `checked` | `not checked` |
| `selected` | `selected` | _(安静地)_ |
| `pressed` | `pressed` | `not pressed` |
| `disabled` | `dimmed` | _(安静地)_ |
| `required` | `required` | _(安静地)_ |
| `invalid` | `invalid` | _(安静地)_ |
| `readonly` | `read only` | _(安静地)_ |
| `multiselectable` | `multi selectable` | _(安静地)_ |

标题级别是特殊情况: `level` 属性生成 `level N` (例如, `level 2`) (中文(简体) ).

当存在多个状态时,它们按上方的固定顺序合并:

```
"Submit, button, expanded, required"
"Email, edit text, invalid, required"
```

## 出口

```typescript
// Main classes
export { SpeechEngine } from '@a11y-oracle/core-engine';
export { A11yOrchestrator } from '@a11y-oracle/core-engine';

// Core types
export type {
  CDPSessionLike,
  SpeechResult,
  SpeechEngineOptions,
  A11yState,
  A11yFocusedElement,
  A11yFocusIndicator,
  A11yOrchestratorOptions,
} from '@a11y-oracle/core-engine';

// Data (for advanced customization)
export { ROLE_TO_SPEECH, LANDMARK_ROLES } from '@a11y-oracle/core-engine';
export { STATE_MAPPINGS, extractStates } from '@a11y-oracle/core-engine';
export type { StateMapping, AXNodeProperty } from '@a11y-oracle/core-engine';

// Re-exports from sub-engines
export type { ModifierKeys, FocusedElementInfo, KeyDefinition } from '@a11y-oracle/core-engine';
export { KEY_DEFINITIONS } from '@a11y-oracle/core-engine';
export type { FocusIndicator, TabOrderEntry, TabOrderReport, TraversalResult } from '@a11y-oracle/core-engine';
```

## 常见问题

### @a11y-oracle/core-engine 是什么？

通过 Chrome DevTools 协议实现框架不可知无障碍语音引擎和统一的 A11y Orchestrator

### 如何安装 @a11y-oracle/core-engine？

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

### @a11y-oracle/core-engine 支持 TypeScript 吗？

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

### @a11y-oracle/core-engine 支持 ESM 还是 CommonJS？

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

### @a11y-oracle/core-engine 可以商用吗？

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

### @a11y-oracle/core-engine 的下载量有多少？

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

### @a11y-oracle/core-engine 还在维护吗？

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

