align implementation with eslint-plugin-jsx-a11y

pull/7838/head
tanhauhau 4 years ago
parent b23e6ce859
commit 3d7609ba5d

@ -24,7 +24,7 @@ import { Literal } from 'estree';
import compiler_warnings from '../compiler_warnings'; import compiler_warnings from '../compiler_warnings';
import compiler_errors from '../compiler_errors'; import compiler_errors from '../compiler_errors';
import { ARIARoleDefintionKey, roles, aria, ARIAPropertyDefinition, ARIAProperty } from 'aria-query'; import { ARIARoleDefintionKey, roles, aria, ARIAPropertyDefinition, ARIAProperty } from 'aria-query';
import { is_interactive_element, is_non_interactive_roles, is_presentation_role, is_interactive_roles, is_hidden_from_screen_reader } from '../utils/a11y'; import { is_interactive_element, is_non_interactive_roles, is_presentation_role, is_interactive_roles, is_hidden_from_screen_reader, is_semantic_role_element } from '../utils/a11y';
const aria_attributes = 'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const aria_attributes = 'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(' ');
const aria_attribute_set = new Set(aria_attributes); const aria_attribute_set = new Set(aria_attributes);
@ -514,21 +514,17 @@ export default class Element extends Node {
} }
// role-has-required-aria-props // role-has-required-aria-props
if (!is_semantic_role_element(value, this.name, attribute_map)) {
const role = roles.get(value); const role = roles.get(value);
if (role) { if (role) {
const required_role_props = Object.keys(role.requiredProps); const required_role_props = Object.keys(role.requiredProps);
const has_missing_props = required_role_props.some(prop => !attributes.find(a => a.name === prop)); const has_missing_props = required_role_props.some(prop => !attributes.find(a => a.name === prop));
if (has_missing_props) { if (has_missing_props) {
// native checkbox/radio inputs do not require ARIA attributes
if (this.name === 'input') {
const type = attributes.find((a) => a.name === 'type').get_static_value();
if (type === 'checkbox' || type === 'radio') return;
}
component.warn(attribute, compiler_warnings.a11y_role_has_required_aria_props(value as string, required_role_props)); component.warn(attribute, compiler_warnings.a11y_role_has_required_aria_props(value as string, required_role_props));
} }
} }
}
// no-interactive-element-to-noninteractive-role // no-interactive-element-to-noninteractive-role
if (is_interactive_element(this.name, attribute_map) && (is_non_interactive_roles(value) || is_presentation_role(value))) { if (is_interactive_element(this.name, attribute_map) && (is_non_interactive_roles(value) || is_presentation_role(value))) {

@ -4,7 +4,7 @@ import {
elementRoles, elementRoles,
ARIARoleRelationConcept ARIARoleRelationConcept
} from 'aria-query'; } from 'aria-query';
import { AXObjects, elementAXObjects } from 'axobject-query'; import { AXObjects, AXObjectRoles, elementAXObjects } from 'axobject-query';
import Attribute from '../nodes/Attribute'; import Attribute from '../nodes/Attribute';
const roles = [...roles_map.keys()]; const roles = [...roles_map.keys()];
@ -119,8 +119,8 @@ function match_schema(
schema_attribute.value && schema_attribute.value &&
schema_attribute.value !== attribute.get_static_value() schema_attribute.value !== attribute.get_static_value()
) { ) {
return false; return false;
} }
return true; return true;
}); });
} }
@ -155,3 +155,23 @@ export function is_interactive_element(
return false; return false;
} }
export function is_semantic_role_element(role: ARIARoleDefintionKey, tag_name: string, attribute_map: Map<string, Attribute>) {
for (const [schema, ax_object] of elementAXObjects.entries()) {
if (schema.name === tag_name && (!schema.attributes || schema.attributes.every(
(attr) => attribute_map.has(attr.name) && attribute_map.get(attr.name).get_static_value() === attr.value
))) {
for (const name of ax_object) {
const roles = AXObjectRoles.get(name);
if (roles) {
for (const { name } of roles) {
if (name === role) {
return true;
}
}
}
}
}
}
return false;
}

@ -224,21 +224,6 @@
"line": 15 "line": 15
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"end": {
"character": 383,
"column": 18,
"line": 15
},
"message": "A11y: Elements with the ARIA role \"heading\" must have the following attributes defined: \"aria-level\"",
"pos": 369,
"start": {
"character": 369,
"column": 4,
"line": 15
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {
@ -254,21 +239,6 @@
"line": 16 "line": 16
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"message": "A11y: Elements with the ARIA role \"heading\" must have the following attributes defined: \"aria-level\"",
"pos": 401,
"start": {
"character": 401,
"column": 4,
"line": 16
},
"end": {
"character": 415,
"column": 18,
"line": 16
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {
@ -284,21 +254,6 @@
"line": 17 "line": 17
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"end": {
"character": 447,
"column": 18,
"line": 17
},
"message": "A11y: Elements with the ARIA role \"heading\" must have the following attributes defined: \"aria-level\"",
"pos": 433,
"start": {
"character": 433,
"column": 4,
"line": 17
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {
@ -314,21 +269,6 @@
"line": 18 "line": 18
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"message": "A11y: Elements with the ARIA role \"heading\" must have the following attributes defined: \"aria-level\"",
"pos": 465,
"start": {
"character": 465,
"column": 4,
"line": 18
},
"end": {
"character": 479,
"column": 18,
"line": 18
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {
@ -344,21 +284,6 @@
"line": 19 "line": 19
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"message": "A11y: Elements with the ARIA role \"heading\" must have the following attributes defined: \"aria-level\"",
"pos": 497,
"start": {
"character": 497,
"column": 4,
"line": 19
},
"end": {
"character": 511,
"column": 18,
"line": 19
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {
@ -374,21 +299,6 @@
"line": 20 "line": 20
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"message": "A11y: Elements with the ARIA role \"heading\" must have the following attributes defined: \"aria-level\"",
"pos": 529,
"start": {
"character": 529,
"column": 4,
"line": 20
},
"end": {
"character": 543,
"column": 18,
"line": 20
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {
@ -524,21 +434,6 @@
"line": 29 "line": 29
} }
}, },
{
"code": "a11y-role-has-required-aria-props",
"message": "A11y: Elements with the ARIA role \"option\" must have the following attributes defined: \"aria-selected\"",
"pos": 751,
"start": {
"character": 751,
"column": 8,
"line": 29
},
"end": {
"character": 764,
"column": 21,
"line": 29
}
},
{ {
"code": "a11y-no-redundant-roles", "code": "a11y-no-redundant-roles",
"end": { "end": {

@ -8,4 +8,4 @@
<div role="meter" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div> <div role="meter" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
<div role="scrollbar" aria-controls="panel" aria-valuenow="50"></div> <div role="scrollbar" aria-controls="panel" aria-valuenow="50"></div>
<input role="switch" type="checkbox" /> <input role="switch" type="checkbox" />
<input role="switch" type="radio" /> <input role="radio" type="radio" />
Loading…
Cancel
Save