feat(a11y): add no-redundant-roles rule (#820)

- flagging easy cases of redundant aria roles on html tags for now

Signed-off-by: mhatvan <markus_hatvan@aon.at>
pull/5361/head
mhatvan 5 years ago
parent c8c50b5ba8
commit 54ed73e524
No known key found for this signature in database
GPG Key ID: 6DD396B45D5556CE

@ -214,12 +214,12 @@ export default class Element extends Node {
} }
case 'Transition': case 'Transition':
{ {
const transition = new Transition(component, this, scope, node); const transition = new Transition(component, this, scope, node);
if (node.intro) this.intro = transition; if (node.intro) this.intro = transition;
if (node.outro) this.outro = transition; if (node.outro) this.outro = transition;
break; break;
} }
case 'Animation': case 'Animation':
this.animation = new Animation(component, this, scope, node); this.animation = new Animation(component, this, scope, node);
@ -357,6 +357,67 @@ export default class Element extends Node {
message message
}); });
} }
const implicitAriaSemantics = new Map([
// ['a', ''],
// ['area', ''],
['article', 'article'],
['aside', 'complementary'],
['body', 'document'],
['button', 'button'],
['datalist', 'listbox'],
['dd', 'definition'],
['dfn', 'term'],
['details', 'group'],
['dialog', 'dialog'],
['dt', 'term'],
['fieldset', 'group'],
['figure', 'figure'],
// ['footer', ''],
['form', 'form'],
['h1', 'heading'],
['h2', 'heading'],
['h3', 'heading'],
['h4', 'heading'],
['h5', 'heading'],
['h6', 'heading'],
// ['header', ''],
['hr', 'separator'],
// ['img', ''],
// ['input', ''],
['li', 'listitem'],
['link', 'link'],
['main', 'main'],
['math', 'math'],
['menu', 'list'],
['nav', 'navigation'],
['ol', 'list'],
['optgroup', 'group'],
['option', 'option'],
['output', 'status'],
['progress', 'progressbar'],
['section', 'region'],
// ['select', ''],
['summary', 'button'],
['table', 'table'],
['tbody', 'rowgroup'],
['textarea', 'textbox'],
['tfoot', 'rowgroup'],
['thead', 'rowgroup'],
// ['td', ''],
// ['th', ''],
['tr', 'row'],
['ul', 'list'],
['ul', 'list']
]);
const redundantAriaRole = implicitAriaSemantics.get(this.name);
if (value === redundantAriaRole)
component.warn(this, {
code: `a11y-no-redundant-roles`,
message: `A11y: The element <${this.name}> has an implicit role of '${redundantAriaRole}'. Defining this explicitly is redundant and should be avoided.`
});
} }
// no-access-key // no-access-key
@ -519,7 +580,7 @@ export default class Element extends Node {
} }
if (this.name === 'label') { if (this.name === 'label') {
const has_input_child = this.children.some(i => (i instanceof Element && a11y_labelable.has(i.name) )); const has_input_child = this.children.some(i => (i instanceof Element && a11y_labelable.has(i.name)));
if (!attribute_map.has('for') && !has_input_child) { if (!attribute_map.has('for') && !has_input_child) {
component.warn(this, { component.warn(this, {
code: `a11y-label-has-associated-control`, code: `a11y-label-has-associated-control`,

@ -0,0 +1,15 @@
<!-- should not warn -->
<article role="feed" />
<aside role="region" />
<button role="radio" />
<form role="search">foo</form>
<h1 role="presentation">foo</h1>
<section role="contentinfo">foo</section>
<!-- should warn -->
<article role="article" />
<aside role="complementary" />
<button role="button" />
<form role="form">foo</form>
<h1 role="heading">foo</h1>
<section role="region">foo</section>

@ -0,0 +1,92 @@
[
{
"code": "a11y-no-redundant-roles",
"message": "A11y: The element <article> has an implicit role of 'article'. Defining this explicitly is redundant and should be avoided.",
"pos": 225,
"start": {
"line": 10,
"column": 0,
"character": 225
},
"end": {
"line": 10,
"column": 26,
"character": 251
}
},
{
"code": "a11y-no-redundant-roles",
"message": "A11y: The element <aside> has an implicit role of 'complementary'. Defining this explicitly is redundant and should be avoided.",
"pos": 252,
"start": {
"line": 11,
"column": 0,
"character": 252
},
"end": {
"line": 11,
"column": 30,
"character": 282
}
},
{
"code": "a11y-no-redundant-roles",
"message": "A11y: The element <button> has an implicit role of 'button'. Defining this explicitly is redundant and should be avoided.",
"pos": 283,
"start": {
"line": 12,
"column": 0,
"character": 283
},
"end": {
"line": 12,
"column": 24,
"character": 307
}
},
{
"code": "a11y-no-redundant-roles",
"message": "A11y: The element <form> has an implicit role of 'form'. Defining this explicitly is redundant and should be avoided.",
"pos": 308,
"start": {
"line": 13,
"column": 0,
"character": 308
},
"end": {
"line": 13,
"column": 28,
"character": 336
}
},
{
"code": "a11y-no-redundant-roles",
"message": "A11y: The element <h1> has an implicit role of 'heading'. Defining this explicitly is redundant and should be avoided.",
"pos": 337,
"start": {
"line": 14,
"column": 0,
"character": 337
},
"end": {
"line": 14,
"column": 27,
"character": 364
}
},
{
"code": "a11y-no-redundant-roles",
"message": "A11y: The element <section> has an implicit role of 'region'. Defining this explicitly is redundant and should be avoided.",
"pos": 365,
"start": {
"line": 15,
"column": 0,
"character": 365
},
"end": {
"line": 15,
"column": 36,
"character": 401
}
}
]
Loading…
Cancel
Save