erblint-github 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 310138254b0989437e8cf803d52cba66ad005d7cae43b8b6233e638a20e40868
4
- data.tar.gz: 654d731eb0c99317883327dd401726582d7df70995350d0006b365fe1b9670b6
3
+ metadata.gz: 2e31129554b451397cf438dc56e52ce9f0e21b7df4cecb59f92324b7ca0c7e5c
4
+ data.tar.gz: a17e3f541f4975cdfafb0d046a312581fe6481ba4e113f49f7cb9ed67a09d477
5
5
  SHA512:
6
- metadata.gz: ce1a90a1c2482b29b406787a1c530614718242de1b9fac828617c2f476db00578872bcddf52037bf8195c71beb8750916e853b5127f4de036aea5771a8edbe2b
7
- data.tar.gz: 2a1e8844fdae5d352a6798937629e4ae70bea7d3a16c00e1a6de363dcc805044164b55e5166d9ffaf6f288bbdb135c373c2f1b1b40d27ecb0705c2cb616a833c
6
+ metadata.gz: 2aba7d9263d58382aabef89e3688993dc7bbf230199ae8b952159bc0c3287402107562537095b7184f55fa192a7bf0366ff43875f3f85fcf73ca57cb45a9ee21
7
+ data.tar.gz: 69a2e3fb5a40d79120655ba41bb38c2120f01b941b73ce888bc7e29e57fc9c31c119770f3b719fedb9cf1a8cef4db341696eea54c4b658320e80ff540dec4e64
@@ -18,6 +18,8 @@ module ERBLint
18
18
  "Link",
19
19
  "Here"
20
20
  ].freeze
21
+ ARIA_LABEL_ATTRIBUTES = %w[aria-labelledby aria-label].freeze
22
+
21
23
  MESSAGE = "Avoid using generic link text such as #{BANNED_GENERIC_TEXT.join(', ')} which do not make sense in isolation."
22
24
 
23
25
  def run(processed_source)
@@ -25,6 +27,7 @@ module ERBLint
25
27
  next unless node.methods.include?(:type) && node.type == :text
26
28
 
27
29
  text = node.children.join.strip
30
+
28
31
  # Checks HTML tags
29
32
  if banned_text?(text)
30
33
  prev_node = processed_source.ast.children[index - 1]
@@ -36,8 +39,17 @@ module ERBLint
36
39
  prev_node_tag = BetterHtml::Tree::Tag.from_node(prev_node)
37
40
  next_node_tag = BetterHtml::Tree::Tag.from_node(next_node)
38
41
 
39
- # We only report if the text is nested between two link tags.
42
+ aria_label = possible_attribute_values(prev_node_tag, "aria-label")
43
+ aria_labelledby = possible_attribute_values(prev_node_tag, "aria-labelledby")
44
+
45
+ # Checks if nested between two link tags.
40
46
  if link_tag?(prev_node_tag) && link_tag?(next_node_tag) && next_node_tag.closing?
47
+ # Skip because we cannot reliably check accessible name from aria-labelledby, or an aria-label that is set to a variable
48
+ # with static code analysis.
49
+ next if aria_labelledby.present? || (aria_label.present? && aria_label.join.include?("<%="))
50
+ # Skip because aria-label starts with visible text which we allow. Related to Success Criterion 2.5.3: Label in Name
51
+ next if aria_label.present? && valid_accessible_name?(aria_label.join, text)
52
+
41
53
  range = prev_node_tag.loc.begin_pos...text_node_tag.loc.end_pos
42
54
  source_range = processed_source.to_source_range(range)
43
55
  generate_offense_from_source_range(self.class, source_range)
@@ -45,20 +57,40 @@ module ERBLint
45
57
  end
46
58
 
47
59
  # Checks Rails link helpers like `link_to`
48
- erb_node = node.type == :erb ? node : node.descendants(:erb).first
49
- next unless erb_node
50
-
51
- _, _, code_node = *erb_node
52
- source = code_node.loc.source
53
- ruby_node = extract_ruby_node(source)
54
- send_node = ruby_node&.descendants(:send)&.first
55
- next unless send_node.methods.include?(:method_name) && send_node.method_name == :link_to
56
-
57
- send_node.child_nodes.each do |child_node|
58
- if child_node.methods.include?(:type) && child_node.type == :str && banned_text?(child_node.children.join)
60
+ node.descendants(:erb).each do |erb_node|
61
+ _, _, code_node = *erb_node
62
+ source = code_node.loc.source
63
+ ruby_node = extract_ruby_node(source)
64
+ send_node = ruby_node&.descendants(:send)&.first
65
+ next unless send_node.methods.include?(:method_name) && send_node.method_name == :link_to
66
+
67
+ banned_text = nil
68
+
69
+ send_node.child_nodes.each do |child_node|
70
+ banned_text = child_node.children.join if child_node.methods.include?(:type) && child_node.type == :str && banned_text?(child_node.children.join)
71
+ next if banned_text.blank?
72
+ next unless child_node.methods.include?(:type) && child_node.type == :hash
73
+
74
+ child_node.descendants(:pair).each do |pair_node|
75
+ next unless pair_node.children.first.type?(:sym)
76
+
77
+ # Skips if `link_to` has `aria-labelledby` or `aria-label` which cannot be evaluated accurately with ERB lint alone.
78
+ # ERB lint removes Ruby string interpolation so the `aria-label` for "<%= link_to 'Learn more', "aria-label": "Learn #{@some_variable}" %>" will
79
+ # only be `Learn` which is unreliable so we can't do checks :(
80
+ key_value = pair_node.children.first.children.join
81
+ banned_text = nil if ARIA_LABEL_ATTRIBUTES.include?(key_value)
82
+ next unless key_value == "aria"
83
+
84
+ pair_node.children[1].descendants(:sym).each do |sym_node|
85
+ banned_text = nil if sym_node.children.join == "label" || sym_node.children.join == "labelledby"
86
+ end
87
+ end
88
+ end
89
+ if banned_text.present?
59
90
  tag = BetterHtml::Tree::Tag.from_node(code_node)
60
91
  generate_offense(self.class, processed_source, tag)
61
- end
92
+ end
93
+ banned_text = nil
62
94
  end
63
95
  end
64
96
  counter_correct?(processed_source)
@@ -84,6 +116,10 @@ module ERBLint
84
116
  BANNED_GENERIC_TEXT.map(&:downcase).include?(text.downcase)
85
117
  end
86
118
 
119
+ def valid_accessible_name?(aria_label, text)
120
+ aria_label.downcase.include?(text.downcase)
121
+ end
122
+
87
123
  def extract_ruby_node(source)
88
124
  BetterHtml::TestHelper::RubyNode.parse(source)
89
125
  rescue ::Parser::SyntaxError
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erblint-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-15 00:00:00.000000000 Z
11
+ date: 2022-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erb_lint