Анализ accessibility tree

Современные браузеры строят внутреннее представление пользовательского интерфейса страницы, предназначенное для вспомогательных технологий — экранных дикторов, систем управления голосом, альтернативных устройств ввода. Это представление называется accessibility tree.

Accessibility tree не повторяет DOM-дерево полностью. В нём остаются только те узлы, которые имеют значение для доступности интерфейса. Каждый элемент получает:

  • роль (role) — тип элемента интерфейса;
  • доступное имя (accessible name);
  • состояния и свойства (states / properties);
  • отношения с другими элементами.

Например, обычный HTML-элемент <button> в accessibility tree будет представлен узлом с ролью button, именем (полученным из текста или атрибутов) и возможными состояниями вроде pressed.

В процессе разработки и автоматической проверки доступности возникает необходимость анализировать соответствие между HTML-разметкой и ожидаемыми ролями, описанными в спецификациях WAI-ARIA. Для решения этой задачи используется библиотека aria-query.


Назначение библиотеки aria-query

aria-query — это JavaScript-библиотека, содержащая структурированные данные о:

  • ARIA-ролях
  • ARIA-свойствах
  • отношениях ролей и HTML-элементов
  • допустимых атрибутах и состояниях

Она используется инструментами анализа доступности и линтерами (например, правилами eslint-plugin-jsx-a11y) для определения того, какой элемент должен появиться в accessibility tree и с какой ролью.

Главная особенность библиотеки — представление данных в виде Map-структур, позволяющих выполнять быстрые запросы:

  • соответствие HTML-элемента ARIA-ролям
  • разрешённые свойства для роли
  • глобальные ARIA-атрибуты
  • роли, запрещённые для конкретных элементов

Связь aria-query с анализом accessibility tree

При построении accessibility tree браузер использует:

  1. нативную семантику HTML
  2. ARIA-атрибуты
  3. правила спецификации ARIA in HTML

aria-query моделирует эти правила в виде таблиц и словарей. Анализ accessibility tree через библиотеку обычно включает:

  • определение implicit role (неявной роли)
  • проверку explicit role
  • анализ допустимых ARIA-атрибутов
  • проверку конфликтов семантики

Таким образом, aria-query позволяет программно воспроизвести часть логики браузера при построении дерева доступности.


Структура данных в aria-query

Библиотека экспортирует несколько основных наборов данных.

roles

Коллекция ролей ARIA.

Каждая роль содержит:

  • тип (widget, structure, landmark)
  • допустимые свойства
  • требования к доступному имени
  • список обязательных контекстов

Пример структуры роли:

import { roles } from "aria-query";

const buttonRole = roles.get("button");

Объект роли содержит:

{
  abstract: false,
  accessibleNameRequired: true,
  baseConcepts: [],
  childrenPresentational: false,
  props: {...},
  requiredProps: {},
  superClass: [...]
}

Эти данные используются при проверке корректности элементов интерфейса.


elementRoles

Коллекция соответствий HTML-элементов и ARIA-ролей.

Каждый ключ представляет описание HTML-элемента:

{
  name: "button"
}

Значением является набор ролей, допустимых для этого элемента.

Пример запроса:

import { elementRoles } from "aria-query";

for (const [element, roles] of elementRoles) {
  if (element.name === "button") {
    console.log(roles);
  }
}

Это позволяет определить:

  • какие роли допустимы для элемента
  • какая роль применяется по умолчанию

roleElements

Обратная структура данных — соответствие ролей и HTML-элементов.

import { roleElements } from "aria-query";

const buttonElements = roleElements.get("button");

Результатом будет список HTML-концептов, реализующих роль button.

Эта структура активно используется анализаторами JSX-разметки для проверки правильности ролей.


aria

Коллекция ARIA-атрибутов.

Каждый атрибут содержит описание:

  • тип значения
  • допустимые значения
  • принадлежность к глобальным или специфическим атрибутам

Пример:

import { aria } from "aria-query";

const checked = aria.get("aria-checked");

Результат:

{
  type: "tristate",
  values: ["true", "false", "mixed"]
}

Это позволяет валидировать корректность значений ARIA-свойств.


Определение неявных ролей (implicit roles)

Большинство HTML-элементов уже имеют встроенную семантику. Например:

HTML элемент implicit role
button button
a[href] link
nav navigation
header banner

aria-query позволяет определить эту роль программно.

Пример определения роли

import { elementRoles } from "aria-query";

function getImplicitRoles(tagName) {
  for (const [element, roles] of elementRoles) {
    if (element.name === tagName) {
      return [...roles];
    }
  }
}

Результат:

