UNPKG

@jsxtools/eslint-plugin-jsx-a11y

Version:

Static AST checker for accessibility rules on JSX elements for flat ESLint Config.

64 lines (61 loc) 2.93 kB
import { roles, elementRoles, dom } from 'aria-query'; import { AXObjects, elementAXObjects } from 'axobject-query'; import { f as filter, i as iterFrom } from '../index-d79WKvnw.js'; import { s as some } from '../index-FhAWpKDl.js'; import attributesComparator from './attributesComparator.js'; const roleKeys = [...roles.keys()]; const elementRoleEntries = [...elementRoles]; const nonInteractiveRoles = new Set(roleKeys.filter((name) => { const role = roles.get(name); return !role.abstract && name !== "toolbar" && name !== "generic" && name !== "cell" && !role.superClass.some((classes) => classes.includes("widget")); }).concat( // The `progressbar` is descended from `widget`, but in practice, its // value is always `readonly`, so we treat it as a non-interactive role. "progressbar" )); const interactiveRoles = new Set(roleKeys.filter((name) => { const role = roles.get(name); return !role.abstract && name !== "progressbar" && name !== "generic" && role.superClass.some((classes) => classes.includes("widget")); }).concat( // 'toolbar' does not descend from widget, but it does support // aria-activedescendant, thus in practice we treat it as a widget. "toolbar" )); const interactiveElementRoleSchemas = elementRoleEntries.flatMap( ([elementSchema, rolesArr]) => rolesArr.some((role) => interactiveRoles.has(role)) ? [elementSchema] : [] ); const nonInteractiveElementRoleSchemas = elementRoleEntries.flatMap( ([elementSchema, rolesArr]) => rolesArr.every((role) => nonInteractiveRoles.has(role)) ? [elementSchema] : [] ); const nonInteractiveAXObjects = new Set(filter(iterFrom(AXObjects.keys()), (name) => ["window", "structure"].includes(AXObjects.get(name).type))); const nonInteractiveElementAXObjectSchemas = [...elementAXObjects].flatMap( ([elementSchema, AXObjectsArr]) => AXObjectsArr.every((role) => nonInteractiveAXObjects.has(role)) ? [elementSchema] : [] ); function checkIsNonInteractiveElement(tagName, attributes) { function elementSchemaMatcher(elementSchema) { return tagName === elementSchema.name && attributesComparator(elementSchema.attributes, attributes); } const isInherentNonInteractiveElement = some(iterFrom(nonInteractiveElementRoleSchemas), elementSchemaMatcher); if (isInherentNonInteractiveElement) { return true; } const isInherentInteractiveElement = some(iterFrom(interactiveElementRoleSchemas), elementSchemaMatcher); if (isInherentInteractiveElement) { return false; } const isNonInteractiveAXElement = some(iterFrom(nonInteractiveElementAXObjectSchemas), elementSchemaMatcher); if (isNonInteractiveAXElement) { return true; } return false; } const isNonInteractiveElement = (tagName, attributes) => { if (!dom.has(tagName)) { return false; } if (tagName === "header") { return false; } return checkIsNonInteractiveElement(tagName, attributes); }; export { isNonInteractiveElement as default };