Skip to content

Commit a14e7c3

Browse files
authored
Merge pull request #63 from github/kh-aria-label-is-well-formatted
New rule that flags downcased aria-label
2 parents 3587894 + 21767fe commit a14e7c3

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ require "erblint-github/linters"
2323
```yaml
2424
---
2525
linters:
26+
GitHub::Accessibility::AriaLabelIsWellFormatted:
27+
enabled: true
2628
GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled:
2729
enabled: true
2830
GitHub::Accessibility::AvoidGenericLinkText:
@@ -55,6 +57,7 @@ linters:
5557
5658
## Rules
5759
60+
- [GitHub::Accessibility::AriaLabelIsWellFormatted](./docs/rules/accessibility/aria-label-is-well-formatted.md)
5861
- [GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled](./docs/rules/accessibility/avoid-both-disabled-and-aria-disabled.md)
5962
- [GitHub::Accessibility::AvoidGenericLinkText](./docs/rules/accessibility/avoid-generic-link-text.md)
6063
- [GitHub::Accessibility::DisabledAttribute](./docs/rules/accessibility/disabled-attribute.md)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# aria-label is well formatted
2+
3+
## Rule Details
4+
5+
`[aria-label]` content should be formatted in the same way you would visual text. Please use sentence case.
6+
7+
Do not kebab case the words like you would an HTML ID. An `aria-label` is different from `aria-labelledby`.
8+
An `aria-label` is not an ID, and should be formatted as human-friendly text.
9+
10+
## Config
11+
12+
If you determine that there are valid scenarios for `aria-label` to start with lowercase, you may exempt it in your `.erb-lint.yml` config like so:
13+
14+
```yml
15+
GitHub::Accessibility::AriaLabelIsWellFormatted:
16+
enabled: true
17+
exceptions:
18+
- allowed for some reason
19+
- also allowed for some reason
20+
```
21+
22+
## Examples
23+
24+
### **Incorrect** code for this rule 👎
25+
26+
```erb
27+
<button aria-label="close">
28+
```
29+
30+
```erb
31+
<button aria-label="submit">
32+
```
33+
34+
```erb
35+
<button aria-label="button-1">
36+
```
37+
38+
### **Correct** code for this rule 👍
39+
40+
```erb
41+
<button aria-label="Submit">
42+
````
43+
44+
```erb
45+
<button aria-label="Close">
46+
````
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../../custom_helpers"
4+
5+
module ERBLint
6+
module Linters
7+
module GitHub
8+
module Accessibility
9+
class AriaLabelIsWellFormatted < Linter
10+
include ERBLint::Linters::CustomHelpers
11+
include LinterRegistry
12+
13+
MESSAGE = "[aria-label] text should be formatted the same as you would visual text. Use sentence case."
14+
15+
class ConfigSchema < LinterConfig
16+
property :exceptions, accepts: array_of?(String),
17+
default: -> { [] }
18+
end
19+
self.config_schema = ConfigSchema
20+
21+
def run(processed_source)
22+
tags(processed_source).each do |tag|
23+
next if tag.closing?
24+
25+
aria_label = possible_attribute_values(tag, "aria-label").join
26+
next if aria_label.empty?
27+
28+
if aria_label.match?(/^[a-z]/) && !@config.exceptions.include?(aria_label)
29+
generate_offense(self.class, processed_source, tag)
30+
end
31+
end
32+
end
33+
end
34+
end
35+
end
36+
end
37+
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
class AriaLabelIsWellFormatted < LinterTestCase
6+
def linter_class
7+
ERBLint::Linters::GitHub::Accessibility::AriaLabelIsWellFormatted
8+
end
9+
10+
def test_warns_when_aria_label_starts_with_downcase
11+
@file = <<~HTML
12+
<button aria-label="submit" ></button>
13+
<button aria-label="check-box-1" ></button>
14+
<button aria-label="ok" ></button>
15+
<button aria-label="no" ></button>
16+
HTML
17+
@linter.run(processed_source)
18+
19+
assert_equal 4, @linter.offenses.count
20+
end
21+
22+
def test_does_not_warn_when_aria_labelledby_starts_with_downcase
23+
@file = "<button aria-labelledby='some-element-1'</button>"
24+
@linter.run(processed_source)
25+
26+
assert_empty @linter.offenses
27+
end
28+
29+
def test_does_not_warn_when_aria_label_starts_with_anything_other_than_downcase
30+
@file = <<~HTML
31+
<button aria-label="Submit" ></button>
32+
<button aria-label="Close" ></button>
33+
<button aria-label="11 open" ></button>
34+
HTML
35+
@linter.run(processed_source)
36+
37+
assert_empty @linter.offenses
38+
end
39+
40+
def test_does_not_warn_when_aria_label_is_excepted_in_config
41+
@file = <<~HTML
42+
<button aria-label="Submit" ></button>
43+
<button aria-label="Close" ></button>
44+
<button aria-label="11 open" ></button>
45+
HTML
46+
@linter.run(processed_source)
47+
48+
assert_empty @linter.offenses
49+
end
50+
51+
52+
def test_does_not_warn_if_aria_label_is_in_excepted_list
53+
@file = <<~HTML
54+
<button aria-label="hello" ></button>
55+
<button aria-label="hello world" ></button>
56+
HTML
57+
@linter.config.exceptions = ["hello"]
58+
@linter.run(processed_source)
59+
60+
assert_equal 1, @linter.offenses.count
61+
end
62+
end

0 commit comments

Comments
 (0)