Использование в axe-core

aria-query — это JavaScript-библиотека, предназначенная для работы с спецификацией ARIA (Accessible Rich Internet Applications) и анализа элементов веб-страниц с точки зрения доступности. Она предоставляет структурированные данные о ARIA ролях, свойствах и состояниях, а также их допустимых контекстах. Библиотека особенно полезна при интеграции с инструментами автоматизированного тестирования доступности, такими как axe-core.

Ключевой объект библиотеки — это набор карточек ролей и атрибутов, которые позволяют определять:

  • какие ARIA-атрибуты поддерживает конкретная роль;
  • какие родительские и дочерние элементы допустимы;
  • какие HTML-элементы могут использоваться с данной ролью.

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

Библиотека поставляется с несколькими основными коллекциями:

  1. Roles Roles представляет собой карту всех стандартных ARIA-ролей, например, button, checkbox, dialog. Каждый объект роли содержит:

    • name: уникальное имя роли;
    • superClass: родительские роли, от которых наследуются свойства;
    • props: список поддерживаемых ARIA-свойств и их допустимых значений;
    • requiredContextRole: контекстные ограничения на использование роли;
    • requiredOwnedElements: список обязательных дочерних ролей.

    Пример получения роли button и её свойств:

    const { roles } = require('aria-query');
    const buttonRole = roles.get('button');
    console.log(buttonRole.props);
  2. Elements Elements связывает HTML-теги с ARIA-ролями, показывая, какие теги могут использоваться с какими ролями. Например:

    • <button> автоматически получает роль button;
    • <input type="checkbox"> автоматически получает роль checkbox.

    Проверка ролей для тега div:

    const { dom } = require('aria-query');
    const divRoles = dom.get('div');
    console.log(divRoles); // Set { 'button', 'dialog', 'tabpanel', ... }
  3. Attributes Attributes содержит все ARIA-атрибуты (aria-label, aria-hidden, aria-expanded и т.д.) с описанием допустимых типов значений и ролей, к которым они применимы.

    Пример проверки атрибута aria-checked:

    const { aria } = require('aria-query');
    const checkedAttr = aria.get('aria-checked');
    console.log(checkedAttr.type); // 'tristate'
    console.log(checkedAttr.allowedRoles); // Set { 'checkbox', 'menuitemcheckbox', 'radio' }

Использование aria-query в axe-core

axe-core использует aria-query для проверки доступности элементов веб-страницы, анализируя соответствие:

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

Пример интеграции с axe-core:

const axe = require('axe-core');
const { roles } = require('aria-query');

function validateAriaRoles(node) {
  const role = node.getAttribute('role');
  if (!roles.has(role)) {
    return [`Роль "${role}" не соответствует спецификации ARIA.`];
  }
  return [];
}

// Применение на DOM-узлах
const results = Array.from(document.querySelectorAll('[role]'))
  .flatMap(validateAriaRoles);

console.log(results);

Внутри axe-core библиотека позволяет:

  • проверять корректность роли: роль должна существовать в aria-query;
  • сопоставлять HTML-элемент с ролью: например, <div role="button"> допустим, <span role="main"> может иметь ограничения;
  • контролировать свойства и состояния: aria-disabled, aria-checked и другие должны использоваться только с ролями, которые их поддерживают;
  • следить за иерархией ARIA: некоторые роли требуют конкретных дочерних элементов, например, list должен содержать listitem.

Расширенные возможности

aria-query позволяет создавать динамические правила проверки доступности, что полезно при кастомных компонентах. Например, можно реализовать проверку:

  • корректности комбинации ролей combobox и option;
  • обязательности атрибутов aria-labelledby и aria-describedby;
  • наследования свойств от суперролей.

Пример проверки обязательных дочерних элементов:

const { roles } = require('aria-query');

function checkRequiredChildren(node) {
  const roleData = roles.get(node.getAttribute('role'));
  if (!roleData || !roleData.requiredOwnedElements) return [];
  
  const errors = [];
  roleData.requiredOwnedElements.forEach(requiredRole => {
    const hasChild = Array.from(node.children)
      .some(child => child.getAttribute('role') === requiredRole);
    if (!hasChild) {
      errors.push(`Элемент с ролью "${roleData.name}" должен содержать "${requiredRole}".`);
    }
  });
  return errors;
}

Такой подход делает анализ доступности гибким и детализированным, позволяя обнаруживать нарушения ARIA на ранних стадиях разработки интерфейсов.

Практические рекомендации

  • Использовать aria-query для статической валидации ролей и атрибутов, что сокращает количество ошибок, которые может выявить axe-core.
  • Встраивать проверки в CI/CD-процессы, чтобы автоматизировать контроль за доступностью.
  • При создании кастомных компонентов всегда сверяться с roles и attributes, чтобы поддерживать совместимость с ARIA.

Эти возможности делают aria-query незаменимым инструментом для интеграции с axe-core и построения доступных веб-интерфейсов, где каждая роль и атрибут проверяется на соответствие стандартам.