Skip to content

Commit f0209b2

Browse files
Merge pull request #2405 from NullVoxPopuli/nvp/template-lint-extract-rule-template-no-aria-unsupported-elements
Extract rule: template-no-aria-unsupported-elements
2 parents 6b27474 + 679e572 commit f0209b2

File tree

4 files changed

+158
-5
lines changed

4 files changed

+158
-5
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,12 @@ rules in templates can be disabled with eslint directives with mustache or html
178178

179179
### Accessibility
180180

181-
| Name | Description | 💼 | 🔧 | 💡 |
182-
| :------------------------------------------------------------------------------- | :-------------------------------------- | :- | :- | :- |
183-
| [template-link-href-attributes](docs/rules/template-link-href-attributes.md) | require href attribute on link elements | | | |
184-
| [template-no-abstract-roles](docs/rules/template-no-abstract-roles.md) | disallow abstract ARIA roles | | | |
185-
| [template-no-accesskey-attribute](docs/rules/template-no-accesskey-attribute.md) | disallow accesskey attribute | | 🔧 | |
181+
| Name                                  | Description | 💼 | 🔧 | 💡 |
182+
| :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- | :- | :- | :- |
183+
| [template-link-href-attributes](docs/rules/template-link-href-attributes.md) | require href attribute on link elements | | | |
184+
| [template-no-abstract-roles](docs/rules/template-no-abstract-roles.md) | disallow abstract ARIA roles | | | |
185+
| [template-no-accesskey-attribute](docs/rules/template-no-accesskey-attribute.md) | disallow accesskey attribute | | 🔧 | |
186+
| [template-no-aria-unsupported-elements](docs/rules/template-no-aria-unsupported-elements.md) | disallow ARIA roles, states, and properties on elements that do not support them | | | |
186187

187188
### Best Practices
188189

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# ember/template-no-aria-unsupported-elements
2+
3+
<!-- end auto-generated rule header -->
4+
5+
Disallows using ARIA roles, states, and properties on elements that do not support them.
6+
7+
Certain HTML elements do not support ARIA roles, states, and properties. This rule helps ensure that ARIA attributes are only used on elements that support them, improving accessibility.
8+
9+
## Rule Details
10+
11+
This rule disallows ARIA attributes on elements that do not support them, including:
12+
13+
- `meta`
14+
- `html`
15+
- `script`
16+
- `style`
17+
- `title`
18+
- `base`
19+
- `head`
20+
- `link`
21+
22+
## Examples
23+
24+
Examples of **incorrect** code for this rule:
25+
26+
```gjs
27+
<template>
28+
<meta role="button" />
29+
</template>
30+
```
31+
32+
```gjs
33+
<template>
34+
<script aria-label="Analytics"></script>
35+
</template>
36+
```
37+
38+
```gjs
39+
<template>
40+
<style role="presentation"></style>
41+
</template>
42+
```
43+
44+
Examples of **correct** code for this rule:
45+
46+
```gjs
47+
<template>
48+
<div role="button" aria-label="Submit"></div>
49+
</template>
50+
```
51+
52+
```gjs
53+
<template>
54+
<button aria-pressed="true">Toggle</button>
55+
</template>
56+
```
57+
58+
## References
59+
60+
- [WAI-ARIA in HTML](https://www.w3.org/TR/html-aria/)
61+
- [ember-template-lint no-aria-unsupported-elements](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-aria-unsupported-elements.md)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'problem',
5+
docs: {
6+
description:
7+
'disallow ARIA roles, states, and properties on elements that do not support them',
8+
category: 'Accessibility',
9+
strictGjs: true,
10+
strictGts: true,
11+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-aria-unsupported-elements.md',
12+
},
13+
fixable: null,
14+
schema: [],
15+
messages: {
16+
unsupported:
17+
'ARIA attribute "{{attribute}}" is not supported on <{{element}}> elements. Consider using a different element.',
18+
},
19+
},
20+
21+
create(context) {
22+
// Elements that don't support ARIA
23+
const ELEMENTS_WITHOUT_ARIA_SUPPORT = new Set([
24+
'meta',
25+
'html',
26+
'script',
27+
'style',
28+
'title',
29+
'base',
30+
'head',
31+
'link',
32+
]);
33+
34+
return {
35+
GlimmerElementNode(node) {
36+
if (ELEMENTS_WITHOUT_ARIA_SUPPORT.has(node.tag)) {
37+
const ariaAttributes = node.attributes?.filter(
38+
(attr) =>
39+
attr.type === 'GlimmerAttrNode' &&
40+
attr.name &&
41+
(attr.name.startsWith('aria-') || attr.name === 'role')
42+
);
43+
44+
for (const attr of ariaAttributes || []) {
45+
context.report({
46+
node: attr,
47+
messageId: 'unsupported',
48+
data: {
49+
attribute: attr.name,
50+
element: node.tag,
51+
},
52+
});
53+
}
54+
}
55+
},
56+
};
57+
},
58+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const rule = require('../../../lib/rules/template-no-aria-unsupported-elements');
2+
const RuleTester = require('eslint').RuleTester;
3+
4+
const ruleTester = new RuleTester({
5+
parser: require.resolve('ember-eslint-parser'),
6+
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
7+
});
8+
9+
ruleTester.run('template-no-aria-unsupported-elements', rule, {
10+
valid: [
11+
'<template><div role="button" aria-label="Submit"></div></template>',
12+
'<template><button aria-pressed="true">Toggle</button></template>',
13+
'<template><input aria-label="Username"></template>',
14+
],
15+
16+
invalid: [
17+
{
18+
code: '<template><meta role="button"></template>',
19+
output: null,
20+
errors: [{ messageId: 'unsupported' }],
21+
},
22+
{
23+
code: '<template><script aria-label="Script"></script></template>',
24+
output: null,
25+
errors: [{ messageId: 'unsupported' }],
26+
},
27+
{
28+
code: '<template><style role="presentation"></style></template>',
29+
output: null,
30+
errors: [{ messageId: 'unsupported' }],
31+
},
32+
],
33+
});

0 commit comments

Comments
 (0)