Работа с типизированными Map

Библиотека Aria-query представляет собой мощный инструмент для работы с ARIA-атрибутами и ролями в веб-разработке. Одним из ключевых элементов её API являются типизированные Map, которые позволяют хранить и быстро получать информацию о ролях, их свойствах и допустимых значениях атрибутов.


Основы структуры Map

В Aria-query используется два основных вида Map:

  1. Roles – карта всех ARIA-ролей и их характеристик.
  2. Attributes – карта ARIA-атрибутов и допустимых значений для каждой роли.

Каждая запись в Map является объектом, содержащим несколько ключевых полей:

  • name – имя роли или атрибута.
  • abstract – булево значение, показывающее, является ли роль абстрактной.
  • superClass – массив ролей, от которых наследуется текущая.
  • props – объект с ключами, соответствующими ARIA-атрибутам, и значениями, которые могут быть типами или конкретными значениями.

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

import { roles } from 'aria-query';

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

console.log(buttonRole);
/*
{
  name: 'button',
  abstract: false,
  superClass: [['command']],
  props: {
    'aria-pressed': 'boolean'
  }
}
*/

Работа с методами Map

Roles и Attributes реализованы как ES6 Map, что позволяет использовать стандартные методы Map:

  • get(key) – получить объект по имени роли или атрибута.
  • has(key) – проверить наличие роли или атрибута.
  • keys() – получить список всех ключей.
  • values() – получить список всех значений.
  • entries() – получить пары [ключ, значение].

Пример использования:

import { roles } from 'aria-query';

if (roles.has('checkbox')) {
  const checkboxRole = roles.get('checkbox');
  console.log(checkboxRole.props);
}

Использование entries() позволяет итерировать все роли:

for (const [roleName, roleInfo] of roles.entries()) {
  console.log(`${roleName} -> abstract: ${roleInfo.abstract}`);
}

Типизация атрибутов

Одно из ключевых преимуществ Aria-query — типизированные значения атрибутов. Каждое свойство props содержит либо:

  • примитивные типы (string, boolean, number);
  • ограниченные множества значений ('true' | 'false', 'ascending' | 'descending');
  • специальные типы (token, IDReference, IDReferenceList).

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

import { roles } from 'aria-query';

const treeRole = roles.get('tree');
const ariaExpandedType = treeRole.props['aria-expanded'];

console.log(ariaExpandedType); // boolean

Это позволяет строить строгую валидацию и автокомплит для ARIA-атрибутов в редакторах кода.


Наследование ролей

Map Roles поддерживает концепцию суперклассов, что позволяет определить, какие свойства унаследованы:

const menuItem = roles.get('menuitem');
console.log(menuItem.superClass); // [['command', 'widget']]

Это означает, что все свойства из command и widget применимы к menuitem, а собственные свойства роли дополняют их.

Для получения всех доступных свойств с учётом наследования можно написать функцию:

function getAllProps(roleName) {
  const role = roles.get(roleName);
  let props = { ...role.props };
  if (role.superClass) {
    role.superClass.forEach(superRoles => {
      superRoles.forEach(sr => {
        const superProps = getAllProps(sr);
        props = { ...superProps, ...props };
      });
    });
  }
  return props;
}

console.log(getAllProps('menuitem'));

Применение валидации и генерации интерфейсов

Типизированные Map позволяют решать несколько задач:

  1. Валидация ARIA-разметки:

    • Проверка, допустим ли атрибут для роли.
    • Проверка типа значения.
const role = roles.get('checkbox');
const attr = 'aria-checked';
const value = 'true';

if (role.props[attr] === 'boolean') {
  console.log('Значение допустимо');
}
  1. Генерация интерфейсов с автокомплитом:

    • Можно динамически создавать выпадающие списки с допустимыми значениями атрибутов.
    • Позволяет редактору кода подсвечивать ошибки и подсказки при работе с ARIA.
  2. Анализ доступности:

    • Автоматическое построение дерева ролей и проверка совместимости элементов.
    • Инструменты тестирования могут использовать Map для проверки корректного использования ARIA.

Оптимизация работы с Map

Несмотря на то что Map уже оптимизирован для поиска по ключу, рекомендуется:

  • Использовать методы get и has вместо перебора values() для частого доступа.
  • Кэшировать результаты сложных операций с наследованием (superClass), чтобы не вычислять рекурсивно каждый раз.
  • Преобразовывать результаты props в строгие типы или enum для облегчения дальнейшей работы с интерфейсом.

Типизированные Map в Aria-query обеспечивают структурированный и безопасный способ работы с ролями и атрибутами ARIA, создавая основу для автоматизации валидации, генерации интерфейсов и анализа доступности веб-приложений. Их использование позволяет писать чистый, предсказуемый код и снижает риск ошибок при работе с динамической ARIA-разметкой.