Skip to content

Commit 153b128

Browse files
authored
a11y: implement img-redundant-alt (#4750)
1 parent 09115b5 commit 153b128

File tree

7 files changed

+101
-22
lines changed

7 files changed

+101
-22
lines changed

src/compiler/compile/nodes/Element.ts

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ export default class Element extends Node {
272272
}
273273

274274
this.validate_attributes();
275+
this.validate_special_cases();
275276
this.validate_bindings();
276277
this.validate_content();
277278
this.validate_event_handlers();
@@ -420,8 +421,16 @@ export default class Element extends Node {
420421

421422
attribute_map.set(attribute.name, attribute);
422423
});
424+
}
425+
426+
validate_special_cases() {
427+
const { component,attributes } = this;
428+
const attribute_map = new Map();
429+
430+
attributes.forEach(attribute => (
431+
attribute_map.set(attribute.name, attribute)
432+
));
423433

424-
// handle special cases
425434
if (this.name === 'a') {
426435
const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
427436
const id_attribute = attribute_map.get('id');
@@ -447,9 +456,7 @@ export default class Element extends Node {
447456
});
448457
}
449458
}
450-
}
451-
452-
else {
459+
} else {
453460
const required_attributes = a11y_required_attributes[this.name];
454461
if (required_attributes) {
455462
const has_attribute = required_attributes.some(name => attribute_map.has(name));
@@ -458,16 +465,34 @@ export default class Element extends Node {
458465
should_have_attribute(this, required_attributes);
459466
}
460467
}
468+
}
461469

462-
if (this.name === 'input') {
463-
const type = attribute_map.get('type');
464-
if (type && type.get_static_value() === 'image') {
465-
const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
466-
const has_attribute = required_attributes.some(name => attribute_map.has(name));
470+
if (this.name === 'input') {
471+
const type = attribute_map.get('type');
472+
if (type && type.get_static_value() === 'image') {
473+
const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
474+
const has_attribute = required_attributes.some(name => attribute_map.has(name));
467475

468-
if (!has_attribute) {
469-
should_have_attribute(this, required_attributes, 'input type="image"');
470-
}
476+
if (!has_attribute) {
477+
should_have_attribute(this, required_attributes, 'input type="image"');
478+
}
479+
}
480+
}
481+
482+
if (this.name === 'img') {
483+
const alt_attribute = attribute_map.get('alt');
484+
const aria_hidden_attribute = attribute_map.get('aria-hidden');
485+
486+
const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
487+
488+
if (alt_attribute && !aria_hidden_exist) {
489+
const alt_value = alt_attribute.get_static_value();
490+
491+
if (alt_value.match(/\b(image|picture|photo)\b/i)) {
492+
component.warn(this, {
493+
code: `a11y-img-redundant-alt`,
494+
message: `A11y: Screenreaders already announce <img> elements as an image.`
495+
});
471496
}
472497
}
473498
}

test/validator/samples/a11y-figcaption-in-non-element-block/input.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</script>
44

55
<figure>
6-
<img src='foo.jpg' alt='a picture of a foo'>
6+
<img src='foo.jpg' alt='a foo'>
77
{#if caption}
88
<figcaption>{caption}</figcaption>
99
{/if}

test/validator/samples/a11y-figcaption-right-place/input.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<figure>
2-
<img src='foo.jpg' alt='a picture of a foo'>
2+
<img src='foo.jpg' alt='a foo'>
33

44
<figcaption>
55
a foo in its natural habitat

test/validator/samples/a11y-figcaption-wrong-place/input.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<figure>
2-
<img src='foo.jpg' alt='a picture of a foo'>
2+
<img src='foo.jpg' alt='a foo'>
33

44
<figcaption>
55
a foo in its natural habitat
@@ -9,7 +9,7 @@
99
</figure>
1010

1111
<figure>
12-
<img src='foo.jpg' alt='a picture of a foo'>
12+
<img src='foo.jpg' alt='a foo'>
1313

1414
<div class='markup-for-styling'>
1515
<figcaption>

test/validator/samples/a11y-figcaption-wrong-place/warnings.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,28 @@
55
"start": {
66
"line": 4,
77
"column": 1,
8-
"character": 57
8+
"character": 44
99
},
1010
"end": {
1111
"line": 6,
1212
"column": 14,
13-
"character": 115
13+
"character": 102
1414
},
15-
"pos": 57
15+
"pos": 44
1616
},
1717
{
1818
"code": "a11y-structure",
1919
"message": "A11y: <figcaption> must be an immediate child of <figure>",
2020
"start": {
2121
"line": 15,
2222
"column": 2,
23-
"character": 252
23+
"character": 226
2424
},
2525
"end": {
2626
"line": 17,
2727
"column": 15,
28-
"character": 328
28+
"character": 302
2929
},
30-
"pos": 252
30+
"pos": 226
3131
}
3232
]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<img src="foo" alt="Foo eating a sandwich." />
2+
<img src="bar" aria-hidden alt="Picture of me taking a photo of an image" />
3+
<img src="foo" alt="Photo of foo being weird." />
4+
<img src="bar" alt="Image of me at a bar!" />
5+
<img src="foo" alt="Picture of baz fixing a bug." />
6+
<img src="bar" alt="Plant doing photosynthesis in the afternoon" />
7+
<img src="foo" alt="Picturesque food" />
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[
2+
{
3+
"code": "a11y-img-redundant-alt",
4+
"message": "A11y: Screenreaders already announce <img> elements as an image.",
5+
"end": {
6+
"character": 173,
7+
"column": 49,
8+
"line": 3
9+
},
10+
"start": {
11+
"character": 124,
12+
"column": 0,
13+
"line": 3
14+
},
15+
"pos": 124
16+
},
17+
{
18+
"code": "a11y-img-redundant-alt",
19+
"message": "A11y: Screenreaders already announce <img> elements as an image.",
20+
"end": {
21+
"character": 219,
22+
"column": 45,
23+
"line": 4
24+
},
25+
"start": {
26+
"character": 174,
27+
"column": 0,
28+
"line": 4
29+
},
30+
"pos": 174
31+
},
32+
{
33+
"code": "a11y-img-redundant-alt",
34+
"message": "A11y: Screenreaders already announce <img> elements as an image.",
35+
"end": {
36+
"character": 272,
37+
"column": 52,
38+
"line": 5
39+
},
40+
"start": {
41+
"character": 220,
42+
"column": 0,
43+
"line": 5
44+
},
45+
"pos": 220
46+
}
47+
]

0 commit comments

Comments
 (0)