Skip to content

Commit 7546951

Browse files
committed
[new] - Consolidate no-marquee and no-blink into no-distracting-elements rule. (#140)
This is a breaking change. Will be included in next major release!
1 parent cd3467d commit 7546951

File tree

7 files changed

+121
-79
lines changed

7 files changed

+121
-79
lines changed
Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @fileoverview Enforce <marquee> elements are not used.
2+
* @fileoverview Enforce distracting elements are not used.
33
* @author Ethan Cohen
44
*/
55

@@ -8,7 +8,7 @@
88
// -----------------------------------------------------------------------------
99

1010
import { RuleTester } from 'eslint';
11-
import rule from '../../../src/rules/no-marquee';
11+
import rule from '../../../src/rules/no-distracting-elements';
1212

1313
const parserOptions = {
1414
ecmaVersion: 6,
@@ -23,20 +23,25 @@ const parserOptions = {
2323

2424
const ruleTester = new RuleTester();
2525

26-
const expectedError = {
27-
message: 'Do not use <marquee> elements as they create accessibility issues and are deprecated.',
26+
const expectedError = element => ({
27+
message: `Do not use <${element}> elements as they can create visual accessibility issues and are deprecated.`,
2828
type: 'JSXOpeningElement',
29-
};
29+
});
3030

3131
ruleTester.run('no-marquee', rule, {
3232
valid: [
3333
{ code: '<div />;', parserOptions },
3434
{ code: '<Marquee />', parserOptions },
3535
{ code: '<div marquee />', parserOptions },
36+
{ code: '<Blink />', parserOptions },
37+
{ code: '<div blink />', parserOptions },
3638
],
3739
invalid: [
38-
{ code: '<marquee />', errors: [expectedError], parserOptions },
39-
{ code: '<marquee {...props} />', errors: [expectedError], parserOptions },
40-
{ code: '<marquee lang={undefined} />', errors: [expectedError], parserOptions },
40+
{ code: '<marquee />', errors: [expectedError('marquee')], parserOptions },
41+
{ code: '<marquee {...props} />', errors: [expectedError('marquee')], parserOptions },
42+
{ code: '<marquee lang={undefined} />', errors: [expectedError('marquee')], parserOptions },
43+
{ code: '<blink />', errors: [expectedError('blink')], parserOptions },
44+
{ code: '<blink {...props} />', errors: [expectedError('blink')], parserOptions },
45+
{ code: '<blink foo={undefined} />', errors: [expectedError('blink')], parserOptions },
4146
],
4247
});

docs/rules/no-distracting-elements.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# no-distracting-elements
2+
3+
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided. By default, the following elements are visually distracting: `<marquee>` and `<blink>`.
4+
5+
#### References
6+
1. [Deque University](https://dequeuniversity.com/rules/axe/1.1/marquee)
7+
2. [Deque University](https://dequeuniversity.com/rules/axe/1.1/blink)
8+
9+
## Rule details
10+
11+
This rule takes one optional object argument of type object:
12+
13+
```json
14+
{
15+
"rules": {
16+
"jsx-a11y/no-distracting-elements": [ 2, {
17+
"elements": [ "marquee", "blink" ],
18+
}],
19+
}
20+
}
21+
```
22+
23+
For the `elements` option, these strings determine which JSX elements should be checked for usage. This shouldn't need to be configured unless you have a seriously compelling use case for these elements. You cannot add any additional elements than what is offered, as the schema is only valid with the provided enumerated list. If you have another element that you think may cause a11y issues due to visual impairment, please feel free to file an issue or send a PR!
24+
25+
### Succeed
26+
```jsx
27+
<div />
28+
```
29+
30+
### Fail
31+
```jsx
32+
<marquee />
33+
<blink />
34+
```

docs/rules/no-marquee.md

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
lang: require('./rules/lang'),
2020
'mouse-events-have-key-events': require('./rules/mouse-events-have-key-events'),
2121
'no-access-key': require('./rules/no-access-key'),
22-
'no-marquee': require('./rules/no-marquee'),
22+
'no-distracting-elements': require('./rules/no-distracting-elements'),
2323
'no-onchange': require('./rules/no-onchange'),
2424
'no-static-element-interactions': require('./rules/no-static-element-interactions'),
2525
'onclick-has-focus': require('./rules/onclick-has-focus'),
@@ -53,7 +53,7 @@ module.exports = {
5353
'jsx-a11y/label-has-for': 'error',
5454
'jsx-a11y/mouse-events-have-key-events': 'error',
5555
'jsx-a11y/no-access-key': 'error',
56-
'jsx-a11y/no-marquee': 'error',
56+
'jsx-a11y/no-distracting-elements': 'error',
5757
'jsx-a11y/no-onchange': 'error',
5858
'jsx-a11y/no-static-element-interactions': 'warn',
5959
'jsx-a11y/onclick-has-focus': 'error',

src/rules/no-distracting-elements.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @fileoverview Enforce distracting elements are not used.
3+
* @author Ethan Cohen
4+
*/
5+
6+
// ----------------------------------------------------------------------------
7+
// Rule Definition
8+
// ----------------------------------------------------------------------------
9+
10+
import { elementType } from 'jsx-ast-utils';
11+
import { generateObjSchema, enumArraySchema } from '../util/schemas';
12+
13+
const errorMessage = element =>
14+
`Do not use <${element}> elements as they can create visual accessibility issues and are deprecated.`;
15+
16+
17+
const DEFAULT_ELEMENTS = [
18+
'marquee',
19+
'blink',
20+
];
21+
22+
const schema = generateObjSchema({
23+
elements: enumArraySchema(DEFAULT_ELEMENTS),
24+
});
25+
26+
module.exports = {
27+
meta: {
28+
docs: {},
29+
schema: [schema],
30+
},
31+
32+
create: context => ({
33+
JSXOpeningElement: (node) => {
34+
const options = context.options[0] || {};
35+
const elementOptions = options.elements || DEFAULT_ELEMENTS;
36+
const type = elementType(node);
37+
const distractingElement = elementOptions.find(element => type === element);
38+
39+
if (distractingElement) {
40+
context.report({
41+
node,
42+
message: errorMessage(distractingElement),
43+
});
44+
}
45+
},
46+
}),
47+
};

src/rules/no-marquee.js

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/util/schemas.js

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
1+
import assign from 'object-assign';
2+
13
/**
24
* JSON schema to accept an array of unique strings
35
*/
4-
export const arraySchema = {
5-
type: 'array',
6-
items: {
7-
type: 'string',
8-
},
9-
minItems: 1,
10-
uniqueItems: true,
11-
};
6+
export const arraySchema = {
7+
type: 'array',
8+
items: {
9+
type: 'string',
10+
},
11+
minItems: 1,
12+
uniqueItems: true,
13+
additionalItems: false,
14+
};
15+
16+
/**
17+
* JSON schema to accept an array of unique strings from an enumerated list.
18+
*/
19+
export const enumArraySchema = (enumeratedList = []) => assign({}, arraySchema, {
20+
items: {
21+
type: 'string',
22+
enum: enumeratedList,
23+
},
24+
});
1225

1326
/**
1427
* Factory function to generate an object schema
1528
* with specified properties object
1629
*/
17-
export const generateObjSchema = (properties = {}) => ({
18-
type: 'object',
19-
properties,
20-
});
30+
export const generateObjSchema = (properties = {}) => ({
31+
type: 'object',
32+
properties,
33+
});

0 commit comments

Comments
 (0)