Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ rules in templates can be disabled with eslint directives with mustache or html
| [template-link-href-attributes](docs/rules/template-link-href-attributes.md) | require href attribute on link elements | | | |
| [template-no-abstract-roles](docs/rules/template-no-abstract-roles.md) | disallow abstract ARIA roles | | | |
| [template-no-accesskey-attribute](docs/rules/template-no-accesskey-attribute.md) | disallow accesskey attribute | | 🔧 | |
| [template-no-aria-hidden-body](docs/rules/template-no-aria-hidden-body.md) | disallow aria-hidden on body element | | 🔧 | |
| [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 | | | |

### Best Practices
Expand Down
31 changes: 31 additions & 0 deletions docs/rules/template-no-aria-hidden-body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ember/template-no-aria-hidden-body

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

<!-- end auto-generated rule header -->

The aria-hidden attribute should never be present on the `<body>` element, as it hides the entire document from assistive technology.

## Examples

This rule **forbids** the following:

```hbs
<body aria-hidden>
```

```hbs
<body aria-hidden="true">
```

This rule **allows** the following:

```hbs
<body>
```

## References

- [Using the aria-hidden attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-hidden_attribute)
- [How Lighthouse identifies hidden body elements](https://web.dev/aria-hidden-body/)
- [WCAG 4.1.2 - Name, Role, Value (Level A)](https://www.w3.org/TR/WCAG21/#name-role-value)
49 changes: 49 additions & 0 deletions lib/rules/template-no-aria-hidden-body.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'disallow aria-hidden on body element',
category: 'Accessibility',
strictGjs: true,
strictGts: true,
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-aria-hidden-body.md',
},
fixable: 'code',
schema: [],
messages: {
noAriaHiddenBody:
'The aria-hidden attribute should never be present on the <body> element, as it hides the entire document from assistive technology',
},
},

create(context) {
return {
GlimmerElementNode(node) {
if (node.tag === 'body') {
const ariaHiddenAttr = node.attributes?.find((attr) => attr.name === 'aria-hidden');

if (ariaHiddenAttr) {
context.report({
node: ariaHiddenAttr,
messageId: 'noAriaHiddenBody',
fix(fixer) {
const sourceCode = context.sourceCode;
const text = sourceCode.getText();
const attrStart = ariaHiddenAttr.range[0];
const attrEnd = ariaHiddenAttr.range[1];

let removeStart = attrStart;
while (removeStart > 0 && /\s/.test(text[removeStart - 1])) {
removeStart--;
}

return fixer.removeRange([removeStart, attrEnd]);
},
});
}
}
},
};
},
};
21 changes: 21 additions & 0 deletions tests/lib/rules/template-no-aria-hidden-body.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const rule = require('../../../lib/rules/template-no-aria-hidden-body');
const RuleTester = require('eslint').RuleTester;

const ruleTester = new RuleTester({
parser: require.resolve('ember-eslint-parser'),
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
});

ruleTester.run('template-no-aria-hidden-body', rule, {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be tests for fixing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the one invalid test is that

valid: [
'<template><body></body></template>',
'<template><div aria-hidden="true"></div></template>',
],
invalid: [
{
code: '<template><body aria-hidden="true"></body></template>',
output: '<template><body></body></template>',
errors: [{ messageId: 'noAriaHiddenBody' }],
},
],
});
Loading