getImplicitRoles("button")
// Set { "button" }

Такая проверка используется в линтерах для выявления избыточных или ошибочных ролей.


Анализ явных ролей (explicit roles)

ARIA позволяет разработчику явно задать роль:

<div role="button"></div>

Однако спецификация накладывает ограничения:

  • не все роли допустимы для любого элемента
  • некоторые роли конфликтуют с нативной семантикой

aria-query помогает определить допустимость роли.

Проверка роли

import { roleElements } from "aria-query";

function isRoleSupported(role, element) {
  const concepts = roleElements.get(role);
  if (!concepts) return false;

  for (const concept of concepts) {
    if (concept.name === element) {
      return true;
    }
  }

  return false;
}

Такой анализ используется инструментами автоматической проверки доступности.


Анализ допустимых ARIA-атрибутов

Не все ARIA-атрибуты могут применяться к любой роли. Например:

  • aria-checked допустим для checkbox
  • aria-expanded используется для элементов с раскрывающимся состоянием

aria-query хранит информацию о том, какие свойства разрешены.

Получение свойств роли

import { roles } from "aria-query";

const checkbox = roles.get("checkbox");

console.log(checkbox.props);

Результат — список допустимых ARIA-свойств.

Это позволяет автоматически проверять:

  • наличие запрещённых атрибутов
  • корректность состояний элемента

Определение глобальных ARIA-атрибутов

Некоторые ARIA-атрибуты можно применять ко всем элементам. Например:

  • aria-label
  • aria-labelledby
  • aria-describedby

aria-query помечает такие атрибуты как глобальные.

Пример проверки:

import { aria } from "aria-query";

function isGlobalAriaAttribute(name) {
  const attr = aria.get(name);
  return attr && attr.global;
}

Это важно при анализе accessibility tree, так как глобальные атрибуты участвуют в вычислении accessible name.


Проверка конфликтов ролей

Одна из распространённых ошибок — конфликт между HTML-семантикой и ARIA-ролью.

Пример ошибки:

<button role="heading"></button>

Элемент button уже имеет роль button. Переопределение её ролью heading нарушает правила доступности.

aria-query позволяет обнаружить подобные ситуации.

Алгоритм проверки обычно включает:

  1. получение implicit role
  2. сравнение с explicit role
  3. анализ допустимости переопределения

Использование aria-query в инструментах анализа

Библиотека редко используется напрямую в прикладном коде интерфейсов. Основная область применения — инструменты анализа доступности.

Примеры:

  • линтеры JSX
  • статические анализаторы HTML
  • инструменты автоматического тестирования accessibility

Типичный процесс анализа:

  1. парсинг DOM или AST
  2. извлечение HTML-элементов
  3. определение implicit roles через aria-query
  4. анализ explicit roles
  5. проверка допустимых ARIA-атрибутов
  6. моделирование accessibility tree

В результате формируется набор предупреждений или ошибок доступности.


Ограничения aria-query

Несмотря на полезность библиотеки, она не заменяет полноценный движок построения accessibility tree.

Причины:

1. Отсутствие реального DOM-контекста

Браузеры учитывают:

  • CSS
  • visibility
  • aria-hidden
  • display properties

aria-query не анализирует эти факторы.


2. Не рассчитывается accessible name

Формирование имени элемента зависит от сложного алгоритма:

  • aria-labelledby
  • aria-label
  • текстовое содержимое
  • label-элементы

aria-query предоставляет только данные о свойствах.


3. Нет обработки состояния интерфейса

Например:

  • expanded
  • selected
  • pressed

Эти состояния должны анализироваться отдельно.


Практическое применение при моделировании accessibility tree

При создании собственного анализатора доступности aria-query используется как база знаний.

Типичный алгоритм:

  1. Получение DOM-узла
  2. Определение HTML-концепта
  3. Поиск implicit role
  4. Проверка explicit role
  5. Определение разрешённых ARIA-свойств
  6. Проверка соответствия спецификации

Результатом становится модель узла accessibility tree:

Node
 ├ role
 ├ accessible name
 ├ states
 ├ properties
 └ relationships

aria-query покрывает шаги, связанные с ролями и свойствами.


Значение для разработки доступных интерфейсов

Библиотека играет важную роль в экосистеме инструментов доступности Jav * aScript:

  • стандартизирует данные спецификаций ARIA
  • позволяет автоматизировать проверки
  • обеспечивает единое представление ролей и свойств
  • упрощает реализацию статического анализа

Использование aria-query делает возможным программный анализ семантики интерфейса и приближает инструменты разработки к логике построения настоящего accessibility tree, используемого браузерами и вспомогательными технологиями.