Skip to content

Commit 4565b54

Browse files
author
Adrián Bolonio
authored
Merge pull request #38 from github/accessibility/issues/1293/migrate-a11y-erblint-rules
Migrate accessibility rule `a11y_link_has_href` from dotcom to erblint-github
2 parents 959dc15 + 8f967fa commit 4565b54

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ linters:
3131
enabled: true
3232
GitHub::Accessibility::ImageHasAlt:
3333
enabled: true
34+
GitHub::Accessibility::LinkHasHrefCounter:
35+
enabled: true
3436
GitHub::Accessibility::NoAriaLabelMisuseCounter:
3537
enabled: true
3638
GitHub::Accessibility::NoPositiveTabIndex:
@@ -47,6 +49,7 @@ linters:
4749
- [GitHub::Accessibility::AvoidGenericLinkTextCounter](./docs/rules/accessibility/avoid-generic-link-text-counter.md)
4850
- [GitHub::Accessibility::IframeHasTitle](./docs/rules/accessibility/iframe-has-title.md)
4951
- [GitHub::Accessibility::ImageHasAlt](./docs/rules/accessibility/image-has-alt.md)
52+
- [GitHub::Accessibility::LinkHasHrefCounter](./docs/rules/accessibility/link_has_href-counter.md)
5053
- [GitHub::Accessibility::NoAriaLabelMisuseCounter](./docs/rules/accessibility/no-aria-label-misuse-counter.md)
5154
- [GitHub::Accessibility::NoPositiveTabIndex](./docs/rules/accessibility/no-positive-tab-index.md)
5255
- [GitHub::Accessibility::NoRedundantImageAlt](./docs/rules/accessibility/no-redundant-image-alt.md)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Link Has Href counter
2+
3+
## Rule Details
4+
5+
An `<a>` element that has an href attribute represents a hyperlink (a hypertext anchor) labeled by its contents. Links, `<a>` elements, should go somewhere, you probably want to use a `<button>` instead.
6+
7+
8+
## Resources
9+
10+
- [`<a>`: The Anchor element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
11+
- [Primer: Links](https://primer.style/design/accessibility/links)
12+
- [HTML Spec: The a element](https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element)
13+
14+
## Examples
15+
### **Incorrect** code for this rule 👎
16+
17+
```erb
18+
<!-- incorrect -->
19+
<a>Go to GitHub</a>
20+
```
21+
22+
### **Correct** code for this rule 👍
23+
24+
```erb
25+
<!-- correct -->
26+
<a href='https://github.com/'>Go to GitHub</a>
27+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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 LinkHasHrefCounter < Linter
10+
include ERBLint::Linters::CustomHelpers
11+
include LinterRegistry
12+
13+
MESSAGE = "Links should go somewhere, you probably want to use a `<button>` instead."
14+
15+
def run(processed_source)
16+
tags(processed_source).each do |tag|
17+
next if tag.name != "a"
18+
next if tag.closing?
19+
20+
href = possible_attribute_values(tag, "href")
21+
name = tag.attributes["name"]
22+
generate_offense(self.class, processed_source, tag) if (!name && href.empty?) || href.include?("#")
23+
end
24+
25+
counter_correct?(processed_source)
26+
end
27+
28+
def autocorrect(processed_source, offense)
29+
return unless offense.context
30+
31+
lambda do |corrector|
32+
if processed_source.file_content.include?("erblint:counter #{simple_class_name}")
33+
# update the counter if exists
34+
corrector.replace(offense.source_range, offense.context)
35+
else
36+
# add comment with counter if none
37+
corrector.insert_before(processed_source.source_buffer.source_range, "#{offense.context}\n")
38+
end
39+
end
40+
end
41+
end
42+
end
43+
end
44+
end
45+
end
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
class LinkHasHrefCounter < LinterTestCase
6+
def linter_class
7+
ERBLint::Linters::GitHub::Accessibility::LinkHasHrefCounter
8+
end
9+
10+
def test_warns_if_link_has_no_href_attribute
11+
@file = "<a>Go to GitHub</a>"
12+
@linter.run(processed_source)
13+
14+
assert_equal(2, @linter.offenses.count)
15+
error_messages = @linter.offenses.map(&:message).sort
16+
assert_match(/If you must, add <%# erblint:counter GitHub::Accessibility::LinkHasHrefCounter 1 %> to bypass this check./, error_messages.first)
17+
assert_match(/Links should go somewhere, you probably want to use a `<button>` instead./, error_messages.last)
18+
end
19+
20+
def test_does_not_warn_if_link_has_href_attribute
21+
@file = "<a href='https://github.com/'>Go to GitHub</a>"
22+
@linter.run(processed_source)
23+
24+
assert_empty @linter.offenses
25+
end
26+
27+
def test_does_not_warn_if_link_has_href_attribute_and_has_correct_counter_comment
28+
@file = <<~ERB
29+
<%# erblint:counter GitHub::Accessibility::LinkHasHrefCounter 1 %>
30+
<a>Go to GitHub</a>
31+
ERB
32+
@linter.run(processed_source)
33+
34+
assert_equal 0, @linter.offenses.count
35+
end
36+
37+
def test_does_not_autocorrect_when_ignores_are_correct
38+
@file = <<~ERB
39+
<%# erblint:counter GitHub::Accessibility::LinkHasHrefCounter 1 %>
40+
<a>Go to GitHub</a>
41+
ERB
42+
43+
assert_equal @file, corrected_content
44+
end
45+
46+
def test_does_autocorrect_when_ignores_are_not_correct
47+
@file = <<~ERB
48+
<%# erblint:counter GitHub::Accessibility::LinkHasHrefCounter 3 %>
49+
<a>Go to GitHub</a>
50+
ERB
51+
refute_equal @file, corrected_content
52+
53+
expected_content = <<~ERB
54+
<%# erblint:counter GitHub::Accessibility::LinkHasHrefCounter 1 %>
55+
<a>Go to GitHub</a>
56+
ERB
57+
assert_equal expected_content, corrected_content
58+
end
59+
end

0 commit comments

Comments
 (0)