Skip to content

Commit

Permalink
check noninteractive roles on interactive elements
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonylegoas committed Feb 9, 2022
1 parent 2de5ec2 commit 0b48e01
Show file tree
Hide file tree
Showing 5 changed files with 685 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/compiler/compile/nodes/Element.ts
Expand Up @@ -20,6 +20,9 @@ import { INode } from './interfaces';
import Component from '../Component';
import compiler_warnings from '../compiler_warnings';
import compiler_errors from '../compiler_errors';
import { ARIARoleDefintionKey } from 'aria-query';
import { noninteractive_roles } from '../utils/aria_roles';
import { interactive_elements } from '../utils/elements';

const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;

Expand Down Expand Up @@ -599,6 +602,18 @@ export default class Element extends Node {
if (handlers_map.has('mouseout') && !handlers_map.has('blur')) {
component.warn(this, compiler_warnings.a11y_mouse_events_have_key_events('mouseout', 'blur'));
}

if (interactive_elements.has(this.name)) {
if (attribute_map.has('role')) {
const roleValue = this.attributes.find(a => a.name === 'role').get_static_value().toString() as ARIARoleDefintionKey;
if (noninteractive_roles.has(roleValue)) {
component.warn(this, {
code: 'a11y-no-interactive-element-to-noninteractive-role',
message: `A11y: <${this.name}> cannot have role ${roleValue}`
});
}
}
}
}

validate_bindings_foreign() {
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/compile/utils/aria_roles.ts
@@ -0,0 +1,9 @@
import { roles as rolesMap } from 'aria-query';

const roles = [...rolesMap.keys()];

const noninteractive_roles = new Set(roles
.filter((name) => !rolesMap.get(name).abstract)
.filter((name) => !rolesMap.get(name).superClass.some((c) => c.includes('widget'))));

export { noninteractive_roles };
5 changes: 5 additions & 0 deletions src/compiler/compile/utils/elements.ts
@@ -0,0 +1,5 @@
const interactive_elements = new Set([
'a', 'button', 'input', 'select', 'textarea'
]);

export { interactive_elements };
@@ -0,0 +1,54 @@
<!-- a -->
<a href="test" role="article">link</a>
<a href="test" role="banner">link</a>
<a href="test" role="complementary">link</a>
<a href="test" role="img">link</a>
<a href="test" role="listitem">link</a>
<a href="test" role="main">link</a>
<a href="test" role="region">link</a>
<a href="test" role="tooltip">link</a>
<a href="test" role="button">link</a>

<!-- button -->
<button role="article">button</button>
<button role="banner">button</button>
<button role="complementary">button</button>
<button role="img">button</button>
<button role="listitem">button</button>
<button role="main">button</button>
<button role="region">button</button>
<button role="tooltip">button</button>
<button role="button">button</button>

<!-- input -->
<input role="article"/>
<input role="banner"/>
<input role="complementary"/>
<input role="img"/>
<input role="listitem"/>
<input role="main"/>
<input role="region"/>
<input role="tooltip"/>
<input role="button"/>

<!-- select -->
<select role="article"/>
<select role="banner"/>
<select role="complementary"/>
<select role="img"/>
<select role="listitem"/>
<select role="main"/>
<select role="region"/>
<select role="tooltip"/>
<select role="button"/>

<!-- textarea -->
<textarea role="article"/>
<textarea role="banner"/>
<textarea role="complementary"/>
<textarea role="img"/>
<textarea role="listitem"/>
<textarea role="main"/>
<textarea role="region"/>
<textarea role="tooltip"/>
<textarea role="button"/>

0 comments on commit 0b48e01

Please sign in to comment.